194 lines
5.8 KiB
Python
194 lines
5.8 KiB
Python
"""Tests for core cache utilities"""
|
|
|
|
from apps.core.cache import (
|
|
CacheManager,
|
|
_build_cache_key,
|
|
cache_method,
|
|
cache_result,
|
|
)
|
|
from django.core.cache import cache
|
|
from django.test import TestCase
|
|
|
|
|
|
class CacheResultDecoratorTest(TestCase):
|
|
"""Tests for @cache_result decorator"""
|
|
|
|
def setUp(self):
|
|
cache.clear()
|
|
self.call_count = 0
|
|
|
|
def test_result_is_cached(self):
|
|
"""Test that function result is cached"""
|
|
|
|
@cache_result(timeout=60, key_prefix="test")
|
|
def expensive_function(x):
|
|
self.call_count += 1
|
|
return x * 2
|
|
|
|
# First call - should execute
|
|
result1 = expensive_function(5)
|
|
self.assertEqual(result1, 10)
|
|
self.assertEqual(self.call_count, 1)
|
|
|
|
# Second call - should return cached result
|
|
result2 = expensive_function(5)
|
|
self.assertEqual(result2, 10)
|
|
self.assertEqual(self.call_count, 1) # Still 1, not called again
|
|
|
|
def test_different_args_not_cached(self):
|
|
"""Test that different arguments create different cache entries"""
|
|
|
|
@cache_result(timeout=60, key_prefix="test")
|
|
def expensive_function(x):
|
|
self.call_count += 1
|
|
return x * 2
|
|
|
|
result1 = expensive_function(5)
|
|
result2 = expensive_function(10)
|
|
|
|
self.assertEqual(result1, 10)
|
|
self.assertEqual(result2, 20)
|
|
self.assertEqual(self.call_count, 2)
|
|
|
|
def test_kwargs_included_in_cache_key(self):
|
|
"""Test that kwargs are included in cache key"""
|
|
|
|
@cache_result(timeout=60, key_prefix="test")
|
|
def expensive_function(x, multiplier=2):
|
|
self.call_count += 1
|
|
return x * multiplier
|
|
|
|
result1 = expensive_function(5, multiplier=2)
|
|
result2 = expensive_function(5, multiplier=3)
|
|
|
|
self.assertEqual(result1, 10)
|
|
self.assertEqual(result2, 15)
|
|
self.assertEqual(self.call_count, 2)
|
|
|
|
|
|
class CacheMethodDecoratorTest(TestCase):
|
|
"""Tests for @cache_method decorator"""
|
|
|
|
def setUp(self):
|
|
cache.clear()
|
|
|
|
def test_classmethod_caching(self):
|
|
"""Test caching works with classmethod"""
|
|
call_count = {"value": 0}
|
|
|
|
class MyService:
|
|
@classmethod
|
|
@cache_method(timeout=60, key_prefix="service")
|
|
def get_data(cls, item_id):
|
|
call_count["value"] += 1
|
|
return {"id": item_id, "data": "test"}
|
|
|
|
# First call
|
|
result1 = MyService.get_data(1)
|
|
self.assertEqual(result1["id"], 1)
|
|
self.assertEqual(call_count["value"], 1)
|
|
|
|
# Second call - should be cached
|
|
result2 = MyService.get_data(1)
|
|
self.assertEqual(result2["id"], 1)
|
|
self.assertEqual(call_count["value"], 1)
|
|
|
|
# Different argument
|
|
result3 = MyService.get_data(2)
|
|
self.assertEqual(result3["id"], 2)
|
|
self.assertEqual(call_count["value"], 2)
|
|
|
|
|
|
class CacheManagerTest(TestCase):
|
|
"""Tests for CacheManager"""
|
|
|
|
def setUp(self):
|
|
cache.clear()
|
|
self.manager = CacheManager("test_prefix")
|
|
|
|
def test_set_and_get(self):
|
|
"""Test basic set and get operations"""
|
|
self.manager.set("key1", "value1", timeout=60)
|
|
result = self.manager.get("key1")
|
|
self.assertEqual(result, "value1")
|
|
|
|
def test_get_default(self):
|
|
"""Test get returns default for missing key"""
|
|
result = self.manager.get("nonexistent", default="default_value")
|
|
self.assertEqual(result, "default_value")
|
|
|
|
def test_delete(self):
|
|
"""Test delete operation"""
|
|
self.manager.set("key1", "value1")
|
|
self.manager.delete("key1")
|
|
result = self.manager.get("key1")
|
|
self.assertIsNone(result)
|
|
|
|
def test_get_or_set(self):
|
|
"""Test get_or_set operation"""
|
|
call_count = {"value": 0}
|
|
|
|
def compute_value():
|
|
call_count["value"] += 1
|
|
return "computed"
|
|
|
|
# First call - should compute
|
|
result1 = self.manager.get_or_set("key1", compute_value)
|
|
self.assertEqual(result1, "computed")
|
|
self.assertEqual(call_count["value"], 1)
|
|
|
|
# Second call - should return cached
|
|
result2 = self.manager.get_or_set("key1", compute_value)
|
|
self.assertEqual(result2, "computed")
|
|
self.assertEqual(call_count["value"], 1)
|
|
|
|
def test_prefix_applied(self):
|
|
"""Test that prefix is applied to keys"""
|
|
self.manager.set("mykey", "myvalue")
|
|
|
|
# Direct cache access should use prefixed key
|
|
direct_result = cache.get("test_prefix:mykey")
|
|
self.assertEqual(direct_result, "myvalue")
|
|
|
|
|
|
class BuildCacheKeyTest(TestCase):
|
|
"""Tests for _build_cache_key function"""
|
|
|
|
def test_key_includes_function_name(self):
|
|
"""Test cache key includes function name"""
|
|
|
|
def my_function():
|
|
pass
|
|
|
|
key = _build_cache_key(my_function, "", (), {})
|
|
self.assertIn("my_function", key)
|
|
|
|
def test_key_includes_prefix(self):
|
|
"""Test cache key includes prefix"""
|
|
|
|
def my_function():
|
|
pass
|
|
|
|
key = _build_cache_key(my_function, "myprefix", (), {})
|
|
self.assertTrue(key.startswith("myprefix:"))
|
|
|
|
def test_different_args_different_keys(self):
|
|
"""Test different arguments produce different keys"""
|
|
|
|
def my_function():
|
|
pass
|
|
|
|
key1 = _build_cache_key(my_function, "", (1, 2), {})
|
|
key2 = _build_cache_key(my_function, "", (1, 3), {})
|
|
self.assertNotEqual(key1, key2)
|
|
|
|
def test_different_kwargs_different_keys(self):
|
|
"""Test different kwargs produce different keys"""
|
|
|
|
def my_function():
|
|
pass
|
|
|
|
key1 = _build_cache_key(my_function, "", (), {"a": 1})
|
|
key2 = _build_cache_key(my_function, "", (), {"a": 2})
|
|
self.assertNotEqual(key1, key2)
|