dcrd/lru/cache_test.go
Aaron Campbell 8be96a8729 multi: Correct typos.
Correct typos found by reading code, ispell, and creative grepping.
2019-08-22 10:20:03 -05:00

155 lines
4.6 KiB
Go

// Copyright (c) 2019 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package lru
import (
"testing"
)
// TestCache ensures the LRU Cache behaves as expected including limiting,
// eviction of least-recently used entries, specific entry removal, and
// existence tests.
func TestCache(t *testing.T) {
// Create a bunch of fake nonces to use in testing the lru nonce code.
numNonces := 10
nonces := make([]uint64, 0, numNonces)
for i := 0; i < numNonces; i++ {
nonces = append(nonces, uint64(i))
}
tests := []struct {
name string
limit int
}{
{name: "limit 0", limit: 0},
{name: "limit 1", limit: 1},
{name: "limit 5", limit: 5},
{name: "limit 7", limit: 7},
{name: "limit one less than available", limit: numNonces - 1},
{name: "limit all available", limit: numNonces},
}
testLoop:
for i, test := range tests {
// Create a new lru cache limited by the specified test limit and add
// all of the test vectors. This will cause eviction since there are
// more test items than the limits.
cache := NewCache(uint(test.limit))
for j := 0; j < numNonces; j++ {
cache.Add(nonces[j])
}
// Ensure the limited number of most recent entries in the list exist.
for j := numNonces - test.limit; j < numNonces; j++ {
if !cache.Contains(nonces[j]) {
t.Errorf("Contains #%d (%s) entry %d does not exist", i,
test.name, nonces[j])
continue testLoop
}
}
// Ensure the entries before the limited number of most recent entries
// in the list do not exist.
for j := 0; j < numNonces-test.limit; j++ {
if cache.Contains(nonces[j]) {
t.Errorf("Contains #%d (%s) entry %d exists", i, test.name,
nonces[j])
continue testLoop
}
}
// Access the entry that should currently be the least-recently used
// entry so it becomes the most-recently used entry, then force an
// eviction by adding an entry that doesn't exist and ensure the evicted
// entry is the new least-recently used entry.
//
// This check needs at least 2 entries.
if test.limit > 1 {
origLruIndex := numNonces - test.limit
_ = cache.Contains(nonces[origLruIndex])
cache.Add(uint64(numNonces) + 1)
// Ensure the original lru entry still exists since it was updated
// and should have become the lru entry.
if !cache.Contains(nonces[origLruIndex]) {
t.Errorf("Contains #%d (%s) entry %d does not exist", i, test.name,
nonces[origLruIndex])
continue testLoop
}
// Ensure the entry that should've become the new lru entry was
// evicted.
newLruIndex := origLruIndex + 1
if cache.Contains(nonces[newLruIndex]) {
t.Errorf("Contains #%d (%s) entry %d exists", i, test.name,
nonces[newLruIndex])
continue testLoop
}
}
// Add the entry that should currently be the least-recently used entry
// again so it becomes the most-recently used entry, then force an
// eviction by adding an entry that doesn't exist and ensure the evicted
// entry is the new least-recently used entry.
//
// This check needs at least 2 entries.
if test.limit > 1 {
origLruIndex := numNonces - test.limit
cache.Add(nonces[origLruIndex])
cache.Add(uint64(numNonces) + 2)
// Ensure the original lru entry still exists since it was updated
// and should've have become the lru entry.
if !cache.Contains(nonces[origLruIndex]) {
t.Errorf("Contains #%d (%s) entry %d does not exist", i, test.name,
nonces[origLruIndex])
continue testLoop
}
// Ensure the entry that should've become the new lru entry was
// evicted.
newLruIndex := origLruIndex + 1
if cache.Contains(nonces[newLruIndex]) {
t.Errorf("Contains #%d (%s) entry %d exists", i, test.name,
nonces[newLruIndex])
continue testLoop
}
}
// Delete all of the entries in the list, including those that don't
// exist in the cache, and ensure they no longer exist.
for j := 0; j < numNonces; j++ {
cache.Delete(nonces[j])
if cache.Contains(nonces[j]) {
t.Errorf("Delete #%d (%s) entry %d exists", i, test.name,
nonces[j])
continue testLoop
}
}
}
}
// BenchmarkCache performs basic benchmarks on the least recently used cache
// handling.
func BenchmarkCache(b *testing.B) {
// Create a bunch of fake nonces to use in benchmarking the lru nonce code.
b.StopTimer()
numNonces := 100000
nonces := make([]uint64, 0, numNonces)
for i := 0; i < numNonces; i++ {
nonces = append(nonces, uint64(i))
}
b.StartTimer()
// Benchmark the add plus eviction code.
limit := uint(20000)
cache := NewCache(limit)
for i := 0; i < b.N; i++ {
cache.Add(nonces[i%numNonces])
}
}