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.
14 func isEqual(a
, b
[]byte) bool {
15 if a
== nil && b
== nil {
18 if a
== nil || b
== nil {
21 return bytes
.Equal(a
, b
)
24 var parseiptests
= []struct {
28 {"127.0.1.2", IPv4(127, 0, 1, 2)},
29 {"127.0.0.1", IPv4(127, 0, 0, 1)},
33 {"::ffff:127.0.0.1", IPv4(127, 0, 0, 1)},
34 {"2001:4860:0:2001::68", IP
{0x20, 0x01, 0x48, 0x60, 0, 0, 0x20, 0x01, 0, 0, 0, 0, 0, 0, 0x00, 0x68}},
35 {"::ffff:4a7d:1363", IPv4(74, 125, 19, 99)},
39 func TestParseIP(t
*testing
.T
) {
40 for _
, tt
:= range parseiptests
{
41 if out
:= ParseIP(tt
.in
); !isEqual(out
, tt
.out
) {
42 t
.Errorf("ParseIP(%q) = %v, want %v", tt
.in
, out
, tt
.out
)
47 var ipstringtests
= []struct {
51 // cf. RFC 5952 (A Recommendation for IPv6 Address Text Representation)
52 {IP
{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0x1, 0x23, 0, 0x12, 0, 0x1}, "2001:db8::123:12:1"},
53 {IP
{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1}, "2001:db8::1"},
54 {IP
{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0x1, 0, 0, 0, 0x1, 0, 0, 0, 0x1}, "2001:db8:0:1:0:1:0:1"},
55 {IP
{0x20, 0x1, 0xd, 0xb8, 0, 0x1, 0, 0, 0, 0x1, 0, 0, 0, 0x1, 0, 0}, "2001:db8:1:0:1:0:1:0"},
56 {IP
{0x20, 0x1, 0, 0, 0, 0, 0, 0, 0, 0x1, 0, 0, 0, 0, 0, 0x1}, "2001::1:0:0:1"},
57 {IP
{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0x1, 0, 0, 0, 0, 0, 0}, "2001:db8:0:0:1::"},
58 {IP
{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0x1, 0, 0, 0, 0, 0, 0x1}, "2001:db8::1:0:0:1"},
59 {IP
{0x20, 0x1, 0xD, 0xB8, 0, 0, 0, 0, 0, 0xA, 0, 0xB, 0, 0xC, 0, 0xD}, "2001:db8::a:b:c:d"},
63 func TestIPString(t
*testing
.T
) {
64 for _
, tt
:= range ipstringtests
{
65 if out
:= tt
.in
.String(); out
!= tt
.out
{
66 t
.Errorf("IP.String(%v) = %q, want %q", tt
.in
, out
, tt
.out
)
71 var ipmasktests
= []struct {
76 {IPv4(192, 168, 1, 127), IPv4Mask(255, 255, 255, 128), IPv4(192, 168, 1, 0)},
77 {IPv4(192, 168, 1, 127), IPMask(ParseIP("255.255.255.192")), IPv4(192, 168, 1, 64)},
78 {IPv4(192, 168, 1, 127), IPMask(ParseIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffe0")), IPv4(192, 168, 1, 96)},
79 {IPv4(192, 168, 1, 127), IPv4Mask(255, 0, 255, 0), IPv4(192, 0, 1, 0)},
80 {ParseIP("2001:db8::1"), IPMask(ParseIP("ffff:ff80::")), ParseIP("2001:d80::")},
81 {ParseIP("2001:db8::1"), IPMask(ParseIP("f0f0:0f0f::")), ParseIP("2000:d08::")},
84 func TestIPMask(t
*testing
.T
) {
85 for _
, tt
:= range ipmasktests
{
86 if out
:= tt
.in
.Mask(tt
.mask
); out
== nil ||
!tt
.out
.Equal(out
) {
87 t
.Errorf("IP(%v).Mask(%v) = %v, want %v", tt
.in
, tt
.mask
, out
, tt
.out
)
92 var ipmaskstringtests
= []struct {
96 {IPv4Mask(255, 255, 255, 240), "fffffff0"},
97 {IPv4Mask(255, 0, 128, 0), "ff008000"},
98 {IPMask(ParseIP("ffff:ff80::")), "ffffff80000000000000000000000000"},
99 {IPMask(ParseIP("ef00:ff80::cafe:0")), "ef00ff800000000000000000cafe0000"},
103 func TestIPMaskString(t
*testing
.T
) {
104 for _
, tt
:= range ipmaskstringtests
{
105 if out
:= tt
.in
.String(); out
!= tt
.out
{
106 t
.Errorf("IPMask.String(%v) = %q, want %q", tt
.in
, out
, tt
.out
)
111 var parsecidrtests
= []struct {
117 {"135.104.0.0/32", IPv4(135, 104, 0, 0), &IPNet
{IP
: IPv4(135, 104, 0, 0), Mask
: IPv4Mask(255, 255, 255, 255)}, nil},
118 {"0.0.0.0/24", IPv4(0, 0, 0, 0), &IPNet
{IP
: IPv4(0, 0, 0, 0), Mask
: IPv4Mask(255, 255, 255, 0)}, nil},
119 {"135.104.0.0/24", IPv4(135, 104, 0, 0), &IPNet
{IP
: IPv4(135, 104, 0, 0), Mask
: IPv4Mask(255, 255, 255, 0)}, nil},
120 {"135.104.0.1/32", IPv4(135, 104, 0, 1), &IPNet
{IP
: IPv4(135, 104, 0, 1), Mask
: IPv4Mask(255, 255, 255, 255)}, nil},
121 {"135.104.0.1/24", IPv4(135, 104, 0, 1), &IPNet
{IP
: IPv4(135, 104, 0, 0), Mask
: IPv4Mask(255, 255, 255, 0)}, nil},
122 {"::1/128", ParseIP("::1"), &IPNet
{IP
: ParseIP("::1"), Mask
: IPMask(ParseIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"))}, nil},
123 {"abcd:2345::/127", ParseIP("abcd:2345::"), &IPNet
{IP
: ParseIP("abcd:2345::"), Mask
: IPMask(ParseIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe"))}, nil},
124 {"abcd:2345::/65", ParseIP("abcd:2345::"), &IPNet
{IP
: ParseIP("abcd:2345::"), Mask
: IPMask(ParseIP("ffff:ffff:ffff:ffff:8000::"))}, nil},
125 {"abcd:2345::/64", ParseIP("abcd:2345::"), &IPNet
{IP
: ParseIP("abcd:2345::"), Mask
: IPMask(ParseIP("ffff:ffff:ffff:ffff::"))}, nil},
126 {"abcd:2345::/63", ParseIP("abcd:2345::"), &IPNet
{IP
: ParseIP("abcd:2345::"), Mask
: IPMask(ParseIP("ffff:ffff:ffff:fffe::"))}, nil},
127 {"abcd:2345::/33", ParseIP("abcd:2345::"), &IPNet
{IP
: ParseIP("abcd:2345::"), Mask
: IPMask(ParseIP("ffff:ffff:8000::"))}, nil},
128 {"abcd:2345::/32", ParseIP("abcd:2345::"), &IPNet
{IP
: ParseIP("abcd:2345::"), Mask
: IPMask(ParseIP("ffff:ffff::"))}, nil},
129 {"abcd:2344::/31", ParseIP("abcd:2344::"), &IPNet
{IP
: ParseIP("abcd:2344::"), Mask
: IPMask(ParseIP("ffff:fffe::"))}, nil},
130 {"abcd:2300::/24", ParseIP("abcd:2300::"), &IPNet
{IP
: ParseIP("abcd:2300::"), Mask
: IPMask(ParseIP("ffff:ff00::"))}, nil},
131 {"abcd:2345::/24", ParseIP("abcd:2345::"), &IPNet
{IP
: ParseIP("abcd:2300::"), Mask
: IPMask(ParseIP("ffff:ff00::"))}, nil},
132 {"2001:DB8::/48", ParseIP("2001:DB8::"), &IPNet
{IP
: ParseIP("2001:DB8::"), Mask
: IPMask(ParseIP("ffff:ffff:ffff::"))}, nil},
133 {"2001:DB8::1/48", ParseIP("2001:DB8::1"), &IPNet
{IP
: ParseIP("2001:DB8::"), Mask
: IPMask(ParseIP("ffff:ffff:ffff::"))}, nil},
134 {"192.168.1.1/255.255.255.0", nil, nil, &ParseError
{"CIDR address", "192.168.1.1/255.255.255.0"}},
135 {"192.168.1.1/35", nil, nil, &ParseError
{"CIDR address", "192.168.1.1/35"}},
136 {"2001:db8::1/-1", nil, nil, &ParseError
{"CIDR address", "2001:db8::1/-1"}},
137 {"", nil, nil, &ParseError
{"CIDR address", ""}},
140 func TestParseCIDR(t
*testing
.T
) {
141 for _
, tt
:= range parsecidrtests
{
142 ip
, net
, err
:= ParseCIDR(tt
.in
)
143 if !reflect
.DeepEqual(err
, tt
.err
) {
144 t
.Errorf("ParseCIDR(%q) = %v, %v; want %v, %v", tt
.in
, ip
, net
, tt
.ip
, tt
.net
)
146 if err
== nil && (!tt
.ip
.Equal(ip
) ||
!tt
.net
.IP
.Equal(net
.IP
) ||
!isEqual(net
.Mask
, tt
.net
.Mask
)) {
147 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
)
152 var ipnetcontainstests
= []struct {
157 {IPv4(172, 16, 1, 1), &IPNet
{IP
: IPv4(172, 16, 0, 0), Mask
: CIDRMask(12, 32)}, true},
158 {IPv4(172, 24, 0, 1), &IPNet
{IP
: IPv4(172, 16, 0, 0), Mask
: CIDRMask(13, 32)}, false},
159 {IPv4(192, 168, 0, 3), &IPNet
{IP
: IPv4(192, 168, 0, 0), Mask
: IPv4Mask(0, 0, 255, 252)}, true},
160 {IPv4(192, 168, 0, 4), &IPNet
{IP
: IPv4(192, 168, 0, 0), Mask
: IPv4Mask(0, 255, 0, 252)}, false},
161 {ParseIP("2001:db8:1:2::1"), &IPNet
{IP
: ParseIP("2001:db8:1::"), Mask
: CIDRMask(47, 128)}, true},
162 {ParseIP("2001:db8:1:2::1"), &IPNet
{IP
: ParseIP("2001:db8:2::"), Mask
: CIDRMask(47, 128)}, false},
163 {ParseIP("2001:db8:1:2::1"), &IPNet
{IP
: ParseIP("2001:db8:1::"), Mask
: IPMask(ParseIP("ffff:0:ffff::"))}, true},
164 {ParseIP("2001:db8:1:2::1"), &IPNet
{IP
: ParseIP("2001:db8:1::"), Mask
: IPMask(ParseIP("0:0:0:ffff::"))}, false},
167 func TestIPNetContains(t
*testing
.T
) {
168 for _
, tt
:= range ipnetcontainstests
{
169 if ok
:= tt
.net
.Contains(tt
.ip
); ok
!= tt
.ok
{
170 t
.Errorf("IPNet(%v).Contains(%v) = %v, want %v", tt
.net
, tt
.ip
, ok
, tt
.ok
)
175 var ipnetstringtests
= []struct {
179 {&IPNet
{IP
: IPv4(192, 168, 1, 0), Mask
: CIDRMask(26, 32)}, "192.168.1.0/26"},
180 {&IPNet
{IP
: IPv4(192, 168, 1, 0), Mask
: IPv4Mask(255, 0, 255, 0)}, "192.168.1.0/ff00ff00"},
181 {&IPNet
{IP
: ParseIP("2001:db8::"), Mask
: CIDRMask(55, 128)}, "2001:db8::/55"},
182 {&IPNet
{IP
: ParseIP("2001:db8::"), Mask
: IPMask(ParseIP("8000:f123:0:cafe::"))}, "2001:db8::/8000f1230000cafe0000000000000000"},
185 func TestIPNetString(t
*testing
.T
) {
186 for _
, tt
:= range ipnetstringtests
{
187 if out
:= tt
.in
.String(); out
!= tt
.out
{
188 t
.Errorf("IPNet.String(%v) = %q, want %q", tt
.in
, out
, tt
.out
)
193 var cidrmasktests
= []struct {
198 {0, 32, IPv4Mask(0, 0, 0, 0)},
199 {12, 32, IPv4Mask(255, 240, 0, 0)},
200 {24, 32, IPv4Mask(255, 255, 255, 0)},
201 {32, 32, IPv4Mask(255, 255, 255, 255)},
202 {0, 128, IPMask
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
203 {4, 128, IPMask
{0xf0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
204 {48, 128, IPMask
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
205 {128, 128, IPMask
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}},
212 func TestCIDRMask(t
*testing
.T
) {
213 for _
, tt
:= range cidrmasktests
{
214 if out
:= CIDRMask(tt
.ones
, tt
.bits
); !isEqual(out
, tt
.out
) {
215 t
.Errorf("CIDRMask(%v, %v) = %v, want %v", tt
.ones
, tt
.bits
, out
, tt
.out
)
221 v4addr
= IP
{192, 168, 0, 1}
222 v4mappedv6addr
= IP
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 192, 168, 0, 1}
223 v6addr
= IP
{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0x1, 0x23, 0, 0x12, 0, 0x1}
224 v4mask
= IPMask
{255, 255, 255, 0}
225 v4mappedv6mask
= IPMask
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 255, 255, 255, 0}
226 v6mask
= IPMask
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0}
227 badaddr
= IP
{192, 168, 0}
228 badmask
= IPMask
{255, 255, 0}
229 v4maskzero
= IPMask
{0, 0, 0, 0}
232 var networknumberandmasktests
= []struct {
236 {IPNet
{IP
: v4addr
, Mask
: v4mask
}, IPNet
{IP
: v4addr
, Mask
: v4mask
}},
237 {IPNet
{IP
: v4addr
, Mask
: v4mappedv6mask
}, IPNet
{IP
: v4addr
, Mask
: v4mask
}},
238 {IPNet
{IP
: v4mappedv6addr
, Mask
: v4mappedv6mask
}, IPNet
{IP
: v4addr
, Mask
: v4mask
}},
239 {IPNet
{IP
: v4mappedv6addr
, Mask
: v6mask
}, IPNet
{IP
: v4addr
, Mask
: v4maskzero
}},
240 {IPNet
{IP
: v4addr
, Mask
: v6mask
}, IPNet
{IP
: v4addr
, Mask
: v4maskzero
}},
241 {IPNet
{IP
: v6addr
, Mask
: v6mask
}, IPNet
{IP
: v6addr
, Mask
: v6mask
}},
242 {IPNet
{IP
: v6addr
, Mask
: v4mappedv6mask
}, IPNet
{IP
: v6addr
, Mask
: v4mappedv6mask
}},
243 {in
: IPNet
{IP
: v6addr
, Mask
: v4mask
}},
244 {in
: IPNet
{IP
: v4addr
, Mask
: badmask
}},
245 {in
: IPNet
{IP
: v4mappedv6addr
, Mask
: badmask
}},
246 {in
: IPNet
{IP
: v6addr
, Mask
: badmask
}},
247 {in
: IPNet
{IP
: badaddr
, Mask
: v4mask
}},
248 {in
: IPNet
{IP
: badaddr
, Mask
: v4mappedv6mask
}},
249 {in
: IPNet
{IP
: badaddr
, Mask
: v6mask
}},
250 {in
: IPNet
{IP
: badaddr
, Mask
: badmask
}},
253 func TestNetworkNumberAndMask(t
*testing
.T
) {
254 for _
, tt
:= range networknumberandmasktests
{
255 ip
, m
:= networkNumberAndMask(&tt
.in
)
256 out
:= &IPNet
{IP
: ip
, Mask
: m
}
257 if !reflect
.DeepEqual(&tt
.out
, out
) {
258 t
.Errorf("networkNumberAndMask(%v) = %v; want %v", tt
.in
, out
, &tt
.out
)
263 var splitjointests
= []struct {
268 {"www.google.com", "80", "www.google.com:80"},
269 {"127.0.0.1", "1234", "127.0.0.1:1234"},
270 {"::1", "80", "[::1]:80"},
271 {"google.com", "https%foo", "google.com:https%foo"}, // Go 1.0 behavior
274 func TestSplitHostPort(t
*testing
.T
) {
275 for _
, tt
:= range splitjointests
{
276 if host
, port
, err
:= SplitHostPort(tt
.Join
); host
!= tt
.Host || port
!= tt
.Port || err
!= nil {
277 t
.Errorf("SplitHostPort(%q) = %q, %q, %v; want %q, %q, nil", tt
.Join
, host
, port
, err
, tt
.Host
, tt
.Port
)
282 func TestJoinHostPort(t
*testing
.T
) {
283 for _
, tt
:= range splitjointests
{
284 if join
:= JoinHostPort(tt
.Host
, tt
.Port
); join
!= tt
.Join
{
285 t
.Errorf("JoinHostPort(%q, %q) = %q; want %q", tt
.Host
, tt
.Port
, join
, tt
.Join
)
290 var ipaftests
= []struct {
295 {IPv4bcast
, true, false},
296 {IPv4allsys
, true, false},
297 {IPv4allrouter
, true, false},
298 {IPv4zero
, true, false},
299 {IPv4(224, 0, 0, 1), true, false},
300 {IPv4(127, 0, 0, 1), true, false},
301 {IPv4(240, 0, 0, 1), true, false},
302 {IPv6unspecified
, false, true},
303 {IPv6loopback
, false, true},
304 {IPv6interfacelocalallnodes
, false, true},
305 {IPv6linklocalallnodes
, false, true},
306 {IPv6linklocalallrouters
, false, true},
307 {ParseIP("ff05::a:b:c:d"), false, true},
308 {ParseIP("fe80::1:2:3:4"), false, true},
309 {ParseIP("2001:db8::123:12:1"), false, true},
312 func TestIPAddrFamily(t
*testing
.T
) {
313 for _
, tt
:= range ipaftests
{
314 if af
:= tt
.in
.To4() != nil; af
!= tt
.af4
{
315 t
.Errorf("verifying IPv4 address family for %q = %v, want %v", tt
.in
, af
, tt
.af4
)
317 if af
:= len(tt
.in
) == IPv6len
&& tt
.in
.To4() == nil; af
!= tt
.af6
{
318 t
.Errorf("verifying IPv6 address family for %q = %v, want %v", tt
.in
, af
, tt
.af6
)
323 var ipscopetests
= []struct {
328 {IP
.IsUnspecified
, IPv4zero
, true},
329 {IP
.IsUnspecified
, IPv4(127, 0, 0, 1), false},
330 {IP
.IsUnspecified
, IPv6unspecified
, true},
331 {IP
.IsUnspecified
, IPv6interfacelocalallnodes
, false},
332 {IP
.IsLoopback
, IPv4(127, 0, 0, 1), true},
333 {IP
.IsLoopback
, IPv4(127, 255, 255, 254), true},
334 {IP
.IsLoopback
, IPv4(128, 1, 2, 3), false},
335 {IP
.IsLoopback
, IPv6loopback
, true},
336 {IP
.IsLoopback
, IPv6linklocalallrouters
, false},
337 {IP
.IsMulticast
, IPv4(224, 0, 0, 0), true},
338 {IP
.IsMulticast
, IPv4(239, 0, 0, 0), true},
339 {IP
.IsMulticast
, IPv4(240, 0, 0, 0), false},
340 {IP
.IsMulticast
, IPv6linklocalallnodes
, true},
341 {IP
.IsMulticast
, IP
{0xff, 0x05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, true},
342 {IP
.IsMulticast
, IP
{0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false},
343 {IP
.IsLinkLocalMulticast
, IPv4(224, 0, 0, 0), true},
344 {IP
.IsLinkLocalMulticast
, IPv4(239, 0, 0, 0), false},
345 {IP
.IsLinkLocalMulticast
, IPv6linklocalallrouters
, true},
346 {IP
.IsLinkLocalMulticast
, IP
{0xff, 0x05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false},
347 {IP
.IsLinkLocalUnicast
, IPv4(169, 254, 0, 0), true},
348 {IP
.IsLinkLocalUnicast
, IPv4(169, 255, 0, 0), false},
349 {IP
.IsLinkLocalUnicast
, IP
{0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, true},
350 {IP
.IsLinkLocalUnicast
, IP
{0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false},
351 {IP
.IsGlobalUnicast
, IPv4(240, 0, 0, 0), true},
352 {IP
.IsGlobalUnicast
, IPv4(232, 0, 0, 0), false},
353 {IP
.IsGlobalUnicast
, IPv4(169, 254, 0, 0), false},
354 {IP
.IsGlobalUnicast
, IP
{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0x1, 0x23, 0, 0x12, 0, 0x1}, true},
355 {IP
.IsGlobalUnicast
, IP
{0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false},
356 {IP
.IsGlobalUnicast
, IP
{0xff, 0x05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false},
359 func name(f
interface{}) string {
360 return runtime
.FuncForPC(reflect
.ValueOf(f
).Pointer()).Name()
363 func TestIPAddrScope(t
*testing
.T
) {
364 for _
, tt
:= range ipscopetests
{
365 if ok
:= tt
.scope(tt
.in
); ok
!= tt
.ok
{
366 t
.Errorf("%s(%q) = %v, want %v", name(tt
.scope
), tt
.in
, ok
, tt
.ok
)