c5751b75a9
Replace assignments to individual fields of wire.NetAddress with creating the entire object at once, as one would do if the type was immutable. In some places this replaces the creation of a NetAddress with a high-precision timestamp with a call to a 'constructor' that converts the timestamp to single second precision. For consistency, the tests have also been changed to use single-precision timestamps. Lastly, the number of allocations in readNetAddress have been reduced by reading the services directly into the NetAddress instead of first into a temporary variable.
472 lines
12 KiB
Go
472 lines
12 KiB
Go
// Copyright (c) 2013-2014 The btcsuite developers
|
|
// Use of this source code is governed by an ISC
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package addrmgr_test
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"net"
|
|
"reflect"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/btcsuite/btcd/addrmgr"
|
|
"github.com/btcsuite/btcd/wire"
|
|
)
|
|
|
|
// naTest is used to describe a test to be performed against the NetAddressKey
|
|
// method.
|
|
type naTest struct {
|
|
in wire.NetAddress
|
|
want string
|
|
}
|
|
|
|
// naTests houses all of the tests to be performed against the NetAddressKey
|
|
// method.
|
|
var naTests = make([]naTest, 0)
|
|
|
|
// Put some IP in here for convenience. Points to google.
|
|
var someIP = "173.194.115.66"
|
|
|
|
// addNaTests
|
|
func addNaTests() {
|
|
// IPv4
|
|
// Localhost
|
|
addNaTest("127.0.0.1", 8333, "127.0.0.1:8333")
|
|
addNaTest("127.0.0.1", 8334, "127.0.0.1:8334")
|
|
|
|
// Class A
|
|
addNaTest("1.0.0.1", 8333, "1.0.0.1:8333")
|
|
addNaTest("2.2.2.2", 8334, "2.2.2.2:8334")
|
|
addNaTest("27.253.252.251", 8335, "27.253.252.251:8335")
|
|
addNaTest("123.3.2.1", 8336, "123.3.2.1:8336")
|
|
|
|
// Private Class A
|
|
addNaTest("10.0.0.1", 8333, "10.0.0.1:8333")
|
|
addNaTest("10.1.1.1", 8334, "10.1.1.1:8334")
|
|
addNaTest("10.2.2.2", 8335, "10.2.2.2:8335")
|
|
addNaTest("10.10.10.10", 8336, "10.10.10.10:8336")
|
|
|
|
// Class B
|
|
addNaTest("128.0.0.1", 8333, "128.0.0.1:8333")
|
|
addNaTest("129.1.1.1", 8334, "129.1.1.1:8334")
|
|
addNaTest("180.2.2.2", 8335, "180.2.2.2:8335")
|
|
addNaTest("191.10.10.10", 8336, "191.10.10.10:8336")
|
|
|
|
// Private Class B
|
|
addNaTest("172.16.0.1", 8333, "172.16.0.1:8333")
|
|
addNaTest("172.16.1.1", 8334, "172.16.1.1:8334")
|
|
addNaTest("172.16.2.2", 8335, "172.16.2.2:8335")
|
|
addNaTest("172.16.172.172", 8336, "172.16.172.172:8336")
|
|
|
|
// Class C
|
|
addNaTest("193.0.0.1", 8333, "193.0.0.1:8333")
|
|
addNaTest("200.1.1.1", 8334, "200.1.1.1:8334")
|
|
addNaTest("205.2.2.2", 8335, "205.2.2.2:8335")
|
|
addNaTest("223.10.10.10", 8336, "223.10.10.10:8336")
|
|
|
|
// Private Class C
|
|
addNaTest("192.168.0.1", 8333, "192.168.0.1:8333")
|
|
addNaTest("192.168.1.1", 8334, "192.168.1.1:8334")
|
|
addNaTest("192.168.2.2", 8335, "192.168.2.2:8335")
|
|
addNaTest("192.168.192.192", 8336, "192.168.192.192:8336")
|
|
|
|
// IPv6
|
|
// Localhost
|
|
addNaTest("::1", 8333, "[::1]:8333")
|
|
addNaTest("fe80::1", 8334, "[fe80::1]:8334")
|
|
|
|
// Link-local
|
|
addNaTest("fe80::1:1", 8333, "[fe80::1:1]:8333")
|
|
addNaTest("fe91::2:2", 8334, "[fe91::2:2]:8334")
|
|
addNaTest("fea2::3:3", 8335, "[fea2::3:3]:8335")
|
|
addNaTest("feb3::4:4", 8336, "[feb3::4:4]:8336")
|
|
|
|
// Site-local
|
|
addNaTest("fec0::1:1", 8333, "[fec0::1:1]:8333")
|
|
addNaTest("fed1::2:2", 8334, "[fed1::2:2]:8334")
|
|
addNaTest("fee2::3:3", 8335, "[fee2::3:3]:8335")
|
|
addNaTest("fef3::4:4", 8336, "[fef3::4:4]:8336")
|
|
}
|
|
|
|
func addNaTest(ip string, port uint16, want string) {
|
|
nip := net.ParseIP(ip)
|
|
na := *wire.NewNetAddressIPPort(nip, port, wire.SFNodeNetwork)
|
|
test := naTest{na, want}
|
|
naTests = append(naTests, test)
|
|
}
|
|
|
|
func lookupFunc(host string) ([]net.IP, error) {
|
|
return nil, errors.New("not implemented")
|
|
}
|
|
|
|
func TestStartStop(t *testing.T) {
|
|
n := addrmgr.New("teststartstop", lookupFunc)
|
|
n.Start()
|
|
err := n.Stop()
|
|
if err != nil {
|
|
t.Fatalf("Address Manager failed to stop: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestAddAddressByIP(t *testing.T) {
|
|
fmtErr := fmt.Errorf("")
|
|
addrErr := &net.AddrError{}
|
|
var tests = []struct {
|
|
addrIP string
|
|
err error
|
|
}{
|
|
{
|
|
someIP + ":8333",
|
|
nil,
|
|
},
|
|
{
|
|
someIP,
|
|
addrErr,
|
|
},
|
|
{
|
|
someIP[:12] + ":8333",
|
|
fmtErr,
|
|
},
|
|
{
|
|
someIP + ":abcd",
|
|
fmtErr,
|
|
},
|
|
}
|
|
|
|
amgr := addrmgr.New("testaddressbyip", nil)
|
|
for i, test := range tests {
|
|
err := amgr.AddAddressByIP(test.addrIP)
|
|
if test.err != nil && err == nil {
|
|
t.Errorf("TestGood test %d failed expected an error and got none", i)
|
|
continue
|
|
}
|
|
if test.err == nil && err != nil {
|
|
t.Errorf("TestGood test %d failed expected no error and got one", i)
|
|
continue
|
|
}
|
|
if reflect.TypeOf(err) != reflect.TypeOf(test.err) {
|
|
t.Errorf("TestGood test %d failed got %v, want %v", i,
|
|
reflect.TypeOf(err), reflect.TypeOf(test.err))
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestAddLocalAddress(t *testing.T) {
|
|
var tests = []struct {
|
|
address wire.NetAddress
|
|
priority addrmgr.AddressPriority
|
|
valid bool
|
|
}{
|
|
{
|
|
wire.NetAddress{IP: net.ParseIP("192.168.0.100")},
|
|
addrmgr.InterfacePrio,
|
|
false,
|
|
},
|
|
{
|
|
wire.NetAddress{IP: net.ParseIP("204.124.1.1")},
|
|
addrmgr.InterfacePrio,
|
|
true,
|
|
},
|
|
{
|
|
wire.NetAddress{IP: net.ParseIP("204.124.1.1")},
|
|
addrmgr.BoundPrio,
|
|
true,
|
|
},
|
|
{
|
|
wire.NetAddress{IP: net.ParseIP("::1")},
|
|
addrmgr.InterfacePrio,
|
|
false,
|
|
},
|
|
{
|
|
wire.NetAddress{IP: net.ParseIP("fe80::1")},
|
|
addrmgr.InterfacePrio,
|
|
false,
|
|
},
|
|
{
|
|
wire.NetAddress{IP: net.ParseIP("2620:100::1")},
|
|
addrmgr.InterfacePrio,
|
|
true,
|
|
},
|
|
}
|
|
amgr := addrmgr.New("testaddlocaladdress", nil)
|
|
for x, test := range tests {
|
|
result := amgr.AddLocalAddress(&test.address, test.priority)
|
|
if result == nil && !test.valid {
|
|
t.Errorf("TestAddLocalAddress test #%d failed: %s should have "+
|
|
"been accepted", x, test.address.IP)
|
|
continue
|
|
}
|
|
if result != nil && test.valid {
|
|
t.Errorf("TestAddLocalAddress test #%d failed: %s should not have "+
|
|
"been accepted", x, test.address.IP)
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestAttempt(t *testing.T) {
|
|
n := addrmgr.New("testattempt", lookupFunc)
|
|
|
|
// Add a new address and get it
|
|
err := n.AddAddressByIP(someIP + ":8333")
|
|
if err != nil {
|
|
t.Fatalf("Adding address failed: %v", err)
|
|
}
|
|
ka := n.GetAddress()
|
|
|
|
if !ka.LastAttempt().IsZero() {
|
|
t.Errorf("Address should not have attempts, but does")
|
|
}
|
|
|
|
na := ka.NetAddress()
|
|
n.Attempt(na)
|
|
|
|
if ka.LastAttempt().IsZero() {
|
|
t.Errorf("Address should have an attempt, but does not")
|
|
}
|
|
}
|
|
|
|
func TestConnected(t *testing.T) {
|
|
n := addrmgr.New("testconnected", lookupFunc)
|
|
|
|
// Add a new address and get it
|
|
err := n.AddAddressByIP(someIP + ":8333")
|
|
if err != nil {
|
|
t.Fatalf("Adding address failed: %v", err)
|
|
}
|
|
ka := n.GetAddress()
|
|
na := ka.NetAddress()
|
|
// make it an hour ago
|
|
na.Timestamp = time.Unix(time.Now().Add(time.Hour*-1).Unix(), 0)
|
|
|
|
n.Connected(na)
|
|
|
|
if !ka.NetAddress().Timestamp.After(na.Timestamp) {
|
|
t.Errorf("Address should have a new timestamp, but does not")
|
|
}
|
|
}
|
|
|
|
func TestNeedMoreAddresses(t *testing.T) {
|
|
n := addrmgr.New("testneedmoreaddresses", lookupFunc)
|
|
addrsToAdd := 1500
|
|
b := n.NeedMoreAddresses()
|
|
if !b {
|
|
t.Errorf("Expected that we need more addresses")
|
|
}
|
|
addrs := make([]*wire.NetAddress, addrsToAdd)
|
|
|
|
var err error
|
|
for i := 0; i < addrsToAdd; i++ {
|
|
s := fmt.Sprintf("%d.%d.173.147:8333", i/128+60, i%128+60)
|
|
addrs[i], err = n.DeserializeNetAddress(s)
|
|
if err != nil {
|
|
t.Errorf("Failed to turn %s into an address: %v", s, err)
|
|
}
|
|
}
|
|
|
|
srcAddr := wire.NewNetAddressIPPort(net.IPv4(173, 144, 173, 111), 8333, 0)
|
|
|
|
n.AddAddresses(addrs, srcAddr)
|
|
numAddrs := n.NumAddresses()
|
|
if numAddrs > addrsToAdd {
|
|
t.Errorf("Number of addresses is too many %d vs %d", numAddrs, addrsToAdd)
|
|
}
|
|
|
|
b = n.NeedMoreAddresses()
|
|
if b {
|
|
t.Errorf("Expected that we don't need more addresses")
|
|
}
|
|
}
|
|
|
|
func TestGood(t *testing.T) {
|
|
n := addrmgr.New("testgood", lookupFunc)
|
|
addrsToAdd := 64 * 64
|
|
addrs := make([]*wire.NetAddress, addrsToAdd)
|
|
|
|
var err error
|
|
for i := 0; i < addrsToAdd; i++ {
|
|
s := fmt.Sprintf("%d.173.147.%d:8333", i/64+60, i%64+60)
|
|
addrs[i], err = n.DeserializeNetAddress(s)
|
|
if err != nil {
|
|
t.Errorf("Failed to turn %s into an address: %v", s, err)
|
|
}
|
|
}
|
|
|
|
srcAddr := wire.NewNetAddressIPPort(net.IPv4(173, 144, 173, 111), 8333, 0)
|
|
|
|
n.AddAddresses(addrs, srcAddr)
|
|
for _, addr := range addrs {
|
|
n.Good(addr)
|
|
}
|
|
|
|
numAddrs := n.NumAddresses()
|
|
if numAddrs >= addrsToAdd {
|
|
t.Errorf("Number of addresses is too many: %d vs %d", numAddrs, addrsToAdd)
|
|
}
|
|
|
|
numCache := len(n.AddressCache())
|
|
if numCache >= numAddrs/4 {
|
|
t.Errorf("Number of addresses in cache: got %d, want %d", numCache, numAddrs/4)
|
|
}
|
|
}
|
|
|
|
func TestGetAddress(t *testing.T) {
|
|
n := addrmgr.New("testgetaddress", lookupFunc)
|
|
|
|
// Get an address from an empty set (should error)
|
|
if rv := n.GetAddress(); rv != nil {
|
|
t.Errorf("GetAddress failed: got: %v want: %v\n", rv, nil)
|
|
}
|
|
|
|
// Add a new address and get it
|
|
err := n.AddAddressByIP(someIP + ":8333")
|
|
if err != nil {
|
|
t.Fatalf("Adding address failed: %v", err)
|
|
}
|
|
ka := n.GetAddress()
|
|
if ka == nil {
|
|
t.Fatalf("Did not get an address where there is one in the pool")
|
|
}
|
|
if ka.NetAddress().IP.String() != someIP {
|
|
t.Errorf("Wrong IP: got %v, want %v", ka.NetAddress().IP.String(), someIP)
|
|
}
|
|
|
|
// Mark this as a good address and get it
|
|
n.Good(ka.NetAddress())
|
|
ka = n.GetAddress()
|
|
if ka == nil {
|
|
t.Fatalf("Did not get an address where there is one in the pool")
|
|
}
|
|
if ka.NetAddress().IP.String() != someIP {
|
|
t.Errorf("Wrong IP: got %v, want %v", ka.NetAddress().IP.String(), someIP)
|
|
}
|
|
|
|
numAddrs := n.NumAddresses()
|
|
if numAddrs != 1 {
|
|
t.Errorf("Wrong number of addresses: got %d, want %d", numAddrs, 1)
|
|
}
|
|
}
|
|
|
|
func TestGetBestLocalAddress(t *testing.T) {
|
|
localAddrs := []wire.NetAddress{
|
|
{IP: net.ParseIP("192.168.0.100")},
|
|
{IP: net.ParseIP("::1")},
|
|
{IP: net.ParseIP("fe80::1")},
|
|
{IP: net.ParseIP("2001:470::1")},
|
|
}
|
|
|
|
var tests = []struct {
|
|
remoteAddr wire.NetAddress
|
|
want0 wire.NetAddress
|
|
want1 wire.NetAddress
|
|
want2 wire.NetAddress
|
|
want3 wire.NetAddress
|
|
}{
|
|
{
|
|
// Remote connection from public IPv4
|
|
wire.NetAddress{IP: net.ParseIP("204.124.8.1")},
|
|
wire.NetAddress{IP: net.IPv4zero},
|
|
wire.NetAddress{IP: net.IPv4zero},
|
|
wire.NetAddress{IP: net.ParseIP("204.124.8.100")},
|
|
wire.NetAddress{IP: net.ParseIP("fd87:d87e:eb43:25::1")},
|
|
},
|
|
{
|
|
// Remote connection from private IPv4
|
|
wire.NetAddress{IP: net.ParseIP("172.16.0.254")},
|
|
wire.NetAddress{IP: net.IPv4zero},
|
|
wire.NetAddress{IP: net.IPv4zero},
|
|
wire.NetAddress{IP: net.IPv4zero},
|
|
wire.NetAddress{IP: net.IPv4zero},
|
|
},
|
|
{
|
|
// Remote connection from public IPv6
|
|
wire.NetAddress{IP: net.ParseIP("2602:100:abcd::102")},
|
|
wire.NetAddress{IP: net.IPv6zero},
|
|
wire.NetAddress{IP: net.ParseIP("2001:470::1")},
|
|
wire.NetAddress{IP: net.ParseIP("2001:470::1")},
|
|
wire.NetAddress{IP: net.ParseIP("2001:470::1")},
|
|
},
|
|
/* XXX
|
|
{
|
|
// Remote connection from Tor
|
|
wire.NetAddress{IP: net.ParseIP("fd87:d87e:eb43::100")},
|
|
wire.NetAddress{IP: net.IPv4zero},
|
|
wire.NetAddress{IP: net.ParseIP("204.124.8.100")},
|
|
wire.NetAddress{IP: net.ParseIP("fd87:d87e:eb43:25::1")},
|
|
},
|
|
*/
|
|
}
|
|
|
|
amgr := addrmgr.New("testgetbestlocaladdress", nil)
|
|
|
|
// Test against default when there's no address
|
|
for x, test := range tests {
|
|
got := amgr.GetBestLocalAddress(&test.remoteAddr)
|
|
if !test.want0.IP.Equal(got.IP) {
|
|
t.Errorf("TestGetBestLocalAddress test1 #%d failed for remote address %s: want %s got %s",
|
|
x, test.remoteAddr.IP, test.want1.IP, got.IP)
|
|
continue
|
|
}
|
|
}
|
|
|
|
for _, localAddr := range localAddrs {
|
|
amgr.AddLocalAddress(&localAddr, addrmgr.InterfacePrio)
|
|
}
|
|
|
|
// Test against want1
|
|
for x, test := range tests {
|
|
got := amgr.GetBestLocalAddress(&test.remoteAddr)
|
|
if !test.want1.IP.Equal(got.IP) {
|
|
t.Errorf("TestGetBestLocalAddress test1 #%d failed for remote address %s: want %s got %s",
|
|
x, test.remoteAddr.IP, test.want1.IP, got.IP)
|
|
continue
|
|
}
|
|
}
|
|
|
|
// Add a public IP to the list of local addresses.
|
|
localAddr := wire.NetAddress{IP: net.ParseIP("204.124.8.100")}
|
|
amgr.AddLocalAddress(&localAddr, addrmgr.InterfacePrio)
|
|
|
|
// Test against want2
|
|
for x, test := range tests {
|
|
got := amgr.GetBestLocalAddress(&test.remoteAddr)
|
|
if !test.want2.IP.Equal(got.IP) {
|
|
t.Errorf("TestGetBestLocalAddress test2 #%d failed for remote address %s: want %s got %s",
|
|
x, test.remoteAddr.IP, test.want2.IP, got.IP)
|
|
continue
|
|
}
|
|
}
|
|
/*
|
|
// Add a tor generated IP address
|
|
localAddr = wire.NetAddress{IP: net.ParseIP("fd87:d87e:eb43:25::1")}
|
|
amgr.AddLocalAddress(&localAddr, addrmgr.ManualPrio)
|
|
|
|
// Test against want3
|
|
for x, test := range tests {
|
|
got := amgr.GetBestLocalAddress(&test.remoteAddr)
|
|
if !test.want3.IP.Equal(got.IP) {
|
|
t.Errorf("TestGetBestLocalAddress test3 #%d failed for remote address %s: want %s got %s",
|
|
x, test.remoteAddr.IP, test.want3.IP, got.IP)
|
|
continue
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
|
|
func TestNetAddressKey(t *testing.T) {
|
|
addNaTests()
|
|
|
|
t.Logf("Running %d tests", len(naTests))
|
|
for i, test := range naTests {
|
|
key := addrmgr.NetAddressKey(&test.in)
|
|
if key != test.want {
|
|
t.Errorf("NetAddressKey #%d\n got: %s want: %s", i, key, test.want)
|
|
continue
|
|
}
|
|
}
|
|
|
|
}
|