import time import pytest from ttl_lru_cache import TTLCache, CacheMiss def test_basic_get_set(): c = TTLCache(2) c.set("a", 1) c.set("b", 2) assert c.get("a") == 1 assert c.get("z", 9) == 9 assert "a" in c def test_lru_eviction(): c = TTLCache(2) c.set("a", 1) c.set("b", 2) c.get("a") # make a recently used c.set("c", 3) assert "b" not in c assert c.get("a") == 1 assert c.get("c") == 3 def test_ttl_expiry(): clock = [0.0] c = TTLCache(10, default_ttl=5, clock=lambda: clock[0]) c.set("a", 1) assert c.get("a") == 1 clock[0] = 6 assert c.get("a") is None assert "a" not in c assert len(c) == 0 def test_per_entry_ttl_override(): clock = [0.0] c = TTLCache(10, default_ttl=100, clock=lambda: clock[0]) c.set("short", 1, ttl=2) c.set("long", 2) clock[0] = 3 assert "short" not in c assert c.get("long") == 2 def test_peek_does_not_update_recency(): c = TTLCache(2) c.set("a", 1) c.set("b", 2) c.peek("a") c.set("c", 3) # a was not touched via get, so it should be evicted (b was more recent? actually b inserted last) # After set a,b: order a,b. peek a no change. set c evicts LRU = a. assert "a" not in c def test_get_strict_raises(): c = TTLCache(2) with pytest.raises(CacheMiss): c.get_strict("nope") def test_invalid_args(): with pytest.raises(ValueError): TTLCache(0) with pytest.raises(ValueError): TTLCache(2, default_ttl=0) c = TTLCache(2) with pytest.raises(ValueError): c.set("x", 1, ttl=0) def test_delete_and_clear(): c = TTLCache(2) c.set("a", 1) assert c.delete("a") is True assert c.delete("a") is False c.set("b", 2) c.clear() assert len(c) == 0 def test_capacity_eviction_with_expired(): clock = [0.0] c = TTLCache(2, clock=lambda: clock[0]) c.set("a", 1, ttl=1) c.set("b", 2, ttl=1) clock[0] = 2 # both expired c.set("c", 3) # should not count expired toward capacity assert len(c) == 1 assert c.get("c") == 3