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