diff --git a/addrmgr/addrmanager_test.go b/addrmgr/addrmanager_test.go index 82d71ed1f..28262ea9a 100644 --- a/addrmgr/addrmanager_test.go +++ b/addrmgr/addrmanager_test.go @@ -6,7 +6,9 @@ package addrmgr_test import ( "errors" + "fmt" "net" + "reflect" "testing" "time" @@ -25,6 +27,9 @@ type naTest struct { // 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 @@ -102,35 +107,99 @@ 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 - valid bool + 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("", nil) + amgr := addrmgr.New("testaddlocaladdress", nil) for x, test := range tests { - result := amgr.AddLocalAddress(&test.address, addrmgr.InterfacePrio) + 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) @@ -144,11 +213,158 @@ func TestAddLocalAddress(t *testing.T) { } } +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("any", 100) + + 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("any", 100) + na := ka.NetAddress() + na.Timestamp = time.Now().Add(time.Hour * -1) // make it an hour ago + + 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 == false { + t.Errorf("Expected that we need more addresses") + } + addrs := make([]*wire.NetAddress, addrsToAdd) + now := time.Now() + + 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.NetAddress{ + Timestamp: now, + Services: 0, + IP: net.IPv4(173, 144, 173, 111), + Port: 8333, + } + + 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 == true { + 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) + now := time.Now() + + 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.NetAddress{ + Timestamp: now, + Services: 0, + IP: net.IPv4(173, 144, 173, 111), + Port: 8333, + } + + 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("testdir", lookupFunc) + n := addrmgr.New("testgetaddress", lookupFunc) + + // Get an address from an empty set (should error) if rv := n.GetAddress("any", 10); 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("any", 120) // 100 bias is max, but shouldn't error + 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("any", -10) // 0 bias is min, but shouldn't error + 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) { @@ -161,6 +377,7 @@ func TestGetBestLocalAddress(t *testing.T) { var tests = []struct { remoteAddr wire.NetAddress + want0 wire.NetAddress want1 wire.NetAddress want2 wire.NetAddress want3 wire.NetAddress @@ -169,6 +386,7 @@ func TestGetBestLocalAddress(t *testing.T) { // 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")}, }, @@ -178,10 +396,12 @@ func TestGetBestLocalAddress(t *testing.T) { 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")}, @@ -197,7 +417,18 @@ func TestGetBestLocalAddress(t *testing.T) { */ } - amgr := addrmgr.New("", nil) + 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) }