2411: Add copyright notices to everything.
[arvados.git] / sdk / python / tests / test_retry.py
index 131872b0b3c660c29cc955e16cd01ad8433d581a..2d020059374b3dc3f42fd95010ebd675605ec929 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 builtins import zip
+from builtins import range
+from builtins import object
 import itertools
 import unittest
 
@@ -7,8 +12,6 @@ import arvados.errors as arv_error
 import arvados.retry as arv_retry
 import mock
 
-from arvados_testutil import fake_httplib2_response
-
 class RetryLoopTestMixin(object):
     @staticmethod
     def loop_success(result):
@@ -27,7 +30,7 @@ class RetryLoopTestMixin(object):
         responses = itertools.chain(results, itertools.repeat(None))
         retrier = arv_retry.RetryLoop(num_retries, self.loop_success,
                                       **kwargs)
-        for tries_left, response in itertools.izip(retrier, responses):
+        for tries_left, response in zip(retrier, responses):
             retrier.save_result(response)
         return retrier
 
@@ -143,9 +146,84 @@ class RetryLoopBackoffTestCase(unittest.TestCase, RetryLoopTestMixin):
 
     def test_backoff_multiplier(self, sleep_mock, time_mock):
         self.run_loop(5, 500, 501, 502, 503, 504, 505,
-                      backoff_start=5, backoff_growth=10)
+                      backoff_start=5, backoff_growth=10, max_wait=1000000000)
         self.check_backoff(sleep_mock, 5, 9)
 
 
+class CheckHTTPResponseSuccessTestCase(unittest.TestCase):
+    def results_map(self, *codes):
+        for code in codes:
+            yield code, arv_retry.check_http_response_success(code)
+
+    def check(assert_name):
+        def check_method(self, expected, *codes):
+            assert_func = getattr(self, assert_name)
+            for code, actual in self.results_map(*codes):
+                assert_func(expected, actual,
+                            "{} status flagged {}".format(code, actual))
+                if assert_name != 'assertIs':
+                    self.assertTrue(
+                        actual is True or actual is False or actual is None,
+                        "{} status returned {}".format(code, actual))
+        return check_method
+
+    check_is = check('assertIs')
+    check_is_not = check('assertIsNot')
+
+    def test_obvious_successes(self):
+        self.check_is(True, *list(range(200, 207)))
+
+    def test_obvious_stops(self):
+        self.check_is(False, 424, 426, 428, 431,
+                      *list(range(400, 408)) + list(range(410, 420)))
+
+    def test_obvious_retries(self):
+        self.check_is(None, 500, 502, 503, 504)
+
+    def test_4xx_retries(self):
+        self.check_is(None, 408, 409, 422, 423)
+
+    def test_5xx_failures(self):
+        self.check_is(False, 501, *list(range(505, 512)))
+
+    def test_1xx_not_retried(self):
+        self.check_is_not(None, 100, 101)
+
+    def test_redirects_not_retried(self):
+        self.check_is_not(None, *list(range(300, 309)))
+
+    def test_wacky_code_retries(self):
+        self.check_is(None, 0, 99, 600, -200)
+
+
+class RetryMethodTestCase(unittest.TestCase):
+    class Tester(object):
+        def __init__(self):
+            self.num_retries = 1
+
+        @arv_retry.retry_method
+        def check(self, a, num_retries=None, z=0):
+            return (a, num_retries, z)
+
+
+    def test_positional_arg_raises(self):
+        # unsupported use -- make sure we raise rather than ignore
+        with self.assertRaises(TypeError):
+            self.assertEqual((3, 2, 0), self.Tester().check(3, 2))
+
+    def test_keyword_arg_passed(self):
+        self.assertEqual((4, 3, 0), self.Tester().check(num_retries=3, a=4))
+
+    def test_not_specified(self):
+        self.assertEqual((0, 1, 0), self.Tester().check(0))
+
+    def test_not_specified_with_other_kwargs(self):
+        self.assertEqual((1, 1, 1), self.Tester().check(1, z=1))
+
+    def test_bad_call(self):
+        with self.assertRaises(TypeError):
+            self.Tester().check(num_retries=2)
+
+
 if __name__ == '__main__':
     unittest.main()