3147: Move PySDK HTTP test infrastructure to testutil.
authorBrett Smith <brett@curoverse.com>
Fri, 12 Sep 2014 20:46:54 +0000 (16:46 -0400)
committerBrett Smith <brett@curoverse.com>
Mon, 15 Sep 2014 20:31:02 +0000 (16:31 -0400)
Making this available to other test collections.

sdk/python/tests/arvados_testutil.py
sdk/python/tests/test_keep_client.py

index 77146db470c1aa93bf0e175d1434a546ad18e6ea..48fb013891564f04fdb69e19d71c6c648b01e97d 100644 (file)
@@ -3,16 +3,27 @@
 import errno
 import httplib
 import httplib2
+import mock
 import os
 import shutil
 import tempfile
 import unittest
 
+# Use this hostname when you want to make sure the traffic will be
+# instantly refused.  100::/64 is a dedicated black hole.
+TEST_HOST = '100::'
+
+skip_sleep = mock.patch('time.sleep', lambda n: None)  # clown'll eat me
+
 def fake_httplib2_response(code, **headers):
     headers.update(status=str(code),
                    reason=httplib.responses.get(code, "Unknown Response"))
     return httplib2.Response(headers)
 
+def mock_responses(body, *codes):
+    return mock.patch('httplib2.Http.request', side_effect=(
+            (fake_httplib2_response(code), body) for code in codes))
+
 class ArvadosBaseTestCase(unittest.TestCase):
     # This class provides common utility functions for our tests.
 
index 900143ebf7a2fa1962ed98926ddf246a818c758b..4ed2912ebe9c7453beb16775767cacaa5c539c78 100644 (file)
@@ -5,8 +5,8 @@ import unittest
 
 import arvados
 import arvados.retry
+import arvados_testutil as tutil
 import run_test_server
-from arvados_testutil import fake_httplib2_response
 
 class KeepTestCase(run_test_server.TestCaseWithServers):
     MAIN_SERVER = {}
@@ -232,15 +232,10 @@ class KeepClientRetryTestMixin(object):
     # supporting servers, and prevents side effects in case something hiccups.
     # To use this mixin, define DEFAULT_EXPECT, DEFAULT_EXCEPTION, and
     # run_method().
-    PROXY_ADDR = 'http://[100::]/'
+    PROXY_ADDR = 'http://[%s]:65535/' % (tutil.TEST_HOST,)
     TEST_DATA = 'testdata'
     TEST_LOCATOR = 'ef654c40ab4f1747fc699915d4f70902+8'
 
-    @staticmethod
-    def mock_responses(body, *codes):
-        return mock.patch('httplib2.Http.request', side_effect=(
-                (fake_httplib2_response(code), body) for code in codes))
-
     def new_client(self):
         return arvados.KeepClient(proxy=self.PROXY_ADDR, local_store='')
 
@@ -258,30 +253,28 @@ class KeepClientRetryTestMixin(object):
         self.assertRaises(error_class, self.run_method, *args, **kwargs)
 
     def test_immediate_success(self):
-        with self.mock_responses(self.DEFAULT_EXPECT, 200):
+        with tutil.mock_responses(self.DEFAULT_EXPECT, 200):
             self.check_success()
 
     def test_retry_then_success(self):
-        with self.mock_responses(self.DEFAULT_EXPECT, 500, 200):
+        with tutil.mock_responses(self.DEFAULT_EXPECT, 500, 200):
             self.check_success(num_retries=3)
 
     def test_no_default_retry(self):
-        with self.mock_responses(self.DEFAULT_EXPECT, 500, 200):
+        with tutil.mock_responses(self.DEFAULT_EXPECT, 500, 200):
             self.check_exception()
 
     def test_no_retry_after_permanent_error(self):
-        with self.mock_responses(self.DEFAULT_EXPECT, 403, 200):
+        with tutil.mock_responses(self.DEFAULT_EXPECT, 403, 200):
             self.check_exception(num_retries=3)
 
     def test_error_after_retries_exhausted(self):
