"""InMemoryShadowLogger 동작 + Protocol 계약.""" from __future__ import annotations import pytest from policy.routing import RoutingDecision, decide_routing from policy.shadow import InMemoryShadowLogger, ShadowLogger @pytest.fixture def sample_decision(policy) -> RoutingDecision: return decide_routing( subject_domain="safety_reference", content_chars=1000, self_declared_high_impact=False, confidence=0.95, policy=policy, ) @pytest.mark.asyncio async def test_inmem_logger_records(sample_decision): logger = InMemoryShadowLogger() await logger.record_would_route( doc_id="doc-001", decision=sample_decision, actual_model_used="4B", prompt_version="v1-abc", policy_version="hash-1234", ) assert logger.count() == 1 rec = logger.records[0] assert rec.doc_id == "doc-001" assert rec.decision == sample_decision assert rec.actual_model_used == "4B" assert rec.prompt_version == "v1-abc" assert rec.policy_version == "hash-1234" @pytest.mark.asyncio async def test_inmem_logger_multiple(sample_decision): logger = InMemoryShadowLogger() for i in range(5): await logger.record_would_route( doc_id=f"doc-{i}", decision=sample_decision, actual_model_used="4B", prompt_version="v1", policy_version="h", ) assert logger.count() == 5 @pytest.mark.asyncio async def test_inmem_logger_clear(sample_decision): logger = InMemoryShadowLogger() await logger.record_would_route( doc_id="doc-1", decision=sample_decision, actual_model_used="4B", prompt_version="v1", policy_version="h", ) logger.clear() assert logger.count() == 0 @pytest.mark.asyncio async def test_inmem_logger_extra_payload(sample_decision): logger = InMemoryShadowLogger() await logger.record_would_route( doc_id="doc-1", decision=sample_decision, actual_model_used="4B", prompt_version="v1", policy_version="h", extra={"latency_ms": 120, "note": "test"}, ) rec = logger.records[0] assert rec.extra == {"latency_ms": 120, "note": "test"} def test_inmem_logger_satisfies_protocol(): """InMemoryShadowLogger 가 ShadowLogger Protocol 을 만족.""" logger = InMemoryShadowLogger() assert isinstance(logger, ShadowLogger)