diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..3fd146e --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module github.com/hnlq715/golang-lru + +go 1.12 diff --git a/simplelru/lru.go b/simplelru/lru.go index 0126f67..d5f0264 100644 --- a/simplelru/lru.go +++ b/simplelru/lru.go @@ -192,6 +192,19 @@ func (c *LRU) Len() int { return c.evictList.Len() } +// Resize changes the cache size. +func (c *LRU) Resize(size int) (evicted int) { + diff := c.Len() - size + if diff < 0 { + diff = 0 + } + for i := 0; i < diff; i++ { + c.removeOldest() + } + c.size = size + return diff +} + // removeOldest removes the oldest item from the cache. func (c *LRU) removeOldest() { ent := c.evictList.Back() diff --git a/simplelru/lru_test.go b/simplelru/lru_test.go index af8dcd4..6ce7095 100644 --- a/simplelru/lru_test.go +++ b/simplelru/lru_test.go @@ -196,3 +196,42 @@ func TestLRU_Expire(t *testing.T) { t.Errorf("1 should not be contained") } } + +// Test that Resize can upsize and downsize +func TestLRU_Resize(t *testing.T) { + onEvictCounter := 0 + onEvicted := func(k interface{}, v interface{}) { + onEvictCounter++ + } + l, err := NewLRU(2, onEvicted) + if err != nil { + t.Fatalf("err: %v", err) + } + + // Downsize + l.Add(1, 1) + l.Add(2, 2) + evicted := l.Resize(1) + if evicted != 1 { + t.Errorf("1 element should have been evicted: %v", evicted) + } + if onEvictCounter != 1 { + t.Errorf("onEvicted should have been called 1 time: %v", onEvictCounter) + } + + l.Add(3, 3) + if l.Contains(1) { + t.Errorf("Element 1 should have been evicted") + } + + // Upsize + evicted = l.Resize(2) + if evicted != 0 { + t.Errorf("0 elements should have been evicted: %v", evicted) + } + + l.Add(4, 4) + if !l.Contains(3) || !l.Contains(4) { + t.Errorf("Cache should have contained 2 elements") + } +}