mirror of
https://github.com/btcsuite/btcd.git
synced 2024-11-19 01:40:07 +01:00
bd4e64d1d4
This is mostly a backport of some of the same modifications made in Decred along with a few additional things cleaned up. In particular, this updates the code to make use of the new chainhash package. Also, since this required API changes anyways and the hash algorithm is no longer tied specifically to SHA, all other functions throughout the code base which had "Sha" in their name have been changed to Hash so they are not incorrectly implying the hash algorithm. The following is an overview of the changes: - Remove the wire.ShaHash type - Update all references to wire.ShaHash to the new chainhash.Hash type - Rename the following functions and update all references: - wire.BlockHeader.BlockSha -> BlockHash - wire.MsgBlock.BlockSha -> BlockHash - wire.MsgBlock.TxShas -> TxHashes - wire.MsgTx.TxSha -> TxHash - blockchain.ShaHashToBig -> HashToBig - peer.ShaFunc -> peer.HashFunc - Rename all variables that included sha in their name to include hash instead - Update for function name changes in other dependent packages such as btcutil - Update copyright dates on all modified files - Update glide.lock file to use the required version of btcutil
171 lines
5.3 KiB
Go
171 lines
5.3 KiB
Go
// Copyright (c) 2013-2016 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 (
|
|
"crypto/rand"
|
|
"fmt"
|
|
"testing"
|
|
|
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
|
"github.com/btcsuite/btcd/wire"
|
|
)
|
|
|
|
// TestMruInventoryMap ensures the MruInventoryMap behaves as expected including
|
|
// limiting, eviction of least-recently used entries, specific entry removal,
|
|
// and existence tests.
|
|
func TestMruInventoryMap(t *testing.T) {
|
|
// Create a bunch of fake inventory vectors to use in testing the mru
|
|
// inventory code.
|
|
numInvVects := 10
|
|
invVects := make([]*wire.InvVect, 0, numInvVects)
|
|
for i := 0; i < numInvVects; i++ {
|
|
hash := &chainhash.Hash{byte(i)}
|
|
iv := wire.NewInvVect(wire.InvTypeBlock, hash)
|
|
invVects = append(invVects, iv)
|
|
}
|
|
|
|
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: numInvVects - 1},
|
|
{name: "limit all available", limit: numInvVects},
|
|
}
|
|
|
|
testLoop:
|
|
for i, test := range tests {
|
|
// Create a new mru inventory map limited by the specified test
|
|
// limit and add all of the test inventory vectors. This will
|
|
// cause evicition since there are more test inventory vectors
|
|
// than the limits.
|
|
mruInvMap := newMruInventoryMap(uint(test.limit))
|
|
for j := 0; j < numInvVects; j++ {
|
|
mruInvMap.Add(invVects[j])
|
|
}
|
|
|
|
// Ensure the limited number of most recent entries in the
|
|
// inventory vector list exist.
|
|
for j := numInvVects - test.limit; j < numInvVects; j++ {
|
|
if !mruInvMap.Exists(invVects[j]) {
|
|
t.Errorf("Exists #%d (%s) entry %s does not "+
|
|
"exist", i, test.name, *invVects[j])
|
|
continue testLoop
|
|
}
|
|
}
|
|
|
|
// Ensure the entries before the limited number of most recent
|
|
// entries in the inventory vector list do not exist.
|
|
for j := 0; j < numInvVects-test.limit; j++ {
|
|
if mruInvMap.Exists(invVects[j]) {
|
|
t.Errorf("Exists #%d (%s) entry %s exists", i,
|
|
test.name, *invVects[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 := numInvVects - test.limit
|
|
mruInvMap.Add(invVects[origLruIndex])
|
|
|
|
iv := wire.NewInvVect(wire.InvTypeBlock,
|
|
&chainhash.Hash{0x00, 0x01})
|
|
mruInvMap.Add(iv)
|
|
|
|
// Ensure the original lru entry still exists since it
|
|
// was updated and should've have become the mru entry.
|
|
if !mruInvMap.Exists(invVects[origLruIndex]) {
|
|
t.Errorf("MRU #%d (%s) entry %s does not exist",
|
|
i, test.name, *invVects[origLruIndex])
|
|
continue testLoop
|
|
}
|
|
|
|
// Ensure the entry that should've become the new lru
|
|
// entry was evicted.
|
|
newLruIndex := origLruIndex + 1
|
|
if mruInvMap.Exists(invVects[newLruIndex]) {
|
|
t.Errorf("MRU #%d (%s) entry %s exists", i,
|
|
test.name, *invVects[newLruIndex])
|
|
continue testLoop
|
|
}
|
|
}
|
|
|
|
// Delete all of the entries in the inventory vector list,
|
|
// including those that don't exist in the map, and ensure they
|
|
// no longer exist.
|
|
for j := 0; j < numInvVects; j++ {
|
|
mruInvMap.Delete(invVects[j])
|
|
if mruInvMap.Exists(invVects[j]) {
|
|
t.Errorf("Delete #%d (%s) entry %s exists", i,
|
|
test.name, *invVects[j])
|
|
continue testLoop
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestMruInventoryMapStringer tests the stringized output for the
|
|
// MruInventoryMap type.
|
|
func TestMruInventoryMapStringer(t *testing.T) {
|
|
// Create a couple of fake inventory vectors to use in testing the mru
|
|
// inventory stringer code.
|
|
hash1 := &chainhash.Hash{0x01}
|
|
hash2 := &chainhash.Hash{0x02}
|
|
iv1 := wire.NewInvVect(wire.InvTypeBlock, hash1)
|
|
iv2 := wire.NewInvVect(wire.InvTypeBlock, hash2)
|
|
|
|
// Create new mru inventory map and add the inventory vectors.
|
|
mruInvMap := newMruInventoryMap(uint(2))
|
|
mruInvMap.Add(iv1)
|
|
mruInvMap.Add(iv2)
|
|
|
|
// 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>[%s, %s]", 2, *iv1, *iv2)
|
|
wantStr2 := fmt.Sprintf("<%d>[%s, %s]", 2, *iv2, *iv1)
|
|
gotStr := mruInvMap.String()
|
|
if gotStr != wantStr1 && gotStr != wantStr2 {
|
|
t.Fatalf("unexpected string representation - got %q, want %q "+
|
|
"or %q", gotStr, wantStr1, wantStr2)
|
|
}
|
|
}
|
|
|
|
// BenchmarkMruInventoryList performs basic benchmarks on the most recently
|
|
// used inventory handling.
|
|
func BenchmarkMruInventoryList(b *testing.B) {
|
|
// Create a bunch of fake inventory vectors to use in benchmarking
|
|
// the mru inventory code.
|
|
b.StopTimer()
|
|
numInvVects := 100000
|
|
invVects := make([]*wire.InvVect, 0, numInvVects)
|
|
for i := 0; i < numInvVects; i++ {
|
|
hashBytes := make([]byte, chainhash.HashSize)
|
|
rand.Read(hashBytes)
|
|
hash, _ := chainhash.NewHash(hashBytes)
|
|
iv := wire.NewInvVect(wire.InvTypeBlock, hash)
|
|
invVects = append(invVects, iv)
|
|
}
|
|
b.StartTimer()
|
|
|
|
// Benchmark the add plus evicition code.
|
|
limit := 20000
|
|
mruInvMap := newMruInventoryMap(uint(limit))
|
|
for i := 0; i < b.N; i++ {
|
|
mruInvMap.Add(invVects[i%numInvVects])
|
|
}
|
|
}
|