1
16
17 package cache
18
19 import (
20 "testing"
21 "time"
22
23 "github.com/google/go-cmp/cmp"
24 testingclock "k8s.io/utils/clock/testing"
25 )
26
27 func expectEntry(t *testing.T, c *LRUExpireCache, key interface{}, value interface{}) {
28 t.Helper()
29 result, ok := c.Get(key)
30 if !ok || result != value {
31 t.Errorf("Expected cache[%v]: %v, got %v", key, value, result)
32 }
33 }
34
35 func expectNotEntry(t *testing.T, c *LRUExpireCache, key interface{}) {
36 t.Helper()
37 if result, ok := c.Get(key); ok {
38 t.Errorf("Expected cache[%v] to be empty, got %v", key, result)
39 }
40 }
41
42
43
44 func assertKeys(t *testing.T, gotKeys, wantKeys []interface{}) {
45 t.Helper()
46 if diff := cmp.Diff(gotKeys, wantKeys); diff != "" {
47 t.Errorf("Wrong result for keys: diff (-got +want):\n%s", diff)
48 }
49 }
50
51 func TestSimpleGet(t *testing.T) {
52 c := NewLRUExpireCache(10)
53 c.Add("long-lived", "12345", 10*time.Hour)
54
55 assertKeys(t, c.Keys(), []interface{}{"long-lived"})
56
57 expectEntry(t, c, "long-lived", "12345")
58 }
59
60 func TestSimpleRemove(t *testing.T) {
61 c := NewLRUExpireCache(10)
62 c.Add("long-lived", "12345", 10*time.Hour)
63 c.Remove("long-lived")
64
65 assertKeys(t, c.Keys(), []interface{}{})
66
67 expectNotEntry(t, c, "long-lived")
68 }
69
70 func TestSimpleRemoveAll(t *testing.T) {
71 c := NewLRUExpireCache(10)
72 c.Add("long-lived", "12345", 10*time.Hour)
73 c.Add("other-long-lived", "12345", 10*time.Hour)
74 c.RemoveAll(func(k any) bool {
75 return k.(string) == "long-lived"
76 })
77
78 assertKeys(t, c.Keys(), []any{"other-long-lived"})
79
80 expectNotEntry(t, c, "long-lived")
81 expectEntry(t, c, "other-long-lived", "12345")
82 }
83
84 func TestExpiredGet(t *testing.T) {
85 fakeClock := testingclock.NewFakeClock(time.Now())
86 c := NewLRUExpireCacheWithClock(10, fakeClock)
87 c.Add("short-lived", "12345", 1*time.Millisecond)
88
89 fakeClock.Step(2 * time.Millisecond)
90
91
92 assertKeys(t, c.Keys(), []interface{}{})
93
94 expectNotEntry(t, c, "short-lived")
95 }
96
97 func TestLRUOverflow(t *testing.T) {
98 c := NewLRUExpireCache(4)
99 c.Add("elem1", "1", 10*time.Hour)
100 c.Add("elem2", "2", 10*time.Hour)
101 c.Add("elem3", "3", 10*time.Hour)
102 c.Add("elem4", "4", 10*time.Hour)
103 c.Add("elem5", "5", 10*time.Hour)
104
105 assertKeys(t, c.Keys(), []interface{}{"elem2", "elem3", "elem4", "elem5"})
106
107 expectNotEntry(t, c, "elem1")
108 expectEntry(t, c, "elem2", "2")
109 expectEntry(t, c, "elem3", "3")
110 expectEntry(t, c, "elem4", "4")
111 expectEntry(t, c, "elem5", "5")
112 }
113
114 func TestAddBringsToFront(t *testing.T) {
115 c := NewLRUExpireCache(4)
116 c.Add("elem1", "1", 10*time.Hour)
117 c.Add("elem2", "2", 10*time.Hour)
118 c.Add("elem3", "3", 10*time.Hour)
119 c.Add("elem4", "4", 10*time.Hour)
120
121 c.Add("elem1", "1-new", 10*time.Hour)
122
123 c.Add("elem5", "5", 10*time.Hour)
124
125 assertKeys(t, c.Keys(), []interface{}{"elem3", "elem4", "elem1", "elem5"})
126
127 expectNotEntry(t, c, "elem2")
128 expectEntry(t, c, "elem1", "1-new")
129 expectEntry(t, c, "elem3", "3")
130 expectEntry(t, c, "elem4", "4")
131 expectEntry(t, c, "elem5", "5")
132 }
133
134 func TestGetBringsToFront(t *testing.T) {
135 c := NewLRUExpireCache(4)
136 c.Add("elem1", "1", 10*time.Hour)
137 c.Add("elem2", "2", 10*time.Hour)
138 c.Add("elem3", "3", 10*time.Hour)
139 c.Add("elem4", "4", 10*time.Hour)
140
141 c.Get("elem1")
142
143 c.Add("elem5", "5", 10*time.Hour)
144
145 assertKeys(t, c.Keys(), []interface{}{"elem3", "elem4", "elem1", "elem5"})
146
147 expectNotEntry(t, c, "elem2")
148 expectEntry(t, c, "elem1", "1")
149 expectEntry(t, c, "elem3", "3")
150 expectEntry(t, c, "elem4", "4")
151 expectEntry(t, c, "elem5", "5")
152 }
153
154 func TestLRUKeys(t *testing.T) {
155 c := NewLRUExpireCache(4)
156 c.Add("elem1", "1", 10*time.Hour)
157 c.Add("elem2", "2", 10*time.Hour)
158 c.Add("elem3", "3", 10*time.Hour)
159 c.Add("elem4", "4", 10*time.Hour)
160
161 assertKeys(t, c.Keys(), []interface{}{"elem1", "elem2", "elem3", "elem4"})
162 }
163
View as plain text