"""Tests for the bounded TTL cache utility.""" from __future__ import annotations import time import pytest from aegis_gitea_mcp.cache import BoundedTTLCache def test_set_and_get_returns_value() -> None: """A stored value is returned before it expires.""" cache: BoundedTTLCache[str, int] = BoundedTTLCache(ttl_seconds=60, max_size=8) cache.set("a", 1) assert cache.get("a") == 1 def test_missing_key_returns_none() -> None: """An unknown key returns None.""" cache: BoundedTTLCache[str, int] = BoundedTTLCache(ttl_seconds=60) assert cache.get("missing") is None def test_entry_expires_after_ttl() -> None: """An entry is evicted once its TTL elapses.""" cache: BoundedTTLCache[str, int] = BoundedTTLCache(ttl_seconds=0.05, max_size=8) cache.set("a", 1) assert cache.get("a") == 1 time.sleep(0.06) assert cache.get("a") is None def test_size_bound_evicts_oldest() -> None: """The cache never exceeds max_size; oldest entries are evicted first.""" cache: BoundedTTLCache[int, int] = BoundedTTLCache(ttl_seconds=60, max_size=3) for i in range(5): cache.set(i, i) assert len(cache) == 3 # 0 and 1 were evicted; 2, 3, 4 remain. assert cache.get(0) is None assert cache.get(1) is None assert cache.get(4) == 4 def test_reinsert_refreshes_recency() -> None: """Re-setting a key refreshes its position so it is not evicted first.""" cache: BoundedTTLCache[str, int] = BoundedTTLCache(ttl_seconds=60, max_size=2) cache.set("a", 1) cache.set("b", 2) cache.set("a", 3) # refresh "a" cache.set("c", 4) # should evict "b", the oldest assert cache.get("b") is None assert cache.get("a") == 3 assert cache.get("c") == 4 def test_clear_empties_cache() -> None: """clear() removes all entries.""" cache: BoundedTTLCache[str, int] = BoundedTTLCache(ttl_seconds=60) cache.set("a", 1) cache.clear() assert cache.get("a") is None assert len(cache) == 0 def test_invalid_constructor_args() -> None: """Non-positive TTL or size is rejected.""" with pytest.raises(ValueError): BoundedTTLCache(ttl_seconds=0) with pytest.raises(ValueError): BoundedTTLCache(ttl_seconds=60, max_size=0)