2014-09-21 17:33:12 +00:00
|
|
|
// Copyright 2013 The Go Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package net
|
|
|
|
|
|
|
|
import (
|
|
|
|
"reflect"
|
|
|
|
"testing"
|
|
|
|
)
|
|
|
|
|
2017-04-10 11:32:00 +00:00
|
|
|
var testInetaddr = func(ip IPAddr) Addr { return &TCPAddr{IP: ip.IP, Port: 5682, Zone: ip.Zone} }
|
2014-09-21 17:33:12 +00:00
|
|
|
|
2017-04-10 11:32:00 +00:00
|
|
|
var addrListTests = []struct {
|
|
|
|
filter func(IPAddr) bool
|
|
|
|
ips []IPAddr
|
|
|
|
inetaddr func(IPAddr) Addr
|
|
|
|
first Addr
|
|
|
|
primaries addrList
|
|
|
|
fallbacks addrList
|
|
|
|
err error
|
2014-09-21 17:33:12 +00:00
|
|
|
}{
|
|
|
|
{
|
|
|
|
nil,
|
2017-04-10 11:32:00 +00:00
|
|
|
[]IPAddr{
|
|
|
|
{IP: IPv4(127, 0, 0, 1)},
|
|
|
|
{IP: IPv6loopback},
|
2014-09-21 17:33:12 +00:00
|
|
|
},
|
|
|
|
testInetaddr,
|
2017-04-10 11:32:00 +00:00
|
|
|
&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
|
|
|
|
addrList{&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682}},
|
|
|
|
addrList{&TCPAddr{IP: IPv6loopback, Port: 5682}},
|
2014-09-21 17:33:12 +00:00
|
|
|
nil,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
nil,
|
2017-04-10 11:32:00 +00:00
|
|
|
[]IPAddr{
|
|
|
|
{IP: IPv6loopback},
|
|
|
|
{IP: IPv4(127, 0, 0, 1)},
|
2014-09-21 17:33:12 +00:00
|
|
|
},
|
|
|
|
testInetaddr,
|
2017-04-10 11:32:00 +00:00
|
|
|
&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
|
|
|
|
addrList{&TCPAddr{IP: IPv6loopback, Port: 5682}},
|
|
|
|
addrList{&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682}},
|
2014-09-21 17:33:12 +00:00
|
|
|
nil,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
nil,
|
2017-04-10 11:32:00 +00:00
|
|
|
[]IPAddr{
|
|
|
|
{IP: IPv4(127, 0, 0, 1)},
|
|
|
|
{IP: IPv4(192, 168, 0, 1)},
|
2014-09-21 17:33:12 +00:00
|
|
|
},
|
|
|
|
testInetaddr,
|
|
|
|
&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
|
2017-04-10 11:32:00 +00:00
|
|
|
addrList{
|
|
|
|
&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
|
|
|
|
&TCPAddr{IP: IPv4(192, 168, 0, 1), Port: 5682},
|
|
|
|
},
|
|
|
|
nil,
|
2014-09-21 17:33:12 +00:00
|
|
|
nil,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
nil,
|
2017-04-10 11:32:00 +00:00
|
|
|
[]IPAddr{
|
|
|
|
{IP: IPv6loopback},
|
|
|
|
{IP: ParseIP("fe80::1"), Zone: "eth0"},
|
2014-09-21 17:33:12 +00:00
|
|
|
},
|
|
|
|
testInetaddr,
|
|
|
|
&TCPAddr{IP: IPv6loopback, Port: 5682},
|
2017-04-10 11:32:00 +00:00
|
|
|
addrList{
|
|
|
|
&TCPAddr{IP: IPv6loopback, Port: 5682},
|
|
|
|
&TCPAddr{IP: ParseIP("fe80::1"), Port: 5682, Zone: "eth0"},
|
|
|
|
},
|
|
|
|
nil,
|
2014-09-21 17:33:12 +00:00
|
|
|
nil,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
nil,
|
2017-04-10 11:32:00 +00:00
|
|
|
[]IPAddr{
|
|
|
|
{IP: IPv4(127, 0, 0, 1)},
|
|
|
|
{IP: IPv4(192, 168, 0, 1)},
|
|
|
|
{IP: IPv6loopback},
|
|
|
|
{IP: ParseIP("fe80::1"), Zone: "eth0"},
|
2014-09-21 17:33:12 +00:00
|
|
|
},
|
|
|
|
testInetaddr,
|
2017-04-10 11:32:00 +00:00
|
|
|
&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
|
2014-09-21 17:33:12 +00:00
|
|
|
addrList{
|
|
|
|
&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
|
2017-04-10 11:32:00 +00:00
|
|
|
&TCPAddr{IP: IPv4(192, 168, 0, 1), Port: 5682},
|
|
|
|
},
|
|
|
|
addrList{
|
2014-09-21 17:33:12 +00:00
|
|
|
&TCPAddr{IP: IPv6loopback, Port: 5682},
|
2017-04-10 11:32:00 +00:00
|
|
|
&TCPAddr{IP: ParseIP("fe80::1"), Port: 5682, Zone: "eth0"},
|
2014-09-21 17:33:12 +00:00
|
|
|
},
|
|
|
|
nil,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
nil,
|
2017-04-10 11:32:00 +00:00
|
|
|
[]IPAddr{
|
|
|
|
{IP: IPv6loopback},
|
|
|
|
{IP: ParseIP("fe80::1"), Zone: "eth0"},
|
|
|
|
{IP: IPv4(127, 0, 0, 1)},
|
|
|
|
{IP: IPv4(192, 168, 0, 1)},
|
2014-09-21 17:33:12 +00:00
|
|
|
},
|
|
|
|
testInetaddr,
|
2017-04-10 11:32:00 +00:00
|
|
|
&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
|
2014-09-21 17:33:12 +00:00
|
|
|
addrList{
|
|
|
|
&TCPAddr{IP: IPv6loopback, Port: 5682},
|
2017-04-10 11:32:00 +00:00
|
|
|
&TCPAddr{IP: ParseIP("fe80::1"), Port: 5682, Zone: "eth0"},
|
|
|
|
},
|
|
|
|
addrList{
|
|
|
|
&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
|
|
|
|
&TCPAddr{IP: IPv4(192, 168, 0, 1), Port: 5682},
|
2014-09-21 17:33:12 +00:00
|
|
|
},
|
|
|
|
nil,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
nil,
|
2017-04-10 11:32:00 +00:00
|
|
|
[]IPAddr{
|
|
|
|
{IP: IPv4(127, 0, 0, 1)},
|
|
|
|
{IP: IPv6loopback},
|
|
|
|
{IP: IPv4(192, 168, 0, 1)},
|
|
|
|
{IP: ParseIP("fe80::1"), Zone: "eth0"},
|
2014-09-21 17:33:12 +00:00
|
|
|
},
|
|
|
|
testInetaddr,
|
2017-04-10 11:32:00 +00:00
|
|
|
&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
|
2014-09-21 17:33:12 +00:00
|
|
|
addrList{
|
|
|
|
&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
|
2017-04-10 11:32:00 +00:00
|
|
|
&TCPAddr{IP: IPv4(192, 168, 0, 1), Port: 5682},
|
|
|
|
},
|
|
|
|
addrList{
|
2014-09-21 17:33:12 +00:00
|
|
|
&TCPAddr{IP: IPv6loopback, Port: 5682},
|
2017-04-10 11:32:00 +00:00
|
|
|
&TCPAddr{IP: ParseIP("fe80::1"), Port: 5682, Zone: "eth0"},
|
2014-09-21 17:33:12 +00:00
|
|
|
},
|
|
|
|
nil,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
nil,
|
2017-04-10 11:32:00 +00:00
|
|
|
[]IPAddr{
|
|
|
|
{IP: IPv6loopback},
|
|
|
|
{IP: IPv4(127, 0, 0, 1)},
|
|
|
|
{IP: ParseIP("fe80::1"), Zone: "eth0"},
|
|
|
|
{IP: IPv4(192, 168, 0, 1)},
|
2014-09-21 17:33:12 +00:00
|
|
|
},
|
|
|
|
testInetaddr,
|
2017-04-10 11:32:00 +00:00
|
|
|
&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
|
2014-09-21 17:33:12 +00:00
|
|
|
addrList{
|
|
|
|
&TCPAddr{IP: IPv6loopback, Port: 5682},
|
2017-04-10 11:32:00 +00:00
|
|
|
&TCPAddr{IP: ParseIP("fe80::1"), Port: 5682, Zone: "eth0"},
|
|
|
|
},
|
|
|
|
addrList{
|
|
|
|
&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
|
|
|
|
&TCPAddr{IP: IPv4(192, 168, 0, 1), Port: 5682},
|
2014-09-21 17:33:12 +00:00
|
|
|
},
|
|
|
|
nil,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
ipv4only,
|
2017-04-10 11:32:00 +00:00
|
|
|
[]IPAddr{
|
|
|
|
{IP: IPv4(127, 0, 0, 1)},
|
|
|
|
{IP: IPv6loopback},
|
2014-09-21 17:33:12 +00:00
|
|
|
},
|
|
|
|
testInetaddr,
|
|
|
|
&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
|
2017-04-10 11:32:00 +00:00
|
|
|
addrList{&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682}},
|
|
|
|
nil,
|
2014-09-21 17:33:12 +00:00
|
|
|
nil,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ipv4only,
|
2017-04-10 11:32:00 +00:00
|
|
|
[]IPAddr{
|
|
|
|
{IP: IPv6loopback},
|
|
|
|
{IP: IPv4(127, 0, 0, 1)},
|
2014-09-21 17:33:12 +00:00
|
|
|
},
|
|
|
|
testInetaddr,
|
|
|
|
&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
|
2017-04-10 11:32:00 +00:00
|
|
|
addrList{&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682}},
|
|
|
|
nil,
|
2014-09-21 17:33:12 +00:00
|
|
|
nil,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
ipv6only,
|
2017-04-10 11:32:00 +00:00
|
|
|
[]IPAddr{
|
|
|
|
{IP: IPv4(127, 0, 0, 1)},
|
|
|
|
{IP: IPv6loopback},
|
2014-09-21 17:33:12 +00:00
|
|
|
},
|
|
|
|
testInetaddr,
|
|
|
|
&TCPAddr{IP: IPv6loopback, Port: 5682},
|
2017-04-10 11:32:00 +00:00
|
|
|
addrList{&TCPAddr{IP: IPv6loopback, Port: 5682}},
|
|
|
|
nil,
|
2014-09-21 17:33:12 +00:00
|
|
|
nil,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ipv6only,
|
2017-04-10 11:32:00 +00:00
|
|
|
[]IPAddr{
|
|
|
|
{IP: IPv6loopback},
|
|
|
|
{IP: IPv4(127, 0, 0, 1)},
|
2014-09-21 17:33:12 +00:00
|
|
|
},
|
|
|
|
testInetaddr,
|
|
|
|
&TCPAddr{IP: IPv6loopback, Port: 5682},
|
2017-04-10 11:32:00 +00:00
|
|
|
addrList{&TCPAddr{IP: IPv6loopback, Port: 5682}},
|
|
|
|
nil,
|
2014-09-21 17:33:12 +00:00
|
|
|
nil,
|
|
|
|
},
|
|
|
|
|
2017-10-07 00:16:47 +00:00
|
|
|
{nil, nil, testInetaddr, nil, nil, nil, &AddrError{errNoSuitableAddress.Error(), "ADDR"}},
|
2014-09-21 17:33:12 +00:00
|
|
|
|
2017-10-07 00:16:47 +00:00
|
|
|
{ipv4only, nil, testInetaddr, nil, nil, nil, &AddrError{errNoSuitableAddress.Error(), "ADDR"}},
|
|
|
|
{ipv4only, []IPAddr{{IP: IPv6loopback}}, testInetaddr, nil, nil, nil, &AddrError{errNoSuitableAddress.Error(), "ADDR"}},
|
2014-09-21 17:33:12 +00:00
|
|
|
|
2017-10-07 00:16:47 +00:00
|
|
|
{ipv6only, nil, testInetaddr, nil, nil, nil, &AddrError{errNoSuitableAddress.Error(), "ADDR"}},
|
|
|
|
{ipv6only, []IPAddr{{IP: IPv4(127, 0, 0, 1)}}, testInetaddr, nil, nil, nil, &AddrError{errNoSuitableAddress.Error(), "ADDR"}},
|
2014-09-21 17:33:12 +00:00
|
|
|
}
|
|
|
|
|
2017-04-10 11:32:00 +00:00
|
|
|
func TestAddrList(t *testing.T) {
|
2018-12-28 15:30:48 +00:00
|
|
|
if !supportsIPv4() || !supportsIPv6() {
|
2017-04-10 11:32:00 +00:00
|
|
|
t.Skip("both IPv4 and IPv6 are required")
|
2014-09-21 17:33:12 +00:00
|
|
|
}
|
|
|
|
|
2017-04-10 11:32:00 +00:00
|
|
|
for i, tt := range addrListTests {
|
2017-10-07 00:16:47 +00:00
|
|
|
addrs, err := filterAddrList(tt.filter, tt.ips, tt.inetaddr, "ADDR")
|
|
|
|
if !reflect.DeepEqual(err, tt.err) {
|
2017-04-10 11:32:00 +00:00
|
|
|
t.Errorf("#%v: got %v; want %v", i, err, tt.err)
|
|
|
|
}
|
|
|
|
if tt.err != nil {
|
|
|
|
if len(addrs) != 0 {
|
|
|
|
t.Errorf("#%v: got %v; want 0", i, len(addrs))
|
|
|
|
}
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
first := addrs.first(isIPv4)
|
|
|
|
if !reflect.DeepEqual(first, tt.first) {
|
|
|
|
t.Errorf("#%v: got %v; want %v", i, first, tt.first)
|
|
|
|
}
|
|
|
|
primaries, fallbacks := addrs.partition(isIPv4)
|
|
|
|
if !reflect.DeepEqual(primaries, tt.primaries) {
|
|
|
|
t.Errorf("#%v: got %v; want %v", i, primaries, tt.primaries)
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(fallbacks, tt.fallbacks) {
|
|
|
|
t.Errorf("#%v: got %v; want %v", i, fallbacks, tt.fallbacks)
|
2014-09-21 17:33:12 +00:00
|
|
|
}
|
2017-04-10 11:32:00 +00:00
|
|
|
expectedLen := len(primaries) + len(fallbacks)
|
|
|
|
if len(addrs) != expectedLen {
|
|
|
|
t.Errorf("#%v: got %v; want %v", i, len(addrs), expectedLen)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestAddrListPartition(t *testing.T) {
|
|
|
|
addrs := addrList{
|
|
|
|
&IPAddr{IP: ParseIP("fe80::"), Zone: "eth0"},
|
|
|
|
&IPAddr{IP: ParseIP("fe80::1"), Zone: "eth0"},
|
|
|
|
&IPAddr{IP: ParseIP("fe80::2"), Zone: "eth0"},
|
|
|
|
}
|
|
|
|
cases := []struct {
|
|
|
|
lastByte byte
|
|
|
|
primaries addrList
|
|
|
|
fallbacks addrList
|
|
|
|
}{
|
|
|
|
{0, addrList{addrs[0]}, addrList{addrs[1], addrs[2]}},
|
|
|
|
{1, addrList{addrs[0], addrs[2]}, addrList{addrs[1]}},
|
|
|
|
{2, addrList{addrs[0], addrs[1]}, addrList{addrs[2]}},
|
|
|
|
{3, addrList{addrs[0], addrs[1], addrs[2]}, nil},
|
|
|
|
}
|
|
|
|
for i, tt := range cases {
|
|
|
|
// Inverting the function's output should not affect the outcome.
|
|
|
|
for _, invert := range []bool{false, true} {
|
|
|
|
primaries, fallbacks := addrs.partition(func(a Addr) bool {
|
|
|
|
ip := a.(*IPAddr).IP
|
|
|
|
return (ip[len(ip)-1] == tt.lastByte) != invert
|
|
|
|
})
|
|
|
|
if !reflect.DeepEqual(primaries, tt.primaries) {
|
|
|
|
t.Errorf("#%v: got %v; want %v", i, primaries, tt.primaries)
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(fallbacks, tt.fallbacks) {
|
|
|
|
t.Errorf("#%v: got %v; want %v", i, fallbacks, tt.fallbacks)
|
|
|
|
}
|
2014-09-21 17:33:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|