def testRetryRetryExceptionExcluded(self, mockTime, mockSleep): """ Test that retry is not triggered if raised exeception is not in retryExceptions """ time_test_utils.configureTimeAndSleepMocks(mockTime, mockSleep) class TestExceptionA(Exception): pass class TestExceptionB(Exception): pass _retry = error_handling.retry(timeoutSec=1, initialRetryDelaySec=1, maxRetryDelaySec=10, retryExceptions=(TestExceptionA, )) @_retry def testFunction(): raise TestExceptionB("Test exception") with self.assertRaises(TestExceptionB): testFunction() self.assertEqual(mockSleep.call_count, 0)
def testWaitForFlusherAndGarbageCollectWithFlusherNotFound(self, getAllCustomMetricsMock, timeMock, sleepMock): time_test_utils.configureTimeAndSleepMocks(timeMock, sleepMock) flusherMetricName = delete_companies._DATA_PATH_FLUSHER_METRIC_PREFIX + "1" # Patch getAllCustomMetrics to return all negatives and positives getAllCustomMetricsMock.return_value = [{"name": "XIGNITE.FOOBAR.CLOSINGPRICE"}] # Execute and validate with self.assertRaises(delete_companies.FlusherMetricNotFound): delete_companies._waitForFlusherAndGarbageCollect( engineServer="host", engineApiKey="apikey", flusherMetricName=flusherMetricName )
def testNoRetryIfCallSucceeds(self, mockTime, mockSleep): """If the initial call succeeds, test that no retries are performed.""" time_test_utils.configureTimeAndSleepMocks(mockTime, mockSleep) _retry = error_handling.retry( timeoutSec=30, initialRetryDelaySec=2, maxRetryDelaySec=10) testFunction = Mock(__name__="testFunction", autospec=True) _retry(testFunction)() testFunction.assert_called_once_with()
def testNoRetryIfCallSucceeds(self, mockTime, mockSleep): """If the initial call succeeds, test that no retries are performed.""" time_test_utils.configureTimeAndSleepMocks(mockTime, mockSleep) _retry = error_handling.retry(timeoutSec=30, initialRetryDelaySec=2, maxRetryDelaySec=10) testFunction = Mock(__name__="testFunction", autospec=True) _retry(testFunction)() testFunction.assert_called_once_with()
def testReturnsExpectedWithExpectedArgs(self, mockTime, mockSleep): """Test that docorated function receives only expected args and that it returns the expected value on success.""" time_test_utils.configureTimeAndSleepMocks(mockTime, mockSleep) _retry = error_handling.retry( timeoutSec=30, initialRetryDelaySec=2, maxRetryDelaySec=10) testFunction = Mock(return_value=321, __name__="testFunction", autospec=True) returnValue = _retry(testFunction)(1, 2, a=3, b=4) self.assertEqual(returnValue, 321) testFunction.assert_called_once_with(1, 2, a=3, b=4)
def _runTransientErrorRetryTest(self, numErrors): with patch("time.sleep", autospec=True) as sleepMock, \ patch("time.time", autospec=True) as timeMock: time_test_utils.configureTimeAndSleepMocks(timeMock, sleepMock) for errorCode in _ALL_RETRIABLE_ERROR_CODES: clientSideEffects = [ sqlalchemy.exc.OperationalError( orig=MySQLdb.OperationalError(errorCode), statement="err", params=None) ] * numErrors + [DEFAULT] serverSideEffects = [ sqlalchemy.exc.InternalError( orig=MySQLdb.InternalError(errorCode), statement="err", params=None) ] * numErrors + [DEFAULT] if 3000 > errorCode >= 2000: # The error is client side. Return one operationalError, then pass with patch.object(Engine, "execute", spec_set=Engine.execute, side_effect=clientSideEffects) \ as mockExecute: retryOnTransientErrors(mockExecute)(Mock()) self.assertEqual(mockExecute.call_count, numErrors + 1) elif errorCode >= 1000: # The error is server side. Return one internalError, then pass with patch.object(Engine, "execute", spec_set=Engine.execute, side_effect=serverSideEffects) \ as mockExecute: retryOnTransientErrors(mockExecute)(Mock()) self.assertEqual(mockExecute.call_count, numErrors + 1) else: self.fail("Error code is neither client nor server: %s" % errorCode)
def testRetryRetryExceptionIncluded(self, mockTime, mockSleep): """Test that retry is triggered if raised exception is in retryExceptions.""" time_test_utils.configureTimeAndSleepMocks(mockTime, mockSleep) _retry = error_handling.retry( timeoutSec=1, initialRetryDelaySec=1, maxRetryDelaySec=10, retryExceptions=(TestParentException,)) @_retry def testFunction(): raise TestChildException("Test exception") with self.assertRaises(TestChildException): testFunction() self.assertEqual(mockSleep.call_count, 1)
def testReturnsExpectedWithExpectedArgs(self, mockTime, mockSleep): """Test that docorated function receives only expected args and that it returns the expected value on success.""" time_test_utils.configureTimeAndSleepMocks(mockTime, mockSleep) _retry = error_handling.retry(timeoutSec=30, initialRetryDelaySec=2, maxRetryDelaySec=10) testFunction = Mock(return_value=321, __name__="testFunction", autospec=True) returnValue = _retry(testFunction)(1, 2, a=3, b=4) self.assertEqual(returnValue, 321) testFunction.assert_called_once_with(1, 2, a=3, b=4)
def testRetryWaitsInitialRetryDelaySec(self, mockTime, mockSleep): """Test that delay times are correct.""" time_test_utils.configureTimeAndSleepMocks(mockTime, mockSleep) _retry = error_handling.retry( timeoutSec=30, initialRetryDelaySec=2, maxRetryDelaySec=10) testFunction = Mock(side_effect=TestParentException("Test exception"), __name__="testFunction", autospec=True) with self.assertRaises(TestParentException): _retry(testFunction)() self.assertEqual(mockSleep.mock_calls, [call(2), call(4), call(8), call(10), call(10)]) self.assertEqual(testFunction.call_count, 6)
def testRetryNoTimeForRetries(self, mockTime, mockSleep): """Test that when timeoutSec == 0, function is executed exactly once with no retries, and raises an exception on failure. """ time_test_utils.configureTimeAndSleepMocks(mockTime, mockSleep) _retry = error_handling.retry( timeoutSec=0, initialRetryDelaySec=0.2, maxRetryDelaySec=10) testFunction = Mock(side_effect=TestParentException("Test exception"), __name__="testFunction", autospec=True) with self.assertRaises(TestParentException): _retry(testFunction)() self.assertFalse(mockSleep.called) testFunction.assert_called_once_with()
def testConfigureTimeAndSleepMocks(self): timeMock = Mock(spec_set=time.time) sleepMock = Mock(spec_set=time.sleep) time_test_utils.configureTimeAndSleepMocks(timeMock, sleepMock) originalTime = timeMock() # Try with floating point sleepMock(10.5) now = timeMock() self.assertEqual(now, originalTime + 10.5) # Try with whole number sleepMock(5) self.assertEqual(timeMock(), originalTime + 10.5 + 5)
def testRetryRetryExceptionIncluded(self, mockTime, mockSleep): """Test that retry is triggered if raised exception is in retryExceptions.""" time_test_utils.configureTimeAndSleepMocks(mockTime, mockSleep) _retry = error_handling.retry(timeoutSec=1, initialRetryDelaySec=1, maxRetryDelaySec=10, retryExceptions=(TestParentException, )) @_retry def testFunction(): raise TestChildException("Test exception") with self.assertRaises(TestChildException): testFunction() self.assertEqual(mockSleep.call_count, 1)
def testRetryRetryFilter(self, mockTime, mockSleep): """Test that if retryFilter is specified and exception is in retryExceptions, retries iff retryFilter returns true.""" time_test_utils.configureTimeAndSleepMocks(mockTime, mockSleep) # Test with retryFilter returning True _retryTrueFilter = error_handling.retry( timeoutSec=1, initialRetryDelaySec=1, maxRetryDelaySec=10, retryExceptions=(TestParentException, ), retryFilter=lambda _1, _2, _3: True) @_retryTrueFilter def testFunctionTrue(): raise TestChildException("Test exception") with self.assertRaises(TestChildException): testFunctionTrue() self.assertEqual(mockSleep.call_count, 1) # Test with retryFilter returning False mockSleep.reset_mock() _retryFalseFilter = error_handling.retry( timeoutSec=1, initialRetryDelaySec=1, maxRetryDelaySec=10, retryExceptions=(TestParentException, ), retryFilter=lambda _1, _2, _3: False) @_retryFalseFilter def testFunctionFalse(): raise TestChildException("Test exception") with self.assertRaises(TestChildException): testFunctionFalse() self.assertEqual(mockSleep.call_count, 0)
def testWaitForFlusherAndGarbageCollectWithFlusherNotFound( self, getAllCustomMetricsMock, timeMock, sleepMock): time_test_utils.configureTimeAndSleepMocks(timeMock, sleepMock) flusherMetricName = ( delete_companies._DATA_PATH_FLUSHER_METRIC_PREFIX + "1") # Patch getAllCustomMetrics to return all negatives and positives getAllCustomMetricsMock.return_value = [{ "name": "XIGNITE.FOOBAR.CLOSINGPRICE" }] # Execute and validate with self.assertRaises(delete_companies.FlusherMetricNotFound): delete_companies._waitForFlusherAndGarbageCollect( engineServer="host", engineApiKey="apikey", flusherMetricName=flusherMetricName)
def testRetryNoTimeForRetries(self, mockTime, mockSleep): """Test that when timeoutSec == 0, function is executed exactly once with no retries, and raises an exception on failure. """ time_test_utils.configureTimeAndSleepMocks(mockTime, mockSleep) _retry = error_handling.retry(timeoutSec=0, initialRetryDelaySec=0.2, maxRetryDelaySec=10) testFunction = Mock(side_effect=TestParentException("Test exception"), __name__="testFunction", autospec=True) with self.assertRaises(TestParentException): _retry(testFunction)() self.assertFalse(mockSleep.called) testFunction.assert_called_once_with()
def testFailsFirstSucceedsLater(self, mockTime, mockSleep): """If initial attempts fail but subsequent attempt succeeds, ensure that expected number of retries is performed and expected value is returned.""" time_test_utils.configureTimeAndSleepMocks(mockTime, mockSleep) _retry = error_handling.retry(timeoutSec=30, initialRetryDelaySec=2, maxRetryDelaySec=10) testFunction = Mock(side_effect=[ TestParentException("Test exception 1"), TestParentException("Test exception 2"), 321 ], __name__="testFunction", autospec=True) returnValue = _retry(testFunction)() self.assertEqual(returnValue, 321) self.assertEqual(testFunction.call_count, 3)
def testRetryWaitsInitialRetryDelaySec(self, mockTime, mockSleep): """Test that delay times are correct.""" time_test_utils.configureTimeAndSleepMocks(mockTime, mockSleep) _retry = error_handling.retry(timeoutSec=30, initialRetryDelaySec=2, maxRetryDelaySec=10) testFunction = Mock(side_effect=TestParentException("Test exception"), __name__="testFunction", autospec=True) with self.assertRaises(TestParentException): _retry(testFunction)() self.assertEqual( mockSleep.mock_calls, [call(2), call(4), call(8), call(10), call(10)]) self.assertEqual(testFunction.call_count, 6)
def testRetryRetryFilter(self, mockTime, mockSleep): """Test that if retryFilter is specified and exception is in retryExceptions, retries iff retryFilter returns true.""" time_test_utils.configureTimeAndSleepMocks(mockTime, mockSleep) # Test with retryFilter returning True _retryTrueFilter = error_handling.retry( timeoutSec=1, initialRetryDelaySec=1, maxRetryDelaySec=10, retryExceptions=(TestParentException,), retryFilter=lambda _1, _2, _3: True) @_retryTrueFilter def testFunctionTrue(): raise TestChildException("Test exception") with self.assertRaises(TestChildException): testFunctionTrue() self.assertEqual(mockSleep.call_count, 1) # Test with retryFilter returning False mockSleep.reset_mock() _retryFalseFilter = error_handling.retry( timeoutSec=1, initialRetryDelaySec=1, maxRetryDelaySec=10, retryExceptions=(TestParentException,), retryFilter=lambda _1, _2, _3: False) @_retryFalseFilter def testFunctionFalse(): raise TestChildException("Test exception") with self.assertRaises(TestChildException): testFunctionFalse() self.assertEqual(mockSleep.call_count, 0)
def testFailsFirstSucceedsLater(self, mockTime, mockSleep): """If initial attempts fail but subsequent attempt succeeds, ensure that expected number of retries is performed and expected value is returned.""" time_test_utils.configureTimeAndSleepMocks(mockTime, mockSleep) _retry = error_handling.retry( timeoutSec=30, initialRetryDelaySec=2, maxRetryDelaySec=10) testFunction = Mock( side_effect=[ TestParentException("Test exception 1"), TestParentException("Test exception 2"), 321 ], __name__="testFunction", autospec=True) returnValue = _retry(testFunction)() self.assertEqual(returnValue, 321) self.assertEqual(testFunction.call_count, 3)
def testRetryRetryExceptionExcluded(self, mockTime, mockSleep): """ Test that retry is not triggered if raised exeception is not in retryExceptions """ time_test_utils.configureTimeAndSleepMocks(mockTime, mockSleep) class TestExceptionA(Exception): pass class TestExceptionB(Exception): pass _retry = error_handling.retry( timeoutSec=1, initialRetryDelaySec=1, maxRetryDelaySec=10, retryExceptions=(TestExceptionA,)) @_retry def testFunction(): raise TestExceptionB("Test exception") with self.assertRaises(TestExceptionB): testFunction() self.assertEqual(mockSleep.call_count, 0)