1
16
17 package cache
18
19 import (
20 "sync"
21 "testing"
22 "time"
23 )
24
25 func testHeapObjectKeyFunc(obj interface{}) (string, error) {
26 return obj.(testHeapObject).name, nil
27 }
28
29 type testHeapObject struct {
30 name string
31 val interface{}
32 }
33
34 func mkHeapObj(name string, val interface{}) testHeapObject {
35 return testHeapObject{name: name, val: val}
36 }
37
38 func compareInts(val1 interface{}, val2 interface{}) bool {
39 first := val1.(testHeapObject).val.(int)
40 second := val2.(testHeapObject).val.(int)
41 return first < second
42 }
43
44
45 func TestHeapBasic(t *testing.T) {
46 h := NewHeap(testHeapObjectKeyFunc, compareInts)
47 var wg sync.WaitGroup
48 wg.Add(2)
49 const amount = 500
50 var i, u int
51
52 go func() {
53 for i = amount; i > 0; i-- {
54 h.Add(mkHeapObj(string([]rune{'a', rune(i)}), i))
55 }
56 wg.Done()
57 }()
58 go func() {
59 for u = 0; u < amount; u++ {
60 h.Add(mkHeapObj(string([]rune{'b', rune(u)}), u+1))
61 }
62 wg.Done()
63 }()
64
65 wg.Wait()
66
67 prevNum := 0
68 for i := 0; i < amount*2; i++ {
69 obj, err := h.Pop()
70 num := obj.(testHeapObject).val.(int)
71
72 if err != nil || prevNum > num {
73 t.Errorf("got %v out of order, last was %v", obj, prevNum)
74 }
75 prevNum = num
76 }
77 }
78
79
80 func TestHeap_Add(t *testing.T) {
81 h := NewHeap(testHeapObjectKeyFunc, compareInts)
82 h.Add(mkHeapObj("foo", 10))
83 h.Add(mkHeapObj("bar", 1))
84 h.Add(mkHeapObj("baz", 11))
85 h.Add(mkHeapObj("zab", 30))
86 h.Add(mkHeapObj("foo", 13))
87
88 item, err := h.Pop()
89 if e, a := 1, item.(testHeapObject).val; err != nil || a != e {
90 t.Fatalf("expected %d, got %d", e, a)
91 }
92 item, err = h.Pop()
93 if e, a := 11, item.(testHeapObject).val; err != nil || a != e {
94 t.Fatalf("expected %d, got %d", e, a)
95 }
96 h.Delete(mkHeapObj("baz", 11))
97 h.Add(mkHeapObj("foo", 14))
98 item, err = h.Pop()
99 if e, a := 14, item.(testHeapObject).val; err != nil || a != e {
100 t.Fatalf("expected %d, got %d", e, a)
101 }
102 item, err = h.Pop()
103 if e, a := 30, item.(testHeapObject).val; err != nil || a != e {
104 t.Fatalf("expected %d, got %d", e, a)
105 }
106 }
107
108
109
110 func TestHeap_BulkAdd(t *testing.T) {
111 h := NewHeap(testHeapObjectKeyFunc, compareInts)
112 const amount = 500
113
114 go func() {
115 l := []interface{}{}
116 for i := amount; i > 0; i-- {
117 l = append(l, mkHeapObj(string([]rune{'a', rune(i)}), i))
118 }
119 h.BulkAdd(l)
120 }()
121 prevNum := -1
122 for i := 0; i < amount; i++ {
123 obj, err := h.Pop()
124 num := obj.(testHeapObject).val.(int)
125
126 if err != nil || prevNum >= num {
127 t.Errorf("got %v out of order, last was %v", obj, prevNum)
128 }
129 prevNum = num
130 }
131 }
132
133
134 func TestHeapEmptyPop(t *testing.T) {
135 h := NewHeap(testHeapObjectKeyFunc, compareInts)
136 go func() {
137 time.Sleep(1 * time.Second)
138 h.Close()
139 }()
140 _, err := h.Pop()
141 if err == nil || err.Error() != closedMsg {
142 t.Errorf("pop should have returned heap closed error: %v", err)
143 }
144 }
145
146
147
148 func TestHeap_AddIfNotPresent(t *testing.T) {
149 h := NewHeap(testHeapObjectKeyFunc, compareInts)
150 h.AddIfNotPresent(mkHeapObj("foo", 10))
151 h.AddIfNotPresent(mkHeapObj("bar", 1))
152 h.AddIfNotPresent(mkHeapObj("baz", 11))
153 h.AddIfNotPresent(mkHeapObj("zab", 30))
154 h.AddIfNotPresent(mkHeapObj("foo", 13))
155
156 if len := len(h.data.items); len != 4 {
157 t.Errorf("unexpected number of items: %d", len)
158 }
159 if val := h.data.items["foo"].obj.(testHeapObject).val; val != 10 {
160 t.Errorf("unexpected value: %d", val)
161 }
162 item, err := h.Pop()
163 if e, a := 1, item.(testHeapObject).val; err != nil || a != e {
164 t.Fatalf("expected %d, got %d", e, a)
165 }
166 item, err = h.Pop()
167 if e, a := 10, item.(testHeapObject).val; err != nil || a != e {
168 t.Fatalf("expected %d, got %d", e, a)
169 }
170
171 h.AddIfNotPresent(mkHeapObj("bar", 14))
172 item, err = h.Pop()
173 if e, a := 11, item.(testHeapObject).val; err != nil || a != e {
174 t.Fatalf("expected %d, got %d", e, a)
175 }
176 item, err = h.Pop()
177 if e, a := 14, item.(testHeapObject).val; err != nil || a != e {
178 t.Fatalf("expected %d, got %d", e, a)
179 }
180 }
181
182
183
184 func TestHeap_Delete(t *testing.T) {
185 h := NewHeap(testHeapObjectKeyFunc, compareInts)
186 h.Add(mkHeapObj("foo", 10))
187 h.Add(mkHeapObj("bar", 1))
188 h.Add(mkHeapObj("bal", 31))
189 h.Add(mkHeapObj("baz", 11))
190
191
192 if err := h.Delete(mkHeapObj("bar", 200)); err != nil {
193 t.Fatalf("Failed to delete head.")
194 }
195 item, err := h.Pop()
196 if e, a := 10, item.(testHeapObject).val; err != nil || a != e {
197 t.Fatalf("expected %d, got %d", e, a)
198 }
199 h.Add(mkHeapObj("zab", 30))
200 h.Add(mkHeapObj("faz", 30))
201 len := h.data.Len()
202
203 if err = h.Delete(mkHeapObj("non-existent", 10)); err == nil || len != h.data.Len() {
204 t.Fatalf("Didn't expect any item removal")
205 }
206
207 if err = h.Delete(mkHeapObj("bal", 31)); err != nil {
208 t.Fatalf("Failed to delete tail.")
209 }
210
211 if err = h.Delete(mkHeapObj("zab", 30)); err != nil {
212 t.Fatalf("Failed to delete item.")
213 }
214 item, err = h.Pop()
215 if e, a := 11, item.(testHeapObject).val; err != nil || a != e {
216 t.Fatalf("expected %d, got %d", e, a)
217 }
218 item, err = h.Pop()
219 if e, a := 30, item.(testHeapObject).val; err != nil || a != e {
220 t.Fatalf("expected %d, got %d", e, a)
221 }
222 if h.data.Len() != 0 {
223 t.Fatalf("expected an empty heap.")
224 }
225 }
226
227
228
229 func TestHeap_Update(t *testing.T) {
230 h := NewHeap(testHeapObjectKeyFunc, compareInts)
231 h.Add(mkHeapObj("foo", 10))
232 h.Add(mkHeapObj("bar", 1))
233 h.Add(mkHeapObj("bal", 31))
234 h.Add(mkHeapObj("baz", 11))
235
236
237 h.Update(mkHeapObj("baz", 0))
238 if h.data.queue[0] != "baz" || h.data.items["baz"].index != 0 {
239 t.Fatalf("expected baz to be at the head")
240 }
241 item, err := h.Pop()
242 if e, a := 0, item.(testHeapObject).val; err != nil || a != e {
243 t.Fatalf("expected %d, got %d", e, a)
244 }
245
246 h.Update(mkHeapObj("bar", 100))
247 if h.data.queue[0] != "foo" || h.data.items["foo"].index != 0 {
248 t.Fatalf("expected foo to be at the head")
249 }
250 }
251
252
253 func TestHeap_Get(t *testing.T) {
254 h := NewHeap(testHeapObjectKeyFunc, compareInts)
255 h.Add(mkHeapObj("foo", 10))
256 h.Add(mkHeapObj("bar", 1))
257 h.Add(mkHeapObj("bal", 31))
258 h.Add(mkHeapObj("baz", 11))
259
260
261 obj, exists, err := h.Get(mkHeapObj("baz", 0))
262 if err != nil || exists == false || obj.(testHeapObject).val != 11 {
263 t.Fatalf("unexpected error in getting element")
264 }
265
266 _, exists, err = h.Get(mkHeapObj("non-existing", 0))
267 if err != nil || exists {
268 t.Fatalf("didn't expect to get any object")
269 }
270 }
271
272
273 func TestHeap_GetByKey(t *testing.T) {
274 h := NewHeap(testHeapObjectKeyFunc, compareInts)
275 h.Add(mkHeapObj("foo", 10))
276 h.Add(mkHeapObj("bar", 1))
277 h.Add(mkHeapObj("bal", 31))
278 h.Add(mkHeapObj("baz", 11))
279
280 obj, exists, err := h.GetByKey("baz")
281 if err != nil || exists == false || obj.(testHeapObject).val != 11 {
282 t.Fatalf("unexpected error in getting element")
283 }
284
285 _, exists, err = h.GetByKey("non-existing")
286 if err != nil || exists {
287 t.Fatalf("didn't expect to get any object")
288 }
289 }
290
291
292 func TestHeap_Close(t *testing.T) {
293 h := NewHeap(testHeapObjectKeyFunc, compareInts)
294 h.Add(mkHeapObj("foo", 10))
295 h.Add(mkHeapObj("bar", 1))
296
297 if h.IsClosed() {
298 t.Fatalf("didn't expect heap to be closed")
299 }
300 h.Close()
301 if !h.IsClosed() {
302 t.Fatalf("expect heap to be closed")
303 }
304 }
305
306
307 func TestHeap_List(t *testing.T) {
308 h := NewHeap(testHeapObjectKeyFunc, compareInts)
309 list := h.List()
310 if len(list) != 0 {
311 t.Errorf("expected an empty list")
312 }
313
314 items := map[string]int{
315 "foo": 10,
316 "bar": 1,
317 "bal": 30,
318 "baz": 11,
319 "faz": 30,
320 }
321 for k, v := range items {
322 h.Add(mkHeapObj(k, v))
323 }
324 list = h.List()
325 if len(list) != len(items) {
326 t.Errorf("expected %d items, got %d", len(items), len(list))
327 }
328 for _, obj := range list {
329 heapObj := obj.(testHeapObject)
330 v, ok := items[heapObj.name]
331 if !ok || v != heapObj.val {
332 t.Errorf("unexpected item in the list: %v", heapObj)
333 }
334 }
335 }
336
337
338
339 func TestHeap_ListKeys(t *testing.T) {
340 h := NewHeap(testHeapObjectKeyFunc, compareInts)
341 list := h.ListKeys()
342 if len(list) != 0 {
343 t.Errorf("expected an empty list")
344 }
345
346 items := map[string]int{
347 "foo": 10,
348 "bar": 1,
349 "bal": 30,
350 "baz": 11,
351 "faz": 30,
352 }
353 for k, v := range items {
354 h.Add(mkHeapObj(k, v))
355 }
356 list = h.ListKeys()
357 if len(list) != len(items) {
358 t.Errorf("expected %d items, got %d", len(items), len(list))
359 }
360 for _, key := range list {
361 _, ok := items[key]
362 if !ok {
363 t.Errorf("unexpected item in the list: %v", key)
364 }
365 }
366 }
367
368
369
370 func TestHeapAddAfterClose(t *testing.T) {
371 h := NewHeap(testHeapObjectKeyFunc, compareInts)
372 h.Close()
373 if err := h.Add(mkHeapObj("test", 1)); err == nil || err.Error() != closedMsg {
374 t.Errorf("expected heap closed error")
375 }
376 if err := h.AddIfNotPresent(mkHeapObj("test", 1)); err == nil || err.Error() != closedMsg {
377 t.Errorf("expected heap closed error")
378 }
379 if err := h.BulkAdd([]interface{}{mkHeapObj("test", 1)}); err == nil || err.Error() != closedMsg {
380 t.Errorf("expected heap closed error")
381 }
382 }
383
View as plain text