diff options
-rw-r--r-- | swiftclient/service.py | 12 | ||||
-rw-r--r-- | tests/unit/test_service.py | 105 | ||||
-rw-r--r-- | tests/unit/test_shell.py | 105 |
3 files changed, 168 insertions, 54 deletions
diff --git a/swiftclient/service.py b/swiftclient/service.py index 492055d..20c023b 100644 --- a/swiftclient/service.py +++ b/swiftclient/service.py @@ -1162,11 +1162,15 @@ class SwiftService(object): if fp is not None: fp.close() if 'x-object-meta-mtime' in headers and not no_file: - mtime = float(headers['x-object-meta-mtime']) - if options['out_file']: - utime(options['out_file'], (mtime, mtime)) + try: + mtime = float(headers['x-object-meta-mtime']) + except ValueError: + pass # no real harm; couldn't trust it anyway else: - utime(path, (mtime, mtime)) + if options['out_file']: + utime(options['out_file'], (mtime, mtime)) + else: + utime(path, (mtime, mtime)) res = { 'action': 'download_object', diff --git a/tests/unit/test_service.py b/tests/unit/test_service.py index 7522e65..64039ad 100644 --- a/tests/unit/test_service.py +++ b/tests/unit/test_service.py @@ -876,7 +876,7 @@ class TestServiceUpload(_TestServiceBase): 'status': 'uploaded', 'success': True, } - expected_mtime = float(os.path.getmtime(f.name)) + expected_mtime = '%f' % os.path.getmtime(f.name) mock_conn = mock.Mock() mock_conn.put_object.return_value = '' @@ -901,13 +901,13 @@ class TestServiceUpload(_TestServiceBase): 'use_slo': False, 'checksum': True}) - mtime = float(r['headers']['x-object-meta-mtime']) - self.assertAlmostEqual(mtime, expected_mtime, delta=0.5) + mtime = r['headers']['x-object-meta-mtime'] + self.assertEqual(expected_mtime, mtime) del r['headers']['x-object-meta-mtime'] self.assertEqual( 'test_c_segments/%E3%83%86%E3%82%B9%E3%83%88/dummy.dat/' + - '%f/30/10/' % mtime, r['headers']['x-object-manifest']) + '%s/30/10/' % mtime, r['headers']['x-object-manifest']) del r['headers']['x-object-manifest'] self.assertEqual(r['path'], f.name) @@ -1073,7 +1073,7 @@ class TestServiceUpload(_TestServiceBase): 'status': 'uploaded', 'success': True, } - expected_mtime = float(os.path.getmtime(f.name)) + expected_mtime = '%f' % os.path.getmtime(f.name) mock_conn = mock.Mock() mock_conn.put_object.return_value = '' @@ -1091,8 +1091,8 @@ class TestServiceUpload(_TestServiceBase): 'segment_size': 0, 'checksum': True}) - mtime = float(r['headers']['x-object-meta-mtime']) - self.assertAlmostEqual(mtime, expected_mtime, delta=0.5) + mtime = r['headers']['x-object-meta-mtime'] + self.assertEqual(expected_mtime, mtime) del r['headers']['x-object-meta-mtime'] self.assertEqual(r['path'], f.name) @@ -1535,6 +1535,97 @@ class TestServiceDownload(_TestServiceBase): ) self._assertDictEqual(expected_r, actual_r) + def test_download_object_job_with_mtime(self): + mock_conn = self._get_mock_connection() + objcontent = six.BytesIO(b'objcontent') + mock_conn.get_object.side_effect = [ + ({'content-type': 'text/plain', + 'etag': '2cbbfe139a744d6abbe695e17f3c1991', + 'x-object-meta-mtime': '1454113727.682512'}, + objcontent) + ] + expected_r = self._get_expected({ + 'success': True, + 'start_time': 1, + 'finish_time': 2, + 'headers_receipt': 3, + 'auth_end_time': 4, + 'read_length': len(b'objcontent'), + }) + + with mock.patch.object(builtins, 'open') as mock_open, \ + mock.patch('swiftclient.service.utime') as mock_utime: + written_content = Mock() + mock_open.return_value = written_content + s = SwiftService() + _opts = self.opts.copy() + _opts['no_download'] = False + actual_r = s._download_object_job( + mock_conn, 'test_c', 'test_o', _opts) + actual_r = dict( # Need to override the times we got from the call + actual_r, + **{ + 'start_time': 1, + 'finish_time': 2, + 'headers_receipt': 3 + } + ) + mock_open.assert_called_once_with('test_o', 'wb') + mock_utime.assert_called_once_with( + 'test_o', (1454113727.682512, 1454113727.682512)) + written_content.write.assert_called_once_with(b'objcontent') + + mock_conn.get_object.assert_called_once_with( + 'test_c', 'test_o', resp_chunk_size=65536, headers={}, + response_dict={} + ) + self._assertDictEqual(expected_r, actual_r) + + def test_download_object_job_bad_mtime(self): + mock_conn = self._get_mock_connection() + objcontent = six.BytesIO(b'objcontent') + mock_conn.get_object.side_effect = [ + ({'content-type': 'text/plain', + 'etag': '2cbbfe139a744d6abbe695e17f3c1991', + 'x-object-meta-mtime': 'foo'}, + objcontent) + ] + expected_r = self._get_expected({ + 'success': True, + 'start_time': 1, + 'finish_time': 2, + 'headers_receipt': 3, + 'auth_end_time': 4, + 'read_length': len(b'objcontent'), + }) + + with mock.patch.object(builtins, 'open') as mock_open, \ + mock.patch('swiftclient.service.utime') as mock_utime: + written_content = Mock() + mock_open.return_value = written_content + s = SwiftService() + _opts = self.opts.copy() + _opts['no_download'] = False + actual_r = s._download_object_job( + mock_conn, 'test_c', 'test_o', _opts) + actual_r = dict( # Need to override the times we got from the call + actual_r, + **{ + 'start_time': 1, + 'finish_time': 2, + 'headers_receipt': 3 + } + ) + mock_open.assert_called_once_with('test_o', 'wb') + self.assertEqual(0, len(mock_utime.mock_calls)) + written_content.write.assert_called_once_with(b'objcontent') + + mock_conn.get_object.assert_called_once_with( + 'test_c', 'test_o', resp_chunk_size=65536, headers={}, + response_dict={} + ) + self._assertDictEqual(expected_r, actual_r) + def test_download_object_job_exception(self): mock_conn = self._get_mock_connection() mock_conn.get_object = Mock(side_effect=self.exc) diff --git a/tests/unit/test_shell.py b/tests/unit/test_shell.py index 5313d41..c7bbf74 100644 --- a/tests/unit/test_shell.py +++ b/tests/unit/test_shell.py @@ -336,15 +336,17 @@ class TestShell(testtools.TestCase): with mock.patch(BUILTIN_OPEN) as mock_open: argv = ["", "download", "container"] swiftclient.shell.main(argv) - calls = [mock.call('container', 'object', - headers={}, resp_chunk_size=65536, - response_dict={}), - mock.call('container', 'pseudo/', - headers={}, resp_chunk_size=65536, - response_dict={})] - connection.return_value.get_object.assert_has_calls( - calls, any_order=True) - mock_open.assert_called_once_with('object', 'wb') + calls = [mock.call('container', 'object', + headers={}, resp_chunk_size=65536, + response_dict={}), + mock.call('container', 'pseudo/', + headers={}, resp_chunk_size=65536, + response_dict={})] + connection.return_value.get_object.assert_has_calls( + calls, any_order=True) + mock_open.assert_called_once_with('object', 'wb') + self.assertEqual([mock.call('pseudo')], makedirs.mock_calls) + makedirs.reset_mock() # Test downloading single object objcontent = six.BytesIO(b'objcontent') @@ -356,10 +358,11 @@ class TestShell(testtools.TestCase): with mock.patch(BUILTIN_OPEN) as mock_open: argv = ["", "download", "container", "object"] swiftclient.shell.main(argv) - connection.return_value.get_object.assert_called_with( - 'container', 'object', headers={}, resp_chunk_size=65536, - response_dict={}) - mock_open.assert_called_with('object', 'wb') + connection.return_value.get_object.assert_called_with( + 'container', 'object', headers={}, resp_chunk_size=65536, + response_dict={}) + mock_open.assert_called_with('object', 'wb') + self.assertEqual([], makedirs.mock_calls) # Test downloading single object to stdout objcontent = six.BytesIO(b'objcontent') @@ -396,13 +399,18 @@ class TestShell(testtools.TestCase): ] with mock.patch(BUILTIN_OPEN) as mock_open: - argv = ["", "download", "--all"] - swiftclient.shell.main(argv) - self.assertEqual(3, mock_shuffle.call_count) - mock_shuffle.assert_any_call(['container']) - mock_shuffle.assert_any_call(['object']) - mock_shuffle.assert_any_call(['pseudo/']) - mock_open.assert_called_once_with('container/object', 'wb') + with mock.patch('swiftclient.service.makedirs') as mock_mkdir: + argv = ["", "download", "--all"] + swiftclient.shell.main(argv) + self.assertEqual(3, mock_shuffle.call_count) + mock_shuffle.assert_any_call(['container']) + mock_shuffle.assert_any_call(['object']) + mock_shuffle.assert_any_call(['pseudo/']) + mock_open.assert_called_once_with('container/object', 'wb') + self.assertEqual([ + mock.call('container'), + mock.call('container/pseudo'), + ], mock_mkdir.mock_calls) # Test that the container and object lists are not shuffled mock_shuffle.reset_mock() @@ -418,10 +426,15 @@ class TestShell(testtools.TestCase): ] with mock.patch(BUILTIN_OPEN) as mock_open: - argv = ["", "download", "--all", "--no-shuffle"] - swiftclient.shell.main(argv) - self.assertEqual(0, mock_shuffle.call_count) - mock_open.assert_called_once_with('container/object', 'wb') + with mock.patch('swiftclient.service.makedirs') as mock_mkdir: + argv = ["", "download", "--all", "--no-shuffle"] + swiftclient.shell.main(argv) + self.assertEqual(0, mock_shuffle.call_count) + mock_open.assert_called_once_with('container/object', 'wb') + self.assertEqual([ + mock.call('container'), + mock.call('container/pseudo'), + ], mock_mkdir.mock_calls) @mock.patch('swiftclient.service.Connection') def test_download_no_content_type(self, connection): @@ -439,17 +452,21 @@ class TestShell(testtools.TestCase): connection.return_value.attempts = 0 with mock.patch(BUILTIN_OPEN) as mock_open: - argv = ["", "download", "container"] - swiftclient.shell.main(argv) - calls = [mock.call('container', 'object', - headers={}, resp_chunk_size=65536, - response_dict={}), - mock.call('container', 'pseudo/', - headers={}, resp_chunk_size=65536, - response_dict={})] - connection.return_value.get_object.assert_has_calls( - calls, any_order=True) - mock_open.assert_called_once_with('object', 'wb') + with mock.patch('swiftclient.service.makedirs') as mock_mkdir: + argv = ["", "download", "container"] + swiftclient.shell.main(argv) + calls = [mock.call('container', 'object', + headers={}, resp_chunk_size=65536, + response_dict={}), + mock.call('container', 'pseudo/', + headers={}, resp_chunk_size=65536, + response_dict={})] + connection.return_value.get_object.assert_has_calls( + calls, any_order=True) + mock_open.assert_called_once_with('object', 'wb') + self.assertEqual([ + mock.call('pseudo'), + ], mock_mkdir.mock_calls) @mock.patch('swiftclient.shell.walk') @mock.patch('swiftclient.service.Connection') @@ -734,14 +751,16 @@ class TestShell(testtools.TestCase): argv = ["", "delete", "--all"] connection.return_value.head_object.return_value = {} swiftclient.shell.main(argv) - self.assertEqual( - connection.return_value.delete_object.mock_calls, [ - mock.call('container', 'object', query_string=None, - response_dict={}), - mock.call('container', 'obj\xe9ct2', query_string=None, - response_dict={}), - mock.call('container2', 'object', query_string=None, - response_dict={})]) + connection.return_value.delete_object.assert_has_calls([ + mock.call('container', 'object', query_string=None, + response_dict={}), + mock.call('container', 'obj\xe9ct2', query_string=None, + response_dict={}), + mock.call('container2', 'object', query_string=None, + response_dict={})], any_order=True) + self.assertEqual(3, connection.return_value.delete_object.call_count, + 'Expected 3 calls but found\n%r' + % connection.return_value.delete_object.mock_calls) self.assertEqual( connection.return_value.delete_container.mock_calls, [ mock.call('container', response_dict={}), |