From a139af414437d150c72562ef765dcb392b58edfa Mon Sep 17 00:00:00 2001 From: Matt Harrison <88399148+mattharr013@users.noreply.github.com> Date: Tue, 20 Dec 2022 10:31:47 -0500 Subject: [PATCH] Fix LRU to correct evict cache items when replaced (#52) --- groupcache_test.go | 15 +++++++++++++++ lru/lru.go | 6 +++++- lru/lru_test.go | 26 ++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/groupcache_test.go b/groupcache_test.go index e87c62a..5eca5e2 100644 --- a/groupcache_test.go +++ b/groupcache_test.go @@ -535,3 +535,18 @@ func TestContextDeadlineOnPeer(t *testing.T) { } } } + +func TestCacheRemovesBytesOfReplacedValues(t *testing.T) { + c := cache{} + + const key = "test" + keyLen := len(key) + + for _, bytes := range []int{100, 1000, 2000} { + c.add(key, ByteView{b: make([]byte, bytes)}) + expected := int64(bytes + keyLen) + if c.nbytes != expected { + t.Fatalf("%s: expected %d was %d", t.Name(), expected, c.nbytes) + } + } +} diff --git a/lru/lru.go b/lru/lru.go index 9e606c0..549122f 100644 --- a/lru/lru.go +++ b/lru/lru.go @@ -63,8 +63,12 @@ func (c *Cache) Add(key Key, value interface{}, expire time.Time) { c.ll = list.New() } if ee, ok := c.cache[key]; ok { + eee := ee.Value.(*entry) + if c.OnEvicted != nil { + c.OnEvicted(key, eee.value) + } c.ll.MoveToFront(ee) - ee.Value.(*entry).value = value + eee.value = value return } ele := c.ll.PushFront(&entry{key, value, expire}) diff --git a/lru/lru_test.go b/lru/lru_test.go index a2e5f0b..4d029c5 100644 --- a/lru/lru_test.go +++ b/lru/lru_test.go @@ -46,6 +46,32 @@ var getTests = []struct { complexStruct{1, simpleStruct{2, "three"}}, true}, } +func TestAdd_evictsOldAndReplaces(t *testing.T) { + var evictedKey Key + var evictedValue interface{} + lru := New(0) + lru.OnEvicted = func(key Key, value interface{}) { + evictedKey = key + evictedValue = value + } + lru.Add("myKey", 1234, time.Time{}) + lru.Add("myKey", 1235, time.Time{}) + + newVal, ok := lru.Get("myKey") + if !ok { + t.Fatalf("%s: cache hit = %v; want %v", t.Name(), ok, !ok) + } + if newVal != 1235 { + t.Fatalf("%s: cache hit = %v; want %v", t.Name(), newVal, 1235) + } + if evictedKey != "myKey" { + t.Fatalf("%s: evictedKey = %v; want %v", t.Name(), evictedKey, "myKey") + } + if evictedValue != 1234 { + t.Fatalf("%s: evictedValue = %v; want %v", t.Name(), evictedValue, 1234) + } +} + func TestGet(t *testing.T) { for _, tt := range getTests { lru := New(0)