Source file
src/net/tcpsock_test.go
Documentation: net
1
2
3
4
5
6
7
8 package net
9
10 import (
11 "fmt"
12 "internal/testenv"
13 "io"
14 "os"
15 "reflect"
16 "runtime"
17 "sync"
18 "testing"
19 "time"
20 )
21
22 func BenchmarkTCP4OneShot(b *testing.B) {
23 benchmarkTCP(b, false, false, "127.0.0.1:0")
24 }
25
26 func BenchmarkTCP4OneShotTimeout(b *testing.B) {
27 benchmarkTCP(b, false, true, "127.0.0.1:0")
28 }
29
30 func BenchmarkTCP4Persistent(b *testing.B) {
31 benchmarkTCP(b, true, false, "127.0.0.1:0")
32 }
33
34 func BenchmarkTCP4PersistentTimeout(b *testing.B) {
35 benchmarkTCP(b, true, true, "127.0.0.1:0")
36 }
37
38 func BenchmarkTCP6OneShot(b *testing.B) {
39 if !supportsIPv6() {
40 b.Skip("ipv6 is not supported")
41 }
42 benchmarkTCP(b, false, false, "[::1]:0")
43 }
44
45 func BenchmarkTCP6OneShotTimeout(b *testing.B) {
46 if !supportsIPv6() {
47 b.Skip("ipv6 is not supported")
48 }
49 benchmarkTCP(b, false, true, "[::1]:0")
50 }
51
52 func BenchmarkTCP6Persistent(b *testing.B) {
53 if !supportsIPv6() {
54 b.Skip("ipv6 is not supported")
55 }
56 benchmarkTCP(b, true, false, "[::1]:0")
57 }
58
59 func BenchmarkTCP6PersistentTimeout(b *testing.B) {
60 if !supportsIPv6() {
61 b.Skip("ipv6 is not supported")
62 }
63 benchmarkTCP(b, true, true, "[::1]:0")
64 }
65
66 func benchmarkTCP(b *testing.B, persistent, timeout bool, laddr string) {
67 testHookUninstaller.Do(uninstallTestHooks)
68
69 const msgLen = 512
70 conns := b.N
71 numConcurrent := runtime.GOMAXPROCS(-1) * 2
72 msgs := 1
73 if persistent {
74 conns = numConcurrent
75 msgs = b.N / conns
76 if msgs == 0 {
77 msgs = 1
78 }
79 if conns > b.N {
80 conns = b.N
81 }
82 }
83 sendMsg := func(c Conn, buf []byte) bool {
84 n, err := c.Write(buf)
85 if n != len(buf) || err != nil {
86 b.Log(err)
87 return false
88 }
89 return true
90 }
91 recvMsg := func(c Conn, buf []byte) bool {
92 for read := 0; read != len(buf); {
93 n, err := c.Read(buf)
94 read += n
95 if err != nil {
96 b.Log(err)
97 return false
98 }
99 }
100 return true
101 }
102 ln, err := Listen("tcp", laddr)
103 if err != nil {
104 b.Fatal(err)
105 }
106 defer ln.Close()
107 serverSem := make(chan bool, numConcurrent)
108
109 go func() {
110 for {
111 c, err := ln.Accept()
112 if err != nil {
113 break
114 }
115 serverSem <- true
116
117 go func(c Conn) {
118 defer func() {
119 c.Close()
120 <-serverSem
121 }()
122 if timeout {
123 c.SetDeadline(time.Now().Add(time.Hour))
124 }
125 var buf [msgLen]byte
126 for m := 0; m < msgs; m++ {
127 if !recvMsg(c, buf[:]) || !sendMsg(c, buf[:]) {
128 break
129 }
130 }
131 }(c)
132 }
133 }()
134 clientSem := make(chan bool, numConcurrent)
135 for i := 0; i < conns; i++ {
136 clientSem <- true
137
138 go func() {
139 defer func() {
140 <-clientSem
141 }()
142 c, err := Dial("tcp", ln.Addr().String())
143 if err != nil {
144 b.Log(err)
145 return
146 }
147 defer c.Close()
148 if timeout {
149 c.SetDeadline(time.Now().Add(time.Hour))
150 }
151 var buf [msgLen]byte
152 for m := 0; m < msgs; m++ {
153 if !sendMsg(c, buf[:]) || !recvMsg(c, buf[:]) {
154 break
155 }
156 }
157 }()
158 }
159 for i := 0; i < numConcurrent; i++ {
160 clientSem <- true
161 serverSem <- true
162 }
163 }
164
165 func BenchmarkTCP4ConcurrentReadWrite(b *testing.B) {
166 benchmarkTCPConcurrentReadWrite(b, "127.0.0.1:0")
167 }
168
169 func BenchmarkTCP6ConcurrentReadWrite(b *testing.B) {
170 if !supportsIPv6() {
171 b.Skip("ipv6 is not supported")
172 }
173 benchmarkTCPConcurrentReadWrite(b, "[::1]:0")
174 }
175
176 func benchmarkTCPConcurrentReadWrite(b *testing.B, laddr string) {
177 testHookUninstaller.Do(uninstallTestHooks)
178
179
180
181
182
183
184 b.StopTimer()
185
186 P := runtime.GOMAXPROCS(0)
187 N := b.N / P
188 W := 1000
189
190
191 clients := make([]Conn, P)
192 servers := make([]Conn, P)
193 ln, err := Listen("tcp", laddr)
194 if err != nil {
195 b.Fatal(err)
196 }
197 defer ln.Close()
198 done := make(chan bool)
199 go func() {
200 for p := 0; p < P; p++ {
201 s, err := ln.Accept()
202 if err != nil {
203 b.Error(err)
204 return
205 }
206 servers[p] = s
207 }
208 done <- true
209 }()
210 for p := 0; p < P; p++ {
211 c, err := Dial("tcp", ln.Addr().String())
212 if err != nil {
213 b.Fatal(err)
214 }
215 clients[p] = c
216 }
217 <-done
218
219 b.StartTimer()
220
221 var wg sync.WaitGroup
222 wg.Add(4 * P)
223 for p := 0; p < P; p++ {
224
225 go func(c Conn) {
226 defer wg.Done()
227 var buf [1]byte
228 for i := 0; i < N; i++ {
229 v := byte(i)
230 for w := 0; w < W; w++ {
231 v *= v
232 }
233 buf[0] = v
234 _, err := c.Write(buf[:])
235 if err != nil {
236 b.Error(err)
237 return
238 }
239 }
240 }(clients[p])
241
242
243 pipe := make(chan byte, 128)
244
245
246 go func(s Conn) {
247 defer wg.Done()
248 var buf [1]byte
249 for i := 0; i < N; i++ {
250 _, err := s.Read(buf[:])
251 if err != nil {
252 b.Error(err)
253 return
254 }
255 pipe <- buf[0]
256 }
257 }(servers[p])
258
259
260 go func(s Conn) {
261 defer wg.Done()
262 var buf [1]byte
263 for i := 0; i < N; i++ {
264 v := <-pipe
265 for w := 0; w < W; w++ {
266 v *= v
267 }
268 buf[0] = v
269 _, err := s.Write(buf[:])
270 if err != nil {
271 b.Error(err)
272 return
273 }
274 }
275 s.Close()
276 }(servers[p])
277
278
279 go func(c Conn) {
280 defer wg.Done()
281 var buf [1]byte
282 for i := 0; i < N; i++ {
283 _, err := c.Read(buf[:])
284 if err != nil {
285 b.Error(err)
286 return
287 }
288 }
289 c.Close()
290 }(clients[p])
291 }
292 wg.Wait()
293 }
294
295 type resolveTCPAddrTest struct {
296 network string
297 litAddrOrName string
298 addr *TCPAddr
299 err error
300 }
301
302 var resolveTCPAddrTests = []resolveTCPAddrTest{
303 {"tcp", "127.0.0.1:0", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil},
304 {"tcp4", "127.0.0.1:65535", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 65535}, nil},
305
306 {"tcp", "[::1]:0", &TCPAddr{IP: ParseIP("::1"), Port: 0}, nil},
307 {"tcp6", "[::1]:65535", &TCPAddr{IP: ParseIP("::1"), Port: 65535}, nil},
308
309 {"tcp", "[::1%en0]:1", &TCPAddr{IP: ParseIP("::1"), Port: 1, Zone: "en0"}, nil},
310 {"tcp6", "[::1%911]:2", &TCPAddr{IP: ParseIP("::1"), Port: 2, Zone: "911"}, nil},
311
312 {"", "127.0.0.1:0", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil},
313 {"", "[::1]:0", &TCPAddr{IP: ParseIP("::1"), Port: 0}, nil},
314
315 {"tcp", ":12345", &TCPAddr{Port: 12345}, nil},
316
317 {"http", "127.0.0.1:0", nil, UnknownNetworkError("http")},
318
319 {"tcp", "127.0.0.1:http", &TCPAddr{IP: ParseIP("127.0.0.1"), Port: 80}, nil},
320 {"tcp", "[::ffff:127.0.0.1]:http", &TCPAddr{IP: ParseIP("::ffff:127.0.0.1"), Port: 80}, nil},
321 {"tcp", "[2001:db8::1]:http", &TCPAddr{IP: ParseIP("2001:db8::1"), Port: 80}, nil},
322 {"tcp4", "127.0.0.1:http", &TCPAddr{IP: ParseIP("127.0.0.1"), Port: 80}, nil},
323 {"tcp4", "[::ffff:127.0.0.1]:http", &TCPAddr{IP: ParseIP("127.0.0.1"), Port: 80}, nil},
324 {"tcp6", "[2001:db8::1]:http", &TCPAddr{IP: ParseIP("2001:db8::1"), Port: 80}, nil},
325
326 {"tcp4", "[2001:db8::1]:http", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "2001:db8::1"}},
327 {"tcp6", "127.0.0.1:http", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "127.0.0.1"}},
328 {"tcp6", "[::ffff:127.0.0.1]:http", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "::ffff:127.0.0.1"}},
329 }
330
331 func TestResolveTCPAddr(t *testing.T) {
332 origTestHookLookupIP := testHookLookupIP
333 defer func() { testHookLookupIP = origTestHookLookupIP }()
334 testHookLookupIP = lookupLocalhost
335
336 for _, tt := range resolveTCPAddrTests {
337 addr, err := ResolveTCPAddr(tt.network, tt.litAddrOrName)
338 if !reflect.DeepEqual(addr, tt.addr) || !reflect.DeepEqual(err, tt.err) {
339 t.Errorf("ResolveTCPAddr(%q, %q) = %#v, %v, want %#v, %v", tt.network, tt.litAddrOrName, addr, err, tt.addr, tt.err)
340 continue
341 }
342 if err == nil {
343 addr2, err := ResolveTCPAddr(addr.Network(), addr.String())
344 if !reflect.DeepEqual(addr2, tt.addr) || err != tt.err {
345 t.Errorf("(%q, %q): ResolveTCPAddr(%q, %q) = %#v, %v, want %#v, %v", tt.network, tt.litAddrOrName, addr.Network(), addr.String(), addr2, err, tt.addr, tt.err)
346 }
347 }
348 }
349 }
350
351 var tcpListenerNameTests = []struct {
352 net string
353 laddr *TCPAddr
354 }{
355 {"tcp4", &TCPAddr{IP: IPv4(127, 0, 0, 1)}},
356 {"tcp4", &TCPAddr{}},
357 {"tcp4", nil},
358 }
359
360 func TestTCPListenerName(t *testing.T) {
361 testenv.MustHaveExternalNetwork(t)
362
363 for _, tt := range tcpListenerNameTests {
364 ln, err := ListenTCP(tt.net, tt.laddr)
365 if err != nil {
366 t.Fatal(err)
367 }
368 defer ln.Close()
369 la := ln.Addr()
370 if a, ok := la.(*TCPAddr); !ok || a.Port == 0 {
371 t.Fatalf("got %v; expected a proper address with non-zero port number", la)
372 }
373 }
374 }
375
376 func TestIPv6LinkLocalUnicastTCP(t *testing.T) {
377 testenv.MustHaveExternalNetwork(t)
378
379 if !supportsIPv6() {
380 t.Skip("IPv6 is not supported")
381 }
382
383 for i, tt := range ipv6LinkLocalUnicastTCPTests {
384 ln, err := Listen(tt.network, tt.address)
385 if err != nil {
386
387
388 t.Log(err)
389 continue
390 }
391 ls, err := (&streamListener{Listener: ln}).newLocalServer()
392 if err != nil {
393 t.Fatal(err)
394 }
395 defer ls.teardown()
396 ch := make(chan error, 1)
397 handler := func(ls *localServer, ln Listener) { ls.transponder(ln, ch) }
398 if err := ls.buildup(handler); err != nil {
399 t.Fatal(err)
400 }
401 if la, ok := ln.Addr().(*TCPAddr); !ok || !tt.nameLookup && la.Zone == "" {
402 t.Fatalf("got %v; expected a proper address with zone identifier", la)
403 }
404
405 c, err := Dial(tt.network, ls.Listener.Addr().String())
406 if err != nil {
407 t.Fatal(err)
408 }
409 defer c.Close()
410 if la, ok := c.LocalAddr().(*TCPAddr); !ok || !tt.nameLookup && la.Zone == "" {
411 t.Fatalf("got %v; expected a proper address with zone identifier", la)
412 }
413 if ra, ok := c.RemoteAddr().(*TCPAddr); !ok || !tt.nameLookup && ra.Zone == "" {
414 t.Fatalf("got %v; expected a proper address with zone identifier", ra)
415 }
416
417 if _, err := c.Write([]byte("TCP OVER IPV6 LINKLOCAL TEST")); err != nil {
418 t.Fatal(err)
419 }
420 b := make([]byte, 32)
421 if _, err := c.Read(b); err != nil {
422 t.Fatal(err)
423 }
424
425 for err := range ch {
426 t.Errorf("#%d: %v", i, err)
427 }
428 }
429 }
430
431 func TestTCPConcurrentAccept(t *testing.T) {
432 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
433 ln, err := Listen("tcp", "127.0.0.1:0")
434 if err != nil {
435 t.Fatal(err)
436 }
437 const N = 10
438 var wg sync.WaitGroup
439 wg.Add(N)
440 for i := 0; i < N; i++ {
441 go func() {
442 for {
443 c, err := ln.Accept()
444 if err != nil {
445 break
446 }
447 c.Close()
448 }
449 wg.Done()
450 }()
451 }
452 attempts := 10 * N
453 fails := 0
454 d := &Dialer{Timeout: 200 * time.Millisecond}
455 for i := 0; i < attempts; i++ {
456 c, err := d.Dial("tcp", ln.Addr().String())
457 if err != nil {
458 fails++
459 } else {
460 c.Close()
461 }
462 }
463 ln.Close()
464 wg.Wait()
465 if fails > attempts/9 {
466 t.Fatalf("too many Dial failed: %v", fails)
467 }
468 if fails > 0 {
469 t.Logf("# of failed Dials: %v", fails)
470 }
471 }
472
473 func TestTCPReadWriteAllocs(t *testing.T) {
474 switch runtime.GOOS {
475 case "plan9":
476
477
478
479 t.Skipf("not supported on %s", runtime.GOOS)
480 }
481
482 ln, err := Listen("tcp", "127.0.0.1:0")
483 if err != nil {
484 t.Fatal(err)
485 }
486 defer ln.Close()
487 var server Conn
488 errc := make(chan error, 1)
489 go func() {
490 var err error
491 server, err = ln.Accept()
492 errc <- err
493 }()
494 client, err := Dial("tcp", ln.Addr().String())
495 if err != nil {
496 t.Fatal(err)
497 }
498 defer client.Close()
499 if err := <-errc; err != nil {
500 t.Fatal(err)
501 }
502 defer server.Close()
503
504 var buf [128]byte
505 allocs := testing.AllocsPerRun(1000, func() {
506 _, err := server.Write(buf[:])
507 if err != nil {
508 t.Fatal(err)
509 }
510 _, err = io.ReadFull(client, buf[:])
511 if err != nil {
512 t.Fatal(err)
513 }
514 })
515 if allocs > 0 {
516 t.Fatalf("got %v; want 0", allocs)
517 }
518
519 var bufwrt [128]byte
520 ch := make(chan bool)
521 defer close(ch)
522 go func() {
523 for <-ch {
524 _, err := server.Write(bufwrt[:])
525 errc <- err
526 }
527 }()
528 allocs = testing.AllocsPerRun(1000, func() {
529 ch <- true
530 if _, err = io.ReadFull(client, buf[:]); err != nil {
531 t.Fatal(err)
532 }
533 if err := <-errc; err != nil {
534 t.Fatal(err)
535 }
536 })
537 if allocs > 0 {
538 t.Fatalf("got %v; want 0", allocs)
539 }
540 }
541
542 func TestTCPStress(t *testing.T) {
543 const conns = 2
544 const msgLen = 512
545 msgs := int(1e4)
546 if testing.Short() {
547 msgs = 1e2
548 }
549
550 sendMsg := func(c Conn, buf []byte) bool {
551 n, err := c.Write(buf)
552 if n != len(buf) || err != nil {
553 t.Log(err)
554 return false
555 }
556 return true
557 }
558 recvMsg := func(c Conn, buf []byte) bool {
559 for read := 0; read != len(buf); {
560 n, err := c.Read(buf)
561 read += n
562 if err != nil {
563 t.Log(err)
564 return false
565 }
566 }
567 return true
568 }
569
570 ln, err := Listen("tcp", "127.0.0.1:0")
571 if err != nil {
572 t.Fatal(err)
573 }
574 done := make(chan bool)
575
576 go func() {
577 defer func() {
578 done <- true
579 }()
580 for {
581 c, err := ln.Accept()
582 if err != nil {
583 break
584 }
585
586 go func(c Conn) {
587 defer c.Close()
588 var buf [msgLen]byte
589 for m := 0; m < msgs; m++ {
590 if !recvMsg(c, buf[:]) || !sendMsg(c, buf[:]) {
591 break
592 }
593 }
594 }(c)
595 }
596 }()
597 for i := 0; i < conns; i++ {
598
599 go func() {
600 defer func() {
601 done <- true
602 }()
603 c, err := Dial("tcp", ln.Addr().String())
604 if err != nil {
605 t.Log(err)
606 return
607 }
608 defer c.Close()
609 var buf [msgLen]byte
610 for m := 0; m < msgs; m++ {
611 if !sendMsg(c, buf[:]) || !recvMsg(c, buf[:]) {
612 break
613 }
614 }
615 }()
616 }
617 for i := 0; i < conns; i++ {
618 <-done
619 }
620 ln.Close()
621 <-done
622 }
623
624 func TestTCPSelfConnect(t *testing.T) {
625 if runtime.GOOS == "windows" {
626
627 t.Skip("known-broken test on windows")
628 }
629
630 ln, err := newLocalListener("tcp")
631 if err != nil {
632 t.Fatal(err)
633 }
634 var d Dialer
635 c, err := d.Dial(ln.Addr().Network(), ln.Addr().String())
636 if err != nil {
637 ln.Close()
638 t.Fatal(err)
639 }
640 network := c.LocalAddr().Network()
641 laddr := *c.LocalAddr().(*TCPAddr)
642 c.Close()
643 ln.Close()
644
645
646 n := 100000
647 if testing.Short() {
648 n = 1000
649 }
650 switch runtime.GOOS {
651 case "darwin", "ios", "dragonfly", "freebsd", "netbsd", "openbsd", "plan9", "illumos", "solaris", "windows":
652
653
654 n = 100
655 }
656 for i := 0; i < n; i++ {
657 d.Timeout = time.Millisecond
658 c, err := d.Dial(network, laddr.String())
659 if err == nil {
660 addr := c.LocalAddr().(*TCPAddr)
661 if addr.Port == laddr.Port || addr.IP.Equal(laddr.IP) {
662 t.Errorf("Dial %v should fail", addr)
663 } else {
664 t.Logf("Dial %v succeeded - possibly racing with other listener", addr)
665 }
666 c.Close()
667 }
668 }
669 }
670
671
672
673 func TestTCPBig(t *testing.T) {
674 if !*testTCPBig {
675 t.Skip("test disabled; use -tcpbig to enable")
676 }
677
678 for _, writev := range []bool{false, true} {
679 t.Run(fmt.Sprintf("writev=%v", writev), func(t *testing.T) {
680 ln, err := newLocalListener("tcp")
681 if err != nil {
682 t.Fatal(err)
683 }
684 defer ln.Close()
685
686 x := int(1 << 30)
687 x = x*5 + 1<<20
688 done := make(chan int)
689 go func() {
690 defer close(done)
691 c, err := ln.Accept()
692 if err != nil {
693 t.Error(err)
694 return
695 }
696 buf := make([]byte, x)
697 var n int
698 if writev {
699 var n64 int64
700 n64, err = (&Buffers{buf}).WriteTo(c)
701 n = int(n64)
702 } else {
703 n, err = c.Write(buf)
704 }
705 if n != len(buf) || err != nil {
706 t.Errorf("Write(buf) = %d, %v, want %d, nil", n, err, x)
707 }
708 c.Close()
709 }()
710
711 c, err := Dial("tcp", ln.Addr().String())
712 if err != nil {
713 t.Fatal(err)
714 }
715 buf := make([]byte, x)
716 n, err := io.ReadFull(c, buf)
717 if n != len(buf) || err != nil {
718 t.Errorf("Read(buf) = %d, %v, want %d, nil", n, err, x)
719 }
720 c.Close()
721 <-done
722 })
723 }
724 }
725
726 func TestCopyPipeIntoTCP(t *testing.T) {
727 ln, err := newLocalListener("tcp")
728 if err != nil {
729 t.Fatal(err)
730 }
731 defer ln.Close()
732
733 errc := make(chan error, 1)
734 defer func() {
735 if err := <-errc; err != nil {
736 t.Error(err)
737 }
738 }()
739 go func() {
740 c, err := ln.Accept()
741 if err != nil {
742 errc <- err
743 return
744 }
745 defer c.Close()
746
747 buf := make([]byte, 100)
748 n, err := io.ReadFull(c, buf)
749 if err != io.ErrUnexpectedEOF || n != 2 {
750 errc <- fmt.Errorf("got err=%q n=%v; want err=%q n=2", err, n, io.ErrUnexpectedEOF)
751 return
752 }
753
754 errc <- nil
755 }()
756
757 c, err := Dial("tcp", ln.Addr().String())
758 if err != nil {
759 t.Fatal(err)
760 }
761 defer c.Close()
762
763 r, w, err := os.Pipe()
764 if err != nil {
765 t.Fatal(err)
766 }
767 defer r.Close()
768
769 errc2 := make(chan error, 1)
770 defer func() {
771 if err := <-errc2; err != nil {
772 t.Error(err)
773 }
774 }()
775
776 defer w.Close()
777
778 go func() {
779 _, err := io.Copy(c, r)
780 errc2 <- err
781 }()
782
783
784
785 packet := make([]byte, 1)
786 _, err = w.Write(packet)
787 if err != nil {
788 t.Fatal(err)
789 }
790 time.Sleep(100 * time.Millisecond)
791 _, err = w.Write(packet)
792 if err != nil {
793 t.Fatal(err)
794 }
795 }
796
797 func BenchmarkSetReadDeadline(b *testing.B) {
798 ln, err := newLocalListener("tcp")
799 if err != nil {
800 b.Fatal(err)
801 }
802 defer ln.Close()
803 var serv Conn
804 done := make(chan error)
805 go func() {
806 var err error
807 serv, err = ln.Accept()
808 done <- err
809 }()
810 c, err := Dial("tcp", ln.Addr().String())
811 if err != nil {
812 b.Fatal(err)
813 }
814 defer c.Close()
815 if err := <-done; err != nil {
816 b.Fatal(err)
817 }
818 defer serv.Close()
819 c.SetWriteDeadline(time.Now().Add(2 * time.Hour))
820 deadline := time.Now().Add(time.Hour)
821 b.ResetTimer()
822 for i := 0; i < b.N; i++ {
823 c.SetReadDeadline(deadline)
824 deadline = deadline.Add(1)
825 }
826 }
827
View as plain text