blob: 69f815638d12c521cd0fd6632f9e8a7854f9e7b7 [file] [log] [blame]
from unittest import IsolatedAsyncioTestCase
from cache import Cache
import time
def compute_to_1():
return 1
def compute_to_2():
return 2
def compute_to_3():
return 3
class CacheTest(IsolatedAsyncioTestCase):
"""
Testing the cache code.
"""
def test_can_get_from_default_value(self):
"""
Testing get data from default function,
because the cache is fresh.
"""
c = Cache()
KEY = 1
# As the cache is empty now, it triggers the `or_default`
# immediately. We get the value `1` now.
res = c.get(KEY, or_default=compute_to_1)
assert(res == 1)
def test_can_get_from_cache_data(self):
"""
Testing get data from the cache.
"""
c = Cache(delay=5)
KEY = 1
# As the cache is empty now, it triggers the `or_default`
# immediately. We get the value `1` now.
res = c.get(KEY, or_default=compute_to_1)
assert(res == 1)
# As the default delay is 5s, the cache won't update within
# 5s. We get the old value from cache is `1`, and the cache
# keeps the `1` and won't update.
res = c.get(KEY, or_default=compute_to_2)
assert(res == 1)
time.sleep(5.5)
# Get the value again. We get the old value `1` from cache.
# As the delay is reached, the cache update the value to `2` for KEY.
res = c.get(KEY, or_default=compute_to_2)
assert(res == 1)
def test_should_refresh_in_background_when_force_updated_is_true(self):
"""
Testing should update data in background
when conditions are reached.
"""
# Arrange - Setup a cache with 60s delay, it means the cache
# will keep the old value for 60s. Within 60s, the cache only
# return the value, which is set by first time.
c = Cache(delay=60)
KEY = 1
# As the cache doesn't store any value for KEY.
# It will execute a default function first, and then
# set a value for KEY. After that, it returns value.
res = c.get(KEY, or_default=compute_to_1)
assert(res == 1)
# As the value is updated/set within 60s(delay), the
# cache won't update, so it always keeps the old value
# and don't refresh the cache.
for _ in range(0, 5):
res = c.get(KEY, or_default=compute_to_2)
assert(res == 1)
# The test is for setting `force_udpate` to True,
# the cache should update immediately.
res = c.get(KEY, or_default=compute_to_2, force_update=True)
assert(res == 2)
def test_should_refresh_in_background_when_delay_is_reached(self):
"""
Testing should update data in background
when conditions are reached.
"""
c = Cache(delay=5)
KEY = 1
# As the cache doesn't store any value for KEY.
# It will execute a default function first, and then
# set a value for KEY. After that, it returns value.
res = c.get(KEY, or_default=compute_to_1)
assert(res == 1)
# As the value is updated/set within 5s(delay), the
# cache won't update, it always keeps the old value
# and don't refresh the cache.
for _ in range(0, 5):
res = c.get(KEY, or_default=compute_to_2)
assert(res == 1)
# Simulate keeping the cache over the delay.
time.sleep(5.5)
# After over 5s(delay, when the user gets the cache again
# it returns the old value first, and updates the cache
# in background, when user gets it again, it should return
# the new value.
res = c.get(KEY, or_default=compute_to_2)
assert(res == 1)
# Even though, we give the `or_default` returns `3`,
# but the value sholud be the cache `2`. As the delay
# isn't reached, the cache won't update, it keeps `2`
res = c.get(KEY, or_default=compute_to_3)
assert(res == 2)
time.sleep(5.5)
# We get the old value from cache, and then as the
# delay is reached, the cache updates to `3` now.
res = c.get(KEY, or_default=compute_to_3)
assert(res == 2)
res = c.get(KEY, or_default=compute_to_3)
assert(res == 3)
def test_should_refresh_when_ttl_is_reached(self):
"""
Testing should update data in background
and return the value
"""
# Arrange the cache with delay 60s, and ttl 3s.
c = Cache(delay=60, ttl=3)
KEY = 1
# As the cache is empty, it returns the value
# and updates the value to cache immediately.
res = c.get(KEY, or_default=compute_to_1)
assert(res == 1)
# Make a sleep over ttl limitation, the cache
# sholud be gone.
time.sleep(3.5)
# test the cache is exist, if it is exit, it
# should return `1`, not the new value `2`.
res = c.get(KEY, or_default=compute_to_2)
assert(res == 2)
def test_should_not_refresh_in_background(self):
"""
Testing shouldn't update data in background
when the conditions aren't reached.
"""
c = Cache(delay=60)
KEY = 1
# As the cache is empty, it returns the value
# and updates the value to cache immediately.
res = c.get(KEY, or_default=compute_to_1)
assert(res == 1)
# As the value is updated/set within 60s(delay), the
# cache won't update, it always keeps the old value
# and don't refresh the cache.
for _ in range(0, 10):
res = c.get(KEY, or_default=compute_to_2)
assert(res == 1)
time.sleep(1)
def test_should_get_the_value_when_the_cache_is_cleared(self):
"""
Testing should upate and return the value when the cache is cleared
"""
c = Cache(delay=60)
KEY = 1
# As the cache is empty, it returns the value
# and updates the value to cache immediately.
res = c.get(KEY, or_default=compute_to_1)
assert(res == 1)
c.clear()
res = c.get(KEY, or_default=compute_to_2)
assert(res == 2)
def test_should_get_none_when_or_default_is_none(self):
"""
Testing the cache without `or_default` function.
"""
c = Cache(delay=5)
KEY = 1
res = c.get(KEY)
assert(res is None)
def test_should_return_cache_value_when_or_default_is_set_at_least_one(self):
"""
Testing the cache set the value at least one.
"""
c = Cache()
KEY = 1
# As the cache is empty, it returns the value
# and updates the value to cache immediately.
res = c.get(KEY, or_default=compute_to_1)
assert(res == 1)
# As the `or_default` function is None,
# but the value is set before, so it will
# return the cache data.
res = c.get(KEY)
assert(res == 1)
def test_should_return_none_when_or_default_is_none_and_cached_data_is_expired(self):
"""
Testing the cached data is expired and without `or_default` function
"""
c = Cache(ttl=3)
KEY = 1
# As the cache is empty, it returns the value
# and updates the value to cache immediately.
res = c.get(KEY, or_default=compute_to_1)
assert(res == 1)
time.sleep(3.5)
# As the cache is expired and without `or_default`
# the value should be None.
res = c.get(KEY)
assert(res is None)