Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(64)

Side by Side Diff: third_party/gsutil/third_party/boto/tests/unit/test_connection.py

Issue 1377933002: [catapult] - Copy Telemetry's gsutilz over to third_party. (Closed) Base URL: https://github.com/catapult-project/catapult.git@master
Patch Set: Rename to gsutil. Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 # Copyright (c) 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved
2 #
3 # Permission is hereby granted, free of charge, to any person obtaining a
4 # copy of this software and associated documentation files (the
5 # "Software"), to deal in the Software without restriction, including
6 # without limitation the rights to use, copy, modify, merge, publish, dis-
7 # tribute, sublicense, and/or sell copies of the Software, and to permit
8 # persons to whom the Software is furnished to do so, subject to the fol-
9 # lowing conditions:
10 #
11 # The above copyright notice and this permission notice shall be included
12 # in all copies or substantial portions of the Software.
13 #
14 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
16 # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
17 # SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20 # IN THE SOFTWARE.
21 #
22 import os
23 import socket
24
25 from tests.compat import mock, unittest
26 from httpretty import HTTPretty
27
28 from boto import UserAgent
29 from boto.compat import json, parse_qs
30 from boto.connection import AWSQueryConnection, AWSAuthConnection, HTTPRequest
31 from boto.exception import BotoServerError
32 from boto.regioninfo import RegionInfo
33
34
35 class TestListParamsSerialization(unittest.TestCase):
36 maxDiff = None
37
38 def setUp(self):
39 self.connection = AWSQueryConnection('access_key', 'secret_key')
40
41 def test_complex_list_serialization(self):
42 # This example is taken from the doc string of
43 # build_complex_list_params.
44 params = {}
45 self.connection.build_complex_list_params(
46 params, [('foo', 'bar', 'baz'), ('foo2', 'bar2', 'baz2')],
47 'ParamName.member', ('One', 'Two', 'Three'))
48 self.assertDictEqual({
49 'ParamName.member.1.One': 'foo',
50 'ParamName.member.1.Two': 'bar',
51 'ParamName.member.1.Three': 'baz',
52 'ParamName.member.2.One': 'foo2',
53 'ParamName.member.2.Two': 'bar2',
54 'ParamName.member.2.Three': 'baz2',
55 }, params)
56
57 def test_simple_list_serialization(self):
58 params = {}
59 self.connection.build_list_params(
60 params, ['foo', 'bar', 'baz'], 'ParamName.member')
61 self.assertDictEqual({
62 'ParamName.member.1': 'foo',
63 'ParamName.member.2': 'bar',
64 'ParamName.member.3': 'baz',
65 }, params)
66
67
68 class MockAWSService(AWSQueryConnection):
69 """
70 Fake AWS Service
71
72 This is used to test the AWSQueryConnection object is behaving properly.
73 """
74
75 APIVersion = '2012-01-01'
76
77 def _required_auth_capability(self):
78 return ['sign-v2']
79
80 def __init__(self, aws_access_key_id=None, aws_secret_access_key=None,
81 is_secure=True, host=None, port=None,
82 proxy=None, proxy_port=None,
83 proxy_user=None, proxy_pass=None, debug=0,
84 https_connection_factory=None, region=None, path='/',
85 api_version=None, security_token=None,
86 validate_certs=True, profile_name=None):
87 self.region = region
88 if host is None:
89 host = self.region.endpoint
90 AWSQueryConnection.__init__(self, aws_access_key_id,
91 aws_secret_access_key,
92 is_secure, port, proxy, proxy_port,
93 proxy_user, proxy_pass,
94 host, debug,
95 https_connection_factory, path,
96 security_token,
97 validate_certs=validate_certs,
98 profile_name=profile_name)
99
100
101 class TestAWSAuthConnection(unittest.TestCase):
102 def test_get_path(self):
103 conn = AWSAuthConnection(
104 'mockservice.cc-zone-1.amazonaws.com',
105 aws_access_key_id='access_key',
106 aws_secret_access_key='secret',
107 suppress_consec_slashes=False
108 )
109 # Test some sample paths for mangling.
110 self.assertEqual(conn.get_path('/'), '/')
111 self.assertEqual(conn.get_path('image.jpg'), '/image.jpg')
112 self.assertEqual(conn.get_path('folder/image.jpg'), '/folder/image.jpg')
113 self.assertEqual(conn.get_path('folder//image.jpg'), '/folder//image.jpg ')
114
115 # Ensure leading slashes aren't removed.
116 # See https://github.com/boto/boto/issues/1387
117 self.assertEqual(conn.get_path('/folder//image.jpg'), '/folder//image.jp g')
118 self.assertEqual(conn.get_path('/folder////image.jpg'), '/folder////imag e.jpg')
119 self.assertEqual(conn.get_path('///folder////image.jpg'), '///folder//// image.jpg')
120
121 def test_connection_behind_proxy(self):
122 os.environ['http_proxy'] = "http://john.doe:p4ssw0rd@127.0.0.1:8180"
123 conn = AWSAuthConnection(
124 'mockservice.cc-zone-1.amazonaws.com',
125 aws_access_key_id='access_key',
126 aws_secret_access_key='secret',
127 suppress_consec_slashes=False
128 )
129 self.assertEqual(conn.proxy, '127.0.0.1')
130 self.assertEqual(conn.proxy_user, 'john.doe')
131 self.assertEqual(conn.proxy_pass, 'p4ssw0rd')
132 self.assertEqual(conn.proxy_port, '8180')
133 del os.environ['http_proxy']
134
135 def test_get_proxy_url_with_auth(self):
136 conn = AWSAuthConnection(
137 'mockservice.cc-zone-1.amazonaws.com',
138 aws_access_key_id='access_key',
139 aws_secret_access_key='secret',
140 suppress_consec_slashes=False,
141 proxy="127.0.0.1",
142 proxy_user="john.doe",
143 proxy_pass="p4ssw0rd",
144 proxy_port="8180"
145 )
146 self.assertEqual(conn.get_proxy_url_with_auth(), 'http://john.doe:p4ssw0 rd@127.0.0.1:8180')
147
148 def test_connection_behind_proxy_without_explicit_port(self):
149 os.environ['http_proxy'] = "http://127.0.0.1"
150 conn = AWSAuthConnection(
151 'mockservice.cc-zone-1.amazonaws.com',
152 aws_access_key_id='access_key',
153 aws_secret_access_key='secret',
154 suppress_consec_slashes=False,
155 port=8180
156 )
157 self.assertEqual(conn.proxy, '127.0.0.1')
158 self.assertEqual(conn.proxy_port, 8180)
159 del os.environ['http_proxy']
160
161 @mock.patch.object(socket, 'create_connection')
162 @mock.patch('boto.compat.http_client.HTTPResponse')
163 @mock.patch('boto.compat.http_client.ssl')
164 def test_proxy_ssl(self, ssl_mock, http_response_mock,
165 create_connection_mock):
166 type(http_response_mock.return_value).status = mock.PropertyMock(
167 return_value=200)
168
169 conn = AWSAuthConnection(
170 'mockservice.cc-zone-1.amazonaws.com',
171 aws_access_key_id='access_key',
172 aws_secret_access_key='secret',
173 suppress_consec_slashes=False,
174 proxy_port=80
175 )
176 conn.https_validate_certificates = False
177
178 # Attempt to call proxy_ssl and make sure it works
179 conn.proxy_ssl('mockservice.cc-zone-1.amazonaws.com', 80)
180
181 # this tests the proper setting of the host_header in v4 signing
182 def test_host_header_with_nonstandard_port(self):
183 # test standard port first
184 conn = V4AuthConnection(
185 'testhost',
186 aws_access_key_id='access_key',
187 aws_secret_access_key='secret')
188 request = conn.build_base_http_request(
189 method='POST', path='/', auth_path=None, params=None, headers=None,
190 data='', host=None)
191 conn.set_host_header(request)
192 self.assertEqual(request.headers['Host'], 'testhost')
193
194 # next, test non-standard port
195 conn = V4AuthConnection(
196 'testhost',
197 aws_access_key_id='access_key',
198 aws_secret_access_key='secret',
199 port=8773)
200 request = conn.build_base_http_request(
201 method='POST', path='/', auth_path=None, params=None, headers=None,
202 data='', host=None)
203 conn.set_host_header(request)
204 self.assertEqual(request.headers['Host'], 'testhost:8773')
205
206
207 class V4AuthConnection(AWSAuthConnection):
208 def __init__(self, host, aws_access_key_id, aws_secret_access_key, port=443) :
209 AWSAuthConnection.__init__(
210 self, host, aws_access_key_id, aws_secret_access_key, port=port)
211
212 def _required_auth_capability(self):
213 return ['hmac-v4']
214
215
216 class TestAWSQueryConnection(unittest.TestCase):
217 def setUp(self):
218 self.region = RegionInfo(
219 name='cc-zone-1',
220 endpoint='mockservice.cc-zone-1.amazonaws.com',
221 connection_cls=MockAWSService)
222
223 HTTPretty.enable()
224
225 def tearDown(self):
226 HTTPretty.disable()
227
228
229 class TestAWSQueryConnectionSimple(TestAWSQueryConnection):
230 def test_query_connection_basis(self):
231 HTTPretty.register_uri(HTTPretty.POST,
232 'https://%s/' % self.region.endpoint,
233 json.dumps({'test': 'secure'}),
234 content_type='application/json')
235
236 conn = self.region.connect(aws_access_key_id='access_key',
237 aws_secret_access_key='secret')
238
239 self.assertEqual(conn.host, 'mockservice.cc-zone-1.amazonaws.com')
240
241 def test_query_connection_noproxy(self):
242 HTTPretty.register_uri(HTTPretty.POST,
243 'https://%s/' % self.region.endpoint,
244 json.dumps({'test': 'secure'}),
245 content_type='application/json')
246
247 os.environ['no_proxy'] = self.region.endpoint
248
249 conn = self.region.connect(aws_access_key_id='access_key',
250 aws_secret_access_key='secret',
251 proxy="NON_EXISTENT_HOSTNAME",
252 proxy_port="3128")
253
254 resp = conn.make_request('myCmd',
255 {'par1': 'foo', 'par2': 'baz'},
256 "/",
257 "POST")
258 del os.environ['no_proxy']
259 args = parse_qs(HTTPretty.last_request.body)
260 self.assertEqual(args[b'AWSAccessKeyId'], [b'access_key'])
261
262 def test_query_connection_noproxy_nosecure(self):
263 HTTPretty.register_uri(HTTPretty.POST,
264 'https://%s/' % self.region.endpoint,
265 json.dumps({'test': 'insecure'}),
266 content_type='application/json')
267
268 os.environ['no_proxy'] = self.region.endpoint
269
270 conn = self.region.connect(aws_access_key_id='access_key',
271 aws_secret_access_key='secret',
272 proxy="NON_EXISTENT_HOSTNAME",
273 proxy_port="3128",
274 is_secure=False)
275
276 resp = conn.make_request('myCmd',
277 {'par1': 'foo', 'par2': 'baz'},
278 "/",
279 "POST")
280 del os.environ['no_proxy']
281 args = parse_qs(HTTPretty.last_request.body)
282 self.assertEqual(args[b'AWSAccessKeyId'], [b'access_key'])
283
284 def test_single_command(self):
285 HTTPretty.register_uri(HTTPretty.POST,
286 'https://%s/' % self.region.endpoint,
287 json.dumps({'test': 'secure'}),
288 content_type='application/json')
289
290 conn = self.region.connect(aws_access_key_id='access_key',
291 aws_secret_access_key='secret')
292 resp = conn.make_request('myCmd',
293 {'par1': 'foo', 'par2': 'baz'},
294 "/",
295 "POST")
296
297 args = parse_qs(HTTPretty.last_request.body)
298 self.assertEqual(args[b'AWSAccessKeyId'], [b'access_key'])
299 self.assertEqual(args[b'SignatureMethod'], [b'HmacSHA256'])
300 self.assertEqual(args[b'Version'], [conn.APIVersion.encode('utf-8')])
301 self.assertEqual(args[b'par1'], [b'foo'])
302 self.assertEqual(args[b'par2'], [b'baz'])
303
304 self.assertEqual(resp.read(), b'{"test": "secure"}')
305
306 def test_multi_commands(self):
307 """Check connection re-use"""
308 HTTPretty.register_uri(HTTPretty.POST,
309 'https://%s/' % self.region.endpoint,
310 json.dumps({'test': 'secure'}),
311 content_type='application/json')
312
313 conn = self.region.connect(aws_access_key_id='access_key',
314 aws_secret_access_key='secret')
315
316 resp1 = conn.make_request('myCmd1',
317 {'par1': 'foo', 'par2': 'baz'},
318 "/",
319 "POST")
320 body1 = parse_qs(HTTPretty.last_request.body)
321
322 resp2 = conn.make_request('myCmd2',
323 {'par3': 'bar', 'par4': 'narf'},
324 "/",
325 "POST")
326 body2 = parse_qs(HTTPretty.last_request.body)
327
328 self.assertEqual(body1[b'par1'], [b'foo'])
329 self.assertEqual(body1[b'par2'], [b'baz'])
330 with self.assertRaises(KeyError):
331 body1[b'par3']
332
333 self.assertEqual(body2[b'par3'], [b'bar'])
334 self.assertEqual(body2[b'par4'], [b'narf'])
335 with self.assertRaises(KeyError):
336 body2['par1']
337
338 self.assertEqual(resp1.read(), b'{"test": "secure"}')
339 self.assertEqual(resp2.read(), b'{"test": "secure"}')
340
341 def test_non_secure(self):
342 HTTPretty.register_uri(HTTPretty.POST,
343 'http://%s/' % self.region.endpoint,
344 json.dumps({'test': 'normal'}),
345 content_type='application/json')
346
347 conn = self.region.connect(aws_access_key_id='access_key',
348 aws_secret_access_key='secret',
349 is_secure=False)
350 resp = conn.make_request('myCmd1',
351 {'par1': 'foo', 'par2': 'baz'},
352 "/",
353 "POST")
354
355 self.assertEqual(resp.read(), b'{"test": "normal"}')
356
357 def test_alternate_port(self):
358 HTTPretty.register_uri(HTTPretty.POST,
359 'http://%s:8080/' % self.region.endpoint,
360 json.dumps({'test': 'alternate'}),
361 content_type='application/json')
362
363 conn = self.region.connect(aws_access_key_id='access_key',
364 aws_secret_access_key='secret',
365 port=8080,
366 is_secure=False)
367 resp = conn.make_request('myCmd1',
368 {'par1': 'foo', 'par2': 'baz'},
369 "/",
370 "POST")
371
372 self.assertEqual(resp.read(), b'{"test": "alternate"}')
373
374 def test_temp_failure(self):
375 responses = [HTTPretty.Response(body="{'test': 'fail'}", status=500),
376 HTTPretty.Response(body="{'test': 'success'}", status=200)]
377
378 HTTPretty.register_uri(HTTPretty.POST,
379 'https://%s/temp_fail/' % self.region.endpoint,
380 responses=responses)
381
382 conn = self.region.connect(aws_access_key_id='access_key',
383 aws_secret_access_key='secret')
384 resp = conn.make_request('myCmd1',
385 {'par1': 'foo', 'par2': 'baz'},
386 '/temp_fail/',
387 'POST')
388 self.assertEqual(resp.read(), b"{'test': 'success'}")
389
390 def test_unhandled_exception(self):
391 HTTPretty.register_uri(HTTPretty.POST,
392 'https://%s/temp_exception/' % self.region.endpoi nt,
393 responses=[])
394
395 def fake_connection(address, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
396 source_address=None):
397 raise socket.timeout('fake error')
398
399 socket.create_connection = fake_connection
400
401 conn = self.region.connect(aws_access_key_id='access_key',
402 aws_secret_access_key='secret')
403 conn.num_retries = 0
404 with self.assertRaises(socket.error):
405 resp = conn.make_request('myCmd1',
406 {'par1': 'foo', 'par2': 'baz'},
407 '/temp_exception/',
408 'POST')
409
410 def test_connection_close(self):
411 """Check connection re-use after close header is received"""
412 HTTPretty.register_uri(HTTPretty.POST,
413 'https://%s/' % self.region.endpoint,
414 json.dumps({'test': 'secure'}),
415 content_type='application/json',
416 connection='close')
417
418 conn = self.region.connect(aws_access_key_id='access_key',
419 aws_secret_access_key='secret')
420
421 def mock_put_conn(*args, **kwargs):
422 raise Exception('put_http_connection should not be called!')
423
424 conn.put_http_connection = mock_put_conn
425
426 resp1 = conn.make_request('myCmd1',
427 {'par1': 'foo', 'par2': 'baz'},
428 "/",
429 "POST")
430
431 # If we've gotten this far then no exception was raised
432 # by attempting to put the connection back into the pool
433 # Now let's just confirm the close header was actually
434 # set or we have another problem.
435 self.assertEqual(resp1.getheader('connection'), 'close')
436
437 def test_port_pooling(self):
438 conn = self.region.connect(aws_access_key_id='access_key',
439 aws_secret_access_key='secret',
440 port=8080)
441
442 # Pick a connection, then put it back
443 con1 = conn.get_http_connection(conn.host, conn.port, conn.is_secure)
444 conn.put_http_connection(conn.host, conn.port, conn.is_secure, con1)
445
446 # Pick another connection, which hopefully is the same yet again
447 con2 = conn.get_http_connection(conn.host, conn.port, conn.is_secure)
448 conn.put_http_connection(conn.host, conn.port, conn.is_secure, con2)
449
450 self.assertEqual(con1, con2)
451
452 # Change the port and make sure a new connection is made
453 conn.port = 8081
454
455 con3 = conn.get_http_connection(conn.host, conn.port, conn.is_secure)
456 conn.put_http_connection(conn.host, conn.port, conn.is_secure, con3)
457
458 self.assertNotEqual(con1, con3)
459
460
461 class TestAWSQueryStatus(TestAWSQueryConnection):
462
463 def test_get_status(self):
464 HTTPretty.register_uri(HTTPretty.GET,
465 'https://%s/status' % self.region.endpoint,
466 '<status>ok</status>',
467 content_type='text/xml')
468
469 conn = self.region.connect(aws_access_key_id='access_key',
470 aws_secret_access_key='secret')
471 resp = conn.get_status('getStatus',
472 {'par1': 'foo', 'par2': 'baz'},
473 'status')
474
475 self.assertEqual(resp, "ok")
476
477 def test_get_status_blank_error(self):
478 HTTPretty.register_uri(HTTPretty.GET,
479 'https://%s/status' % self.region.endpoint,
480 '',
481 content_type='text/xml')
482
483 conn = self.region.connect(aws_access_key_id='access_key',
484 aws_secret_access_key='secret')
485 with self.assertRaises(BotoServerError):
486 resp = conn.get_status('getStatus',
487 {'par1': 'foo', 'par2': 'baz'},
488 'status')
489
490 def test_get_status_error(self):
491 HTTPretty.register_uri(HTTPretty.GET,
492 'https://%s/status' % self.region.endpoint,
493 '<status>error</status>',
494 content_type='text/xml',
495 status=400)
496
497 conn = self.region.connect(aws_access_key_id='access_key',
498 aws_secret_access_key='secret')
499 with self.assertRaises(BotoServerError):
500 resp = conn.get_status('getStatus',
501 {'par1': 'foo', 'par2': 'baz'},
502 'status')
503
504
505 class TestHTTPRequest(unittest.TestCase):
506 def test_user_agent_not_url_encoded(self):
507 headers = {'Some-Header': u'should be url encoded',
508 'User-Agent': UserAgent}
509 request = HTTPRequest('PUT', 'https', 'amazon.com', 443, None,
510 None, {}, headers, 'Body')
511 mock_connection = mock.Mock()
512
513 # Create a method that preserves the headers at the time of
514 # authorization.
515 def mock_add_auth(req, **kwargs):
516 mock_connection.headers_at_auth = req.headers.copy()
517
518 mock_connection._auth_handler.add_auth = mock_add_auth
519
520 request.authorize(mock_connection)
521 # Ensure the headers at authorization are as expected i.e.
522 # the user agent header was not url encoded but the other header was.
523 self.assertEqual(mock_connection.headers_at_auth,
524 {'Some-Header': 'should%20be%20url%20encoded',
525 'User-Agent': UserAgent})
526
527 def test_content_length_str(self):
528 request = HTTPRequest('PUT', 'https', 'amazon.com', 443, None,
529 None, {}, {}, 'Body')
530 mock_connection = mock.Mock()
531 request.authorize(mock_connection)
532
533 # Ensure Content-Length header is a str. This is more explicit than
534 # relying on other code cast the value later. (Python 2.7.0, for
535 # example, assumes headers are of type str.)
536 self.assertIsInstance(request.headers['Content-Length'], str)
537
538 if __name__ == '__main__':
539 unittest.main()
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698