1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
// Copyright (C) 2023 Luke Shumaker <lukeshu@lukeshu.com>
//
// SPDX-License-Identifier: GPL-2.0-or-later
package containers
import (
"runtime/debug"
"testing"
"github.com/stretchr/testify/assert"
)
//nolint:paralleltest // Can't be parallel because we test testing.AllocsPerRun.
func TestLRU(t *testing.T) {
const (
cacheLen = 8
bigNumber = 128
)
evictions := 0
cache := &lruCache[int, int]{
OnEvict: func(_, _ int) {
evictions++
},
}
i := 0
store := func() {
for cache.Len()+1 > cacheLen {
cache.EvictOldest()
}
cache.Store(i, i)
i++
}
// Disable the GC temporarily to prevent cache.byAge.pool from
// being cleaned in the middle of an AllocsPerRun and causing
// spurious allocations.
percent := debug.SetGCPercent(-1)
defer debug.SetGCPercent(percent)
// 1 alloc each as we fill the cache
assert.Equal(t, float64(1), testing.AllocsPerRun(cacheLen-1, store))
assert.Equal(t, 0, evictions)
// after that, it should be alloc-free
assert.Equal(t, float64(0), testing.AllocsPerRun(1, store))
assert.Equal(t, 2, evictions)
assert.Equal(t, float64(0), testing.AllocsPerRun(bigNumber, store))
assert.Equal(t, 3+bigNumber, evictions)
// check the len
assert.Equal(t, cacheLen, len(cache.byName))
cnt := 0
for entry := cache.byAge.newest; entry != nil; entry = entry.older {
cnt++
}
assert.Equal(t, cacheLen, cnt)
cnt = 0
for entry := cache.byAge.oldest; entry != nil; entry = entry.newer {
cnt++
}
assert.Equal(t, cacheLen, cnt)
// check contents
cnt = 0
for j := i - 1; j >= 0; j-- {
if cnt < cacheLen {
assert.True(t, cache.Has(j), j)
cnt++
} else {
assert.False(t, cache.Has(j), j)
}
}
}
|