-        with self.mock_responses(self.DEFAULT_EXPECT, 500, 500, 200):
+        with tutil.mock_responses(self.DEFAULT_EXPECT, 500, 500, 200):
             self.check_exception(num_retries=1)
 
 
-# Don't delay from HTTPRetryLoop's exponential backoff.
-no_backoff = mock.patch('time.sleep', lambda n: None)
-@no_backoff
-class KeepClientRetryGetTestCase(unittest.TestCase, KeepClientRetryTestMixin):
+@tutil.skip_sleep
+class KeepClientRetryGetTestCase(KeepClientRetryTestMixin, unittest.TestCase):
     DEFAULT_EXPECT = KeepClientRetryTestMixin.TEST_DATA
     DEFAULT_EXCEPTION = arvados.errors.KeepReadError
     HINTED_LOCATOR = KeepClientRetryTestMixin.TEST_LOCATOR + '+K@xyzzy'
@@ -291,7 +284,7 @@ class KeepClientRetryGetTestCase(unittest.TestCase, KeepClientRetryTestMixin):
         return self.new_client().get(locator, *args, **kwargs)
 
     def test_specific_exception_when_not_found(self):
-        with self.mock_responses(self.DEFAULT_EXPECT, 404, 200):
+        with tutil.mock_responses(self.DEFAULT_EXPECT, 404, 200):
             self.check_exception(arvados.errors.NotFoundError, num_retries=3)
 
     def test_general_exception_with_mixed_errors(self):
@@ -300,7 +293,7 @@ class KeepClientRetryGetTestCase(unittest.TestCase, KeepClientRetryTestMixin):
         # This test rigs up 50/50 disagreement between two servers, and
         # checks that it does not become a NotFoundError.
         client = self.new_client()
-        with self.mock_responses(self.DEFAULT_EXPECT, 404, 500):
+        with tutil.mock_responses(self.DEFAULT_EXPECT, 404, 500):
             with self.assertRaises(arvados.errors.KeepReadError) as exc_check:
                 client.get(self.HINTED_LOCATOR)
             self.assertNotIsInstance(
@@ -308,19 +301,20 @@ class KeepClientRetryGetTestCase(unittest.TestCase, KeepClientRetryTestMixin):
                 "mixed errors raised NotFoundError")
 
     def test_hint_server_can_succeed_without_retries(self):
-        with self.mock_responses(self.DEFAULT_EXPECT, 404, 200, 500):
+        with tutil.mock_responses(self.DEFAULT_EXPECT, 404, 200, 500):
             self.check_success(locator=self.HINTED_LOCATOR)
 
     def test_try_next_server_after_timeout(self):
-        side_effects = [socket.timeout("timed out"),
-                        (fake_httplib2_response(200), self.DEFAULT_EXPECT)]
+        side_effects = [
+            socket.timeout("timed out"),
+            (tutil.fake_httplib2_response(200), self.DEFAULT_EXPECT)]
         with mock.patch('httplib2.Http.request',
                         side_effect=iter(side_effects)):
             self.check_success(locator=self.HINTED_LOCATOR)
 
 
-@no_backoff
-class KeepClientRetryPutTestCase(unittest.TestCase, KeepClientRetryTestMixin):
+@tutil.skip_sleep
+class KeepClientRetryPutTestCase(KeepClientRetryTestMixin, unittest.TestCase):
     DEFAULT_EXPECT = KeepClientRetryTestMixin.TEST_LOCATOR
     DEFAULT_EXCEPTION = arvados.errors.KeepWriteError
 
@@ -329,5 +323,5 @@ class KeepClientRetryPutTestCase(unittest.TestCase, KeepClientRetryTestMixin):
         return self.new_client().put(data, copies, *args, **kwargs)
 
     def test_do_not_send_multiple_copies_to_same_server(self):
-        with self.mock_responses(self.DEFAULT_EXPECT, 200):
+        with tutil.mock_responses(self.DEFAULT_EXPECT, 200):
             self.check_exception(copies=2, num_retries=3)