...

Source file src/net/ip_test.go

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

View as plain text