From 53be601f35e7bccd699439b3356bd37f49ab1933 Mon Sep 17 00:00:00 2001 From: "Ryan S. Brown" Date: Mon, 30 Nov 2015 13:02:22 -0500 Subject: [PATCH 1/1] Fix Glacier test failure in python 3.5 due to MagicMock In Python 3.5+, the ConcurrentUploader tests were failing due to an equality check. ``` FAIL: test_correct_low_level_api_calls (tests.unit.glacier.test_concurrent.TestConcurrentUploader) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/boto/tests/unit/glacier/test_concurrent.py", line 105, in test_correct_low_level_api_calls 'vault_name', mock.ANY, mock.ANY, 8 * 1024 * 1024) File "/home/ryansb/.pyenv/versions/3.5.0/lib/python3.5/unittest/mock.py", line 792, in assert_called_with raise AssertionError(_error_message()) from cause AssertionError: Expected call: complete_multipart_upload('vault_name', , , 8388608) Actual call: complete_multipart_upload('vault_name', , b'c5aac592460a9ac 7845e341090f6f9c81f201b63e5338ee8948a6fe6830c55dc', 8388608) ``` Note that the MagicMock in the second call position was failing to be equal to mock.ANY. In a Python 3.5 shell, this can be demonstrated as: ``` >>> from unittest import mock >>> m = mock.MagicMock() >>> mock.ANY == m True >>> m == mock.ANY False ``` The tests pass in all supported versions below 3.4, and to get around this in 3.5 I added a return value for the `initiate_multipart_upload` attribute of the mock that contains a request ID to be checked. This prevents `complete_multipart_upload` from being called with the MagicMock. --- tests/unit/glacier/test_concurrent.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/unit/glacier/test_concurrent.py b/tests/unit/glacier/test_concurrent.py index dd33e17..9ed9a89 100644 --- a/tests/unit/glacier/test_concurrent.py +++ b/tests/unit/glacier/test_concurrent.py @@ -95,14 +95,20 @@ class TestConcurrentUploader(unittest.TestCase): def test_correct_low_level_api_calls(self): api_mock = mock.MagicMock() + upload_id = '0898d645-ea45-4548-9a67-578f507ead49' + initiate_upload_mock = mock.Mock( + return_value={'UploadId': upload_id}) + # initiate_multipart_upload must return a body containing an `UploadId` + api_mock.attach_mock(initiate_upload_mock, 'initiate_multipart_upload') + uploader = FakeThreadedConcurrentUploader(api_mock, 'vault_name') uploader.upload('foofile') # The threads call the upload_part, so we're just verifying the # initiate/complete multipart API calls. - api_mock.initiate_multipart_upload.assert_called_with( + initiate_upload_mock.assert_called_with( 'vault_name', 4 * 1024 * 1024, None) api_mock.complete_multipart_upload.assert_called_with( - 'vault_name', mock.ANY, mock.ANY, 8 * 1024 * 1024) + 'vault_name', upload_id, mock.ANY, 8 * 1024 * 1024) def test_downloader_work_queue_is_correctly_populated(self): job = mock.MagicMock() -- 2.4.3