Skip to content

Commit 6621c1b

Browse files
committed
fixed item expiration behavior in lru
1 parent f983da1 commit 6621c1b

File tree

3 files changed

+78
-20
lines changed

3 files changed

+78
-20
lines changed

lru/lru.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ func NewCacheWithCap[K comparable, V any](cap int) *Cache[K, V] {
2727
return &Cache[K, V]{
2828
cap: cap,
2929
list: list.New(),
30-
items: make(map[K]*list.Element),
30+
items: make(map[K]*list.Element, cap),
3131
}
3232
}
3333

@@ -75,7 +75,8 @@ func (c *Cache[K, V]) Keys() []K {
7575
defer c.mu.RUnlock()
7676
keys := make([]K, 0, len(c.items))
7777
for ent := c.list.Back(); ent != nil; ent = ent.Prev() {
78-
keys = append(keys, ent.Value.(*cache.Item[K, V]).Key)
78+
item := ent.Value.(*cache.Item[K, V])
79+
keys = append(keys, item.Key)
7980
}
8081
return keys
8182
}
@@ -100,8 +101,12 @@ func (c *Cache[K, V]) Delete(key K) {
100101
func (c *Cache[K, V]) Contains(key K) bool {
101102
c.mu.RLock()
102103
defer c.mu.RUnlock()
103-
_, ok := c.items[key]
104-
return ok
104+
e, ok := c.items[key]
105+
if !ok {
106+
return false
107+
}
108+
item := e.Value.(*cache.Item[K, V])
109+
return !item.HasExpired()
105110
}
106111

107112
func (c *Cache[K, V]) deleteOldest() {

lru/lru_internal_test.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package lru
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.Value.(*cache.Item[string, int])
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.Value.(*cache.Item[string, int])
64+
item.CreatedAt = time.Now().Add(-2 * exp)
65+
_, ok2 := c.Get(key)
66+
if ok2 {
67+
t.Fatal("unexpected found (expired)")
68+
}
69+
}

lru/lru_test.go

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -43,22 +43,6 @@ func TestSet(t *testing.T) {
4343
}
4444
}
4545

46-
func TestContains(t *testing.T) {
47-
cache := lru.NewCache[string, int]()
48-
cache.Set("foo", 1)
49-
cache.Set("bar", 2)
50-
cache.Set("baz", 3)
51-
for _, key := range []string{
52-
"foo",
53-
"bar",
54-
"baz",
55-
} {
56-
if !cache.Contains(key) {
57-
t.Errorf("not found: %s", key)
58-
}
59-
}
60-
}
61-
6246
func TestDelete(t *testing.T) {
6347
cache := lru.NewCacheWithCap[string, int](1)
6448
cache.Set("foo", 1)

0 commit comments

Comments
 (0)