Files
Latte ed3130ef74 refactor: lifespan handlers, module-level imports, bounded scope cache
Replace deprecated @app.on_event startup/shutdown handlers with a FastAPI
lifespan context manager, move the inline hashlib/time imports in the auth
middleware to module top, and back the unbounded _api_scope_cache with a new
size- and TTL-bounded BoundedTTLCache utility.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 18:39:06 +02:00

73 lines
2.2 KiB
Python

"""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)