summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandy <andy@whiskeymedia.com>2013-06-04 15:13:17 -0400
committerandy <andy@whiskeymedia.com>2013-06-04 15:13:17 -0400
commite1233ff4545de043b5b33b7d50f17d260f1e02ce (patch)
tree59670ca85af8e8ac3a4c6b7bd57fb5affce442b0
parent7d8674f3edb326f29e4a1552ae674ea3ca6e7808 (diff)
downloadredis-py-e1233ff4545de043b5b33b7d50f17d260f1e02ce.tar.gz
pytest framework and server commands
-rw-r--r--redis/client.py67
-rwxr-xr-xrun_tests9
-rw-r--r--setup.py20
-rw-r--r--tests/__init__.py31
-rw-r--r--tests/server_commands.py1843
-rw-r--r--tests/test_commands.py1227
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)
diff --git a/setup.py b/setup.py
index 6d656ee..8b188d7 100644
--- a/setup.py
+++ b/setup.py
@@ -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