From c810d4feb34f08b29ea6fb7cc3c40ae2b6ca8266 Mon Sep 17 00:00:00 2001 From: Karl Seguin Date: Fri, 21 Nov 2014 14:59:04 +0700 Subject: [PATCH] test + fix for actual size function --- cache.go | 2 +- cache_test.go | 37 +++++++++++++++++++++++++++++++++++++ layeredcache.go | 2 +- layeredcache_test.go | 37 +++++++++++++++++++++++++++++++++---- 4 files changed, 72 insertions(+), 6 deletions(-) diff --git a/cache.go b/cache.go index cb20984..f4b1740 100644 --- a/cache.go +++ b/cache.go @@ -149,10 +149,10 @@ func (c *Cache) worker() { c.gc() } case item := <-c.deletables: + atomic.AddInt64(&c.size, -item.size) if item.element == nil { item.promotions = -2 } else { - atomic.AddInt64(&c.size, -item.size) c.list.Remove(item.element) } } diff --git a/cache_test.go b/cache_test.go index d8130ed..edf1ddc 100644 --- a/cache_test.go +++ b/cache_test.go @@ -73,3 +73,40 @@ func (_ CacheTests) RemovesOldestItemWhenFull() { Expect(cache.Get("1")).To.Equal(nil) Expect(cache.Get("2").Value()).To.Equal(2) } + +func (_ CacheTests) RemovesOldestItemWhenFullBySizer() { + cache := New(Configure().MaxItems(9).ItemsToPrune(2)) + for i := 0; i < 7; i++ { + cache.Set(strconv.Itoa(i), &SizedItem{i, 2}, time.Minute) + } + time.Sleep(time.Millisecond * 10) + Expect(cache.Get("0")).To.Equal(nil) + Expect(cache.Get("1")).To.Equal(nil) + Expect(cache.Get("2")).To.Equal(nil) + Expect(cache.Get("3").Value().(*SizedItem).id).To.Equal(3) +} + +func (_ CacheTests) SetUpdatesSizeOnDelta() { + cache := New(Configure()) + cache.Set("a", &SizedItem{0, 2}, time.Minute) + cache.Set("b", &SizedItem{0, 3}, time.Minute) + Expect(cache.size).To.Equal(int64(5)) + cache.Set("b", &SizedItem{0, 3}, time.Minute) + Expect(cache.size).To.Equal(int64(5)) + cache.Set("b", &SizedItem{0, 4}, time.Minute) + Expect(cache.size).To.Equal(int64(6)) + cache.Set("b", &SizedItem{0, 2}, time.Minute) + Expect(cache.size).To.Equal(int64(4)) + cache.Delete("b") + time.Sleep(time.Millisecond * 10) + Expect(cache.size).To.Equal(int64(2)) +} + +type SizedItem struct { + id int + s int64 +} + +func (s *SizedItem) Size() int64 { + return s.s +} diff --git a/layeredcache.go b/layeredcache.go index 869090d..8aa4690 100644 --- a/layeredcache.go +++ b/layeredcache.go @@ -160,10 +160,10 @@ func (c *LayeredCache) worker() { c.gc() } case item := <-c.deletables: + atomic.AddInt64(&c.size, -item.size) if item.element == nil { item.promotions = -2 } else { - atomic.AddInt64(&c.size, -item.size) c.list.Remove(item.element) } } diff --git a/layeredcache_test.go b/layeredcache_test.go index 24abfd5..45ab90f 100644 --- a/layeredcache_test.go +++ b/layeredcache_test.go @@ -77,7 +77,7 @@ func (_ *LayeredCacheTests) DeletesALayer() { Expect(cache.Get("leto", "sister").Value()).To.Equal("ghanima") } -func (c *LayeredCacheTests) GCsTheOldestItems() { +func (_ LayeredCacheTests) GCsTheOldestItems() { cache := Layered(Configure().ItemsToPrune(10)) cache.Set("xx", "a", 23, time.Minute) for i := 0; i < 500; i++ { @@ -94,7 +94,7 @@ func (c *LayeredCacheTests) GCsTheOldestItems() { Expect(cache.Get("10", "a").Value()).To.Equal(10) } -func (c *LayeredCacheTests) PromotedItemsDontGetPruned() { +func (_ LayeredCacheTests) PromotedItemsDontGetPruned() { cache := Layered(Configure().ItemsToPrune(10).GetsPerPromote(1)) for i := 0; i < 500; i++ { cache.Set(strconv.Itoa(i), "a", i, time.Minute) @@ -108,7 +108,7 @@ func (c *LayeredCacheTests) PromotedItemsDontGetPruned() { Expect(cache.Get("11", "a").Value()).To.Equal(11) } -func (c *LayeredCacheTests) TrackerDoesNotCleanupHeldInstance() { +func (_ LayeredCacheTests) TrackerDoesNotCleanupHeldInstance() { cache := Layered(Configure().ItemsToPrune(10).Track()) for i := 0; i < 10; i++ { cache.Set(strconv.Itoa(i), "a", i, time.Minute) @@ -123,7 +123,7 @@ func (c *LayeredCacheTests) TrackerDoesNotCleanupHeldInstance() { Expect(cache.Get("0", "a")).To.Equal(nil) } -func (c *LayeredCacheTests) RemovesOldestItemWhenFull() { +func (_ LayeredCacheTests) RemovesOldestItemWhenFull() { cache := Layered(Configure().MaxItems(5).ItemsToPrune(1)) cache.Set("xx", "a", 23, time.Minute) for i := 0; i < 7; i++ { @@ -142,3 +142,32 @@ func (c *LayeredCacheTests) RemovesOldestItemWhenFull() { func newLayered() *LayeredCache { return Layered(Configure()) } + +func (_ LayeredCacheTests) RemovesOldestItemWhenFullBySizer() { + cache := Layered(Configure().MaxItems(9).ItemsToPrune(2)) + for i := 0; i < 7; i++ { + cache.Set("pri", strconv.Itoa(i), &SizedItem{i, 2}, time.Minute) + } + time.Sleep(time.Millisecond * 10) + Expect(cache.Get("pri", "0")).To.Equal(nil) + Expect(cache.Get("pri", "1")).To.Equal(nil) + Expect(cache.Get("pri", "2")).To.Equal(nil) + Expect(cache.Get("pri", "3").Value().(*SizedItem).id).To.Equal(3) +} + +func (_ LayeredCacheTests) SetUpdatesSizeOnDelta() { + cache := Layered(Configure()) + cache.Set("pri", "a", &SizedItem{0, 2}, time.Minute) + cache.Set("pri", "b", &SizedItem{0, 3}, time.Minute) + Expect(cache.size).To.Equal(int64(5)) + cache.Set("pri", "b", &SizedItem{0, 3}, time.Minute) + Expect(cache.size).To.Equal(int64(5)) + cache.Set("pri", "b", &SizedItem{0, 4}, time.Minute) + Expect(cache.size).To.Equal(int64(6)) + cache.Set("pri", "b", &SizedItem{0, 2}, time.Minute) + cache.Set("sec", "b", &SizedItem{0, 3}, time.Minute) + Expect(cache.size).To.Equal(int64(7)) + cache.Delete("pri", "b") + time.Sleep(time.Millisecond * 10) + Expect(cache.size).To.Equal(int64(5)) +}