diff options
| author | andy <andy@whiskeymedia.com> | 2013-06-04 15:13:17 -0400 |
|---|---|---|
| committer | andy <andy@whiskeymedia.com> | 2013-06-04 15:13:17 -0400 |
| commit | e1233ff4545de043b5b33b7d50f17d260f1e02ce (patch) | |
| tree | 59670ca85af8e8ac3a4c6b7bd57fb5affce442b0 | |
| parent | 7d8674f3edb326f29e4a1552ae674ea3ca6e7808 (diff) | |
| download | redis-py-e1233ff4545de043b5b33b7d50f17d260f1e02ce.tar.gz | |
pytest framework and server commands
| -rw-r--r-- | redis/client.py | 67 | ||||
| -rwxr-xr-x | run_tests | 9 | ||||
| -rw-r--r-- | setup.py | 20 | ||||
| -rw-r--r-- | tests/__init__.py | 31 | ||||
| -rw-r--r-- | tests/server_commands.py | 1843 | ||||
| -rw-r--r-- | tests/test_commands.py | 1227 |
6 files changed, 1286 insertions, 1911 deletions
diff --git a/redis/client.py b/redis/client.py index 352e98a..d6c7917 100644 --- a/redis/client.py +++ b/redis/client.py @@ -243,7 +243,7 @@ class StrictRedis(object): 'PING': lambda r: nativestr(r) == 'PONG', 'RANDOMKEY': lambda r: r and r or None, 'SCRIPT': parse_script, - 'SET': lambda r: r and nativestr(r) == 'OK' or None, + 'SET': lambda r: r and nativestr(r) == 'OK', 'TIME': lambda x: (int(x[0]), int(x[1])) } ) @@ -430,22 +430,10 @@ class StrictRedis(object): "Returns the number of keys in the current database" return self.execute_command('DBSIZE') - def time(self): - """ - Returns the server time as a 2-item tuple of ints: - (seconds since epoch, microseconds into this second). - """ - return self.execute_command('TIME') - def debug_object(self, key): "Returns version specific metainformation about a give key" return self.execute_command('DEBUG', 'OBJECT', key) - def delete(self, *names): - "Delete one or more keys specified by ``names``" - return self.execute_command('DEL', *names) - __delitem__ = delete - def echo(self, value): "Echo the string back from the server" return self.execute_command('ECHO', value) @@ -514,6 +502,13 @@ class StrictRedis(object): return self.execute_command("SLAVEOF", "NO", "ONE") return self.execute_command("SLAVEOF", host, port) + def time(self): + """ + Returns the server time as a 2-item tuple of ints: + (seconds since epoch, microseconds into this second). + """ + return self.execute_command('TIME') + #### BASIC KEY COMMANDS #### def append(self, key, value): """ @@ -523,13 +518,6 @@ class StrictRedis(object): """ return self.execute_command('APPEND', key, value) - def getrange(self, key, start, end): - """ - Returns the substring of the string value stored at ``key``, - determined by the offsets ``start`` and ``end`` (both are inclusive) - """ - return self.execute_command('GETRANGE', key, start, end) - def bitcount(self, key, start=None, end=None): """ Returns the count of set bits in the value of ``key``. Optional @@ -558,6 +546,11 @@ class StrictRedis(object): """ return self.execute_command('DECRBY', name, amount) + def delete(self, *names): + "Delete one or more keys specified by ``names``" + return self.execute_command('DEL', *names) + __delitem__ = delete + def exists(self, name): "Returns a boolean indicating whether key ``name`` exists" return self.execute_command('EXISTS', name) @@ -601,6 +594,13 @@ class StrictRedis(object): "Returns a boolean indicating the value of ``offset`` in ``name``" return self.execute_command('GETBIT', name, offset) + def getrange(self, key, start, end): + """ + Returns the substring of the string value stored at ``key``, + determined by the offsets ``start`` and ``end`` (both are inclusive) + """ + return self.execute_command('GETRANGE', key, start, end) + def getset(self, name, value): """ Set the value at key ``name`` to ``value`` if key doesn't exist @@ -643,20 +643,33 @@ class StrictRedis(object): args = list_or_args(keys, args) return self.execute_command('MGET', *args) - def mset(self, mapping): - "Sets each key in the ``mapping`` dict to its corresponding value" + def mset(self, *args, **kwargs): + """ + Sets key/values based on a mapping. Mapping can be supplied as a single + dictionary argument or as kwargs. + """ + if args: + if len(args) != 1 or not isinstance(args[0], dict): + raise RedisError('MSET requires **kwargs or a single dict arg') + kwargs.update(args[0]) items = [] - for pair in iteritems(mapping): + for pair in iteritems(kwargs): items.extend(pair) return self.execute_command('MSET', *items) - def msetnx(self, mapping): + def msetnx(self, *args, **kwargs): """ - Sets each key in the ``mapping`` dict to its corresponding value if - none of the keys are already set + Sets key/values based on a mapping if none of the keys are already set. + Mapping can be supplied as a single dictionary argument or as kwargs. + Returns a boolean indicating if the operation was successful. """ + if args: + if len(args) != 1 or not isinstance(args[0], dict): + raise RedisError('MSETNX requires **kwargs or a single ' + 'dict arg') + kwargs.update(args[0]) items = [] - for pair in iteritems(mapping): + for pair in iteritems(kwargs): items.extend(pair) return self.execute_command('MSETNX', *items) diff --git a/run_tests b/run_tests deleted file mode 100755 index 2d629c6..0000000 --- a/run_tests +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env python - -import unittest -from tests import all_tests - - -if __name__ == "__main__": - tests = all_tests() - results = unittest.TextTestRunner().run(tests) @@ -1,12 +1,29 @@ #!/usr/bin/env python import os +import sys from redis import __version__ try: from setuptools import setup + from setuptools.command.test import test as TestCommand + + class PyTest(TestCommand): + def finalize_options(self): + TestCommand.finalize_options(self) + self.test_args = [] + self.test_suite = True + + def run_tests(self): + #import here, cause outside the eggs aren't loaded + import pytest + errno = pytest.main(self.test_args) + sys.exit(errno) + except ImportError: + from distutils.core import setup + PyTest = lambda x: x f = open(os.path.join(os.path.dirname(__file__), 'README.rst')) long_description = f.read() @@ -25,7 +42,8 @@ setup( keywords=['Redis', 'key-value store'], license='MIT', packages=['redis'], - test_suite='tests.all_tests', + tests_require=['pytest'], + cmdclass={'test': PyTest}, classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Console', diff --git a/tests/__init__.py b/tests/__init__.py index 71c0179..e69de29 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,31 +0,0 @@ -import unittest - -from tests.server_commands import ServerCommandsTestCase -from tests.connection_pool import ConnectionPoolTestCase -from tests.connection_pool import BlockingConnectionPoolTestCase -from tests.pipeline import PipelineTestCase -from tests.lock import LockTestCase -from tests.pubsub import PubSubTestCase, PubSubRedisDownTestCase -from tests.encoding import (PythonParserEncodingTestCase, - HiredisEncodingTestCase) - -try: - import hiredis - use_hiredis = True -except ImportError: - use_hiredis = False - - -def all_tests(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(ServerCommandsTestCase)) - suite.addTest(unittest.makeSuite(ConnectionPoolTestCase)) - suite.addTest(unittest.makeSuite(BlockingConnectionPoolTestCase)) - suite.addTest(unittest.makeSuite(PipelineTestCase)) - suite.addTest(unittest.makeSuite(LockTestCase)) - suite.addTest(unittest.makeSuite(PubSubTestCase)) - suite.addTest(unittest.makeSuite(PubSubRedisDownTestCase)) - suite.addTest(unittest.makeSuite(PythonParserEncodingTestCase)) - if use_hiredis: - suite.addTest(unittest.makeSuite(HiredisEncodingTestCase)) - return suite diff --git a/tests/server_commands.py b/tests/server_commands.py deleted file mode 100644 index 1ae8f80..0000000 --- a/tests/server_commands.py +++ /dev/null @@ -1,1843 +0,0 @@ -from distutils.version import StrictVersion -import unittest -import datetime -import time -import binascii - -from redis._compat import (unichr, u, b, ascii_letters, iteritems, iterkeys, - itervalues) -from redis.client import parse_info -import redis - - -class ServerCommandsTestCase(unittest.TestCase): - def get_client(self, cls=redis.Redis): - return cls(host='localhost', port=6379, db=9) - - def setUp(self): - self.client = self.get_client() - self.client.flushdb() - - def tearDown(self): - self.client.flushdb() - self.client.connection_pool.disconnect() - - def test_response_callbacks(self): - self.assertEquals( - self.client.response_callbacks, - redis.Redis.RESPONSE_CALLBACKS) - self.assertNotEquals( - id(self.client.response_callbacks), - id(redis.Redis.RESPONSE_CALLBACKS)) - self.client.set_response_callback('GET', lambda x: 'static') - self.client.set('a', 'foo') - self.assertEquals(self.client.get('a'), 'static') - - # GENERAL SERVER COMMANDS - def test_dbsize(self): - self.client['a'] = 'foo' - self.client['b'] = 'bar' - self.assertEquals(self.client.dbsize(), 2) - - def test_get_and_set(self): - # get and set can't be tested independently of each other - client = redis.Redis(host='localhost', port=6379, db=9) - self.assertEquals(client.get('a'), None) - byte_string = b('value') - integer = 5 - unicode_string = unichr(3456) + u('abcd') + unichr(3421) - self.assert_(client.set('byte_string', byte_string)) - self.assert_(client.set('integer', 5)) - self.assert_(client.set('unicode_string', unicode_string)) - self.assertEquals(client.get('byte_string'), byte_string) - self.assertEquals(client.get('integer'), b(str(integer))) - self.assertEquals( - client.get('unicode_string').decode('utf-8'), - unicode_string) - - def test_getitem_and_setitem(self): - self.client['a'] = 'bar' - self.assertEquals(self.client['a'], b('bar')) - self.assertRaises(KeyError, self.client.__getitem__, 'b') - - def test_delete(self): - self.assertEquals(self.client.delete('a'), 0) - self.client['a'] = 'foo' - self.assertEquals(self.client.delete('a'), 1) - - def test_delete_multiple_keys(self): - self.client['a'] = 'foo' - self.client['b'] = 'bar' - self.assertEquals(self.client.delete('a', 'b'), 2) - self.assertEquals(self.client.get('a'), None) - self.assertEquals(self.client.get('b'), None) - - def test_delitem(self): - self.client['a'] = 'foo' - del self.client['a'] - self.assertEquals(self.client.get('a'), None) - - def test_client_list(self): - clients = self.client.client_list() - self.assert_(isinstance(clients[0], dict)) - self.assert_('addr' in clients[0]) - - def test_client_getname(self): - version = self.client.info()['redis_version'] - if StrictVersion(version) < StrictVersion('2.6.9'): - try: - raise unittest.SkipTest() - except AttributeError: - return - - name = self.client.client_getname() - self.assertEquals(name, None) - - def test_client_setname(self): - version = self.client.info()['redis_version'] - if StrictVersion(version) < StrictVersion('2.6.9'): - try: - raise unittest.SkipTest() - except AttributeError: - return - - self.assert_(self.client.client_setname('redis_py_test')) - self.assertEquals( - self.client.client_getname(), - 'redis_py_test' - ) - - def test_config_get(self): - data = self.client.config_get() - self.assert_('maxmemory' in data) - self.assert_(data['maxmemory'].isdigit()) - - def test_config_set(self): - data = self.client.config_get() - rdbname = data['dbfilename'] - self.assert_(self.client.config_set('dbfilename', 'redis_py_test.rdb')) - self.assertEquals( - self.client.config_get()['dbfilename'], - 'redis_py_test.rdb' - ) - self.assert_(self.client.config_set('dbfilename', rdbname)) - self.assertEquals(self.client.config_get()['dbfilename'], rdbname) - - def test_debug_object(self): - self.client['a'] = 'foo' - debug_info = self.client.debug_object('a') - self.assert_(len(debug_info) > 0) - self.assertEquals(debug_info['refcount'], 1) - self.assert_(debug_info['serializedlength'] > 0) - self.client.rpush('b', 'a1') - debug_info = self.client.debug_object('a') - - def test_echo(self): - self.assertEquals(self.client.echo('foo bar'), b('foo bar')) - - def test_info(self): - self.client['a'] = 'foo' - self.client['b'] = 'bar' - info = self.client.info() - self.assert_(isinstance(info, dict)) - self.assertEquals(info['db9']['keys'], 2) - - def test_lastsave(self): - self.assert_(isinstance(self.client.lastsave(), datetime.datetime)) - - def test_object(self): - self.client['a'] = 'foo' - self.assert_(isinstance(self.client.object('refcount', 'a'), int)) - self.assert_(isinstance(self.client.object('idletime', 'a'), int)) - self.assertEquals(self.client.object('encoding', 'a'), b('raw')) - - def test_ping(self): - self.assertEquals(self.client.ping(), True) - - def test_time(self): - version = self.client.info()['redis_version'] - if StrictVersion(version) < StrictVersion('2.6.0'): - try: - raise unittest.SkipTest() - except AttributeError: - return - - t = self.client.time() - self.assertEquals(len(t), 2) - self.assert_(isinstance(t[0], int)) - self.assert_(isinstance(t[1], int)) - - # KEYS - def test_append(self): - # invalid key type - self.client.rpush('a', 'a1') - self.assertRaises(redis.ResponseError, self.client.append, 'a', 'a1') - del self.client['a'] - # real logic - self.assertEquals(self.client.append('a', 'a1'), 2) - self.assertEquals(self.client['a'], b('a1')) - self.assert_(self.client.append('a', 'a2'), 4) - self.assertEquals(self.client['a'], b('a1a2')) - - def test_getrange(self): - self.client['a'] = 'foo' - self.assertEquals(self.client.getrange('a', 0, 0), b('f')) - self.assertEquals(self.client.getrange('a', 0, 2), b('foo')) - self.assertEquals(self.client.getrange('a', 3, 4), b('')) - - def test_decr(self): - self.assertEquals(self.client.decr('a'), -1) - self.assertEquals(self.client['a'], b('-1')) - self.assertEquals(self.client.decr('a'), -2) - self.assertEquals(self.client['a'], b('-2')) - self.assertEquals(self.client.decr('a', amount=5), -7) - self.assertEquals(self.client['a'], b('-7')) - - def test_exists(self): - self.assertEquals(self.client.exists('a'), False) - self.client['a'] = 'foo' - self.assertEquals(self.client.exists('a'), True) - - def test_expire(self): - self.assertEquals(self.client.expire('a', 10), False) - self.client['a'] = 'foo' - self.assertEquals(self.client.expire('a', 10), True) - self.assertEquals(self.client.ttl('a'), 10) - self.assertEquals(self.client.persist('a'), True) - self.assertEquals(self.client.ttl('a'), None) - - def test_expireat(self): - expire_at = datetime.datetime.now() + datetime.timedelta(minutes=1) - self.assertEquals(self.client.expireat('a', expire_at), False) - self.client['a'] = 'foo' - # expire at in unix time - expire_at_seconds = int(time.mktime(expire_at.timetuple())) - self.assertEquals(self.client.expireat('a', expire_at_seconds), True) - self.assertEquals(self.client.ttl('a'), 60) - # expire at given a datetime object - self.client['b'] = 'bar' - self.assertEquals(self.client.expireat('b', expire_at), True) - self.assertEquals(self.client.ttl('b'), 60) - - def test_pexpire(self): - version = self.client.info()['redis_version'] - if StrictVersion(version) < StrictVersion('2.6.0'): - try: - raise unittest.SkipTest() - except AttributeError: - return - - self.assertEquals(self.client.pexpire('a', 10000), False) - self.client['a'] = 'foo' - self.assertEquals(self.client.pexpire('a', 10000), True) - self.assert_(self.client.pttl('a') <= 10000) - self.assertEquals(self.client.persist('a'), True) - self.assertEquals(self.client.pttl('a'), None) - - def test_pexpireat(self): - version = self.client.info()['redis_version'] - if StrictVersion(version) < StrictVersion('2.6.0'): - try: - raise unittest.SkipTest() - except AttributeError: - return - - expire_at = datetime.datetime.now() + datetime.timedelta(minutes=1) - self.assertEquals(self.client.pexpireat('a', expire_at), False) - self.client['a'] = 'foo' - # expire at in unix time (milliseconds) - expire_at_seconds = int(time.mktime(expire_at.timetuple())) * 1000 - self.assertEquals(self.client.pexpireat('a', expire_at_seconds), True) - self.assert_(self.client.ttl('a') <= 60) - # expire at given a datetime object - self.client['b'] = 'bar' - self.assertEquals(self.client.pexpireat('b', expire_at), True) - self.assert_(self.client.ttl('b') <= 60) - - def test_psetex(self): - self.assertEquals(self.client.psetex('a', 1000, 'value'), True) - self.assertEquals(self.client['a'], b('value')) - self.assert_(0 < self.client.pttl('a') <= 1000) - # expire given a timeelta - expire_at = datetime.timedelta(milliseconds=1000) - self.assertEquals(self.client.psetex('a', expire_at, 'value'), True) - self.assertEquals(self.client['a'], b('value')) - self.assert_(0 < self.client.pttl('a') <= 1000) - - def test_get_set_bit(self): - self.assertEquals(self.client.getbit('a', 5), False) - self.assertEquals(self.client.setbit('a', 5, True), False) - self.assertEquals(self.client.getbit('a', 5), True) - self.assertEquals(self.client.setbit('a', 4, False), False) - self.assertEquals(self.client.getbit('a', 4), False) - self.assertEquals(self.client.setbit('a', 4, True), False) - self.assertEquals(self.client.setbit('a', 5, True), True) - self.assertEquals(self.client.getbit('a', 4), True) - self.assertEquals(self.client.getbit('a', 5), True) - - def test_bitcount(self): - version = self.client.info()['redis_version'] - if StrictVersion(version) < StrictVersion('2.6.0'): - try: - raise unittest.SkipTest() - except AttributeError: - return - - self.client.setbit('a', 5, True) - self.assertEquals(self.client.bitcount('a'), 1) - self.client.setbit('a', 6, True) - self.assertEquals(self.client.bitcount('a'), 2) - self.client.setbit('a', 5, False) - self.assertEquals(self.client.bitcount('a'), 1) - self.client.setbit('a', 9, True) - self.client.setbit('a', 17, True) - self.client.setbit('a', 25, True) - self.client.setbit('a', 33, True) - self.assertEquals(self.client.bitcount('a'), 5) - self.assertEquals(self.client.bitcount('a', 0, -1), 5) - self.assertEquals(self.client.bitcount('a', 2, 3), 2) - self.assertEquals(self.client.bitcount('a', 2, -1), 3) - self.assertEquals(self.client.bitcount('a', -2, -1), 2) - self.assertEquals(self.client.bitcount('a', 1, 1), 1) - - def test_bitop_not_empty_string(self): - version = self.client.info()['redis_version'] - if StrictVersion(version) < StrictVersion('2.6.0'): - try: - raise unittest.SkipTest() - except AttributeError: - return - - self.client.set('a', '') - self.client.bitop('not', 'r', 'a') - self.assertEquals(self.client.get('r'), None) - - def test_bitop_not(self): - version = self.client.info()['redis_version'] - if StrictVersion(version) < StrictVersion('2.6.0'): - try: - raise unittest.SkipTest() - except AttributeError: - return - - test_str = b('\xAA\x00\xFF\x55') - correct = ~0xAA00FF55 & 0xFFFFFFFF - self.client.set('a', test_str) - self.client.bitop('not', 'r', 'a') - self.assertEquals( - int(binascii.hexlify(self.client.get('r')), 16), - correct) - - def test_bitop_not_in_place(self): - version = self.client.info()['redis_version'] - if StrictVersion(version) < StrictVersion('2.6.0'): - try: - raise unittest.SkipTest() - except AttributeError: - return - - test_str = b('\xAA\x00\xFF\x55') - correct = ~0xAA00FF55 & 0xFFFFFFFF - self.client.set('a', test_str) - self.client.bitop('not', 'a', 'a') - self.assertEquals( - int(binascii.hexlify(self.client.get('a')), 16), - correct) - - def test_bitop_single_string(self): - version = self.client.info()['redis_version'] - if StrictVersion(version) < StrictVersion('2.6.0'): - try: - raise unittest.SkipTest() - except AttributeError: - return - - test_str = b('\x01\x02\xFF') - self.client.set('a', test_str) - self.client.bitop('and', 'res1', 'a') - self.client.bitop('or', 'res2', 'a') - self.client.bitop('xor', 'res3', 'a') - self.assertEquals(self.client.get('res1'), test_str) - self.assertEquals(self.client.get('res2'), test_str) - self.assertEquals(self.client.get('res3'), test_str) - - def test_bitop_string_operands(self): - version = self.client.info()['redis_version'] - if StrictVersion(version) < StrictVersion('2.6.0'): - try: - raise unittest.SkipTest() - except AttributeError: - return - - self.client.set('a', b('\x01\x02\xFF\xFF')) - self.client.set('b', b('\x01\x02\xFF')) - self.client.bitop('and', 'res1', 'a', 'b') - self.client.bitop('or', 'res2', 'a', 'b') - self.client.bitop('xor', 'res3', 'a', 'b') - self.assertEquals( - int(binascii.hexlify(self.client.get('res1')), 16), - 0x0102FF00) - self.assertEquals( - int(binascii.hexlify(self.client.get('res2')), 16), - 0x0102FFFF) - self.assertEquals( - int(binascii.hexlify(self.client.get('res3')), 16), - 0x000000FF) - - def test_getset(self): - self.assertEquals(self.client.getset('a', 'foo'), None) - self.assertEquals(self.client.getset('a', 'bar'), b('foo')) - - def test_incr(self): - self.assertEquals(self.client.incr('a'), 1) - self.assertEquals(self.client['a'], b('1')) - self.assertEquals(self.client.incr('a'), 2) - self.assertEquals(self.client['a'], b('2')) - self.assertEquals(self.client.incr('a', amount=5), 7) - self.assertEquals(self.client['a'], b('7')) - - def test_incrbyfloat(self): - version = self.client.info()['redis_version'] - if StrictVersion(version) < StrictVersion('2.6.0'): - try: - raise unittest.SkipTest() - except AttributeError: - return - - self.assertEquals(self.client.incrbyfloat('a'), 1.0) - self.assertEquals(self.client['a'], b('1')) - self.assertEquals(self.client.incrbyfloat('a', 1.1), 2.1) - self.assertEquals(float(self.client['a']), float(2.1)) - - def test_keys(self): - self.assertEquals(self.client.keys(), []) - keys = set([b('test_a'), b('test_b'), b('testc')]) - for key in keys: - self.client[key] = 1 - self.assertEquals( - set(self.client.keys(pattern='test_*')), - keys - set([b('testc')])) - self.assertEquals(set(self.client.keys(pattern='test*')), keys) - - def test_mget(self): - self.assertEquals(self.client.mget(['a', 'b']), [None, None]) - self.client['a'] = '1' - self.client['b'] = '2' - self.client['c'] = '3' - self.assertEquals( - self.client.mget(['a', 'other', 'b', 'c']), - [b('1'), None, b('2'), b('3')]) - - def test_mset(self): - d = {'a': '1', 'b': '2', 'c': '3'} - self.assert_(self.client.mset(d)) - for k, v in iteritems(d): - self.assertEquals(self.client[k], b(v)) - - def test_msetnx(self): - d = {'a': '1', 'b': '2', 'c': '3'} - self.assert_(self.client.msetnx(d)) - d2 = {'a': 'x', 'd': '4'} - self.assert_(not self.client.msetnx(d2)) - for k, v in iteritems(d): - self.assertEquals(self.client[k], b(v)) - self.assertEquals(self.client.get('d'), None) - - def test_randomkey(self): - self.assertEquals(self.client.randomkey(), None) - self.client['a'] = '1' - self.client['b'] = '2' - self.client['c'] = '3' - self.assert_(self.client.randomkey() in (b('a'), b('b'), b('c'))) - - def test_rename(self): - self.client['a'] = '1' - self.assert_(self.client.rename('a', 'b')) - self.assertEquals(self.client.get('a'), None) - self.assertEquals(self.client['b'], b('1')) - - def test_renamenx(self): - self.client['a'] = '1' - self.client['b'] = '2' - self.assert_(not self.client.renamenx('a', 'b')) - self.assertEquals(self.client['a'], b('1')) - self.assertEquals(self.client['b'], b('2')) - - def test_set_nx(self): - version = self.client.info()['redis_version'] - if StrictVersion(version) < StrictVersion('2.6.12'): - try: - raise unittest.SkipTest() - except AttributeError: - return - - self.assertEquals(self.client.set('foo', '1', nx=True), True) - self.assertEquals(self.client.set('foo', '2', nx=True), None) - self.assertEquals(self.client.get('foo'), b('1')) - - def test_set_xx(self): - version = self.client.info()['redis_version'] - if StrictVersion(version) < StrictVersion('2.6.12'): - try: - raise unittest.SkipTest() - except AttributeError: - return - - self.assertEquals(self.client.set('foo', '1', xx=True), None) - self.assertEquals(self.client.get('foo'), None) - self.client.set('foo', 'bar') - self.assertEquals(self.client.set('foo', '2', xx=True), True) - self.assertEquals(self.client.get('foo'), b('2')) - - def test_set_px(self): - version = self.client.info()['redis_version'] - if StrictVersion(version) < StrictVersion('2.6.12'): - try: - raise unittest.SkipTest() - except AttributeError: - return - - self.assertEquals(self.client.set('foo', '1', px=10000), True) - self.assertEquals(self.client['foo'], b('1')) - self.assert_(0 < self.client.pttl('foo') <= 10000) - self.assert_(0 < self.client.ttl('foo') <= 10) - # expire given a timedelta - expire_at = datetime.timedelta(milliseconds=1000) - self.assertEquals(self.client.set('foo', '1', px=expire_at), True) - self.assert_(0 < self.client.pttl('foo') <= 1000) - self.assert_(0 < self.client.ttl('foo') <= 1) - - def test_set_ex(self): - version = self.client.info()['redis_version'] - if StrictVersion(version) < StrictVersion('2.6.12'): - try: - raise unittest.SkipTest() - except AttributeError: - return - - self.assertEquals(self.client.set('foo', '1', ex=10), True) - self.assertEquals(self.client.ttl('foo'), 10) - # expire given a timedelta - expire_at = datetime.timedelta(seconds=60) - self.assertEquals(self.client.set('foo', '1', ex=expire_at), True) - self.assertEquals(self.client.ttl('foo'), 60) - - def test_set_multipleoptions(self): - version = self.client.info()['redis_version'] - if StrictVersion(version) < StrictVersion('2.6.12'): - try: - raise unittest.SkipTest() - except AttributeError: - return - - self.client['foo'] = 'val' - self.assertEquals( - self.client.set('foo', 'bar', xx=True, px=10000), - True) - self.assertEquals(self.client.ttl('foo'), 10) - - def test_setex(self): - self.assertEquals(self.client.setex('a', '1', 60), True) - self.assertEquals(self.client['a'], b('1')) - self.assertEquals(self.client.ttl('a'), 60) - - def test_setnx(self): - self.assert_(self.client.setnx('a', '1')) - self.assertEquals(self.client['a'], b('1')) - self.assert_(not self.client.setnx('a', '2')) - self.assertEquals(self.client['a'], b('1')) - - def test_setrange(self): - self.assertEquals(self.client.setrange('a', 5, 'abcdef'), 11) - self.assertEquals(self.client['a'], b('\0\0\0\0\0abcdef')) - self.client['a'] = 'Hello World' - self.assertEquals(self.client.setrange('a', 6, 'Redis'), 11) - self.assertEquals(self.client['a'], b('Hello Redis')) - - def test_strlen(self): - self.client['a'] = 'abcdef' - self.assertEquals(self.client.strlen('a'), 6) - - def test_substr(self): - # invalid key type - self.client.rpush('a', 'a1') - self.assertRaises(redis.ResponseError, self.client.substr, 'a', 0) - del self.client['a'] - # real logic - self.client['a'] = 'abcdefghi' - self.assertEquals(self.client.substr('a', 0), b('abcdefghi')) - self.assertEquals(self.client.substr('a', 2), b('cdefghi')) - self.assertEquals(self.client.substr('a', 3, 5), b('def')) - self.assertEquals(self.client.substr('a', 3, -2), b('defgh')) - self.client['a'] = 123456 # does substr work with ints? - self.assertEquals(self.client.substr('a', 2, -2), b('345')) - - def test_type(self): - self.assertEquals(self.client.type('a'), b('none')) - self.client['a'] = '1' - self.assertEquals(self.client.type('a'), b('string')) - del self.client['a'] - self.client.lpush('a', '1') - self.assertEquals(self.client.type('a'), b('list')) - del self.client['a'] - self.client.sadd('a', '1') - self.assertEquals(self.client.type('a'), b('set')) - del self.client['a'] - self.client.zadd('a', **{'1': 1}) - self.assertEquals(self.client.type('a'), b('zset')) - - # LISTS - def make_list(self, name, l): - for i in l: - self.client.rpush(name, i) - - def test_blpop(self): - self.make_list('a', 'ab') - self.make_list('b', 'cd') - self.assertEquals( - self.client.blpop(['b', 'a'], timeout=1), - (b('b'), b('c'))) - self.assertEquals( - self.client.blpop(['b', 'a'], timeout=1), - (b('b'), b('d'))) - self.assertEquals( - self.client.blpop(['b', 'a'], timeout=1), - (b('a'), b('a'))) - self.assertEquals( - self.client.blpop(['b', 'a'], timeout=1), - (b('a'), b('b'))) - self.assertEquals(self.client.blpop(['b', 'a'], timeout=1), None) - self.make_list('c', 'a') - self.assertEquals(self.client.blpop('c', timeout=1), (b('c'), b('a'))) - - def test_brpop(self): - self.make_list('a', 'ab') - self.make_list('b', 'cd') - self.assertEquals( - self.client.brpop(['b', 'a'], timeout=1), - (b('b'), b('d'))) - self.assertEquals( - self.client.brpop(['b', 'a'], timeout=1), - (b('b'), b('c'))) - self.assertEquals( - self.client.brpop(['b', 'a'], timeout=1), - (b('a'), b('b'))) - self.assertEquals( - self.client.brpop(['b', 'a'], timeout=1), - (b('a'), b('a'))) - self.assertEquals(self.client.brpop(['b', 'a'], timeout=1), None) - self.make_list('c', 'a') - self.assertEquals(self.client.brpop('c', timeout=1), (b('c'), b('a'))) - - def test_brpoplpush(self): - self.make_list('a', '12') - self.make_list('b', '34') - self.assertEquals(self.client.brpoplpush('a', 'b'), b('2')) - self.assertEquals(self.client.brpoplpush('a', 'b'), b('1')) - self.assertEquals(self.client.brpoplpush('a', 'b', timeout=1), None) - self.assertEquals(self.client.lrange('a', 0, -1), []) - self.assertEquals( - self.client.lrange('b', 0, -1), - [b('1'), b('2'), b('3'), b('4')]) - - def test_brpoplpush_empty_string(self): - self.client.lpush('a', '') - self.assertEquals(self.client.brpoplpush('a', 'b'), b('')) - - def test_lindex(self): - # no key - self.assertEquals(self.client.lindex('a', '0'), None) - # key is not a list - self.client['a'] = 'b' - self.assertRaises(redis.ResponseError, self.client.lindex, 'a', '0') - del self.client['a'] - # real logic - self.make_list('a', 'abc') - self.assertEquals(self.client.lindex('a', '0'), b('a')) - self.assertEquals(self.client.lindex('a', '1'), b('b')) - self.assertEquals(self.client.lindex('a', '2'), b('c')) - - def test_linsert(self): - # no key - self.assertEquals(self.client.linsert('a', 'after', 'x', 'y'), 0) - # key is not a list - self.client['a'] = 'b' - self.assertRaises( - redis.ResponseError, self.client.linsert, 'a', 'after', 'x', 'y' - ) - del self.client['a'] - # real logic - self.make_list('a', 'abc') - self.assertEquals(self.client.linsert('a', 'after', 'b', 'b1'), 4) - self.assertEquals( - self.client.lrange('a', 0, -1), - [b('a'), b('b'), b('b1'), b('c')]) - self.assertEquals(self.client.linsert('a', 'before', 'b', 'a1'), 5) - self.assertEquals( - self.client.lrange('a', 0, -1), - [b('a'), b('a1'), b('b'), b('b1'), b('c')]) - - def test_llen(self): - # no key - self.assertEquals(self.client.llen('a'), 0) - # key is not a list - self.client['a'] = 'b' - self.assertRaises(redis.ResponseError, self.client.llen, 'a') - del self.client['a'] - # real logic - self.make_list('a', 'abc') - self.assertEquals(self.client.llen('a'), 3) - - def test_lpop(self): - # no key - self.assertEquals(self.client.lpop('a'), None) - # key is not a list - self.client['a'] = 'b' - self.assertRaises(redis.ResponseError, self.client.lpop, 'a') - del self.client['a'] - # real logic - self.make_list('a', 'abc') - self.assertEquals(self.client.lpop('a'), b('a')) - self.assertEquals(self.client.lpop('a'), b('b')) - self.assertEquals(self.client.lpop('a'), b('c')) - self.assertEquals(self.client.lpop('a'), None) - - def test_lpush(self): - # key is not a list - self.client['a'] = 'b' - self.assertRaises(redis.ResponseError, self.client.lpush, 'a', 'a') - del self.client['a'] - # real logic - version = self.client.info()['redis_version'] - if StrictVersion(version) >= StrictVersion('2.4.0'): - self.assertEqual(1, self.client.lpush('a', 'b')) - self.assertEqual(2, self.client.lpush('a', 'a')) - self.assertEqual(4, self.client.lpush('a', 'b', 'a')) - elif StrictVersion(version) >= StrictVersion('1.3.4'): - self.assertEqual(1, self.client.lpush('a', 'b')) - self.assertEqual(2, self.client.lpush('a', 'a')) - else: - self.assert_(self.client.lpush('a', 'b')) - self.assert_(self.client.lpush('a', 'a')) - self.assertEquals(self.client.lindex('a', 0), b('a')) - self.assertEquals(self.client.lindex('a', 1), b('b')) - - def test_lpushx(self): - # key is not a list - self.client['a'] = 'b' - self.assertRaises(redis.ResponseError, self.client.lpushx, 'a', 'a') - del self.client['a'] - # real logic - self.assertEquals(self.client.lpushx('a', 'b'), 0) - self.assertEquals(self.client.lrange('a', 0, -1), []) - self.make_list('a', 'abc') - self.assertEquals(self.client.lpushx('a', 'd'), 4) - self.assertEquals( - self.client.lrange('a', 0, -1), - [b('d'), b('a'), b('b'), b('c')]) - - def test_lrange(self): - # no key - self.assertEquals(self.client.lrange('a', 0, 1), []) - # key is not a list - self.client['a'] = 'b' - self.assertRaises(redis.ResponseError, self.client.lrange, 'a', 0, 1) - del self.client['a'] - # real logic - self.make_list('a', 'abcde') - self.assertEquals( - self.client.lrange('a', 0, 2), - [b('a'), b('b'), b('c')]) - self.assertEquals( - self.client.lrange('a', 2, 10), - [b('c'), b('d'), b('e')]) - - def test_lrem(self): - # no key - self.assertEquals(self.client.lrem('a', 'foo'), 0) - # key is not a list - self.client['a'] = 'b' - self.assertRaises(redis.ResponseError, self.client.lrem, 'a', 'b') - del self.client['a'] - # real logic - self.make_list('a', 'aaaa') - self.assertEquals(self.client.lrem('a', 'a', 1), 1) - self.assertEquals( - self.client.lrange('a', 0, 3), - [b('a'), b('a'), b('a')]) - self.assertEquals(self.client.lrem('a', 'a'), 3) - # remove all the elements in the list means the key is deleted - self.assertEquals(self.client.lrange('a', 0, 1), []) - - def test_lset(self): - # no key - self.assertRaises(redis.ResponseError, self.client.lset, 'a', 1, 'b') - # key is not a list - self.client['a'] = 'b' - self.assertRaises(redis.ResponseError, self.client.lset, 'a', 1, 'b') - del self.client['a'] - # real logic - self.make_list('a', 'abc') - self.assertEquals( - self.client.lrange('a', 0, 2), - [b('a'), b('b'), b('c')]) - self.assert_(self.client.lset('a', 1, 'd')) - self.assertEquals( - self.client.lrange('a', 0, 2), - [b('a'), b('d'), b('c')]) - - def test_ltrim(self): - # no key -- TODO: Not sure why this is actually true. - self.assert_(self.client.ltrim('a', 0, 2)) - # key is not a list - self.client['a'] = 'b' - self.assertRaises(redis.ResponseError, self.client.ltrim, 'a', 0, 2) - del self.client['a'] - # real logic - self.make_list('a', 'abc') - self.assert_(self.client.ltrim('a', 0, 1)) - self.assertEquals(self.client.lrange('a', 0, 5), [b('a'), b('b')]) - - def test_rpop(self): - # no key - self.assertEquals(self.client.rpop('a'), None) - # key is not a list - self.client['a'] = 'b' - self.assertRaises(redis.ResponseError, self.client.rpop, 'a') - del self.client['a'] - # real logic - self.make_list('a', 'abc') - self.assertEquals(self.client.rpop('a'), b('c')) - self.assertEquals(self.client.rpop('a'), b('b')) - self.assertEquals(self.client.rpop('a'), b('a')) - self.assertEquals(self.client.rpop('a'), None) - - def test_rpoplpush(self): - # no src key - self.make_list('b', ['b1']) - self.assertEquals(self.client.rpoplpush('a', 'b'), None) - # no dest key - self.assertEquals(self.client.rpoplpush('b', 'a'), b('b1')) - self.assertEquals(self.client.lindex('a', 0), b('b1')) - del self.client['a'] - del self.client['b'] - # src key is not a list - self.client['a'] = 'a1' - self.assertRaises(redis.ResponseError, self.client.rpoplpush, 'a', 'b') - del self.client['a'] - # dest key is not a list - self.make_list('a', ['a1']) - self.client['b'] = 'b' - self.assertRaises(redis.ResponseError, self.client.rpoplpush, 'a', 'b') - del self.client['a'] - del self.client['b'] - # real logic - self.make_list('a', ['a1', 'a2', 'a3']) - self.make_list('b', ['b1', 'b2', 'b3']) - self.assertEquals(self.client.rpoplpush('a', 'b'), b('a3')) - self.assertEquals(self.client.lrange('a', 0, 2), [b('a1'), b('a2')]) - self.assertEquals( - self.client.lrange('b', 0, 4), - [b('a3'), b('b1'), b('b2'), b('b3')]) - - def test_rpush(self): - # key is not a list - self.client['a'] = 'b' - self.assertRaises(redis.ResponseError, self.client.rpush, 'a', 'a') - del self.client['a'] - # real logic - version = self.client.info()['redis_version'] - if StrictVersion(version) >= StrictVersion('2.4.0'): - self.assertEqual(1, self.client.rpush('a', 'a')) - self.assertEqual(2, self.client.rpush('a', 'b')) - self.assertEqual(4, self.client.rpush('a', 'a', 'b')) - elif StrictVersion(version) >= StrictVersion('1.3.4'): - self.assertEqual(1, self.client.rpush('a', 'a')) - self.assertEqual(2, self.client.rpush('a', 'b')) - else: - self.assert_(self.client.rpush('a', 'a')) - self.assert_(self.client.rpush('a', 'b')) - self.assertEquals(self.client.lindex('a', 0), b('a')) - self.assertEquals(self.client.lindex('a', 1), b('b')) - - def test_rpushx(self): - # key is not a list - self.client['a'] = 'b' - self.assertRaises(redis.ResponseError, self.client.rpushx, 'a', 'a') - del self.client['a'] - # real logic - self.assertEquals(self.client.rpushx('a', 'b'), 0) - self.assertEquals(self.client.lrange('a', 0, -1), []) - self.make_list('a', 'abc') - self.assertEquals(self.client.rpushx('a', 'd'), 4) - self.assertEquals( - self.client.lrange('a', 0, -1), - [b('a'), b('b'), b('c'), b('d')]) - - # Set commands - def make_set(self, name, l): - for i in l: - self.client.sadd(name, i) - - def test_sadd(self): - # key is not a set - self.client['a'] = 'a' - self.assertRaises(redis.ResponseError, self.client.sadd, 'a', 'a1') - del self.client['a'] - # real logic - members = set([b('a1'), b('a2'), b('a3')]) - self.make_set('a', members) - self.assertEquals(self.client.smembers('a'), members) - - def test_scard(self): - # key is not a set - self.client['a'] = 'a' - self.assertRaises(redis.ResponseError, self.client.scard, 'a') - del self.client['a'] - # real logic - self.make_set('a', 'abc') - self.assertEquals(self.client.scard('a'), 3) - - def test_sdiff(self): - # some key is not a set - self.make_set('a', ['a1', 'a2', 'a3']) - self.client['b'] = 'b' - self.assertRaises(redis.ResponseError, self.client.sdiff, ['a', 'b']) - del self.client['b'] - # real logic - self.make_set('b', ['b1', 'a2', 'b3']) - self.assertEquals( - self.client.sdiff(['a', 'b']), - set([b('a1'), b('a3')])) - - def test_sdiffstore(self): - # some key is not a set - self.make_set('a', ['a1', 'a2', 'a3']) - self.client['b'] = 'b' - self.assertRaises( - redis.ResponseError, self.client.sdiffstore, - 'c', ['a', 'b']) - del self.client['b'] - self.make_set('b', ['b1', 'a2', 'b3']) - # dest key always gets overwritten, even if it's not a set, so don't - # test for that - # real logic - self.assertEquals(self.client.sdiffstore('c', ['a', 'b']), 2) - self.assertEquals(self.client.smembers('c'), set([b('a1'), b('a3')])) - - def test_sinter(self): - # some key is not a set - self.make_set('a', ['a1', 'a2', 'a3']) - self.client['b'] = 'b' - self.assertRaises(redis.ResponseError, self.client.sinter, ['a', 'b']) - del self.client['b'] - # real logic - self.make_set('b', ['a1', 'b2', 'a3']) - self.assertEquals( - self.client.sinter(['a', 'b']), - set([b('a1'), b('a3')])) - - def test_sinterstore(self): - # some key is not a set - self.make_set('a', ['a1', 'a2', 'a3']) - self.client['b'] = 'b' - self.assertRaises( - redis.ResponseError, self.client.sinterstore, - 'c', ['a', 'b']) - del self.client['b'] - self.make_set('b', ['a1', 'b2', 'a3']) - # dest key always gets overwritten, even if it's not a set, so don't - # test for that - # real logic - self.assertEquals(self.client.sinterstore('c', ['a', 'b']), 2) - self.assertEquals(self.client.smembers('c'), set([b('a1'), b('a3')])) - - def test_sismember(self): - # key is not a set - self.client['a'] = 'a' - self.assertRaises(redis.ResponseError, self.client.sismember, 'a', 'a') - del self.client['a'] - # real logic - self.make_set('a', 'abc') - self.assertEquals(self.client.sismember('a', 'a'), True) - self.assertEquals(self.client.sismember('a', 'b'), True) - self.assertEquals(self.client.sismember('a', 'c'), True) - self.assertEquals(self.client.sismember('a', 'd'), False) - - def test_smembers(self): - # key is not a set - self.client['a'] = 'a' - self.assertRaises(redis.ResponseError, self.client.smembers, 'a') - del self.client['a'] - # set doesn't exist - self.assertEquals(self.client.smembers('a'), set()) - # real logic - self.make_set('a', 'abc') - self.assertEquals( - self.client.smembers('a'), - set([b('a'), b('b'), b('c')])) - - def test_smove(self): - # src key is not set - self.make_set('b', ['b1', 'b2']) - self.assertEquals(self.client.smove('a', 'b', 'a1'), 0) - # src key is not a set - self.client['a'] = 'a' - self.assertRaises( - redis.ResponseError, self.client.smove, - 'a', 'b', 'a1') - del self.client['a'] - self.make_set('a', ['a1', 'a2']) - # dest key is not a set - del self.client['b'] - self.client['b'] = 'b' - self.assertRaises( - redis.ResponseError, self.client.smove, - 'a', 'b', 'a1') - del self.client['b'] - self.make_set('b', ['b1', 'b2']) - # real logic - self.assert_(self.client.smove('a', 'b', 'a1')) - self.assertEquals(self.client.smembers('a'), set([b('a2')])) - self.assertEquals( - self.client.smembers('b'), - set([b('b1'), b('b2'), b('a1')])) - - def test_spop(self): - # key is not set - self.assertEquals(self.client.spop('a'), None) - # key is not a set - self.client['a'] = 'a' - self.assertRaises(redis.ResponseError, self.client.spop, 'a') - del self.client['a'] - # real logic - s = [b('a'), b('b'), b('c')] - self.make_set('a', s) - value = self.client.spop('a') - self.assert_(value in s) - self.assertEquals(self.client.smembers('a'), set(s) - set([value])) - - def test_srandmember(self): - # key is not set - self.assertEquals(self.client.srandmember('a'), None) - # key is not a set - self.client['a'] = 'a' - self.assertRaises(redis.ResponseError, self.client.srandmember, 'a') - del self.client['a'] - # real logic - self.make_set('a', 'abc') - self.assert_(self.client.srandmember('a') in b('abc')) - - version = self.client.info()['redis_version'] - if StrictVersion(version) >= StrictVersion('2.6.0'): - randoms = self.client.srandmember('a', number=2) - self.assertEquals(len(randoms), 2) - for r in randoms: - self.assert_(r in b('abc')) - - def test_srem(self): - # key is not set - self.assertEquals(self.client.srem('a', 'a'), 0) - # key is not a set - self.client['a'] = 'a' - self.assertRaises(redis.ResponseError, self.client.srem, 'a', 'a') - del self.client['a'] - # real logic - self.make_set('a', 'abcd') - self.assertEquals(self.client.srem('a', 'e'), 0) - self.assertEquals(self.client.srem('a', 'b', 'd'), 2) - self.assertEquals(self.client.smembers('a'), set([b('a'), b('c')])) - - def test_sunion(self): - # some key is not a set - self.make_set('a', ['a1', 'a2', 'a3']) - self.client['b'] = 'b' - self.assertRaises(redis.ResponseError, self.client.sunion, ['a', 'b']) - del self.client['b'] - # real logic - self.make_set('b', ['a1', 'b2', 'a3']) - self.assertEquals( - self.client.sunion(['a', 'b']), - set([b('a1'), b('a2'), b('a3'), b('b2')])) - - def test_sunionstore(self): - # some key is not a set - self.make_set('a', ['a1', 'a2', 'a3']) - self.client['b'] = 'b' - self.assertRaises( - redis.ResponseError, self.client.sunionstore, - 'c', ['a', 'b']) - del self.client['b'] - self.make_set('b', ['a1', 'b2', 'a3']) - # dest key always gets overwritten, even if it's not a set, so don't - # test for that - # real logic - self.assertEquals(self.client.sunionstore('c', ['a', 'b']), 4) - self.assertEquals( - self.client.smembers('c'), - set([b('a1'), b('a2'), b('a3'), b('b2')])) - - # SORTED SETS - def make_zset(self, name, d): - for k, v in d.items(): - self.client.zadd(name, **{k: v}) - - def test_zadd(self): - self.make_zset('a', {'a1': 1, 'a2': 2, 'a3': 3}) - self.assertEquals( - self.client.zrange('a', 0, 3), - [b('a1'), b('a2'), b('a3')]) - - def test_zcard(self): - # key is not a zset - self.client['a'] = 'a' - self.assertRaises(redis.ResponseError, self.client.zcard, 'a') - del self.client['a'] - # real logic - self.make_zset('a', {'a1': 1, 'a2': 2, 'a3': 3}) - self.assertEquals(self.client.zcard('a'), 3) - - def test_zcount(self): - # key is not a zset - self.client['a'] = 'a' - self.assertRaises(redis.ResponseError, self.client.zcount, 'a', 0, 0) - del self.client['a'] - # real logic - self.make_zset('a', {'a1': 1, 'a2': 2, 'a3': 3}) - self.assertEquals(self.client.zcount('a', '-inf', '+inf'), 3) - self.assertEquals(self.client.zcount('a', 1, 2), 2) - self.assertEquals(self.client.zcount('a', 10, 20), 0) - - def test_zincrby(self): - # key is not a zset - self.client['a'] = 'a' - self.assertRaises(redis.ResponseError, self.client.zincrby, 'a', 'a1') - del self.client['a'] - # real logic - self.make_zset('a', {'a1': 1, 'a2': 2, 'a3': 3}) - self.assertEquals(self.client.zincrby('a', 'a2'), 3.0) - self.assertEquals(self.client.zincrby('a', 'a3', amount=5), 8.0) - self.assertEquals(self.client.zscore('a', 'a2'), 3.0) - self.assertEquals(self.client.zscore('a', 'a3'), 8.0) - - def test_zinterstore(self): - self.make_zset('a', {'a1': 1, 'a2': 1, 'a3': 1}) - self.make_zset('b', {'a1': 2, 'a3': 2, 'a4': 2}) - self.make_zset('c', {'a1': 6, 'a3': 5, 'a4': 4}) - - # sum, no weight - self.assert_(self.client.zinterstore('z', ['a', 'b', 'c'])) - self.assertEquals( - self.client.zrange('z', 0, -1, withscores=True), - [(b('a3'), 8), (b('a1'), 9)] - ) - - # max, no weight - self.assert_( - self.client.zinterstore('z', ['a', 'b', 'c'], aggregate='MAX') - ) - self.assertEquals( - self.client.zrange('z', 0, -1, withscores=True), - [(b('a3'), 5), (b('a1'), 6)] - ) - - # with weight - self.assert_(self.client.zinterstore('z', {'a': 1, 'b': 2, 'c': 3})) - self.assertEquals( - self.client.zrange('z', 0, -1, withscores=True), - [(b('a3'), 20), (b('a1'), 23)] - ) - - def test_zrange(self): - # key is not a zset - self.client['a'] = 'a' - self.assertRaises(redis.ResponseError, self.client.zrange, 'a', 0, 1) - del self.client['a'] - # real logic - self.make_zset('a', {'a1': 1, 'a2': 2, 'a3': 3}) - self.assertEquals(self.client.zrange('a', 0, 1), [b('a1'), b('a2')]) - self.assertEquals(self.client.zrange('a', 1, 2), [b('a2'), b('a3')]) - self.assertEquals( - self.client.zrange('a', 0, 1, withscores=True), - [(b('a1'), 1.0), (b('a2'), 2.0)]) - self.assertEquals( - self.client.zrange('a', 1, 2, withscores=True), - [(b('a2'), 2.0), (b('a3'), 3.0)]) - # test a custom score casting function returns the correct value - self.assertEquals( - self.client.zrange('a', 0, 1, withscores=True, - score_cast_func=int), - [(b('a1'), 1), (b('a2'), 2)]) - # a non existant key should return empty list - self.assertEquals(self.client.zrange('b', 0, 1, withscores=True), []) - - def test_zrangebyscore(self): - # key is not a zset - self.client['a'] = 'a' - self.assertRaises( - redis.ResponseError, self.client.zrangebyscore, - 'a', 0, 1) - del self.client['a'] - # real logic - self.make_zset('a', {'a1': 1, 'a2': 2, 'a3': 3, 'a4': 4, 'a5': 5}) - self.assertEquals( - self.client.zrangebyscore('a', 2, 4), - [b('a2'), b('a3'), b('a4')]) - self.assertEquals( - self.client.zrangebyscore('a', 2, 4, start=1, num=2), - [b('a3'), b('a4')]) - self.assertEquals( - self.client.zrangebyscore('a', 2, 4, withscores=True), - [(b('a2'), 2.0), (b('a3'), 3.0), (b('a4'), 4.0)]) - # a non existant key should return empty list - self.assertEquals( - self.client.zrangebyscore('b', 0, 1, withscores=True), []) - - def test_zrank(self): - # key is not a zset - self.client['a'] = 'a' - self.assertRaises(redis.ResponseError, self.client.zrank, 'a', 'a4') - del self.client['a'] - # real logic - self.make_zset('a', {'a1': 1, 'a2': 2, 'a3': 3, 'a4': 4, 'a5': 5}) - self.assertEquals(self.client.zrank('a', 'a1'), 0) - self.assertEquals(self.client.zrank('a', 'a2'), 1) - self.assertEquals(self.client.zrank('a', 'a3'), 2) - self.assertEquals(self.client.zrank('a', 'a4'), 3) - self.assertEquals(self.client.zrank('a', 'a5'), 4) - # non-existent value in zset - self.assertEquals(self.client.zrank('a', 'a6'), None) - - def test_zrem(self): - # key is not a zset - self.client['a'] = 'a' - self.assertRaises(redis.ResponseError, self.client.zrem, 'a', 'a1') - del self.client['a'] - # real logic - self.make_zset('a', {'a1': 1, 'a2': 2, 'a3': 3}) - self.assertEquals(self.client.zrem('a', 'a2'), 1) - self.assertEquals(self.client.zrange('a', 0, 5), [b('a1'), b('a3')]) - self.assertEquals(self.client.zrem('a', 'b'), 0) - self.assertEquals(self.client.zrange('a', 0, 5), [b('a1'), b('a3')]) - - def test_zrem_multiple_keys(self): - self.make_zset('a', {'a1': 1, 'a2': 2, 'a3': 3}) - self.assertEquals(self.client.zrem('a', 'a1', 'a2'), 2) - self.assertEquals(self.client.zrange('a', 0, 5), [b('a3')]) - - def test_zremrangebyrank(self): - # key is not a zset - self.client['a'] = 'a' - self.assertRaises( - redis.ResponseError, self.client.zremrangebyscore, - 'a', 0, 1) - del self.client['a'] - # real logic - self.make_zset('a', {'a1': 1, 'a2': 2, 'a3': 3, 'a4': 4, 'a5': 5}) - self.assertEquals(self.client.zremrangebyrank('a', 1, 3), 3) - self.assertEquals(self.client.zrange('a', 0, 5), [b('a1'), b('a5')]) - - def test_zremrangebyscore(self): - # key is not a zset - self.client['a'] = 'a' - self.assertRaises( - redis.ResponseError, self.client.zremrangebyscore, - 'a', 0, 1) - del self.client['a'] - # real logic - self.make_zset('a', {'a1': 1, 'a2': 2, 'a3': 3, 'a4': 4, 'a5': 5}) - self.assertEquals(self.client.zremrangebyscore('a', 2, 4), 3) - self.assertEquals(self.client.zrange('a', 0, 5), [b('a1'), b('a5')]) - self.assertEquals(self.client.zremrangebyscore('a', 2, 4), 0) - self.assertEquals(self.client.zrange('a', 0, 5), [b('a1'), b('a5')]) - - def test_zrevrange(self): - # key is not a zset - self.client['a'] = 'a' - self.assertRaises( - redis.ResponseError, self.client.zrevrange, - 'a', 0, 1) - del self.client['a'] - # real logic - self.make_zset('a', {'a1': 1, 'a2': 2, 'a3': 3}) - self.assertEquals(self.client.zrevrange('a', 0, 1), [b('a3'), b('a2')]) - self.assertEquals(self.client.zrevrange('a', 1, 2), [b('a2'), b('a1')]) - self.assertEquals( - self.client.zrevrange('a', 0, 1, withscores=True), - [(b('a3'), 3.0), (b('a2'), 2.0)]) - self.assertEquals( - self.client.zrevrange('a', 1, 2, withscores=True), - [(b('a2'), 2.0), (b('a1'), 1.0)]) - # a non existant key should return empty list - self.assertEquals(self.client.zrange('b', 0, 1, withscores=True), []) - - def test_zrevrangebyscore(self): - # key is not a zset - self.client['a'] = 'a' - self.assertRaises( - redis.ResponseError, self.client.zrevrangebyscore, - 'a', 0, 1) - del self.client['a'] - # real logic - self.make_zset('a', {'a1': 1, 'a2': 2, 'a3': 3, 'a4': 4, 'a5': 5}) - self.assertEquals( - self.client.zrevrangebyscore('a', 4, 2), - [b('a4'), b('a3'), b('a2')]) - self.assertEquals( - self.client.zrevrangebyscore('a', 4, 2, start=1, num=2), - [b('a3'), b('a2')]) - self.assertEquals( - self.client.zrevrangebyscore('a', 4, 2, withscores=True), - [(b('a4'), 4.0), (b('a3'), 3.0), (b('a2'), 2.0)]) - # a non existant key should return empty list - self.assertEquals( - self.client.zrevrangebyscore('b', 1, 0, withscores=True), - []) - - def test_zrevrank(self): - # key is not a zset - self.client['a'] = 'a' - self.assertRaises(redis.ResponseError, self.client.zrevrank, 'a', 'a4') - del self.client['a'] - # real logic - self.make_zset('a', {'a1': 5, 'a2': 4, 'a3': 3, 'a4': 2, 'a5': 1}) - self.assertEquals(self.client.zrevrank('a', 'a1'), 0) - self.assertEquals(self.client.zrevrank('a', 'a2'), 1) - self.assertEquals(self.client.zrevrank('a', 'a3'), 2) - self.assertEquals(self.client.zrevrank('a', 'a4'), 3) - self.assertEquals(self.client.zrevrank('a', 'a5'), 4) - self.assertEquals(self.client.zrevrank('a', 'b'), None) - - def test_zscore(self): - # key is not a zset - self.client['a'] = 'a' - self.assertRaises(redis.ResponseError, self.client.zscore, 'a', 'a1') - del self.client['a'] - # real logic - self.make_zset('a', {'a1': 0, 'a2': 1, 'a3': 2}) - self.assertEquals(self.client.zscore('a', 'a1'), 0.0) - self.assertEquals(self.client.zscore('a', 'a2'), 1.0) - # test a non-existant member - self.assertEquals(self.client.zscore('a', 'a4'), None) - - def test_zunionstore(self): - self.make_zset('a', {'a1': 1, 'a2': 1, 'a3': 1}) - self.make_zset('b', {'a1': 2, 'a3': 2, 'a4': 2}) - self.make_zset('c', {'a1': 6, 'a4': 5, 'a5': 4}) - - # sum, no weight - self.assert_(self.client.zunionstore('z', ['a', 'b', 'c'])) - self.assertEquals( - self.client.zrange('z', 0, -1, withscores=True), - [ - (b('a2'), 1), - (b('a3'), 3), - (b('a5'), 4), - (b('a4'), 7), - (b('a1'), 9) - ] - ) - - # max, no weight - self.assert_( - self.client.zunionstore('z', ['a', 'b', 'c'], aggregate='MAX') - ) - self.assertEquals( - self.client.zrange('z', 0, -1, withscores=True), - [ - (b('a2'), 1), - (b('a3'), 2), - (b('a5'), 4), - (b('a4'), 5), - (b('a1'), 6) - ] - ) - - # with weight - self.assert_(self.client.zunionstore('z', {'a': 1, 'b': 2, 'c': 3})) - self.assertEquals( - self.client.zrange('z', 0, -1, withscores=True), - [ - (b('a2'), 1), - (b('a3'), 5), - (b('a5'), 12), - (b('a4'), 19), - (b('a1'), 23) - ] - ) - - # HASHES - def make_hash(self, key, d): - for k, v in iteritems(d): - self.client.hset(key, k, v) - - def test_hget_and_hset(self): - # key is not a hash - self.client['a'] = 'a' - self.assertRaises(redis.ResponseError, self.client.hget, 'a', 'a1') - del self.client['a'] - # no key - self.assertEquals(self.client.hget('a', 'a1'), None) - # real logic - self.make_hash('a', {'a1': 1, 'a2': 2, 'a3': 3}) - self.assertEquals(self.client.hget('a', 'a1'), b('1')) - self.assertEquals(self.client.hget('a', 'a2'), b('2')) - self.assertEquals(self.client.hget('a', 'a3'), b('3')) - # field was updated, redis returns 0 - self.assertEquals(self.client.hset('a', 'a2', 5), 0) - self.assertEquals(self.client.hget('a', 'a2'), b('5')) - # field is new, redis returns 1 - self.assertEquals(self.client.hset('a', 'a4', 4), 1) - self.assertEquals(self.client.hget('a', 'a4'), b('4')) - # key inside of hash that doesn't exist returns null value - self.assertEquals(self.client.hget('a', 'b'), None) - - def test_hsetnx(self): - # Initially set the hash field - self.client.hsetnx('a', 'a1', 1) - self.assertEqual(self.client.hget('a', 'a1'), b('1')) - # Try and set the existing hash field to a different value - self.client.hsetnx('a', 'a1', 2) - self.assertEqual(self.client.hget('a', 'a1'), b('1')) - - def test_hmset(self): - d = {b('a'): b('1'), b('b'): b('2'), b('c'): b('3')} - self.assert_(self.client.hmset('foo', d)) - self.assertEqual(self.client.hgetall('foo'), d) - self.assertRaises(redis.DataError, self.client.hmset, 'foo', {}) - - def test_hmset_empty_value(self): - d = {b('a'): b('1'), b('b'): b('2'), b('c'): b('')} - self.assert_(self.client.hmset('foo', d)) - self.assertEqual(self.client.hgetall('foo'), d) - - def test_hmget(self): - d = {'a': 1, 'b': 2, 'c': 3} - self.assert_(self.client.hmset('foo', d)) - self.assertEqual( - self.client.hmget('foo', ['a', 'b', 'c']), [b('1'), b('2'), b('3')] - ) - self.assertEqual( - self.client.hmget('foo', ['a', 'c']), [b('1'), b('3')] - ) - # using *args type args - self.assertEquals(self.client.hmget('foo', 'a', 'c'), [b('1'), b('3')]) - - def test_hmget_empty(self): - self.assertEqual(self.client.hmget('foo', ['a', 'b']), [None, None]) - - def test_hmget_no_keys(self): - self.assertRaises(redis.ResponseError, self.client.hmget, 'foo', []) - - def test_hdel(self): - # key is not a hash - self.client['a'] = 'a' - self.assertRaises(redis.ResponseError, self.client.hdel, 'a', 'a1') - del self.client['a'] - # no key - self.assertEquals(self.client.hdel('a', 'a1'), 0) - # real logic - self.make_hash('a', {'a1': 1, 'a2': 2, 'a3': 3}) - self.assertEquals(self.client.hget('a', 'a2'), b('2')) - self.assertEquals(self.client.hdel('a', 'a2'), 1) - self.assertEquals(self.client.hget('a', 'a2'), None) - - def test_hdel_multiple_keys(self): - self.make_hash('a', {'a1': 1, 'a2': 2, 'a3': 3}) - self.assertEquals(self.client.hdel('a', 'a1', 'a2'), 2) - self.assertEquals(self.client.hget('a', 'a1'), None) - self.assertEquals(self.client.hget('a', 'a2'), None) - self.assertEquals(self.client.hget('a', 'a3'), b('3')) - - def test_hexists(self): - # key is not a hash - self.client['a'] = 'a' - self.assertRaises(redis.ResponseError, self.client.hexists, 'a', 'a1') - del self.client['a'] - # no key - self.assertEquals(self.client.hexists('a', 'a1'), False) - # real logic - self.make_hash('a', {'a1': 1, 'a2': 2, 'a3': 3}) - self.assertEquals(self.client.hexists('a', 'a1'), True) - self.assertEquals(self.client.hexists('a', 'a4'), False) - self.client.hdel('a', 'a1') - self.assertEquals(self.client.hexists('a', 'a1'), False) - - def test_hgetall(self): - # key is not a hash - self.client['a'] = 'a' - self.assertRaises(redis.ResponseError, self.client.hgetall, 'a') - del self.client['a'] - # no key - self.assertEquals(self.client.hgetall('a'), {}) - # real logic - h = {b('a1'): b('1'), b('a2'): b('2'), b('a3'): b('3')} - self.make_hash('a', h) - remote_hash = self.client.hgetall('a') - self.assertEquals(h, remote_hash) - - def test_hincrby(self): - # key is not a hash - self.client['a'] = 'a' - self.assertRaises(redis.ResponseError, self.client.hincrby, 'a', 'a1') - del self.client['a'] - # no key should create the hash and incr the key's value to 1 - self.assertEquals(self.client.hincrby('a', 'a1'), 1) - # real logic - self.assertEquals(self.client.hincrby('a', 'a1'), 2) - self.assertEquals(self.client.hincrby('a', 'a1', amount=2), 4) - # negative values decrement - self.assertEquals(self.client.hincrby('a', 'a1', amount=-3), 1) - # hash that exists, but key that doesn't - self.assertEquals(self.client.hincrby('a', 'a2', amount=3), 3) - # finally a key that's not an int - self.client.hset('a', 'a3', 'foo') - self.assertRaises(redis.ResponseError, self.client.hincrby, 'a', 'a3') - - def test_hincrbyfloat(self): - version = self.client.info()['redis_version'] - if StrictVersion(version) < StrictVersion('2.6.0'): - try: - raise unittest.SkipTest() - except AttributeError: - return - - # key is not a hash - self.client['a'] = 'a' - self.assertRaises(redis.ResponseError, - self.client.hincrbyfloat, 'a', 'a1') - del self.client['a'] - # no key should create the hash and incr the key's value to 1 - self.assertEquals(self.client.hincrbyfloat('a', 'a1'), 1.0) - self.assertEquals(self.client.hincrbyfloat('a', 'a1'), 2.0) - self.assertEquals(self.client.hincrbyfloat('a', 'a1', 1.2), 3.2) - - def test_hkeys(self): - # key is not a hash - self.client['a'] = 'a' - self.assertRaises(redis.ResponseError, self.client.hkeys, 'a') - del self.client['a'] - # no key - self.assertEquals(self.client.hkeys('a'), []) - # real logic - h = {b('a1'): b('1'), b('a2'): b('2'), b('a3'): b('3')} - self.make_hash('a', h) - keys = list(iterkeys(h)) - keys.sort() - remote_keys = self.client.hkeys('a') - remote_keys.sort() - self.assertEquals(keys, remote_keys) - - def test_hlen(self): - # key is not a hash - self.client['a'] = 'a' - self.assertRaises(redis.ResponseError, self.client.hlen, 'a') - del self.client['a'] - # no key - self.assertEquals(self.client.hlen('a'), 0) - # real logic - self.make_hash('a', {'a1': 1, 'a2': 2, 'a3': 3}) - self.assertEquals(self.client.hlen('a'), 3) - self.client.hdel('a', 'a3') - self.assertEquals(self.client.hlen('a'), 2) - - def test_hvals(self): - # key is not a hash - self.client['a'] = 'a' - self.assertRaises(redis.ResponseError, self.client.hvals, 'a') - del self.client['a'] - # no key - self.assertEquals(self.client.hvals('a'), []) - # real logic - h = {b('a1'): b('1'), b('a2'): b('2'), b('a3'): b('3')} - self.make_hash('a', h) - vals = list(itervalues(h)) - vals.sort() - remote_vals = self.client.hvals('a') - remote_vals.sort() - self.assertEquals(vals, remote_vals) - - # SORT - def test_sort_bad_key(self): - # key is not set - self.assertEquals(self.client.sort('a'), []) - # key is a string value - self.client['a'] = 'a' - self.assertRaises(redis.ResponseError, self.client.sort, 'a') - del self.client['a'] - - def test_sort_basic(self): - self.make_list('a', '3214') - self.assertEquals( - self.client.sort('a'), - [b('1'), b('2'), b('3'), b('4')]) - - def test_sort_limited(self): - self.make_list('a', '3214') - self.assertEquals( - self.client.sort('a', start=1, num=2), - [b('2'), b('3')]) - - def test_sort_by(self): - self.client['score:1'] = 8 - self.client['score:2'] = 3 - self.client['score:3'] = 5 - self.make_list('a_values', '123') - self.assertEquals( - self.client.sort('a_values', by='score:*'), - [b('2'), b('3'), b('1')]) - - def test_sort_get(self): - self.client['user:1'] = 'u1' - self.client['user:2'] = 'u2' - self.client['user:3'] = 'u3' - self.make_list('a', '231') - self.assertEquals( - self.client.sort('a', get='user:*'), - [b('u1'), b('u2'), b('u3')]) - - def test_sort_get_multi(self): - self.client['user:1'] = 'u1' - self.client['user:2'] = 'u2' - self.client['user:3'] = 'u3' - self.make_list('a', '231') - self.assertEquals( - self.client.sort('a', get=('user:*', '#')), - [b('u1'), b('1'), b('u2'), b('2'), b('u3'), b('3')]) - - def test_sort_get_groups_two(self): - self.client['user:1'] = 'u1' - self.client['user:2'] = 'u2' - self.client['user:3'] = 'u3' - self.make_list('a', '231') - self.assertEquals( - self.client.sort('a', get=('user:*', '#'), groups=True), - [(b('u1'), b('1')), (b('u2'), b('2')), (b('u3'), b('3'))]) - - def test_sort_groups_string_get(self): - self.client['user:1'] = 'u1' - self.client['user:2'] = 'u2' - self.client['user:3'] = 'u3' - self.make_list('a', '231') - self.assertRaises(redis.DataError, self.client.sort, 'a', - get='user:*', groups=True) - - def test_sort_groups_just_one_get(self): - self.client['user:1'] = 'u1' - self.client['user:2'] = 'u2' - self.client['user:3'] = 'u3' - self.make_list('a', '231') - self.assertRaises(redis.DataError, self.client.sort, 'a', - get=['user:*'], groups=True) - - def test_sort_groups_no_get(self): - self.client['user:1'] = 'u1' - self.client['user:2'] = 'u2' - self.client['user:3'] = 'u3' - self.make_list('a', '231') - self.assertRaises(redis.DataError, self.client.sort, 'a', groups=True) - - def test_sort_groups_three_gets(self): - self.client['user:1'] = 'u1' - self.client['user:2'] = 'u2' - self.client['user:3'] = 'u3' - self.client['door:1'] = 'd1' - self.client['door:2'] = 'd2' - self.client['door:3'] = 'd3' - self.make_list('a', '231') - self.assertEquals( - self.client.sort('a', get=('user:*', 'door:*', '#'), groups=True), - [ - (b('u1'), b('d1'), b('1')), - (b('u2'), b('d2'), b('2')), - (b('u3'), b('d3'), b('3')) - ] - ) - - def test_sort_desc(self): - self.make_list('a', '231') - self.assertEquals( - self.client.sort('a', desc=True), - [b('3'), b('2'), b('1')]) - - def test_sort_alpha(self): - self.make_list('a', 'ecbda') - self.assertEquals( - self.client.sort('a', alpha=True), - [b('a'), b('b'), b('c'), b('d'), b('e')]) - - def test_sort_store(self): - self.make_list('a', '231') - self.assertEquals(self.client.sort('a', store='sorted_values'), 3) - self.assertEquals( - self.client.lrange('sorted_values', 0, 5), - [b('1'), b('2'), b('3')]) - - def test_sort_all_options(self): - self.client['user:1:username'] = 'zeus' - self.client['user:2:username'] = 'titan' - self.client['user:3:username'] = 'hermes' - self.client['user:4:username'] = 'hercules' - self.client['user:5:username'] = 'apollo' - self.client['user:6:username'] = 'athena' - self.client['user:7:username'] = 'hades' - self.client['user:8:username'] = 'dionysus' - - self.client['user:1:favorite_drink'] = 'yuengling' - self.client['user:2:favorite_drink'] = 'rum' - self.client['user:3:favorite_drink'] = 'vodka' - self.client['user:4:favorite_drink'] = 'milk' - self.client['user:5:favorite_drink'] = 'pinot noir' - self.client['user:6:favorite_drink'] = 'water' - self.client['user:7:favorite_drink'] = 'gin' - self.client['user:8:favorite_drink'] = 'apple juice' - - self.make_list('gods', '12345678') - num = self.client.sort( - 'gods', start=2, num=4, by='user:*:username', - get='user:*:favorite_drink', desc=True, alpha=True, store='sorted') - self.assertEquals(num, 4) - self.assertEquals( - self.client.lrange('sorted', 0, 10), - [b('vodka'), b('milk'), b('gin'), b('apple juice')]) - - def test_strict_zadd(self): - client = self.get_client(redis.StrictRedis) - client.zadd('a', 1.0, 'a1', 2.0, 'a2', a3=3.0) - self.assertEquals(client.zrange('a', 0, 3, withscores=True), - [(b('a1'), 1.0), (b('a2'), 2.0), (b('a3'), 3.0)]) - - def test_strict_lrem(self): - client = self.get_client(redis.StrictRedis) - client.rpush('a', 'a1') - client.rpush('a', 'a2') - client.rpush('a', 'a3') - client.rpush('a', 'a1') - client.lrem('a', 0, 'a1') - self.assertEquals(client.lrange('a', 0, -1), [b('a2'), b('a3')]) - - def test_strict_setex(self): - "SETEX swaps the order of the value and timeout" - client = self.get_client(redis.StrictRedis) - self.assertEquals(client.setex('a', 60, '1'), True) - self.assertEquals(client['a'], b('1')) - self.assertEquals(client.ttl('a'), 60) - - def test_strict_expire(self): - "TTL is -1 by default in StrictRedis" - client = self.get_client(redis.StrictRedis) - self.assertEquals(client.expire('a', 10), False) - self.client['a'] = 'foo' - self.assertEquals(client.expire('a', 10), True) - self.assertEquals(client.ttl('a'), 10) - self.assertEquals(client.persist('a'), True) - self.assertEquals(client.ttl('a'), -1) - - def test_strict_pexpire(self): - client = self.get_client(redis.StrictRedis) - version = client.info()['redis_version'] - if StrictVersion(version) < StrictVersion('2.6.0'): - try: - raise unittest.SkipTest() - except AttributeError: - return - - self.assertEquals(client.pexpire('a', 10000), False) - self.client['a'] = 'foo' - self.assertEquals(client.pexpire('a', 10000), True) - self.assert_(client.pttl('a') <= 10000) - self.assertEquals(client.persist('a'), True) - self.assertEquals(client.pttl('a'), -1) - - ## BINARY SAFE - # TODO add more tests - def test_binary_get_set(self): - self.assertTrue(self.client.set(' foo bar ', '123')) - self.assertEqual(self.client.get(' foo bar '), b('123')) - - self.assertTrue(self.client.set(' foo\r\nbar\r\n ', '456')) - self.assertEqual(self.client.get(' foo\r\nbar\r\n '), b('456')) - - self.assertTrue(self.client.set(' \r\n\t\x07\x13 ', '789')) - self.assertEqual(self.client.get(' \r\n\t\x07\x13 '), b('789')) - - self.assertEqual( - sorted(self.client.keys('*')), - [b(' \r\n\t\x07\x13 '), b(' foo\r\nbar\r\n '), b(' foo bar ')]) - - self.assertTrue(self.client.delete(' foo bar ')) - self.assertTrue(self.client.delete(' foo\r\nbar\r\n ')) - self.assertTrue(self.client.delete(' \r\n\t\x07\x13 ')) - - def test_binary_lists(self): - mapping = { - b('foo bar'): [b('1'), b('2'), b('3')], - b('foo\r\nbar\r\n'): [b('4'), b('5'), b('6')], - b('foo\tbar\x07'): [b('7'), b('8'), b('9')], - } - # fill in lists - for key, value in iteritems(mapping): - for c in value: - self.assertTrue(self.client.rpush(key, c)) - - # check that KEYS returns all the keys as they are - self.assertEqual(sorted(self.client.keys('*')), - sorted(list(iterkeys(mapping)))) - - # check that it is possible to get list content by key name - for key in iterkeys(mapping): - self.assertEqual(self.client.lrange(key, 0, -1), - mapping[key]) - - def test_22_info(self): - """ - Older Redis versions contained 'allocation_stats' in INFO that - was the cause of a number of bugs when parsing. - """ - info = "allocation_stats:6=1,7=1,8=7141,9=180,10=92,11=116,12=5330," \ - "13=123,14=3091,15=11048,16=225842,17=1784,18=814,19=12020," \ - "20=2530,21=645,22=15113,23=8695,24=142860,25=318,26=3303," \ - "27=20561,28=54042,29=37390,30=1884,31=18071,32=31367,33=160," \ - "34=169,35=201,36=10155,37=1045,38=15078,39=22985,40=12523," \ - "41=15588,42=265,43=1287,44=142,45=382,46=945,47=426,48=171," \ - "49=56,50=516,51=43,52=41,53=46,54=54,55=75,56=647,57=332," \ - "58=32,59=39,60=48,61=35,62=62,63=32,64=221,65=26,66=30," \ - "67=36,68=41,69=44,70=26,71=144,72=169,73=24,74=37,75=25," \ - "76=42,77=21,78=126,79=374,80=27,81=40,82=43,83=47,84=46," \ - "85=114,86=34,87=37,88=7240,89=34,90=38,91=18,92=99,93=20," \ - "94=18,95=17,96=15,97=22,98=18,99=69,100=17,101=22,102=15," \ - "103=29,104=39,105=30,106=70,107=22,108=21,109=26,110=52," \ - "111=45,112=33,113=67,114=41,115=44,116=48,117=53,118=54," \ - "119=51,120=75,121=44,122=57,123=44,124=66,125=56,126=52," \ - "127=81,128=108,129=70,130=50,131=51,132=53,133=45,134=62," \ - "135=12,136=13,137=7,138=15,139=21,140=11,141=20,142=6,143=7," \ - "144=11,145=6,146=16,147=19,148=1112,149=1,151=83,154=1," \ - "155=1,156=1,157=1,160=1,161=1,162=2,166=1,169=1,170=1,171=2," \ - "172=1,174=1,176=2,177=9,178=34,179=73,180=30,181=1,185=3," \ - "187=1,188=1,189=1,192=1,196=1,198=1,200=1,201=1,204=1,205=1," \ - "207=1,208=1,209=1,214=2,215=31,216=78,217=28,218=5,219=2," \ - "220=1,222=1,225=1,227=1,234=1,242=1,250=1,252=1,253=1," \ - ">=256=203" - parsed = parse_info(info) - self.assert_('allocation_stats' in parsed) - self.assert_('6' in parsed['allocation_stats']) - self.assert_('>=256' in parsed['allocation_stats']) - - def test_large_responses(self): - "The PythonParser has some special cases for return values > 1MB" - # load up 5MB of data into a key - data = [] - for i in range(5000000 // len(ascii_letters)): - data.append(ascii_letters) - data = ''.join(data) - self.client.set('a', data) - self.assertEquals(self.client.get('a'), b(data)) - - def test_floating_point_encoding(self): - """ - High precision floating point values sent to the server should keep - precision. - """ - timestamp = 1349673917.939762 - self.client.zadd('a', 'aaa', timestamp) - self.assertEquals(self.client.zscore('a', 'aaa'), timestamp) diff --git a/tests/test_commands.py b/tests/test_commands.py new file mode 100644 index 0000000..ee9227e --- /dev/null +++ b/tests/test_commands.py @@ -0,0 +1,1227 @@ +import binascii +import datetime +import pytest +import redis +import time + +from redis._compat import (unichr, u, b, ascii_letters, iteritems, iterkeys, + itervalues) +from redis.client import parse_info +from redis import exceptions + +from .conftest import skip_if_server_version_lt +# won't need this after next version of pytest +from distutils.version import StrictVersion + + +# RESPONSE CALLBACKS +class TestResponseCallbacks(object): + "Tests for the response callback system" + + def test_response_callbacks(self, r): + assert r.response_callbacks == redis.Redis.RESPONSE_CALLBACKS + assert id(r.response_callbacks) != id(redis.Redis.RESPONSE_CALLBACKS) + r.set_response_callback('GET', lambda x: 'static') + r['a'] = 'foo' + assert r['a'] == 'static' + + +class TestRedisCommands(object): + + def test_command_on_invalid_key_type(self, r): + r.lpush('a', '1') + with pytest.raises(redis.ResponseError): + r['a'] + + ### SERVER INFORMATION ### + def test_client_list(self, r): + clients = r.client_list() + assert isinstance(clients[0], dict) + assert 'addr' in clients[0] + + @skip_if_server_version_lt('2.6.9') + def test_client_getname(self, r): + assert r.client_getname() is None + + @skip_if_server_version_lt('2.6.9') + def test_client_setname(self, r): + assert r.client_setname('redis_py_test') + assert r.client_getname() == 'redis_py_test' + + def test_config_get(self, r): + data = r.config_get() + assert 'maxmemory' in data + assert data['maxmemory'].isdigit() + + def test_config_set(self, r): + data = r.config_get() + rdbname = data['dbfilename'] + try: + assert r.config_set('dbfilename', 'redis_py_test.rdb') + assert r.config_get()['dbfilename'] == 'redis_py_test.rdb' + finally: + assert r.config_set('dbfilename', rdbname) + + def test_dbsize(self, r): + r['a'] = 'foo' + r['b'] = 'bar' + assert r.dbsize() == 2 + + def test_debug_object(self, r): + r['a'] = 'foo' + debug_info = r.debug_object('a') + assert len(debug_info) > 0 + assert 'refcount' in debug_info + assert debug_info['refcount'] == 1 + + def test_echo(self, r): + assert r.echo('foo bar') == b('foo bar') + + def test_info(self, r): + r['a'] = 'foo' + r['b'] = 'bar' + info = r.info() + assert isinstance(info, dict) + assert info['db9']['keys'] == 2 + + def test_lastsave(self, r): + assert isinstance(r.lastsave(), datetime.datetime) + + def test_object(self, r): + r['a'] = 'foo' + assert isinstance(r.object('refcount', 'a'), int) + assert isinstance(r.object('idletime', 'a'), int) + assert r.object('encoding', 'a') == b('raw') + + def test_ping(self, r): + assert r.ping() + + @skip_if_server_version_lt('2.6.0') + def test_time(self, r): + t = r.time() + assert len(t) == 2 + assert isinstance(t[0], int) + assert isinstance(t[1], int) + + ### BASIC KEY COMMANDS ### + def test_append(self, r): + assert r.append('a', 'a1') == 2 + assert r['a'] == b('a1') + assert r.append('a', 'a2') == 4 + assert r['a'] == b('a1a2') + + @skip_if_server_version_lt('2.6.0') + def test_bitcount(self, r): + r.setbit('a', 5, True) + assert r.bitcount('a') == 1 + r.setbit('a', 6, True) + assert r.bitcount('a') == 2 + r.setbit('a', 5, False) + assert r.bitcount('a') == 1 + r.setbit('a', 9, True) + r.setbit('a', 17, True) + r.setbit('a', 25, True) + r.setbit('a', 33, True) + assert r.bitcount('a') == 5 + assert r.bitcount('a', 0, -1) == 5 + assert r.bitcount('a', 2, 3) == 2 + assert r.bitcount('a', 2, -1) == 3 + assert r.bitcount('a', -2, -1) == 2 + assert r.bitcount('a', 1, 1) == 1 + + @skip_if_server_version_lt('2.6.0') + def test_bitop_not_empty_string(self, r): + r['a'] = '' + r.bitop('not', 'r', 'a') + assert r.get('r') is None + + @skip_if_server_version_lt('2.6.0') + def test_bitop_not(self, r): + test_str = b('\xAA\x00\xFF\x55') + correct = ~0xAA00FF55 & 0xFFFFFFFF + r['a'] = test_str + r.bitop('not', 'r', 'a') + assert int(binascii.hexlify(r['r']), 16) == correct + + @skip_if_server_version_lt('2.6.0') + def test_bitop_not_in_place(self, r): + test_str = b('\xAA\x00\xFF\x55') + correct = ~0xAA00FF55 & 0xFFFFFFFF + r['a'] = test_str + r.bitop('not', 'a', 'a') + assert int(binascii.hexlify(r['a']), 16) == correct + + @skip_if_server_version_lt('2.6.0') + def test_bitop_single_string(self, r): + test_str = b('\x01\x02\xFF') + r['a'] = test_str + r.bitop('and', 'res1', 'a') + r.bitop('or', 'res2', 'a') + r.bitop('xor', 'res3', 'a') + assert r['res1'] == test_str + assert r['res2'] == test_str + assert r['res3'] == test_str + + @skip_if_server_version_lt('2.6.0') + def test_bitop_string_operands(self, r): + r['a'] = b('\x01\x02\xFF\xFF') + r['b'] = b('\x01\x02\xFF') + r.bitop('and', 'res1', 'a', 'b') + r.bitop('or', 'res2', 'a', 'b') + r.bitop('xor', 'res3', 'a', 'b') + assert int(binascii.hexlify(r['res1']), 16) == 0x0102FF00 + assert int(binascii.hexlify(r['res2']), 16) == 0x0102FFFF + assert int(binascii.hexlify(r['res3']), 16) == 0x000000FF + + def test_decr(self, r): + assert r.decr('a') == -1 + assert r['a'] == b('-1') + assert r.decr('a') == -2 + assert r['a'] == b('-2') + assert r.decr('a', amount=5) == -7 + assert r['a'] == b('-7') + + def test_delete(self, r): + assert r.delete('a') == 0 + r['a'] = 'foo' + assert r.delete('a') == 1 + + def test_delete_with_multiple_keys(self, r): + r['a'] = 'foo' + r['b'] = 'bar' + assert r.delete('a', 'b') == 2 + assert r.get('a') is None + assert r.get('b') is None + + def test_delitem(self, r): + r['a'] = 'foo' + del r['a'] + assert r.get('a') is None + + def test_exists(self, r): + assert not r.exists('a') + r['a'] = 'foo' + assert r.exists('a') + + def test_exists_contains(self, r): + assert 'a' not in r + r['a'] = 'foo' + assert 'a' in r + + def test_expire(self, r): + assert not r.expire('a', 10) + r['a'] = 'foo' + assert r.expire('a', 10) + assert 0 < r.ttl('a') <= 10 + assert r.persist('a') + assert not r.ttl('a') + + def test_expireat_datetime(self, r): + expire_at = datetime.datetime.now() + datetime.timedelta(minutes=1) + r['a'] = 'foo' + assert r.expireat('a', expire_at) + assert 0 < r.ttl('a') <= 60 + + def test_expireat_no_key(self, r): + expire_at = datetime.datetime.now() + datetime.timedelta(minutes=1) + assert not r.expireat('a', expire_at) + + def test_expireat_unixtime(self, r): + expire_at = datetime.datetime.now() + datetime.timedelta(minutes=1) + r['a'] = 'foo' + expire_at_seconds = int(time.mktime(expire_at.timetuple())) + assert r.expireat('a', expire_at_seconds) + assert 0 < r.ttl('a') <= 60 + + def test_get_and_set(self, r): + # get and set can't be tested independently of each other + assert r.get('a') is None + byte_string = b('value') + integer = 5 + unicode_string = unichr(3456) + u('abcd') + unichr(3421) + assert r.set('byte_string', byte_string) + assert r.set('integer', 5) + assert r.set('unicode_string', unicode_string) + assert r.get('byte_string') == byte_string + assert r.get('integer') == b(str(integer)) + assert r.get('unicode_string').decode('utf-8') == unicode_string + + def test_getitem_and_setitem(self, r): + r['a'] = 'bar' + assert r['a'] == b('bar') + + def test_getitem_raises_keyerror_for_missing_key(self, r): + with pytest.raises(KeyError): + r['a'] + + def test_get_set_bit(self, r): + # no value + assert not r.getbit('a', 5) + # set bit 5 + assert not r.setbit('a', 5, True) + assert r.getbit('a', 5) + # unset bit 4 + assert not r.setbit('a', 4, False) + assert not r.getbit('a', 4) + # set bit 4 + assert not r.setbit('a', 4, True) + assert r.getbit('a', 4) + # set bit 5 again + assert r.setbit('a', 5, True) + assert r.getbit('a', 5) + + def test_getrange(self, r): + r['a'] = 'foo' + assert r.getrange('a', 0, 0) == b('f') + assert r.getrange('a', 0, 2) == b('foo') + assert r.getrange('a', 3, 4) == b('') + + def test_getset(self, r): + assert r.getset('a', 'foo') is None + assert r.getset('a', 'bar') == b('foo') + + def test_incr(self, r): + assert r.incr('a') == 1 + assert r['a'] == b('1') + assert r.incr('a') == 2 + assert r['a'] == b('2') + assert r.incr('a', amount=5) == 7 + assert r['a'] == b('7') + + def test_incrby(self, r): + assert r.incrby('a') == 1 + assert r.incrby('a', 4) == 5 + assert r['a'] == b('5') + + @skip_if_server_version_lt('2.6.0') + def test_incrbyfloat(self, r): + assert r.incrbyfloat('a') == 1.0 + assert r['a'] == b('1') + assert r.incrbyfloat('a', 1.1) == 2.1 + assert float(r['a']) == float(2.1) + + def test_keys(self, r): + assert r.keys() == [] + keys_with_underscores = set([b('test_a'), b('test_b')]) + keys = keys_with_underscores.union(set([b('testc')])) + for key in keys: + r[key] = 1 + assert set(r.keys(pattern='test_*')) == keys_with_underscores + assert set(r.keys(pattern='test*')) == keys + + def test_mget(self, r): + assert r.mget(['a', 'b']) == [None, None] + r['a'] = '1' + r['b'] = '2' + r['c'] = '3' + assert r.mget('a', 'other', 'b', 'c') == [b('1'), None, b('2'), b('3')] + + def test_mset(self, r): + d = {'a': b('1'), 'b': b('2'), 'c': b('3')} + assert r.mset(d) + for k, v in iteritems(d): + assert r[k] == v + + def test_mset_kwargs(self, r): + d = {'a': b('1'), 'b': b('2'), 'c': b('3')} + assert r.mset(**d) + for k, v in iteritems(d): + assert r[k] == v + + def test_msetnx(self, r): + d = {'a': b('1'), 'b': b('2'), 'c': b('3')} + assert r.msetnx(d) + d2 = {'a': b('x'), 'd': b('4')} + assert not r.msetnx(d2) + for k, v in iteritems(d): + assert r[k] == v + assert r.get('d') is None + + def test_msetnx_kwargs(self, r): + d = {'a': b('1'), 'b': b('2'), 'c': b('3')} + assert r.msetnx(**d) + d2 = {'a': b('x'), 'd': b('4')} + assert not r.msetnx(**d2) + for k, v in iteritems(d): + assert r[k] == v + assert r.get('d') is None + + @skip_if_server_version_lt('2.6.0') + def test_pexpire(self, r): + assert not r.pexpire('a', 60000) + r['a'] = 'foo' + assert r.pexpire('a', 60000) + assert 0 < r.pttl('a') <= 60000 + assert r.persist('a') + assert r.pttl('a') is None + + @skip_if_server_version_lt('2.6.0') + def test_pexpireat_datetime(self, r): + expire_at = datetime.datetime.now() + datetime.timedelta(minutes=1) + r['a'] = 'foo' + assert r.pexpireat('a', expire_at) + assert 0 < r.pttl('a') <= 60000 + + @skip_if_server_version_lt('2.6.0') + def test_pexpireat_no_key(self, r): + expire_at = datetime.datetime.now() + datetime.timedelta(minutes=1) + assert not r.pexpireat('a', expire_at) + + @skip_if_server_version_lt('2.6.0') + def test_pexpireat_unixtime(self, r): + expire_at = datetime.datetime.now() + datetime.timedelta(minutes=1) + r['a'] = 'foo' + expire_at_seconds = int(time.mktime(expire_at.timetuple())) * 1000 + assert r.pexpireat('a', expire_at_seconds) + assert 0 < r.pttl('a') <= 60000 + + @skip_if_server_version_lt('2.6.0') + def test_psetex(self, r): + assert r.psetex('a', 1000, 'value') + assert r['a'] == b('value') + assert 0 < r.pttl('a') <= 1000 + + @skip_if_server_version_lt('2.6.0') + def test_psetex_timedelta(self, r): + expire_at = datetime.timedelta(milliseconds=1000) + assert r.psetex('a', expire_at, 'value') + assert r['a'] == b('value') + assert 0 < r.pttl('a') <= 1000 + + def test_randomkey(self, r): + assert r.randomkey() is None + for key in ('a', 'b', 'c'): + r[key] = 1 + assert r.randomkey() in (b('a'), b('b'), b('c')) + + def test_rename(self, r): + r['a'] = '1' + assert r.rename('a', 'b') + assert r.get('a') is None + assert r['b'] == b('1') + + def test_renamenx(self, r): + r['a'] = '1' + r['b'] = '2' + assert not r.renamenx('a', 'b') + assert r['a'] == b('1') + assert r['b'] == b('2') + + @skip_if_server_version_lt('2.6.0') + def test_set_nx(self, r): + assert r.set('a', '1', nx=True) + assert not r.set('a', '2', nx=True) + assert r['a'] == b('1') + + @skip_if_server_version_lt('2.6.0') + def test_set_xx(self, r): + assert not r.set('a', '1', xx=True) + assert r.get('a') is None + r['a'] = 'bar' + assert r.set('a', '2', xx=True) + assert r.get('a') == b('2') + + @skip_if_server_version_lt('2.6.0') + def test_set_px(self, r): + assert r.set('a', '1', px=10000) + assert r['a'] == b('1') + assert 0 < r.pttl('a') <= 10000 + assert 0 < r.ttl('a') <= 10 + + @skip_if_server_version_lt('2.6.0') + def test_set_px_timedelta(self, r): + expire_at = datetime.timedelta(milliseconds=1000) + assert r.set('a', '1', px=expire_at) + assert 0 < r.pttl('a') <= 1000 + assert 0 < r.ttl('a') <= 1 + + @skip_if_server_version_lt('2.6.0') + def test_set_ex(self, r): + assert r.set('a', '1', ex=10) + assert 0 < r.ttl('a') <= 10 + + @skip_if_server_version_lt('2.6.0') + def test_set_ex_timedelta(self, r): + expire_at = datetime.timedelta(seconds=60) + assert r.set('a', '1', ex=expire_at) + assert 0 < r.ttl('a') <= 60 + + @skip_if_server_version_lt('2.6.0') + def test_set_multipleoptions(self, r): + r['a'] = 'val' + assert r.set('a', '1', xx=True, px=10000) + assert 0 < r.ttl('a') <= 10 + + def test_setex(self, r): + assert r.setex('a', '1', 60) + assert r['a'] == b('1') + assert 0 < r.ttl('a') <= 60 + + def test_setnx(self, r): + assert r.setnx('a', '1') + assert r['a'] == b('1') + assert not r.setnx('a', '2') + assert r['a'] == b('1') + + def test_setrange(self, r): + assert r.setrange('a', 5, 'foo') == 8 + assert r['a'] == b('\0\0\0\0\0foo') + r['a'] = 'abcdefghijh' + assert r.setrange('a', 6, '12345') == 11 + assert r['a'] == b('abcdef12345') + + def test_strlen(self, r): + r['a'] = 'foo' + assert r.strlen('a') == 3 + + def test_substr(self, r): + r['a'] = '0123456789' + assert r.substr('a', 0) == b('0123456789') + assert r.substr('a', 2) == b('23456789') + assert r.substr('a', 3, 5) == b('345') + assert r.substr('a', 3, -2) == b('345678') + + def test_type(self, r): + assert r.type('a') == b('none') + r['a'] = '1' + assert r.type('a') == b('string') + del r['a'] + r.lpush('a', '1') + assert r.type('a') == b('list') + del r['a'] + r.sadd('a', '1') + assert r.type('a') == b('set') + del r['a'] + r.zadd('a', **{'1': 1}) + assert r.type('a') == b('zset') + + #### LIST COMMANDS #### + def test_blpop(self, r): + r.rpush('a', '1', '2') + r.rpush('b', '3', '4') + assert r.blpop(['b', 'a'], timeout=1) == (b('b'), b('3')) + assert r.blpop(['b', 'a'], timeout=1) == (b('b'), b('4')) + assert r.blpop(['b', 'a'], timeout=1) == (b('a'), b('1')) + assert r.blpop(['b', 'a'], timeout=1) == (b('a'), b('2')) + assert r.blpop(['b', 'a'], timeout=1) is None + r.rpush('c', '1') + assert r.blpop('c', timeout=1) == (b('c'), b('1')) + + def test_brpop(self, r): + r.rpush('a', '1', '2') + r.rpush('b', '3', '4') + assert r.brpop(['b', 'a'], timeout=1) == (b('b'), b('4')) + assert r.brpop(['b', 'a'], timeout=1) == (b('b'), b('3')) + assert r.brpop(['b', 'a'], timeout=1) == (b('a'), b('2')) + assert r.brpop(['b', 'a'], timeout=1) == (b('a'), b('1')) + assert r.brpop(['b', 'a'], timeout=1) is None + r.rpush('c', '1') + assert r.brpop('c', timeout=1) == (b('c'), b('1')) + + def test_brpoplpush(self, r): + r.rpush('a', '1', '2') + r.rpush('b', '3', '4') + assert r.brpoplpush('a', 'b') == b('2') + assert r.brpoplpush('a', 'b') == b('1') + assert r.brpoplpush('a', 'b', timeout=1) is None + assert r.lrange('a', 0, -1) == [] + assert r.lrange('b', 0, -1) == [b('1'), b('2'), b('3'), b('4')] + + def test_brpoplpush_empty_string(self, r): + r.rpush('a', '') + assert r.brpoplpush('a', 'b') == b('') + + def test_lindex(self, r): + r.rpush('a', '1', '2', '3') + assert r.lindex('a', '0') == b('1') + assert r.lindex('a', '1') == b('2') + assert r.lindex('a', '2') == b('3') + + def test_linsert(self, r): + r.rpush('a', '1', '2', '3') + assert r.linsert('a', 'after', '2', '2.5') == 4 + assert r.lrange('a', 0, -1) == [b('1'), b('2'), b('2.5'), b('3')] + assert r.linsert('a', 'before', '2', '1.5') == 5 + assert r.lrange('a', 0, -1) == \ + [b('1'), b('1.5'), b('2'), b('2.5'), b('3')] + + def test_llen(self, r): + r.rpush('a', '1', '2', '3') + assert r.llen('a') == 3 + + def test_lpop(self, r): + r.rpush('a', '1', '2', '3') + assert r.lpop('a') == b('1') + assert r.lpop('a') == b('2') + assert r.lpop('a') == b('3') + assert r.lpop('a') is None + + def test_lpush(self, r): + assert r.lpush('a', '1') == 1 + assert r.lpush('a', '2') == 2 + assert r.lpush('a', '3', '4') == 4 + assert r.lrange('a', 0, -1) == [b('4'), b('3'), b('2'), b('1')] + + def test_lpushx(self, r): + assert r.lpushx('a', '1') == 0 + assert r.lrange('a', 0, -1) == [] + r.rpush('a', '1', '2', '3') + assert r.lpushx('a', '4') == 4 + assert r.lrange('a', 0, -1) == [b('4'), b('1'), b('2'), b('3')] + + def test_lrange(self, r): + r.rpush('a', '1', '2', '3', '4', '5') + assert r.lrange('a', 0, 2) == [b('1'), b('2'), b('3')] + assert r.lrange('a', 2, 10) == [b('3'), b('4'), b('5')] + assert r.lrange('a', 0, -1) == [b('1'), b('2'), b('3'), b('4'), b('5')] + + def test_lrem(self, r): + r.rpush('a', '1', '1', '1', '1') + assert r.lrem('a', '1', 1) == 1 + assert r.lrange('a', 0, -1) == [b('1'), b('1'), b('1')] + assert r.lrem('a', '1') == 3 + assert r.lrange('a', 0, -1) == [] + + def test_lset(self, r): + r.rpush('a', '1', '2', '3') + assert r.lrange('a', 0, -1) == [b('1'), b('2'), b('3')] + assert r.lset('a', 1, '4') + assert r.lrange('a', 0, 2) == [b('1'), b('4'), b('3')] + + def test_ltrim(self, r): + r.rpush('a', '1', '2', '3') + assert r.ltrim('a', 0, 1) + assert r.lrange('a', 0, -1) == [b('1'), b('2')] + + def test_rpop(self, r): + r.rpush('a', '1', '2', '3') + assert r.rpop('a') == b('3') + assert r.rpop('a') == b('2') + assert r.rpop('a') == b('1') + assert r.rpop('a') is None + + def test_rpoplpush(self, r): + r.rpush('a', 'a1', 'a2', 'a3') + r.rpush('b', 'b1', 'b2', 'b3') + assert r.rpoplpush('a', 'b') == b('a3') + assert r.lrange('a', 0, -1) == [b('a1'), b('a2')] + assert r.lrange('b', 0, -1) == [b('a3'), b('b1'), b('b2'), b('b3')] + + def test_rpush(self, r): + assert r.rpush('a', '1') == 1 + assert r.rpush('a', '2') == 2 + assert r.rpush('a', '3', '4') == 4 + assert r.lrange('a', 0, -1) == [b('1'), b('2'), b('3'), b('4')] + + def test_rpushx(self, r): + assert r.rpushx('a', 'b') == 0 + assert r.lrange('a', 0, -1) == [] + r.rpush('a', '1', '2', '3') + assert r.rpushx('a', '4') == 4 + assert r.lrange('a', 0, -1) == [b('1'), b('2'), b('3'), b('4')] + + ### SET COMMANDS ### + def test_sadd(self, r): + members = set([b('1'), b('2'), b('3')]) + r.sadd('a', *members) + assert r.smembers('a') == members + + def test_scard(self, r): + r.sadd('a', '1', '2', '3') + assert r.scard('a') == 3 + + def test_sdiff(self, r): + r.sadd('a', '1', '2', '3') + assert r.sdiff('a', 'b') == set([b('1'), b('2'), b('3')]) + r.sadd('b', '2', '3') + assert r.sdiff('a', 'b') == set([b('1')]) + + def test_sdiffstore(self, r): + r.sadd('a', '1', '2', '3') + assert r.sdiffstore('c', 'a', 'b') == 3 + assert r.smembers('c') == set([b('1'), b('2'), b('3')]) + r.sadd('b', '2', '3') + assert r.sdiffstore('c', 'a', 'b') == 1 + assert r.smembers('c') == set([b('1')]) + + def test_sinter(self, r): + r.sadd('a', '1', '2', '3') + assert r.sinter('a', 'b') == set() + r.sadd('b', '2', '3') + assert r.sinter('a', 'b') == set([b('2'), b('3')]) + + def test_sinterstore(self, r): + r.sadd('a', '1', '2', '3') + assert r.sinterstore('c', 'a', 'b') == 0 + assert r.smembers('c') == set() + r.sadd('b', '2', '3') + assert r.sinterstore('c', 'a', 'b') == 2 + assert r.smembers('c') == set([b('2'), b('3')]) + + def test_sismember(self, r): + r.sadd('a', '1', '2', '3') + assert r.sismember('a', '1') + assert r.sismember('a', '2') + assert r.sismember('a', '3') + assert not r.sismember('a', '4') + + def test_smembers(self, r): + r.sadd('a', '1', '2', '3') + assert r.smembers('a') == set([b('1'), b('2'), b('3')]) + + def test_smove(self, r): + r.sadd('a', 'a1', 'a2') + r.sadd('b', 'b1', 'b2') + assert r.smove('a', 'b', 'a1') + assert r.smembers('a') == set([b('a2')]) + assert r.smembers('b') == set([b('b1'), b('b2'), b('a1')]) + + def test_spop(self, r): + s = [b('1'), b('2'), b('3')] + r.sadd('a', *s) + value = r.spop('a') + assert value in s + assert r.smembers('a') == set(s) - set([value]) + + def test_srandmember(self, r): + s = [b('1'), b('2'), b('3')] + r.sadd('a', *s) + assert r.srandmember('a') in s + + @skip_if_server_version_lt('2.6.0') + def test_srandmember_multi_value(self, r): + s = [b('1'), b('2'), b('3')] + r.sadd('a', *s) + randoms = r.srandmember('a', number=2) + assert len(randoms) == 2 + assert set(randoms).intersection(s) == set(randoms) + + def test_srem(self, r): + r.sadd('a', '1', '2', '3', '4') + assert r.srem('a', '5') == 0 + assert r.srem('a', '2', '4') == 2 + assert r.smembers('a') == set([b('1'), b('3')]) + + def test_sunion(self, r): + r.sadd('a', '1', '2') + r.sadd('b', '2', '3') + assert r.sunion('a', 'b') == set([b('1'), b('2'), b('3')]) + + def test_sunionstore(self, r): + r.sadd('a', '1', '2') + r.sadd('b', '2', '3') + assert r.sunionstore('c', 'a', 'b') == 3 + assert r.smembers('c') == set([b('1'), b('2'), b('3')]) + + ### SORTED SET COMMANDS ### + def test_zadd(self, r): + r.zadd('a', a1=1, a2=2, a3=3) + assert r.zrange('a', 0, -1) == [b('a1'), b('a2'), b('a3')] + + def test_zcard(self, r): + r.zadd('a', a1=1, a2=2, a3=3) + assert r.zcard('a') == 3 + + def test_zcount(self, r): + r.zadd('a', a1=1, a2=2, a3=3) + assert r.zcount('a', '-inf', '+inf') == 3 + assert r.zcount('a', 1, 2) == 2 + assert r.zcount('a', 10, 20) == 0 + + def test_zincrby(self, r): + r.zadd('a', a1=1, a2=2, a3=3) + assert r.zincrby('a', 'a2') == 3.0 + assert r.zincrby('a', 'a3', amount=5) == 8.0 + assert r.zscore('a', 'a2') == 3.0 + assert r.zscore('a', 'a3') == 8.0 + + def test_zinterstore_sum(self, r): + r.zadd('a', a1=1, a2=1, a3=1) + r.zadd('b', a1=2, a2=2, a3=2) + r.zadd('c', a1=6, a3=5, a4=4) + assert r.zinterstore('d', ['a', 'b', 'c']) == 2 + assert r.zrange('d', 0, -1, withscores=True) == \ + [(b('a3'), 8), (b('a1'), 9)] + + def test_zinterstore_max(self, r): + r.zadd('a', a1=1, a2=1, a3=1) + r.zadd('b', a1=2, a2=2, a3=2) + r.zadd('c', a1=6, a3=5, a4=4) + assert r.zinterstore('d', ['a', 'b', 'c'], aggregate='MAX') == 2 + assert r.zrange('d', 0, -1, withscores=True) == \ + [(b('a3'), 5), (b('a1'), 6)] + + def test_zinterstore_min(self, r): + r.zadd('a', a1=1, a2=2, a3=3) + r.zadd('b', a1=2, a2=3, a3=5) + r.zadd('c', a1=6, a3=5, a4=4) + assert r.zinterstore('d', ['a', 'b', 'c'], aggregate='MIN') == 2 + assert r.zrange('d', 0, -1, withscores=True) == \ + [(b('a1'), 1), (b('a3'), 3)] + + def test_zinterstore_with_weight(self, r): + r.zadd('a', a1=1, a2=1, a3=1) + r.zadd('b', a1=2, a2=2, a3=2) + r.zadd('c', a1=6, a3=5, a4=4) + assert r.zinterstore('d', {'a': 1, 'b': 2, 'c': 3}) == 2 + assert r.zrange('d', 0, -1, withscores=True) == \ + [(b('a3'), 20), (b('a1'), 23)] + + def test_zrange(self, r): + r.zadd('a', a1=1, a2=2, a3=3) + assert r.zrange('a', 0, 1) == [b('a1'), b('a2')] + assert r.zrange('a', 1, 2) == [b('a2'), b('a3')] + + # withscores + assert r.zrange('a', 0, 1, withscores=True) == \ + [(b('a1'), 1.0), (b('a2'), 2.0)] + assert r.zrange('a', 1, 2, withscores=True) == \ + [(b('a2'), 2.0), (b('a3'), 3.0)] + + # custom score function + assert r.zrange('a', 0, 1, withscores=True, score_cast_func=int) == \ + [(b('a1'), 1), (b('a2'), 2)] + + def test_zrangebyscore(self, r): + r.zadd('a', a1=1, a2=2, a3=3, a4=4, a5=5) + assert r.zrangebyscore('a', 2, 4) == [b('a2'), b('a3'), b('a4')] + + # slicing with start/num + assert r.zrangebyscore('a', 2, 4, start=1, num=2) == \ + [b('a3'), b('a4')] + + # withscores + assert r.zrangebyscore('a', 2, 4, withscores=True) == \ + [(b('a2'), 2.0), (b('a3'), 3.0), (b('a4'), 4.0)] + + # custom score function + assert r.zrangebyscore('a', 2, 4, withscores=True, + score_cast_func=int) == \ + [(b('a2'), 2), (b('a3'), 3), (b('a4'), 4)] + + def test_zrank(self, r): + r.zadd('a', a1=1, a2=2, a3=3, a4=4, a5=5) + assert r.zrank('a', 'a1') == 0 + assert r.zrank('a', 'a2') == 1 + assert r.zrank('a', 'a6') is None + + def test_zrem(self, r): + r.zadd('a', a1=1, a2=2, a3=3) + assert r.zrem('a', 'a2') == 1 + assert r.zrange('a', 0, -1) == [b('a1'), b('a3')] + assert r.zrem('a', 'b') == 0 + assert r.zrange('a', 0, -1) == [b('a1'), b('a3')] + + def test_zrem_multiple_keys(self, r): + r.zadd('a', a1=1, a2=2, a3=3) + assert r.zrem('a', 'a1', 'a2') == 2 + assert r.zrange('a', 0, 5) == [b('a3')] + + def test_zremrangebyrank(self, r): + r.zadd('a', a1=1, a2=2, a3=3, a4=4, a5=5) + assert r.zremrangebyrank('a', 1, 3) == 3 + assert r.zrange('a', 0, 5) == [b('a1'), b('a5')] + + def test_zremrangebyscore(self, r): + r.zadd('a', a1=1, a2=2, a3=3, a4=4, a5=5) + assert r.zremrangebyscore('a', 2, 4) == 3 + assert r.zrange('a', 0, -1) == [b('a1'), b('a5')] + assert r.zremrangebyscore('a', 2, 4) == 0 + assert r.zrange('a', 0, -1) == [b('a1'), b('a5')] + + def test_zrevrange(self, r): + r.zadd('a', a1=1, a2=2, a3=3) + assert r.zrevrange('a', 0, 1) == [b('a3'), b('a2')] + assert r.zrevrange('a', 1, 2) == [b('a2'), b('a1')] + + # withscores + assert r.zrevrange('a', 0, 1, withscores=True) == \ + [(b('a3'), 3.0), (b('a2'), 2.0)] + assert r.zrevrange('a', 1, 2, withscores=True) == \ + [(b('a2'), 2.0), (b('a1'), 1.0)] + + # custom score function + assert r.zrevrange('a', 0, 1, withscores=True, + score_cast_func=int) == \ + [(b('a3'), 3.0), (b('a2'), 2.0)] + + def test_zrevrangebyscore(self, r): + r.zadd('a', a1=1, a2=2, a3=3, a4=4, a5=5) + assert r.zrevrangebyscore('a', 4, 2) == [b('a4'), b('a3'), b('a2')] + + # slicing with start/num + assert r.zrevrangebyscore('a', 4, 2, start=1, num=2) == \ + [b('a3'), b('a2')] + + # withscores + assert r.zrevrangebyscore('a', 4, 2, withscores=True) == \ + [(b('a4'), 4.0), (b('a3'), 3.0), (b('a2'), 2.0)] + + # custom score function + assert r.zrevrangebyscore('a', 4, 2, withscores=True, + score_cast_func=int) == \ + [(b('a4'), 4), (b('a3'), 3), (b('a2'), 2)] + + def test_zrevrank(self, r): + r.zadd('a', a1=1, a2=2, a3=3, a4=4, a5=5) + assert r.zrevrank('a', 'a1') == 4 + assert r.zrevrank('a', 'a2') == 3 + assert r.zrevrank('a', 'a6') is None + + def test_zscore(self, r): + r.zadd('a', a1=1, a2=2, a3=3) + assert r.zscore('a', 'a1') == 1.0 + assert r.zscore('a', 'a2') == 2.0 + assert r.zscore('a', 'a4') is None + + def test_zunionstore_sum(self, r): + r.zadd('a', a1=1, a2=1, a3=1) + r.zadd('b', a1=2, a2=2, a3=2) + r.zadd('c', a1=6, a3=5, a4=4) + assert r.zunionstore('d', ['a', 'b', 'c']) == 4 + assert r.zrange('d', 0, -1, withscores=True) == \ + [(b('a2'), 3), (b('a4'), 4), (b('a3'), 8), (b('a1'), 9)] + + def test_zunionstore_max(self, r): + r.zadd('a', a1=1, a2=1, a3=1) + r.zadd('b', a1=2, a2=2, a3=2) + r.zadd('c', a1=6, a3=5, a4=4) + assert r.zunionstore('d', ['a', 'b', 'c'], aggregate='MAX') == 4 + assert r.zrange('d', 0, -1, withscores=True) == \ + [(b('a2'), 2), (b('a4'), 4), (b('a3'), 5), (b('a1'), 6)] + + def test_zunionstore_min(self, r): + r.zadd('a', a1=1, a2=2, a3=3) + r.zadd('b', a1=2, a2=2, a3=4) + r.zadd('c', a1=6, a3=5, a4=4) + assert r.zunionstore('d', ['a', 'b', 'c'], aggregate='MIN') == 4 + assert r.zrange('d', 0, -1, withscores=True) == \ + [(b('a1'), 1), (b('a2'), 2), (b('a3'), 3), (b('a4'), 4)] + + def test_zunionstore_with_weight(self, r): + r.zadd('a', a1=1, a2=1, a3=1) + r.zadd('b', a1=2, a2=2, a3=2) + r.zadd('c', a1=6, a3=5, a4=4) + assert r.zunionstore('d', {'a': 1, 'b': 2, 'c': 3}) == 4 + assert r.zrange('d', 0, -1, withscores=True) == \ + [(b('a2'), 5), (b('a4'), 12), (b('a3'), 20), (b('a1'), 23)] + + ### HASH COMMANDS ### + def test_hget_and_hset(self, r): + r.hmset('a', {'1': 1, '2': 2, '3': 3}) + assert r.hget('a', '1') == b('1') + assert r.hget('a', '2') == b('2') + assert r.hget('a', '3') == b('3') + + # field was updated, redis returns 0 + assert r.hset('a', '2', 5) == 0 + assert r.hget('a', '2') == b('5') + + # field is new, redis returns 1 + assert r.hset('a', '4', 4) == 1 + assert r.hget('a', '4') == b('4') + + # key inside of hash that doesn't exist returns null value + assert r.hget('a', 'b') is None + + def test_hdel(self, r): + r.hmset('a', {'1': 1, '2': 2, '3': 3}) + assert r.hdel('a', '2') == 1 + assert r.hget('a', '2') is None + assert r.hdel('a', '1', '3') == 2 + assert r.hlen('a') == 0 + + def test_hexists(self, r): + r.hmset('a', {'1': 1, '2': 2, '3': 3}) + assert r.hexists('a', '1') + assert not r.hexists('a', '4') + + def test_hgetall(self, r): + h = {b('a1'): b('1'), b('a2'): b('2'), b('a3'): b('3')} + r.hmset('a', h) + assert r.hgetall('a') == h + + def test_hincrby(self, r): + assert r.hincrby('a', '1') == 1 + assert r.hincrby('a', '1', amount=2) == 3 + assert r.hincrby('a', '1', amount=-2) == 1 + + @skip_if_server_version_lt('2.6.0') + def test_hincrbyfloat(self, r): + assert r.hincrbyfloat('a', '1') == 1.0 + assert r.hincrbyfloat('a', '1') == 2.0 + assert r.hincrbyfloat('a', '1', 1.2) == 3.2 + + def test_hkeys(self, r): + h = {b('a1'): b('1'), b('a2'): b('2'), b('a3'): b('3')} + r.hmset('a', h) + local_keys = list(iterkeys(h)) + remote_keys = r.hkeys('a') + assert (sorted(local_keys) == sorted(remote_keys)) + + def test_hlen(self, r): + r.hmset('a', {'1': 1, '2': 2, '3': 3}) + assert r.hlen('a') == 3 + + def test_hmget(self, r): + assert r.hmset('a', {'a': 1, 'b': 2, 'c': 3}) + assert r.hmget('a', 'a', 'b', 'c') == [b('1'), b('2'), b('3')] + + def test_hmset(self, r): + h = {b('a'): b('1'), b('b'): b('2'), b('c'): b('3')} + assert r.hmset('a', h) + assert r.hgetall('a') == h + + def test_hsetnx(self, r): + # Initially set the hash field + assert r.hsetnx('a', '1', 1) + assert r.hget('a', '1') == b('1') + assert not r.hsetnx('a', '1', 2) + assert r.hget('a', '1') == b('1') + + def test_hvals(self, r): + h = {b('a1'): b('1'), b('a2'): b('2'), b('a3'): b('3')} + r.hmset('a', h) + local_vals = list(itervalues(h)) + remote_vals = r.hvals('a') + assert sorted(local_vals) == sorted(remote_vals) + + ### SORT ### + def test_sort_basic(self, r): + r.rpush('a', '3', '2', '1', '4') + assert r.sort('a') == [b('1'), b('2'), b('3'), b('4')] + + def test_sort_limited(self, r): + r.rpush('a', '3', '2', '1', '4') + assert r.sort('a', start=1, num=2) == [b('2'), b('3')] + + def test_sort_by(self, r): + r['score:1'] = 8 + r['score:2'] = 3 + r['score:3'] = 5 + r.rpush('a', '3', '2', '1') + assert r.sort('a', by='score:*') == [b('2'), b('3'), b('1')] + + def test_sort_get(self, r): + r['user:1'] = 'u1' + r['user:2'] = 'u2' + r['user:3'] = 'u3' + r.rpush('a', '2', '3', '1') + assert r.sort('a', get='user:*') == [b('u1'), b('u2'), b('u3')] + + def test_sort_get_multi(self, r): + r['user:1'] = 'u1' + r['user:2'] = 'u2' + r['user:3'] = 'u3' + r.rpush('a', '2', '3', '1') + assert r.sort('a', get=('user:*', '#')) == \ + [b('u1'), b('1'), b('u2'), b('2'), b('u3'), b('3')] + + def test_sort_get_groups_two(self, r): + r['user:1'] = 'u1' + r['user:2'] = 'u2' + r['user:3'] = 'u3' + r.rpush('a', '2', '3', '1') + assert r.sort('a', get=('user:*', '#'), groups=True) == \ + [(b('u1'), b('1')), (b('u2'), b('2')), (b('u3'), b('3'))] + + def test_sort_groups_string_get(self, r): + r['user:1'] = 'u1' + r['user:2'] = 'u2' + r['user:3'] = 'u3' + r.rpush('a', '2', '3', '1') + with pytest.raises(exceptions.DataError): + r.sort('a', get='user:*', groups=True) + + def test_sort_groups_just_one_get(self, r): + r['user:1'] = 'u1' + r['user:2'] = 'u2' + r['user:3'] = 'u3' + r.rpush('a', '2', '3', '1') + with pytest.raises(exceptions.DataError): + r.sort('a', get=['user:*'], groups=True) + + def test_sort_groups_no_get(self, r): + r['user:1'] = 'u1' + r['user:2'] = 'u2' + r['user:3'] = 'u3' + r.rpush('a', '2', '3', '1') + with pytest.raises(exceptions.DataError): + r.sort('a', groups=True) + + def test_sort_groups_three_gets(self, r): + r['user:1'] = 'u1' + r['user:2'] = 'u2' + r['user:3'] = 'u3' + r['door:1'] = 'd1' + r['door:2'] = 'd2' + r['door:3'] = 'd3' + r.rpush('a', '2', '3', '1') + assert r.sort('a', get=('user:*', 'door:*', '#'), groups=True) == \ + [ + (b('u1'), b('d1'), b('1')), + (b('u2'), b('d2'), b('2')), + (b('u3'), b('d3'), b('3')) + ] + + def test_sort_desc(self, r): + r.rpush('a', '2', '3', '1') + assert r.sort('a', desc=True) == [b('3'), b('2'), b('1')] + + def test_sort_alpha(self, r): + r.rpush('a', 'e', 'c', 'b', 'd', 'a') + assert r.sort('a', alpha=True) == \ + [b('a'), b('b'), b('c'), b('d'), b('e')] + + def test_sort_store(self, r): + r.rpush('a', '2', '3', '1') + assert r.sort('a', store='sorted_values') == 3 + assert r.lrange('sorted_values', 0, -1) == [b('1'), b('2'), b('3')] + + def test_sort_all_options(self, r): + r['user:1:username'] = 'zeus' + r['user:2:username'] = 'titan' + r['user:3:username'] = 'hermes' + r['user:4:username'] = 'hercules' + r['user:5:username'] = 'apollo' + r['user:6:username'] = 'athena' + r['user:7:username'] = 'hades' + r['user:8:username'] = 'dionysus' + + r['user:1:favorite_drink'] = 'yuengling' + r['user:2:favorite_drink'] = 'rum' + r['user:3:favorite_drink'] = 'vodka' + r['user:4:favorite_drink'] = 'milk' + r['user:5:favorite_drink'] = 'pinot noir' + r['user:6:favorite_drink'] = 'water' + r['user:7:favorite_drink'] = 'gin' + r['user:8:favorite_drink'] = 'apple juice' + + r.rpush('gods', '5', '8', '3', '1', '2', '7', '6', '4') + num = r.sort('gods', start=2, num=4, by='user:*:username', + get='user:*:favorite_drink', desc=True, alpha=True, + store='sorted') + assert num == 4 + assert r.lrange('sorted', 0, 10) == \ + [b('vodka'), b('milk'), b('gin'), b('apple juice')] + + +class TestStrictCommands(object): + + def test_strict_zadd(self, sr): + sr.zadd('a', 1.0, 'a1', 2.0, 'a2', a3=3.0) + assert sr.zrange('a', 0, -1, withscores=True) == \ + [(b('a1'), 1.0), (b('a2'), 2.0), (b('a3'), 3.0)] + + def test_strict_lrem(self, sr): + sr.rpush('a', 'a1', 'a2', 'a3', 'a1') + sr.lrem('a', 0, 'a1') + assert sr.lrange('a', 0, -1) == [b('a2'), b('a3')] + + def test_strict_setex(self, sr): + assert sr.setex('a', 60, '1') + assert sr['a'] == b('1') + assert 0 < sr.ttl('a') <= 60 + + def test_strict_ttl(self, sr): + assert not sr.expire('a', 10) + sr['a'] = '1' + assert sr.expire('a', 10) + assert 0 < sr.ttl('a') <= 10 + assert sr.persist('a') + assert sr.ttl('a') == -1 + + @skip_if_server_version_lt('2.6.0') + def test_strict_pttl(self, sr): + assert not sr.pexpire('a', 10000) + sr['a'] = '1' + assert sr.pexpire('a', 10000) + assert 0 < sr.pttl('a') <= 10000 + assert sr.persist('a') + assert sr.pttl('a') == -1 + + +class TestBinarySave(object): + def test_binary_get_set(self, r): + assert r.set(' foo bar ', '123') + assert r.get(' foo bar ') == b('123') + + assert r.set(' foo\r\nbar\r\n ', '456') + assert r.get(' foo\r\nbar\r\n ') == b('456') + + assert r.set(' \r\n\t\x07\x13 ', '789') + assert r.get(' \r\n\t\x07\x13 ') == b('789') + + assert sorted(r.keys('*')) == \ + [b(' \r\n\t\x07\x13 '), b(' foo\r\nbar\r\n '), b(' foo bar ')] + + assert r.delete(' foo bar ') + assert r.delete(' foo\r\nbar\r\n ') + assert r.delete(' \r\n\t\x07\x13 ') + + def test_binary_lists(self, r): + mapping = { + b('foo bar'): [b('1'), b('2'), b('3')], + b('foo\r\nbar\r\n'): [b('4'), b('5'), b('6')], + b('foo\tbar\x07'): [b('7'), b('8'), b('9')], + } + # fill in lists + for key, value in iteritems(mapping): + r.rpush(key, *value) + + # check that KEYS returns all the keys as they are + assert sorted(r.keys('*')) == sorted(list(iterkeys(mapping))) + + # check that it is possible to get list content by key name + for key, value in iteritems(mapping): + assert r.lrange(key, 0, -1) == value + + def test_22_info(self, r): + """ + Older Redis versions contained 'allocation_stats' in INFO that + was the cause of a number of bugs when parsing. + """ + info = "allocation_stats:6=1,7=1,8=7141,9=180,10=92,11=116,12=5330," \ + "13=123,14=3091,15=11048,16=225842,17=1784,18=814,19=12020," \ + "20=2530,21=645,22=15113,23=8695,24=142860,25=318,26=3303," \ + "27=20561,28=54042,29=37390,30=1884,31=18071,32=31367,33=160," \ + "34=169,35=201,36=10155,37=1045,38=15078,39=22985,40=12523," \ + "41=15588,42=265,43=1287,44=142,45=382,46=945,47=426,48=171," \ + "49=56,50=516,51=43,52=41,53=46,54=54,55=75,56=647,57=332," \ + "58=32,59=39,60=48,61=35,62=62,63=32,64=221,65=26,66=30," \ + "67=36,68=41,69=44,70=26,71=144,72=169,73=24,74=37,75=25," \ + "76=42,77=21,78=126,79=374,80=27,81=40,82=43,83=47,84=46," \ + "85=114,86=34,87=37,88=7240,89=34,90=38,91=18,92=99,93=20," \ + "94=18,95=17,96=15,97=22,98=18,99=69,100=17,101=22,102=15," \ + "103=29,104=39,105=30,106=70,107=22,108=21,109=26,110=52," \ + "111=45,112=33,113=67,114=41,115=44,116=48,117=53,118=54," \ + "119=51,120=75,121=44,122=57,123=44,124=66,125=56,126=52," \ + "127=81,128=108,129=70,130=50,131=51,132=53,133=45,134=62," \ + "135=12,136=13,137=7,138=15,139=21,140=11,141=20,142=6,143=7," \ + "144=11,145=6,146=16,147=19,148=1112,149=1,151=83,154=1," \ + "155=1,156=1,157=1,160=1,161=1,162=2,166=1,169=1,170=1,171=2," \ + "172=1,174=1,176=2,177=9,178=34,179=73,180=30,181=1,185=3," \ + "187=1,188=1,189=1,192=1,196=1,198=1,200=1,201=1,204=1,205=1," \ + "207=1,208=1,209=1,214=2,215=31,216=78,217=28,218=5,219=2," \ + "220=1,222=1,225=1,227=1,234=1,242=1,250=1,252=1,253=1," \ + ">=256=203" + parsed = parse_info(info) + assert 'allocation_stats' in parsed + assert '6' in parsed['allocation_stats'] + assert '>=256' in parsed['allocation_stats'] + + def test_large_responses(self, r): + "The PythonParser has some special cases for return values > 1MB" + # load up 5MB of data into a key + data = ''.join([ascii_letters] * (5000000 // len(ascii_letters))) + r['a'] = data + assert r['a'] == b(data) + + def test_floating_point_encoding(self, r): + """ + High precision floating point values sent to the server should keep + precision. + """ + timestamp = 1349673917.939762 + r.zadd('a', 'a1', timestamp) + assert r.zscore('a', 'a1') == timestamp |
