1import unittest 2 3import cachetools.func 4 5 6class DecoratorTestMixin: 7 def decorator(self, maxsize, **kwargs): 8 return self.DECORATOR(maxsize, **kwargs) 9 10 def test_decorator(self): 11 cached = self.decorator(maxsize=2)(lambda n: n) 12 self.assertEqual(cached.cache_parameters(), {"maxsize": 2, "typed": False}) 13 self.assertEqual(cached.cache_info(), (0, 0, 2, 0)) 14 self.assertEqual(cached(1), 1) 15 self.assertEqual(cached.cache_info(), (0, 1, 2, 1)) 16 self.assertEqual(cached(1), 1) 17 self.assertEqual(cached.cache_info(), (1, 1, 2, 1)) 18 self.assertEqual(cached(1.0), 1.0) 19 self.assertEqual(cached.cache_info(), (2, 1, 2, 1)) 20 21 def test_decorator_clear(self): 22 cached = self.decorator(maxsize=2)(lambda n: n) 23 self.assertEqual(cached.cache_parameters(), {"maxsize": 2, "typed": False}) 24 self.assertEqual(cached.cache_info(), (0, 0, 2, 0)) 25 self.assertEqual(cached(1), 1) 26 self.assertEqual(cached.cache_info(), (0, 1, 2, 1)) 27 cached.cache_clear() 28 self.assertEqual(cached.cache_info(), (0, 0, 2, 0)) 29 self.assertEqual(cached(1), 1) 30 self.assertEqual(cached.cache_info(), (0, 1, 2, 1)) 31 32 def test_decorator_nocache(self): 33 cached = self.decorator(maxsize=0)(lambda n: n) 34 self.assertEqual(cached.cache_parameters(), {"maxsize": 0, "typed": False}) 35 self.assertEqual(cached.cache_info(), (0, 0, 0, 0)) 36 self.assertEqual(cached(1), 1) 37 self.assertEqual(cached.cache_info(), (0, 1, 0, 0)) 38 self.assertEqual(cached(1), 1) 39 self.assertEqual(cached.cache_info(), (0, 2, 0, 0)) 40 self.assertEqual(cached(1.0), 1.0) 41 self.assertEqual(cached.cache_info(), (0, 3, 0, 0)) 42 43 def test_decorator_unbound(self): 44 cached = self.decorator(maxsize=None)(lambda n: n) 45 self.assertEqual(cached.cache_parameters(), {"maxsize": None, "typed": False}) 46 self.assertEqual(cached.cache_info(), (0, 0, None, 0)) 47 self.assertEqual(cached(1), 1) 48 self.assertEqual(cached.cache_info(), (0, 1, None, 1)) 49 self.assertEqual(cached(1), 1) 50 self.assertEqual(cached.cache_info(), (1, 1, None, 1)) 51 self.assertEqual(cached(1.0), 1.0) 52 self.assertEqual(cached.cache_info(), (2, 1, None, 1)) 53 54 def test_decorator_typed(self): 55 cached = self.decorator(maxsize=2, typed=True)(lambda n: n) 56 self.assertEqual(cached.cache_parameters(), {"maxsize": 2, "typed": True}) 57 self.assertEqual(cached.cache_info(), (0, 0, 2, 0)) 58 self.assertEqual(cached(1), 1) 59 self.assertEqual(cached.cache_info(), (0, 1, 2, 1)) 60 self.assertEqual(cached(1), 1) 61 self.assertEqual(cached.cache_info(), (1, 1, 2, 1)) 62 self.assertEqual(cached(1.0), 1.0) 63 self.assertEqual(cached.cache_info(), (1, 2, 2, 2)) 64 self.assertEqual(cached(1.0), 1.0) 65 self.assertEqual(cached.cache_info(), (2, 2, 2, 2)) 66 67 def test_decorator_user_function(self): 68 cached = self.decorator(lambda n: n) 69 self.assertEqual(cached.cache_parameters(), {"maxsize": 128, "typed": False}) 70 self.assertEqual(cached.cache_info(), (0, 0, 128, 0)) 71 self.assertEqual(cached(1), 1) 72 self.assertEqual(cached.cache_info(), (0, 1, 128, 1)) 73 self.assertEqual(cached(1), 1) 74 self.assertEqual(cached.cache_info(), (1, 1, 128, 1)) 75 self.assertEqual(cached(1.0), 1.0) 76 self.assertEqual(cached.cache_info(), (2, 1, 128, 1)) 77 78 def test_decorator_needs_rlock(self): 79 cached = self.decorator(lambda n: n) 80 81 class RecursiveEquals: 82 def __init__(self, use_cache): 83 self._use_cache = use_cache 84 85 def __hash__(self): 86 return hash(self._use_cache) 87 88 def __eq__(self, other): 89 if self._use_cache: 90 # This call will happen while the cache-lock is held, 91 # requiring a reentrant lock to avoid deadlock. 92 cached(self) 93 return self._use_cache == other._use_cache 94 95 # Prime the cache. 96 cached(RecursiveEquals(False)) 97 cached(RecursiveEquals(True)) 98 # Then do a call which will cause a deadlock with a non-reentrant lock. 99 self.assertEqual(cached(RecursiveEquals(True)), RecursiveEquals(True)) 100 101 102class FIFODecoratorTest(unittest.TestCase, DecoratorTestMixin): 103 104 DECORATOR = staticmethod(cachetools.func.fifo_cache) 105 106 107class LFUDecoratorTest(unittest.TestCase, DecoratorTestMixin): 108 109 DECORATOR = staticmethod(cachetools.func.lfu_cache) 110 111 112class LRUDecoratorTest(unittest.TestCase, DecoratorTestMixin): 113 114 DECORATOR = staticmethod(cachetools.func.lru_cache) 115 116 117class MRUDecoratorTest(unittest.TestCase, DecoratorTestMixin): 118 119 DECORATOR = staticmethod(cachetools.func.mru_cache) 120 121 122class RRDecoratorTest(unittest.TestCase, DecoratorTestMixin): 123 124 DECORATOR = staticmethod(cachetools.func.rr_cache) 125 126 127class TTLDecoratorTest(unittest.TestCase, DecoratorTestMixin): 128 129 DECORATOR = staticmethod(cachetools.func.ttl_cache) 130