import random from collections import OrderedDict from lru_cache import LRUCache def test_basic_get_put(): c = LRUCache(2) c.put(1, 1) c.put(2, 2) assert c.get(1) == 1 c.put(3, 3) # evicts 2 assert c.get(2) == -1 assert c.get(1) == 1 assert c.get(3) == 3 def test_update_promotes_recency(): # subtle bug: updating existing key must move to MRU c = LRUCache(2) c.put(1, 1) c.put(2, 2) c.put(1, 10) # update -> 1 becomes MRU, 2 LRU c.put(3, 3) # should evict 2, not 1 assert c.get(2) == -1 assert c.get(1) == 10 assert c.get(3) == 3 def test_eviction_removes_from_map(): c = LRUCache(1) c.put(1, 1) c.put(2, 2) assert c.size() == 1 assert c.get(1) == -1 def test_capacity_validation(): for bad in (0, -1, True, "2", 2.0): try: LRUCache(bad) raised = False except (ValueError, TypeError): raised = True assert raised, bad def test_order_introspection(): c = LRUCache(3) for k in (1, 2, 3): c.put(k, k) assert c.order_mru_to_lru() == [3, 2, 1] c.get(1) assert c.order_mru_to_lru() == [1, 3, 2] def test_randomized_against_ordereddict(): random.seed(42) cap = 5 c = LRUCache(cap) ref = OrderedDict() ops = 2000 for _ in range(ops): k = random.randrange(0, 12) if random.random() < 0.5: v = random.randrange(0, 100) c.put(k, v) ref[k] = v # move to end (MRU) in reference ref.move_to_end(k) if len(ref) > cap: ref.popitem(last=False) else: got = c.get(k) if k in ref: ref.move_to_end(k) assert got == ref[k], (k, got, ref[k]) else: assert got == -1 # size invariant assert c.size() == len(ref) # order invariant expected_order = list(reversed(list(ref.keys()))) # MRU..LRU assert c.order_mru_to_lru() == expected_order, (c.order_mru_to_lru(), expected_order)