MockMemcached cleanup
* Break sendall's switch into different functions * Actually name some parameters * Raise errors on unexpected input * Consistently use tuples in self.cache Change-Id: I93aa33f83cdf6943a43f14a1868b1497bc7f4478
This commit is contained in:
parent
c0217a4845
commit
143b0eec92
@ -62,6 +62,8 @@ class ExplodingMockMemcached(object):
|
|||||||
|
|
||||||
|
|
||||||
class MockMemcached(object):
|
class MockMemcached(object):
|
||||||
|
# See https://github.com/memcached/memcached/blob/master/doc/protocol.txt
|
||||||
|
# In particular, the "Storage commands" section may be interesting.
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.inbuf = ''
|
self.inbuf = ''
|
||||||
@ -79,58 +81,67 @@ class MockMemcached(object):
|
|||||||
while '\n' in self.inbuf:
|
while '\n' in self.inbuf:
|
||||||
cmd, self.inbuf = self.inbuf.split('\n', 1)
|
cmd, self.inbuf = self.inbuf.split('\n', 1)
|
||||||
parts = cmd.split()
|
parts = cmd.split()
|
||||||
if parts[0].lower() == 'set':
|
handler = getattr(self, 'handle_%s' % parts[0].lower(), None)
|
||||||
self.cache[parts[1]] = parts[2], parts[3], \
|
if handler:
|
||||||
self.inbuf[:int(parts[4])]
|
handler(*parts[1:])
|
||||||
self.inbuf = self.inbuf[int(parts[4]) + 2:]
|
else:
|
||||||
if len(parts) < 6 or parts[5] != 'noreply':
|
raise ValueError('Unhandled command: %s' % parts[0])
|
||||||
self.outbuf += 'STORED\r\n'
|
|
||||||
elif parts[0].lower() == 'add':
|
def handle_set(self, key, flags, exptime, num_bytes, noreply=''):
|
||||||
value = self.inbuf[:int(parts[4])]
|
self.cache[key] = flags, exptime, self.inbuf[:int(num_bytes)]
|
||||||
self.inbuf = self.inbuf[int(parts[4]) + 2:]
|
self.inbuf = self.inbuf[int(num_bytes) + 2:]
|
||||||
if parts[1] in self.cache:
|
if noreply != 'noreply':
|
||||||
if len(parts) < 6 or parts[5] != 'noreply':
|
self.outbuf += 'STORED\r\n'
|
||||||
self.outbuf += 'NOT_STORED\r\n'
|
|
||||||
else:
|
def handle_add(self, key, flags, exptime, num_bytes, noreply=''):
|
||||||
self.cache[parts[1]] = parts[2], parts[3], value
|
value = self.inbuf[:int(num_bytes)]
|
||||||
if len(parts) < 6 or parts[5] != 'noreply':
|
self.inbuf = self.inbuf[int(num_bytes) + 2:]
|
||||||
self.outbuf += 'STORED\r\n'
|
if key in self.cache:
|
||||||
elif parts[0].lower() == 'delete':
|
if noreply != 'noreply':
|
||||||
if self.exc_on_delete:
|
self.outbuf += 'NOT_STORED\r\n'
|
||||||
raise Exception('mock is has exc_on_delete set')
|
else:
|
||||||
if parts[1] in self.cache:
|
self.cache[key] = flags, exptime, value
|
||||||
del self.cache[parts[1]]
|
if noreply != 'noreply':
|
||||||
if 'noreply' not in parts:
|
self.outbuf += 'STORED\r\n'
|
||||||
self.outbuf += 'DELETED\r\n'
|
|
||||||
elif 'noreply' not in parts:
|
def handle_delete(self, key, noreply=''):
|
||||||
self.outbuf += 'NOT_FOUND\r\n'
|
if self.exc_on_delete:
|
||||||
elif parts[0].lower() == 'get':
|
raise Exception('mock is has exc_on_delete set')
|
||||||
for key in parts[1:]:
|
if key in self.cache:
|
||||||
if key in self.cache:
|
del self.cache[key]
|
||||||
val = self.cache[key]
|
if noreply != 'noreply':
|
||||||
self.outbuf += 'VALUE %s %s %s\r\n' % (
|
self.outbuf += 'DELETED\r\n'
|
||||||
key, val[0], len(val[2]))
|
elif noreply != 'noreply':
|
||||||
self.outbuf += val[2] + '\r\n'
|
self.outbuf += 'NOT_FOUND\r\n'
|
||||||
self.outbuf += 'END\r\n'
|
|
||||||
elif parts[0].lower() == 'incr':
|
def handle_get(self, *keys):
|
||||||
if parts[1] in self.cache:
|
for key in keys:
|
||||||
val = list(self.cache[parts[1]])
|
if key in self.cache:
|
||||||
val[2] = str(int(val[2]) + int(parts[2]))
|
val = self.cache[key]
|
||||||
self.cache[parts[1]] = val
|
self.outbuf += 'VALUE %s %s %s\r\n' % (
|
||||||
self.outbuf += str(val[2]) + '\r\n'
|
key, val[0], len(val[2]))
|
||||||
else:
|
self.outbuf += val[2] + '\r\n'
|
||||||
self.outbuf += 'NOT_FOUND\r\n'
|
self.outbuf += 'END\r\n'
|
||||||
elif parts[0].lower() == 'decr':
|
|
||||||
if parts[1] in self.cache:
|
def handle_incr(self, key, value, noreply=''):
|
||||||
val = list(self.cache[parts[1]])
|
if key in self.cache:
|
||||||
if int(val[2]) - int(parts[2]) > 0:
|
current = self.cache[key][2]
|
||||||
val[2] = str(int(val[2]) - int(parts[2]))
|
new_val = str(int(current) + int(value))
|
||||||
else:
|
self.cache[key] = self.cache[key][:2] + (new_val, )
|
||||||
val[2] = '0'
|
self.outbuf += str(new_val) + '\r\n'
|
||||||
self.cache[parts[1]] = val
|
else:
|
||||||
self.outbuf += str(val[2]) + '\r\n'
|
self.outbuf += 'NOT_FOUND\r\n'
|
||||||
else:
|
|
||||||
self.outbuf += 'NOT_FOUND\r\n'
|
def handle_decr(self, key, value, noreply=''):
|
||||||
|
if key in self.cache:
|
||||||
|
current = self.cache[key][2]
|
||||||
|
new_val = str(int(current) - int(value))
|
||||||
|
if new_val[0] == '-': # ie, val is negative
|
||||||
|
new_val = '0'
|
||||||
|
self.cache[key] = self.cache[key][:2] + (new_val, )
|
||||||
|
self.outbuf += str(new_val) + '\r\n'
|
||||||
|
else:
|
||||||
|
self.outbuf += 'NOT_FOUND\r\n'
|
||||||
|
|
||||||
def readline(self):
|
def readline(self):
|
||||||
if self.read_return_none:
|
if self.read_return_none:
|
||||||
|
Loading…
Reference in New Issue
Block a user