Source file
src/net/mockserver_test.go
1
2
3
4
5
6
7 package net
8
9 import (
10 "context"
11 "errors"
12 "fmt"
13 "os"
14 "path/filepath"
15 "sync"
16 "testing"
17 "time"
18 )
19
20
21 func testUnixAddr(t testing.TB) string {
22
23
24
25 d, err := os.MkdirTemp("", "")
26 if err != nil {
27 t.Fatal(err)
28 }
29 t.Cleanup(func() {
30 if err := os.RemoveAll(d); err != nil {
31 t.Error(err)
32 }
33 })
34 return filepath.Join(d, "sock")
35 }
36
37 func newLocalListener(t testing.TB, network string, lcOpt ...*ListenConfig) Listener {
38 var lc *ListenConfig
39 switch len(lcOpt) {
40 case 0:
41 lc = new(ListenConfig)
42 case 1:
43 lc = lcOpt[0]
44 default:
45 t.Helper()
46 t.Fatal("too many ListenConfigs passed to newLocalListener: want 0 or 1")
47 }
48
49 listen := func(net, addr string) Listener {
50 ln, err := lc.Listen(context.Background(), net, addr)
51 if err != nil {
52 t.Helper()
53 t.Fatal(err)
54 }
55 return ln
56 }
57
58 switch network {
59 case "tcp":
60 if supportsIPv4() {
61 if !supportsIPv6() {
62 return listen("tcp4", "127.0.0.1:0")
63 }
64 if ln, err := Listen("tcp4", "127.0.0.1:0"); err == nil {
65 return ln
66 }
67 }
68 if supportsIPv6() {
69 return listen("tcp6", "[::1]:0")
70 }
71 case "tcp4":
72 if supportsIPv4() {
73 return listen("tcp4", "127.0.0.1:0")
74 }
75 case "tcp6":
76 if supportsIPv6() {
77 return listen("tcp6", "[::1]:0")
78 }
79 case "unix", "unixpacket":
80 return listen(network, testUnixAddr(t))
81 }
82
83 t.Helper()
84 t.Fatalf("%s is not supported", network)
85 return nil
86 }
87
88 func newDualStackListener() (lns []*TCPListener, err error) {
89 var args = []struct {
90 network string
91 TCPAddr
92 }{
93 {"tcp4", TCPAddr{IP: IPv4(127, 0, 0, 1)}},
94 {"tcp6", TCPAddr{IP: IPv6loopback}},
95 }
96 for i := 0; i < 64; i++ {
97 var port int
98 var lns []*TCPListener
99 for _, arg := range args {
100 arg.TCPAddr.Port = port
101 ln, err := ListenTCP(arg.network, &arg.TCPAddr)
102 if err != nil {
103 continue
104 }
105 port = ln.Addr().(*TCPAddr).Port
106 lns = append(lns, ln)
107 }
108 if len(lns) != len(args) {
109 for _, ln := range lns {
110 ln.Close()
111 }
112 continue
113 }
114 return lns, nil
115 }
116 return nil, errors.New("no dualstack port available")
117 }
118
119 type localServer struct {
120 lnmu sync.RWMutex
121 Listener
122 done chan bool
123 cl []Conn
124 }
125
126 func (ls *localServer) buildup(handler func(*localServer, Listener)) error {
127 go func() {
128 handler(ls, ls.Listener)
129 close(ls.done)
130 }()
131 return nil
132 }
133
134 func (ls *localServer) teardown() error {
135 ls.lnmu.Lock()
136 defer ls.lnmu.Unlock()
137 if ls.Listener != nil {
138 network := ls.Listener.Addr().Network()
139 address := ls.Listener.Addr().String()
140 ls.Listener.Close()
141 for _, c := range ls.cl {
142 if err := c.Close(); err != nil {
143 return err
144 }
145 }
146 <-ls.done
147 ls.Listener = nil
148 switch network {
149 case "unix", "unixpacket":
150 os.Remove(address)
151 }
152 }
153 return nil
154 }
155
156 func newLocalServer(t testing.TB, network string) *localServer {
157 t.Helper()
158 ln := newLocalListener(t, network)
159 return &localServer{Listener: ln, done: make(chan bool)}
160 }
161
162 type streamListener struct {
163 network, address string
164 Listener
165 done chan bool
166 }
167
168 func (sl *streamListener) newLocalServer() *localServer {
169 return &localServer{Listener: sl.Listener, done: make(chan bool)}
170 }
171
172 type dualStackServer struct {
173 lnmu sync.RWMutex
174 lns []streamListener
175 port string
176
177 cmu sync.RWMutex
178 cs []Conn
179 }
180
181 func (dss *dualStackServer) buildup(handler func(*dualStackServer, Listener)) error {
182 for i := range dss.lns {
183 go func(i int) {
184 handler(dss, dss.lns[i].Listener)
185 close(dss.lns[i].done)
186 }(i)
187 }
188 return nil
189 }
190
191 func (dss *dualStackServer) teardownNetwork(network string) error {
192 dss.lnmu.Lock()
193 for i := range dss.lns {
194 if network == dss.lns[i].network && dss.lns[i].Listener != nil {
195 dss.lns[i].Listener.Close()
196 <-dss.lns[i].done
197 dss.lns[i].Listener = nil
198 }
199 }
200 dss.lnmu.Unlock()
201 return nil
202 }
203
204 func (dss *dualStackServer) teardown() error {
205 dss.lnmu.Lock()
206 for i := range dss.lns {
207 if dss.lns[i].Listener != nil {
208 dss.lns[i].Listener.Close()
209 <-dss.lns[i].done
210 }
211 }
212 dss.lns = dss.lns[:0]
213 dss.lnmu.Unlock()
214 dss.cmu.Lock()
215 for _, c := range dss.cs {
216 c.Close()
217 }
218 dss.cs = dss.cs[:0]
219 dss.cmu.Unlock()
220 return nil
221 }
222
223 func newDualStackServer() (*dualStackServer, error) {
224 lns, err := newDualStackListener()
225 if err != nil {
226 return nil, err
227 }
228 _, port, err := SplitHostPort(lns[0].Addr().String())
229 if err != nil {
230 lns[0].Close()
231 lns[1].Close()
232 return nil, err
233 }
234 return &dualStackServer{
235 lns: []streamListener{
236 {network: "tcp4", address: lns[0].Addr().String(), Listener: lns[0], done: make(chan bool)},
237 {network: "tcp6", address: lns[1].Addr().String(), Listener: lns[1], done: make(chan bool)},
238 },
239 port: port,
240 }, nil
241 }
242
243 func (ls *localServer) transponder(ln Listener, ch chan<- error) {
244 defer close(ch)
245
246 switch ln := ln.(type) {
247 case *TCPListener:
248 ln.SetDeadline(time.Now().Add(someTimeout))
249 case *UnixListener:
250 ln.SetDeadline(time.Now().Add(someTimeout))
251 }
252 c, err := ln.Accept()
253 if err != nil {
254 if perr := parseAcceptError(err); perr != nil {
255 ch <- perr
256 }
257 ch <- err
258 return
259 }
260 ls.cl = append(ls.cl, c)
261
262 network := ln.Addr().Network()
263 if c.LocalAddr().Network() != network || c.RemoteAddr().Network() != network {
264 ch <- fmt.Errorf("got %v->%v; expected %v->%v", c.LocalAddr().Network(), c.RemoteAddr().Network(), network, network)
265 return
266 }
267 c.SetDeadline(time.Now().Add(someTimeout))
268 c.SetReadDeadline(time.Now().Add(someTimeout))
269 c.SetWriteDeadline(time.Now().Add(someTimeout))
270
271 b := make([]byte, 256)
272 n, err := c.Read(b)
273 if err != nil {
274 if perr := parseReadError(err); perr != nil {
275 ch <- perr
276 }
277 ch <- err
278 return
279 }
280 if _, err := c.Write(b[:n]); err != nil {
281 if perr := parseWriteError(err); perr != nil {
282 ch <- perr
283 }
284 ch <- err
285 return
286 }
287 }
288
289 func transceiver(c Conn, wb []byte, ch chan<- error) {
290 defer close(ch)
291
292 c.SetDeadline(time.Now().Add(someTimeout))
293 c.SetReadDeadline(time.Now().Add(someTimeout))
294 c.SetWriteDeadline(time.Now().Add(someTimeout))
295
296 n, err := c.Write(wb)
297 if err != nil {
298 if perr := parseWriteError(err); perr != nil {
299 ch <- perr
300 }
301 ch <- err
302 return
303 }
304 if n != len(wb) {
305 ch <- fmt.Errorf("wrote %d; want %d", n, len(wb))
306 }
307 rb := make([]byte, len(wb))
308 n, err = c.Read(rb)
309 if err != nil {
310 if perr := parseReadError(err); perr != nil {
311 ch <- perr
312 }
313 ch <- err
314 return
315 }
316 if n != len(wb) {
317 ch <- fmt.Errorf("read %d; want %d", n, len(wb))
318 }
319 }
320
321 func newLocalPacketListener(t testing.TB, network string, lcOpt ...*ListenConfig) PacketConn {
322 var lc *ListenConfig
323 switch len(lcOpt) {
324 case 0:
325 lc = new(ListenConfig)
326 case 1:
327 lc = lcOpt[0]
328 default:
329 t.Helper()
330 t.Fatal("too many ListenConfigs passed to newLocalListener: want 0 or 1")
331 }
332
333 listenPacket := func(net, addr string) PacketConn {
334 c, err := lc.ListenPacket(context.Background(), net, addr)
335 if err != nil {
336 t.Helper()
337 t.Fatal(err)
338 }
339 return c
340 }
341
342 switch network {
343 case "udp":
344 if supportsIPv4() {
345 return listenPacket("udp4", "127.0.0.1:0")
346 }
347 if supportsIPv6() {
348 return listenPacket("udp6", "[::1]:0")
349 }
350 case "udp4":
351 if supportsIPv4() {
352 return listenPacket("udp4", "127.0.0.1:0")
353 }
354 case "udp6":
355 if supportsIPv6() {
356 return listenPacket("udp6", "[::1]:0")
357 }
358 case "unixgram":
359 return listenPacket(network, testUnixAddr(t))
360 }
361
362 t.Helper()
363 t.Fatalf("%s is not supported", network)
364 return nil
365 }
366
367 func newDualStackPacketListener() (cs []*UDPConn, err error) {
368 var args = []struct {
369 network string
370 UDPAddr
371 }{
372 {"udp4", UDPAddr{IP: IPv4(127, 0, 0, 1)}},
373 {"udp6", UDPAddr{IP: IPv6loopback}},
374 }
375 for i := 0; i < 64; i++ {
376 var port int
377 var cs []*UDPConn
378 for _, arg := range args {
379 arg.UDPAddr.Port = port
380 c, err := ListenUDP(arg.network, &arg.UDPAddr)
381 if err != nil {
382 continue
383 }
384 port = c.LocalAddr().(*UDPAddr).Port
385 cs = append(cs, c)
386 }
387 if len(cs) != len(args) {
388 for _, c := range cs {
389 c.Close()
390 }
391 continue
392 }
393 return cs, nil
394 }
395 return nil, errors.New("no dualstack port available")
396 }
397
398 type localPacketServer struct {
399 pcmu sync.RWMutex
400 PacketConn
401 done chan bool
402 }
403
404 func (ls *localPacketServer) buildup(handler func(*localPacketServer, PacketConn)) error {
405 go func() {
406 handler(ls, ls.PacketConn)
407 close(ls.done)
408 }()
409 return nil
410 }
411
412 func (ls *localPacketServer) teardown() error {
413 ls.pcmu.Lock()
414 if ls.PacketConn != nil {
415 network := ls.PacketConn.LocalAddr().Network()
416 address := ls.PacketConn.LocalAddr().String()
417 ls.PacketConn.Close()
418 <-ls.done
419 ls.PacketConn = nil
420 switch network {
421 case "unixgram":
422 os.Remove(address)
423 }
424 }
425 ls.pcmu.Unlock()
426 return nil
427 }
428
429 func newLocalPacketServer(t testing.TB, network string) *localPacketServer {
430 t.Helper()
431 c := newLocalPacketListener(t, network)
432 return &localPacketServer{PacketConn: c, done: make(chan bool)}
433 }
434
435 type packetListener struct {
436 PacketConn
437 }
438
439 func (pl *packetListener) newLocalServer() *localPacketServer {
440 return &localPacketServer{PacketConn: pl.PacketConn, done: make(chan bool)}
441 }
442
443 func packetTransponder(c PacketConn, ch chan<- error) {
444 defer close(ch)
445
446 c.SetDeadline(time.Now().Add(someTimeout))
447 c.SetReadDeadline(time.Now().Add(someTimeout))
448 c.SetWriteDeadline(time.Now().Add(someTimeout))
449
450 b := make([]byte, 256)
451 n, peer, err := c.ReadFrom(b)
452 if err != nil {
453 if perr := parseReadError(err); perr != nil {
454 ch <- perr
455 }
456 ch <- err
457 return
458 }
459 if peer == nil {
460 switch c.LocalAddr().Network() {
461 case "udp":
462 peer, err = ResolveUDPAddr("udp", string(b[:n]))
463 case "unixgram":
464 peer, err = ResolveUnixAddr("unixgram", string(b[:n]))
465 }
466 if err != nil {
467 ch <- err
468 return
469 }
470 }
471 if _, err := c.WriteTo(b[:n], peer); err != nil {
472 if perr := parseWriteError(err); perr != nil {
473 ch <- perr
474 }
475 ch <- err
476 return
477 }
478 }
479
480 func packetTransceiver(c PacketConn, wb []byte, dst Addr, ch chan<- error) {
481 defer close(ch)
482
483 c.SetDeadline(time.Now().Add(someTimeout))
484 c.SetReadDeadline(time.Now().Add(someTimeout))
485 c.SetWriteDeadline(time.Now().Add(someTimeout))
486
487 n, err := c.WriteTo(wb, dst)
488 if err != nil {
489 if perr := parseWriteError(err); perr != nil {
490 ch <- perr
491 }
492 ch <- err
493 return
494 }
495 if n != len(wb) {
496 ch <- fmt.Errorf("wrote %d; want %d", n, len(wb))
497 }
498 rb := make([]byte, len(wb))
499 n, _, err = c.ReadFrom(rb)
500 if err != nil {
501 if perr := parseReadError(err); perr != nil {
502 ch <- perr
503 }
504 ch <- err
505 return
506 }
507 if n != len(wb) {
508 ch <- fmt.Errorf("read %d; want %d", n, len(wb))
509 }
510 }
511
View as plain text