SummarizerApp / tests /test_cache.py
ming
feat: Implement V3 Web Scraping + Summarization API
2ed2bd7
raw
history blame
3.93 kB
"""
Tests for the cache service.
"""
import time
import pytest
from app.core.cache import SimpleCache
def test_cache_initialization():
"""Test cache is initialized with correct settings."""
cache = SimpleCache(ttl_seconds=3600, max_size=100)
assert cache._ttl == 3600
assert cache._max_size == 100
stats = cache.stats()
assert stats["size"] == 0
assert stats["hits"] == 0
assert stats["misses"] == 0
def test_cache_set_and_get():
"""Test setting and getting cache entries."""
cache = SimpleCache(ttl_seconds=60)
test_data = {"text": "Test article", "title": "Test"}
cache.set("http://example.com", test_data)
result = cache.get("http://example.com")
assert result is not None
assert result["text"] == "Test article"
assert result["title"] == "Test"
def test_cache_miss():
"""Test cache miss returns None."""
cache = SimpleCache()
result = cache.get("http://nonexistent.com")
assert result is None
def test_cache_expiration():
"""Test cache entries expire after TTL."""
cache = SimpleCache(ttl_seconds=1) # 1 second TTL
test_data = {"text": "Test article"}
cache.set("http://example.com", test_data)
# Should be in cache immediately
assert cache.get("http://example.com") is not None
# Wait for expiration
time.sleep(1.5)
# Should be expired now
assert cache.get("http://example.com") is None
def test_cache_max_size():
"""Test cache enforces max size by removing oldest entries."""
cache = SimpleCache(ttl_seconds=3600, max_size=3)
cache.set("url1", {"data": "1"})
cache.set("url2", {"data": "2"})
cache.set("url3", {"data": "3"})
assert cache.stats()["size"] == 3
# Adding a 4th entry should remove the oldest
cache.set("url4", {"data": "4"})
assert cache.stats()["size"] == 3
assert cache.get("url1") is None # Oldest should be removed
assert cache.get("url4") is not None
def test_cache_stats():
"""Test cache statistics tracking."""
cache = SimpleCache()
cache.set("url1", {"data": "1"})
cache.set("url2", {"data": "2"})
# Generate some hits and misses
cache.get("url1") # hit
cache.get("url1") # hit
cache.get("url3") # miss
stats = cache.stats()
assert stats["size"] == 2
assert stats["hits"] == 2
assert stats["misses"] == 1
assert stats["hit_rate"] == 66.67
def test_cache_clear_expired():
"""Test clearing expired entries."""
cache = SimpleCache(ttl_seconds=1)
cache.set("url1", {"data": "1"})
cache.set("url2", {"data": "2"})
# Wait for expiration
time.sleep(1.5)
# Add a fresh entry
cache.set("url3", {"data": "3"})
# Clear expired entries
removed = cache.clear_expired()
assert removed == 2
assert cache.stats()["size"] == 1
assert cache.get("url3") is not None
def test_cache_clear_all():
"""Test clearing all cache entries."""
cache = SimpleCache()
cache.set("url1", {"data": "1"})
cache.set("url2", {"data": "2"})
cache.get("url1") # Generate some stats
cache.clear_all()
stats = cache.stats()
assert stats["size"] == 0
assert stats["hits"] == 0
assert stats["misses"] == 0
def test_cache_thread_safety():
"""Test cache thread safety with concurrent access."""
import threading
cache = SimpleCache()
def set_values():
for i in range(10):
cache.set(f"url{i}", {"data": str(i)})
def get_values():
for i in range(10):
cache.get(f"url{i}")
threads = []
for _ in range(5):
threads.append(threading.Thread(target=set_values))
threads.append(threading.Thread(target=get_values))
for t in threads:
t.start()
for t in threads:
t.join()
# No assertion needed - test passes if no race condition errors occur
assert cache.stats()["size"] <= 10