def test_change_timeout(): f = Mock(__name__='f', return_value=SOME_VALUE) decorated = cache()(f) # Cache FOREVER decorated() # Warm cache f.return_value = None assert decorated() == SOME_VALUE assert cache(0)(f)() is None
def test_key_func(): """ Test that the provided key function is used. """ f = Mock(__name__='f', return_value=None) g = Mock(__name__='g', return_value=None) key_func = lambda fn, *args, **kwargs: 'key' cache(key_func=key_func)(f)() cache(key_func=key_func)(g)() assert g.call_count == 0
def test_value(): """ Makes sure the cached value is correct. """ f = Mock(__name__='f', return_value=SOME_VALUE) decorated = cache()(f) assert decorated() == SOME_VALUE
def test_caching(): """ Makes sure the cache is actually used. """ f = Mock(__name__='f', return_value=None) decorated = cache()(f) decorated() decorated() assert f.call_count == 1
def test_invalidate_args(): """ Ensure that invalidate clears the cache for the provided args. """ f = Mock(__name__='f', return_value=None) decorated = cache()(f) decorated(1) decorated.invalidate(1) decorated(1) assert f.call_count == 2
def test_invalidate(): """ Ensure that invalidate clears the cache. """ f = Mock(__name__='f', return_value=None) decorated = cache()(f) decorated() decorated.invalidate() decorated() assert f.call_count == 2
def test_nocache(): """ Makes sure that the cache decorator doesn't cache when it has a 0 timeout. """ f = Mock(__name__='f', return_value=None) decorated = cache(timeout=0)(f) decorated() decorated() assert f.call_count == 2
def test_key_func_nocache(): """ Test that returning ``None`` from the key function bypasses the cache. """ f = Mock(__name__='f', return_value=None) key_func = lambda fn, *args, **kwargs: None decorated = cache(key_func=key_func)(f) decorated(1) decorated(1) assert f.call_count == 2
def test_only_invalidate_args(): """ Ensure that invalidate doesn't clear the cache for other args. """ f = Mock(__name__='f', return_value=None) decorated = cache()(f) decorated(1) decorated.invalidate(2) decorated(1) assert f.call_count == 1
def test_gh_1(): """Test that updating the TTL doesn't break backgrounding.""" cache_backend = get_cache_backend('default') mocked = Mock(wraps=cache_backend) with patch('throttleandcache.decorators.get_cache_backend') as factory: factory.return_value = mocked f = Mock(__name__='f', return_value=None) key_func = lambda *args, **kwargs: 'key' # Prime the cache decorated = cache('5s', key_func=key_func, graceful=True)(f) decorated() ttl = mocked.set.call_args[0][2] assert ttl == settings.THROTTLEANDCACHE_MAX_TIMEOUT # Now change the cache TTL decorated = cache('6s', key_func=key_func, graceful=True)(f) decorated() ttl = mocked.set.call_args[0][2] assert ttl == settings.THROTTLEANDCACHE_MAX_TIMEOUT
def test_graceful(): def f(): if f.called: f.errored = True raise Exception f.called = True return SOME_VALUE f.called = False f.errored = False decorated = cache('0s', graceful=True)(f) decorated() # Successful call value = decorated() # Unsuccessful, but should be handled gracefully. assert f.errored assert value == SOME_VALUE
def test_background(): """ Test that caching in the background will actually call the celery task. """ f = Mock(__name__='f', return_value=SOME_VALUE) with patch('throttleandcache.tasks._get_result.delay') as mocked: # Use a zero timeout to make sure that the value is expired for # subsequent calls. decorated = cache(timeout=0, background=True)(f) # With a cold cache, the call should be synchronous. decorated() assert f.call_count == 1 assert mocked.call_count == 0 # After that, the Celery task should be used. decorated() assert f.call_count == 1 assert mocked.call_count == 1
def test_none(): fn = cache()(lambda: None) assert fn() is None
assert f.call_count == 1 assert mocked.call_count == 1 THE_KEY = 'the_key' def get_value(): return None def key_func(*args, **kwargs): return THE_KEY original_get_value = get_value get_value = cache('1 day', key_func=key_func, background=True)(get_value) def test_background_serialization(): """Make sure that the wrapped function is what's serialized.""" # Prime the cache get_value() # Update the set_time to make sure we trigger a background process. val = cache_obj.get(THE_KEY) val.set_time = datetime(2000, 1, 1) cache_obj.set(THE_KEY, val) with patch('throttleandcache.tasks._get_result.delay') as mocked: get_value()