summaryrefslogtreecommitdiff
path: root/lib/containers/lrucache_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'lib/containers/lrucache_test.go')
-rw-r--r--lib/containers/lrucache_test.go86
1 files changed, 58 insertions, 28 deletions
diff --git a/lib/containers/lrucache_test.go b/lib/containers/lrucache_test.go
index f04df99..4918303 100644
--- a/lib/containers/lrucache_test.go
+++ b/lib/containers/lrucache_test.go
@@ -5,67 +5,97 @@
package containers
import (
- "runtime/debug"
+ "context"
"testing"
+ "time"
+ "github.com/datawire/dlib/dlog"
"github.com/stretchr/testify/assert"
)
+func TestLRUBlocking(t *testing.T) {
+ t.Parallel()
+ const tick = time.Second / 2
+
+ ctx := dlog.NewTestContext(t, false)
+
+ cache := NewLRUCache[int, int](4,
+ SourceFunc[int, int](func(_ context.Context, k int, v *int) { *v = k * k }))
+
+ assert.Equal(t, 1, *cache.Acquire(ctx, 1))
+ assert.Equal(t, 4, *cache.Acquire(ctx, 2))
+ assert.Equal(t, 9, *cache.Acquire(ctx, 3))
+ assert.Equal(t, 16, *cache.Acquire(ctx, 4))
+
+ ch := make(chan int)
+ start := time.Now()
+ go func() {
+ ch <- *cache.Acquire(ctx, 5)
+ }()
+ go func() {
+ time.Sleep(tick)
+ cache.Release(3)
+ }()
+ result := <-ch
+ dur := time.Since(start)
+ assert.Equal(t, 25, result)
+ assert.Greater(t, dur, tick)
+}
+
//nolint:paralleltest // Can't be parallel because we test testing.AllocsPerRun.
-func TestLRU(t *testing.T) {
+func TestLRUAllocs(t *testing.T) {
const (
cacheLen = 8
bigNumber = 128
)
+
+ ctx := dlog.NewTestContext(t, false)
+
evictions := 0
- cache := &lruCache[int, int]{
- OnEvict: func(_, _ int) {
+ cache := NewLRUCache[int, int](cacheLen, SourceFunc[int, int](func(_ context.Context, k int, v *int) {
+ if *v > 0 {
evictions++
- },
- }
- i := 0
- store := func() {
- for cache.Len()+1 > cacheLen {
- cache.EvictOldest()
}
- cache.Store(i, i)
+ *v = k
+ }))
+
+ i := 1
+ store := func() {
+ cache.Acquire(ctx, i)
+ cache.Release(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))
+ // it should be alloc-free after construction
+ assert.Equal(t, float64(0), testing.AllocsPerRun(cacheLen+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))
+ assert.Equal(t, cacheLen, len(cache.(*lruCache[int, int]).byName))
+ assert.Equal(t, cacheLen, cache.(*lruCache[int, int]).evictable.Len)
cnt := 0
- for entry := cache.byAge.newest; entry != nil; entry = entry.older {
+ for entry := cache.(*lruCache[int, int]).evictable.Oldest; entry != nil; entry = entry.Newer {
cnt++
}
assert.Equal(t, cacheLen, cnt)
cnt = 0
- for entry := cache.byAge.oldest; entry != nil; entry = entry.newer {
+ for entry := cache.(*lruCache[int, int]).evictable.Newest; entry != nil; entry = entry.Older {
cnt++
}
assert.Equal(t, cacheLen, cnt)
// check contents
cnt = 0
- for j := i - 1; j >= 0; j-- {
+ for j := i - 1; j > 0; j-- {
+ entry, ok := cache.(*lruCache[int, int]).byName[j]
if cnt < cacheLen {
- assert.True(t, cache.Has(j), j)
+ if assert.True(t, ok, j) {
+ val := entry.Value.val
+ assert.Equal(t, j, val, j)
+ }
cnt++
} else {
- assert.False(t, cache.Has(j), j)
+ assert.False(t, ok, j)
}
}
}