You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

67 lines
2.2 KiB
Python

"""Unit tests for LLMCacheStore."""
from __future__ import annotations
from unittest.mock import AsyncMock, MagicMock
import pytest
from libs.llm.cache import LLMCacheStore, build_cache_key
@pytest.mark.unit
class TestBuildCacheKey:
def test_deterministic(self) -> None:
key1 = build_cache_key("text", "prompt_v1", "v1", "llama3.2", "1.0.0")
key2 = build_cache_key("text", "prompt_v1", "v1", "llama3.2", "1.0.0")
assert key1 == key2
def test_different_inputs_different_keys(self) -> None:
key1 = build_cache_key("text_a", "p", "v1", "llama3.2")
key2 = build_cache_key("text_b", "p", "v1", "llama3.2")
assert key1 != key2
@pytest.mark.unit
class TestLLMCacheStore:
@pytest.mark.asyncio
async def test_get_returns_none_on_miss(self) -> None:
"""Cache miss returns None."""
cache = LLMCacheStore()
mock_session = AsyncMock()
mock_result = MagicMock()
mock_result.scalar_one_or_none.return_value = None
mock_session.execute = AsyncMock(return_value=mock_result)
result = await cache.get(mock_session, "deadbeef" * 8)
assert result is None
@pytest.mark.asyncio
async def test_put_stores_entry(self) -> None:
"""Cache put creates a new row when key is absent."""
cache = LLMCacheStore()
mock_session = AsyncMock()
# Simulate no existing entry
mock_result = MagicMock()
mock_result.scalar_one_or_none.return_value = None
mock_session.execute = AsyncMock(return_value=mock_result)
mock_session.add = MagicMock()
mock_session.flush = AsyncMock()
await cache.put(
session=mock_session,
cache_key="deadbeef" * 8,
document_id="DOC::test",
model_name="llama3.2",
prompt_version="v1",
schema_version="1.0.0",
raw_prompt='[{"role":"user","content":"test"}]',
raw_response='{"event_type":"unknown"}',
normalized={"event_type": "unknown"},
token_usage={"prompt_tokens": 10, "completion_tokens": 5},
elapsed_ms=250,
)
mock_session.add.assert_called_once()
mock_session.flush.assert_called_once()