Path: blob/develop/tests/unit/customizations/s3/test_results.py
1569 views
# Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.1#2# Licensed under the Apache License, Version 2.0 (the "License"). You3# may not use this file except in compliance with the License. A copy of4# the License is located at5#6# http://aws.amazon.com/apache2.0/7#8# or in the "license" file accompanying this file. This file is9# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF10# ANY KIND, either express or implied. See the License for the specific11# language governing permissions and limitations under the License.12from s3transfer.exceptions import CancelledError13from s3transfer.exceptions import FatalError1415from awscli.testutils import unittest16from awscli.testutils import mock17from awscli.compat import queue18from awscli.compat import StringIO19from awscli.customizations.s3.results import ShutdownThreadRequest20from awscli.customizations.s3.results import QueuedResult21from awscli.customizations.s3.results import ProgressResult22from awscli.customizations.s3.results import SuccessResult23from awscli.customizations.s3.results import FailureResult24from awscli.customizations.s3.results import ErrorResult25from awscli.customizations.s3.results import CtrlCResult26from awscli.customizations.s3.results import DryRunResult27from awscli.customizations.s3.results import FinalTotalSubmissionsResult28from awscli.customizations.s3.results import UploadResultSubscriber29from awscli.customizations.s3.results import UploadStreamResultSubscriber30from awscli.customizations.s3.results import DownloadResultSubscriber31from awscli.customizations.s3.results import DownloadStreamResultSubscriber32from awscli.customizations.s3.results import CopyResultSubscriber33from awscli.customizations.s3.results import DeleteResultSubscriber34from awscli.customizations.s3.results import ResultRecorder35from awscli.customizations.s3.results import ResultPrinter36from awscli.customizations.s3.results import OnlyShowErrorsResultPrinter37from awscli.customizations.s3.results import NoProgressResultPrinter38from awscli.customizations.s3.results import ResultProcessor39from awscli.customizations.s3.results import CommandResultRecorder40from awscli.customizations.s3.utils import relative_path41from awscli.customizations.s3.utils import WarningResult42from tests.unit.customizations.s3 import FakeTransferFuture43from tests.unit.customizations.s3 import FakeTransferFutureMeta44from tests.unit.customizations.s3 import FakeTransferFutureCallArgs454647class BaseResultSubscriberTest(unittest.TestCase):48def setUp(self):49self.result_queue = queue.Queue()5051self.bucket = 'mybucket'52self.key = 'mykey'53self.filename = 'myfile'54self.size = 20 * (1024 * 1024) # 20 MB5556self.ref_exception = Exception()57self.set_ref_transfer_futures()5859self.src = None60self.dest = None61self.transfer_type = None6263def set_ref_transfer_futures(self):64self.future = self.get_success_transfer_future('foo')65self.failure_future = self.get_failed_transfer_future(66self.ref_exception)6768def get_success_transfer_future(self, result):69return self._get_transfer_future(result=result)7071def get_failed_transfer_future(self, exception):72return self._get_transfer_future(exception=exception)7374def _get_transfer_future(self, result=None, exception=None):75call_args = self._get_transfer_future_call_args()76meta = FakeTransferFutureMeta(size=self.size, call_args=call_args)77return FakeTransferFuture(78result=result, exception=exception, meta=meta)7980def _get_transfer_future_call_args(self):81return FakeTransferFutureCallArgs(82fileobj=self.filename, key=self.key, bucket=self.bucket)8384def get_queued_result(self):85return self.result_queue.get(block=False)8687def assert_result_queue_is_empty(self):88self.assertTrue(self.result_queue.empty())899091class TestUploadResultSubscriber(BaseResultSubscriberTest):92def setUp(self):93super(TestUploadResultSubscriber, self).setUp()94self.src = relative_path(self.filename)95self.dest = 's3://' + self.bucket + '/' + self.key96self.transfer_type = 'upload'97self.result_subscriber = UploadResultSubscriber(self.result_queue)9899def test_on_queued(self):100self.result_subscriber.on_queued(self.future)101result = self.get_queued_result()102self.assert_result_queue_is_empty()103self.assertEqual(104result,105QueuedResult(106transfer_type=self.transfer_type,107src=self.src,108dest=self.dest,109total_transfer_size=self.size110)111)112113def test_on_progress(self):114# Simulate a queue result (i.e. submitting and processing the result)115# before processing the progress result.116self.result_subscriber.on_queued(self.future)117self.assertEqual(118self.get_queued_result(),119QueuedResult(120transfer_type=self.transfer_type,121src=self.src,122dest=self.dest,123total_transfer_size=self.size124)125)126self.assert_result_queue_is_empty()127128ref_bytes_transferred = 1024 * 1024 # 1MB129self.result_subscriber.on_progress(self.future, ref_bytes_transferred)130result = self.get_queued_result()131self.assert_result_queue_is_empty()132self.assertEqual(133result,134ProgressResult(135transfer_type=self.transfer_type,136src=self.src,137dest=self.dest,138bytes_transferred=ref_bytes_transferred,139total_transfer_size=self.size,140timestamp=mock.ANY141)142)143144def test_on_done_success(self):145# Simulate a queue result (i.e. submitting and processing the result)146# before processing the progress result.147self.result_subscriber.on_queued(self.future)148self.assertEqual(149self.get_queued_result(),150QueuedResult(151transfer_type=self.transfer_type,152src=self.src,153dest=self.dest,154total_transfer_size=self.size155)156)157self.assert_result_queue_is_empty()158159self.result_subscriber.on_done(self.future)160result = self.get_queued_result()161self.assert_result_queue_is_empty()162self.assertEqual(163result,164SuccessResult(165transfer_type=self.transfer_type,166src=self.src,167dest=self.dest,168)169)170171def test_on_done_failure(self):172# Simulate a queue result (i.e. submitting and processing the result)173# before processing the progress result.174self.result_subscriber.on_queued(self.future)175self.assertEqual(176self.get_queued_result(),177QueuedResult(178transfer_type=self.transfer_type,179src=self.src,180dest=self.dest,181total_transfer_size=self.size182)183)184self.assert_result_queue_is_empty()185186self.result_subscriber.on_done(self.failure_future)187result = self.get_queued_result()188self.assert_result_queue_is_empty()189self.assertEqual(190result,191FailureResult(192transfer_type=self.transfer_type,193src=self.src,194dest=self.dest,195exception=self.ref_exception196)197)198199def test_on_done_unexpected_cancelled(self):200# Simulate a queue result (i.e. submitting and processing the result)201# before processing the progress result.202self.result_subscriber.on_queued(self.future)203self.assertEqual(204self.get_queued_result(),205QueuedResult(206transfer_type=self.transfer_type,207src=self.src,208dest=self.dest,209total_transfer_size=self.size210)211)212self.assert_result_queue_is_empty()213214cancelled_exception = FatalError('some error')215cancelled_future = self.get_failed_transfer_future(cancelled_exception)216self.result_subscriber.on_done(cancelled_future)217result = self.get_queued_result()218self.assert_result_queue_is_empty()219self.assertEqual(result, ErrorResult(exception=cancelled_exception))220221def test_on_done_cancelled_for_ctrl_c(self):222# Simulate a queue result (i.e. submitting and processing the result)223# before processing the progress result.224self.result_subscriber.on_queued(self.future)225self.assertEqual(226self.get_queued_result(),227QueuedResult(228transfer_type=self.transfer_type,229src=self.src,230dest=self.dest,231total_transfer_size=self.size232)233)234self.assert_result_queue_is_empty()235236cancelled_exception = CancelledError('KeyboardInterrupt()')237cancelled_future = self.get_failed_transfer_future(cancelled_exception)238self.result_subscriber.on_done(cancelled_future)239result = self.get_queued_result()240self.assert_result_queue_is_empty()241self.assertEqual(result, CtrlCResult(exception=cancelled_exception))242243244class TestUploadStreamResultSubscriber(TestUploadResultSubscriber):245def setUp(self):246super(TestUploadStreamResultSubscriber, self).setUp()247self.src = '-'248self.result_subscriber = UploadStreamResultSubscriber(249self.result_queue)250251252class TestDownloadResultSubscriber(TestUploadResultSubscriber):253def setUp(self):254super(TestDownloadResultSubscriber, self).setUp()255self.src = 's3://' + self.bucket + '/' + self.key256self.dest = relative_path(self.filename)257self.transfer_type = 'download'258self.result_subscriber = DownloadResultSubscriber(self.result_queue)259260261class TestDownloadStreamResultSubscriber(TestDownloadResultSubscriber):262def setUp(self):263super(TestDownloadStreamResultSubscriber, self).setUp()264self.dest = '-'265self.result_subscriber = DownloadStreamResultSubscriber(266self.result_queue)267268269class TestCopyResultSubscriber(TestUploadResultSubscriber):270def setUp(self):271self.source_bucket = 'sourcebucket'272self.source_key = 'sourcekey'273self.copy_source = {274'Bucket': self.source_bucket,275'Key': self.source_key,276}277super(TestCopyResultSubscriber, self).setUp()278self.src = 's3://' + self.source_bucket + '/' + self.source_key279self.dest = 's3://' + self.bucket + '/' + self.key280self.transfer_type = 'copy'281self.result_subscriber = CopyResultSubscriber(self.result_queue)282283def _get_transfer_future_call_args(self):284return FakeTransferFutureCallArgs(285copy_source=self.copy_source, key=self.key, bucket=self.bucket)286287def test_transfer_type_override(self):288new_transfer_type = 'move'289self.result_subscriber = CopyResultSubscriber(290self.result_queue, new_transfer_type)291self.result_subscriber.on_queued(self.future)292result = self.get_queued_result()293self.assert_result_queue_is_empty()294expected = QueuedResult(295transfer_type=new_transfer_type,296src=self.src,297dest=self.dest,298total_transfer_size=self.size299)300self.assertEqual(result, expected)301302303class TestDeleteResultSubscriber(TestUploadResultSubscriber):304def setUp(self):305super(TestDeleteResultSubscriber, self).setUp()306self.src = 's3://' + self.bucket + '/' + self.key307self.dest = None308self.transfer_type = 'delete'309self.result_subscriber = DeleteResultSubscriber(self.result_queue)310311def _get_transfer_future_call_args(self):312return FakeTransferFutureCallArgs(313bucket=self.bucket, key=self.key)314315316class ResultRecorderTest(unittest.TestCase):317def setUp(self):318self.transfer_type = 'upload'319self.src = 'file'320self.dest = 's3://mybucket/mykey'321self.total_transfer_size = 20 * (1024 ** 1024) # 20MB322self.warning_message = 'a dummy warning message'323self.exception_message = 'a dummy exception message'324self.exception = Exception(self.exception_message)325self.result_recorder = ResultRecorder()326self.result_recorder.start_time = 0327328def test_queued_result(self):329self.result_recorder(330QueuedResult(331transfer_type=self.transfer_type, src=self.src,332dest=self.dest, total_transfer_size=self.total_transfer_size333)334)335self.assertEqual(336self.result_recorder.expected_bytes_transferred,337self.total_transfer_size338)339self.assertEqual(self.result_recorder.expected_files_transferred, 1)340341def test_multiple_queued_results(self):342num_results = 5343for i in range(num_results):344self.result_recorder(345QueuedResult(346transfer_type=self.transfer_type,347src=self.src + str(i),348dest=self.dest + str(i),349total_transfer_size=self.total_transfer_size350)351)352353self.assertEqual(354self.result_recorder.expected_bytes_transferred,355num_results * self.total_transfer_size356)357self.assertEqual(358self.result_recorder.expected_files_transferred, num_results)359360def test_queued_result_with_no_full_transfer_size(self):361self.result_recorder(362QueuedResult(363transfer_type=self.transfer_type, src=self.src,364dest=self.dest, total_transfer_size=None365)366)367# Since we do not know how many bytes are expected to be transferred368# do not incremenent the count as we have no idea how much it may be.369self.assertEqual(370self.result_recorder.expected_bytes_transferred, 0)371self.assertEqual(372self.result_recorder.expected_files_transferred, 1)373374def test_progress_result(self):375self.result_recorder(376QueuedResult(377transfer_type=self.transfer_type, src=self.src,378dest=self.dest, total_transfer_size=self.total_transfer_size379)380)381382bytes_transferred = 1024 * 1024 # 1MB383self.result_recorder(384ProgressResult(385transfer_type=self.transfer_type, src=self.src,386dest=self.dest, bytes_transferred=bytes_transferred,387total_transfer_size=self.total_transfer_size,388timestamp=0389)390)391392self.assertEqual(393self.result_recorder.bytes_transferred, bytes_transferred)394395def test_multiple_progress_results(self):396self.result_recorder(397QueuedResult(398transfer_type=self.transfer_type, src=self.src,399dest=self.dest, total_transfer_size=self.total_transfer_size400)401)402403bytes_transferred = 1024 * 1024 # 1MB404num_results = 5405for i in range(num_results):406self.result_recorder(407ProgressResult(408transfer_type=self.transfer_type, src=self.src,409dest=self.dest, bytes_transferred=bytes_transferred,410total_transfer_size=self.total_transfer_size,411timestamp=i412)413)414415self.assertEqual(416self.result_recorder.bytes_transferred,417num_results * bytes_transferred418)419420def test_progress_result_with_no_known_transfer_size(self):421self.result_recorder(422QueuedResult(423transfer_type=self.transfer_type, src=self.src,424dest=self.dest, total_transfer_size=None425)426)427428bytes_transferred = 1024 * 1024429self.result_recorder(430ProgressResult(431transfer_type=self.transfer_type, src=self.src,432dest=self.dest, bytes_transferred=bytes_transferred,433total_transfer_size=None, timestamp=0434)435)436# Because the transfer size is still not known, update the437# expected bytes transferred with what was actually transferred.438self.assertEqual(439self.result_recorder.bytes_transferred, bytes_transferred)440self.assertEqual(441self.result_recorder.expected_bytes_transferred, bytes_transferred)442443def test_progress_result_with_transfer_size_provided_during_progress(self):444self.result_recorder(445QueuedResult(446transfer_type=self.transfer_type, src=self.src,447dest=self.dest, total_transfer_size=None448)449)450451bytes_transferred = 1024 * 1024452self.result_recorder(453ProgressResult(454transfer_type=self.transfer_type, src=self.src,455dest=self.dest, bytes_transferred=bytes_transferred,456total_transfer_size=self.total_transfer_size,457timestamp=0458)459)460461self.assertEqual(462self.result_recorder.bytes_transferred, bytes_transferred)463# With the total size provided in the progress result, it should464# accurately be reflected in the expected bytes transferred.465self.assertEqual(466self.result_recorder.expected_bytes_transferred,467self.total_transfer_size)468469def test_captures_start_time_on_queued(self):470result_recorder = ResultRecorder()471self.assertIsNone(result_recorder.start_time)472result_recorder(473QueuedResult(474transfer_type=self.transfer_type, src=self.src,475dest=self.dest, total_transfer_size=self.total_transfer_size476)477)478self.assertIsInstance(result_recorder.start_time, float)479480def test_progress_calculates_transfer_speed(self):481start_time = 0482self.result_recorder.start_time = start_time483self.total_transfer_size = 10484self.result_recorder(485QueuedResult(486transfer_type=self.transfer_type, src=self.src,487dest=self.dest, total_transfer_size=self.total_transfer_size488)489)490# At this point nothing should have been uploaded so transfer speed491# is zero492self.assertEqual(self.result_recorder.bytes_transfer_speed, 0)493494self.result_recorder(495ProgressResult(496transfer_type=self.transfer_type, src=self.src,497dest=self.dest, bytes_transferred=1,498total_transfer_size=self.total_transfer_size,499timestamp=(start_time + 1)500)501)502503# One bytes has been transferred in one second504self.assertEqual(self.result_recorder.bytes_transfer_speed, 1)505506self.result_recorder(507ProgressResult(508transfer_type=self.transfer_type, src=self.src,509dest=self.dest, bytes_transferred=4,510total_transfer_size=self.total_transfer_size,511timestamp=(start_time + 2)512)513)514515# Five bytes have been transferred in two seconds516self.assertEqual(self.result_recorder.bytes_transfer_speed, 2.5)517518self.result_recorder(519ProgressResult(520transfer_type=self.transfer_type, src=self.src,521dest=self.dest, bytes_transferred=1,522total_transfer_size=self.total_transfer_size,523timestamp=(start_time + 3)524)525)526527# Six bytes have been transferred in three seconds528self.assertEqual(self.result_recorder.bytes_transfer_speed, 2.0)529530def test_success_result(self):531self.result_recorder(532QueuedResult(533transfer_type=self.transfer_type, src=self.src,534dest=self.dest, total_transfer_size=self.total_transfer_size535)536)537538self.result_recorder(539SuccessResult(540transfer_type=self.transfer_type, src=self.src,541dest=self.dest542)543)544self.assertEqual(self.result_recorder.files_transferred, 1)545self.assertEqual(self.result_recorder.files_failed, 0)546547def test_multiple_success_results(self):548num_results = 5549for i in range(num_results):550self.result_recorder(551QueuedResult(552transfer_type=self.transfer_type,553src=self.src + str(i),554dest=self.dest + str(i),555total_transfer_size=self.total_transfer_size556)557)558559for i in range(num_results):560self.result_recorder(561SuccessResult(562transfer_type=self.transfer_type,563src=self.src + str(i),564dest=self.dest + str(i),565)566)567568self.assertEqual(self.result_recorder.files_transferred, num_results)569self.assertEqual(self.result_recorder.files_failed, 0)570571def test_failure_result(self):572self.result_recorder(573QueuedResult(574transfer_type=self.transfer_type, src=self.src,575dest=self.dest, total_transfer_size=self.total_transfer_size576)577)578579self.result_recorder(580FailureResult(581transfer_type=self.transfer_type, src=self.src, dest=self.dest,582exception=self.exception583)584)585586self.assertEqual(self.result_recorder.files_transferred, 1)587self.assertEqual(self.result_recorder.files_failed, 1)588self.assertEqual(589self.result_recorder.bytes_failed_to_transfer,590self.total_transfer_size)591self.assertEqual(self.result_recorder.bytes_transferred, 0)592593def test_multiple_failure_results(self):594num_results = 5595for i in range(num_results):596self.result_recorder(597QueuedResult(598transfer_type=self.transfer_type,599src=self.src + str(i),600dest=self.dest + str(i),601total_transfer_size=self.total_transfer_size602)603)604605for i in range(num_results):606self.result_recorder(607FailureResult(608transfer_type=self.transfer_type,609src=self.src + str(i),610dest=self.dest + str(i),611exception=self.exception612)613)614615self.assertEqual(self.result_recorder.files_transferred, num_results)616self.assertEqual(self.result_recorder.files_failed, num_results)617self.assertEqual(618self.result_recorder.bytes_failed_to_transfer,619self.total_transfer_size * num_results)620self.assertEqual(self.result_recorder.bytes_transferred, 0)621622def test_failure_result_mid_progress(self):623self.result_recorder(624QueuedResult(625transfer_type=self.transfer_type, src=self.src,626dest=self.dest, total_transfer_size=self.total_transfer_size627)628)629630bytes_transferred = 1024 * 1024 # 1MB631self.result_recorder(632ProgressResult(633transfer_type=self.transfer_type, src=self.src,634dest=self.dest, bytes_transferred=bytes_transferred,635total_transfer_size=self.total_transfer_size,636timestamp=0637)638)639640self.result_recorder(641FailureResult(642transfer_type=self.transfer_type, src=self.src, dest=self.dest,643exception=self.exception644)645)646647self.assertEqual(self.result_recorder.files_transferred, 1)648self.assertEqual(self.result_recorder.files_failed, 1)649self.assertEqual(650self.result_recorder.bytes_failed_to_transfer,651self.total_transfer_size - bytes_transferred)652self.assertEqual(653self.result_recorder.bytes_transferred, bytes_transferred)654655def test_failure_result_still_did_not_know_transfer_size(self):656self.result_recorder(657QueuedResult(658transfer_type=self.transfer_type, src=self.src,659dest=self.dest, total_transfer_size=None660)661)662self.result_recorder(663FailureResult(664transfer_type=self.transfer_type, src=self.src, dest=self.dest,665exception=self.exception666)667)668self.assertEqual(self.result_recorder.files_transferred, 1)669self.assertEqual(self.result_recorder.files_failed, 1)670# Because we never knew how many bytes to expect, do not make671# any adjustments to bytes failed to transfer because it is impossible672# to know that.673self.assertEqual(674self.result_recorder.bytes_failed_to_transfer, 0)675676def test_failure_result_and_learned_of_transfer_size_in_progress(self):677self.result_recorder(678QueuedResult(679transfer_type=self.transfer_type, src=self.src,680dest=self.dest, total_transfer_size=None681)682)683684bytes_transferred = 1024 * 1024685self.result_recorder(686ProgressResult(687transfer_type=self.transfer_type, src=self.src,688dest=self.dest, bytes_transferred=bytes_transferred,689total_transfer_size=self.total_transfer_size,690timestamp=0691)692)693self.result_recorder(694FailureResult(695transfer_type=self.transfer_type, src=self.src, dest=self.dest,696exception=self.exception697)698)699self.assertEqual(self.result_recorder.files_transferred, 1)700self.assertEqual(self.result_recorder.files_failed, 1)701# Since we knew how many bytes to expect at some point, it should702# be accurately reflected in the amount failed to send when the703# failure result is processed.704self.assertEqual(705self.result_recorder.bytes_failed_to_transfer,706self.total_transfer_size - bytes_transferred)707708def test_can_handle_results_with_no_dest(self):709# This is just a quick smoke test to make sure that a result with710# no destination like deletes can be handled for the lifecycle of711# a transfer (i.e. being queued and finishing)712self.result_recorder(713QueuedResult(714transfer_type=self.transfer_type, src=self.src,715dest=None, total_transfer_size=None))716self.result_recorder(717SuccessResult(718transfer_type=self.transfer_type, src=self.src, dest=None))719self.assertEqual(self.result_recorder.expected_files_transferred, 1)720self.assertEqual(self.result_recorder.files_transferred, 1)721722def test_warning_result(self):723self.result_recorder(724WarningResult(message=self.warning_message))725self.assertEqual(self.result_recorder.files_warned, 1)726727def test_multiple_warning_results(self):728num_results = 5729for _ in range(num_results):730self.result_recorder(731WarningResult(message=self.warning_message))732self.assertEqual(self.result_recorder.files_warned, num_results)733734def test_error_result(self):735self.result_recorder(ErrorResult(exception=self.exception))736self.assertEqual(self.result_recorder.errors, 1)737738def test_ctrl_c_result(self):739self.result_recorder(CtrlCResult(Exception()))740self.assertEqual(self.result_recorder.errors, 1)741742def test_expected_totals_are_final(self):743self.result_recorder(744QueuedResult(745transfer_type=self.transfer_type, src=self.src,746dest=self.dest, total_transfer_size=self.total_transfer_size747)748)749self.result_recorder(FinalTotalSubmissionsResult(1))750self.assertEqual(751self.result_recorder.final_expected_files_transferred, 1)752self.assertTrue(self.result_recorder.expected_totals_are_final())753754def test_expected_totals_are_final_reaches_final_after_notification(self):755self.result_recorder(FinalTotalSubmissionsResult(1))756self.assertFalse(self.result_recorder.expected_totals_are_final())757self.result_recorder(758QueuedResult(759transfer_type=self.transfer_type, src=self.src,760dest=self.dest, total_transfer_size=self.total_transfer_size761)762)763self.assertTrue(self.result_recorder.expected_totals_are_final())764765def test_expected_totals_are_final_is_false_with_no_notification(self):766self.assertIsNone(767self.result_recorder.final_expected_files_transferred)768self.assertFalse(self.result_recorder.expected_totals_are_final())769self.result_recorder(770QueuedResult(771transfer_type=self.transfer_type, src=self.src,772dest=self.dest, total_transfer_size=self.total_transfer_size773)774)775# It should still be None because it has not yet been notified776# of finals.777self.assertIsNone(778self.result_recorder.final_expected_files_transferred)779# This should remain False as well.780self.assertFalse(self.result_recorder.expected_totals_are_final())781782def test_unknown_result_object(self):783self.result_recorder(object())784# Nothing should have been affected785self.assertEqual(self.result_recorder.bytes_transferred, 0)786self.assertEqual(self.result_recorder.expected_bytes_transferred, 0)787self.assertEqual(self.result_recorder.expected_files_transferred, 0)788self.assertEqual(self.result_recorder.files_transferred, 0)789790def test_result_with_unicode(self):791unicode_source = u'\u2713'792self.result_recorder(793QueuedResult(794transfer_type=self.transfer_type, src=unicode_source,795dest=self.dest, total_transfer_size=self.total_transfer_size796)797)798self.assertEqual(799self.result_recorder.expected_bytes_transferred,800self.total_transfer_size801)802self.assertEqual(self.result_recorder.expected_files_transferred, 1)803804def test_result_with_encoded_unicode(self):805unicode_source = u'\u2713'.encode('utf-8')806self.result_recorder(807QueuedResult(808transfer_type=self.transfer_type, src=unicode_source,809dest=self.dest, total_transfer_size=self.total_transfer_size810)811)812self.assertEqual(813self.result_recorder.expected_bytes_transferred,814self.total_transfer_size815)816self.assertEqual(self.result_recorder.expected_files_transferred, 1)817818819class BaseResultPrinterTest(unittest.TestCase):820def setUp(self):821self.result_recorder = ResultRecorder()822self.out_file = StringIO()823self.error_file = StringIO()824self.result_printer = ResultPrinter(825result_recorder=self.result_recorder,826out_file=self.out_file,827error_file=self.error_file828)829830def get_progress_result(self):831# NOTE: The actual values are not important for the purpose832# of printing as the ResultPrinter only looks at the type and833# the ResultRecorder to determine what to print out on progress.834return ProgressResult(835transfer_type=None, src=None, dest=None, bytes_transferred=None,836total_transfer_size=None, timestamp=0837)838839840class TestResultPrinter(BaseResultPrinterTest):841def test_unknown_result_object(self):842self.result_printer(object())843# Nothing should have been printed because of it.844self.assertEqual(self.out_file.getvalue(), '')845self.assertEqual(self.error_file.getvalue(), '')846847def test_progress(self):848mb = 1024 * 1024849850self.result_recorder.expected_bytes_transferred = 20 * mb851self.result_recorder.expected_files_transferred = 4852self.result_recorder.final_expected_files_transferred = 4853self.result_recorder.bytes_transferred = mb854self.result_recorder.files_transferred = 1855856progress_result = self.get_progress_result()857self.result_printer(progress_result)858ref_progress_statement = (859'Completed 1.0 MiB/20.0 MiB (0 Bytes/s) with 3 file(s) '860'remaining\r')861self.assertEqual(self.out_file.getvalue(), ref_progress_statement)862863def test_progress_with_no_expected_transfer_bytes(self):864self.result_recorder.files_transferred = 1865self.result_recorder.expected_files_transferred = 4866self.result_recorder.final_expected_files_transferred = 4867self.result_recorder.bytes_transferred = 0868self.result_recorder.expected_bytes_transferred = 0869870progress_result = self.get_progress_result()871self.result_printer(progress_result)872ref_progress_statement = (873'Completed 1 file(s) with 3 file(s) remaining\r')874self.assertEqual(self.out_file.getvalue(), ref_progress_statement)875876def test_progress_then_more_progress(self):877mb = 1024 * 1024878879progress_result = self.get_progress_result()880881# Add the first progress update and print it out882self.result_recorder.expected_bytes_transferred = 20 * mb883self.result_recorder.expected_files_transferred = 4884self.result_recorder.final_expected_files_transferred = 4885self.result_recorder.bytes_transferred = mb886self.result_recorder.files_transferred = 1887888self.result_printer(progress_result)889ref_progress_statement = (890'Completed 1.0 MiB/20.0 MiB (0 Bytes/s) with 3 file(s) remaining\r'891)892self.assertEqual(self.out_file.getvalue(), ref_progress_statement)893894# Add the second progress update895self.result_recorder.bytes_transferred += mb896self.result_printer(progress_result)897898# The result should be the combination of the two899ref_progress_statement = (900'Completed 1.0 MiB/20.0 MiB (0 Bytes/s) with 3 file(s) remaining\r'901'Completed 2.0 MiB/20.0 MiB (0 Bytes/s) with 3 file(s) remaining\r'902)903self.assertEqual(self.out_file.getvalue(), ref_progress_statement)904905def test_progress_still_calculating_totals(self):906mb = 1024 * 1024907908self.result_recorder.expected_bytes_transferred = 20 * mb909self.result_recorder.expected_files_transferred = 4910self.result_recorder.bytes_transferred = mb911self.result_recorder.files_transferred = 1912913progress_result = self.get_progress_result()914self.result_printer(progress_result)915ref_progress_statement = (916'Completed 1.0 MiB/~20.0 MiB (0 Bytes/s) with ~3 file(s) '917'remaining (calculating...)\r')918self.assertEqual(self.out_file.getvalue(), ref_progress_statement)919920def test_progress_still_calculating_totals_no_bytes(self):921self.result_recorder.expected_bytes_transferred = 0922self.result_recorder.expected_files_transferred = 4923self.result_recorder.bytes_transferred = 0924self.result_recorder.files_transferred = 1925926progress_result = self.get_progress_result()927self.result_printer(progress_result)928ref_progress_statement = (929'Completed 1 file(s) with ~3 file(s) remaining (calculating...)\r')930self.assertEqual(self.out_file.getvalue(), ref_progress_statement)931932def test_progress_with_transfer_speed_reporting(self):933mb = 1024 * 1024934935self.result_recorder.expected_bytes_transferred = 20 * mb936self.result_recorder.expected_files_transferred = 4937self.result_recorder.final_expected_files_transferred = 4938self.result_recorder.bytes_transferred = mb939self.result_recorder.files_transferred = 1940self.result_recorder.bytes_transfer_speed = 1024 * 7941942progress_result = self.get_progress_result()943self.result_printer(progress_result)944ref_progress_statement = (945'Completed 1.0 MiB/20.0 MiB (7.0 KiB/s) with 3 file(s) '946'remaining\r')947self.assertEqual(self.out_file.getvalue(), ref_progress_statement)948949def test_success(self):950transfer_type = 'upload'951src = 'file'952dest = 's3://mybucket/mykey'953954# Pretend that this is the final result in the result queue that955# is processed.956self.result_recorder.final_expected_files_transferred = 1957self.result_recorder.expected_files_transferred = 1958self.result_recorder.files_transferred = 1959960success_result = SuccessResult(961transfer_type=transfer_type, src=src, dest=dest)962963self.result_printer(success_result)964965ref_success_statement = (966'upload: file to s3://mybucket/mykey\n'967)968self.assertEqual(self.out_file.getvalue(), ref_success_statement)969970def test_success_with_progress(self):971mb = 1024 * 1024972973progress_result = self.get_progress_result()974975# Add the first progress update and print it out976self.result_recorder.expected_bytes_transferred = 20 * mb977self.result_recorder.expected_files_transferred = 4978self.result_recorder.final_expected_files_transferred = 4979self.result_recorder.bytes_transferred = mb980self.result_recorder.files_transferred = 1981self.result_printer(progress_result)982983# Add a success result and print it out.984transfer_type = 'upload'985src = 'file'986dest = 's3://mybucket/mykey'987success_result = SuccessResult(988transfer_type=transfer_type, src=src, dest=dest)989990self.result_recorder.files_transferred += 1991self.result_printer(success_result)992993# The statement should consist of:994# * The first progress statement995# * The success statement996# * And the progress again since the transfer is still ongoing997ref_statement = (998'Completed 1.0 MiB/20.0 MiB (0 Bytes/s) with 3 file(s) remaining\r'999'upload: file to s3://mybucket/mykey \n'1000'Completed 1.0 MiB/20.0 MiB (0 Bytes/s) with 2 file(s) remaining\r'1001)1002self.assertEqual(self.out_file.getvalue(), ref_statement)10031004def test_success_with_files_remaining(self):1005transfer_type = 'upload'1006src = 'file'1007dest = 's3://mybucket/mykey'10081009mb = 1024 * 10241010self.result_recorder.expected_files_transferred = 41011self.result_recorder.files_transferred = 11012self.result_recorder.expected_bytes_transferred = 4 * mb1013self.result_recorder.bytes_transferred = mb10141015success_result = SuccessResult(1016transfer_type=transfer_type, src=src, dest=dest)10171018self.result_printer(success_result)10191020ref_success_statement = (1021'upload: file to s3://mybucket/mykey\n'1022'Completed 1.0 MiB/~4.0 MiB (0 Bytes/s) with ~3 file(s) '1023'remaining (calculating...)\r'1024)1025self.assertEqual(self.out_file.getvalue(), ref_success_statement)10261027def test_success_but_no_expected_files_transferred_provided(self):1028transfer_type = 'upload'1029src = 'file'1030dest = 's3://mybucket/mykey'10311032mb = 1024 * 10241033self.result_recorder.expected_files_transferred = 11034self.result_recorder.files_transferred = 11035self.result_recorder.expected_bytes_transferred = mb1036self.result_recorder.bytes_transferred = mb10371038success_result = SuccessResult(1039transfer_type=transfer_type, src=src, dest=dest)10401041self.result_printer(success_result)10421043ref_success_statement = (1044'upload: file to s3://mybucket/mykey\n'1045'Completed 1.0 MiB/~1.0 MiB (0 Bytes/s) with ~0 file(s) '1046'remaining (calculating...)\r'1047)1048self.assertEqual(self.out_file.getvalue(), ref_success_statement)10491050def test_success_for_delete(self):1051transfer_type = 'delete'1052src = 's3://mybucket/mykey'10531054# Pretend that this is the final result in the result queue that1055# is processed.1056self.result_recorder.final_expected_files_transferred = 11057self.result_recorder.expected_files_transferred = 11058self.result_recorder.files_transferred = 110591060success_result = SuccessResult(1061transfer_type=transfer_type, src=src, dest=None)10621063self.result_printer(success_result)10641065ref_success_statement = (1066'delete: s3://mybucket/mykey\n'1067)1068self.assertEqual(self.out_file.getvalue(), ref_success_statement)10691070def test_delete_success_with_files_remaining(self):1071transfer_type = 'delete'1072src = 's3://mybucket/mykey'10731074self.result_recorder.expected_files_transferred = 41075self.result_recorder.files_transferred = 110761077success_result = SuccessResult(1078transfer_type=transfer_type, src=src, dest=None)10791080self.result_printer(success_result)10811082ref_success_statement = (1083'delete: s3://mybucket/mykey\n'1084'Completed 1 file(s) with ~3 file(s) remaining (calculating...)\r'1085)1086self.assertEqual(self.out_file.getvalue(), ref_success_statement)10871088def test_delete_success_but_no_expected_files_transferred_provided(self):1089transfer_type = 'delete'1090src = 's3://mybucket/mykey'10911092self.result_recorder.expected_files_transferred = 11093self.result_recorder.files_transferred = 110941095success_result = SuccessResult(1096transfer_type=transfer_type, src=src, dest=None)10971098self.result_printer(success_result)10991100ref_success_statement = (1101'delete: s3://mybucket/mykey\n'1102'Completed 1 file(s) with ~0 file(s) remaining (calculating...)\r'1103)1104self.assertEqual(self.out_file.getvalue(), ref_success_statement)11051106def test_failure(self):1107transfer_type = 'upload'1108src = 'file'1109dest = 's3://mybucket/mykey'11101111# Pretend that this is the final result in the result queue that1112# is processed.1113self.result_recorder.final_expected_files_transferred = 11114self.result_recorder.expected_files_transferred = 11115self.result_recorder.files_transferred = 111161117failure_result = FailureResult(1118transfer_type=transfer_type, src=src, dest=dest,1119exception=Exception('my exception'))11201121self.result_printer(failure_result)11221123ref_failure_statement = (1124'upload failed: file to s3://mybucket/mykey my exception\n'1125)1126self.assertEqual(self.error_file.getvalue(), ref_failure_statement)1127self.assertEqual(self.out_file.getvalue(), '')11281129def test_failure_with_files_remaining(self):1130shared_file = self.out_file1131self.result_printer = ResultPrinter(1132result_recorder=self.result_recorder,1133out_file=shared_file,1134error_file=shared_file1135)11361137transfer_type = 'upload'1138src = 'file'1139dest = 's3://mybucket/mykey'11401141mb = 1024 * 10241142self.result_recorder.expected_files_transferred = 41143self.result_recorder.files_transferred = 11144self.result_recorder.expected_bytes_transferred = 4 * mb1145self.result_recorder.bytes_transferred = mb11461147failure_result = FailureResult(1148transfer_type=transfer_type, src=src, dest=dest,1149exception=Exception('my exception'))11501151self.result_printer(failure_result)11521153ref_statement = (1154'upload failed: file to s3://mybucket/mykey my exception\n'1155'Completed 1.0 MiB/~4.0 MiB (0 Bytes/s) with ~3 file(s) '1156'remaining (calculating...)\r'1157)1158self.assertEqual(self.out_file.getvalue(), ref_statement)11591160def test_failure_but_no_expected_files_transferred_provided(self):1161shared_file = self.out_file1162self.result_printer = ResultPrinter(1163result_recorder=self.result_recorder,1164out_file=shared_file,1165error_file=shared_file1166)11671168transfer_type = 'upload'1169src = 'file'1170dest = 's3://mybucket/mykey'11711172mb = 1024 * 10241173self.result_recorder.expected_files_transferred = 11174self.result_recorder.files_transferred = 11175self.result_recorder.expected_bytes_transferred = mb1176self.result_recorder.bytes_transferred = mb11771178failure_result = FailureResult(1179transfer_type=transfer_type, src=src, dest=dest,1180exception=Exception('my exception'))11811182self.result_printer(failure_result)11831184ref_statement = (1185'upload failed: file to s3://mybucket/mykey my exception\n'1186'Completed 1.0 MiB/~1.0 MiB (0 Bytes/s) with ~0 file(s) '1187'remaining (calculating...)\r'1188)1189self.assertEqual(self.out_file.getvalue(), ref_statement)11901191def test_failure_with_progress(self):1192# Make errors and regular outprint go to the same file to track order.1193shared_file = self.out_file1194self.result_printer = ResultPrinter(1195result_recorder=self.result_recorder,1196out_file=shared_file,1197error_file=shared_file1198)11991200mb = 1024 * 102412011202progress_result = self.get_progress_result()12031204# Add the first progress update and print it out1205self.result_recorder.expected_bytes_transferred = 20 * mb1206self.result_recorder.expected_files_transferred = 41207self.result_recorder.final_expected_files_transferred = 41208self.result_recorder.bytes_transferred = mb1209self.result_recorder.files_transferred = 11210self.result_printer(progress_result)12111212# Add a success result and print it out.1213transfer_type = 'upload'1214src = 'file'1215dest = 's3://mybucket/mykey'1216failure_result = FailureResult(1217transfer_type=transfer_type, src=src, dest=dest,1218exception=Exception('my exception'))12191220self.result_recorder.bytes_failed_to_transfer = 3 * mb1221self.result_recorder.files_transferred += 11222self.result_printer(failure_result)12231224# The statement should consist of:1225# * The first progress statement1226# * The failure statement1227# * And the progress again since the transfer is still ongoing1228ref_statement = (1229'Completed 1.0 MiB/20.0 MiB (0 Bytes/s) with 3 file(s) remaining\r'1230'upload failed: file to s3://mybucket/mykey my exception \n'1231'Completed 4.0 MiB/20.0 MiB (0 Bytes/s) with 2 file(s) remaining\r'1232)1233self.assertEqual(shared_file.getvalue(), ref_statement)12341235def test_failure_for_delete(self):1236transfer_type = 'delete'1237src = 's3://mybucket/mykey'12381239# Pretend that this is the final result in the result queue that1240# is processed.1241self.result_recorder.final_expected_files_transferred = 11242self.result_recorder.expected_files_transferred = 11243self.result_recorder.files_transferred = 112441245failure_result = FailureResult(1246transfer_type=transfer_type, src=src, dest=None,1247exception=Exception('my exception'))12481249self.result_printer(failure_result)12501251ref_failure_statement = (1252'delete failed: s3://mybucket/mykey my exception\n'1253)1254self.assertEqual(self.error_file.getvalue(), ref_failure_statement)1255self.assertEqual(self.out_file.getvalue(), '')12561257def test_delete_failure_with_files_remaining(self):1258shared_file = self.out_file1259self.result_printer = ResultPrinter(1260result_recorder=self.result_recorder,1261out_file=shared_file,1262error_file=shared_file1263)12641265transfer_type = 'delete'1266src = 's3://mybucket/mykey'12671268self.result_recorder.expected_files_transferred = 41269self.result_recorder.expected_files_transferred = 41270self.result_recorder.files_transferred = 112711272failure_result = FailureResult(1273transfer_type=transfer_type, src=src, dest=None,1274exception=Exception('my exception'))12751276self.result_printer(failure_result)12771278ref_statement = (1279'delete failed: s3://mybucket/mykey my exception\n'1280'Completed 1 file(s) with ~3 file(s) remaining (calculating...)\r'1281)1282self.assertEqual(self.out_file.getvalue(), ref_statement)12831284def test_delete_failure_but_no_expected_files_transferred_provided(self):1285shared_file = self.out_file1286self.result_printer = ResultPrinter(1287result_recorder=self.result_recorder,1288out_file=shared_file,1289error_file=shared_file1290)12911292transfer_type = 'delete'1293src = 's3://mybucket/mykey'12941295self.result_recorder.expected_files_transferred = 11296self.result_recorder.files_transferred = 112971298failure_result = FailureResult(1299transfer_type=transfer_type, src=src, dest=None,1300exception=Exception('my exception'))13011302self.result_printer(failure_result)13031304ref_statement = (1305'delete failed: s3://mybucket/mykey my exception\n'1306'Completed 1 file(s) with ~0 file(s) remaining (calculating...)\r'1307)1308self.assertEqual(self.out_file.getvalue(), ref_statement)13091310def test_warning(self):1311# Pretend that this is the final result in the result queue that1312# is processed.1313self.result_recorder.final_expected_files_transferred = 11314self.result_recorder.expected_files_transferred = 11315self.result_recorder.files_transferred = 113161317self.result_printer(WarningResult('warning: my warning'))1318ref_warning_statement = 'warning: my warning\n'1319self.assertEqual(self.error_file.getvalue(), ref_warning_statement)1320self.assertEqual(self.out_file.getvalue(), '')13211322def test_warning_with_progress(self):1323# Make errors and regular outprint go to the same file to track order.1324shared_file = self.out_file1325self.result_printer = ResultPrinter(1326result_recorder=self.result_recorder,1327out_file=shared_file,1328error_file=shared_file1329)13301331mb = 1024 * 102413321333progress_result = self.get_progress_result()13341335# Add the first progress update and print it out1336self.result_recorder.expected_bytes_transferred = 20 * mb1337self.result_recorder.expected_files_transferred = 41338self.result_recorder.final_expected_files_transferred = 41339self.result_recorder.bytes_transferred = mb1340self.result_recorder.files_transferred = 11341self.result_printer(progress_result)13421343self.result_printer(WarningResult('warning: my warning'))13441345# The statement should consist of:1346# * The first progress statement1347# * The warning statement1348# * And the progress again since the transfer is still ongoing1349ref_statement = (1350'Completed 1.0 MiB/20.0 MiB (0 Bytes/s) with 3 file(s) remaining\r'1351'warning: my warning \n'1352'Completed 1.0 MiB/20.0 MiB (0 Bytes/s) with 3 file(s) remaining\r'1353)13541355self.assertEqual(shared_file.getvalue(), ref_statement)13561357def test_error(self):1358self.result_printer(ErrorResult(Exception('my exception')))1359ref_error_statement = 'fatal error: my exception\n'1360self.assertEqual(self.error_file.getvalue(), ref_error_statement)13611362def test_ctrl_c_error(self):1363self.result_printer(CtrlCResult(Exception()))1364ref_error_statement = 'cancelled: ctrl-c received\n'1365self.assertEqual(self.error_file.getvalue(), ref_error_statement)13661367def test_error_while_progress(self):1368mb = 1024 * 10241369self.result_recorder.expected_bytes_transferred = 20 * mb1370self.result_recorder.expected_files_transferred = 41371self.result_recorder.final_expected_files_transferred = 41372self.result_recorder.bytes_transferred = mb1373self.result_recorder.files_transferred = 113741375self.result_printer(ErrorResult(Exception('my exception')))1376ref_error_statement = 'fatal error: my exception\n'1377# Even though there was progress, we do not want to print the1378# progress because errors are really only seen when the entire1379# s3 command fails.1380self.assertEqual(self.error_file.getvalue(), ref_error_statement)13811382def test_dry_run(self):1383result = DryRunResult(1384transfer_type='upload',1385src='s3://mybucket/key',1386dest='./local/file'1387)1388self.result_printer(result)1389expected = '(dryrun) upload: s3://mybucket/key to ./local/file\n'1390self.assertEqual(self.out_file.getvalue(), expected)13911392def test_final_total_notification_with_no_more_expected_progress(self):1393transfer_type = 'upload'1394src = 'file'1395dest = 's3://mybucket/mykey'13961397mb = 1024 * 10241398self.result_recorder.expected_files_transferred = 11399self.result_recorder.files_transferred = 11400self.result_recorder.expected_bytes_transferred = mb1401self.result_recorder.bytes_transferred = mb14021403success_result = SuccessResult(1404transfer_type=transfer_type, src=src, dest=dest)14051406self.result_printer(success_result)14071408ref_success_statement = (1409'upload: file to s3://mybucket/mykey\n'1410'Completed 1.0 MiB/~1.0 MiB (0 Bytes/s) with ~0 file(s) '1411'remaining (calculating...)\r'1412)1413self.assertEqual(self.out_file.getvalue(), ref_success_statement)14141415# Now the result recorder/printer is notified it was just1416# there will be no more queueing. Therefore it should1417# clear out remaining progress if the expected number of files1418# transferred is equal to the number of files that has completed1419# because this is the final task meaning we want to clear any progress1420# that is displayed.1421self.result_recorder.final_expected_files_transferred = 11422self.result_printer(FinalTotalSubmissionsResult(1))1423ref_success_statement = (1424'upload: file to s3://mybucket/mykey\n'1425'Completed 1.0 MiB/~1.0 MiB (0 Bytes/s) '1426'with ~0 file(s) remaining (calculating...)\r'1427' '1428' \n'1429)1430self.assertEqual(self.out_file.getvalue(), ref_success_statement)14311432def test_final_total_does_not_print_out_newline_for_no_transfers(self):1433self.result_recorder.final_expected_files_transferred = 01434self.result_printer(FinalTotalSubmissionsResult(0))1435self.assertEqual(self.out_file.getvalue(), '')14361437def test_print_unicode_success_src_and_dest(self):1438# Pretend that this is the final result in the result queue that1439# is processed.1440self.result_recorder.final_expected_files_transferred = 11441self.result_recorder.expected_files_transferred = 11442self.result_recorder.files_transferred = 114431444result = SuccessResult(1445transfer_type='upload',1446src=u'/tmp/\u2713',1447dest='s3://mybucket/mykey'1448)1449self.result_printer(result)1450expected = u'upload: /tmp/\u2713 to s3://mybucket/mykey\n'1451self.assertEqual(self.out_file.getvalue(), expected)14521453def test_print_unicode_success_src(self):1454# Pretend that this is the final result in the result queue that1455# is processed.1456self.result_recorder.final_expected_files_transferred = 11457self.result_recorder.expected_files_transferred = 11458self.result_recorder.files_transferred = 114591460result = SuccessResult(1461transfer_type='delete',1462src=u's3://mybucket/tmp/\u2713',1463dest=None1464)1465self.result_printer(result)1466expected = u'delete: s3://mybucket/tmp/\u2713\n'1467self.assertEqual(self.out_file.getvalue(), expected)14681469def test_print_unicode_dryrun(self):1470result = DryRunResult(1471transfer_type='upload',1472src=u's3://mybucket/\u2713',1473dest='./local/file'1474)1475self.result_printer(result)1476expected = u'(dryrun) upload: s3://mybucket/\u2713 to ./local/file\n'1477self.assertEqual(self.out_file.getvalue(), expected)14781479def test_print_unicode_failure(self):1480transfer_type = 'upload'1481src = u'\u2713'1482dest = 's3://mybucket/mykey'14831484# Pretend that this is the final result in the result queue that1485# is processed.1486self.result_recorder.final_expected_files_transferred = 11487self.result_recorder.expected_files_transferred = 11488self.result_recorder.files_transferred = 114891490failure_result = FailureResult(1491transfer_type=transfer_type, src=src, dest=dest,1492exception=Exception('my exception'))14931494self.result_printer(failure_result)14951496ref_failure_statement = (1497u'upload failed: \u2713 to s3://mybucket/mykey my exception\n'1498)1499self.assertEqual(self.error_file.getvalue(), ref_failure_statement)1500self.assertEqual(self.out_file.getvalue(), '')15011502def test_print_unicode_warning(self):1503# Pretend that this is the final result in the result queue that1504# is processed.1505self.result_recorder.final_expected_files_transferred = 11506self.result_recorder.expected_files_transferred = 11507self.result_recorder.files_transferred = 115081509self.result_printer(WarningResult(u'warning: unicode exists \u2713'))1510ref_warning_statement = u'warning: unicode exists \u2713\n'1511self.assertEqual(self.error_file.getvalue(), ref_warning_statement)1512self.assertEqual(self.out_file.getvalue(), '')15131514def test_print_unicode_error(self):1515self.result_printer(ErrorResult(Exception('unicode exists \u2713')))1516ref_error_statement = 'fatal error: unicode exists \u2713\n'1517self.assertEqual(self.error_file.getvalue(), ref_error_statement)151815191520class TestNoProgressResultPrinter(BaseResultPrinterTest):1521def setUp(self):1522super(TestNoProgressResultPrinter, self).setUp()1523self.result_printer = NoProgressResultPrinter(1524result_recorder=self.result_recorder,1525out_file=self.out_file,1526error_file=self.error_file1527)15281529def test_does_not_print_progress_result(self):1530progress_result = self.get_progress_result()1531self.result_printer(progress_result)1532self.assertEqual(self.out_file.getvalue(), '')15331534def test_does_print_sucess_result(self):1535transfer_type = 'upload'1536src = 'file'1537dest = 's3://mybucket/mykey'1538success_result = SuccessResult(1539transfer_type=transfer_type, src=src, dest=dest)15401541self.result_printer(success_result)1542expected_message = 'upload: file to s3://mybucket/mykey\n'1543self.assertEqual(self.out_file.getvalue(), expected_message)15441545def test_print_failure_result(self):1546transfer_type = 'upload'1547src = 'file'1548dest = 's3://mybucket/mykey'1549failure_result = FailureResult(1550transfer_type=transfer_type, src=src, dest=dest,1551exception=Exception('my exception'))15521553self.result_printer(failure_result)15541555ref_failure_statement = (1556'upload failed: file to s3://mybucket/mykey my exception\n'1557)1558self.assertEqual(self.error_file.getvalue(), ref_failure_statement)15591560def test_print_warnings_result(self):1561self.result_printer(WarningResult('warning: my warning'))1562ref_warning_statement = 'warning: my warning\n'1563self.assertEqual(self.error_file.getvalue(), ref_warning_statement)15641565def test_final_total_does_not_try_to_clear_empty_progress(self):1566transfer_type = 'upload'1567src = 'file'1568dest = 's3://mybucket/mykey'15691570mb = 1024 * 10241571self.result_recorder.expected_files_transferred = 11572self.result_recorder.files_transferred = 11573self.result_recorder.expected_bytes_transferred = mb1574self.result_recorder.bytes_transferred = mb15751576success_result = SuccessResult(1577transfer_type=transfer_type, src=src, dest=dest)1578self.result_printer(success_result)1579ref_statement = 'upload: file to s3://mybucket/mykey\n'1580self.assertEqual(self.out_file.getvalue(), ref_statement)15811582self.result_recorder.final_expected_files_transferred = 11583self.result_printer(FinalTotalSubmissionsResult(1))1584self.assertEqual(self.out_file.getvalue(), ref_statement)158515861587class TestOnlyShowErrorsResultPrinter(BaseResultPrinterTest):1588def setUp(self):1589super(TestOnlyShowErrorsResultPrinter, self).setUp()1590self.result_printer = OnlyShowErrorsResultPrinter(1591result_recorder=self.result_recorder,1592out_file=self.out_file,1593error_file=self.error_file1594)15951596def test_does_not_print_progress_result(self):1597progress_result = self.get_progress_result()1598self.result_printer(progress_result)1599self.assertEqual(self.out_file.getvalue(), '')16001601def test_does_not_print_sucess_result(self):1602transfer_type = 'upload'1603src = 'file'1604dest = 's3://mybucket/mykey'1605success_result = SuccessResult(1606transfer_type=transfer_type, src=src, dest=dest)16071608self.result_printer(success_result)1609self.assertEqual(self.out_file.getvalue(), '')16101611def test_print_failure_result(self):1612transfer_type = 'upload'1613src = 'file'1614dest = 's3://mybucket/mykey'1615failure_result = FailureResult(1616transfer_type=transfer_type, src=src, dest=dest,1617exception=Exception('my exception'))16181619self.result_printer(failure_result)16201621ref_failure_statement = (1622'upload failed: file to s3://mybucket/mykey my exception\n'1623)1624self.assertEqual(self.error_file.getvalue(), ref_failure_statement)16251626def test_print_warnings_result(self):1627self.result_printer(WarningResult('warning: my warning'))1628ref_warning_statement = 'warning: my warning\n'1629self.assertEqual(self.error_file.getvalue(), ref_warning_statement)16301631def test_final_total_does_not_try_to_clear_empty_progress(self):1632transfer_type = 'upload'1633src = 'file'1634dest = 's3://mybucket/mykey'16351636mb = 1024 * 10241637self.result_recorder.expected_files_transferred = 11638self.result_recorder.files_transferred = 11639self.result_recorder.expected_bytes_transferred = mb1640self.result_recorder.bytes_transferred = mb16411642success_result = SuccessResult(1643transfer_type=transfer_type, src=src, dest=dest)1644self.result_printer(success_result)1645ref_statement = ''1646self.assertEqual(self.out_file.getvalue(), ref_statement)16471648self.result_recorder.final_expected_files_transferred = 11649self.result_printer(FinalTotalSubmissionsResult(1))1650# The final total submission result should be a noop and1651# not print anything out.1652self.assertEqual(self.out_file.getvalue(), ref_statement)165316541655class TestResultProcessor(unittest.TestCase):1656def setUp(self):1657self.result_queue = queue.Queue()1658self.result_recorder = mock.Mock()1659self.result_printer = mock.Mock()1660self.results_handled = []16611662self.result_processor = ResultProcessor(1663self.result_queue, [self.results_handled.append])16641665def _handle_result_with_exception(self, result):1666raise Exception()16671668def test_run(self):1669transfer_type = 'upload'1670src = 'src'1671dest = 'dest'1672total_transfer_size = 1024 * 10241673results_to_process = [1674QueuedResult(transfer_type, src, dest, total_transfer_size),1675SuccessResult(transfer_type, src, dest)1676]1677results_with_shutdown = results_to_process + [ShutdownThreadRequest()]16781679for result in results_with_shutdown:1680self.result_queue.put(result)1681self.result_processor.run()16821683self.assertEqual(self.results_handled, results_to_process)16841685def test_run_without_result_handlers(self):1686transfer_type = 'upload'1687src = 'src'1688dest = 'dest'1689total_transfer_size = 1024 * 10241690results_to_process = [1691QueuedResult(transfer_type, src, dest, total_transfer_size),1692SuccessResult(transfer_type, src, dest)1693]1694results_with_shutdown = results_to_process + [ShutdownThreadRequest()]16951696for result in results_with_shutdown:1697self.result_queue.put(result)1698self.result_processor = ResultProcessor(self.result_queue)1699self.result_processor.run()17001701# Ensure that the entire result queue got processed even though1702# there was no handlers provided.1703self.assertTrue(self.result_queue.empty())17041705def test_exception_handled_in_loop(self):1706transfer_type = 'upload'1707src = 'src'1708dest = 'dest'1709total_transfer_size = 1024 * 10241710results_to_process = [1711QueuedResult(transfer_type, src, dest, total_transfer_size),1712SuccessResult(transfer_type, src, dest)1713]1714results_with_shutdown = results_to_process + [ShutdownThreadRequest()]17151716for result in results_with_shutdown:1717self.result_queue.put(result)17181719results_handled_after_exception = []1720self.result_processor = ResultProcessor(1721self.result_queue,1722[self.results_handled.append, self._handle_result_with_exception,1723results_handled_after_exception.append])17241725self.result_processor.run()17261727self.assertEqual(self.results_handled, results_to_process)1728# The exception happens in the second handler, the exception being1729# thrown should result in the first handler and the ResultProcessor1730# continuing to process through the result queue despite the exception.1731# However, any handlers after the exception should not be run just1732# in case order of the handlers mattering and an unhandled exception1733# in one affects another handler.1734self.assertEqual(results_handled_after_exception, results_to_process)17351736def test_does_not_handle_results_after_receiving_error_result(self):1737transfer_type = 'upload'1738src = 'src'1739dest = 'dest'1740results_to_be_handled = [1741SuccessResult(transfer_type, src, dest),1742ErrorResult(Exception('my exception'))1743]1744result_not_to_be_handled = [1745ErrorResult(Exception('my second exception'))1746]1747results_with_shutdown = results_to_be_handled + \1748result_not_to_be_handled + [ShutdownThreadRequest()]17491750for result in results_with_shutdown:1751self.result_queue.put(result)17521753self.result_processor.run()1754# Only the results including and before the first the ErrorResult1755# should be handled. Any results after the first ErrorResult should1756# be ignored because ErrorResults are considered fatal meaning the1757# ResultProcessor needs to consume through the rest of result queue1758# to shutdown as quickly as possible.1759self.assertEqual(self.results_handled, results_to_be_handled)17601761def test_does_not_process_results_after_shutdown(self):1762transfer_type = 'upload'1763src = 'src'1764dest = 'dest'1765total_transfer_size = 1024 * 10241766results_to_process = [1767QueuedResult(transfer_type, src, dest, total_transfer_size),1768SuccessResult(transfer_type, src, dest)1769]1770results_with_shutdown = results_to_process + [1771ShutdownThreadRequest(), WarningResult('my warning')]17721773for result in results_with_shutdown:1774self.result_queue.put(result)1775self.result_processor.run()1776# Because a ShutdownThreadRequest was sent the processor should1777# not have processed anymore results stored after it.1778self.assertEqual(self.results_handled, results_to_process)177917801781class TestCommandResultRecorder(unittest.TestCase):1782def setUp(self):1783self.result_queue = queue.Queue()1784self.result_recorder = ResultRecorder()1785self.result_processor = ResultProcessor(1786self.result_queue, [self.result_recorder])1787self.command_result_recorder = CommandResultRecorder(1788self.result_queue, self.result_recorder, self.result_processor)17891790self.transfer_type = 'upload'1791self.src = 'file'1792self.dest = 's3://mybucket/mykey'1793self.total_transfer_size = 20 * (1024 ** 1024)17941795def test_success(self):1796with self.command_result_recorder:1797self.result_queue.put(1798QueuedResult(1799transfer_type=self.transfer_type, src=self.src,1800dest=self.dest,1801total_transfer_size=self.total_transfer_size1802)1803)1804self.result_queue.put(1805SuccessResult(1806transfer_type=self.transfer_type, src=self.src,1807dest=self.dest1808)1809)1810self.assertEqual(1811self.command_result_recorder.get_command_result(), (0, 0))18121813def test_fail(self):1814with self.command_result_recorder:1815self.result_queue.put(1816QueuedResult(1817transfer_type=self.transfer_type, src=self.src,1818dest=self.dest,1819total_transfer_size=self.total_transfer_size1820)1821)1822self.result_queue.put(1823FailureResult(1824transfer_type=self.transfer_type, src=self.src,1825dest=self.dest, exception=Exception('my exception')1826)1827)1828self.assertEqual(1829self.command_result_recorder.get_command_result(), (1, 0))18301831def test_warning(self):1832with self.command_result_recorder:1833self.result_queue.put(WarningResult(message='my warning'))1834self.assertEqual(1835self.command_result_recorder.get_command_result(), (0, 1))18361837def test_error(self):1838with self.command_result_recorder:1839raise Exception('my exception')1840self.assertEqual(1841self.command_result_recorder.get_command_result(), (1, 0))18421843def test_notify_total_submissions(self):1844total = 51845self.command_result_recorder.notify_total_submissions(total)1846self.assertEqual(1847self.result_queue.get(), FinalTotalSubmissionsResult(total))184818491850