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