Skip to content

Commit 5098153

Browse files
committed
added more tests for lfu
1 parent e071df4 commit 5098153

File tree

3 files changed

+146
-5
lines changed

3 files changed

+146
-5
lines changed

lfu/lfu.go

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,14 @@ func (c *Cache[K, V]) Set(key K, val V, opts ...cache.ItemOption) {
5858
return
5959
}
6060

61-
e := newEntry(key, val, opts...)
62-
heap.Push(c.queue, e)
63-
c.items[key] = e
64-
65-
if len(c.items) > c.cap {
61+
if len(c.items) == c.cap {
6662
evictedEntry := heap.Pop(c.queue).(*entry[K, V])
6763
delete(c.items, evictedEntry.item.Key)
6864
}
65+
66+
e := newEntry(key, val, opts...)
67+
heap.Push(c.queue, e)
68+
c.items[key] = e
6969
}
7070

7171
// Keys returns the keys of the cache. the order is from oldest to newest.
@@ -99,3 +99,10 @@ func (c *Cache[K, V]) Contains(key K) bool {
9999
}
100100
return !e.item.HasExpired()
101101
}
102+
103+
// Len returns the number of items in the cache.
104+
func (c *Cache[K, V]) Len() int {
105+
c.mu.RLock()
106+
defer c.mu.RUnlock()
107+
return c.queue.Len()
108+
}

lfu/lfu_internal_test.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package lfu
2+
3+
import (
4+
"testing"
5+
"time"
6+
7+
cache "github.com/Code-Hex/go-generics-cache"
8+
)
9+
10+
func TestContains(t *testing.T) {
11+
t.Run("without expiration", func(t *testing.T) {
12+
cache := NewCache[string, int]()
13+
cache.Set("foo", 1)
14+
cache.Set("bar", 2)
15+
cache.Set("baz", 3)
16+
for _, key := range []string{
17+
"foo",
18+
"bar",
19+
"baz",
20+
} {
21+
if !cache.Contains(key) {
22+
t.Errorf("not found: %s", key)
23+
}
24+
}
25+
if cache.Contains("not found") {
26+
t.Errorf("found")
27+
}
28+
})
29+
30+
t.Run("with expiration", func(t *testing.T) {
31+
c := NewCache[string, int]()
32+
key := "foo"
33+
exp := time.Hour
34+
c.Set(key, 1, cache.WithExpiration(exp))
35+
// modify directly
36+
e, ok := c.items[key]
37+
if !ok {
38+
t.Fatal("unexpected not found key")
39+
}
40+
item := e.item
41+
item.CreatedAt = time.Now().Add(-2 * exp)
42+
43+
if c.Contains(key) {
44+
t.Errorf("found")
45+
}
46+
})
47+
}
48+
49+
func TestGet(t *testing.T) {
50+
c := NewCache[string, int]()
51+
key := "foo"
52+
exp := time.Hour
53+
c.Set(key, 1, cache.WithExpiration(exp))
54+
_, ok := c.Get(key)
55+
if !ok {
56+
t.Fatal("unexpected not found")
57+
}
58+
// modify directly
59+
e, ok := c.items[key]
60+
if !ok {
61+
t.Fatal("unexpected not found key")
62+
}
63+
item := e.item
64+
item.CreatedAt = time.Now().Add(-2 * exp)
65+
_, ok2 := c.Get(key)
66+
if ok2 {
67+
t.Fatal("unexpected found (expired)")
68+
}
69+
}

lfu/lfu_test.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package lfu_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/Code-Hex/go-generics-cache/lfu"
7+
)
8+
9+
func TestSet(t *testing.T) {
10+
// set capacity is 1
11+
cache := lfu.NewCacheWithCap[string, int](1)
12+
cache.Set("foo", 1)
13+
if got := cache.Len(); got != 1 {
14+
t.Fatalf("invalid length: %d", got)
15+
}
16+
if got, ok := cache.Get("foo"); got != 1 || !ok {
17+
t.Fatalf("invalid value got %d, cachehit %v", got, ok)
18+
}
19+
20+
// if over the cap
21+
cache.Set("bar", 2)
22+
if got := cache.Len(); got != 1 {
23+
t.Fatalf("invalid length: %d", got)
24+
}
25+
bar, ok := cache.Get("bar")
26+
if bar != 2 || !ok {
27+
t.Fatalf("invalid value bar %d, cachehit %v", bar, ok)
28+
}
29+
30+
// checks deleted oldest
31+
if _, ok := cache.Get("foo"); ok {
32+
t.Fatalf("invalid delete oldest value foo %v", ok)
33+
}
34+
35+
// valid: if over the cap but same key
36+
cache.Set("bar", 100)
37+
if got := cache.Len(); got != 1 {
38+
t.Fatalf("invalid length: %d", got)
39+
}
40+
bar, ok = cache.Get("bar")
41+
if bar != 100 || !ok {
42+
t.Fatalf("invalid replacing value bar %d, cachehit %v", bar, ok)
43+
}
44+
}
45+
46+
func TestDelete(t *testing.T) {
47+
cache := lfu.NewCacheWithCap[string, int](1)
48+
cache.Set("foo", 1)
49+
if got := cache.Len(); got != 1 {
50+
t.Fatalf("invalid length: %d", got)
51+
}
52+
53+
cache.Delete("foo2")
54+
if got := cache.Len(); got != 1 {
55+
t.Fatalf("invalid length after deleted does not exist key: %d", got)
56+
}
57+
58+
cache.Delete("foo")
59+
if got := cache.Len(); got != 0 {
60+
t.Fatalf("invalid length after deleted: %d", got)
61+
}
62+
if _, ok := cache.Get("foo"); ok {
63+
t.Fatalf("invalid get after deleted %v", ok)
64+
}
65+
}

0 commit comments

Comments
 (0)