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

Side by Side Diff: tests/s3/test_resumable_downloads.py

Issue 8386013: Merging in latest boto. (Closed) Base URL: svn://svn.chromium.org/boto
Patch Set: Redoing vendor drop by deleting and then merging. Created 9 years, 1 month 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 | Annotate | Revision Log
« no previous file with comments | « tests/s3/test_pool.py ('k') | tests/s3/test_resumable_uploads.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # 2 #
3 # Copyright 2010 Google Inc. 3 # Copyright 2010 Google Inc.
4 # 4 #
5 # Permission is hereby granted, free of charge, to any person obtaining a 5 # Permission is hereby granted, free of charge, to any person obtaining a
6 # copy of this software and associated documentation files (the 6 # copy of this software and associated documentation files (the
7 # "Software"), to deal in the Software without restriction, including 7 # "Software"), to deal in the Software without restriction, including
8 # without limitation the rights to use, copy, modify, merge, publish, dis- 8 # without limitation the rights to use, copy, modify, merge, publish, dis-
9 # tribute, sublicense, and/or sell copies of the Software, and to permit 9 # tribute, sublicense, and/or sell copies of the Software, and to permit
10 # persons to whom the Software is furnished to do so, subject to the fol- 10 # persons to whom the Software is furnished to do so, subject to the fol-
(...skipping 27 matching lines...) Expand all
38 import time 38 import time
39 import unittest 39 import unittest
40 40
41 import boto 41 import boto
42 from boto import storage_uri 42 from boto import storage_uri
43 from boto.s3.resumable_download_handler import get_cur_file_size 43 from boto.s3.resumable_download_handler import get_cur_file_size
44 from boto.s3.resumable_download_handler import ResumableDownloadHandler 44 from boto.s3.resumable_download_handler import ResumableDownloadHandler
45 from boto.exception import ResumableTransferDisposition 45 from boto.exception import ResumableTransferDisposition
46 from boto.exception import ResumableDownloadException 46 from boto.exception import ResumableDownloadException
47 from boto.exception import StorageResponseError 47 from boto.exception import StorageResponseError
48 from boto.tests.cb_test_harnass import CallbackTestHarnass 48 from cb_test_harnass import CallbackTestHarnass
49
50 # We don't use the OAuth2 authentication plugin directly; importing it here
51 # ensures that it's loaded and available by default.
52 try:
53 from oauth2_plugin import oauth2_plugin
54 except ImportError:
55 # Do nothing - if user doesn't have OAuth2 configured it doesn't matter;
56 # and if they do, the tests will fail (as they should in that case).
57 pass
49 58
50 59
51 class ResumableDownloadTests(unittest.TestCase): 60 class ResumableDownloadTests(unittest.TestCase):
52 """ 61 """
53 Resumable download test suite. 62 Resumable download test suite.
54 """ 63 """
55 64
56 def get_suite_description(self): 65 def get_suite_description(self):
57 return 'Resumable download test suite' 66 return 'Resumable download test suite'
58 67
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 return (string_data, key) 115 return (string_data, key)
107 116
108 @classmethod 117 @classmethod
109 def set_up_class(cls, debug): 118 def set_up_class(cls, debug):
110 """ 119 """
111 Initializes test suite. 120 Initializes test suite.
112 """ 121 """
113 122
114 # Create the test bucket. 123 # Create the test bucket.
115 hostname = socket.gethostname().split('.')[0] 124 hostname = socket.gethostname().split('.')[0]
116 uri_base_str = 'gs://res_download_test_%s_%s_%s' % ( 125 uri_base_str = 'gs://res-download-test-%s-%s-%s' % (
117 hostname, os.getpid(), int(time.time())) 126 hostname, os.getpid(), int(time.time()))
118 cls.src_bucket_uri = storage_uri('%s_dst' % uri_base_str) 127 cls.src_bucket_uri = storage_uri('%s-dst' % uri_base_str)
119 cls.src_bucket_uri.create_bucket() 128 cls.src_bucket_uri.create_bucket()
120 129
121 # Create test source objects. 130 # Create test source objects.
122 cls.empty_src_key_size = 0 131 cls.empty_src_key_size = 0
123 (cls.empty_src_key_as_string, cls.empty_src_key) = ( 132 (cls.empty_src_key_as_string, cls.empty_src_key) = (
124 cls.build_test_input_object('empty', cls.empty_src_key_size, 133 cls.build_test_input_object('empty', cls.empty_src_key_size,
125 debug=debug)) 134 debug=debug))
126 cls.small_src_key_size = 2 * 1024 # 2 KB. 135 cls.small_src_key_size = 2 * 1024 # 2 KB.
127 (cls.small_src_key_as_string, cls.small_src_key) = ( 136 (cls.small_src_key_as_string, cls.small_src_key) = (
128 cls.build_test_input_object('small', cls.small_src_key_size, 137 cls.build_test_input_object('small', cls.small_src_key_size,
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
205 tracker_file_name=self.tracker_file_name, num_retries=0) 214 tracker_file_name=self.tracker_file_name, num_retries=0)
206 try: 215 try:
207 self.small_src_key.get_contents_to_file( 216 self.small_src_key.get_contents_to_file(
208 self.dst_fp, cb=harnass.call, 217 self.dst_fp, cb=harnass.call,
209 res_download_handler=res_download_handler) 218 res_download_handler=res_download_handler)
210 self.fail('Did not get expected ResumableDownloadException') 219 self.fail('Did not get expected ResumableDownloadException')
211 except ResumableDownloadException, e: 220 except ResumableDownloadException, e:
212 # We'll get a ResumableDownloadException at this point because 221 # We'll get a ResumableDownloadException at this point because
213 # of CallbackTestHarnass (above). Check that the tracker file was 222 # of CallbackTestHarnass (above). Check that the tracker file was
214 # created correctly. 223 # created correctly.
215 self.assertEqual(e.disposition, ResumableTransferDisposition.ABORT) 224 self.assertEqual(e.disposition,
225 ResumableTransferDisposition.ABORT_CUR_PROCESS)
216 self.assertTrue(os.path.exists(self.tracker_file_name)) 226 self.assertTrue(os.path.exists(self.tracker_file_name))
217 f = open(self.tracker_file_name) 227 f = open(self.tracker_file_name)
218 etag_line = f.readline() 228 etag_line = f.readline()
219 m = re.search(ResumableDownloadHandler.ETAG_REGEX, etag_line) 229 m = re.search(ResumableDownloadHandler.ETAG_REGEX, etag_line)
220 f.close() 230 f.close()
221 self.assertTrue(m) 231 self.assertTrue(m)
222 232
223 def test_retryable_exception_recovery(self): 233 def test_retryable_exception_recovery(self):
224 """ 234 """
225 Tests handling of a retryable exception 235 Tests handling of a retryable exception
226 """ 236 """
227 # Test one of the RETRYABLE_EXCEPTIONS. 237 # Test one of the RETRYABLE_EXCEPTIONS.
228 exception = ResumableDownloadHandler.RETRYABLE_EXCEPTIONS[0] 238 exception = ResumableDownloadHandler.RETRYABLE_EXCEPTIONS[0]
229 harnass = CallbackTestHarnass(exception=exception) 239 harnass = CallbackTestHarnass(exception=exception)
230 res_download_handler = ResumableDownloadHandler(num_retries=1) 240 res_download_handler = ResumableDownloadHandler(num_retries=1)
231 self.small_src_key.get_contents_to_file( 241 self.small_src_key.get_contents_to_file(
232 self.dst_fp, cb=harnass.call, 242 self.dst_fp, cb=harnass.call,
233 res_download_handler=res_download_handler) 243 res_download_handler=res_download_handler)
234 # Ensure downloaded object has correct content. 244 # Ensure downloaded object has correct content.
235 self.assertEqual(self.small_src_key_size, 245 self.assertEqual(self.small_src_key_size,
236 get_cur_file_size(self.dst_fp)) 246 get_cur_file_size(self.dst_fp))
237 self.assertEqual(self.small_src_key_as_string, 247 self.assertEqual(self.small_src_key_as_string,
238 self.small_src_key.get_contents_as_string()) 248 self.small_src_key.get_contents_as_string())
239 249
250 def test_broken_pipe_recovery(self):
251 """
252 Tests handling of a Broken Pipe (which interacts with an httplib bug)
253 """
254 exception = IOError(errno.EPIPE, "Broken pipe")
255 harnass = CallbackTestHarnass(exception=exception)
256 res_download_handler = ResumableDownloadHandler(num_retries=1)
257 self.small_src_key.get_contents_to_file(
258 self.dst_fp, cb=harnass.call,
259 res_download_handler=res_download_handler)
260 # Ensure downloaded object has correct content.
261 self.assertEqual(self.small_src_key_size,
262 get_cur_file_size(self.dst_fp))
263 self.assertEqual(self.small_src_key_as_string,
264 self.small_src_key.get_contents_as_string())
265
240 def test_non_retryable_exception_handling(self): 266 def test_non_retryable_exception_handling(self):
241 """ 267 """
242 Tests resumable download that fails with a non-retryable exception 268 Tests resumable download that fails with a non-retryable exception
243 """ 269 """
244 harnass = CallbackTestHarnass( 270 harnass = CallbackTestHarnass(
245 exception=OSError(errno.EACCES, 'Permission denied')) 271 exception=OSError(errno.EACCES, 'Permission denied'))
246 res_download_handler = ResumableDownloadHandler(num_retries=1) 272 res_download_handler = ResumableDownloadHandler(num_retries=1)
247 try: 273 try:
248 self.small_src_key.get_contents_to_file( 274 self.small_src_key.get_contents_to_file(
249 self.dst_fp, cb=harnass.call, 275 self.dst_fp, cb=harnass.call,
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 harnass = CallbackTestHarnass( 322 harnass = CallbackTestHarnass(
297 fail_after_n_bytes=self.larger_src_key_size/2, num_times_to_fail=2) 323 fail_after_n_bytes=self.larger_src_key_size/2, num_times_to_fail=2)
298 res_download_handler = ResumableDownloadHandler( 324 res_download_handler = ResumableDownloadHandler(
299 tracker_file_name=self.tracker_file_name, num_retries=0) 325 tracker_file_name=self.tracker_file_name, num_retries=0)
300 try: 326 try:
301 self.larger_src_key.get_contents_to_file( 327 self.larger_src_key.get_contents_to_file(
302 self.dst_fp, cb=harnass.call, 328 self.dst_fp, cb=harnass.call,
303 res_download_handler=res_download_handler) 329 res_download_handler=res_download_handler)
304 self.fail('Did not get expected ResumableDownloadException') 330 self.fail('Did not get expected ResumableDownloadException')
305 except ResumableDownloadException, e: 331 except ResumableDownloadException, e:
306 self.assertEqual(e.disposition, ResumableTransferDisposition.ABORT) 332 self.assertEqual(e.disposition,
333 ResumableTransferDisposition.ABORT_CUR_PROCESS)
307 # Ensure a tracker file survived. 334 # Ensure a tracker file survived.
308 self.assertTrue(os.path.exists(self.tracker_file_name)) 335 self.assertTrue(os.path.exists(self.tracker_file_name))
309 # Try it one more time; this time should succeed. 336 # Try it one more time; this time should succeed.
310 self.larger_src_key.get_contents_to_file( 337 self.larger_src_key.get_contents_to_file(
311 self.dst_fp, cb=harnass.call, 338 self.dst_fp, cb=harnass.call,
312 res_download_handler=res_download_handler) 339 res_download_handler=res_download_handler)
313 self.assertEqual(self.larger_src_key_size, 340 self.assertEqual(self.larger_src_key_size,
314 get_cur_file_size(self.dst_fp)) 341 get_cur_file_size(self.dst_fp))
315 self.assertEqual(self.larger_src_key_as_string, 342 self.assertEqual(self.larger_src_key_as_string,
316 self.larger_src_key.get_contents_as_string()) 343 self.larger_src_key.get_contents_as_string())
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 # retries (initial download request will establish expected size to 390 # retries (initial download request will establish expected size to
364 # download server). 391 # download server).
365 res_download_handler = ResumableDownloadHandler( 392 res_download_handler = ResumableDownloadHandler(
366 tracker_file_name=self.tracker_file_name, num_retries=0) 393 tracker_file_name=self.tracker_file_name, num_retries=0)
367 try: 394 try:
368 self.larger_src_key.get_contents_to_file( 395 self.larger_src_key.get_contents_to_file(
369 self.dst_fp, cb=harnass.call, 396 self.dst_fp, cb=harnass.call,
370 res_download_handler=res_download_handler) 397 res_download_handler=res_download_handler)
371 self.fail('Did not get expected ResumableDownloadException') 398 self.fail('Did not get expected ResumableDownloadException')
372 except ResumableDownloadException, e: 399 except ResumableDownloadException, e:
373 self.assertEqual(e.disposition, ResumableTransferDisposition.ABORT) 400 # First abort (from harnass-forced failure) should be
401 # ABORT_CUR_PROCESS.
402 self.assertEqual(e.disposition, ResumableTransferDisposition.ABORT_C UR_PROCESS)
374 # Ensure a tracker file survived. 403 # Ensure a tracker file survived.
375 self.assertTrue(os.path.exists(self.tracker_file_name)) 404 self.assertTrue(os.path.exists(self.tracker_file_name))
376 # Try it again, this time with different src key (simulating an 405 # Try it again, this time with different src key (simulating an
377 # object that changes sizes between downloads). 406 # object that changes sizes between downloads).
378 try: 407 try:
379 self.small_src_key.get_contents_to_file( 408 self.small_src_key.get_contents_to_file(
380 self.dst_fp, res_download_handler=res_download_handler) 409 self.dst_fp, res_download_handler=res_download_handler)
381 self.fail('Did not get expected ResumableDownloadException') 410 self.fail('Did not get expected ResumableDownloadException')
382 except ResumableDownloadException, e: 411 except ResumableDownloadException, e:
412 # This abort should be a hard abort (object size changing during
413 # transfer).
383 self.assertEqual(e.disposition, ResumableTransferDisposition.ABORT) 414 self.assertEqual(e.disposition, ResumableTransferDisposition.ABORT)
384 self.assertNotEqual( 415 self.assertNotEqual(
385 e.message.find('md5 signature doesn\'t match etag'), -1) 416 e.message.find('md5 signature doesn\'t match etag'), -1)
386 417
387 def test_download_with_file_content_change_during_download(self): 418 def test_download_with_file_content_change_during_download(self):
388 """ 419 """
389 Tests resumable download on an object where the file content changes 420 Tests resumable download on an object where the file content changes
390 without changing length while download in progress 421 without changing length while download in progress
391 """ 422 """
392 harnass = CallbackTestHarnass( 423 harnass = CallbackTestHarnass(
393 fail_after_n_bytes=self.larger_src_key_size/2, num_times_to_fail=2) 424 fail_after_n_bytes=self.larger_src_key_size/2, num_times_to_fail=2)
394 # Set up first process' ResumableDownloadHandler not to do any 425 # Set up first process' ResumableDownloadHandler not to do any
395 # retries (initial download request will establish expected size to 426 # retries (initial download request will establish expected size to
396 # download server). 427 # download server).
397 res_download_handler = ResumableDownloadHandler( 428 res_download_handler = ResumableDownloadHandler(
398 tracker_file_name=self.tracker_file_name, num_retries=0) 429 tracker_file_name=self.tracker_file_name, num_retries=0)
399 dst_filename = self.dst_fp.name 430 dst_filename = self.dst_fp.name
400 try: 431 try:
401 self.larger_src_key.get_contents_to_file( 432 self.larger_src_key.get_contents_to_file(
402 self.dst_fp, cb=harnass.call, 433 self.dst_fp, cb=harnass.call,
403 res_download_handler=res_download_handler) 434 res_download_handler=res_download_handler)
404 self.fail('Did not get expected ResumableDownloadException') 435 self.fail('Did not get expected ResumableDownloadException')
405 except ResumableDownloadException, e: 436 except ResumableDownloadException, e:
406 self.assertEqual(e.disposition, ResumableTransferDisposition.ABORT) 437 # First abort (from harnass-forced failure) should be
438 # ABORT_CUR_PROCESS.
439 self.assertEqual(e.disposition,
440 ResumableTransferDisposition.ABORT_CUR_PROCESS)
407 # Ensure a tracker file survived. 441 # Ensure a tracker file survived.
408 self.assertTrue(os.path.exists(self.tracker_file_name)) 442 self.assertTrue(os.path.exists(self.tracker_file_name))
409 # Before trying again change the first byte of the file fragment 443 # Before trying again change the first byte of the file fragment
410 # that was already downloaded. 444 # that was already downloaded.
411 orig_size = get_cur_file_size(self.dst_fp) 445 orig_size = get_cur_file_size(self.dst_fp)
412 self.dst_fp.seek(0, os.SEEK_SET) 446 self.dst_fp.seek(0, os.SEEK_SET)
413 self.dst_fp.write('a') 447 self.dst_fp.write('a')
414 # Ensure the file size didn't change. 448 # Ensure the file size didn't change.
415 self.assertEqual(orig_size, get_cur_file_size(self.dst_fp)) 449 self.assertEqual(orig_size, get_cur_file_size(self.dst_fp))
416 try: 450 try:
417 self.larger_src_key.get_contents_to_file( 451 self.larger_src_key.get_contents_to_file(
418 self.dst_fp, cb=harnass.call, 452 self.dst_fp, cb=harnass.call,
419 res_download_handler=res_download_handler) 453 res_download_handler=res_download_handler)
420 self.fail('Did not get expected ResumableDownloadException') 454 self.fail('Did not get expected ResumableDownloadException')
421 except ResumableDownloadException, e: 455 except ResumableDownloadException, e:
456 # This abort should be a hard abort (file content changing during
457 # transfer).
422 self.assertEqual(e.disposition, ResumableTransferDisposition.ABORT) 458 self.assertEqual(e.disposition, ResumableTransferDisposition.ABORT)
423 self.assertNotEqual( 459 self.assertNotEqual(
424 e.message.find('md5 signature doesn\'t match etag'), -1) 460 e.message.find('md5 signature doesn\'t match etag'), -1)
425 # Ensure the bad data wasn't left around. 461 # Ensure the bad data wasn't left around.
426 self.assertFalse(os.path.exists(dst_filename)) 462 self.assertFalse(os.path.exists(dst_filename))
427 463
428 def test_download_with_invalid_tracker_etag(self): 464 def test_download_with_invalid_tracker_etag(self):
429 """ 465 """
430 Tests resumable download with a tracker file containing an invalid etag 466 Tests resumable download with a tracker file containing an invalid etag
431 """ 467 """
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
512 # that do it, with camelCase versions of these names). 548 # that do it, with camelCase versions of these names).
513 try: 549 try:
514 print 'Setting up %s...' % test_class.get_suite_description() 550 print 'Setting up %s...' % test_class.get_suite_description()
515 test_class.set_up_class(debug) 551 test_class.set_up_class(debug)
516 print 'Running %s...' % test_class.get_suite_description() 552 print 'Running %s...' % test_class.get_suite_description()
517 unittest.TextTestRunner(verbosity=2).run(suite) 553 unittest.TextTestRunner(verbosity=2).run(suite)
518 finally: 554 finally:
519 print 'Cleaning up after %s...' % test_class.get_suite_description() 555 print 'Cleaning up after %s...' % test_class.get_suite_description()
520 test_class.tear_down_class() 556 test_class.tear_down_class()
521 print '' 557 print ''
OLDNEW
« no previous file with comments | « tests/s3/test_pool.py ('k') | tests/s3/test_resumable_uploads.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698