transcription/tests/test_qmd_cache.py

70 lines
2.5 KiB
Python
Raw Normal View History

"""Tests for qmd search-result cache (TTL + mtime invalidation)."""
import asyncio
import tempfile
import time
import unittest
from pathlib import Path
from unittest.mock import patch
from src.rag.qmd.cache import SearchCache
class SearchCacheTestCase(unittest.IsolatedAsyncioTestCase):
async def test_get_set_roundtrip(self):
cache = SearchCache(ttl_seconds=60)
args = ("merakom", "2026", "bm25", True)
self.assertIsNone(cache.get("hello", args))
cache.set("hello", args, "ctx-blob")
self.assertEqual(cache.get("hello", args), "ctx-blob")
async def test_question_normalization(self):
cache = SearchCache(ttl_seconds=60)
args = ("merakom", "2026", "bm25", True)
cache.set("Hello World", args, "ctx")
self.assertEqual(cache.get(" hello world ", args), "ctx")
async def test_different_args_yield_different_keys(self):
cache = SearchCache(ttl_seconds=60)
cache.set("q", ("o", "p1", "bm25", True), "ctx1")
cache.set("q", ("o", "p2", "bm25", True), "ctx2")
self.assertEqual(cache.get("q", ("o", "p1", "bm25", True)), "ctx1")
self.assertEqual(cache.get("q", ("o", "p2", "bm25", True)), "ctx2")
async def test_set_skips_empty_value(self):
cache = SearchCache(ttl_seconds=60)
cache.set("q", ("o", "p", "bm25", True), "")
self.assertIsNone(cache.get("q", ("o", "p", "bm25", True)))
async def test_ttl_expiry(self):
cache = SearchCache(ttl_seconds=0)
args = ("o", "p", "bm25", True)
with patch("src.rag.qmd.cache._index_mtime", return_value=0.0):
cache.set("q", args, "ctx")
await asyncio.sleep(0.05)
self.assertIsNone(cache.get("q", args))
async def test_mtime_invalidation(self):
cache = SearchCache(ttl_seconds=60)
args = ("o", "p", "bm25", True)
with patch("src.rag.qmd.cache._index_mtime", return_value=10.0):
cache.set("q", args, "ctx")
with patch("src.rag.qmd.cache._index_mtime", return_value=20.0):
self.assertIsNone(cache.get("q", args))
async def test_clear(self):
cache = SearchCache(ttl_seconds=60)
cache.set("q", ("o", "p", "bm25", True), "ctx")
cache.clear()
self.assertIsNone(cache.get("q", ("o", "p", "bm25", True)))
async def test_stats(self):
cache = SearchCache(ttl_seconds=42)
stats = cache.stats()
self.assertEqual(stats["entries"], 0)
self.assertEqual(stats["ttl_seconds"], 42)
if __name__ == "__main__":
unittest.main()