From a97537e158a78b7c49f11aef2756fa65093a05dd Mon Sep 17 00:00:00 2001 From: Clay Gerrard Date: Mon, 25 Jul 2016 12:22:20 -0700 Subject: [PATCH] Split up backend/sysmeta header/footer preference tests The change in preference to the Related-Change is simply to prefer sysmeta overrides in the headers to backend overrides in the footers: Before: sysmeta footers > backend footers > sysmeta headers > backend headers After: sysmeta footers > sysmeta headers > backend footers > backend headers This change just breaks up the tests to try to make it more obvious what already worked and what has changed. The justification seems to be that overrides in sysmeta headers only work on policies that don't send backend footers, but sysmeta overrides should always have a higher preference than backend overrides. Related-Change: Idb40361ac72da51e1390dff690723dbc2c653a13 Change-Id: I074fbecb6440fb1d04279cd892d38d2acc44b47d --- test/unit/obj/test_server.py | 155 +++++++++++++++++++---------------- 1 file changed, 84 insertions(+), 71 deletions(-) diff --git a/test/unit/obj/test_server.py b/test/unit/obj/test_server.py index 536a746037..540bd0e2fa 100755 --- a/test/unit/obj/test_server.py +++ b/test/unit/obj/test_server.py @@ -121,6 +121,7 @@ class TestObjectController(unittest.TestCase): self.object_controller.logger) self.logger = debug_logger('test-object-controller') + self.ts = make_timestamp_iter() def tearDown(self): """Tear down for testing swift.object.server.ObjectController""" @@ -1435,85 +1436,97 @@ class TestObjectController(unittest.TestCase): with open(objfile) as fh: self.assertEqual(fh.read(), "obj data") - def test_PUT_container_override_etag_in_footer(self): - ts_iter = make_timestamp_iter() + def _check_container_override_etag_preference(self, override_headers, + override_footers): + def mock_container_update(ctlr, op, account, container, obj, req, + headers_out, objdevice, policy): + calls_made.append((headers_out, policy)) + calls_made = [] + ts_put = next(self.ts) - def do_test(override_headers, override_footers): - def mock_container_update(ctlr, op, account, container, obj, req, - headers_out, objdevice, policy): - calls_made.append((headers_out, policy)) - calls_made = [] - ts_put = next(ts_iter) + headers = { + 'X-Timestamp': ts_put.internal, + 'Content-Type': 'text/plain', + 'Transfer-Encoding': 'chunked', + 'Etag': 'other-etag', + 'X-Backend-Obj-Metadata-Footer': 'yes', + 'X-Backend-Obj-Multipart-Mime-Boundary': 'boundary'} + headers.update(override_headers) + req = Request.blank( + '/sda1/p/a/c/o', headers=headers, + environ={'REQUEST_METHOD': 'PUT'}) - headers = { - 'X-Timestamp': ts_put.internal, - 'Content-Type': 'text/plain', - 'Transfer-Encoding': 'chunked', - 'Etag': 'other-etag', - 'X-Backend-Obj-Metadata-Footer': 'yes', - 'X-Backend-Obj-Multipart-Mime-Boundary': 'boundary'} - headers.update(override_headers) - req = Request.blank( - '/sda1/p/a/c/o', headers=headers, - environ={'REQUEST_METHOD': 'PUT'}) + obj_etag = md5("obj data").hexdigest() + footers = {'Etag': obj_etag} + footers.update(override_footers) + footer_meta = json.dumps(footers) + footer_meta_cksum = md5(footer_meta).hexdigest() - obj_etag = md5("obj data").hexdigest() - footers = {'Etag': obj_etag} - footers.update(override_footers) - footer_meta = json.dumps(footers) - footer_meta_cksum = md5(footer_meta).hexdigest() + req.body = "\r\n".join(( + "--boundary", + "", + "obj data", + "--boundary", + "Content-MD5: " + footer_meta_cksum, + "", + footer_meta, + "--boundary--", + )) + req.headers.pop("Content-Length", None) - req.body = "\r\n".join(( - "--boundary", - "", - "obj data", - "--boundary", - "Content-MD5: " + footer_meta_cksum, - "", - footer_meta, - "--boundary--", - )) - req.headers.pop("Content-Length", None) + with mock.patch( + 'swift.obj.server.ObjectController.container_update', + mock_container_update): + resp = req.get_response(self.object_controller) + self.assertEqual(resp.etag, obj_etag) + self.assertEqual(resp.status_int, 201) + self.assertEqual(1, len(calls_made)) + self.assertEqual({ + 'X-Size': str(len('obj data')), + 'X-Etag': 'update-etag', + 'X-Content-Type': 'text/plain', + 'X-Timestamp': ts_put.internal, + }, calls_made[0][0]) + self.assertEqual(POLICIES[0], calls_made[0][1]) - with mock.patch( - 'swift.obj.server.ObjectController.container_update', - mock_container_update): - resp = req.get_response(self.object_controller) - self.assertEqual(resp.etag, obj_etag) - self.assertEqual(resp.status_int, 201) - self.assertEqual(1, len(calls_made)) - self.assertEqual({ - 'X-Size': str(len('obj data')), - 'X-Etag': 'update-etag', - 'X-Content-Type': 'text/plain', - 'X-Timestamp': ts_put.internal, - }, calls_made[0][0]) - self.assertEqual(POLICIES[0], calls_made[0][1]) + def test_lone_header_footer_override_preference(self): + self._check_container_override_etag_preference( + {'X-Backend-Container-Update-Override-Etag': 'update-etag'}, {}) + self._check_container_override_etag_preference( + {}, {'X-Backend-Container-Update-Override-Etag': 'update-etag'}) + self._check_container_override_etag_preference( + {'X-Object-Sysmeta-Container-Update-Override-Etag': + 'update-etag'}, {}) + self._check_container_override_etag_preference( + {}, {'X-Object-Sysmeta-Container-Update-Override-Etag': + 'update-etag'}), - # lone headers/footers work - do_test({'X-Backend-Container-Update-Override-Etag': 'update-etag'}, - {}) - do_test({}, - {'X-Backend-Container-Update-Override-Etag': 'update-etag'}) - do_test({'X-Object-Sysmeta-Container-Update-Override-Etag': - 'update-etag'}, - {}) - do_test({}, - {'X-Object-Sysmeta-Container-Update-Override-Etag': + def test_footer_trumps_header(self): + self._check_container_override_etag_preference( + {'X-Backend-Container-Update-Override-Etag': 'ignored-etag'}, + {'X-Backend-Container-Update-Override-Etag': 'update-etag'}) + self._check_container_override_etag_preference( + {'X-Object-Sysmeta-Container-Update-Override-Etag': + 'ignored-etag'}, + {'X-Object-Sysmeta-Container-Update-Override-Etag': + 'update-etag'}) + + def test_sysmeta_trumps_backend(self): + self._check_container_override_etag_preference( + {'X-Backend-Container-Update-Override-Etag': 'ignored-etag', + 'X-Object-Sysmeta-Container-Update-Override-Etag': + 'update-etag'}, {}) + self._check_container_override_etag_preference( + {}, {'X-Backend-Container-Update-Override-Etag': 'ignored-etag', + 'X-Object-Sysmeta-Container-Update-Override-Etag': 'update-etag'}) - # footer trumps header - do_test({'X-Backend-Container-Update-Override-Etag': 'ignored-etag'}, - {'X-Backend-Container-Update-Override-Etag': 'update-etag'}) - do_test({'X-Object-Sysmeta-Container-Update-Override-Etag': - 'ignored-etag'}, - {'X-Object-Sysmeta-Container-Update-Override-Etag': - 'update-etag'}) - - # but sysmeta header trumps backend footer - do_test({'X-Object-Sysmeta-Container-Update-Override-Etag': - 'update-etag'}, - {'X-Backend-Container-Update-Override-Etag': 'ignored-etag'}) + def test_sysmeta_header_trumps_backend_footer(self): + headers = {'X-Object-Sysmeta-Container-Update-Override-Etag': + 'update-etag'} + footers = {'X-Backend-Container-Update-Override-Etag': + 'ignored-etag'} + self._check_container_override_etag_preference(headers, footers) def test_PUT_etag_in_footer_mismatch(self): timestamp = normalize_timestamp(time())