| 300 | # ============================================================================= |
| 301 | |
| 302 | class TestRetryEngine: |
| 303 | |
| 304 | def setup_method(self): |
| 305 | self.config = ControlLayerConfig( |
| 306 | max_attempts=3, base_delay_ms=50, max_delay_ms=2000, jitter_ms=0 |
| 307 | ) |
| 308 | self.engine = RetryEngine(self.config) |
| 309 | |
| 310 | def test_should_retry_within_max(self): |
| 311 | assert self.engine.should_retry(FailureMode.SCHEMA_VIOLATION, 1) is True |
| 312 | assert self.engine.should_retry(FailureMode.SCHEMA_VIOLATION, 2) is True |
| 313 | |
| 314 | def test_no_retry_at_max_attempts(self): |
| 315 | assert self.engine.should_retry(FailureMode.SCHEMA_VIOLATION, 3) is False |
| 316 | |
| 317 | def test_injection_never_retried(self): |
| 318 | assert self.engine.should_retry(FailureMode.PROMPT_INJECTION, 1) is False |
| 319 | |
| 320 | def test_circuit_open_never_retried(self): |
| 321 | assert self.engine.should_retry(FailureMode.CIRCUIT_OPEN, 1) is False |
| 322 | |
| 323 | def test_mutation_hint_returned(self): |
| 324 | hint = self.engine.get_mutation_hint(FailureMode.SCHEMA_VIOLATION) |
| 325 | assert isinstance(hint, str) |
| 326 | assert len(hint) > 0 |
| 327 | |
| 328 | def test_delay_increases_with_attempt(self): |
| 329 | d1 = self.engine.jittered_delay_s(1) |
| 330 | d2 = self.engine.jittered_delay_s(2) |
| 331 | assert d2 > d1 |
| 332 | |
| 333 | |
| 334 | # ============================================================================= |
nothing calls this directly
no outgoing calls
no test coverage detected