diff options
author | Luke Shumaker <lukeshu@lukeshu.com> | 2023-03-28 14:47:09 -0600 |
---|---|---|
committer | Luke Shumaker <lukeshu@lukeshu.com> | 2023-03-28 14:47:09 -0600 |
commit | 0b092a27122fcf19479d6cdeae5f7c9493d9741a (patch) | |
tree | d5e8802ad7b62f5222d3d88a0c592ff6cbb6b4ba /lib/containers/lrucache_test.go | |
parent | bf5eed5af5c34b8cf9dc2985a7c4475602929bb1 (diff) | |
parent | f6f0a251ed962374f69e9fd7722dcd5c44aa58ad (diff) |
Merge branch 'lukeshu/node-cache'
Diffstat (limited to 'lib/containers/lrucache_test.go')
-rw-r--r-- | lib/containers/lrucache_test.go | 86 |
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) } } } |