diff --git a/test/unit/common/middleware/s3api/__init__.py b/test/unit/common/middleware/s3api/__init__.py index e11d0fdc85..2a180b2da8 100644 --- a/test/unit/common/middleware/s3api/__init__.py +++ b/test/unit/common/middleware/s3api/__init__.py @@ -25,6 +25,7 @@ from swift.common.middleware.s3api.etree import fromstring from swift.common.middleware.s3api.utils import Config from test.unit.common.middleware.s3api.helpers import FakeSwift +from test.unit import debug_logger class FakeApp(object): @@ -79,6 +80,7 @@ class S3ApiTestCase(unittest.TestCase): self.app = FakeApp() self.swift = self.app.swift self.s3api = filter_factory({}, **self.conf)(self.app) + self.s3api.logger = debug_logger() self.swift.register('HEAD', '/v1/AUTH_test', swob.HTTPOk, {}, None) diff --git a/test/unit/common/middleware/s3api/test_multi_upload.py b/test/unit/common/middleware/s3api/test_multi_upload.py index 282a0538f4..2dc3d8db61 100644 --- a/test/unit/common/middleware/s3api/test_multi_upload.py +++ b/test/unit/common/middleware/s3api/test_multi_upload.py @@ -35,7 +35,7 @@ from swift.common.middleware.s3api.utils import sysmeta_header, mktime, \ S3Timestamp from swift.common.middleware.s3api.s3request import MAX_32BIT_INT -xml = '' \ +XML = '' \ '' \ '1' \ '0123456789abcdef0123456789abcdef' \ @@ -46,11 +46,11 @@ xml = '' \ '' \ '' -objects_template = \ +OBJECTS_TEMPLATE = \ (('object/X/1', '2014-05-07T19:47:51.592270', '0123456789abcdef', 100), ('object/X/2', '2014-05-07T19:47:52.592270', 'fedcba9876543210', 200)) -multiparts_template = \ +MULTIPARTS_TEMPLATE = \ (('object/X', '2014-05-07T19:47:50.592270', 'HASH', 1), ('object/X/1', '2014-05-07T19:47:51.592270', '0123456789abcdef', 11), ('object/X/2', '2014-05-07T19:47:52.592270', 'fedcba9876543210', 21), @@ -66,7 +66,7 @@ multiparts_template = \ ('subdir/object/Z/2', '2014-05-07T19:47:58.592270', 'fedcba9876543210', 41)) -s3_etag = '"%s-2"' % hashlib.md5(( +S3_ETAG = '"%s-2"' % hashlib.md5(( '0123456789abcdef0123456789abcdef' 'fedcba9876543210fedcba9876543210').decode('hex')).hexdigest() @@ -85,7 +85,7 @@ class TestS3ApiMultiUpload(S3ApiTestCase): objects = map(lambda item: {'name': item[0], 'last_modified': item[1], 'hash': item[2], 'bytes': item[3]}, - objects_template) + OBJECTS_TEMPLATE) object_list = json.dumps(objects) self.swift.register('PUT', segment_bucket, @@ -171,7 +171,7 @@ class TestS3ApiMultiUpload(S3ApiTestCase): def _test_bucket_multipart_uploads_GET(self, query=None, multiparts=None): segment_bucket = '/v1/AUTH_test/bucket+segments' - objects = multiparts or multiparts_template + objects = multiparts or MULTIPARTS_TEMPLATE objects = map(lambda item: {'name': item[0], 'last_modified': item[1], 'hash': item[2], 'bytes': item[3]}, objects) @@ -197,7 +197,7 @@ class TestS3ApiMultiUpload(S3ApiTestCase): self.assertEqual(elem.find('MaxUploads').text, '1000') self.assertEqual(elem.find('IsTruncated').text, 'false') self.assertEqual(len(elem.findall('Upload')), 4) - objects = [(o[0], o[1][:-3] + 'Z') for o in multiparts_template] + objects = [(o[0], o[1][:-3] + 'Z') for o in MULTIPARTS_TEMPLATE] for u in elem.findall('Upload'): name = u.find('Key').text + '/' + u.find('UploadId').text initiated = u.find('Initiated').text @@ -657,7 +657,7 @@ class TestS3ApiMultiUpload(S3ApiTestCase): environ={'REQUEST_METHOD': 'POST'}, headers={'Authorization': 'AWS test:tester:hmac', 'Date': self.get_date_header(), }, - body=xml) + body=XML) with patch( 'swift.common.middleware.s3api.s3request.get_container_info', lambda x, y: {'status': 404}): @@ -667,17 +667,17 @@ class TestS3ApiMultiUpload(S3ApiTestCase): self.assertEqual(self._get_error_code(body), 'NoSuchBucket') def test_object_multipart_upload_complete(self): - content_md5 = base64.b64encode(hashlib.md5(xml).digest()) + content_md5 = base64.b64encode(hashlib.md5(XML).digest()) req = Request.blank('/bucket/object?uploadId=X', environ={'REQUEST_METHOD': 'POST'}, headers={'Authorization': 'AWS test:tester:hmac', 'Date': self.get_date_header(), 'Content-MD5': content_md5, }, - body=xml) + body=XML) status, headers, body = self.call_s3api(req) elem = fromstring(body, 'CompleteMultipartUploadResult') self.assertNotIn('Etag', headers) - self.assertEqual(elem.find('ETag').text, s3_etag) + self.assertEqual(elem.find('ETag').text, S3_ETAG) self.assertEqual(status.split()[0], '200') self.assertEqual(self.swift.calls, [ @@ -696,10 +696,22 @@ class TestS3ApiMultiUpload(S3ApiTestCase): self.assertEqual(headers.get('X-Object-Meta-Foo'), 'bar') self.assertEqual(headers.get('Content-Type'), 'baz/quux') # SLO will provide a base value - override_etag = '; s3_etag=%s' % s3_etag.strip('"') + override_etag = '; s3_etag=%s' % S3_ETAG.strip('"') h = 'X-Object-Sysmeta-Container-Update-Override-Etag' self.assertEqual(headers.get(h), override_etag) + def test_object_multipart_upload_invalid_md5(self): + bad_md5 = base64.b64encode(hashlib.md5(XML + 'some junk').digest()) + req = Request.blank('/bucket/object?uploadId=X', + environ={'REQUEST_METHOD': 'POST'}, + headers={'Authorization': 'AWS test:tester:hmac', + 'Date': self.get_date_header(), + 'Content-MD5': bad_md5, }, + body=XML) + status, headers, body = self.call_s3api(req) + self.assertEqual('400 Bad Request', status) + self.assertEqual(self._get_error_code(body), 'BadDigest') + @patch('swift.common.middleware.s3api.controllers.multi_upload.time') def test_object_multipart_upload_complete_with_heartbeat(self, mock_time): self.swift.register( @@ -710,7 +722,7 @@ class TestS3ApiMultiUpload(S3ApiTestCase): json.dumps([ {'name': item[0].replace('object', 'heartbeat-ok'), 'last_modified': item[1], 'hash': item[2], 'bytes': item[3]} - for item in objects_template + for item in OBJECTS_TEMPLATE ])) self.swift.register( 'PUT', '/v1/AUTH_test/bucket/heartbeat-ok', @@ -734,7 +746,7 @@ class TestS3ApiMultiUpload(S3ApiTestCase): environ={'REQUEST_METHOD': 'POST'}, headers={'Authorization': 'AWS test:tester:hmac', 'Date': self.get_date_header(), }, - body=xml) + body=XML) status, headers, body = self.call_s3api(req) lines = body.split('\n') self.assertTrue(lines[0].startswith('%s' % s3_etag, body) + # NB: S3_ETAG includes quotes + self.assertIn('%s' % S3_ETAG, body) self.assertEqual(self.swift.calls, [ ('HEAD', '/v1/AUTH_test/bucket'), ('HEAD', '/v1/AUTH_test/bucket+segments/heartbeat-ok/X'), @@ -763,7 +775,7 @@ class TestS3ApiMultiUpload(S3ApiTestCase): json.dumps([ {'name': item[0].replace('object', 'heartbeat-fail'), 'last_modified': item[1], 'hash': item[2], 'bytes': item[3]} - for item in objects_template + for item in OBJECTS_TEMPLATE ])) self.swift.register( 'PUT', '/v1/AUTH_test/bucket/heartbeat-fail', @@ -783,7 +795,7 @@ class TestS3ApiMultiUpload(S3ApiTestCase): environ={'REQUEST_METHOD': 'POST'}, headers={'Authorization': 'AWS test:tester:hmac', 'Date': self.get_date_header(), }, - body=xml) + body=XML) status, headers, body = self.call_s3api(req) lines = body.split('\n') self.assertTrue(lines[0].startswith('