diff options
| author | Craig Jackson | 2011-12-13 14:46:59 -0700 |
|---|---|---|
| committer | Craig Jackson | 2011-12-13 14:46:59 -0700 |
| commit | 647c078f0c801eb9fa63dfc7ba3c017b30e4d467 (patch) | |
| tree | a13b16dbd41bb39269c7649fcc2f2ad77137500a /src/amazons3/s3-test.py | |
| parent | db95070a37f70a00f80a1a2a9ba732c55f6bee1b (diff) | |
| download | amazons3-py-647c078f0c801eb9fa63dfc7ba3c017b30e4d467.tar.gz amazons3-py-647c078f0c801eb9fa63dfc7ba3c017b30e4d467.zip | |
Made the project available in pypi. Involved moving files and
initializing a setup.py.
Diffstat (limited to 'src/amazons3/s3-test.py')
| -rw-r--r-- | src/amazons3/s3-test.py | 267 |
1 files changed, 267 insertions, 0 deletions
diff --git a/src/amazons3/s3-test.py b/src/amazons3/s3-test.py new file mode 100644 index 0000000..fbd8d9c --- /dev/null +++ b/src/amazons3/s3-test.py | |||
| @@ -0,0 +1,267 @@ | |||
| 1 | #!/usr/bin/env python | ||
| 2 | |||
| 3 | # This software code is made available "AS IS" without warranties of any | ||
| 4 | # kind. You may copy, display, modify and redistribute the software | ||
| 5 | # code either by itself or as incorporated into your code; provided that | ||
| 6 | # you do not remove any proprietary notices. Your use of this software | ||
| 7 | # code is at your own risk and you waive any claim against Amazon | ||
| 8 | # Digital Services, Inc. or its affiliates with respect to your use of | ||
| 9 | # this software code. (c) 2006-2007 Amazon Digital Services, Inc. or its | ||
| 10 | # affiliates. | ||
| 11 | |||
| 12 | import unittest | ||
| 13 | import S3 | ||
| 14 | import httplib | ||
| 15 | import sys | ||
| 16 | |||
| 17 | AWS_ACCESS_KEY_ID = '<INSERT YOUR AWS ACCESS KEY ID HERE>' | ||
| 18 | AWS_SECRET_ACCESS_KEY = '<INSERT YOUR AWS SECRET ACCESS KEY HERE>' | ||
| 19 | # remove these next two lines when you've updated your credentials. | ||
| 20 | print "update s3-test.py with your AWS credentials" | ||
| 21 | sys.exit(); | ||
| 22 | |||
| 23 | # for subdomains (bucket.s3.amazonaws.com), | ||
| 24 | # the bucket name must be lowercase since DNS is case-insensitive | ||
| 25 | BUCKET_NAME = "%s-test-bucket" % AWS_ACCESS_KEY_ID.lower(); | ||
| 26 | |||
| 27 | |||
| 28 | class TestAWSAuthConnection(unittest.TestCase): | ||
| 29 | def setUp(self): | ||
| 30 | self.conn = S3.AWSAuthConnection(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY) | ||
| 31 | |||
| 32 | # test all operations for both regular and vanity domains | ||
| 33 | # regular: http://s3.amazonaws.com/bucket/key | ||
| 34 | # subdomain: http://bucket.s3.amazonaws.com/key | ||
| 35 | # testing pure vanity domains (http://<vanity domain>/key) is not covered here | ||
| 36 | # but is possible with some additional setup (set the server in @conn to your vanity domain) | ||
| 37 | |||
| 38 | def test_subdomain_default(self): | ||
| 39 | self.run_tests(S3.CallingFormat.SUBDOMAIN, S3.Location.DEFAULT) | ||
| 40 | |||
| 41 | def test_subdomain_eu(self): | ||
| 42 | self.run_tests(S3.CallingFormat.SUBDOMAIN, S3.Location.EU) | ||
| 43 | |||
| 44 | def test_path_default(self): | ||
| 45 | self.run_tests(S3.CallingFormat.PATH, S3.Location.DEFAULT) | ||
| 46 | |||
| 47 | |||
| 48 | def run_tests(self, calling_format, location): | ||
| 49 | self.conn.calling_format = calling_format | ||
| 50 | |||
| 51 | response = self.conn.create_located_bucket(BUCKET_NAME, location) | ||
| 52 | self.assertEquals(response.http_response.status, 200, 'create bucket') | ||
| 53 | |||
| 54 | response = self.conn.list_bucket(BUCKET_NAME) | ||
| 55 | self.assertEquals(response.http_response.status, 200, 'list bucket') | ||
| 56 | self.assertEquals(len(response.entries), 0, 'bucket is empty') | ||
| 57 | |||
| 58 | text = 'this is a test' | ||
| 59 | key = 'example.txt' | ||
| 60 | |||
| 61 | response = self.conn.put(BUCKET_NAME, key, text) | ||
| 62 | self.assertEquals(response.http_response.status, 200, 'put with a string argument') | ||
| 63 | |||
| 64 | response = \ | ||
| 65 | self.conn.put( | ||
| 66 | BUCKET_NAME, | ||
| 67 | key, | ||
| 68 | S3.S3Object(text, {'title': 'title'}), | ||
| 69 | {'Content-Type': 'text/plain'}) | ||
| 70 | |||
| 71 | self.assertEquals(response.http_response.status, 200, 'put with complex argument and headers') | ||
| 72 | |||
| 73 | response = self.conn.get(BUCKET_NAME, key) | ||
| 74 | self.assertEquals(response.http_response.status, 200, 'get object') | ||
| 75 | self.assertEquals(response.object.data, text, 'got right data') | ||
| 76 | self.assertEquals(response.object.metadata, { 'title': 'title' }, 'metadata is correct') | ||
| 77 | self.assertEquals(int(response.http_response.getheader('Content-Length')), len(text), 'got content-length header') | ||
| 78 | |||
| 79 | title_with_spaces = " \t title with leading and trailing spaces " | ||
| 80 | response = \ | ||
| 81 | self.conn.put( | ||
| 82 | BUCKET_NAME, | ||
| 83 | key, | ||
| 84 | S3.S3Object(text, {'title': title_with_spaces}), | ||
| 85 | {'Content-Type': 'text/plain'}) | ||
| 86 | |||
| 87 | self.assertEquals(response.http_response.status, 200, 'put with headers with spaces') | ||
| 88 | |||
| 89 | response = self.conn.get(BUCKET_NAME, key) | ||
| 90 | self.assertEquals(response.http_response.status, 200, 'get object') | ||
| 91 | self.assertEquals( | ||
| 92 | response.object.metadata, | ||
| 93 | { 'title': title_with_spaces.strip() }, | ||
| 94 | 'metadata with spaces is correct') | ||
| 95 | |||
| 96 | # delimited list tests | ||
| 97 | inner_key = 'test/inner.txt' | ||
| 98 | last_key = 'z-last-key.txt' | ||
| 99 | response = self.conn.put(BUCKET_NAME, inner_key, text) | ||
| 100 | self.assertEquals(response.http_response.status, 200, 'put inner key') | ||
| 101 | |||
| 102 | response = self.conn.put(BUCKET_NAME, last_key, text) | ||
| 103 | self.assertEquals(response.http_response.status, 200, 'put last key') | ||
| 104 | |||
| 105 | response = self.do_delimited_list(BUCKET_NAME, False, {'delimiter': '/'}, 2, 1, 'root list') | ||
| 106 | |||
| 107 | response = self.do_delimited_list(BUCKET_NAME, True, {'max-keys': 1, 'delimiter': '/'}, 1, 0, 'root list with max keys of 1', 'example.txt') | ||
| 108 | |||
| 109 | response = self.do_delimited_list(BUCKET_NAME, True, {'max-keys': 2, 'delimiter': '/'}, 1, 1, 'root list with max keys of 2, page 1', 'test/') | ||
| 110 | |||
| 111 | marker = response.next_marker | ||
| 112 | |||
| 113 | response = self.do_delimited_list(BUCKET_NAME, False, {'marker': marker, 'max-keys': 2, 'delimiter': '/'}, 1, 0, 'root list with max keys of 2, page 2') | ||
| 114 | |||
| 115 | response = self.do_delimited_list(BUCKET_NAME, False, {'prefix': 'test/', 'delimiter': '/'}, 1, 0, 'test/ list') | ||
| 116 | |||
| 117 | response = self.conn.delete(BUCKET_NAME, inner_key) | ||
| 118 | self.assertEquals(response.http_response.status, 204, 'delete %s' % inner_key) | ||
| 119 | |||
| 120 | response = self.conn.delete(BUCKET_NAME, last_key) | ||
| 121 | self.assertEquals(response.http_response.status, 204, 'delete %s' % last_key) | ||
| 122 | |||
| 123 | |||
| 124 | weird_key = '&=//%# ++++' | ||
| 125 | |||
| 126 | response = self.conn.put(BUCKET_NAME, weird_key, text) | ||
| 127 | self.assertEquals(response.http_response.status, 200, 'put weird key') | ||
| 128 | |||
| 129 | response = self.conn.get(BUCKET_NAME, weird_key) | ||
| 130 | self.assertEquals(response.http_response.status, 200, 'get weird key') | ||
| 131 | |||
| 132 | response = self.conn.get_acl(BUCKET_NAME, key) | ||
| 133 | self.assertEquals(response.http_response.status, 200, 'get acl') | ||
| 134 | |||
| 135 | acl = response.object.data | ||
| 136 | |||
| 137 | response = self.conn.put_acl(BUCKET_NAME, key, acl) | ||
| 138 | self.assertEquals(response.http_response.status, 200, 'put acl') | ||
| 139 | |||
| 140 | response = self.conn.get_bucket_acl(BUCKET_NAME) | ||
| 141 | self.assertEquals(response.http_response.status, 200, 'get bucket acl') | ||
| 142 | |||
| 143 | bucket_acl = response.object.data | ||
| 144 | |||
| 145 | response = self.conn.put_bucket_acl(BUCKET_NAME, bucket_acl) | ||
| 146 | self.assertEquals(response.http_response.status, 200, 'put bucket acl') | ||
| 147 | |||
| 148 | response = self.conn.get_bucket_acl(BUCKET_NAME) | ||
| 149 | self.assertEquals(response.http_response.status, 200, 'get bucket logging') | ||
| 150 | |||
| 151 | bucket_logging = response.object.data | ||
| 152 | |||
| 153 | response = self.conn.put_bucket_acl(BUCKET_NAME, bucket_logging) | ||
| 154 | self.assertEquals(response.http_response.status, 200, 'put bucket logging') | ||
| 155 | |||
| 156 | response = self.conn.list_bucket(BUCKET_NAME) | ||
| 157 | self.assertEquals(response.http_response.status, 200, 'list bucket') | ||
| 158 | entries = response.entries | ||
| 159 | self.assertEquals(len(entries), 2, 'got back right number of keys') | ||
| 160 | # depends on weird_key < key | ||
| 161 | self.assertEquals(entries[0].key, weird_key, 'first key is right') | ||
| 162 | self.assertEquals(entries[1].key, key, 'second key is right') | ||
| 163 | |||
| 164 | response = self.conn.list_bucket(BUCKET_NAME, {'max-keys': 1}) | ||
| 165 | self.assertEquals(response.http_response.status, 200, 'list bucket with args') | ||
| 166 | self.assertEquals(len(response.entries), 1, 'got back right number of keys') | ||
| 167 | |||
| 168 | for entry in entries: | ||
| 169 | response = self.conn.delete(BUCKET_NAME, entry.key) | ||
| 170 | self.assertEquals(response.http_response.status, 204, 'delete %s' % entry.key) | ||
| 171 | |||
| 172 | response = self.conn.list_all_my_buckets() | ||
| 173 | self.assertEquals(response.http_response.status, 200, 'list all my buckets') | ||
| 174 | buckets = response.entries | ||
| 175 | |||
| 176 | response = self.conn.delete_bucket(BUCKET_NAME) | ||
| 177 | self.assertEquals(response.http_response.status, 204, 'delete bucket') | ||
| 178 | |||
| 179 | response = self.conn.list_all_my_buckets() | ||
| 180 | self.assertEquals(response.http_response.status, 200, 'list all my buckets again') | ||
| 181 | |||
| 182 | self.assertEquals(len(response.entries), len(buckets) - 1, 'bucket count is correct') | ||
| 183 | |||
| 184 | def verify_list_bucket_response(self, response, bucket, is_truncated, parameters, next_marker=''): | ||
| 185 | prefix = '' | ||
| 186 | marker = '' | ||
| 187 | |||
| 188 | if parameters.has_key('prefix'): | ||
| 189 | prefix = parameters['prefix'] | ||
| 190 | if parameters.has_key('marker'): | ||
| 191 | marker = parameters['marker'] | ||
| 192 | |||
| 193 | self.assertEquals(bucket, response.name, 'bucket name should match') | ||
| 194 | self.assertEquals(prefix, response.prefix, 'prefix should match') | ||
| 195 | self.assertEquals(marker, response.marker, 'marker should match') | ||
| 196 | if parameters.has_key('max-keys'): | ||
| 197 | self.assertEquals(parameters['max-keys'], response.max_keys, 'max-keys should match') | ||
| 198 | self.assertEquals(parameters['delimiter'], response.delimiter, 'delimiter should match') | ||
| 199 | self.assertEquals(is_truncated, response.is_truncated, 'is_truncated should match') | ||
| 200 | self.assertEquals(next_marker, response.next_marker, 'next_marker should match') | ||
| 201 | |||
| 202 | def do_delimited_list(self, bucket_name, is_truncated, parameters, regular_expected, common_expected, test_name, next_marker=''): | ||
| 203 | response = self.conn.list_bucket(bucket_name, parameters) | ||
| 204 | self.assertEquals(response.http_response.status, 200, test_name) | ||
| 205 | self.assertEquals(regular_expected, len(response.entries), 'right number of regular entries') | ||
| 206 | self.assertEquals(common_expected, len(response.common_prefixes), 'right number of common prefixes') | ||
| 207 | |||
| 208 | self.verify_list_bucket_response(response, bucket_name, is_truncated, parameters, next_marker) | ||
| 209 | |||
| 210 | return response | ||
| 211 | |||
| 212 | class TestQueryStringAuthGenerator(unittest.TestCase): | ||
| 213 | def setUp(self): | ||
| 214 | self.generator = S3.QueryStringAuthGenerator(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY) | ||
| 215 | if (self.generator.is_secure == True): | ||
| 216 | self.connection = httplib.HTTPSConnection(self.generator.server_name) | ||
| 217 | else: | ||
| 218 | self.connection = httplib.HTTPConnection(self.generator.server_name) | ||
| 219 | |||
| 220 | def check_url(self, url, method, status, message, data=''): | ||
| 221 | if (method == 'PUT'): | ||
| 222 | headers = { 'Content-Length': len(data) } | ||
| 223 | self.connection.request(method, url, data, headers) | ||
| 224 | else: | ||
| 225 | self.connection.request(method, url) | ||
| 226 | |||
| 227 | response = self.connection.getresponse() | ||
| 228 | self.assertEquals(response.status, status, message) | ||
| 229 | |||
| 230 | return response.read() | ||
| 231 | |||
| 232 | # test all operations for both regular and vanity domains | ||
| 233 | # regular: http://s3.amazonaws.com/bucket/key | ||
| 234 | # subdomain: http://bucket.s3.amazonaws.com/key | ||
| 235 | # testing pure vanity domains (http://<vanity domain>/key) is not covered here | ||
| 236 | # but is possible with some additional setup (set the server in @conn to your vanity domain) | ||
| 237 | |||
| 238 | def test_subdomain(self): | ||
| 239 | self.run_tests(S3.CallingFormat.SUBDOMAIN) | ||
| 240 | |||
| 241 | def test_path(self): | ||
| 242 | self.run_tests(S3.CallingFormat.PATH) | ||
| 243 | |||
| 244 | def run_tests(self, calling_format): | ||
| 245 | self.generator.calling_format = calling_format | ||
| 246 | |||
| 247 | key = 'test' | ||
| 248 | |||
| 249 | self.check_url(self.generator.create_bucket(BUCKET_NAME), 'PUT', 200, 'create_bucket') | ||
| 250 | self.check_url(self.generator.put(BUCKET_NAME, key, ''), 'PUT', 200, 'put object', 'test data') | ||
| 251 | self.check_url(self.generator.get(BUCKET_NAME, key), 'GET', 200, 'get object') | ||
| 252 | self.check_url(self.generator.list_bucket(BUCKET_NAME), 'GET', 200, 'list bucket') | ||
| 253 | self.check_url(self.generator.list_all_my_buckets(), 'GET', 200, 'list all my buckets') | ||
| 254 | acl = self.check_url(self.generator.get_acl(BUCKET_NAME, key), 'GET', 200, 'get acl') | ||
| 255 | self.check_url(self.generator.put_acl(BUCKET_NAME, key, acl), 'PUT', 200, 'put acl', acl) | ||
| 256 | bucket_acl = self.check_url(self.generator.get_bucket_acl(BUCKET_NAME), 'GET', 200, 'get bucket acl') | ||
| 257 | self.check_url(self.generator.put_bucket_acl(BUCKET_NAME, bucket_acl), 'PUT', 200, 'put bucket acl', bucket_acl) | ||
| 258 | bucket_logging = self.check_url(self.generator.get_bucket_logging(BUCKET_NAME), 'GET', 200, 'get bucket logging') | ||
| 259 | self.check_url(self.generator.put_bucket_logging(BUCKET_NAME, bucket_logging), 'PUT', 200, 'put bucket logging', bucket_logging) | ||
| 260 | self.check_url(self.generator.delete(BUCKET_NAME, key), 'DELETE', 204, 'delete object') | ||
| 261 | self.check_url(self.generator.delete_bucket(BUCKET_NAME), 'DELETE', 204, 'delete bucket') | ||
| 262 | |||
| 263 | |||
| 264 | if __name__ == '__main__': | ||
| 265 | unittest.main() | ||
| 266 | |||
| 267 | |||