Merge branch '17989-pysdk-timeout' into main. Refs #17989
[arvados.git] / sdk / python / tests / test_api.py
index 795a9aa22a2b0ad161a6bf1ee26228ca1ba771f5..9b944f6c53e7ec0abc4d323d83d7ba0aece43741 100644 (file)
@@ -1,5 +1,10 @@
-#!/usr/bin/env python
+# Copyright (C) The Arvados Authors. All rights reserved.
+#
+# SPDX-License-Identifier: Apache-2.0
 
+from __future__ import absolute_import
+from builtins import str
+from builtins import range
 import arvados
 import collections
 import httplib2
@@ -12,12 +17,12 @@ import string
 import unittest
 
 import mock
-import run_test_server
+from . import run_test_server
 
 from apiclient import errors as apiclient_errors
 from apiclient import http as apiclient_http
 from arvados.api import OrderedJsonModel, RETRY_DELAY_INITIAL, RETRY_DELAY_BACKOFF, RETRY_COUNT
-from arvados_testutil import fake_httplib2_response, queue_with
+from .arvados_testutil import fake_httplib2_response, queue_with
 
 if not mimetypes.inited:
     mimetypes.init()
@@ -29,7 +34,7 @@ class ArvadosApiTest(run_test_server.TestCaseWithServers):
     def api_error_response(self, code, *errors):
         return (fake_httplib2_response(code, **self.ERROR_HEADERS),
                 json.dumps({'errors': errors,
-                            'error_token': '1234567890+12345678'}))
+                            'error_token': '1234567890+12345678'}).encode())
 
     def test_new_api_objects_with_cache(self):
         clients = [arvados.api('v1', cache=True) for index in [0, 1]]
@@ -37,7 +42,7 @@ class ArvadosApiTest(run_test_server.TestCaseWithServers):
 
     def test_empty_list(self):
         answer = arvados.api('v1').humans().list(
-            filters=[['uuid', 'is', None]]).execute()
+            filters=[['uuid', '=', None]]).execute()
         self.assertEqual(answer['items_available'], len(answer['items']))
 
     def test_nonempty_list(self):
@@ -81,7 +86,7 @@ class ArvadosApiTest(run_test_server.TestCaseWithServers):
         mock_responses = {
             'arvados.humans.delete': (
                 fake_httplib2_response(500, **self.ERROR_HEADERS),
-                "")
+                b"")
             }
         req_builder = apiclient_http.RequestMockBuilder(mock_responses)
         api = arvados.api('v1', requestBuilder=req_builder)
@@ -96,16 +101,32 @@ class ArvadosApiTest(run_test_server.TestCaseWithServers):
             text = "X" * maxsize
             arvados.api('v1').collections().create(body={"manifest_text": text}).execute()
 
+    # Checks for bug #17171
+    def test_default_request_timeout(self):
+        api = arvados.api('v1')
+        self.assertEqual(api._http.timeout, 10,
+            "Default timeout value should be 10")
+
+    # Checks for bug #17989
+    def test_custom_request_timeout(self):
+        api = arvados.api('v1', timeout=1234)
+        self.assertEqual(api._http.timeout, 1234,
+            "Requested timeout value was 1234")
+
     def test_ordered_json_model(self):
         mock_responses = {
-            'arvados.humans.get': (None, json.dumps(collections.OrderedDict(
-                        (c, int(c, 16)) for c in string.hexdigits))),
-            }
+            'arvados.humans.get': (
+                None,
+                json.dumps(collections.OrderedDict(
+                    (c, int(c, 16)) for c in string.hexdigits
+                )).encode(),
+            ),
+        }
         req_builder = apiclient_http.RequestMockBuilder(mock_responses)
         api = arvados.api('v1',
                           requestBuilder=req_builder, model=OrderedJsonModel())
         result = api.humans().get(uuid='test').execute()
-        self.assertEqual(string.hexdigits, ''.join(result.keys()))
+        self.assertEqual(string.hexdigits, ''.join(list(result.keys())))
 
 
 class RetryREST(unittest.TestCase):
@@ -133,6 +154,33 @@ class RetryREST(unittest.TestCase):
         self.assertEqual(sleep.call_args_list,
                          [mock.call(RETRY_DELAY_INITIAL)])
 
+    @mock.patch('time.sleep')
+    def test_same_automatic_request_id_on_retry(self, sleep):
+        self.api._http.orig_http_request.side_effect = (
+            socket.error('mock error'),
+            self.request_success,
+        )
+        self.api.users().current().execute()
+        calls = self.api._http.orig_http_request.call_args_list
+        self.assertEqual(len(calls), 2)
+        self.assertEqual(
+            calls[0][1]['headers']['X-Request-Id'],
+            calls[1][1]['headers']['X-Request-Id'])
+        self.assertRegex(calls[0][1]['headers']['X-Request-Id'], r'^req-[a-z0-9]{20}$')
+
+    @mock.patch('time.sleep')
+    def test_provided_request_id_on_retry(self, sleep):
+        self.api.request_id='fake-request-id'
+        self.api._http.orig_http_request.side_effect = (
+            socket.error('mock error'),
+            self.request_success,
+        )
+        self.api.users().current().execute()
+        calls = self.api._http.orig_http_request.call_args_list
+        self.assertEqual(len(calls), 2)
+        for call in calls:
+            self.assertEqual(call[1]['headers']['X-Request-Id'], 'fake-request-id')
+
     @mock.patch('time.sleep')
     def test_socket_error_retry_delay(self, sleep):
         self.api._http.orig_http_request.side_effect = socket.error('mock')
@@ -166,7 +214,7 @@ class RetryREST(unittest.TestCase):
         mock_conns = {str(i): mock.MagicMock() for i in range(2)}
         self.api._http.connections = mock_conns.copy()
         self.api.users().create(body={}).execute()
-        for c in mock_conns.itervalues():
+        for c in mock_conns.values():
             self.assertEqual(c.close.call_count, expect)
 
     @mock.patch('time.sleep')