Files
troupe-standup/wizard-work/beam/test_lru_ttl_cache_beam.py
T

79 lines
2.3 KiB
Python

import threading
import time
import unittest
from lru_ttl_cache_beam import LRUTTLCache
class TestLRUTTLCache(unittest.TestCase):
def test_basic_put_get(self):
c = LRUTTLCache(maxsize=2, ttl=10)
c.put("a", 1)
self.assertEqual(c.get("a"), 1)
self.assertEqual(c.get("missing", "d"), "d")
def test_lru_eviction(self):
c = LRUTTLCache(maxsize=2, ttl=10)
c.put("a", 1); c.put("b", 2)
c.get("a") # refresh a
c.put("c", 3) # evicts b
self.assertEqual(c.get("b", None), None)
self.assertEqual(c.get("a"), 1)
self.assertEqual(c.get("c"), 3)
def test_ttl_expiry(self):
clock = {"t": 0.0}
c = LRUTTLCache(maxsize=4, ttl=5, clock=lambda: clock["t"])
c.put("a", 1)
self.assertTrue(c.contains("a"))
clock["t"] = 6.0
self.assertFalse(c.contains("a"))
self.assertEqual(c.get("a", "x"), "x")
def test_put_overwrite_resets_ttl(self):
clock = {"t": 0.0}
c = LRUTTLCache(maxsize=4, ttl=5, clock=lambda: clock["t"])
c.put("a", 1)
clock["t"] = 4.0
c.put("a", 2) # reset ttl: now expires at 9
clock["t"] = 8.0
self.assertEqual(c.get("a"), 2)
clock["t"] = 10.0
self.assertEqual(c.get("a", "x"), "x")
def test_stats(self):
c = LRUTTLCache(maxsize=2, ttl=10)
c.put("a", 1); c.put("b", 2)
c.get("a"); c.get("zzz")
s = c.stats
self.assertEqual(s["hits"], 1)
self.assertEqual(s["misses"], 1)
self.assertEqual(s["size"], 2)
def test_thread_safety(self):
c = LRUTTLCache(maxsize=100, ttl=100)
errs = []
def w(i):
try:
for j in range(50):
c.put((i, j), i * j)
c.get((i, j))
except Exception as e: # noqa
errs.append(e)
ts = [threading.Thread(target=w, args=(i,)) for i in range(8)]
for t in ts: t.start()
for t in ts: t.join()
self.assertFalse(errs)
def test_validation(self):
with self.assertRaises(ValueError):
LRUTTLCache(maxsize=0, ttl=1)
with self.assertRaises(ValueError):
LRUTTLCache(maxsize=1, ttl=0)
if __name__ == "__main__":
unittest.main()