"""Tests for src/log_registry.py Session + SessionMetadata dataclasses Phase 4 of any_type_componentization_20260621. Verifies: - Session dataclass (session_id, path, start_time, whitelisted, metadata) - SessionMetadata dataclass (message_count, errors, size_kb, whitelisted, reason, timestamp) - Session.from_dict() round-trip - Session.to_dict() preserves TOML-compatible shape - LogRegistry.data is now dict[str, Session] (typed) - LogRegistry.register_session() returns Session instance - LogRegistry.update_session_metadata() sets Session.metadata - LogRegistry.get_old_non_whitelisted_sessions() returns Session list CONVENTION: 1-space indentation. NO COMMENTS. """ from __future__ import annotations import os from datetime import datetime import pytest from src.log_registry import ( LogRegistry, Session, SessionMetadata, ) @pytest.fixture def tmp_registry(tmp_path) -> LogRegistry: path = tmp_path / "registry.toml" return LogRegistry(str(path)) def test_session_dataclass_construction() -> None: s = Session(session_id="s1", path="/tmp/s1", start_time="2026-06-21T10:00:00") assert s.session_id == "s1" assert s.path == "/tmp/s1" assert s.start_time == "2026-06-21T10:00:00" assert s.whitelisted is False assert s.metadata is None def test_session_metadata_dataclass_construction() -> None: m = SessionMetadata(message_count=10, errors=2, size_kb=5) assert m.message_count == 10 assert m.errors == 2 assert m.size_kb == 5 assert m.whitelisted is False assert m.reason == "" def test_session_from_dict_basic() -> None: d = {"path": "/x", "start_time": "2026-06-21T10:00:00", "whitelisted": False, "metadata": None} s = Session.from_dict("s1", d) assert s.session_id == "s1" assert s.path == "/x" assert s.start_time == "2026-06-21T10:00:00" assert s.whitelisted is False assert s.metadata is None def test_session_from_dict_with_metadata() -> None: d = { "path": "/x", "start_time": "2026-06-21T10:00:00", "whitelisted": True, "metadata": {"message_count": 100, "errors": 1, "size_kb": 20, "whitelisted": True, "reason": "high"}, } s = Session.from_dict("s1", d) assert s.whitelisted is True assert s.metadata is not None assert s.metadata.message_count == 100 assert s.metadata.reason == "high" def test_session_to_dict_round_trip() -> None: m = SessionMetadata(message_count=42, errors=0, size_kb=15, whitelisted=True, reason="high count") s = Session(session_id="s1", path="/x", start_time="2026-06-21T10:00:00", whitelisted=True, metadata=m) d = s.to_dict() assert d["path"] == "/x" assert d["start_time"] == "2026-06-21T10:00:00" assert d["whitelisted"] is True assert d["metadata"]["message_count"] == 42 def test_session_metadata_to_dict() -> None: m = SessionMetadata(message_count=5, errors=1, size_kb=2) d = m.to_dict() assert d == {"message_count": 5, "errors": 1, "size_kb": 2, "whitelisted": False, "reason": "", "timestamp": None} def test_log_registry_data_is_typed() -> None: """self.data is now dict[str, Session].""" registry = LogRegistry("/tmp/_test_registry_xyz.toml") assert isinstance(registry.data, dict) def test_log_registry_register_session_returns_session(tmp_registry: LogRegistry) -> None: tmp_registry.register_session("s1", "/tmp/s1", "2026-06-21T10:00:00") s = tmp_registry.data["s1"] assert isinstance(s, Session) assert s.session_id == "s1" assert s.path == "/tmp/s1" assert s.start_time == "2026-06-21T10:00:00" assert s.whitelisted is False def test_log_registry_update_session_metadata_sets_metadata(tmp_registry: LogRegistry) -> None: tmp_registry.register_session("s1", "/tmp/s1", "2026-06-21T10:00:00") tmp_registry.update_session_metadata("s1", message_count=10, errors=2, size_kb=5, whitelisted=True, reason="test") s = tmp_registry.data["s1"] assert s.metadata is not None assert s.metadata.message_count == 10 assert s.metadata.errors == 2 assert s.whitelisted is True def test_log_registry_is_session_whitelisted(tmp_registry: LogRegistry) -> None: tmp_registry.register_session("s1", "/tmp/s1", "2026-06-21T10:00:00") assert tmp_registry.is_session_whitelisted("s1") is False tmp_registry.update_session_metadata("s1", 10, 0, 5, True, "test") assert tmp_registry.is_session_whitelisted("s1") is True def test_log_registry_get_old_non_whitelisted_sessions(tmp_registry: LogRegistry) -> None: cutoff = datetime(2026, 6, 1) old_start = "2026-05-01T10:00:00" recent_start = "2026-06-21T10:00:00" tmp_registry.register_session("old", "/tmp/old", old_start) tmp_registry.register_session("recent", "/tmp/recent", recent_start) # Update metadata so neither session is "empty" (otherwise both would be flagged as old) tmp_registry.update_session_metadata("old", 10, 0, 5, False, "test") tmp_registry.update_session_metadata("recent", 10, 0, 5, False, "test") old_sessions = tmp_registry.get_old_non_whitelisted_sessions(cutoff) assert any(s["session_id"] == "old" for s in old_sessions) assert not any(s["session_id"] == "recent" for s in old_sessions) def test_session_is_frozen() -> None: s = Session(session_id="s1", path="/x", start_time="2026-06-21T10:00:00") with pytest.raises(Exception): s.path = "mutated" def test_session_metadata_is_frozen() -> None: m = SessionMetadata(message_count=10) with pytest.raises(Exception): m.message_count = 999