X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/0eb72b526bf8bbb011551ecf019f604e17a534f1..b17f04b7797eda5a5d888264f7d480d762a9966f:/sdk/python/tests/test_keep_client.py diff --git a/sdk/python/tests/test_keep_client.py b/sdk/python/tests/test_keep_client.py index c2c4728253..872c93bae2 100644 --- a/sdk/python/tests/test_keep_client.py +++ b/sdk/python/tests/test_keep_client.py @@ -23,6 +23,7 @@ import urllib.parse import arvados import arvados.retry +import arvados.util from . import arvados_testutil as tutil from . import keepstub from . import run_test_server @@ -517,6 +518,77 @@ class KeepClientServiceTestCase(unittest.TestCase, tutil.ApiClientMock): self.assertEqual(1, req_mock.call_count) +@tutil.skip_sleep +class KeepXRequestIdTestCase(unittest.TestCase, tutil.ApiClientMock): + def setUp(self): + self.api_client = self.mock_keep_services(count=2) + self.keep_client = arvados.KeepClient(api_client=self.api_client) + self.data = b'xyzzy' + self.locator = '1271ed5ef305aadabc605b1609e24c52' + self.test_id = arvados.util.new_request_id() + self.assertRegex(self.test_id, r'^req-[a-z0-9]{20}$') + # If we don't set request_id to None explicitly here, it will + # return : + self.api_client.request_id = None + + def test_default_to_api_client_request_id(self): + self.api_client.request_id = self.test_id + with tutil.mock_keep_responses(self.locator, 200, 200) as mock: + self.keep_client.put(self.data) + self.assertEqual(2, len(mock.responses)) + for resp in mock.responses: + self.assertProvidedRequestId(resp) + + with tutil.mock_keep_responses(self.data, 200) as mock: + self.keep_client.get(self.locator) + self.assertProvidedRequestId(mock.responses[0]) + + with tutil.mock_keep_responses(b'', 200) as mock: + self.keep_client.head(self.locator) + self.assertProvidedRequestId(mock.responses[0]) + + def test_explicit_request_id(self): + with tutil.mock_keep_responses(self.locator, 200, 200) as mock: + self.keep_client.put(self.data, request_id=self.test_id) + self.assertEqual(2, len(mock.responses)) + for resp in mock.responses: + self.assertProvidedRequestId(resp) + + with tutil.mock_keep_responses(self.data, 200) as mock: + self.keep_client.get(self.locator, request_id=self.test_id) + self.assertProvidedRequestId(mock.responses[0]) + + with tutil.mock_keep_responses(b'', 200) as mock: + self.keep_client.head(self.locator, request_id=self.test_id) + self.assertProvidedRequestId(mock.responses[0]) + + def test_automatic_request_id(self): + with tutil.mock_keep_responses(self.locator, 200, 200) as mock: + self.keep_client.put(self.data) + self.assertEqual(2, len(mock.responses)) + for resp in mock.responses: + self.assertAutomaticRequestId(resp) + + with tutil.mock_keep_responses(self.data, 200) as mock: + self.keep_client.get(self.locator) + self.assertAutomaticRequestId(mock.responses[0]) + + with tutil.mock_keep_responses(b'', 200) as mock: + self.keep_client.head(self.locator) + self.assertAutomaticRequestId(mock.responses[0]) + + def assertAutomaticRequestId(self, resp): + hdr = [x for x in resp.getopt(pycurl.HTTPHEADER) + if x.startswith('X-Request-Id: ')][0] + self.assertNotEqual(hdr, 'X-Request-Id: '+self.test_id) + self.assertRegex(hdr, r'^X-Request-Id: req-[a-z0-9]{20}$') + + def assertProvidedRequestId(self, resp): + self.assertIn('X-Request-Id: '+self.test_id, + resp.getopt(pycurl.HTTPHEADER)) + + @tutil.skip_sleep class KeepClientRendezvousTestCase(unittest.TestCase, tutil.ApiClientMock): @@ -1099,7 +1171,7 @@ class AvoidOverreplication(unittest.TestCase, tutil.ApiClientMock): def finished(self): return False - + def setUp(self): self.copies = 3 self.pool = arvados.KeepClient.KeepWriterThreadPool( @@ -1143,7 +1215,7 @@ class AvoidOverreplication(unittest.TestCase, tutil.ApiClientMock): self.pool.add_task(ks, None) self.pool.join() self.assertEqual(self.pool.done(), self.copies-1) - + @tutil.skip_sleep class RetryNeedsMultipleServices(unittest.TestCase, tutil.ApiClientMock): @@ -1178,3 +1250,27 @@ class RetryNeedsMultipleServices(unittest.TestCase, tutil.ApiClientMock): with self.assertRaises(arvados.errors.KeepWriteError): self.keep_client.put('foo', num_retries=1, copies=2) self.assertEqual(2, req_mock.call_count) + +class KeepClientAPIErrorTest(unittest.TestCase): + def test_api_fail(self): + class ApiMock(object): + def __getattr__(self, r): + if r == "api_token": + return "abc" + else: + raise arvados.errors.KeepReadError() + keep_client = arvados.KeepClient(api_client=ApiMock(), + proxy='', local_store='') + + # The bug this is testing for is that if an API (not + # keepstore) exception is thrown as part of a get(), the next + # attempt to get that same block will result in a deadlock. + # This is why there are two get()s in a row. Unfortunately, + # the failure mode for this test is that the test suite + # deadlocks, there isn't a good way to avoid that without + # adding a special case that has no use except for this test. + + with self.assertRaises(arvados.errors.KeepReadError): + keep_client.get("acbd18db4cc2f85cedef654fccc4a4d8+3") + with self.assertRaises(arvados.errors.KeepReadError): + keep_client.get("acbd18db4cc2f85cedef654fccc4a4d8+3")