test_memcache.py 3.59 KB
Newer Older
1 2 3 4 5
"""
Tests for memcache in util app
"""

from django.test import TestCase
6
from django.core.cache import caches
7 8 9 10 11 12 13 14 15
from util.memcache import safe_key


class MemcacheTest(TestCase):
    """
    Test memcache key cleanup
    """

    # Test whitespace, control characters, and some non-ASCII UTF-16
16
    UNICODE_CHAR_CODES = (range(30) + [127] +
17 18 19
                          [129, 500, 2 ** 8 - 1, 2 ** 8 + 1, 2 ** 16 - 1])

    def setUp(self):
20
        super(MemcacheTest, self).setUp()
21
        self.cache = caches['default']
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54

    def test_safe_key(self):
        key = safe_key('test', 'prefix', 'version')
        self.assertEqual(key, 'prefix:version:test')

    def test_numeric_inputs(self):

        # Numeric key
        self.assertEqual(safe_key(1, 'prefix', 'version'), 'prefix:version:1')

        # Numeric prefix
        self.assertEqual(safe_key('test', 5, 'version'), '5:version:test')

        # Numeric version
        self.assertEqual(safe_key('test', 'prefix', 5), 'prefix:5:test')

    def test_safe_key_long(self):

        # Choose lengths close to memcached's cutoff (250)
        for length in [248, 249, 250, 251, 252]:

            # Generate a key of that length
            key = 'a' * length

            # Make the key safe
            key = safe_key(key, '', '')

            # The key should now be valid
            self.assertTrue(self._is_valid_key(key),
                            msg="Failed for key length {0}".format(length))

    def test_long_key_prefix_version(self):

55
        # Long key
56
        key = safe_key('a' * 300, 'prefix', 'version')
57 58 59 60 61 62 63 64 65
        self.assertTrue(self._is_valid_key(key))

        # Long prefix
        key = safe_key('key', 'a' * 300, 'version')
        self.assertTrue(self._is_valid_key(key))

        # Long version
        key = safe_key('key', 'prefix', 'a' * 300)
        self.assertTrue(self._is_valid_key(key))
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124

    def test_safe_key_unicode(self):

        for unicode_char in self.UNICODE_CHAR_CODES:

            # Generate a key with that character
            key = unichr(unicode_char)

            # Make the key safe
            key = safe_key(key, '', '')

            # The key should now be valid
            self.assertTrue(self._is_valid_key(key),
                            msg="Failed for unicode character {0}".format(unicode_char))

    def test_safe_key_prefix_unicode(self):

        for unicode_char in self.UNICODE_CHAR_CODES:

            # Generate a prefix with that character
            prefix = unichr(unicode_char)

            # Make the key safe
            key = safe_key('test', prefix, '')

            # The key should now be valid
            self.assertTrue(self._is_valid_key(key),
                            msg="Failed for unicode character {0}".format(unicode_char))

    def test_safe_key_version_unicode(self):

        for unicode_char in self.UNICODE_CHAR_CODES:

            # Generate a version with that character
            version = unichr(unicode_char)

            # Make the key safe
            key = safe_key('test', '', version)

            # The key should now be valid
            self.assertTrue(self._is_valid_key(key),
                            msg="Failed for unicode character {0}".format(unicode_char))

    def _is_valid_key(self, key):
        """
        Test that a key is memcache-compatible.
        Based on Django's validator in core.cache.backends.base
        """

        # Check the length
        if len(key) > 250:
            return False

        # Check that there are no spaces or control characters
        for char in key:
            if ord(char) < 33 or ord(char) == 127:
                return False

        return True