Source file
src/net/ipsock_test.go
1
2
3
4
5 package net
6
7 import (
8 "reflect"
9 "runtime"
10 "testing"
11 )
12
13 var testInetaddr = func(ip IPAddr) Addr { return &TCPAddr{IP: ip.IP, Port: 5682, Zone: ip.Zone} }
14
15 var addrListTests = []struct {
16 filter func(IPAddr) bool
17 ips []IPAddr
18 inetaddr func(IPAddr) Addr
19 first Addr
20 primaries addrList
21 fallbacks addrList
22 err error
23 }{
24 {
25 nil,
26 []IPAddr{
27 {IP: IPv4(127, 0, 0, 1)},
28 {IP: IPv6loopback},
29 },
30 testInetaddr,
31 &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
32 addrList{&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682}},
33 addrList{&TCPAddr{IP: IPv6loopback, Port: 5682}},
34 nil,
35 },
36 {
37 nil,
38 []IPAddr{
39 {IP: IPv6loopback},
40 {IP: IPv4(127, 0, 0, 1)},
41 },
42 testInetaddr,
43 &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
44 addrList{&TCPAddr{IP: IPv6loopback, Port: 5682}},
45 addrList{&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682}},
46 nil,
47 },
48 {
49 nil,
50 []IPAddr{
51 {IP: IPv4(127, 0, 0, 1)},
52 {IP: IPv4(192, 168, 0, 1)},
53 },
54 testInetaddr,
55 &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
56 addrList{
57 &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
58 &TCPAddr{IP: IPv4(192, 168, 0, 1), Port: 5682},
59 },
60 nil,
61 nil,
62 },
63 {
64 nil,
65 []IPAddr{
66 {IP: IPv6loopback},
67 {IP: ParseIP("fe80::1"), Zone: "eth0"},
68 },
69 testInetaddr,
70 &TCPAddr{IP: IPv6loopback, Port: 5682},
71 addrList{
72 &TCPAddr{IP: IPv6loopback, Port: 5682},
73 &TCPAddr{IP: ParseIP("fe80::1"), Port: 5682, Zone: "eth0"},
74 },
75 nil,
76 nil,
77 },
78 {
79 nil,
80 []IPAddr{
81 {IP: IPv4(127, 0, 0, 1)},
82 {IP: IPv4(192, 168, 0, 1)},
83 {IP: IPv6loopback},
84 {IP: ParseIP("fe80::1"), Zone: "eth0"},
85 },
86 testInetaddr,
87 &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
88 addrList{
89 &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
90 &TCPAddr{IP: IPv4(192, 168, 0, 1), Port: 5682},
91 },
92 addrList{
93 &TCPAddr{IP: IPv6loopback, Port: 5682},
94 &TCPAddr{IP: ParseIP("fe80::1"), Port: 5682, Zone: "eth0"},
95 },
96 nil,
97 },
98 {
99 nil,
100 []IPAddr{
101 {IP: IPv6loopback},
102 {IP: ParseIP("fe80::1"), Zone: "eth0"},
103 {IP: IPv4(127, 0, 0, 1)},
104 {IP: IPv4(192, 168, 0, 1)},
105 },
106 testInetaddr,
107 &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
108 addrList{
109 &TCPAddr{IP: IPv6loopback, Port: 5682},
110 &TCPAddr{IP: ParseIP("fe80::1"), Port: 5682, Zone: "eth0"},
111 },
112 addrList{
113 &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
114 &TCPAddr{IP: IPv4(192, 168, 0, 1), Port: 5682},
115 },
116 nil,
117 },
118 {
119 nil,
120 []IPAddr{
121 {IP: IPv4(127, 0, 0, 1)},
122 {IP: IPv6loopback},
123 {IP: IPv4(192, 168, 0, 1)},
124 {IP: ParseIP("fe80::1"), Zone: "eth0"},
125 },
126 testInetaddr,
127 &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
128 addrList{
129 &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
130 &TCPAddr{IP: IPv4(192, 168, 0, 1), Port: 5682},
131 },
132 addrList{
133 &TCPAddr{IP: IPv6loopback, Port: 5682},
134 &TCPAddr{IP: ParseIP("fe80::1"), Port: 5682, Zone: "eth0"},
135 },
136 nil,
137 },
138 {
139 nil,
140 []IPAddr{
141 {IP: IPv6loopback},
142 {IP: IPv4(127, 0, 0, 1)},
143 {IP: ParseIP("fe80::1"), Zone: "eth0"},
144 {IP: IPv4(192, 168, 0, 1)},
145 },
146 testInetaddr,
147 &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
148 addrList{
149 &TCPAddr{IP: IPv6loopback, Port: 5682},
150 &TCPAddr{IP: ParseIP("fe80::1"), Port: 5682, Zone: "eth0"},
151 },
152 addrList{
153 &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
154 &TCPAddr{IP: IPv4(192, 168, 0, 1), Port: 5682},
155 },
156 nil,
157 },
158
159 {
160 ipv4only,
161 []IPAddr{
162 {IP: IPv4(127, 0, 0, 1)},
163 {IP: IPv6loopback},
164 },
165 testInetaddr,
166 &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
167 addrList{&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682}},
168 nil,
169 nil,
170 },
171 {
172 ipv4only,
173 []IPAddr{
174 {IP: IPv6loopback},
175 {IP: IPv4(127, 0, 0, 1)},
176 },
177 testInetaddr,
178 &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
179 addrList{&TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682}},
180 nil,
181 nil,
182 },
183
184 {
185 ipv6only,
186 []IPAddr{
187 {IP: IPv4(127, 0, 0, 1)},
188 {IP: IPv6loopback},
189 },
190 testInetaddr,
191 &TCPAddr{IP: IPv6loopback, Port: 5682},
192 addrList{&TCPAddr{IP: IPv6loopback, Port: 5682}},
193 nil,
194 nil,
195 },
196 {
197 ipv6only,
198 []IPAddr{
199 {IP: IPv6loopback},
200 {IP: IPv4(127, 0, 0, 1)},
201 },
202 testInetaddr,
203 &TCPAddr{IP: IPv6loopback, Port: 5682},
204 addrList{&TCPAddr{IP: IPv6loopback, Port: 5682}},
205 nil,
206 nil,
207 },
208
209 {nil, nil, testInetaddr, nil, nil, nil, &AddrError{errNoSuitableAddress.Error(), "ADDR"}},
210
211 {ipv4only, nil, testInetaddr, nil, nil, nil, &AddrError{errNoSuitableAddress.Error(), "ADDR"}},
212 {ipv4only, []IPAddr{{IP: IPv6loopback}}, testInetaddr, nil, nil, nil, &AddrError{errNoSuitableAddress.Error(), "ADDR"}},
213
214 {ipv6only, nil, testInetaddr, nil, nil, nil, &AddrError{errNoSuitableAddress.Error(), "ADDR"}},
215 {ipv6only, []IPAddr{{IP: IPv4(127, 0, 0, 1)}}, testInetaddr, nil, nil, nil, &AddrError{errNoSuitableAddress.Error(), "ADDR"}},
216 }
217
218 func TestAddrList(t *testing.T) {
219 if !supportsIPv4() || !supportsIPv6() {
220 t.Skip("both IPv4 and IPv6 are required")
221 }
222
223 for i, tt := range addrListTests {
224 addrs, err := filterAddrList(tt.filter, tt.ips, tt.inetaddr, "ADDR")
225 if !reflect.DeepEqual(err, tt.err) {
226 t.Errorf("#%v: got %v; want %v", i, err, tt.err)
227 }
228 if tt.err != nil {
229 if len(addrs) != 0 {
230 t.Errorf("#%v: got %v; want 0", i, len(addrs))
231 }
232 continue
233 }
234 first := addrs.first(isIPv4)
235 if !reflect.DeepEqual(first, tt.first) {
236 t.Errorf("#%v: got %v; want %v", i, first, tt.first)
237 }
238 primaries, fallbacks := addrs.partition(isIPv4)
239 if !reflect.DeepEqual(primaries, tt.primaries) {
240 t.Errorf("#%v: got %v; want %v", i, primaries, tt.primaries)
241 }
242 if !reflect.DeepEqual(fallbacks, tt.fallbacks) {
243 t.Errorf("#%v: got %v; want %v", i, fallbacks, tt.fallbacks)
244 }
245 expectedLen := len(primaries) + len(fallbacks)
246 if len(addrs) != expectedLen {
247 t.Errorf("#%v: got %v; want %v", i, len(addrs), expectedLen)
248 }
249 }
250 }
251
252 func TestAddrListPartition(t *testing.T) {
253 addrs := addrList{
254 &IPAddr{IP: ParseIP("fe80::"), Zone: "eth0"},
255 &IPAddr{IP: ParseIP("fe80::1"), Zone: "eth0"},
256 &IPAddr{IP: ParseIP("fe80::2"), Zone: "eth0"},
257 }
258 cases := []struct {
259 lastByte byte
260 primaries addrList
261 fallbacks addrList
262 }{
263 {0, addrList{addrs[0]}, addrList{addrs[1], addrs[2]}},
264 {1, addrList{addrs[0], addrs[2]}, addrList{addrs[1]}},
265 {2, addrList{addrs[0], addrs[1]}, addrList{addrs[2]}},
266 {3, addrList{addrs[0], addrs[1], addrs[2]}, nil},
267 }
268 for i, tt := range cases {
269
270 for _, invert := range []bool{false, true} {
271 primaries, fallbacks := addrs.partition(func(a Addr) bool {
272 ip := a.(*IPAddr).IP
273 return (ip[len(ip)-1] == tt.lastByte) != invert
274 })
275 if !reflect.DeepEqual(primaries, tt.primaries) {
276 t.Errorf("#%v: got %v; want %v", i, primaries, tt.primaries)
277 }
278 if !reflect.DeepEqual(fallbacks, tt.fallbacks) {
279 t.Errorf("#%v: got %v; want %v", i, fallbacks, tt.fallbacks)
280 }
281 }
282 }
283 }
284
285 func TestListenIPv6WildcardAddr(t *testing.T) {
286 if runtime.GOOS == "js" || runtime.GOOS == "wasip1" {
287 t.Skip("fake networking does not implement [::] wildcard address assertions")
288 }
289 if !supportsIPv6() {
290 t.Skip("IPv6 not supported")
291 }
292 if !supportsIPv4map() {
293 t.Skip("dual-stack IPv6 sockets not supported")
294 }
295
296 ln, err := Listen("tcp", "[::]:0")
297 if err != nil {
298 t.Fatal(err)
299 }
300 defer ln.Close()
301
302 addr := ln.Addr().(*TCPAddr)
303 if addr.IP.To4() != nil {
304 t.Errorf("Listen(\"tcp\", \"[::]:0\") bound to %v, want IPv6 address", addr)
305 }
306 }
307
View as plain text