Merge "tests: Improve FakeMemcache call tracking"
This commit is contained in:
commit
96b7980196
@ -401,6 +401,13 @@ class FabricatedRing(Ring):
|
|||||||
self._update_bookkeeping()
|
self._update_bookkeeping()
|
||||||
|
|
||||||
|
|
||||||
|
def track(f):
|
||||||
|
def wrapper(self, *a, **kw):
|
||||||
|
self.calls.append(getattr(mocklib.call, f.__name__)(*a, **kw))
|
||||||
|
return f(self, *a, **kw)
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
class FakeMemcache(object):
|
class FakeMemcache(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -412,19 +419,16 @@ class FakeMemcache(object):
|
|||||||
def clear_calls(self):
|
def clear_calls(self):
|
||||||
del self.calls[:]
|
del self.calls[:]
|
||||||
|
|
||||||
def _called(self, method, key=None, value=None, time=None):
|
@track
|
||||||
self.calls.append((method, key, value, time))
|
|
||||||
|
|
||||||
def get(self, key):
|
def get(self, key):
|
||||||
self._called('get', key)
|
|
||||||
return self.store.get(key)
|
return self.store.get(key)
|
||||||
|
|
||||||
|
@property
|
||||||
def keys(self):
|
def keys(self):
|
||||||
self._called('keys')
|
return self.store.keys
|
||||||
return self.store.keys()
|
|
||||||
|
|
||||||
|
@track
|
||||||
def set(self, key, value, serialize=True, time=0):
|
def set(self, key, value, serialize=True, time=0):
|
||||||
self._called('set', key, value, time)
|
|
||||||
if serialize:
|
if serialize:
|
||||||
value = json.loads(json.dumps(value))
|
value = json.loads(json.dumps(value))
|
||||||
else:
|
else:
|
||||||
@ -432,8 +436,8 @@ class FakeMemcache(object):
|
|||||||
self.store[key] = value
|
self.store[key] = value
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@track
|
||||||
def incr(self, key, delta=1, time=0):
|
def incr(self, key, delta=1, time=0):
|
||||||
self._called('incr', key, time=time)
|
|
||||||
if self.error_on_incr:
|
if self.error_on_incr:
|
||||||
raise MemcacheConnectionError('Memcache restarting')
|
raise MemcacheConnectionError('Memcache restarting')
|
||||||
if self.init_incr_return_neg:
|
if self.init_incr_return_neg:
|
||||||
@ -445,6 +449,7 @@ class FakeMemcache(object):
|
|||||||
self.store[key] = 0
|
self.store[key] = 0
|
||||||
return self.store[key]
|
return self.store[key]
|
||||||
|
|
||||||
|
# tracked via incr()
|
||||||
def decr(self, key, delta=1, time=0):
|
def decr(self, key, delta=1, time=0):
|
||||||
return self.incr(key, delta=-delta, time=time)
|
return self.incr(key, delta=-delta, time=time)
|
||||||
|
|
||||||
@ -452,8 +457,8 @@ class FakeMemcache(object):
|
|||||||
def soft_lock(self, key, timeout=0, retries=5):
|
def soft_lock(self, key, timeout=0, retries=5):
|
||||||
yield True
|
yield True
|
||||||
|
|
||||||
|
@track
|
||||||
def delete(self, key):
|
def delete(self, key):
|
||||||
self._called('delete', key)
|
|
||||||
try:
|
try:
|
||||||
del self.store[key]
|
del self.store[key]
|
||||||
except Exception:
|
except Exception:
|
||||||
@ -464,6 +469,11 @@ class FakeMemcache(object):
|
|||||||
self.store.clear()
|
self.store.clear()
|
||||||
|
|
||||||
|
|
||||||
|
# This decorator only makes sense in the context of FakeMemcache;
|
||||||
|
# may as well clean it up now
|
||||||
|
del track
|
||||||
|
|
||||||
|
|
||||||
class FakeIterable(object):
|
class FakeIterable(object):
|
||||||
def __init__(self, values):
|
def __init__(self, values):
|
||||||
self.next_call_count = 0
|
self.next_call_count = 0
|
||||||
|
@ -2110,14 +2110,13 @@ class TestContainerController(TestRingBase):
|
|||||||
'X-Backend-Record-Type': 'shard',
|
'X-Backend-Record-Type': 'shard',
|
||||||
'X-Backend-Sharding-State': sharding_state})
|
'X-Backend-Sharding-State': sharding_state})
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
[('get', 'container/a/c', None, None),
|
[mock.call.get('container/a/c'),
|
||||||
('set', 'shard-listing/a/c', self.sr_dicts,
|
mock.call.set('shard-listing/a/c', self.sr_dicts,
|
||||||
exp_recheck_listing),
|
time=exp_recheck_listing),
|
||||||
('set', 'container/a/c', mock.ANY, 60)],
|
mock.call.set('container/a/c', mock.ANY, time=60)],
|
||||||
self.memcache.calls)
|
self.memcache.calls)
|
||||||
self.assertEqual(self.sr_dicts, self.memcache.calls[1][2])
|
|
||||||
self.assertEqual(sharding_state,
|
self.assertEqual(sharding_state,
|
||||||
self.memcache.calls[2][2]['sharding_state'])
|
self.memcache.calls[2][1][1]['sharding_state'])
|
||||||
self.assertIn('swift.infocache', req.environ)
|
self.assertIn('swift.infocache', req.environ)
|
||||||
self.assertIn('shard-listing/a/c', req.environ['swift.infocache'])
|
self.assertIn('shard-listing/a/c', req.environ['swift.infocache'])
|
||||||
self.assertEqual(tuple(self.sr_dicts),
|
self.assertEqual(tuple(self.sr_dicts),
|
||||||
@ -2134,8 +2133,8 @@ class TestContainerController(TestRingBase):
|
|||||||
'X-Backend-Record-Type': 'shard',
|
'X-Backend-Record-Type': 'shard',
|
||||||
'X-Backend-Sharding-State': sharding_state})
|
'X-Backend-Sharding-State': sharding_state})
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
[('get', 'container/a/c', None, None),
|
[mock.call.get('container/a/c'),
|
||||||
('get', 'shard-listing/a/c', None, None)],
|
mock.call.get('shard-listing/a/c')],
|
||||||
self.memcache.calls)
|
self.memcache.calls)
|
||||||
self.assertIn('swift.infocache', req.environ)
|
self.assertIn('swift.infocache', req.environ)
|
||||||
self.assertIn('shard-listing/a/c', req.environ['swift.infocache'])
|
self.assertIn('shard-listing/a/c', req.environ['swift.infocache'])
|
||||||
@ -2151,8 +2150,8 @@ class TestContainerController(TestRingBase):
|
|||||||
self._capture_backend_request(req, 204, b'', {},
|
self._capture_backend_request(req, 204, b'', {},
|
||||||
num_resp=self.CONTAINER_REPLICAS)
|
num_resp=self.CONTAINER_REPLICAS)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
[('delete', 'container/a/c', None, None),
|
[mock.call.delete('container/a/c'),
|
||||||
('delete', 'shard-listing/a/c', None, None)],
|
mock.call.delete('shard-listing/a/c')],
|
||||||
self.memcache.calls)
|
self.memcache.calls)
|
||||||
|
|
||||||
def test_get_from_shards_add_root_spi(self):
|
def test_get_from_shards_add_root_spi(self):
|
||||||
@ -2281,11 +2280,11 @@ class TestContainerController(TestRingBase):
|
|||||||
# Note: container metadata is updated in cache but shard ranges are not
|
# Note: container metadata is updated in cache but shard ranges are not
|
||||||
# deleted from cache
|
# deleted from cache
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
[('get', 'container/a/c', None, None),
|
[mock.call.get('container/a/c'),
|
||||||
('get', 'shard-listing/a/c', None, None),
|
mock.call.get('shard-listing/a/c'),
|
||||||
('set', 'container/a/c', mock.ANY, 6.0)],
|
mock.call.set('container/a/c', mock.ANY, time=6.0)],
|
||||||
self.memcache.calls)
|
self.memcache.calls)
|
||||||
self.assertEqual(404, self.memcache.calls[2][2]['status'])
|
self.assertEqual(404, self.memcache.calls[2][1][1]['status'])
|
||||||
self.assertEqual(b'', resp.body)
|
self.assertEqual(b'', resp.body)
|
||||||
self.assertEqual(404, resp.status_int)
|
self.assertEqual(404, resp.status_int)
|
||||||
|
|
||||||
@ -2304,8 +2303,8 @@ class TestContainerController(TestRingBase):
|
|||||||
req = self._build_request(req_hdrs, params, {})
|
req = self._build_request(req_hdrs, params, {})
|
||||||
resp = req.get_response(self.app)
|
resp = req.get_response(self.app)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
[('get', 'container/a/c', None, None),
|
[mock.call.get('container/a/c'),
|
||||||
('get', 'shard-listing/a/c', None, None)],
|
mock.call.get('shard-listing/a/c')],
|
||||||
self.memcache.calls)
|
self.memcache.calls)
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
@ -2387,14 +2386,13 @@ class TestContainerController(TestRingBase):
|
|||||||
expected_hdrs = {'X-Backend-Recheck-Container-Existence': '60'}
|
expected_hdrs = {'X-Backend-Recheck-Container-Existence': '60'}
|
||||||
expected_hdrs.update(resp_hdrs)
|
expected_hdrs.update(resp_hdrs)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
[('get', 'container/a/c', None, None),
|
[mock.call.get('container/a/c'),
|
||||||
('set', 'shard-listing/a/c', self.sr_dicts, 600),
|
mock.call.set('shard-listing/a/c', self.sr_dicts, time=600),
|
||||||
('set', 'container/a/c', mock.ANY, 60)],
|
mock.call.set('container/a/c', mock.ANY, time=60)],
|
||||||
self.memcache.calls)
|
self.memcache.calls)
|
||||||
# shards were cached
|
# shards were cached
|
||||||
self.assertEqual(self.sr_dicts, self.memcache.calls[1][2])
|
|
||||||
self.assertEqual('sharded',
|
self.assertEqual('sharded',
|
||||||
self.memcache.calls[2][2]['sharding_state'])
|
self.memcache.calls[2][1][1]['sharding_state'])
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
def test_GET_shard_ranges_write_to_cache(self):
|
def test_GET_shard_ranges_write_to_cache(self):
|
||||||
@ -2480,12 +2478,11 @@ class TestContainerController(TestRingBase):
|
|||||||
expected_hdrs.update(resp_hdrs)
|
expected_hdrs.update(resp_hdrs)
|
||||||
self._check_response(resp, self.sr_dicts, expected_hdrs)
|
self._check_response(resp, self.sr_dicts, expected_hdrs)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
[('set', 'shard-listing/a/c', self.sr_dicts, 600),
|
[mock.call.set('shard-listing/a/c', self.sr_dicts, time=600),
|
||||||
('set', 'container/a/c', mock.ANY, 60)],
|
mock.call.set('container/a/c', mock.ANY, time=60)],
|
||||||
self.memcache.calls)
|
self.memcache.calls)
|
||||||
self.assertEqual(self.sr_dicts, self.memcache.calls[0][2])
|
|
||||||
self.assertEqual('sharded',
|
self.assertEqual('sharded',
|
||||||
self.memcache.calls[1][2]['sharding_state'])
|
self.memcache.calls[1][1][1]['sharding_state'])
|
||||||
|
|
||||||
def _do_test_GET_shard_ranges_no_cache_write(self, resp_hdrs):
|
def _do_test_GET_shard_ranges_no_cache_write(self, resp_hdrs):
|
||||||
# verify that there is a cache lookup to check container info but then
|
# verify that there is a cache lookup to check container info but then
|
||||||
@ -2516,11 +2513,11 @@ class TestContainerController(TestRingBase):
|
|||||||
# container metadata is looked up in memcache for sharding state
|
# container metadata is looked up in memcache for sharding state
|
||||||
# container metadata is set in memcache
|
# container metadata is set in memcache
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
[('get', 'container/a/c', None, None),
|
[mock.call.get('container/a/c'),
|
||||||
('set', 'container/a/c', mock.ANY, 60)],
|
mock.call.set('container/a/c', mock.ANY, time=60)],
|
||||||
self.memcache.calls)
|
self.memcache.calls)
|
||||||
self.assertEqual(resp.headers.get('X-Backend-Sharding-State'),
|
self.assertEqual(resp.headers.get('X-Backend-Sharding-State'),
|
||||||
self.memcache.calls[1][2]['sharding_state'])
|
self.memcache.calls[1][1][1]['sharding_state'])
|
||||||
self.memcache.delete_all()
|
self.memcache.delete_all()
|
||||||
|
|
||||||
def test_GET_shard_ranges_no_cache_write_with_cached_container_info(self):
|
def test_GET_shard_ranges_no_cache_write_with_cached_container_info(self):
|
||||||
@ -2650,11 +2647,11 @@ class TestContainerController(TestRingBase):
|
|||||||
# container metadata is looked up in memcache for sharding state
|
# container metadata is looked up in memcache for sharding state
|
||||||
# container metadata is set in memcache
|
# container metadata is set in memcache
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
[('get', 'container/a/c', None, None),
|
[mock.call.get('container/a/c'),
|
||||||
('set', 'container/a/c', mock.ANY, 60)],
|
mock.call.set('container/a/c', mock.ANY, time=60)],
|
||||||
self.memcache.calls)
|
self.memcache.calls)
|
||||||
self.assertEqual(resp.headers.get('X-Backend-Sharding-State'),
|
self.assertEqual(resp.headers.get('X-Backend-Sharding-State'),
|
||||||
self.memcache.calls[1][2]['sharding_state'])
|
self.memcache.calls[1][1][1]['sharding_state'])
|
||||||
self.memcache.delete_all()
|
self.memcache.delete_all()
|
||||||
|
|
||||||
def test_GET_shard_ranges_bad_response_body(self):
|
def test_GET_shard_ranges_bad_response_body(self):
|
||||||
@ -2703,10 +2700,10 @@ class TestContainerController(TestRingBase):
|
|||||||
'X-Backend-Sharding-State': sharding_state})
|
'X-Backend-Sharding-State': sharding_state})
|
||||||
# container metadata from backend response is set in memcache
|
# container metadata from backend response is set in memcache
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
[('set', 'container/a/c', mock.ANY, 60)],
|
[mock.call.set('container/a/c', mock.ANY, time=60)],
|
||||||
self.memcache.calls)
|
self.memcache.calls)
|
||||||
self.assertEqual(sharding_state,
|
self.assertEqual(sharding_state,
|
||||||
self.memcache.calls[0][2]['sharding_state'])
|
self.memcache.calls[0][1][1]['sharding_state'])
|
||||||
|
|
||||||
def test_GET_shard_ranges_no_cache_recheck_listing_shard_ranges(self):
|
def test_GET_shard_ranges_no_cache_recheck_listing_shard_ranges(self):
|
||||||
# verify that a GET for shards does not lookup or store in cache when
|
# verify that a GET for shards does not lookup or store in cache when
|
||||||
@ -2773,10 +2770,10 @@ class TestContainerController(TestRingBase):
|
|||||||
'X-Backend-Sharding-State': 'sharded'})
|
'X-Backend-Sharding-State': 'sharded'})
|
||||||
# container metadata from backend response is set in memcache
|
# container metadata from backend response is set in memcache
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
[('set', 'container/a/c', mock.ANY, 60)],
|
[mock.call.set('container/a/c', mock.ANY, time=60)],
|
||||||
self.memcache.calls)
|
self.memcache.calls)
|
||||||
self.assertEqual('sharded',
|
self.assertEqual('sharded',
|
||||||
self.memcache.calls[0][2]['sharding_state'])
|
self.memcache.calls[0][1][1]['sharding_state'])
|
||||||
|
|
||||||
def test_GET_shard_ranges_no_memcache_available(self):
|
def test_GET_shard_ranges_no_memcache_available(self):
|
||||||
self._setup_shard_range_stubs()
|
self._setup_shard_range_stubs()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user