Home | History | Annotate | Download | only in net
      1 // Copyright 2009 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package net
      6 
      7 import (
      8 	"bytes"
      9 	"math/rand"
     10 	"reflect"
     11 	"runtime"
     12 	"testing"
     13 )
     14 
     15 var parseIPTests = []struct {
     16 	in  string
     17 	out IP
     18 }{
     19 	{"127.0.1.2", IPv4(127, 0, 1, 2)},
     20 	{"127.0.0.1", IPv4(127, 0, 0, 1)},
     21 	{"127.001.002.003", IPv4(127, 1, 2, 3)},
     22 	{"::ffff:127.1.2.3", IPv4(127, 1, 2, 3)},
     23 	{"::ffff:127.001.002.003", IPv4(127, 1, 2, 3)},
     24 	{"::ffff:7f01:0203", IPv4(127, 1, 2, 3)},
     25 	{"0:0:0:0:0000:ffff:127.1.2.3", IPv4(127, 1, 2, 3)},
     26 	{"0:0:0:0:000000:ffff:127.1.2.3", IPv4(127, 1, 2, 3)},
     27 	{"0:0:0:0::ffff:127.1.2.3", IPv4(127, 1, 2, 3)},
     28 
     29 	{"2001:4860:0:2001::68", IP{0x20, 0x01, 0x48, 0x60, 0, 0, 0x20, 0x01, 0, 0, 0, 0, 0, 0, 0x00, 0x68}},
     30 	{"2001:4860:0000:2001:0000:0000:0000:0068", IP{0x20, 0x01, 0x48, 0x60, 0, 0, 0x20, 0x01, 0, 0, 0, 0, 0, 0, 0x00, 0x68}},
     31 
     32 	{"-0.0.0.0", nil},
     33 	{"0.-1.0.0", nil},
     34 	{"0.0.-2.0", nil},
     35 	{"0.0.0.-3", nil},
     36 	{"127.0.0.256", nil},
     37 	{"abc", nil},
     38 	{"123:", nil},
     39 	{"fe80::1%lo0", nil},
     40 	{"fe80::1%911", nil},
     41 	{"", nil},
     42 	{"a1:a2:a3:a4::b1:b2:b3:b4", nil}, // Issue 6628
     43 }
     44 
     45 func TestParseIP(t *testing.T) {
     46 	for _, tt := range parseIPTests {
     47 		if out := ParseIP(tt.in); !reflect.DeepEqual(out, tt.out) {
     48 			t.Errorf("ParseIP(%q) = %v, want %v", tt.in, out, tt.out)
     49 		}
     50 		if tt.in == "" {
     51 			// Tested in TestMarshalEmptyIP below.
     52 			continue
     53 		}
     54 		var out IP
     55 		if err := out.UnmarshalText([]byte(tt.in)); !reflect.DeepEqual(out, tt.out) || (tt.out == nil) != (err != nil) {
     56 			t.Errorf("IP.UnmarshalText(%q) = %v, %v, want %v", tt.in, out, err, tt.out)
     57 		}
     58 	}
     59 }
     60 
     61 func TestLookupWithIP(t *testing.T) {
     62 	_, err := LookupIP("")
     63 	if err == nil {
     64 		t.Errorf(`LookupIP("") succeeded, should fail`)
     65 	}
     66 	_, err = LookupHost("")
     67 	if err == nil {
     68 		t.Errorf(`LookupIP("") succeeded, should fail`)
     69 	}
     70 
     71 	// Test that LookupHost and LookupIP, which normally
     72 	// expect host names, work with IP addresses.
     73 	for _, tt := range parseIPTests {
     74 		if tt.out != nil {
     75 			addrs, err := LookupHost(tt.in)
     76 			if len(addrs) != 1 || addrs[0] != tt.in || err != nil {
     77 				t.Errorf("LookupHost(%q) = %v, %v, want %v, nil", tt.in, addrs, err, []string{tt.in})
     78 			}
     79 		} else if !testing.Short() {
     80 			// We can't control what the host resolver does; if it can resolve, say,
     81 			// 127.0.0.256 or fe80::1%911 or a host named 'abc', who are we to judge?
     82 			// Warn about these discrepancies but don't fail the test.
     83 			addrs, err := LookupHost(tt.in)
     84 			if err == nil {
     85 				t.Logf("warning: LookupHost(%q) = %v, want error", tt.in, addrs)
     86 			}
     87 		}
     88 
     89 		if tt.out != nil {
     90 			ips, err := LookupIP(tt.in)
     91 			if len(ips) != 1 || !reflect.DeepEqual(ips[0], tt.out) || err != nil {
     92 				t.Errorf("LookupIP(%q) = %v, %v, want %v, nil", tt.in, ips, err, []IP{tt.out})
     93 			}
     94 		} else if !testing.Short() {
     95 			ips, err := LookupIP(tt.in)
     96 			// We can't control what the host resolver does. See above.
     97 			if err == nil {
     98 				t.Logf("warning: LookupIP(%q) = %v, want error", tt.in, ips)
     99 			}
    100 		}
    101 	}
    102 }
    103 
    104 func BenchmarkParseIP(b *testing.B) {
    105 	testHookUninstaller.Do(uninstallTestHooks)
    106 
    107 	for i := 0; i < b.N; i++ {
    108 		for _, tt := range parseIPTests {
    109 			ParseIP(tt.in)
    110 		}
    111 	}
    112 }
    113 
    114 // Issue 6339
    115 func TestMarshalEmptyIP(t *testing.T) {
    116 	for _, in := range [][]byte{nil, []byte("")} {
    117 		var out = IP{1, 2, 3, 4}
    118 		if err := out.UnmarshalText(in); err != nil || out != nil {
    119 			t.Errorf("UnmarshalText(%v) = %v, %v; want nil, nil", in, out, err)
    120 		}
    121 	}
    122 	var ip IP
    123 	got, err := ip.MarshalText()
    124 	if err != nil {
    125 		t.Fatal(err)
    126 	}
    127 	if !reflect.DeepEqual(got, []byte("")) {
    128 		t.Errorf(`got %#v, want []byte("")`, got)
    129 	}
    130 }
    131 
    132 var ipStringTests = []struct {
    133 	in  IP     // see RFC 791 and RFC 4291
    134 	str string // see RFC 791, RFC 4291 and RFC 5952
    135 	byt []byte
    136 	error
    137 }{
    138 	// IPv4 address
    139 	{
    140 		IP{192, 0, 2, 1},
    141 		"192.0.2.1",
    142 		[]byte("192.0.2.1"),
    143 		nil,
    144 	},
    145 	{
    146 		IP{0, 0, 0, 0},
    147 		"0.0.0.0",
    148 		[]byte("0.0.0.0"),
    149 		nil,
    150 	},
    151 
    152 	// IPv4-mapped IPv6 address
    153 	{
    154 		IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 192, 0, 2, 1},
    155 		"192.0.2.1",
    156 		[]byte("192.0.2.1"),
    157 		nil,
    158 	},
    159 	{
    160 		IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0, 0, 0, 0},
    161 		"0.0.0.0",
    162 		[]byte("0.0.0.0"),
    163 		nil,
    164 	},
    165 
    166 	// IPv6 address
    167 	{
    168 		IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0x1, 0x23, 0, 0x12, 0, 0x1},
    169 		"2001:db8::123:12:1",
    170 		[]byte("2001:db8::123:12:1"),
    171 		nil,
    172 	},
    173 	{
    174 		IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1},
    175 		"2001:db8::1",
    176 		[]byte("2001:db8::1"),
    177 		nil,
    178 	},
    179 	{
    180 		IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0x1, 0, 0, 0, 0x1, 0, 0, 0, 0x1},
    181 		"2001:db8:0:1:0:1:0:1",
    182 		[]byte("2001:db8:0:1:0:1:0:1"),
    183 		nil,
    184 	},
    185 	{
    186 		IP{0x20, 0x1, 0xd, 0xb8, 0, 0x1, 0, 0, 0, 0x1, 0, 0, 0, 0x1, 0, 0},
    187 		"2001:db8:1:0:1:0:1:0",
    188 		[]byte("2001:db8:1:0:1:0:1:0"),
    189 		nil,
    190 	},
    191 	{
    192 		IP{0x20, 0x1, 0, 0, 0, 0, 0, 0, 0, 0x1, 0, 0, 0, 0, 0, 0x1},
    193 		"2001::1:0:0:1",
    194 		[]byte("2001::1:0:0:1"),
    195 		nil,
    196 	},
    197 	{
    198 		IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0x1, 0, 0, 0, 0, 0, 0},
    199 		"2001:db8:0:0:1::",
    200 		[]byte("2001:db8:0:0:1::"),
    201 		nil,
    202 	},
    203 	{
    204 		IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0x1, 0, 0, 0, 0, 0, 0x1},
    205 		"2001:db8::1:0:0:1",
    206 		[]byte("2001:db8::1:0:0:1"),
    207 		nil,
    208 	},
    209 	{
    210 		IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0xa, 0, 0xb, 0, 0xc, 0, 0xd},
    211 		"2001:db8::a:b:c:d",
    212 		[]byte("2001:db8::a:b:c:d"),
    213 		nil,
    214 	},
    215 	{
    216 		IPv6unspecified,
    217 		"::",
    218 		[]byte("::"),
    219 		nil,
    220 	},
    221 
    222 	// IP wildcard equivalent address in Dial/Listen API
    223 	{
    224 		nil,
    225 		"<nil>",
    226 		nil,
    227 		nil,
    228 	},
    229 
    230 	// Opaque byte sequence
    231 	{
    232 		IP{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
    233 		"?0123456789abcdef",
    234 		nil,
    235 		&AddrError{Err: "invalid IP address", Addr: "0123456789abcdef"},
    236 	},
    237 }
    238 
    239 func TestIPString(t *testing.T) {
    240 	for _, tt := range ipStringTests {
    241 		if out := tt.in.String(); out != tt.str {
    242 			t.Errorf("IP.String(%v) = %q, want %q", tt.in, out, tt.str)
    243 		}
    244 		if out, err := tt.in.MarshalText(); !bytes.Equal(out, tt.byt) || !reflect.DeepEqual(err, tt.error) {
    245 			t.Errorf("IP.MarshalText(%v) = %v, %v, want %v, %v", tt.in, out, err, tt.byt, tt.error)
    246 		}
    247 	}
    248 }
    249 
    250 var sink string
    251 
    252 func BenchmarkIPString(b *testing.B) {
    253 	testHookUninstaller.Do(uninstallTestHooks)
    254 
    255 	for i := 0; i < b.N; i++ {
    256 		for _, tt := range ipStringTests {
    257 			if tt.in != nil {
    258 				sink = tt.in.String()
    259 			}
    260 		}
    261 	}
    262 }
    263 
    264 var ipMaskTests = []struct {
    265 	in   IP
    266 	mask IPMask
    267 	out  IP
    268 }{
    269 	{IPv4(192, 168, 1, 127), IPv4Mask(255, 255, 255, 128), IPv4(192, 168, 1, 0)},
    270 	{IPv4(192, 168, 1, 127), IPMask(ParseIP("255.255.255.192")), IPv4(192, 168, 1, 64)},
    271 	{IPv4(192, 168, 1, 127), IPMask(ParseIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffe0")), IPv4(192, 168, 1, 96)},
    272 	{IPv4(192, 168, 1, 127), IPv4Mask(255, 0, 255, 0), IPv4(192, 0, 1, 0)},
    273 	{ParseIP("2001:db8::1"), IPMask(ParseIP("ffff:ff80::")), ParseIP("2001:d80::")},
    274 	{ParseIP("2001:db8::1"), IPMask(ParseIP("f0f0:0f0f::")), ParseIP("2000:d08::")},
    275 }
    276 
    277 func TestIPMask(t *testing.T) {
    278 	for _, tt := range ipMaskTests {
    279 		if out := tt.in.Mask(tt.mask); out == nil || !tt.out.Equal(out) {
    280 			t.Errorf("IP(%v).Mask(%v) = %v, want %v", tt.in, tt.mask, out, tt.out)
    281 		}
    282 	}
    283 }
    284 
    285 var ipMaskStringTests = []struct {
    286 	in  IPMask
    287 	out string
    288 }{
    289 	{IPv4Mask(255, 255, 255, 240), "fffffff0"},
    290 	{IPv4Mask(255, 0, 128, 0), "ff008000"},
    291 	{IPMask(ParseIP("ffff:ff80::")), "ffffff80000000000000000000000000"},
    292 	{IPMask(ParseIP("ef00:ff80::cafe:0")), "ef00ff800000000000000000cafe0000"},
    293 	{nil, "<nil>"},
    294 }
    295 
    296 func TestIPMaskString(t *testing.T) {
    297 	for _, tt := range ipMaskStringTests {
    298 		if out := tt.in.String(); out != tt.out {
    299 			t.Errorf("IPMask.String(%v) = %q, want %q", tt.in, out, tt.out)
    300 		}
    301 	}
    302 }
    303 
    304 func BenchmarkIPMaskString(b *testing.B) {
    305 	testHookUninstaller.Do(uninstallTestHooks)
    306 
    307 	for i := 0; i < b.N; i++ {
    308 		for _, tt := range ipMaskStringTests {
    309 			sink = tt.in.String()
    310 		}
    311 	}
    312 }
    313 
    314 var parseCIDRTests = []struct {
    315 	in  string
    316 	ip  IP
    317 	net *IPNet
    318 	err error
    319 }{
    320 	{"135.104.0.0/32", IPv4(135, 104, 0, 0), &IPNet{IP: IPv4(135, 104, 0, 0), Mask: IPv4Mask(255, 255, 255, 255)}, nil},
    321 	{"0.0.0.0/24", IPv4(0, 0, 0, 0), &IPNet{IP: IPv4(0, 0, 0, 0), Mask: IPv4Mask(255, 255, 255, 0)}, nil},
    322 	{"135.104.0.0/24", IPv4(135, 104, 0, 0), &IPNet{IP: IPv4(135, 104, 0, 0), Mask: IPv4Mask(255, 255, 255, 0)}, nil},
    323 	{"135.104.0.1/32", IPv4(135, 104, 0, 1), &IPNet{IP: IPv4(135, 104, 0, 1), Mask: IPv4Mask(255, 255, 255, 255)}, nil},
    324 	{"135.104.0.1/24", IPv4(135, 104, 0, 1), &IPNet{IP: IPv4(135, 104, 0, 0), Mask: IPv4Mask(255, 255, 255, 0)}, nil},
    325 	{"::1/128", ParseIP("::1"), &IPNet{IP: ParseIP("::1"), Mask: IPMask(ParseIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"))}, nil},
    326 	{"abcd:2345::/127", ParseIP("abcd:2345::"), &IPNet{IP: ParseIP("abcd:2345::"), Mask: IPMask(ParseIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe"))}, nil},
    327 	{"abcd:2345::/65", ParseIP("abcd:2345::"), &IPNet{IP: ParseIP("abcd:2345::"), Mask: IPMask(ParseIP("ffff:ffff:ffff:ffff:8000::"))}, nil},
    328 	{"abcd:2345::/64", ParseIP("abcd:2345::"), &IPNet{IP: ParseIP("abcd:2345::"), Mask: IPMask(ParseIP("ffff:ffff:ffff:ffff::"))}, nil},
    329 	{"abcd:2345::/63", ParseIP("abcd:2345::"), &IPNet{IP: ParseIP("abcd:2345::"), Mask: IPMask(ParseIP("ffff:ffff:ffff:fffe::"))}, nil},
    330 	{"abcd:2345::/33", ParseIP("abcd:2345::"), &IPNet{IP: ParseIP("abcd:2345::"), Mask: IPMask(ParseIP("ffff:ffff:8000::"))}, nil},
    331 	{"abcd:2345::/32", ParseIP("abcd:2345::"), &IPNet{IP: ParseIP("abcd:2345::"), Mask: IPMask(ParseIP("ffff:ffff::"))}, nil},
    332 	{"abcd:2344::/31", ParseIP("abcd:2344::"), &IPNet{IP: ParseIP("abcd:2344::"), Mask: IPMask(ParseIP("ffff:fffe::"))}, nil},
    333 	{"abcd:2300::/24", ParseIP("abcd:2300::"), &IPNet{IP: ParseIP("abcd:2300::"), Mask: IPMask(ParseIP("ffff:ff00::"))}, nil},
    334 	{"abcd:2345::/24", ParseIP("abcd:2345::"), &IPNet{IP: ParseIP("abcd:2300::"), Mask: IPMask(ParseIP("ffff:ff00::"))}, nil},
    335 	{"2001:DB8::/48", ParseIP("2001:DB8::"), &IPNet{IP: ParseIP("2001:DB8::"), Mask: IPMask(ParseIP("ffff:ffff:ffff::"))}, nil},
    336 	{"2001:DB8::1/48", ParseIP("2001:DB8::1"), &IPNet{IP: ParseIP("2001:DB8::"), Mask: IPMask(ParseIP("ffff:ffff:ffff::"))}, nil},
    337 	{"192.168.1.1/255.255.255.0", nil, nil, &ParseError{Type: "CIDR address", Text: "192.168.1.1/255.255.255.0"}},
    338 	{"192.168.1.1/35", nil, nil, &ParseError{Type: "CIDR address", Text: "192.168.1.1/35"}},
    339 	{"2001:db8::1/-1", nil, nil, &ParseError{Type: "CIDR address", Text: "2001:db8::1/-1"}},
    340 	{"2001:db8::1/-0", nil, nil, &ParseError{Type: "CIDR address", Text: "2001:db8::1/-0"}},
    341 	{"-0.0.0.0/32", nil, nil, &ParseError{Type: "CIDR address", Text: "-0.0.0.0/32"}},
    342 	{"0.-1.0.0/32", nil, nil, &ParseError{Type: "CIDR address", Text: "0.-1.0.0/32"}},
    343 	{"0.0.-2.0/32", nil, nil, &ParseError{Type: "CIDR address", Text: "0.0.-2.0/32"}},
    344 	{"0.0.0.-3/32", nil, nil, &ParseError{Type: "CIDR address", Text: "0.0.0.-3/32"}},
    345 	{"0.0.0.0/-0", nil, nil, &ParseError{Type: "CIDR address", Text: "0.0.0.0/-0"}},
    346 	{"", nil, nil, &ParseError{Type: "CIDR address", Text: ""}},
    347 }
    348 
    349 func TestParseCIDR(t *testing.T) {
    350 	for _, tt := range parseCIDRTests {
    351 		ip, net, err := ParseCIDR(tt.in)
    352 		if !reflect.DeepEqual(err, tt.err) {
    353 			t.Errorf("ParseCIDR(%q) = %v, %v; want %v, %v", tt.in, ip, net, tt.ip, tt.net)
    354 		}
    355 		if err == nil && (!tt.ip.Equal(ip) || !tt.net.IP.Equal(net.IP) || !reflect.DeepEqual(net.Mask, tt.net.Mask)) {
    356 			t.Errorf("ParseCIDR(%q) = %v, {%v, %v}; want %v, {%v, %v}", tt.in, ip, net.IP, net.Mask, tt.ip, tt.net.IP, tt.net.Mask)
    357 		}
    358 	}
    359 }
    360 
    361 var ipNetContainsTests = []struct {
    362 	ip  IP
    363 	net *IPNet
    364 	ok  bool
    365 }{
    366 	{IPv4(172, 16, 1, 1), &IPNet{IP: IPv4(172, 16, 0, 0), Mask: CIDRMask(12, 32)}, true},
    367 	{IPv4(172, 24, 0, 1), &IPNet{IP: IPv4(172, 16, 0, 0), Mask: CIDRMask(13, 32)}, false},
    368 	{IPv4(192, 168, 0, 3), &IPNet{IP: IPv4(192, 168, 0, 0), Mask: IPv4Mask(0, 0, 255, 252)}, true},
    369 	{IPv4(192, 168, 0, 4), &IPNet{IP: IPv4(192, 168, 0, 0), Mask: IPv4Mask(0, 255, 0, 252)}, false},
    370 	{ParseIP("2001:db8:1:2::1"), &IPNet{IP: ParseIP("2001:db8:1::"), Mask: CIDRMask(47, 128)}, true},
    371 	{ParseIP("2001:db8:1:2::1"), &IPNet{IP: ParseIP("2001:db8:2::"), Mask: CIDRMask(47, 128)}, false},
    372 	{ParseIP("2001:db8:1:2::1"), &IPNet{IP: ParseIP("2001:db8:1::"), Mask: IPMask(ParseIP("ffff:0:ffff::"))}, true},
    373 	{ParseIP("2001:db8:1:2::1"), &IPNet{IP: ParseIP("2001:db8:1::"), Mask: IPMask(ParseIP("0:0:0:ffff::"))}, false},
    374 }
    375 
    376 func TestIPNetContains(t *testing.T) {
    377 	for _, tt := range ipNetContainsTests {
    378 		if ok := tt.net.Contains(tt.ip); ok != tt.ok {
    379 			t.Errorf("IPNet(%v).Contains(%v) = %v, want %v", tt.net, tt.ip, ok, tt.ok)
    380 		}
    381 	}
    382 }
    383 
    384 var ipNetStringTests = []struct {
    385 	in  *IPNet
    386 	out string
    387 }{
    388 	{&IPNet{IP: IPv4(192, 168, 1, 0), Mask: CIDRMask(26, 32)}, "192.168.1.0/26"},
    389 	{&IPNet{IP: IPv4(192, 168, 1, 0), Mask: IPv4Mask(255, 0, 255, 0)}, "192.168.1.0/ff00ff00"},
    390 	{&IPNet{IP: ParseIP("2001:db8::"), Mask: CIDRMask(55, 128)}, "2001:db8::/55"},
    391 	{&IPNet{IP: ParseIP("2001:db8::"), Mask: IPMask(ParseIP("8000:f123:0:cafe::"))}, "2001:db8::/8000f1230000cafe0000000000000000"},
    392 }
    393 
    394 func TestIPNetString(t *testing.T) {
    395 	for _, tt := range ipNetStringTests {
    396 		if out := tt.in.String(); out != tt.out {
    397 			t.Errorf("IPNet.String(%v) = %q, want %q", tt.in, out, tt.out)
    398 		}
    399 	}
    400 }
    401 
    402 var cidrMaskTests = []struct {
    403 	ones int
    404 	bits int
    405 	out  IPMask
    406 }{
    407 	{0, 32, IPv4Mask(0, 0, 0, 0)},
    408 	{12, 32, IPv4Mask(255, 240, 0, 0)},
    409 	{24, 32, IPv4Mask(255, 255, 255, 0)},
    410 	{32, 32, IPv4Mask(255, 255, 255, 255)},
    411 	{0, 128, IPMask{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
    412 	{4, 128, IPMask{0xf0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
    413 	{48, 128, IPMask{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
    414 	{128, 128, IPMask{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}},
    415 	{33, 32, nil},
    416 	{32, 33, nil},
    417 	{-1, 128, nil},
    418 	{128, -1, nil},
    419 }
    420 
    421 func TestCIDRMask(t *testing.T) {
    422 	for _, tt := range cidrMaskTests {
    423 		if out := CIDRMask(tt.ones, tt.bits); !reflect.DeepEqual(out, tt.out) {
    424 			t.Errorf("CIDRMask(%v, %v) = %v, want %v", tt.ones, tt.bits, out, tt.out)
    425 		}
    426 	}
    427 }
    428 
    429 var (
    430 	v4addr         = IP{192, 168, 0, 1}
    431 	v4mappedv6addr = IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 192, 168, 0, 1}
    432 	v6addr         = IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0x1, 0x23, 0, 0x12, 0, 0x1}
    433 	v4mask         = IPMask{255, 255, 255, 0}
    434 	v4mappedv6mask = IPMask{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 255, 255, 255, 0}
    435 	v6mask         = IPMask{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0}
    436 	badaddr        = IP{192, 168, 0}
    437 	badmask        = IPMask{255, 255, 0}
    438 	v4maskzero     = IPMask{0, 0, 0, 0}
    439 )
    440 
    441 var networkNumberAndMaskTests = []struct {
    442 	in  IPNet
    443 	out IPNet
    444 }{
    445 	{IPNet{IP: v4addr, Mask: v4mask}, IPNet{IP: v4addr, Mask: v4mask}},
    446 	{IPNet{IP: v4addr, Mask: v4mappedv6mask}, IPNet{IP: v4addr, Mask: v4mask}},
    447 	{IPNet{IP: v4mappedv6addr, Mask: v4mappedv6mask}, IPNet{IP: v4addr, Mask: v4mask}},
    448 	{IPNet{IP: v4mappedv6addr, Mask: v6mask}, IPNet{IP: v4addr, Mask: v4maskzero}},
    449 	{IPNet{IP: v4addr, Mask: v6mask}, IPNet{IP: v4addr, Mask: v4maskzero}},
    450 	{IPNet{IP: v6addr, Mask: v6mask}, IPNet{IP: v6addr, Mask: v6mask}},
    451 	{IPNet{IP: v6addr, Mask: v4mappedv6mask}, IPNet{IP: v6addr, Mask: v4mappedv6mask}},
    452 	{in: IPNet{IP: v6addr, Mask: v4mask}},
    453 	{in: IPNet{IP: v4addr, Mask: badmask}},
    454 	{in: IPNet{IP: v4mappedv6addr, Mask: badmask}},
    455 	{in: IPNet{IP: v6addr, Mask: badmask}},
    456 	{in: IPNet{IP: badaddr, Mask: v4mask}},
    457 	{in: IPNet{IP: badaddr, Mask: v4mappedv6mask}},
    458 	{in: IPNet{IP: badaddr, Mask: v6mask}},
    459 	{in: IPNet{IP: badaddr, Mask: badmask}},
    460 }
    461 
    462 func TestNetworkNumberAndMask(t *testing.T) {
    463 	for _, tt := range networkNumberAndMaskTests {
    464 		ip, m := networkNumberAndMask(&tt.in)
    465 		out := &IPNet{IP: ip, Mask: m}
    466 		if !reflect.DeepEqual(&tt.out, out) {
    467 			t.Errorf("networkNumberAndMask(%v) = %v, want %v", tt.in, out, &tt.out)
    468 		}
    469 	}
    470 }
    471 
    472 func TestSplitHostPort(t *testing.T) {
    473 	for _, tt := range []struct {
    474 		hostPort string
    475 		host     string
    476 		port     string
    477 	}{
    478 		// Host name
    479 		{"localhost:http", "localhost", "http"},
    480 		{"localhost:80", "localhost", "80"},
    481 
    482 		// Go-specific host name with zone identifier
    483 		{"localhost%lo0:http", "localhost%lo0", "http"},
    484 		{"localhost%lo0:80", "localhost%lo0", "80"},
    485 		{"[localhost%lo0]:http", "localhost%lo0", "http"}, // Go 1 behavior
    486 		{"[localhost%lo0]:80", "localhost%lo0", "80"},     // Go 1 behavior
    487 
    488 		// IP literal
    489 		{"127.0.0.1:http", "127.0.0.1", "http"},
    490 		{"127.0.0.1:80", "127.0.0.1", "80"},
    491 		{"[::1]:http", "::1", "http"},
    492 		{"[::1]:80", "::1", "80"},
    493 
    494 		// IP literal with zone identifier
    495 		{"[::1%lo0]:http", "::1%lo0", "http"},
    496 		{"[::1%lo0]:80", "::1%lo0", "80"},
    497 
    498 		// Go-specific wildcard for host name
    499 		{":http", "", "http"}, // Go 1 behavior
    500 		{":80", "", "80"},     // Go 1 behavior
    501 
    502 		// Go-specific wildcard for service name or transport port number
    503 		{"golang.org:", "golang.org", ""}, // Go 1 behavior
    504 		{"127.0.0.1:", "127.0.0.1", ""},   // Go 1 behavior
    505 		{"[::1]:", "::1", ""},             // Go 1 behavior
    506 
    507 		// Opaque service name
    508 		{"golang.org:https%foo", "golang.org", "https%foo"}, // Go 1 behavior
    509 	} {
    510 		if host, port, err := SplitHostPort(tt.hostPort); host != tt.host || port != tt.port || err != nil {
    511 			t.Errorf("SplitHostPort(%q) = %q, %q, %v; want %q, %q, nil", tt.hostPort, host, port, err, tt.host, tt.port)
    512 		}
    513 	}
    514 
    515 	for _, tt := range []struct {
    516 		hostPort string
    517 		err      string
    518 	}{
    519 		{"golang.org", "missing port in address"},
    520 		{"127.0.0.1", "missing port in address"},
    521 		{"[::1]", "missing port in address"},
    522 		{"[fe80::1%lo0]", "missing port in address"},
    523 		{"[localhost%lo0]", "missing port in address"},
    524 		{"localhost%lo0", "missing port in address"},
    525 
    526 		{"::1", "too many colons in address"},
    527 		{"fe80::1%lo0", "too many colons in address"},
    528 		{"fe80::1%lo0:80", "too many colons in address"},
    529 
    530 		// Test cases that didn't fail in Go 1
    531 
    532 		{"[foo:bar]", "missing port in address"},
    533 		{"[foo:bar]baz", "missing port in address"},
    534 		{"[foo]bar:baz", "missing port in address"},
    535 
    536 		{"[foo]:[bar]:baz", "too many colons in address"},
    537 
    538 		{"[foo]:[bar]baz", "unexpected '[' in address"},
    539 		{"foo[bar]:baz", "unexpected '[' in address"},
    540 
    541 		{"foo]bar:baz", "unexpected ']' in address"},
    542 	} {
    543 		if host, port, err := SplitHostPort(tt.hostPort); err == nil {
    544 			t.Errorf("SplitHostPort(%q) should have failed", tt.hostPort)
    545 		} else {
    546 			e := err.(*AddrError)
    547 			if e.Err != tt.err {
    548 				t.Errorf("SplitHostPort(%q) = _, _, %q; want %q", tt.hostPort, e.Err, tt.err)
    549 			}
    550 			if host != "" || port != "" {
    551 				t.Errorf("SplitHostPort(%q) = %q, %q, err; want %q, %q, err on failure", tt.hostPort, host, port, "", "")
    552 			}
    553 		}
    554 	}
    555 }
    556 
    557 func TestJoinHostPort(t *testing.T) {
    558 	for _, tt := range []struct {
    559 		host     string
    560 		port     string
    561 		hostPort string
    562 	}{
    563 		// Host name
    564 		{"localhost", "http", "localhost:http"},
    565 		{"localhost", "80", "localhost:80"},
    566 
    567 		// Go-specific host name with zone identifier
    568 		{"localhost%lo0", "http", "localhost%lo0:http"},
    569 		{"localhost%lo0", "80", "localhost%lo0:80"},
    570 
    571 		// IP literal
    572 		{"127.0.0.1", "http", "127.0.0.1:http"},
    573 		{"127.0.0.1", "80", "127.0.0.1:80"},
    574 		{"::1", "http", "[::1]:http"},
    575 		{"::1", "80", "[::1]:80"},
    576 
    577 		// IP literal with zone identifier
    578 		{"::1%lo0", "http", "[::1%lo0]:http"},
    579 		{"::1%lo0", "80", "[::1%lo0]:80"},
    580 
    581 		// Go-specific wildcard for host name
    582 		{"", "http", ":http"}, // Go 1 behavior
    583 		{"", "80", ":80"},     // Go 1 behavior
    584 
    585 		// Go-specific wildcard for service name or transport port number
    586 		{"golang.org", "", "golang.org:"}, // Go 1 behavior
    587 		{"127.0.0.1", "", "127.0.0.1:"},   // Go 1 behavior
    588 		{"::1", "", "[::1]:"},             // Go 1 behavior
    589 
    590 		// Opaque service name
    591 		{"golang.org", "https%foo", "golang.org:https%foo"}, // Go 1 behavior
    592 	} {
    593 		if hostPort := JoinHostPort(tt.host, tt.port); hostPort != tt.hostPort {
    594 			t.Errorf("JoinHostPort(%q, %q) = %q; want %q", tt.host, tt.port, hostPort, tt.hostPort)
    595 		}
    596 	}
    597 }
    598 
    599 var ipAddrFamilyTests = []struct {
    600 	in  IP
    601 	af4 bool
    602 	af6 bool
    603 }{
    604 	{IPv4bcast, true, false},
    605 	{IPv4allsys, true, false},
    606 	{IPv4allrouter, true, false},
    607 	{IPv4zero, true, false},
    608 	{IPv4(224, 0, 0, 1), true, false},
    609 	{IPv4(127, 0, 0, 1), true, false},
    610 	{IPv4(240, 0, 0, 1), true, false},
    611 	{IPv6unspecified, false, true},
    612 	{IPv6loopback, false, true},
    613 	{IPv6interfacelocalallnodes, false, true},
    614 	{IPv6linklocalallnodes, false, true},
    615 	{IPv6linklocalallrouters, false, true},
    616 	{ParseIP("ff05::a:b:c:d"), false, true},
    617 	{ParseIP("fe80::1:2:3:4"), false, true},
    618 	{ParseIP("2001:db8::123:12:1"), false, true},
    619 }
    620 
    621 func TestIPAddrFamily(t *testing.T) {
    622 	for _, tt := range ipAddrFamilyTests {
    623 		if af := tt.in.To4() != nil; af != tt.af4 {
    624 			t.Errorf("verifying IPv4 address family for %q = %v, want %v", tt.in, af, tt.af4)
    625 		}
    626 		if af := len(tt.in) == IPv6len && tt.in.To4() == nil; af != tt.af6 {
    627 			t.Errorf("verifying IPv6 address family for %q = %v, want %v", tt.in, af, tt.af6)
    628 		}
    629 	}
    630 }
    631 
    632 var ipAddrScopeTests = []struct {
    633 	scope func(IP) bool
    634 	in    IP
    635 	ok    bool
    636 }{
    637 	{IP.IsUnspecified, IPv4zero, true},
    638 	{IP.IsUnspecified, IPv4(127, 0, 0, 1), false},
    639 	{IP.IsUnspecified, IPv6unspecified, true},
    640 	{IP.IsUnspecified, IPv6interfacelocalallnodes, false},
    641 	{IP.IsUnspecified, nil, false},
    642 	{IP.IsLoopback, IPv4(127, 0, 0, 1), true},
    643 	{IP.IsLoopback, IPv4(127, 255, 255, 254), true},
    644 	{IP.IsLoopback, IPv4(128, 1, 2, 3), false},
    645 	{IP.IsLoopback, IPv6loopback, true},
    646 	{IP.IsLoopback, IPv6linklocalallrouters, false},
    647 	{IP.IsLoopback, nil, false},
    648 	{IP.IsMulticast, IPv4(224, 0, 0, 0), true},
    649 	{IP.IsMulticast, IPv4(239, 0, 0, 0), true},
    650 	{IP.IsMulticast, IPv4(240, 0, 0, 0), false},
    651 	{IP.IsMulticast, IPv6linklocalallnodes, true},
    652 	{IP.IsMulticast, IP{0xff, 0x05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, true},
    653 	{IP.IsMulticast, IP{0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false},
    654 	{IP.IsMulticast, nil, false},
    655 	{IP.IsInterfaceLocalMulticast, IPv4(224, 0, 0, 0), false},
    656 	{IP.IsInterfaceLocalMulticast, IPv4(0xff, 0x01, 0, 0), false},
    657 	{IP.IsInterfaceLocalMulticast, IPv6interfacelocalallnodes, true},
    658 	{IP.IsInterfaceLocalMulticast, nil, false},
    659 	{IP.IsLinkLocalMulticast, IPv4(224, 0, 0, 0), true},
    660 	{IP.IsLinkLocalMulticast, IPv4(239, 0, 0, 0), false},
    661 	{IP.IsLinkLocalMulticast, IPv4(0xff, 0x02, 0, 0), false},
    662 	{IP.IsLinkLocalMulticast, IPv6linklocalallrouters, true},
    663 	{IP.IsLinkLocalMulticast, IP{0xff, 0x05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false},
    664 	{IP.IsLinkLocalMulticast, nil, false},
    665 	{IP.IsLinkLocalUnicast, IPv4(169, 254, 0, 0), true},
    666 	{IP.IsLinkLocalUnicast, IPv4(169, 255, 0, 0), false},
    667 	{IP.IsLinkLocalUnicast, IPv4(0xfe, 0x80, 0, 0), false},
    668 	{IP.IsLinkLocalUnicast, IP{0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, true},
    669 	{IP.IsLinkLocalUnicast, IP{0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false},
    670 	{IP.IsLinkLocalUnicast, nil, false},
    671 	{IP.IsGlobalUnicast, IPv4(240, 0, 0, 0), true},
    672 	{IP.IsGlobalUnicast, IPv4(232, 0, 0, 0), false},
    673 	{IP.IsGlobalUnicast, IPv4(169, 254, 0, 0), false},
    674 	{IP.IsGlobalUnicast, IPv4bcast, false},
    675 	{IP.IsGlobalUnicast, IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0x1, 0x23, 0, 0x12, 0, 0x1}, true},
    676 	{IP.IsGlobalUnicast, IP{0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false},
    677 	{IP.IsGlobalUnicast, IP{0xff, 0x05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false},
    678 	{IP.IsGlobalUnicast, nil, false},
    679 }
    680 
    681 func name(f interface{}) string {
    682 	return runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name()
    683 }
    684 
    685 func TestIPAddrScope(t *testing.T) {
    686 	for _, tt := range ipAddrScopeTests {
    687 		if ok := tt.scope(tt.in); ok != tt.ok {
    688 			t.Errorf("%s(%q) = %v, want %v", name(tt.scope), tt.in, ok, tt.ok)
    689 		}
    690 		ip := tt.in.To4()
    691 		if ip == nil {
    692 			continue
    693 		}
    694 		if ok := tt.scope(ip); ok != tt.ok {
    695 			t.Errorf("%s(%q) = %v, want %v", name(tt.scope), ip, ok, tt.ok)
    696 		}
    697 	}
    698 }
    699 
    700 func BenchmarkIPEqual(b *testing.B) {
    701 	b.Run("IPv4", func(b *testing.B) {
    702 		benchmarkIPEqual(b, IPv4len)
    703 	})
    704 	b.Run("IPv6", func(b *testing.B) {
    705 		benchmarkIPEqual(b, IPv6len)
    706 	})
    707 }
    708 
    709 func benchmarkIPEqual(b *testing.B, size int) {
    710 	ips := make([]IP, 1000)
    711 	for i := range ips {
    712 		ips[i] = make(IP, size)
    713 		rand.Read(ips[i])
    714 	}
    715 	// Half of the N are equal.
    716 	for i := 0; i < b.N/2; i++ {
    717 		x := ips[i%len(ips)]
    718 		y := ips[i%len(ips)]
    719 		x.Equal(y)
    720 	}
    721 	// The other half are not equal.
    722 	for i := 0; i < b.N/2; i++ {
    723 		x := ips[i%len(ips)]
    724 		y := ips[(i+1)%len(ips)]
    725 		x.Equal(y)
    726 	}
    727 }
    728