"""Tests for the in-process TTL cache. Covers: - stored values round-trip via ``get`` before TTL expiry - entries expire after TTL elapses - ``invalidate_all`` drops every entry - construction rejects a non-positive TTL - the cache is typed-generic (spot check at runtime that multiple concrete types work — the real type safety comes from static checking, which isn't part of the runtime suite) """ from __future__ import annotations import time import pytest from app.services.cache import TTLCache def test_set_then_get_returns_stored_value() -> None: """A value stored via ``set`` is visible to ``get`` until expiry.""" cache: TTLCache[str, int] = TTLCache(ttl_seconds=5.0) cache.set("answer", 42) assert cache.get("answer") == 42 def test_get_returns_none_for_missing_key() -> None: """Absent keys return ``None`` cleanly (no KeyError).""" cache: TTLCache[str, str] = TTLCache(ttl_seconds=5.0) assert cache.get("nope") is None def test_entries_expire_after_ttl() -> None: """An entry past its TTL is treated as absent. Uses a tiny TTL + ``time.sleep`` rather than mocking ``time.monotonic`` so the test exercises the real code path. """ cache: TTLCache[str, str] = TTLCache(ttl_seconds=0.05) cache.set("k", "v") time.sleep(0.1) assert cache.get("k") is None def test_invalidate_all_clears_everything() -> None: """``invalidate_all`` drops every entry regardless of TTL.""" cache: TTLCache[str, int] = TTLCache(ttl_seconds=60.0) cache.set("a", 1) cache.set("b", 2) cache.invalidate_all() assert cache.get("a") is None assert cache.get("b") is None def test_non_positive_ttl_is_rejected() -> None: """Zero/negative TTL raises at construction time. A zero TTL would make every write immediately expire, which is almost certainly a bug; the defensive check turns it into a loud failure. """ with pytest.raises(ValueError): TTLCache(ttl_seconds=0.0) with pytest.raises(ValueError): TTLCache(ttl_seconds=-1.0) def test_cache_works_with_int_keys_and_list_values() -> None: """Runtime smoke: generic over both ``K`` and ``V``.""" cache: TTLCache[int, list[str]] = TTLCache(ttl_seconds=5.0) cache.set(10, ["a", "b"]) stored = cache.get(10) assert stored == ["a", "b"]