From 6cf2bd6626df8e4c68bd5463d9b030e315f76b42 Mon Sep 17 00:00:00 2001 From: Charles Hsu Date: Mon, 19 Sep 2016 23:18:18 +0800 Subject: Add additional headers for HEAD/GET/DELETE requests. Change-Id: I69276ba711057c122f97deac412e492e313c34dd Closes-Bug: 1615830 --- tests/unit/test_service.py | 158 ++++++++++++++++++++++++++++----- tests/unit/test_shell.py | 197 +++++++++++++++++++++++++++++++++++------ tests/unit/test_swiftclient.py | 2 +- 3 files changed, 307 insertions(+), 50 deletions(-) (limited to 'tests') diff --git a/tests/unit/test_service.py b/tests/unit/test_service.py index 546e495..e8385b7 100644 --- a/tests/unit/test_service.py +++ b/tests/unit/test_service.py @@ -291,9 +291,33 @@ class TestServiceDelete(_TestServiceBase): s = SwiftService() r = s._delete_object(mock_conn, 'test_c', 'test_o', self.opts, mock_q) - mock_conn.head_object.assert_called_once_with('test_c', 'test_o') + mock_conn.head_object.assert_called_once_with('test_c', 'test_o', + headers={}) mock_conn.delete_object.assert_called_once_with( - 'test_c', 'test_o', query_string=None, response_dict={} + 'test_c', 'test_o', query_string=None, response_dict={}, + headers={} + ) + self.assertEqual(expected_r, r) + + def test_delete_object_with_headers(self): + mock_q = Queue() + mock_conn = self._get_mock_connection() + mock_conn.head_object = Mock(return_value={}) + expected_r = self._get_expected({ + 'action': 'delete_object', + 'success': True + }) + opt_c = self.opts.copy() + opt_c['header'] = ['Skip-Middleware: Test'] + + s = SwiftService() + r = s._delete_object(mock_conn, 'test_c', 'test_o', opt_c, mock_q) + + mock_conn.head_object.assert_called_once_with( + 'test_c', 'test_o', headers={'Skip-Middleware': 'Test'}) + mock_conn.delete_object.assert_called_once_with( + 'test_c', 'test_o', query_string=None, response_dict={}, + headers={'Skip-Middleware': 'Test'} ) self.assertEqual(expected_r, r) @@ -317,9 +341,11 @@ class TestServiceDelete(_TestServiceBase): r = s._delete_object(mock_conn, 'test_c', 'test_o', self.opts, mock_q) after = time.time() - mock_conn.head_object.assert_called_once_with('test_c', 'test_o') + mock_conn.head_object.assert_called_once_with('test_c', 'test_o', + headers={}) mock_conn.delete_object.assert_called_once_with( - 'test_c', 'test_o', query_string=None, response_dict={} + 'test_c', 'test_o', query_string=None, response_dict={}, + headers={} ) self.assertEqual(expected_r, r) self.assertGreaterEqual(r['error_timestamp'], before) @@ -342,11 +368,13 @@ class TestServiceDelete(_TestServiceBase): s = SwiftService() r = s._delete_object(mock_conn, 'test_c', 'test_o', self.opts, mock_q) - mock_conn.head_object.assert_called_once_with('test_c', 'test_o') + mock_conn.head_object.assert_called_once_with('test_c', 'test_o', + headers={}) mock_conn.delete_object.assert_called_once_with( 'test_c', 'test_o', query_string='multipart-manifest=delete', - response_dict={} + response_dict={}, + headers={} ) self.assertEqual(expected_r, r) @@ -381,7 +409,8 @@ class TestServiceDelete(_TestServiceBase): self.assertEqual(expected_r, r) expected = [ - mock.call('test_c', 'test_o', query_string=None, response_dict={}), + mock.call('test_c', 'test_o', query_string=None, response_dict={}, + headers={}), mock.call('manifest_c', 'test_seg_1', response_dict={}), mock.call('manifest_c', 'test_seg_2', response_dict={})] mock_conn.delete_object.assert_has_calls(expected, any_order=True) @@ -394,10 +423,28 @@ class TestServiceDelete(_TestServiceBase): 'object': None }) - r = SwiftService._delete_empty_container(mock_conn, 'test_c') + r = SwiftService._delete_empty_container(mock_conn, 'test_c', + self.opts) + + mock_conn.delete_container.assert_called_once_with( + 'test_c', response_dict={}, headers={} + ) + self.assertEqual(expected_r, r) + + def test_delete_empty_container_with_headers(self): + mock_conn = self._get_mock_connection() + expected_r = self._get_expected({ + 'action': 'delete_container', + 'success': True, + 'object': None + }) + opt_c = self.opts.copy() + opt_c['header'] = ['Skip-Middleware: Test'] + + r = SwiftService._delete_empty_container(mock_conn, 'test_c', opt_c) mock_conn.delete_container.assert_called_once_with( - 'test_c', response_dict={} + 'test_c', response_dict={}, headers={'Skip-Middleware': 'Test'} ) self.assertEqual(expected_r, r) @@ -415,11 +462,11 @@ class TestServiceDelete(_TestServiceBase): before = time.time() s = SwiftService() - r = s._delete_empty_container(mock_conn, 'test_c') + r = s._delete_empty_container(mock_conn, 'test_c', {}) after = time.time() mock_conn.delete_container.assert_called_once_with( - 'test_c', response_dict={} + 'test_c', response_dict={}, headers={} ) self.assertEqual(expected_r, r) self.assertGreaterEqual(r['error_timestamp'], before) @@ -665,6 +712,34 @@ class TestServiceList(_TestServiceBase): self.assertEqual(expected_r_long, self._get_queue(mock_q)) self.assertIsNone(self._get_queue(mock_q)) + def test_list_account_with_headers(self): + mock_q = Queue() + mock_conn = self._get_mock_connection() + get_account_returns = [ + (None, [{'name': 'test_c'}]), + (None, []) + ] + mock_conn.get_account = Mock(side_effect=get_account_returns) + + expected_r = self._get_expected({ + 'action': 'list_account_part', + 'success': True, + 'listing': [{'name': 'test_c'}], + 'marker': '' + }) + opt_c = self.opts.copy() + opt_c['header'] = ['Skip-Middleware: True'] + SwiftService._list_account_job( + mock_conn, opt_c, mock_q + ) + self.assertEqual(expected_r, self._get_queue(mock_q)) + self.assertIsNone(self._get_queue(mock_q)) + self.assertEqual(mock_conn.get_account.mock_calls, [ + mock.call(headers={'Skip-Middleware': 'True'}, marker='', + prefix=None), + mock.call(headers={'Skip-Middleware': 'True'}, marker='test_c', + prefix=None)]) + def test_list_account_exception(self): mock_q = Queue() mock_conn = self._get_mock_connection() @@ -682,7 +757,7 @@ class TestServiceList(_TestServiceBase): mock_conn, self.opts, mock_q) mock_conn.get_account.assert_called_once_with( - marker='', prefix=None + marker='', prefix=None, headers={} ) self.assertEqual(expected_r, self._get_queue(mock_q)) self.assertIsNone(self._get_queue(mock_q)) @@ -767,6 +842,37 @@ class TestServiceList(_TestServiceBase): self.assertIsNone(self._get_queue(mock_q)) + def test_list_container_with_headers(self): + mock_q = Queue() + mock_conn = self._get_mock_connection() + get_container_returns = [ + (None, [{'name': 'test_o'}]), + (None, []) + ] + mock_conn.get_container = Mock(side_effect=get_container_returns) + + expected_r = self._get_expected({ + 'action': 'list_container_part', + 'container': 'test_c', + 'success': True, + 'listing': [{'name': 'test_o'}], + 'marker': '' + }) + + opt_c = self.opts.copy() + opt_c['header'] = ['Skip-Middleware: Test'] + + SwiftService._list_container_job( + mock_conn, 'test_c', opt_c, mock_q + ) + self.assertEqual(expected_r, self._get_queue(mock_q)) + self.assertIsNone(self._get_queue(mock_q)) + self.assertEqual(mock_conn.get_container.mock_calls, [ + mock.call('test_c', headers={'Skip-Middleware': 'Test'}, + delimiter='', marker='', prefix=None), + mock.call('test_c', headers={'Skip-Middleware': 'Test'}, + delimiter='', marker='test_o', prefix=None)]) + def test_list_container_exception(self): mock_q = Queue() mock_conn = self._get_mock_connection() @@ -786,7 +892,7 @@ class TestServiceList(_TestServiceBase): ) mock_conn.get_container.assert_called_once_with( - 'test_c', marker='', delimiter='', prefix=None + 'test_c', marker='', delimiter='', prefix=None, headers={} ) self.assertEqual(expected_r, self._get_queue(mock_q)) self.assertIsNone(self._get_queue(mock_q)) @@ -1397,11 +1503,13 @@ class TestServiceUpload(_TestServiceBase): mock_conn.head_object.assert_called_with('test_c', 'test_o') expected = [ mock.call('test_c_segments', prefix='test_o/prefix', - marker='', delimiter=None), + marker='', delimiter=None, headers={}), mock.call('test_c_segments', prefix='test_o/prefix', - marker="test_o/prefix/01", delimiter=None), + marker="test_o/prefix/01", delimiter=None, + headers={}), mock.call('test_c_segments', prefix='test_o/prefix', - marker="test_o/prefix/02", delimiter=None), + marker="test_o/prefix/02", delimiter=None, + headers={}), ] mock_conn.get_container.assert_has_calls(expected) @@ -2102,15 +2210,18 @@ class TestServiceDownload(_TestServiceBase): mock.call('test_c_segments', delimiter=None, prefix='test_o/prefix', - marker=''), + marker='', + headers={}), mock.call('test_c_segments', delimiter=None, prefix='test_o/prefix', - marker='test_o/prefix/2'), + marker='test_o/prefix/2', + headers={}), mock.call('test_c_segments', delimiter=None, prefix='test_o/prefix', - marker='test_o/prefix/3')]) + marker='test_o/prefix/3', + headers={})]) def test_download_object_job_skip_identical_nested_slo(self): with tempfile.NamedTemporaryFile() as f: @@ -2243,15 +2354,18 @@ class TestServiceDownload(_TestServiceBase): mock.call('test_c_segments', delimiter=None, prefix='test_o/prefix', - marker=''), + marker='', + headers={}), mock.call('test_c_segments', delimiter=None, prefix='test_o/prefix', - marker='test_o/prefix/2'), + marker='test_o/prefix/2', + headers={}), mock.call('test_c_segments', delimiter=None, prefix='test_o/prefix', - marker='test_o/prefix/3')]) + marker='test_o/prefix/3', + headers={})]) self.assertEqual(mock_conn.get_object.mock_calls, [ mock.call('test_c', 'test_o', diff --git a/tests/unit/test_shell.py b/tests/unit/test_shell.py index 33e297d..a6490b8 100644 --- a/tests/unit/test_shell.py +++ b/tests/unit/test_shell.py @@ -142,6 +142,28 @@ class TestShell(unittest.TestCase): ' Objects: 2\n' ' Bytes: 3\n') + @mock.patch('swiftclient.service.Connection') + def test_stat_account_with_headers(self, connection): + argv = ["", "stat", "-H", "Skip-Middleware: Test"] + return_headers = { + 'x-account-container-count': '1', + 'x-account-object-count': '2', + 'x-account-bytes-used': '3', + 'content-length': 0, + 'date': ''} + connection.return_value.head_account.return_value = return_headers + connection.return_value.url = 'http://127.0.0.1/v1/AUTH_account' + with CaptureOutput() as output: + swiftclient.shell.main(argv) + + self.assertEqual(output.out, + ' Account: AUTH_account\n' + 'Containers: 1\n' + ' Objects: 2\n' + ' Bytes: 3\n') + self.assertEqual(connection.return_value.head_account.mock_calls, [ + mock.call(headers={'Skip-Middleware': 'Test'})]) + @mock.patch('swiftclient.service.Connection') def test_stat_container(self, connection): return_headers = { @@ -168,6 +190,34 @@ class TestShell(unittest.TestCase): ' Sync To: other\n' ' Sync Key: secret\n') + @mock.patch('swiftclient.service.Connection') + def test_stat_container_with_headers(self, connection): + return_headers = { + 'x-container-object-count': '1', + 'x-container-bytes-used': '2', + 'x-container-read': 'test2:tester2', + 'x-container-write': 'test3:tester3', + 'x-container-sync-to': 'other', + 'x-container-sync-key': 'secret', + } + argv = ["", "stat", "container", "-H", "Skip-Middleware: Test"] + connection.return_value.head_container.return_value = return_headers + connection.return_value.url = 'http://127.0.0.1/v1/AUTH_account' + with CaptureOutput() as output: + swiftclient.shell.main(argv) + + self.assertEqual(output.out, + ' Account: AUTH_account\n' + 'Container: container\n' + ' Objects: 1\n' + ' Bytes: 2\n' + ' Read ACL: test2:tester2\n' + 'Write ACL: test3:tester3\n' + ' Sync To: other\n' + ' Sync Key: secret\n') + self.assertEqual(connection.return_value.head_container.mock_calls, [ + mock.call('container', headers={'Skip-Middleware': 'Test'})]) + @mock.patch('swiftclient.service.Connection') def test_stat_object(self, connection): return_headers = { @@ -194,6 +244,36 @@ class TestShell(unittest.TestCase): ' ETag: md5\n' ' Manifest: manifest\n') + @mock.patch('swiftclient.service.Connection') + def test_stat_object_with_headers(self, connection): + return_headers = { + 'x-object-manifest': 'manifest', + 'etag': 'md5', + 'last-modified': 'yesterday', + 'content-type': 'text/plain', + 'content-length': 42, + } + argv = ["", "stat", "container", "object", + "-H", "Skip-Middleware: Test"] + connection.return_value.head_object.return_value = return_headers + connection.return_value.url = 'http://127.0.0.1/v1/AUTH_account' + + with CaptureOutput() as output: + swiftclient.shell.main(argv) + + self.assertEqual(output.out, + ' Account: AUTH_account\n' + ' Container: container\n' + ' Object: object\n' + ' Content Type: text/plain\n' + 'Content Length: 42\n' + ' Last Modified: yesterday\n' + ' ETag: md5\n' + ' Manifest: manifest\n') + self.assertEqual(connection.return_value.head_object.mock_calls, [ + mock.call('container', 'object', + headers={'Skip-Middleware': 'Test'})]) + @mock.patch('swiftclient.service.Connection') def test_list_account(self, connection): # Test account listing @@ -206,8 +286,28 @@ class TestShell(unittest.TestCase): with CaptureOutput() as output: swiftclient.shell.main(argv) - calls = [mock.call(marker='', prefix=None), - mock.call(marker='container', prefix=None)] + calls = [mock.call(marker='', prefix=None, headers={}), + mock.call(marker='container', prefix=None, headers={})] + connection.return_value.get_account.assert_has_calls(calls) + + self.assertEqual(output.out, 'container\n') + + @mock.patch('swiftclient.service.Connection') + def test_list_account_with_headers(self, connection): + # Test account listing + connection.return_value.get_account.side_effect = [ + [None, [{'name': 'container'}]], + [None, []], + ] + + argv = ["", "list", '-H', 'Skip-Custom-Middleware: True'] + + with CaptureOutput() as output: + swiftclient.shell.main(argv) + calls = [mock.call(marker='', prefix=None, + headers={'Skip-Custom-Middleware': 'True'}), + mock.call(marker='container', prefix=None, + headers={'Skip-Custom-Middleware': 'True'})] connection.return_value.get_account.assert_has_calls(calls) self.assertEqual(output.out, 'container\n') @@ -223,8 +323,8 @@ class TestShell(unittest.TestCase): argv = ["", "list", "--lh"] with CaptureOutput() as output: swiftclient.shell.main(argv) - calls = [mock.call(marker='', prefix=None), - mock.call(marker='container', prefix=None)] + calls = [mock.call(marker='', prefix=None, headers={}), + mock.call(marker='container', prefix=None, headers={})] connection.return_value.get_account.assert_has_calls(calls) self.assertEqual(output.out, @@ -243,8 +343,8 @@ class TestShell(unittest.TestCase): argv = ["", "list", "--lh"] with CaptureOutput() as output: swiftclient.shell.main(argv) - calls = [mock.call(marker='', prefix=None), - mock.call(marker='container', prefix=None)] + calls = [mock.call(marker='', prefix=None, headers={}), + mock.call(marker='container', prefix=None, headers={})] connection.return_value.get_account.assert_has_calls(calls) self.assertEqual(output.out, @@ -273,7 +373,7 @@ class TestShell(unittest.TestCase): argv = ["", "list", "--lh", "--totals"] with CaptureOutput() as output: swiftclient.shell.main(argv) - calls = [mock.call(marker='', prefix=None)] + calls = [mock.call(marker='', prefix=None, headers={})] connection.return_value.get_account.assert_has_calls(calls) self.assertEqual(output.out, ' 6 3\n') @@ -287,9 +387,10 @@ class TestShell(unittest.TestCase): with CaptureOutput() as output: swiftclient.shell.main(argv) calls = [ - mock.call('container', marker='', delimiter=None, prefix=None), + mock.call('container', marker='', + delimiter=None, prefix=None, headers={}), mock.call('container', marker='object_a', - delimiter=None, prefix=None)] + delimiter=None, prefix=None, headers={})] connection.return_value.get_container.assert_has_calls(calls) self.assertEqual(output.out, 'object_a\n') @@ -305,9 +406,10 @@ class TestShell(unittest.TestCase): with CaptureOutput() as output: swiftclient.shell.main(argv) calls = [ - mock.call('container', marker='', delimiter=None, prefix=None), + mock.call('container', marker='', + delimiter=None, prefix=None, headers={}), mock.call('container', marker='object_a', - delimiter=None, prefix=None)] + delimiter=None, prefix=None, headers={})] connection.return_value.get_container.assert_has_calls(calls) self.assertEqual(output.out, @@ -315,6 +417,26 @@ class TestShell(unittest.TestCase): ' type/content object_a\n' ' 0\n') + @mock.patch('swiftclient.service.Connection') + def test_list_container_with_headers(self, connection): + connection.return_value.get_container.side_effect = [ + [None, [{'name': 'object_a'}]], + [None, []], + ] + argv = ["", "list", "container", "-H", "Skip-Middleware: Test"] + with CaptureOutput() as output: + swiftclient.shell.main(argv) + calls = [ + mock.call('container', marker='', + delimiter=None, prefix=None, + headers={'Skip-Middleware': 'Test'}), + mock.call('container', marker='object_a', + delimiter=None, prefix=None, + headers={'Skip-Middleware': 'Test'})] + connection.return_value.get_container.assert_has_calls(calls) + + self.assertEqual(output.out, 'object_a\n') + @mock.patch('swiftclient.service.makedirs') @mock.patch('swiftclient.service.Connection') def test_download(self, connection, makedirs): @@ -835,19 +957,19 @@ class TestShell(unittest.TestCase): swiftclient.shell.main(argv) connection.return_value.delete_object.assert_has_calls([ mock.call('container', 'object', query_string=None, - response_dict={}), + response_dict={}, headers={}), mock.call('container', 'obj\xe9ct2', query_string=None, - response_dict={}), + response_dict={}, headers={}), mock.call('container2', 'object', query_string=None, - response_dict={})], any_order=True) + response_dict={}, headers={})], 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={}), - mock.call('container2', response_dict={}), - mock.call('empty_container', response_dict={})]) + mock.call('container', response_dict={}, headers={}), + mock.call('container2', response_dict={}, headers={}), + mock.call('empty_container', response_dict={}, headers={})]) @mock.patch.object(swiftclient.service.SwiftService, '_should_bulk_delete', lambda *a: True) @@ -900,9 +1022,9 @@ class TestShell(unittest.TestCase): connection.return_value.post_account.mock_calls[2]) self.assertEqual( connection.return_value.delete_container.mock_calls, [ - mock.call('container', response_dict={}), - mock.call('container2', response_dict={}), - mock.call('empty_container', response_dict={})]) + mock.call('container', response_dict={}, headers={}), + mock.call('container2', response_dict={}, headers={}), + mock.call('empty_container', response_dict={}, headers={})]) @mock.patch('swiftclient.service.Connection') def test_delete_bulk_account_with_capabilities(self, connection): @@ -957,9 +1079,9 @@ class TestShell(unittest.TestCase): response_dict={})]) self.assertEqual( connection.return_value.delete_container.mock_calls, [ - mock.call('container', response_dict={}), - mock.call('container2', response_dict={}), - mock.call('empty_container', response_dict={})]) + mock.call('container', response_dict={}, headers={}), + mock.call('container2', response_dict={}, headers={}), + mock.call('empty_container', response_dict={}, headers={})]) self.assertEqual(connection.return_value.get_capabilities.mock_calls, [mock.call(None)]) # only one /info request @@ -976,9 +1098,29 @@ class TestShell(unittest.TestCase): connection.return_value.head_object.return_value = {} swiftclient.shell.main(argv) connection.return_value.delete_container.assert_called_with( - 'container', response_dict={}) + 'container', response_dict={}, headers={}) + connection.return_value.delete_object.assert_called_with( + 'container', 'object', query_string=None, response_dict={}, + headers={}) + + @mock.patch.object(swiftclient.service.SwiftService, '_should_bulk_delete', + lambda *a: False) + @mock.patch('swiftclient.service.Connection') + def test_delete_container_headers(self, connection): + connection.return_value.get_container.side_effect = [ + [None, [{'name': 'object'}]], + [None, []], + ] + connection.return_value.attempts = 0 + argv = ["", "delete", "container", "-H", "Skip-Middleware: Test"] + connection.return_value.head_object.return_value = {} + swiftclient.shell.main(argv) + connection.return_value.delete_container.assert_called_with( + 'container', response_dict={}, + headers={'Skip-Middleware': 'Test'}) connection.return_value.delete_object.assert_called_with( - 'container', 'object', query_string=None, response_dict={}) + 'container', 'object', query_string=None, response_dict={}, + headers={'Skip-Middleware': 'Test'}) @mock.patch.object(swiftclient.service.SwiftService, '_should_bulk_delete', lambda *a: True) @@ -1000,7 +1142,7 @@ class TestShell(unittest.TestCase): 'Accept': 'application/json'}, response_dict={}) connection.return_value.delete_container.assert_called_with( - 'container', response_dict={}) + 'container', response_dict={}, headers={}) def test_delete_verbose_output_utf8(self): container = 't\u00e9st_c' @@ -1043,7 +1185,8 @@ class TestShell(unittest.TestCase): connection.return_value.attempts = 0 swiftclient.shell.main(argv) connection.return_value.delete_object.assert_called_with( - 'container', 'object', query_string=None, response_dict={}) + 'container', 'object', query_string=None, response_dict={}, + headers={}) @mock.patch.object(swiftclient.service.SwiftService, '_should_bulk_delete', lambda *a: True) diff --git a/tests/unit/test_swiftclient.py b/tests/unit/test_swiftclient.py index 7d0dd9a..f717e52 100644 --- a/tests/unit/test_swiftclient.py +++ b/tests/unit/test_swiftclient.py @@ -3003,7 +3003,7 @@ class TestServiceToken(MockHttpTest): with mock.patch('swiftclient.client.http_connection', self.fake_http_connection(202)): conn = self.get_connection() - conn.delete_object('container1', 'obj1', 'a_string') + conn.delete_object('container1', 'obj1', query_string='a_string') self.assertEqual(1, len(self.request_log), self.request_log) for actual in self.iter_request_log(): self.assertEqual('DELETE', actual['method']) -- cgit v1.2.1