| import unittest | |
| import cachetools.func | |
| class DecoratorTestMixin: | |
| def decorator(self, maxsize, **kwargs): | |
| return self.DECORATOR(maxsize, **kwargs) | |
| def test_decorator(self): | |
| cached = self.decorator(maxsize=2)(lambda n: n) | |
| self.assertEqual(cached.cache_parameters(), {"maxsize": 2, "typed": False}) | |
| self.assertEqual(cached.cache_info(), (0, 0, 2, 0)) | |
| self.assertEqual(cached(1), 1) | |
| self.assertEqual(cached.cache_info(), (0, 1, 2, 1)) | |
| self.assertEqual(cached(1), 1) | |
| self.assertEqual(cached.cache_info(), (1, 1, 2, 1)) | |
| self.assertEqual(cached(1.0), 1.0) | |
| self.assertEqual(cached.cache_info(), (2, 1, 2, 1)) | |
| def test_decorator_clear(self): | |
| cached = self.decorator(maxsize=2)(lambda n: n) | |
| self.assertEqual(cached.cache_parameters(), {"maxsize": 2, "typed": False}) | |
| self.assertEqual(cached.cache_info(), (0, 0, 2, 0)) | |
| self.assertEqual(cached(1), 1) | |
| self.assertEqual(cached.cache_info(), (0, 1, 2, 1)) | |
| cached.cache_clear() | |
| self.assertEqual(cached.cache_info(), (0, 0, 2, 0)) | |
| self.assertEqual(cached(1), 1) | |
| self.assertEqual(cached.cache_info(), (0, 1, 2, 1)) | |
| def test_decorator_nocache(self): | |
| cached = self.decorator(maxsize=0)(lambda n: n) | |
| self.assertEqual(cached.cache_parameters(), {"maxsize": 0, "typed": False}) | |
| self.assertEqual(cached.cache_info(), (0, 0, 0, 0)) | |
| self.assertEqual(cached(1), 1) | |
| self.assertEqual(cached.cache_info(), (0, 1, 0, 0)) | |
| self.assertEqual(cached(1), 1) | |
| self.assertEqual(cached.cache_info(), (0, 2, 0, 0)) | |
| self.assertEqual(cached(1.0), 1.0) | |
| self.assertEqual(cached.cache_info(), (0, 3, 0, 0)) | |
| def test_decorator_unbound(self): | |
| cached = self.decorator(maxsize=None)(lambda n: n) | |
| self.assertEqual(cached.cache_parameters(), {"maxsize": None, "typed": False}) | |
| self.assertEqual(cached.cache_info(), (0, 0, None, 0)) | |
| self.assertEqual(cached(1), 1) | |
| self.assertEqual(cached.cache_info(), (0, 1, None, 1)) | |
| self.assertEqual(cached(1), 1) | |
| self.assertEqual(cached.cache_info(), (1, 1, None, 1)) | |
| self.assertEqual(cached(1.0), 1.0) | |
| self.assertEqual(cached.cache_info(), (2, 1, None, 1)) | |
| def test_decorator_typed(self): | |
| cached = self.decorator(maxsize=2, typed=True)(lambda n: n) | |
| self.assertEqual(cached.cache_parameters(), {"maxsize": 2, "typed": True}) | |
| self.assertEqual(cached.cache_info(), (0, 0, 2, 0)) | |
| self.assertEqual(cached(1), 1) | |
| self.assertEqual(cached.cache_info(), (0, 1, 2, 1)) | |
| self.assertEqual(cached(1), 1) | |
| self.assertEqual(cached.cache_info(), (1, 1, 2, 1)) | |
| self.assertEqual(cached(1.0), 1.0) | |
| self.assertEqual(cached.cache_info(), (1, 2, 2, 2)) | |
| self.assertEqual(cached(1.0), 1.0) | |
| self.assertEqual(cached.cache_info(), (2, 2, 2, 2)) | |
| def test_decorator_user_function(self): | |
| cached = self.decorator(lambda n: n) | |
| self.assertEqual(cached.cache_parameters(), {"maxsize": 128, "typed": False}) | |
| self.assertEqual(cached.cache_info(), (0, 0, 128, 0)) | |
| self.assertEqual(cached(1), 1) | |
| self.assertEqual(cached.cache_info(), (0, 1, 128, 1)) | |
| self.assertEqual(cached(1), 1) | |
| self.assertEqual(cached.cache_info(), (1, 1, 128, 1)) | |
| self.assertEqual(cached(1.0), 1.0) | |
| self.assertEqual(cached.cache_info(), (2, 1, 128, 1)) | |
| def test_decorator_needs_rlock(self): | |
| cached = self.decorator(lambda n: n) | |
| class RecursiveEquals: | |
| def __init__(self, use_cache): | |
| self._use_cache = use_cache | |
| def __hash__(self): | |
| return hash(self._use_cache) | |
| def __eq__(self, other): | |
| if self._use_cache: | |
| # This call will happen while the cache-lock is held, | |
| # requiring a reentrant lock to avoid deadlock. | |
| cached(self) | |
| return self._use_cache == other._use_cache | |
| # Prime the cache. | |
| cached(RecursiveEquals(False)) | |
| cached(RecursiveEquals(True)) | |
| # Then do a call which will cause a deadlock with a non-reentrant lock. | |
| self.assertEqual(cached(RecursiveEquals(True)), RecursiveEquals(True)) | |
| class FIFODecoratorTest(unittest.TestCase, DecoratorTestMixin): | |
| DECORATOR = staticmethod(cachetools.func.fifo_cache) | |
| class LFUDecoratorTest(unittest.TestCase, DecoratorTestMixin): | |
| DECORATOR = staticmethod(cachetools.func.lfu_cache) | |
| class LRUDecoratorTest(unittest.TestCase, DecoratorTestMixin): | |
| DECORATOR = staticmethod(cachetools.func.lru_cache) | |
| class MRUDecoratorTest(unittest.TestCase, DecoratorTestMixin): | |
| DECORATOR = staticmethod(cachetools.func.mru_cache) | |
| class RRDecoratorTest(unittest.TestCase, DecoratorTestMixin): | |
| DECORATOR = staticmethod(cachetools.func.rr_cache) | |
| class TTLDecoratorTest(unittest.TestCase, DecoratorTestMixin): | |
| DECORATOR = staticmethod(cachetools.func.ttl_cache) |