293dd2e848
* Add vendor dir so builds dont require dep * Pin specific version go-eth version
153 lines
4.5 KiB
Go
153 lines
4.5 KiB
Go
// Copyright (c) 2015 The btcsuite developers
|
|
// Use of this source code is governed by an ISC
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package peer
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
)
|
|
|
|
// TestMruNonceMap ensures the mruNonceMap behaves as expected including
|
|
// limiting, eviction of least-recently used entries, specific entry removal,
|
|
// and existence tests.
|
|
func TestMruNonceMap(t *testing.T) {
|
|
// Create a bunch of fake nonces to use in testing the mru 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 mru nonce map limited by the specified test
|
|
// limit and add all of the test nonces. This will cause
|
|
// evicition since there are more test nonces than the limits.
|
|
mruNonceMap := newMruNonceMap(uint(test.limit))
|
|
for j := 0; j < numNonces; j++ {
|
|
mruNonceMap.Add(nonces[j])
|
|
}
|
|
|
|
// Ensure the limited number of most recent entries in the list
|
|
// exist.
|
|
for j := numNonces - test.limit; j < numNonces; j++ {
|
|
if !mruNonceMap.Exists(nonces[j]) {
|
|
t.Errorf("Exists #%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 mruNonceMap.Exists(nonces[j]) {
|
|
t.Errorf("Exists #%d (%s) entry %d exists", i,
|
|
test.name, nonces[j])
|
|
continue testLoop
|
|
}
|
|
}
|
|
|
|
// Readd 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
|
|
mruNonceMap.Add(nonces[origLruIndex])
|
|
|
|
mruNonceMap.Add(uint64(numNonces) + 1)
|
|
|
|
// Ensure the original lru entry still exists since it
|
|
// was updated and should've have become the mru entry.
|
|
if !mruNonceMap.Exists(nonces[origLruIndex]) {
|
|
t.Errorf("MRU #%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 mruNonceMap.Exists(nonces[newLruIndex]) {
|
|
t.Errorf("MRU #%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 map, and ensure they no longer exist.
|
|
for j := 0; j < numNonces; j++ {
|
|
mruNonceMap.Delete(nonces[j])
|
|
if mruNonceMap.Exists(nonces[j]) {
|
|
t.Errorf("Delete #%d (%s) entry %d exists", i,
|
|
test.name, nonces[j])
|
|
continue testLoop
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestMruNonceMapStringer tests the stringized output for the mruNonceMap type.
|
|
func TestMruNonceMapStringer(t *testing.T) {
|
|
// Create a couple of fake nonces to use in testing the mru nonce
|
|
// stringer code.
|
|
nonce1 := uint64(10)
|
|
nonce2 := uint64(20)
|
|
|
|
// Create new mru nonce map and add the nonces.
|
|
mruNonceMap := newMruNonceMap(uint(2))
|
|
mruNonceMap.Add(nonce1)
|
|
mruNonceMap.Add(nonce2)
|
|
|
|
// Ensure the stringer gives the expected result. Since map iteration
|
|
// is not ordered, either entry could be first, so account for both
|
|
// cases.
|
|
wantStr1 := fmt.Sprintf("<%d>[%d, %d]", 2, nonce1, nonce2)
|
|
wantStr2 := fmt.Sprintf("<%d>[%d, %d]", 2, nonce2, nonce1)
|
|
gotStr := mruNonceMap.String()
|
|
if gotStr != wantStr1 && gotStr != wantStr2 {
|
|
t.Fatalf("unexpected string representation - got %q, want %q "+
|
|
"or %q", gotStr, wantStr1, wantStr2)
|
|
}
|
|
}
|
|
|
|
// BenchmarkMruNonceList performs basic benchmarks on the most recently used
|
|
// nonce handling.
|
|
func BenchmarkMruNonceList(b *testing.B) {
|
|
// Create a bunch of fake nonces to use in benchmarking the mru 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 evicition code.
|
|
limit := 20000
|
|
mruNonceMap := newMruNonceMap(uint(limit))
|
|
for i := 0; i < b.N; i++ {
|
|
mruNonceMap.Add(nonces[i%numNonces])
|
|
}
|
|
}
|