18d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# -*- coding: utf-8 -*- 28d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# Copyright (c) 2006-2011 Mitch Garnaat http://garnaat.org/ 38d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# 48d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# Permission is hereby granted, free of charge, to any person obtaining a 58d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# copy of this software and associated documentation files (the 68d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# "Software"), to deal in the Software without restriction, including 78d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# without limitation the rights to use, copy, modify, merge, publish, dis- 88d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# tribute, sublicense, and/or sell copies of the Software, and to permit 98d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# persons to whom the Software is furnished to do so, subject to the fol- 108d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# lowing conditions: 118d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# 128d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# The above copyright notice and this permission notice shall be included 138d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# in all copies or substantial portions of the Software. 148d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# 158d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 168d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- 178d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 188d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 198d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 208d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 218d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# IN THE SOFTWARE. 228d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 238d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi""" 248d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi KandoiSome unit tests for the S3Connection 258d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi""" 268d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoiimport unittest 278d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoiimport time 288d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoiimport os 298d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 308d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoifrom boto.s3.connection import S3Connection 318d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoifrom boto.s3.bucket import Bucket 328d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoifrom boto.exception import S3PermissionsError, S3ResponseError 338d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoifrom boto.compat import http_client, six, urlopen, urlsplit 348d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 358d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 368d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoiclass S3ConnectionTest (unittest.TestCase): 378d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi s3 = True 388d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 398d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi def test_1_basic(self): 408d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi print('--- running S3Connection tests ---') 418d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi c = S3Connection() 428d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi # create a new, empty bucket 438d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi bucket_name = 'test-%d' % int(time.time()) 448d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi bucket = c.create_bucket(bucket_name) 458d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi # now try a get_bucket call and see if it's really there 468d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi bucket = c.get_bucket(bucket_name) 478d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi # test logging 488d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi logging_bucket = c.create_bucket(bucket_name + '-log') 498d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi logging_bucket.set_as_logging_target() 508d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi bucket.enable_logging(target_bucket=logging_bucket, target_prefix=bucket.name) 518d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi bucket.disable_logging() 528d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi c.delete_bucket(logging_bucket) 538d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi k = bucket.new_key('foobar') 548d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi s1 = 'This is a test of file upload and download' 558d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi s2 = 'This is a second string to test file upload and download' 568d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi k.set_contents_from_string(s1) 578d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi fp = open('foobar', 'wb') 588d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi # now get the contents from s3 to a local file 598d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi k.get_contents_to_file(fp) 608d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi fp.close() 618d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi fp = open('foobar') 628d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi # check to make sure content read from s3 is identical to original 638d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi assert s1 == fp.read(), 'corrupted file' 648d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi fp.close() 658d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi # test generated URLs 668d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi url = k.generate_url(3600) 678d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi file = urlopen(url) 688d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi assert s1 == file.read().decode('utf-8'), 'invalid URL %s' % url 698d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi url = k.generate_url(3600, force_http=True) 708d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi file = urlopen(url) 718d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi assert s1 == file.read().decode('utf-8'), 'invalid URL %s' % url 728d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi url = k.generate_url(3600, force_http=True, headers={'x-amz-x-token' : 'XYZ'}) 738d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi file = urlopen(url) 748d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi assert s1 == file.read().decode('utf-8'), 'invalid URL %s' % url 758d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi rh = {'response-content-disposition': 'attachment; filename="foo.txt"'} 768d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi url = k.generate_url(60, response_headers=rh) 778d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi file = urlopen(url) 788d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi assert s1 == file.read().decode('utf-8'), 'invalid URL %s' % url 798d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi #test whether amperands and to-be-escaped characters work in header filename 808d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi rh = {'response-content-disposition': 'attachment; filename="foo&z%20ar&ar&zar&bar.txt"'} 818d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi url = k.generate_url(60, response_headers=rh, force_http=True) 828d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi file = urlopen(url) 838d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi assert s1 == file.read().decode('utf-8'), 'invalid URL %s' % url 848d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi # overwrite foobar contents with a PUT 858d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi url = k.generate_url(3600, 'PUT', force_http=True, policy='private', reduced_redundancy=True) 868d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi up = urlsplit(url) 878d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi con = http_client.HTTPConnection(up.hostname, up.port) 888d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi con.request("PUT", up.path + '?' + up.query, body="hello there") 898d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi resp = con.getresponse() 908d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi assert 200 == resp.status 918d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi assert b"hello there" == k.get_contents_as_string() 928d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi bucket.delete_key(k) 938d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi # test a few variations on get_all_keys - first load some data 948d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi # for the first one, let's override the content type 958d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi phony_mimetype = 'application/x-boto-test' 968d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi headers = {'Content-Type': phony_mimetype} 978d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi k.name = 'foo/bar' 988d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi k.set_contents_from_string(s1, headers) 998d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi k.name = 'foo/bas' 1008d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi size = k.set_contents_from_filename('foobar') 1018d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi assert size == 42 1028d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi k.name = 'foo/bat' 1038d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi k.set_contents_from_string(s1) 1048d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi k.name = 'fie/bar' 1058d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi k.set_contents_from_string(s1) 1068d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi k.name = 'fie/bas' 1078d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi k.set_contents_from_string(s1) 1088d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi k.name = 'fie/bat' 1098d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi k.set_contents_from_string(s1) 1108d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi # try resetting the contents to another value 1118d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi md5 = k.md5 1128d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi k.set_contents_from_string(s2) 1138d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi assert k.md5 != md5 1148d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi os.unlink('foobar') 1158d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi all = bucket.get_all_keys() 1168d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi assert len(all) == 6 1178d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi rs = bucket.get_all_keys(prefix='foo') 1188d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi assert len(rs) == 3 1198d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi rs = bucket.get_all_keys(prefix='', delimiter='/') 1208d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi assert len(rs) == 2 1218d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi rs = bucket.get_all_keys(maxkeys=5) 1228d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi assert len(rs) == 5 1238d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi # test the lookup method 1248d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi k = bucket.lookup('foo/bar') 1258d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi assert isinstance(k, bucket.key_class) 1268d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi assert k.content_type == phony_mimetype 1278d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi k = bucket.lookup('notthere') 1288d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi assert k == None 1298d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi # try some metadata stuff 1308d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi k = bucket.new_key('has_metadata') 1318d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi mdkey1 = 'meta1' 1328d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi mdval1 = 'This is the first metadata value' 1338d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi k.set_metadata(mdkey1, mdval1) 1348d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi mdkey2 = 'meta2' 1358d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi mdval2 = 'This is the second metadata value' 1368d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi k.set_metadata(mdkey2, mdval2) 1378d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi # try a unicode metadata value 1388d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi mdval3 = u'föö' 1398d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi mdkey3 = 'meta3' 1408d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi k.set_metadata(mdkey3, mdval3) 1418d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi k.set_contents_from_string(s1) 1428d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi k = bucket.lookup('has_metadata') 1438d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi assert k.get_metadata(mdkey1) == mdval1 1448d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi assert k.get_metadata(mdkey2) == mdval2 1458d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi assert k.get_metadata(mdkey3) == mdval3 1468d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi k = bucket.new_key('has_metadata') 1478d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi k.get_contents_as_string() 1488d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi assert k.get_metadata(mdkey1) == mdval1 1498d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi assert k.get_metadata(mdkey2) == mdval2 1508d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi assert k.get_metadata(mdkey3) == mdval3 1518d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi bucket.delete_key(k) 1528d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi # test list and iterator 1538d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi rs1 = bucket.list() 1548d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi num_iter = 0 1558d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi for r in rs1: 1568d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi num_iter = num_iter + 1 1578d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi rs = bucket.get_all_keys() 1588d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi num_keys = len(rs) 1598d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi assert num_iter == num_keys 1608d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi # try a key with a funny character 1618d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi k = bucket.new_key('testnewline\n') 1628d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi k.set_contents_from_string('This is a test') 1638d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi rs = bucket.get_all_keys() 1648d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi assert len(rs) == num_keys + 1 1658d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi bucket.delete_key(k) 1668d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi rs = bucket.get_all_keys() 1678d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi assert len(rs) == num_keys 1688d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi # try some acl stuff 1698d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi bucket.set_acl('public-read') 1708d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi policy = bucket.get_acl() 1718d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi assert len(policy.acl.grants) == 2 1728d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi bucket.set_acl('private') 1738d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi policy = bucket.get_acl() 1748d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi assert len(policy.acl.grants) == 1 1758d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi k = bucket.lookup('foo/bar') 1768d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi k.set_acl('public-read') 1778d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi policy = k.get_acl() 1788d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi assert len(policy.acl.grants) == 2 1798d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi k.set_acl('private') 1808d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi policy = k.get_acl() 1818d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi assert len(policy.acl.grants) == 1 1828d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi # try the convenience methods for grants 1838d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi bucket.add_user_grant('FULL_CONTROL', 1848d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 'c1e724fbfa0979a4448393c59a8c055011f739b6d102fb37a65f26414653cd67') 1858d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi try: 1868d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi bucket.add_email_grant('foobar', 'foo@bar.com') 1878d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi except S3PermissionsError: 1888d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi pass 1898d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi # now try to create an RRS key 1908d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi k = bucket.new_key('reduced_redundancy') 1918d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi k.set_contents_from_string('This key has reduced redundancy', 1928d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi reduced_redundancy=True) 1938d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 1948d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi # now try to inject a response header 1958d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi data = k.get_contents_as_string(response_headers={'response-content-type' : 'foo/bar'}) 1968d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi assert k.content_type == 'foo/bar' 1978d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 1988d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi # now delete all keys in bucket 1998d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi for k in bucket: 2008d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi if k.name == 'reduced_redundancy': 2018d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi assert k.storage_class == 'REDUCED_REDUNDANCY' 2028d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi bucket.delete_key(k) 2038d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi # now delete bucket 2048d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi time.sleep(5) 2058d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi c.delete_bucket(bucket) 2068d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi print('--- tests completed ---') 2078d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 2088d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi def test_basic_anon(self): 2098d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi auth_con = S3Connection() 2108d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi # create a new, empty bucket 2118d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi bucket_name = 'test-%d' % int(time.time()) 2128d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi auth_bucket = auth_con.create_bucket(bucket_name) 2138d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 2148d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi # try read the bucket anonymously 2158d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi anon_con = S3Connection(anon=True) 2168d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi anon_bucket = Bucket(anon_con, bucket_name) 2178d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi try: 2188d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi next(iter(anon_bucket.list())) 2198d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.fail("anon bucket list should fail") 2208d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi except S3ResponseError: 2218d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi pass 2228d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 2238d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi # give bucket anon user access and anon read again 2248d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi auth_bucket.set_acl('public-read') 2258d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi time.sleep(5) 2268d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi try: 2278d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi next(iter(anon_bucket.list())) 2288d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.fail("not expecting contents") 2298d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi except S3ResponseError as e: 2308d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.fail("We should have public-read access, but received " 2318d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi "an error: %s" % e) 2328d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi except StopIteration: 2338d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi pass 2348d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 2358d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi # cleanup 2368d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi auth_con.delete_bucket(auth_bucket) 2378d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 2388d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi def test_error_code_populated(self): 2398d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi c = S3Connection() 2408d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi try: 2418d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi c.create_bucket('bad$bucket$name') 2428d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi except S3ResponseError as e: 2438d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.assertEqual(e.error_code, 'InvalidBucketName') 2448d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi else: 2458d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.fail("S3ResponseError not raised.") 246