Skip to content
Snippets Groups Projects
Verified Commit 130380d6 authored by Daniel Hornung's avatar Daniel Hornung
Browse files

TEST: Added and improved unit tests.

parent f49137e6
No related branches found
No related tags found
2 merge requests!107ENH: add entity getters and cached functions,!100ENH: add entity getters and cached functions
Pipeline #35537 failed
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
""" Test the caosdb.cached module """ """ Test the caosdb.cached module """
from caosdb.cached import (cached_get_entity_by, cache_clear, cache_info, fill_cache, from caosdb.cached import (cached_get_entity_by, cache_clear, cache_info, cache_fill,
AccessType, cache_initialize, cached_query) AccessType, cache_initialize, cached_query)
from unittest.mock import patch from unittest.mock import patch
import caosdb as db import caosdb as db
...@@ -60,11 +60,17 @@ def mocked_path_query(path): ...@@ -60,11 +60,17 @@ def mocked_path_query(path):
return deepcopy([el for el in DUMMY_SERVER_CONTENT if el.path == path][0]) return deepcopy([el for el in DUMMY_SERVER_CONTENT if el.path == path][0])
def mocked_gen_query(q): def mocked_gen_query(q, unique):
if q == 'a': if unique:
return db.Container().extend([DUMMY_SERVER_CONTENT[0]]) if q == 'a':
return DUMMY_SERVER_CONTENT[0]
else:
return None
else: else:
return db.Container().extend(DUMMY_SERVER_CONTENT) if q == 'a':
return db.Container().extend([DUMMY_SERVER_CONTENT[0]])
else:
return db.Container().extend(DUMMY_SERVER_CONTENT)
@patch("caosdb.utils.get_entity.get_entity_by_name") @patch("caosdb.utils.get_entity.get_entity_by_name")
...@@ -87,7 +93,7 @@ def test_get_by_name(mocked_get_by_name): ...@@ -87,7 +93,7 @@ def test_get_by_name(mocked_get_by_name):
cached_get_entity_by(name='a') cached_get_entity_by(name='a')
assert mocked_get_by_name.call_count == 2 assert mocked_get_by_name.call_count == 2
# we fill the cache manually and make sure the element is used # we fill the cache manually and make sure the element is used
fill_cache({'lol': db.Entity(id=10001, name='lol')}, AccessType.NAME, unique=True) cache_fill({'lol': db.Entity(id=10001, name='lol')}, AccessType.NAME, unique=True)
# there are now two elements in the cache: a and lol # there are now two elements in the cache: a and lol
assert cache_info().currsize == 2 assert cache_info().currsize == 2
# we can retrieve the inserted element # we can retrieve the inserted element
...@@ -122,7 +128,7 @@ def test_get_by_id(mocked_get_by_id): ...@@ -122,7 +128,7 @@ def test_get_by_id(mocked_get_by_id):
cached_get_entity_by(eid=102) cached_get_entity_by(eid=102)
assert mocked_get_by_id.call_count == 2 assert mocked_get_by_id.call_count == 2
# we fill the cache manually and make sure the element is used # we fill the cache manually and make sure the element is used
fill_cache({10001: db.Entity(id=10001, name='lol')}, AccessType.EID, unique=True) cache_fill({10001: db.Entity(id=10001, name='lol')}, AccessType.EID, unique=True)
# there are now two elements in the cache: a and lol # there are now two elements in the cache: a and lol
assert cache_info().currsize == 2 assert cache_info().currsize == 2
# we can retrieve the inserted element # we can retrieve the inserted element
...@@ -156,7 +162,7 @@ def test_get_by_path(mocked_get_by_path): ...@@ -156,7 +162,7 @@ def test_get_by_path(mocked_get_by_path):
cached_get_entity_by(path='p') cached_get_entity_by(path='p')
assert mocked_get_by_path.call_count == 2 assert mocked_get_by_path.call_count == 2
# we fill the cache manually and make sure the element is used # we fill the cache manually and make sure the element is used
fill_cache({'lol': db.File(id=10001, path='lol')}, AccessType.PATH, unique=True) cache_fill({'lol': db.File(id=10001, path='lol')}, AccessType.PATH, unique=True)
# there are now two elements in the cache: a and lol # there are now two elements in the cache: a and lol
assert cache_info().currsize == 2 assert cache_info().currsize == 2
# we can retrieve the inserted element # we can retrieve the inserted element
...@@ -170,6 +176,35 @@ def test_get_by_path(mocked_get_by_path): ...@@ -170,6 +176,35 @@ def test_get_by_path(mocked_get_by_path):
assert c.id == 105 assert c.id == 105
@patch("caosdb.cached.execute_query")
def test_get_by_query(mocked_query):
mocked_query.side_effect = mocked_gen_query
# test cache initialization
cache_initialize(maxsize=10)
assert cache_info().currsize == 0
# Non-existent entity
res = cached_get_entity_by(query='stuff')
assert res is None
assert cache_info().currsize == 1
assert cache_info().hits == 0
assert cache_info().misses == 1
res = cached_get_entity_by(query='stuff')
assert res is None
assert cache_info().currsize == 1
assert cache_info().hits == 1
assert cache_info().misses == 1
# Existent entity
a = cached_get_entity_by(query='a')
assert a is not None
assert a.id == 101
assert cache_info().currsize == 2
assert cache_info().hits == 1
assert cache_info().misses == 2
@patch("caosdb.cached.execute_query") @patch("caosdb.cached.execute_query")
def test_cached_query(mocked_query): def test_cached_query(mocked_query):
mocked_query.side_effect = mocked_gen_query mocked_query.side_effect = mocked_gen_query
...@@ -206,3 +241,55 @@ def test_cached_query(mocked_query): ...@@ -206,3 +241,55 @@ def test_cached_query(mocked_query):
c = cached_query('a') c = cached_query('a')
assert mocked_query.call_count == 3 assert mocked_query.call_count == 3
assert c[0].id == 101 assert c[0].id == 101
@patch("caosdb.utils.get_entity.get_entity_by_name")
def test_cache_size(mocked_get_by_name):
mocked_get_by_name.side_effect = lambda x: x
# first call; not in cache -> mocked_execute is touched
maxsize = 5
cache_initialize(maxsize=maxsize)
assert cache_info().currsize == 0
names_first = ("a", "b", "c", "d", "e")
names_later = ("A", "B", "C", "D", "E")
names_fill = {"X": None, "Y": None, "Z": None}
# Use the first batch of names
for ii, name in enumerate(names_first, start=1):
cached_get_entity_by(name=name)
assert cache_info().currsize == ii
assert cache_info().hits == 0
assert cache_info().misses == ii
for ii, name in enumerate(names_first, start=1):
cached_get_entity_by(name=name)
assert cache_info().currsize == maxsize
assert cache_info().hits == ii
assert cache_info().misses == maxsize
# use the second batch of names
for ii, name in enumerate(names_later, start=1):
cached_get_entity_by(name=name)
assert cache_info().currsize == maxsize
assert cache_info().hits == len(names_first)
assert cache_info().misses == len(names_first) + ii
for ii, name in enumerate(names_later, start=1):
cached_get_entity_by(name=name)
assert cache_info().currsize == maxsize
assert cache_info().hits == len(names_first) + ii
assert cache_info().misses == len(names_first) + len(names_later)
# The cache is now filled with A,B,C,D,E (oldest to least recently used).
# Let's fill it with X,Y,Z.
cache_fill(names_fill, kind=AccessType.NAME)
# Now, the cache should be: D,E,X,Y,Z
current_misses = cache_info().misses
for name in ("Z", "Y", "X", "E", "D"):
cached_get_entity_by(name=name)
assert cache_info().misses == current_misses
for ii, name in enumerate(("A", "B", "C"), start=1):
cached_get_entity_by(name=name)
assert cache_info().misses == current_misses + ii
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment