diff --git a/test/unit/common/middleware/helpers.py b/test/unit/common/middleware/helpers.py index c58b6ae5ab..a3f77395ae 100644 --- a/test/unit/common/middleware/helpers.py +++ b/test/unit/common/middleware/helpers.py @@ -125,7 +125,8 @@ class FakeSwift(object): container_existence_skip_cache = 0.0 account_existence_skip_cache = 0.0 - def __init__(self): + def __init__(self, capture_unexpected_calls=True): + self.capture_unexpected_calls = capture_unexpected_calls self._calls = [] self.req_bodies = [] self._unclosed_req_keys = defaultdict(int) @@ -248,15 +249,20 @@ class FakeSwift(object): self.swift_sources.append(env.get('swift.source')) self.txn_ids.append(env.get('swift.trans_id')) - resp_class, headers, body = self._select_response(env) - # Capture the request before reading the body, in case the iter raises # an exception. # note: tests may assume this copy of req_headers is case insensitive # so we deliberately use a HeaderKeyDict req_headers_copy = HeaderKeyDict(req.headers) - self._calls.append( - FakeSwiftCall(method, path, req_headers_copy)) + call = FakeSwiftCall(method, path, req_headers_copy) + try: + resp_class, headers, body = self._select_response(env) + except KeyError: + if self.capture_unexpected_calls: + self._calls.append(call) + raise + else: + self._calls.append(call) req_body = None # generally, we don't care and let eventlet discard() if (cont and not obj and method == 'UPDATE') or ( diff --git a/test/unit/common/middleware/test_helpers.py b/test/unit/common/middleware/test_helpers.py index 1e2e84bc35..5363e38328 100644 --- a/test/unit/common/middleware/test_helpers.py +++ b/test/unit/common/middleware/test_helpers.py @@ -55,6 +55,28 @@ class TestFakeSwift(unittest.TestCase): do_test('PUT') do_test('DELETE') + def test_capture_unexpected_calls(self): + req = Request.blank('/v1/a/c/o') + req.method = 'GET' + swift = FakeSwift() + with self.assertRaises(KeyError): + req.get_response(swift) + self.assertEqual([('GET', '/v1/a/c/o')], swift.calls) + + req = Request.blank('/v1/a/c/o') + req.method = 'GET' + swift = FakeSwift(capture_unexpected_calls=True) + with self.assertRaises(KeyError): + req.get_response(swift) + self.assertEqual([('GET', '/v1/a/c/o')], swift.calls) + + req = Request.blank('/v1/a/c/o') + req.method = 'GET' + swift = FakeSwift(capture_unexpected_calls=False) + with self.assertRaises(KeyError): + req.get_response(swift) + self.assertEqual([], swift.calls) + def test_GET_registered(self): # verify that a single registered GET response is sufficient to handle # GETs and HEADS, with and without query strings @@ -110,16 +132,18 @@ class TestFakeSwift(unittest.TestCase): self.assertEqual(('HEAD', '/v1/a/c/o?p=q'), swift.calls[-1]) def test_GET_registered_with_query_string(self): - # verify that a single registered GET response is sufficient to handle - # GETs and HEADS, with and without query strings + # verify that a registered GET response with query string only matches + # a request with that query string swift = FakeSwift() swift.register('GET', '/v1/a/c/o?p=q', HTTPOk, {'X-Foo': 'Bar'}, b'stuff') - req = Request.blank('/v1/a/c/o') + req = Request.blank('/v1/a/c/o') # no query string req.method = 'GET' with self.assertRaises(KeyError): - resp = req.get_response(swift) + req.get_response(swift) + self.assertEqual(1, swift.call_count) + self.assertEqual([('GET', '/v1/a/c/o')], swift.calls) req.query_string = 'p=q' resp = req.get_response(swift) @@ -129,8 +153,19 @@ class TestFakeSwift(unittest.TestCase): 'X-Foo': 'Bar'}, resp.headers) self.assertEqual(b'stuff', resp.body) - self.assertEqual(1, swift.call_count) - self.assertEqual(('GET', '/v1/a/c/o?p=q'), swift.calls[-1]) + self.assertEqual(2, swift.call_count) + self.assertEqual([('GET', '/v1/a/c/o'), + ('GET', '/v1/a/c/o?p=q')], + swift.calls) + + req.query_string = 'p=z' + with self.assertRaises(KeyError): + req.get_response(swift) + self.assertEqual(3, swift.call_count) + self.assertEqual([('GET', '/v1/a/c/o'), + ('GET', '/v1/a/c/o?p=q'), + ('GET', '/v1/a/c/o?p=z')], + swift.calls) def test_GET_and_HEAD_registered(self): # verify that a registered HEAD response will be preferred over GET for diff --git a/test/unit/container/test_reconciler.py b/test/unit/container/test_reconciler.py index 00e0e26646..5fe8edca6a 100644 --- a/test/unit/container/test_reconciler.py +++ b/test/unit/container/test_reconciler.py @@ -14,6 +14,7 @@ import json import numbers import shutil +from functools import partial from tempfile import mkdtemp import mock @@ -60,7 +61,8 @@ def container_resp_headers(**kwargs): class FakeStoragePolicySwift(object): def __init__(self): - self.storage_policy = defaultdict(helpers.FakeSwift) + self.storage_policy = defaultdict( + partial(helpers.FakeSwift, capture_unexpected_calls=False)) self._mock_oldest_spi_map = {} def __getattribute__(self, name):