Skip to content

Commit 76567d7

Browse files
committed
test(core.utils): cover SQLiteProgramCache LRU eviction
Exercises the size-cap eviction path, confirms reads update accessed_at (so a recently read entry is preserved when a newer write forces eviction), and asserts that omitting the cap keeps the cache unbounded. Part of issue #178.
1 parent 9bd35c0 commit 76567d7

File tree

1 file changed

+58
-0
lines changed

1 file changed

+58
-0
lines changed

cuda_core/tests/test_program_cache.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE
44

55
import abc
6+
import time
67

78
import pytest
89

@@ -376,3 +377,60 @@ def test_sqlite_cache_accepts_str_keys(tmp_path):
376377
assert "str-key" in cache
377378
# Same bytes representation so the corresponding bytes key also hits.
378379
assert b"str-key" in cache
380+
381+
382+
def test_sqlite_cache_rejects_negative_size_cap(tmp_path):
383+
from cuda.core.utils import SQLiteProgramCache
384+
385+
with pytest.raises(ValueError, match="non-negative"):
386+
SQLiteProgramCache(tmp_path / "cache.db", max_size_bytes=-1)
387+
388+
389+
# ---------------------------------------------------------------------------
390+
# SQLiteProgramCache -- LRU eviction
391+
# ---------------------------------------------------------------------------
392+
393+
394+
def test_sqlite_cache_evicts_under_size_cap(tmp_path):
395+
from cuda.core.utils import SQLiteProgramCache
396+
397+
# Each payload pickles to > 2000 bytes; cap is 5000 so only ~2 fit.
398+
cap = 5000
399+
db = tmp_path / "cache.db"
400+
with SQLiteProgramCache(db, max_size_bytes=cap) as cache:
401+
cache[b"a"] = _fake_object_code(b"A" * 2000, name="a")
402+
cache[b"b"] = _fake_object_code(b"B" * 2000, name="b")
403+
cache[b"c"] = _fake_object_code(b"C" * 2000, name="c")
404+
# Adding c must have evicted a (oldest by accessed_at).
405+
assert b"a" not in cache
406+
assert b"b" in cache
407+
assert b"c" in cache
408+
409+
410+
def test_sqlite_cache_lru_order_respects_reads(tmp_path):
411+
from cuda.core.utils import SQLiteProgramCache
412+
413+
cap = 5000
414+
db = tmp_path / "cache.db"
415+
with SQLiteProgramCache(db, max_size_bytes=cap) as cache:
416+
cache[b"a"] = _fake_object_code(b"A" * 2000, name="a")
417+
time.sleep(0.01)
418+
cache[b"b"] = _fake_object_code(b"B" * 2000, name="b")
419+
time.sleep(0.01)
420+
# Touch 'a' so it becomes MRU; 'b' must be evicted when 'c' is added.
421+
_ = cache[b"a"]
422+
time.sleep(0.01)
423+
cache[b"c"] = _fake_object_code(b"C" * 2000, name="c")
424+
assert b"a" in cache
425+
assert b"b" not in cache
426+
assert b"c" in cache
427+
428+
429+
def test_sqlite_cache_unbounded_by_default(tmp_path):
430+
from cuda.core.utils import SQLiteProgramCache
431+
432+
db = tmp_path / "cache.db"
433+
with SQLiteProgramCache(db) as cache:
434+
for i in range(25):
435+
cache[f"k{i}".encode()] = _fake_object_code(b"X" * 1024, name=f"n{i}")
436+
assert len(cache) == 25

0 commit comments

Comments
 (0)