mirror of
https://github.com/btcsuite/btcd.git
synced 2024-11-19 01:40:07 +01:00
217 lines
5.8 KiB
Go
217 lines
5.8 KiB
Go
package addrmgr
|
|
|
|
import (
|
|
"math/rand"
|
|
"net"
|
|
"os"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/btcsuite/btcd/wire"
|
|
)
|
|
|
|
// randAddr generates a *wire.NetAddressV2 backed by a random IPv4/IPv6
|
|
// address. Some of the returned addresses may not be routable.
|
|
func randAddr(t *testing.T) *wire.NetAddressV2 {
|
|
t.Helper()
|
|
|
|
ipv4 := rand.Intn(2) == 0
|
|
var ip net.IP
|
|
if ipv4 {
|
|
var b [4]byte
|
|
if _, err := rand.Read(b[:]); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
ip = b[:]
|
|
} else {
|
|
var b [16]byte
|
|
if _, err := rand.Read(b[:]); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
ip = b[:]
|
|
}
|
|
|
|
services := wire.ServiceFlag(rand.Uint64())
|
|
port := uint16(rand.Uint32())
|
|
|
|
return wire.NetAddressV2FromBytes(
|
|
time.Now(), services, ip, port,
|
|
)
|
|
}
|
|
|
|
// routableRandAddr generates a *wire.NetAddressV2 backed by a random IPv4/IPv6
|
|
// address that is always routable.
|
|
func routableRandAddr(t *testing.T) *wire.NetAddressV2 {
|
|
t.Helper()
|
|
|
|
var addr *wire.NetAddressV2
|
|
|
|
// If the address is not routable, try again.
|
|
routable := false
|
|
for !routable {
|
|
addr = randAddr(t)
|
|
routable = IsRoutable(addr)
|
|
}
|
|
|
|
return addr
|
|
}
|
|
|
|
// assertAddr ensures that the two addresses match. The timestamp is not
|
|
// checked as it does not affect uniquely identifying a specific address.
|
|
func assertAddr(t *testing.T, got, expected *wire.NetAddressV2) {
|
|
if got.Services != expected.Services {
|
|
t.Fatalf("expected address services %v, got %v",
|
|
expected.Services, got.Services)
|
|
}
|
|
gotAddr := got.Addr.String()
|
|
expectedAddr := expected.Addr.String()
|
|
if gotAddr != expectedAddr {
|
|
t.Fatalf("expected address IP %v, got %v", expectedAddr,
|
|
gotAddr)
|
|
}
|
|
if got.Port != expected.Port {
|
|
t.Fatalf("expected address port %d, got %d", expected.Port,
|
|
got.Port)
|
|
}
|
|
}
|
|
|
|
// assertAddrs ensures that the manager's address cache matches the given
|
|
// expected addresses.
|
|
func assertAddrs(t *testing.T, addrMgr *AddrManager,
|
|
expectedAddrs map[string]*wire.NetAddressV2) {
|
|
|
|
t.Helper()
|
|
|
|
addrs := addrMgr.getAddresses()
|
|
|
|
if len(addrs) != len(expectedAddrs) {
|
|
t.Fatalf("expected to find %d addresses, found %d",
|
|
len(expectedAddrs), len(addrs))
|
|
}
|
|
|
|
for _, addr := range addrs {
|
|
addrStr := NetAddressKey(addr)
|
|
expectedAddr, ok := expectedAddrs[addrStr]
|
|
if !ok {
|
|
t.Fatalf("expected to find address %v", addrStr)
|
|
}
|
|
|
|
assertAddr(t, addr, expectedAddr)
|
|
}
|
|
}
|
|
|
|
// TestAddrManagerSerialization ensures that we can properly serialize and
|
|
// deserialize the manager's current address cache.
|
|
func TestAddrManagerSerialization(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
// We'll start by creating our address manager backed by a temporary
|
|
// directory.
|
|
tempDir, err := os.MkdirTemp("", "addrmgr")
|
|
if err != nil {
|
|
t.Fatalf("unable to create temp dir: %v", err)
|
|
}
|
|
defer os.RemoveAll(tempDir)
|
|
|
|
addrMgr := New(tempDir, nil)
|
|
|
|
// We'll be adding 5 random addresses to the manager.
|
|
const numAddrs = 5
|
|
|
|
expectedAddrs := make(map[string]*wire.NetAddressV2, numAddrs)
|
|
for i := 0; i < numAddrs; i++ {
|
|
addr := routableRandAddr(t)
|
|
expectedAddrs[NetAddressKey(addr)] = addr
|
|
addrMgr.AddAddress(addr, routableRandAddr(t))
|
|
}
|
|
|
|
// Now that the addresses have been added, we should be able to retrieve
|
|
// them.
|
|
assertAddrs(t, addrMgr, expectedAddrs)
|
|
|
|
// Then, we'll persist these addresses to disk and restart the address
|
|
// manager.
|
|
addrMgr.savePeers()
|
|
addrMgr = New(tempDir, nil)
|
|
|
|
// Finally, we'll read all of the addresses from disk and ensure they
|
|
// match as expected.
|
|
addrMgr.loadPeers()
|
|
assertAddrs(t, addrMgr, expectedAddrs)
|
|
}
|
|
|
|
// TestAddrManagerV1ToV2 ensures that we can properly upgrade the serialized
|
|
// version of the address manager from v1 to v2.
|
|
func TestAddrManagerV1ToV2(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
// We'll start by creating our address manager backed by a temporary
|
|
// directory.
|
|
tempDir, err := os.MkdirTemp("", "addrmgr")
|
|
if err != nil {
|
|
t.Fatalf("unable to create temp dir: %v", err)
|
|
}
|
|
defer os.RemoveAll(tempDir)
|
|
|
|
addrMgr := New(tempDir, nil)
|
|
|
|
// As we're interested in testing the upgrade path from v1 to v2, we'll
|
|
// override the manager's current version.
|
|
addrMgr.version = 1
|
|
|
|
// We'll be adding 5 random addresses to the manager. Since this is v1,
|
|
// each addresses' services will not be stored.
|
|
const numAddrs = 5
|
|
|
|
expectedAddrs := make(map[string]*wire.NetAddressV2, numAddrs)
|
|
for i := 0; i < numAddrs; i++ {
|
|
addr := routableRandAddr(t)
|
|
expectedAddrs[NetAddressKey(addr)] = addr
|
|
addrMgr.AddAddress(addr, routableRandAddr(t))
|
|
}
|
|
|
|
// Then, we'll persist these addresses to disk and restart the address
|
|
// manager - overriding its version back to v1.
|
|
addrMgr.savePeers()
|
|
addrMgr = New(tempDir, nil)
|
|
addrMgr.version = 1
|
|
|
|
// When we read all of the addresses back from disk, we should expect to
|
|
// find all of them, but their services will be set to a default of
|
|
// SFNodeNetwork since they were not previously stored. After ensuring
|
|
// that this default is set, we'll override each addresses' services
|
|
// with the original value from when they were created.
|
|
addrMgr.loadPeers()
|
|
addrs := addrMgr.getAddresses()
|
|
if len(addrs) != len(expectedAddrs) {
|
|
t.Fatalf("expected to find %d addresses, found %d",
|
|
len(expectedAddrs), len(addrs))
|
|
}
|
|
for _, addr := range addrs {
|
|
addrStr := NetAddressKey(addr)
|
|
expectedAddr, ok := expectedAddrs[addrStr]
|
|
if !ok {
|
|
t.Fatalf("expected to find address %v", addrStr)
|
|
}
|
|
|
|
if addr.Services != wire.SFNodeNetwork {
|
|
t.Fatalf("expected address services to be %v, got %v",
|
|
wire.SFNodeNetwork, addr.Services)
|
|
}
|
|
|
|
addrMgr.SetServices(addr, expectedAddr.Services)
|
|
}
|
|
|
|
// We'll also bump up the manager's version to v2, which should signal
|
|
// that it should include the address services when persisting its
|
|
// state.
|
|
addrMgr.version = 2
|
|
addrMgr.savePeers()
|
|
|
|
// Finally, we'll recreate the manager and ensure that the services were
|
|
// persisted correctly.
|
|
addrMgr = New(tempDir, nil)
|
|
addrMgr.loadPeers()
|
|
assertAddrs(t, addrMgr, expectedAddrs)
|
|
}
|