"""Tests for circuit breaker and infrastructure."""
import time
import pytest
from world_intel_mcp.circuit_breaker import CircuitBreaker
def test_circuit_starts_closed() -> None:
cb = CircuitBreaker(failure_threshold=3, cooldown_seconds=1.0)
assert cb.is_available("test-source")
def test_circuit_trips_after_threshold() -> None:
cb = CircuitBreaker(failure_threshold=2, cooldown_seconds=10.0)
cb.record_failure("src")
assert cb.is_available("src") # 1 failure, threshold is 2
cb.record_failure("src")
assert not cb.is_available("src") # tripped
def test_circuit_recovers_after_cooldown() -> None:
cb = CircuitBreaker(failure_threshold=1, cooldown_seconds=0.5)
cb.record_failure("src")
assert not cb.is_available("src")
time.sleep(0.6)
assert cb.is_available("src") # half-open, allows probe
def test_success_resets_failures() -> None:
cb = CircuitBreaker(failure_threshold=3, cooldown_seconds=10.0)
cb.record_failure("src")
cb.record_failure("src")
cb.record_success("src")
assert cb.is_available("src")
# Even after 2 more failures, need 3 consecutive
cb.record_failure("src")
cb.record_failure("src")
assert cb.is_available("src") # only 2 since reset
def test_status_output() -> None:
cb = CircuitBreaker(failure_threshold=2, cooldown_seconds=60.0)
cb.record_success("healthy")
cb.record_failure("unhealthy")
cb.record_failure("unhealthy")
status = cb.status()
assert status["healthy"]["status"] == "closed"
assert status["unhealthy"]["status"] == "open"
assert status["unhealthy"]["total_trips"] == 1
def test_independent_sources() -> None:
cb = CircuitBreaker(failure_threshold=1, cooldown_seconds=60.0)
cb.record_failure("source_a")
assert not cb.is_available("source_a")
assert cb.is_available("source_b") # independent