Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test FakeRedis against real Redis #900

Merged
merged 10 commits into from
Mar 4, 2015
43 changes: 30 additions & 13 deletions vumi/persist/fake_redis.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ def call_to_deferred(deferred, func, *args, **kw):
execute(func, *args, **kw).chainDeferred(deferred)


class ResponseError(Exception):
"""
Exception class for things we throw to match the real Redis client
libraries.
"""


class FakeRedis(object):
"""In process and memory implementation of redis-like data store.

Expand Down Expand Up @@ -171,7 +178,7 @@ def scan(self, cursor, match=None, count=None):
else:
cursor = str(start + i + 1)

return cursor, fnmatch.filter(output, match)
return [cursor, fnmatch.filter(output, match)]

@maybe_async
def flushdb(self):
Expand All @@ -188,6 +195,7 @@ def get(self, key):
def set(self, key, value):
value = self._encode(value) # set() sets string value
self._set_key(key, value)
return True

@maybe_async
def setex(self, key, time, value):
Expand Down Expand Up @@ -272,8 +280,8 @@ def hmset(self, key, mapping):

@maybe_async
def hgetall(self, key):
return dict((self._encode(k), self._encode(v)) for k, v in
self._data.get(key, {}).items())
return dict((self._encode(k), self._encode(v))
for k, v in self._data.get(key, {}).items())

@maybe_async
def hlen(self, key):
Expand Down Expand Up @@ -376,18 +384,18 @@ def zrange(self, key, start, stop, desc=False, withscores=False,

@maybe_async
def zrangebyscore(self, key, min='-inf', max='+inf', start=0, num=None,
withscores=False, score_cast_func=float):
withscores=False, score_cast_func=float):
zval = self._data.get(key, Zset())
results = zval.zrangebyscore(min, max, start, num,
score_cast_func=score_cast_func)
results = zval.zrangebyscore(
min, max, start, num, score_cast_func=score_cast_func)
if withscores:
return results
else:
return [v for v, k in results]

@maybe_async
def zcount(self, key, min, max):
return str(len(self.zrangebyscore.sync(self, key, min, max)))
return len(self.zrangebyscore.sync(self, key, min, max))

@maybe_async
def zscore(self, key, value):
Expand Down Expand Up @@ -416,12 +424,13 @@ def rpop(self, key):

@maybe_async
def lpush(self, key, obj):
self._setdefault_key(key, []).insert(0, obj)
self._setdefault_key(key, []).insert(0, self._encode(obj))
return self.llen.sync(self, key)

@maybe_async
def rpush(self, key, obj):
self._setdefault_key(key, []).append(obj)
return self.llen.sync(self, key) - 1
self._setdefault_key(key, []).append(self._encode(obj))
return self.llen.sync(self, key)

@maybe_async
def lrange(self, key, start, end):
Expand All @@ -435,6 +444,7 @@ def lrange(self, key, start, end):
@maybe_async
def lrem(self, key, value, num=0):
removed = [0]
value = self._encode(value)

def keep(v):
if v == value and (num == 0 or removed[0] < abs(num)):
Expand Down Expand Up @@ -468,6 +478,7 @@ def ltrim(self, key, start, stop):
# want to keep.
del lval[stop + 1:]
del lval[:start]
return True

# Expiry operations

Expand All @@ -484,7 +495,7 @@ def expire(self, key, seconds):
def ttl(self, key):
delayed = self._expiries.get(key)
if delayed is not None and delayed.active():
return int(delayed.getTime() - self.clock.seconds())
return round(delayed.getTime() - self.clock.seconds())
return None

@maybe_async
Expand All @@ -508,10 +519,16 @@ def _redis_range_to_py_range(self, start, end):
end = None
return start, end

def _to_float(self, value):
try:
return float(value)
except (ValueError, TypeError):
raise ResponseError("value is not a valid float")

def zadd(self, **valscores):
new_zval = [val for val in self._zval if val[1] not in valscores]
new_zval.extend((float(score), value) for value, score
in valscores.items())
new_zval.extend((self._to_float(score), value)
for value, score in valscores.items())
new_zval.sort()
added = len(new_zval) - len(self._zval)
self._zval = new_zval
Expand Down
9 changes: 5 additions & 4 deletions vumi/persist/redis_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,8 +260,9 @@ def _unkeys_scan(self, scan_results):
zcard = RedisCall(['key'])
zrange = RedisCall(['key', 'start', 'stop', 'desc', 'withscores'],
defaults=[False, False])
zrangebyscore = RedisCall(['key', 'min', 'max', 'start', 'num',
'withscores'], defaults=['-inf', '+inf', None, None, False])
zrangebyscore = RedisCall(
['key', 'min', 'max', 'start', 'num', 'withscores'],
defaults=['-inf', '+inf', None, None, False])
zscore = RedisCall(['key', 'value'])
zcount = RedisCall(['key', 'min', 'max'])
zremrangebyrank = RedisCall(['key', 'start', 'stop'])
Expand All @@ -275,8 +276,8 @@ def _unkeys_scan(self, scan_results):
rpush = RedisCall(['key', 'obj'])
lrange = RedisCall(['key', 'start', 'end'])
lrem = RedisCall(['key', 'value', 'num'], defaults=[0])
rpoplpush = RedisCall(['source'], vararg='destination',
key_args=['source', 'destination'])
rpoplpush = RedisCall(
['source'], vararg='destination', key_args=['source', 'destination'])
ltrim = RedisCall(['key', 'start', 'stop'])

# Expiry operations
Expand Down
Loading