def test_turns_off_if_too_long(): # Given off_count = 0 on_count = 0 time_limit = 0.1 def off_func(*args, **kwargs): nonlocal off_count off_count += 1 return "OFF" def on_func(*args, **kwargs): nonlocal on_count on_count += 1 time.sleep(0.04 * on_count) return 'ON' breaker = CircuitBreaker(name=name, on=on_func, off=off_func, trigger=1, time_limit=time_limit) breaker.clear() # When breaker() # ON in 40ms breaker() # ON in 80ms breaker() # ON in 120ms -> fail breaker() # OFF # Then assert off_count == 1 assert on_count == 3
def test_calls_off_function_with_args(): # Given off_args = None off_kwargs = None def off_func(*args, **kwargs): nonlocal off_args, off_kwargs off_args = args off_kwargs = kwargs return "OFF" def on_func(*args, **kwargs): raise Exception("SomeError") breaker = CircuitBreaker(name=name, on=on_func, off=off_func, trigger=1) breaker.clear() # When ignore_exception(lambda: breaker(8, 6, 'Hey', salut="bonjour")) actual = breaker(8, 6, 'Hey', salut="bonjour") # Then assert off_args == (8, 6, 'Hey') assert off_kwargs == {'salut': "bonjour"} assert actual == "OFF"
def test_calls_off_after_trigger(): # Given off_count = 0 on_count = 0 def off_func(*args, **kwargs): nonlocal off_count off_count += 1 def on_func(*args, **kwargs): nonlocal on_count on_count += 1 if on_count <= 6: raise Exception('Some Error') return 'ON' breaker = CircuitBreaker(name=name, on=on_func, off=off_func, trigger=3, release=5) breaker.clear() # When ignore_exception(lambda: breaker()) # fail ON ignore_exception(lambda: breaker()) # fail ON ignore_exception(lambda: breaker()) # fail ON breaker() # pass OFF breaker() # pass OFF breaker() # pass OFF breaker() # pass OFF breaker() # pass OFF ignore_exception(lambda: breaker()) # fail ON ignore_exception(lambda: breaker()) # fail ON ignore_exception(lambda: breaker()) # fail ON breaker() # pass OFF breaker() # pass OFF breaker() # pass OFF breaker() # pass OFF breaker() # pass OFF actual = breaker() # pass ON # Then assert on_count == 7 assert off_count == 10 assert actual == "ON"
def test_calls_on_function(): # Given on_count = 0 def on_func(): nonlocal on_count on_count = on_count + 1 breaker = CircuitBreaker(name=name, on=on_func, off=noop) breaker.clear() # When breaker() breaker() breaker() breaker() breaker() # Then assert on_count == 5
def test_calls_off_after_soft_trigger(): # Given off_count = 0 on_count = 0 def off_func(*args, **kwargs): nonlocal off_count off_count += 1 def on_func(*args, **kwargs): nonlocal on_count on_count += 1 if (on_count % 3) == 0: return 'ON' else: raise Exception('Some Error') breaker = CircuitBreaker(name=name, on=on_func, off=off_func, trigger=3, release=5) breaker.clear() # When ignore_exception(lambda: breaker()) # ON fail ignore_exception(lambda: breaker()) # ON fail breaker() # ON pass ignore_exception(lambda: breaker()) # ON fail ignore_exception(lambda: breaker()) # ON fail breaker() # OFF pass breaker() # OFF pass breaker() # OFF pass breaker() # OFF pass breaker() # OFF pass actual = breaker() # ON pass # Then assert on_count == 6 assert off_count == 5 assert actual == "ON"
def test_calls_default_off_behaviour(): # Given expected_error_msg = f"CircuitBreaker 'test name' is currently off" def on_func(*args, **kwargs): raise Exception("some error") breaker = CircuitBreaker(on=on_func, name="test name", trigger=1) breaker.clear() actual = None # When ignore_exception(lambda: breaker()) try: breaker() except Exception as e: actual = e # Then assert True == isinstance(actual, CircuitBreakerOffException) assert actual.message == expected_error_msg
def test_calls_on_function_with_args(): # Given on_args = None on_kwargs = None ret = {"some": 'return value'} def on_func(*args, **kwargs): nonlocal on_args, on_kwargs, ret on_args = args on_kwargs = kwargs return ret breaker = CircuitBreaker(name=name, on=on_func, off=noop) breaker.clear() # When actual = breaker(8, 6, 'Hey', salut="bonjour") # Then assert on_args == (8, 6, 'Hey') assert on_kwargs == {'salut': "bonjour"} assert actual == ret
def test_always_calls_on_when_disabled(): # Given off_count = 0 on_count = 0 def off_func(*args, **kwargs): nonlocal off_count off_count += 1 def on_func(*args, **kwargs): nonlocal on_count on_count += 1 if on_count <= 6: raise Exception('Some Error') return 'ON' breaker = CircuitBreaker(name=name, on=on_func, off=off_func, trigger=3, release=5) breaker.clear() breaker.breaker_enabled(False) # When ignore_exception(lambda: breaker()) ignore_exception(lambda: breaker()) ignore_exception(lambda: breaker()) ignore_exception(lambda: breaker()) ignore_exception(lambda: breaker()) ignore_exception(lambda: breaker()) ignore_exception(lambda: breaker()) ignore_exception(lambda: breaker()) # Then assert on_count == 8 assert off_count == 0
def test_calls_on_function_again(): # Given off_count = 0 on_count = 0 def off_func(*args, **kwargs): nonlocal off_count off_count += 1 def on_func(*args, **kwargs): nonlocal on_count on_count += 1 if on_count == 1: raise Exception('Some Error') return 'ON' breaker = CircuitBreaker(name=name, on=on_func, off=off_func, trigger=1) breaker.clear() # When ignore_exception(lambda: breaker()) breaker() breaker() breaker() breaker() breaker() breaker() breaker() breaker() breaker() breaker() actual = breaker() # Then assert actual == "ON" assert on_count == 2 assert off_count == 10