123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361 |
- import contextlib
- import datetime
- import pytest
- import library.python.retry as retry
- def test_default():
- @retry.retry()
- def foo():
- pass
- foo()
- def test_exec():
- ctx = {"run": False}
- @retry.retry()
- def foo():
- ctx["run"] = True
- foo()
- assert ctx["run"]
- class RetriableError(Exception):
- pass
- def test_conf():
- conf = retry.RetryConf()
- conf2 = conf.clone()
- assert conf2 is not conf
- conf_on = conf.on(RetriableError)
- assert conf_on.retriable is not conf.retriable
- assert conf_on.retriable(RetriableError("error"))
- t = datetime.timedelta(seconds=3)
- conf_waiting = conf.waiting(42, backoff=1.5)
- assert conf_waiting.get_delay is not conf.get_delay
- assert conf_waiting.get_delay(3, t, 63) == 94.5
- class Counter(object):
- def __init__(self):
- self.value = 0
- def checkin(self):
- self.value += 1
- def DUMMY_RUN(*args, **kwargs):
- return None
- @contextlib.contextmanager
- def erroneous_runner(run, n=1, error=Exception):
- counter = Counter()
- def wrapped_run(*args, **kwargs):
- counter.checkin()
- if counter.value <= n:
- raise error("Error")
- return run(*args, **kwargs)
- yield wrapped_run
- @contextlib.contextmanager
- def counting_runner(run, counter):
- def wrapped_run(*args, **kwargs):
- counter.checkin()
- return run(*args, **kwargs)
- yield wrapped_run
- param_runs = pytest.mark.parametrize("runs", (1, 2, 3))
- @param_runs
- def test_retries_call(runs):
- counter = Counter()
- with erroneous_runner(DUMMY_RUN, runs) as run:
- with counting_runner(run, counter) as run:
- def foo():
- run()
- retry.retry_call(foo)
- assert counter.value == runs + 1
- @param_runs
- def test_retries_call_args(runs):
- counter = Counter()
- with erroneous_runner(DUMMY_RUN, runs) as run:
- with counting_runner(run, counter) as run:
- def foo(arg, kwarg=None):
- import logging
- logging.info("!!! %s %s", arg, kwarg)
- run()
- retry.retry_call(foo, (1,), {"kwarg": 2})
- assert counter.value == runs + 1
- @param_runs
- def test_retries_decorator(runs):
- counter = Counter()
- with erroneous_runner(DUMMY_RUN, runs) as run:
- with counting_runner(run, counter) as run:
- @retry.retry(retry.RetryConf())
- def foo():
- run()
- foo()
- assert counter.value == runs + 1
- @param_runs
- def test_retries_decorator_args(runs):
- counter = Counter()
- with erroneous_runner(DUMMY_RUN, runs) as run:
- with counting_runner(run, counter) as run:
- @retry.retry(retry.RetryConf())
- def foo(arg, kwarg=None):
- run()
- foo(1, kwarg=2)
- assert counter.value == runs + 1
- @param_runs
- def test_retries_decorator_method(runs):
- counter = Counter()
- with erroneous_runner(DUMMY_RUN, runs) as run:
- with counting_runner(run, counter) as run:
- class Bar(object):
- @retry.retry(retry.RetryConf())
- def foo(self):
- run()
- Bar().foo()
- assert counter.value == runs + 1
- @param_runs
- def test_retries_decorator_method_args(runs):
- counter = Counter()
- with erroneous_runner(DUMMY_RUN, runs) as run:
- with counting_runner(run, counter) as run:
- class Bar(object):
- @retry.retry(retry.RetryConf())
- def foo(self, arg, kwarg=None):
- run()
- Bar().foo(1, kwarg=2)
- assert counter.value == runs + 1
- @param_runs
- def test_retries_decorator_intrusive(runs):
- counter = Counter()
- with erroneous_runner(DUMMY_RUN, runs) as run:
- with counting_runner(run, counter) as run:
- class Bar(object):
- def __init__(self):
- self.retry_conf = retry.RetryConf()
- @retry.retry_intrusive
- def foo(self, arg, kwarg=None):
- run()
- Bar().foo(1, kwarg=2)
- assert counter.value == runs + 1
- def test_retries_decorator_intrusive_fail():
- class Bar(object):
- @retry.retry_intrusive
- def foo(self, arg, kwarg=None):
- pass
- with pytest.raises(AssertionError):
- Bar().foo(1, kwarg=2)
- @pytest.mark.parametrize(
- "conf",
- (
- retry.RetryConf(),
- retry.DEFAULT_CONF,
- ),
- )
- def test_confs(conf):
- counter = Counter()
- with erroneous_runner(DUMMY_RUN) as run:
- with counting_runner(run, counter) as run:
- def foo():
- run()
- retry.retry_call(foo, conf=conf)
- assert counter.value == 2
- counter = Counter()
- with erroneous_runner(DUMMY_RUN) as run:
- with counting_runner(run, counter) as run:
- @retry.retry(conf)
- def foo_retried():
- run()
- foo_retried()
- assert counter.value == 2
- @pytest.mark.parametrize(
- "conf",
- (
- retry.RetryConf().on(RetriableError),
- retry.RetryConf(retriable=lambda e: isinstance(e, RetriableError)),
- ),
- )
- def test_retriable(conf):
- counter = Counter()
- with erroneous_runner(DUMMY_RUN, error=RetriableError) as run:
- with counting_runner(run, counter) as run:
- @retry.retry(conf)
- def foo():
- run()
- foo()
- assert counter.value == 2
- counter = Counter()
- with erroneous_runner(DUMMY_RUN) as run:
- with counting_runner(run, counter) as run:
- @retry.retry(conf)
- def foo():
- run()
- with pytest.raises(Exception):
- foo()
- assert counter.value == 1
- def test_waiting():
- conf = retry.RetryConf().waiting(1)
- with erroneous_runner(DUMMY_RUN) as run:
- @retry.retry(conf)
- def foo():
- run()
- foo()
- def test_waiting_backoff():
- conf = retry.RetryConf().waiting(1, backoff=2)
- with erroneous_runner(DUMMY_RUN) as run:
- @retry.retry(conf)
- def foo():
- run()
- foo()
- def test_waiting_jitter():
- conf = retry.RetryConf().waiting(0, jitter=1)
- with erroneous_runner(DUMMY_RUN) as run:
- @retry.retry(conf)
- def foo():
- run()
- foo()
- def test_upto():
- conf = retry.RetryConf().upto(0)
- counter = Counter()
- with erroneous_runner(DUMMY_RUN) as run:
- with counting_runner(run, counter) as run:
- @retry.retry(conf)
- def foo():
- run()
- with pytest.raises(Exception):
- foo()
- assert counter.value == 1
- def test_upto_retries():
- conf = retry.RetryConf().upto_retries(0)
- counter = Counter()
- with erroneous_runner(DUMMY_RUN, 2) as run:
- with counting_runner(run, counter) as run:
- @retry.retry(conf)
- def foo():
- run()
- with pytest.raises(Exception):
- foo()
- assert counter.value == 1
- conf = retry.RetryConf().upto_retries(1)
- counter = Counter()
- with erroneous_runner(DUMMY_RUN, 2) as run:
- with counting_runner(run, counter) as run:
- @retry.retry(conf)
- def foo():
- run()
- with pytest.raises(Exception):
- foo()
- assert counter.value == 2
- conf = retry.RetryConf().upto_retries(2)
- counter = Counter()
- with erroneous_runner(DUMMY_RUN, 2) as run:
- with counting_runner(run, counter) as run:
- @retry.retry(conf)
- def foo():
- run()
- foo()
- assert counter.value == 3
- conf = retry.RetryConf().upto_retries(4)
- counter = Counter()
- with erroneous_runner(DUMMY_RUN, 2) as run:
- with counting_runner(run, counter) as run:
- @retry.retry(conf)
- def foo():
- run()
- foo()
- assert counter.value == 3
|