def test_bucket_GET_is_truncated(self): bucket_name = 'junk' req = Request.blank('/%s?max-keys=5' % bucket_name, environ={'REQUEST_METHOD': 'GET'}, headers={'Authorization': 'AWS test:tester:hmac', 'Date': self.get_date_header()}) status, headers, body = self.call_swift3(req) elem = fromstring(body, 'ListBucketResult') self.assertEqual(elem.find('./IsTruncated').text, 'false') req = Request.blank('/%s?max-keys=4' % bucket_name, environ={'REQUEST_METHOD': 'GET'}, headers={'Authorization': 'AWS test:tester:hmac', 'Date': self.get_date_header()}) status, headers, body = self.call_swift3(req) elem = fromstring(body, 'ListBucketResult') self.assertEqual(elem.find('./IsTruncated').text, 'true') req = Request.blank('/subdirs?delimiter=/&max-keys=2', environ={'REQUEST_METHOD': 'GET'}, headers={'Authorization': 'AWS test:tester:hmac', 'Date': self.get_date_header()}) status, headers, body = self.call_swift3(req) elem = fromstring(body, 'ListBucketResult') self.assertEqual(elem.find('./IsTruncated').text, 'true') self.assertEqual(elem.find('./NextMarker').text, 'but/')
def test_service(self): # GET Service(without bucket) status, headers, body = self.conn.make_request('GET') self.assertEquals(status, 200) self.assertCommonResponseHeaders(headers) self.assertTrue(headers['content-type'] is not None) # TODO; requires consideration # self.assertEquasl(headers['transfer-encoding'], 'chunked') elem = fromstring(body, 'ListAllMyBucketsResult') buckets = elem.findall('./Buckets/Bucket') self.assertEquals(list(buckets), []) owner = elem.find('Owner') self.assertEquals(self.conn.user_id, owner.find('ID').text) self.assertEquals(self.conn.user_id, owner.find('DisplayName').text) # GET Service(with Bucket) req_buckets = ('bucket', 'bucket2') for bucket in req_buckets: self.conn.make_request('PUT', bucket) status, headers, body = self.conn.make_request('GET') self.assertEquals(status, 200) elem = fromstring(body, 'ListAllMyBucketsResult') resp_buckets = elem.findall('./Buckets/Bucket') self.assertEquals(len(list(resp_buckets)), 2) for b in resp_buckets: self.assertTrue(b.find('Name').text in req_buckets) self.assertTrue(b.find('CreationDate') is not None)
def test_bucket_GET_v2_with_delimiter_max_keys(self): bucket_name = 'junk' req = Request.blank( '/%s?list-type=2&delimiter=a&max-keys=2' % bucket_name, environ={'REQUEST_METHOD': 'GET'}, headers={'Authorization': 'AWS test:tester:hmac', 'Date': self.get_date_header()}) status, headers, body = self.call_swift3(req) self.assertEqual(status.split()[0], '200') elem = fromstring(body, 'ListBucketResult') next_token = elem.find('./NextContinuationToken') self.assertIsNotNone(next_token) self.assertEqual(elem.find('./MaxKeys').text, '2') self.assertEqual(elem.find('./IsTruncated').text, 'true') req = Request.blank( '/%s?list-type=2&delimiter=a&max-keys=2&continuation-token=%s' % (bucket_name, next_token.text), environ={'REQUEST_METHOD': 'GET'}, headers={'Authorization': 'AWS test:tester:hmac', 'Date': self.get_date_header()}) status, headers, body = self.call_swift3(req) self.assertEqual(status.split()[0], '200') elem = fromstring(body, 'ListBucketResult') names = [o.find('./Key').text for o in elem.iterchildren('Contents')] self.assertEqual(names[0], 'lily')
def test_bucket_GET_v2_is_truncated(self): bucket_name = 'junk' req = Request.blank('/%s?list-type=2&max-keys=5' % bucket_name, environ={'REQUEST_METHOD': 'GET'}, headers={'Authorization': 'AWS test:tester:hmac', 'Date': self.get_date_header()}) status, headers, body = self.call_swift3(req) elem = fromstring(body, 'ListBucketResult') self.assertEqual(elem.find('./KeyCount').text, '5') self.assertEqual(elem.find('./IsTruncated').text, 'false') req = Request.blank('/%s?list-type=2&max-keys=4' % bucket_name, environ={'REQUEST_METHOD': 'GET'}, headers={'Authorization': 'AWS test:tester:hmac', 'Date': self.get_date_header()}) status, headers, body = self.call_swift3(req) elem = fromstring(body, 'ListBucketResult') self.assertIsNotNone(elem.find('./NextContinuationToken')) self.assertEqual(elem.find('./KeyCount').text, '4') self.assertEqual(elem.find('./IsTruncated').text, 'true') req = Request.blank('/subdirs?list-type=2&delimiter=/&max-keys=2', environ={'REQUEST_METHOD': 'GET'}, headers={'Authorization': 'AWS test:tester:hmac', 'Date': self.get_date_header()}) status, headers, body = self.call_swift3(req) elem = fromstring(body, 'ListBucketResult') self.assertIsNotNone(elem.find('./NextContinuationToken')) self.assertEqual(elem.find('./KeyCount').text, '2') self.assertEqual(elem.find('./IsTruncated').text, 'true')
def test_bucket_object_versions_GET_version_id_marker(self): req = Request.blank('/bucket?versions&version-id-marker=X', environ={'REQUEST_METHOD': 'GET'}, headers={'Authorization': 'AWS test:tester:hmac'}) status, headers, body = self.call_swift3(req) fromstring(body, 'ListVersionsResult') self.assertEquals(status.split()[0], '200')
def test_bucket_GET_v2_fetch_owner(self): bucket_name = 'junk' req = Request.blank('/%s?list-type=2' % bucket_name, environ={'REQUEST_METHOD': 'GET'}, headers={'Authorization': 'AWS test:tester:hmac', 'Date': self.get_date_header()}) status, headers, body = self.call_swift3(req) self.assertEqual(status.split()[0], '200') elem = fromstring(body, 'ListBucketResult') name = elem.find('./Name').text self.assertEqual(name, bucket_name) objects = elem.iterchildren('Contents') for o in objects: self.assertIsNone(o.find('./Owner')) req = Request.blank('/%s?list-type=2&fetch-owner=true' % bucket_name, environ={'REQUEST_METHOD': 'GET'}, headers={'Authorization': 'AWS test:tester:hmac', 'Date': self.get_date_header()}) status, headers, body = self.call_swift3(req) self.assertEqual(status.split()[0], '200') elem = fromstring(body, 'ListBucketResult') name = elem.find('./Name').text self.assertEqual(name, bucket_name) objects = elem.iterchildren('Contents') for o in objects: self.assertIsNotNone(o.find('./Owner'))
def test_xml_namespace(self): def test_xml(ns, prefix): return '<A %(ns)s><%(prefix)sB>C</%(prefix)sB></A>' % \ ({'ns': ns, 'prefix': prefix}) # No namespace is same as having the S3 namespace. xml = test_xml('', '') elem = etree.fromstring(xml) self.assertEqual(elem.find('./B').text, 'C') # The S3 namespace is handled as no namespace. xml = test_xml('xmlns="%s"' % etree.XMLNS_S3, '') elem = etree.fromstring(xml) self.assertEqual(elem.find('./B').text, 'C') xml = test_xml('xmlns:s3="%s"' % etree.XMLNS_S3, 's3:') elem = etree.fromstring(xml) self.assertEqual(elem.find('./B').text, 'C') # Any namespaces without a prefix work as no namespace. xml = test_xml('xmlns="http://example.com/"', '') elem = etree.fromstring(xml) self.assertEqual(elem.find('./B').text, 'C') xml = test_xml('xmlns:s3="http://example.com/"', 's3:') elem = etree.fromstring(xml) self.assertIsNone(elem.find('./B'))
def test_delete_multi_objects_with_quiet(self): bucket = 'bucket' put_objects = ['obj'] query = 'delete' # with Quiet true quiet = 'true' self._prepare_test_delete_multi_objects(bucket, put_objects) xml = self._gen_multi_delete_xml(put_objects, quiet) content_md5 = calculate_md5(xml) status, headers, body = \ self.conn.make_request('POST', bucket, body=xml, headers={'Content-MD5': content_md5}, query=query) self.assertEquals(status, 200) elem = fromstring(body, 'DeleteResult') resp_objects = elem.findall('Deleted') self.assertEquals(len(resp_objects), 0) # with Quiet false quiet = 'false' self._prepare_test_delete_multi_objects(bucket, put_objects) xml = self._gen_multi_delete_xml(put_objects, quiet) content_md5 = calculate_md5(xml) status, headers, body = \ self.conn.make_request('POST', bucket, body=xml, headers={'Content-MD5': content_md5}, query=query) self.assertEquals(status, 200) elem = fromstring(body, 'DeleteResult') resp_objects = elem.findall('Deleted') self.assertEquals(len(resp_objects), 1)
def test_object_versioning_GET(self): req = Request.blank('/bucket/object?versioning', environ={'REQUEST_METHOD': 'GET'}, headers={'Authorization': 'AWS test:tester:hmac'}) status, headers, body = self.call_swift3(req) self.assertEquals(status.split()[0], '200') fromstring(body, 'VersioningConfiguration')
def test_service(self): # GET Service(without bucket) status, headers, body = self.conn.make_request("GET") self.assertEquals(status, 200) self.assertCommonResponseHeaders(headers) self.assertTrue(headers["content-type"] is not None) # TODO; requires consideration # self.assertEquasl(headers['transfer-encoding'], 'chunked') elem = fromstring(body, "ListAllMyBucketsResult") buckets = elem.findall("./Buckets/Bucket") self.assertEquals(list(buckets), []) owner = elem.find("Owner") self.assertEquals(self.conn.user_id, owner.find("ID").text) self.assertEquals(self.conn.user_id, owner.find("DisplayName").text) # GET Service(with Bucket) req_buckets = ("bucket", "bucket2") for bucket in req_buckets: self.conn.make_request("PUT", bucket) status, headers, body = self.conn.make_request("GET") self.assertEquals(status, 200) elem = fromstring(body, "ListAllMyBucketsResult") resp_buckets = elem.findall("./Buckets/Bucket") self.assertEquals(len(list(resp_buckets)), 2) for b in resp_buckets: self.assertTrue(b.find("Name").text in req_buckets) self.assertTrue(b.find("CreationDate") is not None)
def test_bucket_GET_max_keys(self): bucket_name = 'junk' req = Request.blank('/%s?max-keys=5' % bucket_name, environ={'REQUEST_METHOD': 'GET'}, headers={'Authorization': 'AWS test:tester:hmac', 'Date': self.get_date_header()}) status, headers, body = self.call_swift3(req) elem = fromstring(body, 'ListBucketResult') self.assertEquals(elem.find('./MaxKeys').text, '5') _, path = self.swift.calls[-1] _, query_string = path.split('?') args = dict(cgi.parse_qsl(query_string)) self.assert_(args['limit'] == '6') req = Request.blank('/%s?max-keys=5000' % bucket_name, environ={'REQUEST_METHOD': 'GET'}, headers={'Authorization': 'AWS test:tester:hmac', 'Date': self.get_date_header()}) status, headers, body = self.call_swift3(req) elem = fromstring(body, 'ListBucketResult') self.assertEquals(elem.find('./MaxKeys').text, '5000') _, path = self.swift.calls[-1] _, query_string = path.split('?') args = dict(cgi.parse_qsl(query_string)) self.assertEquals(args['limit'], '1001')
def test_bucket_multipart_uploads_GET_with_prefix(self): req = Request.blank('/bucket/?uploads&prefix=X', environ={'REQUEST_METHOD': 'GET'}, headers={'Authorization': 'AWS test:tester:hmac'}) status, headers, body = self.call_swift3(req) fromstring(body, 'ListMultipartUploadsResult') self.assertEquals(status.split()[0], '200')
def test_bucket_object_versions_GET_common_prefix(self): req = Request.blank('/bucket?versions&prefix=photos/2006/&delimiter=/', environ={'REQUEST_METHOD': 'GET'}, headers={'Authorization': 'AWS test:tester:hmac'}) status, headers, body = self.call_swift3(req) fromstring(body, 'ListVersionsResult') self.assertEquals(status.split()[0], '200')
def test_bucket_versioning_GET(self): req = Request.blank('/bucket?versioning', environ={'REQUEST_METHOD': 'GET'}, headers={'Authorization': 'AWS test:tester:hmac', 'Date': self.get_date_header()}) status, headers, body = self.call_swift3(req) fromstring(body, 'VersioningConfiguration')
def test_object_list_parts_same_max_marts_as_objects_num(self): req = Request.blank('/bucket/object?uploadId=X&max-parts=3', environ={'REQUEST_METHOD': 'GET'}, headers={'Authorization': 'AWS test:tester:hmac'}) status, headers, body = self.call_swift3(req) fromstring(body, 'ListPartsResult') self.assertEquals(status.split()[0], '200')
def test_object_multipart_upload_initiate(self): req = Request.blank('/bucket/object?uploads', environ={'REQUEST_METHOD': 'POST'}, headers={'Authorization': 'AWS test:tester:hmac'}) status, headers, body = self.call_swift3(req) fromstring(body, 'InitiateMultipartUploadResult') self.assertEquals(status.split()[0], '200')
def test_object_list_parts_invalid_part_number_marker(self): req = Request.blank('/bucket/object?uploadId=X&part-number-marker=' 'invalid', environ={'REQUEST_METHOD': 'GET'}, headers={'Authorization': 'AWS test:tester:hmac'}) status, headers, body = self.call_swift3(req) fromstring(body, 'ListPartsResult') self.assertEquals(status.split()[0], '200')
def test_get_bucket_v2_with_continuation_token(self): bucket = 'bucket' put_objects = ('object', 'object2', 'subdir/object', 'subdir2/object', 'dir/subdir/object') self._prepare_test_get_bucket(bucket, put_objects) query = 'list-type=2&max-keys=3' expect_objects = ('dir/subdir/object', 'object', 'object2') status, headers, body = \ self.conn.make_request('GET', bucket, query=query) self.assertEqual(status, 200) elem = fromstring(body, 'ListBucketResult') self.assertEqual(elem.find('MaxKeys').text, '3') self.assertEqual(elem.find('KeyCount').text, '3') self.assertEqual(elem.find('IsTruncated').text, 'true') next_cont_token_elem = elem.find('NextContinuationToken') self.assertIsNotNone(next_cont_token_elem) resp_objects = elem.findall('./Contents') self.assertEqual(len(list(resp_objects)), len(expect_objects)) for i, o in enumerate(resp_objects): self.assertEqual(o.find('Key').text, expect_objects[i]) self.assertTrue(o.find('LastModified').text is not None) self.assertRegexpMatches( o.find('LastModified').text, r'^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$') self.assertTrue(o.find('ETag').text is not None) self.assertTrue(o.find('Size').text is not None) self.assertEqual(o.find('StorageClass').text, 'STANDARD') self.assertIsNone(o.find('Owner/ID')) self.assertIsNone(o.find('Owner/DisplayName')) query = 'list-type=2&max-keys=3&continuation-token=%s' % \ next_cont_token_elem.text expect_objects = ('subdir/object', 'subdir2/object') status, headers, body = \ self.conn.make_request('GET', bucket, query=query) self.assertEqual(status, 200) elem = fromstring(body, 'ListBucketResult') self.assertEqual(elem.find('MaxKeys').text, '3') self.assertEqual(elem.find('KeyCount').text, '2') self.assertEqual(elem.find('IsTruncated').text, 'false') self.assertIsNone(elem.find('NextContinuationToken')) cont_token_elem = elem.find('ContinuationToken') self.assertEqual(cont_token_elem.text, next_cont_token_elem.text) resp_objects = elem.findall('./Contents') self.assertEqual(len(list(resp_objects)), len(expect_objects)) for i, o in enumerate(resp_objects): self.assertEqual(o.find('Key').text, expect_objects[i]) self.assertTrue(o.find('LastModified').text is not None) self.assertRegexpMatches( o.find('LastModified').text, r'^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$') self.assertTrue(o.find('ETag').text is not None) self.assertTrue(o.find('Size').text is not None) self.assertEqual(o.find('StorageClass').text, 'STANDARD') self.assertIsNone(o.find('Owner/ID')) self.assertIsNone(o.find('Owner/DisplayName'))
def test_object_PUT_copy_to_itself(self): req = Request.blank( '/bucket/object', environ={'REQUEST_METHOD': 'PUT'}, headers={'Authorization': 'AWS test:tester:hmac', 'X-Amz-Storage-Class': 'STANDARD', 'X-Amz-Copy-Source': '/bucket/object', 'x-amz-metadata-directive': 'REPLACE'}) req.date = datetime.now() req.content_type = 'text/plain' status, headers, body = self.call_swift3(req) fromstring(body, 'CopyObjectResult') self.assertEquals(status.split()[0], '200')
def test_object_PUT_copy_without_slash_prefix(self): req = Request.blank( '/bucket/object', environ={'REQUEST_METHOD': 'PUT'}, headers={'Authorization': 'AWS test:tester:hmac', 'X-Amz-Storage-Class': 'STANDARD', 'X-Amz-Copy-Source': 'some/source'}) req.date = datetime.now() req.content_type = 'text/plain' status, headers, body = self.call_swift3(req) fromstring(body, 'CopyObjectResult') self.assertEquals(status.split()[0], '200') headers = [h for m, p, h in self.app.calls_with_headers if m == 'PUT' and p == '/v1/AUTH_test/bucket/object'][-1] self.assertEquals(int(headers['Content-Length']), len('copy source'))
def test_upload_part_error(self): bucket = 'bucket' self.conn.make_request('PUT', bucket) query = 'uploads' key = 'obj' status, headers, body = \ self.conn.make_request('POST', bucket, key, query=query) elem = fromstring(body, 'InitiateMultipartUploadResult') upload_id = elem.find('UploadId').text query = 'partNumber=%s&uploadId=%s' % (1, upload_id) auth_error_conn = Connection(aws_secret_key='invalid') status, headers, body = \ auth_error_conn.make_request('PUT', bucket, key, query=query) self.assertEquals(get_error_code(body), 'SignatureDoesNotMatch') status, headers, body = \ self.conn.make_request('PUT', 'nothing', key, query=query) self.assertEquals(get_error_code(body), 'NoSuchBucket') query = 'partNumber=%s&uploadId=%s' % (1, 'nothing') status, headers, body = \ self.conn.make_request('PUT', bucket, key, query=query) self.assertEquals(get_error_code(body), 'NoSuchUpload') query = 'partNumber=%s&uploadId=%s' % (0, upload_id) status, headers, body = \ self.conn.make_request('PUT', bucket, key, query=query) self.assertEquals(get_error_code(body), 'InvalidArgument') err_msg = 'Part number must be an integer between 1 and' self.assertTrue(err_msg in get_error_msg(body))
def test_bucket_GET_is_truncated(self): bucket_name = 'junk' req = Request.blank('/%s?max-keys=5' % bucket_name, environ={'REQUEST_METHOD': 'GET'}, headers={'Authorization': 'AWS test:tester:hmac'}) status, headers, body = self.call_swift3(req) elem = fromstring(body, 'ListBucketResult') self.assertEquals(elem.find('./IsTruncated').text, 'false') req = Request.blank('/%s?max-keys=4' % bucket_name, environ={'REQUEST_METHOD': 'GET'}, headers={'Authorization': 'AWS test:tester:hmac'}) status, headers, body = self.call_swift3(req) elem = fromstring(body, 'ListBucketResult') self.assertEquals(elem.find('./IsTruncated').text, 'true')
def test_bucket_versioning_GET(self): req = Request.blank('/bucket?versioning', environ={'REQUEST_METHOD': 'GET'}, headers={'Authorization': 'AWS test:tester:hmac'}) status, headers, body = self.call_swift3(req) elem = fromstring(body) self.assertEquals(elem.tag, 'VersioningConfiguration')
def get_acl(headers, body, bucket_owner, object_owner=None): """ Get ACL instance from S3 (e.g. x-amz-grant) headers or S3 acl xml body. """ acl = ACL.from_headers(headers, bucket_owner, object_owner, as_private=False) if acl is None: # Get acl from request body if possible. if not body: msg = 'Your request was missing a required header' raise MissingSecurityHeader(msg, missing_header_name='x-amz-acl') try: elem = fromstring(body, ACL.root_tag) acl = ACL.from_elem(elem) except(XMLSyntaxError, DocumentInvalid): raise MalformedACLError() except Exception as e: exc_type, exc_value, exc_traceback = sys.exc_info() LOGGER.error(e) raise exc_type, exc_value, exc_traceback else: if body: # Specifying grant with both header and xml is not allowed. raise UnexpectedContent() return acl
def test_bucket_GET(self): bucket_name = 'junk' req = Request.blank('/%s' % bucket_name, environ={'REQUEST_METHOD': 'GET'}, headers={'Authorization': 'AWS test:tester:hmac', 'Date': self.get_date_header()}) status, headers, body = self.call_swift3(req) self.assertEquals(status.split()[0], '200') elem = fromstring(body, 'ListBucketResult') name = elem.find('./Name').text self.assertEquals(name, bucket_name) objects = elem.iterchildren('Contents') names = [] for o in objects: names.append(o.find('./Key').text) self.assertEqual('2011-01-05T02:19:14.275Z', o.find('./LastModified').text) self.assertEqual('"0"', o.find('./ETag').text) self.assertEquals(len(names), len(self.objects)) for i in self.objects: self.assertTrue(i[0] in names)
def test_fromstring_with_nonascii_text(self): input_str = '<?xml version="1.0" encoding="UTF-8"?>\n' \ '<Test><FOO>\xef\xbc\xa1</FOO></Test>' elem = etree.fromstring(input_str) text = elem.find('FOO').text self.assertEqual(text, '\xef\xbc\xa1') self.assertTrue(isinstance(text, str))
def PUT(self, req): """ Handle PUT Bucket request """ xml = req.xml(MAX_PUT_BUCKET_BODY_SIZE) if xml: # check location try: elem = fromstring(xml, 'CreateBucketConfiguration') location = elem.find('./LocationConstraint').text except (XMLSyntaxError, DocumentInvalid): raise MalformedXML() except Exception as e: exc_type, exc_value, exc_traceback = sys.exc_info() LOGGER.error(e) raise exc_type, exc_value, exc_traceback if location != CONF.location: # Swift3 cannot support multiple regions currently. raise InvalidLocationConstraint() resp = req.get_response(self.app) resp.status = HTTP_OK resp.location = '/' + req.container_name return resp
def test_abort_multi_upload_error(self): bucket = 'bucket' self.conn.make_request('PUT', bucket) key = 'obj' query = 'uploads' status, headers, body = \ self.conn.make_request('POST', bucket, key, query=query) elem = fromstring(body, 'InitiateMultipartUploadResult') upload_id = elem.find('UploadId').text self._upload_part(bucket, key, upload_id) query = 'uploadId=%s' % upload_id auth_error_conn = Connection(aws_secret_key='invalid') status, headers, body = \ auth_error_conn.make_request('DELETE', bucket, key, query=query) self.assertEquals(get_error_code(body), 'SignatureDoesNotMatch') status, headers, body = \ self.conn.make_request('DELETE', 'nothing', key, query=query) self.assertEquals(get_error_code(body), 'NoSuchBucket') query = 'uploadId=%s' % 'nothing' status, headers, body = \ self.conn.make_request('DELETE', bucket, key, query=query) self.assertEquals(get_error_code(body), 'NoSuchUpload')
def test_object(self): obj = 'object' content = 'abc123' etag = md5(content).hexdigest() # PUT Object status, headers, body = \ self.conn.make_request('PUT', self.bucket, obj, body=content) self.assertEquals(status, 200) self.assertCommonResponseHeaders(headers) self.assertTrue('content-length' in headers) # sanity self.assertEquals(headers['content-length'], '0') self._assertObjectEtag(self.bucket, obj, etag) # PUT Object Copy dst_bucket = 'dst-bucket' dst_obj = 'dst_obj' self.conn.make_request('PUT', dst_bucket) headers = {'x-amz-copy-source': '/%s/%s' % (self.bucket, obj)} status, headers, body = \ self.conn.make_request('PUT', dst_bucket, dst_obj, headers=headers) self.assertEquals(status, 200) self.assertCommonResponseHeaders(headers) self.assertEquals(headers['content-length'], str(len(body))) elem = fromstring(body, 'CopyObjectResult') self.assertTrue(elem.find('LastModified').text is not None) # TODO: assert LastModified value self.assertTrue(elem.find('ETag').text is not None) self.assertEquals(etag, elem.find('ETag').text.strip('"')) self._assertObjectEtag(dst_bucket, dst_obj, etag) # GET Object status, headers, body = \ self.conn.make_request('GET', self.bucket, obj) self.assertEquals(status, 200) self.assertCommonResponseHeaders(headers, etag) self.assertTrue(headers['last-modified'] is not None) self.assertTrue(headers['content-type'] is not None) self.assertEquals(headers['content-length'], str(len(content))) # HEAD Object status, headers, body = \ self.conn.make_request('HEAD', self.bucket, obj) self.assertEquals(status, 200) self.assertCommonResponseHeaders(headers, etag) self.assertTrue(headers['last-modified'] is not None) self.assertTrue('content-type' in headers) self.assertEquals(headers['content-length'], str(len(content))) # DELETE Object status, headers, body = \ self.conn.make_request('DELETE', self.bucket, obj) self.assertEquals(status, 204) self.assertCommonResponseHeaders(headers)
def test_get_bucket_with_prefix(self): bucket = 'bucket' req_objects = ('object', 'object2', 'subdir/object', 'subdir2/object', 'dir/subdir/object') self._prepare_test_get_bucket(bucket, req_objects) prefix = 'object' query = 'prefix=%s' % prefix expect_objects = ('object', 'object2') status, headers, body = \ self.conn.make_request('GET', bucket, query=query) self.assertEquals(status, 200) elem = fromstring(body, 'ListBucketResult') self.assertEquals(elem.find('Prefix').text, prefix) resp_objects = elem.findall('./Contents') self.assertEquals(len(list(resp_objects)), len(expect_objects)) for i, o in enumerate(resp_objects): self.assertEquals(o.find('Key').text, expect_objects[i]) self.assertTrue(o.find('LastModified').text is not None) self.assertRegexpMatches( o.find('LastModified').text, r'^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$') self.assertTrue(o.find('ETag').text is not None) self.assertTrue(o.find('Size').text is not None) self.assertEquals(o.find('StorageClass').text, 'STANDARD') self.assertTrue(o.find('Owner/ID').text, self.conn.user_id) self.assertTrue(o.find('Owner/DisplayName').text, self.conn.user_id)
def test_object_list_parts_same_max_marts_as_objects_num(self): req = Request.blank('/bucket/object?uploadId=X&max-parts=2', environ={'REQUEST_METHOD': 'GET'}, headers={'Authorization': 'AWS test:tester:hmac'}) status, headers, body = self.call_swift3(req) elem = fromstring(body, 'ListPartsResult') self.assertEquals(len(elem.findall('Part')), 2) self.assertEquals(status.split()[0], '200')
def test_bucket_logging_GET(self): req = Request.blank('/bucket?logging', environ={'REQUEST_METHOD': 'GET'}, headers={'Authorization': 'AWS test:tester:hmac', 'Date': self.get_date_header()}) status, headers, body = self.call_swift3(req) xml = fromstring(body, 'BucketLoggingStatus') self.assertEquals(xml.keys(), []) self.assertEquals(status.split()[0], '200')
def test_object_multipart_upload_complete(self): xml = '<CompleteMultipartUpload>' \ '<Part>' \ '<PartNumber>1</PartNumber>' \ '<ETag>HASH</ETag>' \ '</Part>' \ '<Part>' \ '<PartNumber>2</PartNumber>' \ '<ETag>"HASH"</ETag>' \ '</Part>' \ '</CompleteMultipartUpload>' req = Request.blank('/bucket/object?uploadId=X', environ={'REQUEST_METHOD': 'POST'}, headers={'Authorization': 'AWS test:tester:hmac'}, body=xml) status, headers, body = self.call_swift3(req) fromstring(body, 'CompleteMultipartUploadResult') self.assertEquals(status.split()[0], '200')
def test_object_location(self): req = Request.blank('/bucket?location', environ={'REQUEST_METHOD': 'GET'}, headers={'Authorization': 'AWS test:tester:hmac'}) status, headers, body = self.call_swift3(req) self.assertEquals(status.split()[0], '200') elem = fromstring(body, 'LocationConstraint') location = elem.text self.assertEquals(location, None)
def test_unsupported_method(self): req = Request.blank('/bucket?acl', environ={'REQUEST_METHOD': 'POST'}, headers={'Authorization': 'AWS test:tester:hmac'}) status, headers, body = self.call_swift3(req) elem = fromstring(body, 'Error') self.assertEquals(elem.find('./Code').text, 'MethodNotAllowed') self.assertEquals(elem.find('./Method').text, 'POST') self.assertEquals(elem.find('./ResourceType').text, 'ACL')
def test_acl(self): self.conn.make_request('PUT', self.bucket, self.obj) query = 'acl' # PUT Bucket ACL headers = {'x-amz-acl': 'public-read'} status, headers, body = \ self.conn.make_request('PUT', self.bucket, headers=headers, query=query) self.assertEqual(status, 200) self.assertCommonResponseHeaders(headers) self.assertEqual(headers['content-length'], '0') # GET Bucket ACL status, headers, body = \ self.conn.make_request('GET', self.bucket, query=query) self.assertEqual(status, 200) self.assertCommonResponseHeaders(headers) # TODO: Fix the response that last-modified must be in the response. # self.assertTrue(headers['last-modified'] is not None) self.assertEqual(headers['content-length'], str(len(body))) self.assertTrue(headers['content-type'] is not None) elem = fromstring(body, 'AccessControlPolicy') owner = elem.find('Owner') self.assertEqual(owner.find('ID').text, self.conn.user_id) self.assertEqual(owner.find('DisplayName').text, self.conn.user_id) acl = elem.find('AccessControlList') self.assertTrue(acl.find('Grant') is not None) # GET Object ACL status, headers, body = \ self.conn.make_request('GET', self.bucket, self.obj, query=query) self.assertEqual(status, 200) self.assertCommonResponseHeaders(headers) # TODO: Fix the response that last-modified must be in the response. # self.assertTrue(headers['last-modified'] is not None) self.assertEqual(headers['content-length'], str(len(body))) self.assertTrue(headers['content-type'] is not None) elem = fromstring(body, 'AccessControlPolicy') owner = elem.find('Owner') self.assertEqual(owner.find('ID').text, self.conn.user_id) self.assertEqual(owner.find('DisplayName').text, self.conn.user_id) acl = elem.find('AccessControlList') self.assertTrue(acl.find('Grant') is not None)
def test_object_list_parts_without_encoding_type(self): self.swift.register('HEAD', '/v1/AUTH_test/bucket+segments/object@@/X', swob.HTTPOk, {}, None) req = Request.blank('/bucket/object@@?uploadId=X', environ={'REQUEST_METHOD': 'GET'}, headers={'Authorization': 'AWS test:tester:hmac'}) status, headers, body = self.call_swift3(req) elem = fromstring(body, 'ListPartsResult') self.assertEquals(elem.find('Key').text, 'object@@') self.assertEquals(status.split()[0], '200')
def test_object_multi_DELETE_without_permission(self): status, headers, body = self._test_object_multi_DELETE('test:other') self.assertEquals(status.split()[0], '200') elem = fromstring(body) errors = elem.findall('Error') self.assertEquals(len(errors), len(self.keys)) for e in errors: self.assertTrue(e.find('Key').text in self.keys) self.assertEquals(e.find('Code').text, 'AccessDenied') self.assertEquals(e.find('Message').text, 'Access Denied.')
def test_versioning_put(self): # Versioning not configured status, headers, body = self.conn.make_request('GET', 'bucket', query='versioning') self.assertEqual(status, 200) elem = fromstring(body) self.assertEqual(elem.getchildren(), []) # Enable versioning elem = Element('VersioningConfiguration') SubElement(elem, 'Status').text = 'Enabled' xml = tostring(elem) status, headers, body = self.conn.make_request('PUT', 'bucket', body=xml, query='versioning') self.assertEqual(status, 200) status, headers, body = self.conn.make_request('GET', 'bucket', query='versioning') self.assertEqual(status, 200) elem = fromstring(body) self.assertEqual(elem.find('./Status').text, 'Enabled') # Suspend versioning elem = Element('VersioningConfiguration') SubElement(elem, 'Status').text = 'Suspended' xml = tostring(elem) status, headers, body = self.conn.make_request('PUT', 'bucket', body=xml, query='versioning') self.assertEqual(status, 200) status, headers, body = self.conn.make_request('GET', 'bucket', query='versioning') self.assertEqual(status, 200) elem = fromstring(body) self.assertEqual(elem.find('./Status').text, 'Suspended')
def test_object_list_parts_with_part_number_marker(self): req = Request.blank( '/bucket/object?uploadId=X&' 'part-number-marker=1', environ={'REQUEST_METHOD': 'GET'}, headers={'Authorization': 'AWS test:tester:hmac'}) status, headers, body = self.call_swift3(req) elem = fromstring(body, 'ListPartsResult') self.assertEquals(len(elem.findall('Part')), 1) self.assertEquals(elem.find('Part/PartNumber').text, '2') self.assertEquals(status.split()[0], '200')
def test_bucket_multipart_uploads_GET_maxuploads(self): query = 'max-uploads=2' status, headers, body = \ self._test_bucket_multipart_uploads_GET(query) elem = fromstring(body, 'ListMultipartUploadsResult') self.assertEquals(len(elem.findall('Upload/UploadId')), 2) self.assertEquals(elem.find('NextKeyMarker').text, 'object') self.assertEquals(elem.find('NextUploadIdMarker').text, 'Y') self.assertEquals(elem.find('MaxUploads').text, '2') self.assertEquals(elem.find('IsTruncated').text, 'true') self.assertEquals(status.split()[0], '200')
def _versioning_GET_suspended(self, path): self.swift.register('HEAD', '/v1/AUTH_test/%s' % VERSIONING_BUCKET, HTTPNoContent, {}, None) self.swift.register('HEAD', '/v1/AUTH_test/bucket', HTTPNoContent, {}, None) status, headers, body = self._versioning_GET('/bucket/object') self.assertEqual(status.split()[0], '200') elem = fromstring(body, 'VersioningConfiguration') status = elem.find('./Status').text self.assertEqual(status, 'Suspended')
def test_object_multipart_upload_initiate_s3acl(self): req = Request.blank('/bucket/object?uploads', environ={'REQUEST_METHOD': 'POST'}, headers={ 'Authorization': 'AWS test:tester:hmac', 'x-amz-acl': 'public-read', 'x-amz-meta-foo': 'bar' }) status, headers, body = self.call_swift3(req) fromstring(body, 'InitiateMultipartUploadResult') self.assertEquals(status.split()[0], '200') _, _, req_headers = self.swift.calls_with_headers[-1] self.assertEquals(req_headers.get('X-Object-Meta-Foo'), 'bar') tmpacl_header = req_headers.get(sysmeta_header('object', 'tmpacl')) self.assertTrue(tmpacl_header) acl_header = encode_acl( 'object', ACLPublicRead(Owner('test:tester', 'test:tester'))) self.assertEquals(acl_header.get(sysmeta_header('object', 'acl')), tmpacl_header)
def test_bucket_GET_with_versions_versioning_not_configured(self): self.swift.register('GET', '/v1/AUTH_test/junk+versioning', swob.HTTPNotFound, {}, None) for obj in self.objects: self.swift.register('HEAD', '/v1/AUTH_test/junk/%s' % obj[0], swob.HTTPOk, {}, None) self.swift.register('HEAD', '/v1/AUTH_test/junk/viola', swob.HTTPOk, {}, None) req = Request.blank('/junk?versions', environ={'REQUEST_METHOD': 'GET'}, headers={ 'Authorization': 'AWS test:tester:hmac', 'Date': self.get_date_header() }) status, headers, body = self.call_swift3(req) self.assertEqual(status.split()[0], '200') elem = fromstring(body, 'ListVersionsResult') self.assertEqual(elem.find('./Name').text, 'junk') self.assertIsNone(elem.find('./Prefix').text) self.assertIsNone(elem.find('./KeyMarker').text) self.assertIsNone(elem.find('./VersionIdMarker').text) self.assertEqual(elem.find('./MaxKeys').text, '1000') self.assertEqual(elem.find('./IsTruncated').text, 'false') self.assertEqual(elem.findall('./DeleteMarker'), []) versions = elem.findall('./Version') objects = list(self.objects) objects.sort(key=lambda o: o[0]) self.assertEqual(len(versions), len(objects)) self.assertEqual([v.find('./Key').text for v in versions], [v[0] for v in objects]) self.assertEqual([v.find('./IsLatest').text for v in versions], ['true' for v in objects]) self.assertEqual([v.find('./VersionId').text for v in versions], ['null' for v in objects]) # Last modified in self.objects is 2011-01-05T02:19:14.275290 but # the returned value is 2011-01-05T02:19:14.275Z self.assertEqual([v.find('./LastModified').text for v in versions], [v[1][:-3] + 'Z' for v in objects]) self.assertEqual([v.find('./ETag').text for v in versions], [ PFS_ETAG if v[0] == 'pfs-obj' else '"0-N"' if v[0] == 'slo' else '"0"' for v in objects ]) self.assertEqual([v.find('./Size').text for v in versions], [str(v[3]) for v in objects]) self.assertEqual([v.find('./Owner/ID').text for v in versions], ['test:tester' for v in objects]) self.assertEqual( [v.find('./Owner/DisplayName').text for v in versions], ['test:tester' for v in objects]) self.assertEqual([v.find('./StorageClass').text for v in versions], ['STANDARD' for v in objects])
def test_object_PUT_copy_self(self): status, headers, body = \ self._test_object_PUT_copy_self(swob.HTTPOk) self.assertEqual(status.split()[0], '400') elem = fromstring(body, 'Error') err_msg = ("This copy request is illegal because it is trying to copy " "an object to itself without changing the object's " "metadata, storage class, website redirect location or " "encryption attributes.") self.assertEqual(elem.find('Code').text, 'InvalidRequest') self.assertEqual(elem.find('Message').text, err_msg)
def test_object_location_setting_as_us_west_1(self): CONF.location = 'us-west-1' req = Request.blank('/bucket?location', environ={'REQUEST_METHOD': 'GET'}, headers={'Authorization': 'AWS test:tester:hmac', 'Date': self.get_date_header()}) status, headers, body = self.call_swift3(req) self.assertEquals(status.split()[0], '200') elem = fromstring(body, 'LocationConstraint') location = elem.text self.assertEquals(location, 'us-west-1')
def test_bucket_GET_subdir_with_delimiter_max_keys(self): bucket_name = 'junk_subdir' req = Request.blank('/%s?delimiter=a&max-keys=1' % bucket_name, environ={'REQUEST_METHOD': 'GET'}, headers={'Authorization': 'AWS test:tester:hmac'}) status, headers, body = self.call_swift3(req) self.assertEquals(status.split()[0], '200') elem = fromstring(body, 'ListBucketResult') self.assertEquals(elem.find('./NextMarker').text, 'rose') self.assertEquals(elem.find('./MaxKeys').text, '1') self.assertEquals(elem.find('./IsTruncated').text, 'true')
def test_bucket_GET_v2_is_truncated(self): bucket_name = 'junk' req = Request.blank('/%s?list-type=2&max-keys=%d' % (bucket_name, len(self.objects)), environ={'REQUEST_METHOD': 'GET'}, headers={ 'Authorization': 'AWS test:tester:hmac', 'Date': self.get_date_header() }) status, headers, body = self.call_swift3(req) elem = fromstring(body, 'ListBucketResult') self.assertEqual(elem.find('./KeyCount').text, str(len(self.objects))) self.assertEqual(elem.find('./IsTruncated').text, 'false') req = Request.blank('/%s?list-type=2&max-keys=%d' % (bucket_name, len(self.objects) - 1), environ={'REQUEST_METHOD': 'GET'}, headers={ 'Authorization': 'AWS test:tester:hmac', 'Date': self.get_date_header() }) status, headers, body = self.call_swift3(req) elem = fromstring(body, 'ListBucketResult') self.assertEqual( elem.find('./NextContinuationToken').text, 'd2l0aCBzcGFjZQ==') self.assertEqual( elem.find('./KeyCount').text, str(len(self.objects) - 1)) self.assertEqual(elem.find('./IsTruncated').text, 'true') req = Request.blank('/subdirs?list-type=2&delimiter=/&max-keys=2', environ={'REQUEST_METHOD': 'GET'}, headers={ 'Authorization': 'AWS test:tester:hmac', 'Date': self.get_date_header() }) status, headers, body = self.call_swift3(req) elem = fromstring(body, 'ListBucketResult') self.assertEqual(elem.find('./NextContinuationToken').text, 'YnV0Lw==') self.assertEqual(elem.find('./KeyCount').text, '2') self.assertEqual(elem.find('./IsTruncated').text, 'true')
def _upload_part_copy(self, src_bucket, src_obj, dst_bucket, dst_key, upload_id, part_num=1): src_path = '%s/%s' % (src_bucket, src_obj) query = 'partNumber=%s&uploadId=%s' % (part_num, upload_id) status, headers, body = \ self.conn.make_request('PUT', dst_bucket, dst_key, headers={'X-Amz-Copy-Source': src_path}, query=query) elem = fromstring(body, 'CopyPartResult') etag = elem.find('ETag').text.strip('"') return status, headers, body, etag
def test_delete_bucket_multi_upload_object_exisiting(self): bucket = 'bucket' keys = ['obj1'] uploads = [] results_generator = self._initiate_multi_uploads_result_generator( bucket, keys) # Initiate Multipart Upload for expected_key, (status, _, body) in \ izip(keys, results_generator): self.assertEqual(status, 200) # sanity elem = fromstring(body, 'InitiateMultipartUploadResult') key = elem.find('Key').text self.assertEqual(expected_key, key) # sanity upload_id = elem.find('UploadId').text self.assertTrue(upload_id is not None) # sanity self.assertTrue((key, upload_id) not in uploads) uploads.append((key, upload_id)) self.assertEqual(len(uploads), len(keys)) # sanity # Upload Part key, upload_id = uploads[0] content = 'a' * MIN_SEGMENT_SIZE status, headers, body = \ self._upload_part(bucket, key, upload_id, content) self.assertEqual(status, 200) # Complete Multipart Upload key, upload_id = uploads[0] etags = [md5(content).hexdigest()] xml = self._gen_comp_xml(etags) status, headers, body = \ self._complete_multi_upload(bucket, key, upload_id, xml) self.assertEqual(status, 200) # sanity # GET multipart object status, headers, body = \ self.conn.make_request('GET', bucket, key) self.assertEqual(status, 200) # sanity self.assertEqual(content, body) # sanity # DELETE bucket while the object existing status, headers, body = \ self.conn.make_request('DELETE', bucket) self.assertEqual(status, 409) # sanity # The object must still be there. status, headers, body = \ self.conn.make_request('GET', bucket, key) self.assertEqual(status, 200) # sanity self.assertEqual(content, body) # sanity
def test_get_bucket_with_encoding_type(self): bucket = 'bucket' put_objects = ('object', 'object2') self._prepare_test_get_bucket(bucket, put_objects) encoding_type = 'url' query = 'encoding-type=%s' % encoding_type status, headers, body = \ self.conn.make_request('GET', bucket, query=query) self.assertEqual(status, 200) elem = fromstring(body, 'ListBucketResult') self.assertEqual(elem.find('EncodingType').text, encoding_type)
def test_bucket_GET_is_truncated(self): bucket_name = 'junk' req = Request.blank('/%s' % bucket_name, environ={ 'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'max-keys=5' }, headers={'Authorization': 'AWS test:tester:hmac'}) status, headers, body = self.call_swift3(req) elem = fromstring(body, 'ListBucketResult') self.assertEquals(elem.find('./IsTruncated').text, 'false') req = Request.blank('/%s' % bucket_name, environ={ 'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'max-keys=4' }, headers={'Authorization': 'AWS test:tester:hmac'}) status, headers, body = self.call_swift3(req) elem = fromstring(body, 'ListBucketResult') self.assertEquals(elem.find('./IsTruncated').text, 'true')
def test_object_PUT_copy(self): last_modified = '2014-04-01T12:00:00.000Z' status, headers, body = self._test_object_PUT_copy(swob.HTTPOk) self.assertEquals(status.split()[0], '200') self.assertEquals(headers['Content-Type'], 'application/xml') self.assertTrue(headers.get('etag') is None) self.assertTrue(headers.get('x-amz-meta-something') is None) elem = fromstring(body, 'CopyObjectResult') self.assertEquals(elem.find('LastModified').text, last_modified) self.assertEquals(elem.find('ETag').text, '"%s"' % self.etag) _, _, headers = self.swift.calls_with_headers[-1] self.assertEquals(headers['X-Copy-From'], '/some/source') self.assertEquals(headers['Content-Length'], '0')
def test_upload_part_copy(self): iso_format = '2014-04-01T12:00:00.000Z' status, headers, body = \ self._test_copy_for_s3acl('test:tester') self.assertEquals(status.split()[0], '200') self.assertEquals(headers['Content-Type'], 'application/xml') self.assertTrue(headers.get('etag') is None) elem = fromstring(body, 'CopyPartResult') self.assertEquals(elem.find('LastModified').text, iso_format) self.assertEquals(elem.find('ETag').text, '"%s"' % self.etag) _, _, headers = self.swift.calls_with_headers[-1] self.assertEquals(headers['X-Copy-From'], '/src_bucket/src_obj') self.assertEquals(headers['Content-Length'], '0')
def test_object_multipart_upload_complete_s3acl(self): acl_headers = encode_acl( 'object', ACLPublicRead(Owner('test:tester', 'test:tester'))) headers = {} headers[sysmeta_header('object', 'tmpacl')] = \ acl_headers.get(sysmeta_header('object', 'acl')) headers['X-Object-Meta-Foo'] = 'bar' self.swift.register('HEAD', '/v1/AUTH_test/bucket+segments/object/X', swob.HTTPOk, headers, None) req = Request.blank('/bucket/object?uploadId=X', environ={'REQUEST_METHOD': 'POST'}, headers={'Authorization': 'AWS test:tester:hmac'}, body=xml) status, headers, body = self.call_swift3(req) fromstring(body, 'CompleteMultipartUploadResult') self.assertEquals(status.split()[0], '200') _, _, headers = self.swift.calls_with_headers[-2] self.assertEquals(headers.get('X-Object-Meta-Foo'), 'bar') self.assertEquals( tostring( ACLPublicRead(Owner('test:tester', 'test:tester')).elem()), tostring(decode_acl('object', headers).elem()))
def _versioning_GET_enabled(self, path): self.swift.register('HEAD', '/v1/AUTH_test/%s' % VERSIONING_BUCKET, HTTPNoContent, {}, None) self.swift.register( 'HEAD', '/v1/AUTH_test/bucket', HTTPNoContent, { 'X-Container-Sysmeta-Versions-Location': VERSIONING_BUCKET, 'X-Container-Sysmeta-Versions-Mode': 'history', }, None) status, headers, body = self._versioning_GET(path) self.assertEqual(status.split()[0], '200') elem = fromstring(body, 'VersioningConfiguration') status = elem.find('./Status').text self.assertEqual(status, 'Enabled')
def test_bucket_GET_max_keys(self): bucket_name = 'junk' req = Request.blank('/%s?max-keys=5' % bucket_name, environ={'REQUEST_METHOD': 'GET'}, headers={'Authorization': 'AWS test:tester:hmac'}) status, headers, body = self.call_swift3(req) elem = fromstring(body, 'ListBucketResult') self.assertEquals(elem.find('./MaxKeys').text, '5') _, path = self.swift.calls[-1] _, query_string = path.split('?') args = dict(cgi.parse_qsl(query_string)) self.assert_(args['limit'] == '6') req = Request.blank('/%s?max-keys=5000' % bucket_name, environ={'REQUEST_METHOD': 'GET'}, headers={'Authorization': 'AWS test:tester:hmac'}) status, headers, body = self.call_swift3(req) elem = fromstring(body, 'ListBucketResult') self.assertEquals(elem.find('./MaxKeys').text, '1000') _, path = self.swift.calls[-1] _, query_string = path.split('?') args = dict(cgi.parse_qsl(query_string)) self.assertEquals(args['limit'], '1001')
def PUT(self, req): # pylint: disable=invalid-name """ Handles PUT Bucket tagging and PUT Object tagging. """ body = req.xml(MAX_TAGGING_BODY_SIZE) try: # Just validate the body fromstring(body, 'Tagging') except (DocumentInvalid, XMLSyntaxError) as exc: raise MalformedXML(str(exc)) if req.object_name: req.headers[OBJECT_TAGGING_HEADER] = body else: req.headers[BUCKET_TAGGING_HEADER] = body resp = req.get_versioned_response(self.app, 'POST', req.container_name, req.object_name) if resp.status_int == 202: headers = dict() if req.object_name: headers['x-amz-version-id'] = \ resp.sw_headers[VERSION_ID_HEADER] return HTTPOk(headers=headers) return resp
def test_object_PUT_copy_self_metadata_replace(self): last_modified = '2014-04-01T12:00:00.000Z' header = {'x-amz-metadata-directive': 'REPLACE'} status, headers, body = \ self._test_object_PUT_copy_self(swob.HTTPOk, header) self.assertEquals(status.split()[0], '200') self.assertEquals(headers['Content-Type'], 'application/xml') self.assertTrue(headers.get('etag') is None) elem = fromstring(body, 'CopyObjectResult') self.assertEquals(elem.find('LastModified').text, last_modified) self.assertEquals(elem.find('ETag').text, '"%s"' % self.etag) _, _, headers = self.swift.calls_with_headers[-1] self.assertEquals(headers['X-Copy-From'], '/bucket/object') self.assertEquals(headers['Content-Length'], '0')
def _validate_tagset(self, body, empty=False): root = fromstring(body, 'Tagging') tagset = root.find('./TagSet') self.assertIsNotNone(tagset) tag = tagset.find('./Tag') if empty: self.assertIsNone(tag) else: self.assertIsNotNone(tag) key = tag.find('./Key') value = tag.find('./Value') self.assertIsNotNone(key) self.assertIsNotNone(value) self.assertEqual('organization', key.text) self.assertEqual('marketing', value.text)