65 lines
2.3 KiB
Python
65 lines
2.3 KiB
Python
from __future__ import annotations
|
|
|
|
from unittest.mock import patch
|
|
|
|
from yuxi.channel.lifecycle.backoff import BackoffPolicy
|
|
|
|
|
|
class TestBackoffPolicy:
|
|
def test_default_parameters(self):
|
|
policy = BackoffPolicy()
|
|
assert policy.base_ms == 1000
|
|
assert policy.max_ms == 30000
|
|
assert policy.jitter_ms == 1000
|
|
|
|
def test_custom_parameters(self):
|
|
policy = BackoffPolicy(base_ms=500, max_ms=10000, jitter_ms=200)
|
|
assert policy.base_ms == 500
|
|
assert policy.max_ms == 10000
|
|
assert policy.jitter_ms == 200
|
|
|
|
def test_zero_attempts_uses_base_delay(self):
|
|
policy = BackoffPolicy(base_ms=1000, jitter_ms=0)
|
|
assert policy.compute(0) == 1000
|
|
|
|
def test_exponential_growth(self):
|
|
policy = BackoffPolicy(base_ms=1000, jitter_ms=0)
|
|
assert policy.compute(1) == 2000
|
|
assert policy.compute(2) == 4000
|
|
assert policy.compute(3) == 8000
|
|
|
|
def test_max_delay_cap(self):
|
|
policy = BackoffPolicy(base_ms=1000, max_ms=5000, jitter_ms=0)
|
|
assert policy.compute(10) == 5000
|
|
|
|
def test_negative_attempts_clamped_to_zero(self):
|
|
policy = BackoffPolicy(base_ms=1000, jitter_ms=0)
|
|
assert policy.compute(-1) == 1000
|
|
assert policy.compute(-5) == 1000
|
|
|
|
def test_jitter_is_applied(self):
|
|
policy = BackoffPolicy(base_ms=1000, jitter_ms=500)
|
|
with patch.object(policy, "jitter_ms", 500):
|
|
with patch("yuxi.channel.lifecycle.backoff.random.randint", return_value=250):
|
|
assert policy.compute(0) == 1250
|
|
|
|
def test_attempts_capped_at_30(self):
|
|
policy = BackoffPolicy(base_ms=1, max_ms=1_000_000_000, jitter_ms=0)
|
|
# 2**30 is large but capped by attempts, not max_ms
|
|
value_30 = policy.compute(30)
|
|
value_31 = policy.compute(31)
|
|
value_100 = policy.compute(100)
|
|
assert value_30 == value_31 == value_100
|
|
|
|
def test_jitter_range(self):
|
|
policy = BackoffPolicy(base_ms=1000, jitter_ms=100)
|
|
for _ in range(50):
|
|
delay = policy.compute(0)
|
|
assert 1000 <= delay <= 1100
|
|
|
|
def test_jitter_does_not_exceed_max_ms(self):
|
|
policy = BackoffPolicy(base_ms=1000, max_ms=2000, jitter_ms=500)
|
|
with patch("yuxi.channel.lifecycle.backoff.random.randint", return_value=500):
|
|
delay = policy.compute(10)
|
|
assert delay == 2000
|