github.com/slayercat/go@v0.0.0-20170428012452-c51559813f61/src/net/tcpsock_test.go (about) 1 // Copyright 2012 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. 4 5 package net 6 7 import ( 8 "fmt" 9 "internal/testenv" 10 "io" 11 "reflect" 12 "runtime" 13 "sync" 14 "testing" 15 "time" 16 ) 17 18 func BenchmarkTCP4OneShot(b *testing.B) { 19 benchmarkTCP(b, false, false, "127.0.0.1:0") 20 } 21 22 func BenchmarkTCP4OneShotTimeout(b *testing.B) { 23 benchmarkTCP(b, false, true, "127.0.0.1:0") 24 } 25 26 func BenchmarkTCP4Persistent(b *testing.B) { 27 benchmarkTCP(b, true, false, "127.0.0.1:0") 28 } 29 30 func BenchmarkTCP4PersistentTimeout(b *testing.B) { 31 benchmarkTCP(b, true, true, "127.0.0.1:0") 32 } 33 34 func BenchmarkTCP6OneShot(b *testing.B) { 35 if !supportsIPv6() { 36 b.Skip("ipv6 is not supported") 37 } 38 benchmarkTCP(b, false, false, "[::1]:0") 39 } 40 41 func BenchmarkTCP6OneShotTimeout(b *testing.B) { 42 if !supportsIPv6() { 43 b.Skip("ipv6 is not supported") 44 } 45 benchmarkTCP(b, false, true, "[::1]:0") 46 } 47 48 func BenchmarkTCP6Persistent(b *testing.B) { 49 if !supportsIPv6() { 50 b.Skip("ipv6 is not supported") 51 } 52 benchmarkTCP(b, true, false, "[::1]:0") 53 } 54 55 func BenchmarkTCP6PersistentTimeout(b *testing.B) { 56 if !supportsIPv6() { 57 b.Skip("ipv6 is not supported") 58 } 59 benchmarkTCP(b, true, true, "[::1]:0") 60 } 61 62 func benchmarkTCP(b *testing.B, persistent, timeout bool, laddr string) { 63 testHookUninstaller.Do(uninstallTestHooks) 64 65 const msgLen = 512 66 conns := b.N 67 numConcurrent := runtime.GOMAXPROCS(-1) * 2 68 msgs := 1 69 if persistent { 70 conns = numConcurrent 71 msgs = b.N / conns 72 if msgs == 0 { 73 msgs = 1 74 } 75 if conns > b.N { 76 conns = b.N 77 } 78 } 79 sendMsg := func(c Conn, buf []byte) bool { 80 n, err := c.Write(buf) 81 if n != len(buf) || err != nil { 82 b.Log(err) 83 return false 84 } 85 return true 86 } 87 recvMsg := func(c Conn, buf []byte) bool { 88 for read := 0; read != len(buf); { 89 n, err := c.Read(buf) 90 read += n 91 if err != nil { 92 b.Log(err) 93 return false 94 } 95 } 96 return true 97 } 98 ln, err := Listen("tcp", laddr) 99 if err != nil { 100 b.Fatal(err) 101 } 102 defer ln.Close() 103 serverSem := make(chan bool, numConcurrent) 104 // Acceptor. 105 go func() { 106 for { 107 c, err := ln.Accept() 108 if err != nil { 109 break 110 } 111 serverSem <- true 112 // Server connection. 113 go func(c Conn) { 114 defer func() { 115 c.Close() 116 <-serverSem 117 }() 118 if timeout { 119 c.SetDeadline(time.Now().Add(time.Hour)) // Not intended to fire. 120 } 121 var buf [msgLen]byte 122 for m := 0; m < msgs; m++ { 123 if !recvMsg(c, buf[:]) || !sendMsg(c, buf[:]) { 124 break 125 } 126 } 127 }(c) 128 } 129 }() 130 clientSem := make(chan bool, numConcurrent) 131 for i := 0; i < conns; i++ { 132 clientSem <- true 133 // Client connection. 134 go func() { 135 defer func() { 136 <-clientSem 137 }() 138 c, err := Dial("tcp", ln.Addr().String()) 139 if err != nil { 140 b.Log(err) 141 return 142 } 143 defer c.Close() 144 if timeout { 145 c.SetDeadline(time.Now().Add(time.Hour)) // Not intended to fire. 146 } 147 var buf [msgLen]byte 148 for m := 0; m < msgs; m++ { 149 if !sendMsg(c, buf[:]) || !recvMsg(c, buf[:]) { 150 break 151 } 152 } 153 }() 154 } 155 for i := 0; i < numConcurrent; i++ { 156 clientSem <- true 157 serverSem <- true 158 } 159 } 160 161 func BenchmarkTCP4ConcurrentReadWrite(b *testing.B) { 162 benchmarkTCPConcurrentReadWrite(b, "127.0.0.1:0") 163 } 164 165 func BenchmarkTCP6ConcurrentReadWrite(b *testing.B) { 166 if !supportsIPv6() { 167 b.Skip("ipv6 is not supported") 168 } 169 benchmarkTCPConcurrentReadWrite(b, "[::1]:0") 170 } 171 172 func benchmarkTCPConcurrentReadWrite(b *testing.B, laddr string) { 173 testHookUninstaller.Do(uninstallTestHooks) 174 175 // The benchmark creates GOMAXPROCS client/server pairs. 176 // Each pair creates 4 goroutines: client reader/writer and server reader/writer. 177 // The benchmark stresses concurrent reading and writing to the same connection. 178 // Such pattern is used in net/http and net/rpc. 179 180 b.StopTimer() 181 182 P := runtime.GOMAXPROCS(0) 183 N := b.N / P 184 W := 1000 185 186 // Setup P client/server connections. 187 clients := make([]Conn, P) 188 servers := make([]Conn, P) 189 ln, err := Listen("tcp", laddr) 190 if err != nil { 191 b.Fatal(err) 192 } 193 defer ln.Close() 194 done := make(chan bool) 195 go func() { 196 for p := 0; p < P; p++ { 197 s, err := ln.Accept() 198 if err != nil { 199 b.Error(err) 200 return 201 } 202 servers[p] = s 203 } 204 done <- true 205 }() 206 for p := 0; p < P; p++ { 207 c, err := Dial("tcp", ln.Addr().String()) 208 if err != nil { 209 b.Fatal(err) 210 } 211 clients[p] = c 212 } 213 <-done 214 215 b.StartTimer() 216 217 var wg sync.WaitGroup 218 wg.Add(4 * P) 219 for p := 0; p < P; p++ { 220 // Client writer. 221 go func(c Conn) { 222 defer wg.Done() 223 var buf [1]byte 224 for i := 0; i < N; i++ { 225 v := byte(i) 226 for w := 0; w < W; w++ { 227 v *= v 228 } 229 buf[0] = v 230 _, err := c.Write(buf[:]) 231 if err != nil { 232 b.Error(err) 233 return 234 } 235 } 236 }(clients[p]) 237 238 // Pipe between server reader and server writer. 239 pipe := make(chan byte, 128) 240 241 // Server reader. 242 go func(s Conn) { 243 defer wg.Done() 244 var buf [1]byte 245 for i := 0; i < N; i++ { 246 _, err := s.Read(buf[:]) 247 if err != nil { 248 b.Error(err) 249 return 250 } 251 pipe <- buf[0] 252 } 253 }(servers[p]) 254 255 // Server writer. 256 go func(s Conn) { 257 defer wg.Done() 258 var buf [1]byte 259 for i := 0; i < N; i++ { 260 v := <-pipe 261 for w := 0; w < W; w++ { 262 v *= v 263 } 264 buf[0] = v 265 _, err := s.Write(buf[:]) 266 if err != nil { 267 b.Error(err) 268 return 269 } 270 } 271 s.Close() 272 }(servers[p]) 273 274 // Client reader. 275 go func(c Conn) { 276 defer wg.Done() 277 var buf [1]byte 278 for i := 0; i < N; i++ { 279 _, err := c.Read(buf[:]) 280 if err != nil { 281 b.Error(err) 282 return 283 } 284 } 285 c.Close() 286 }(clients[p]) 287 } 288 wg.Wait() 289 } 290 291 type resolveTCPAddrTest struct { 292 network string 293 litAddrOrName string 294 addr *TCPAddr 295 err error 296 } 297 298 var resolveTCPAddrTests = []resolveTCPAddrTest{ 299 {"tcp", "127.0.0.1:0", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil}, 300 {"tcp4", "127.0.0.1:65535", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 65535}, nil}, 301 302 {"tcp", "[::1]:0", &TCPAddr{IP: ParseIP("::1"), Port: 0}, nil}, 303 {"tcp6", "[::1]:65535", &TCPAddr{IP: ParseIP("::1"), Port: 65535}, nil}, 304 305 {"tcp", "[::1%en0]:1", &TCPAddr{IP: ParseIP("::1"), Port: 1, Zone: "en0"}, nil}, 306 {"tcp6", "[::1%911]:2", &TCPAddr{IP: ParseIP("::1"), Port: 2, Zone: "911"}, nil}, 307 308 {"", "127.0.0.1:0", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil}, // Go 1.0 behavior 309 {"", "[::1]:0", &TCPAddr{IP: ParseIP("::1"), Port: 0}, nil}, // Go 1.0 behavior 310 311 {"tcp", ":12345", &TCPAddr{Port: 12345}, nil}, 312 313 {"http", "127.0.0.1:0", nil, UnknownNetworkError("http")}, 314 315 {"tcp", "127.0.0.1:http", &TCPAddr{IP: ParseIP("127.0.0.1"), Port: 80}, nil}, 316 {"tcp", "[::ffff:127.0.0.1]:http", &TCPAddr{IP: ParseIP("::ffff:127.0.0.1"), Port: 80}, nil}, 317 {"tcp", "[2001:db8::1]:http", &TCPAddr{IP: ParseIP("2001:db8::1"), Port: 80}, nil}, 318 {"tcp4", "127.0.0.1:http", &TCPAddr{IP: ParseIP("127.0.0.1"), Port: 80}, nil}, 319 {"tcp4", "[::ffff:127.0.0.1]:http", &TCPAddr{IP: ParseIP("127.0.0.1"), Port: 80}, nil}, 320 {"tcp6", "[2001:db8::1]:http", &TCPAddr{IP: ParseIP("2001:db8::1"), Port: 80}, nil}, 321 322 {"tcp4", "[2001:db8::1]:http", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "2001:db8::1"}}, 323 {"tcp6", "127.0.0.1:http", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "127.0.0.1"}}, 324 {"tcp6", "[::ffff:127.0.0.1]:http", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "::ffff:127.0.0.1"}}, 325 } 326 327 func TestResolveTCPAddr(t *testing.T) { 328 origTestHookLookupIP := testHookLookupIP 329 defer func() { testHookLookupIP = origTestHookLookupIP }() 330 testHookLookupIP = lookupLocalhost 331 332 for _, tt := range resolveTCPAddrTests { 333 addr, err := ResolveTCPAddr(tt.network, tt.litAddrOrName) 334 if !reflect.DeepEqual(addr, tt.addr) || !reflect.DeepEqual(err, tt.err) { 335 t.Errorf("ResolveTCPAddr(%q, %q) = %#v, %v, want %#v, %v", tt.network, tt.litAddrOrName, addr, err, tt.addr, tt.err) 336 continue 337 } 338 if err == nil { 339 addr2, err := ResolveTCPAddr(addr.Network(), addr.String()) 340 if !reflect.DeepEqual(addr2, tt.addr) || err != tt.err { 341 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) 342 } 343 } 344 } 345 } 346 347 var tcpListenerNameTests = []struct { 348 net string 349 laddr *TCPAddr 350 }{ 351 {"tcp4", &TCPAddr{IP: IPv4(127, 0, 0, 1)}}, 352 {"tcp4", &TCPAddr{}}, 353 {"tcp4", nil}, 354 } 355 356 func TestTCPListenerName(t *testing.T) { 357 testenv.MustHaveExternalNetwork(t) 358 359 for _, tt := range tcpListenerNameTests { 360 ln, err := ListenTCP(tt.net, tt.laddr) 361 if err != nil { 362 t.Fatal(err) 363 } 364 defer ln.Close() 365 la := ln.Addr() 366 if a, ok := la.(*TCPAddr); !ok || a.Port == 0 { 367 t.Fatalf("got %v; expected a proper address with non-zero port number", la) 368 } 369 } 370 } 371 372 func TestIPv6LinkLocalUnicastTCP(t *testing.T) { 373 testenv.MustHaveExternalNetwork(t) 374 375 if !supportsIPv6() { 376 t.Skip("IPv6 is not supported") 377 } 378 379 for i, tt := range ipv6LinkLocalUnicastTCPTests { 380 ln, err := Listen(tt.network, tt.address) 381 if err != nil { 382 // It might return "LookupHost returned no 383 // suitable address" error on some platforms. 384 t.Log(err) 385 continue 386 } 387 ls, err := (&streamListener{Listener: ln}).newLocalServer() 388 if err != nil { 389 t.Fatal(err) 390 } 391 defer ls.teardown() 392 ch := make(chan error, 1) 393 handler := func(ls *localServer, ln Listener) { transponder(ln, ch) } 394 if err := ls.buildup(handler); err != nil { 395 t.Fatal(err) 396 } 397 if la, ok := ln.Addr().(*TCPAddr); !ok || !tt.nameLookup && la.Zone == "" { 398 t.Fatalf("got %v; expected a proper address with zone identifier", la) 399 } 400 401 c, err := Dial(tt.network, ls.Listener.Addr().String()) 402 if err != nil { 403 t.Fatal(err) 404 } 405 defer c.Close() 406 if la, ok := c.LocalAddr().(*TCPAddr); !ok || !tt.nameLookup && la.Zone == "" { 407 t.Fatalf("got %v; expected a proper address with zone identifier", la) 408 } 409 if ra, ok := c.RemoteAddr().(*TCPAddr); !ok || !tt.nameLookup && ra.Zone == "" { 410 t.Fatalf("got %v; expected a proper address with zone identifier", ra) 411 } 412 413 if _, err := c.Write([]byte("TCP OVER IPV6 LINKLOCAL TEST")); err != nil { 414 t.Fatal(err) 415 } 416 b := make([]byte, 32) 417 if _, err := c.Read(b); err != nil { 418 t.Fatal(err) 419 } 420 421 for err := range ch { 422 t.Errorf("#%d: %v", i, err) 423 } 424 } 425 } 426 427 func TestTCPConcurrentAccept(t *testing.T) { 428 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4)) 429 ln, err := Listen("tcp", "127.0.0.1:0") 430 if err != nil { 431 t.Fatal(err) 432 } 433 const N = 10 434 var wg sync.WaitGroup 435 wg.Add(N) 436 for i := 0; i < N; i++ { 437 go func() { 438 for { 439 c, err := ln.Accept() 440 if err != nil { 441 break 442 } 443 c.Close() 444 } 445 wg.Done() 446 }() 447 } 448 attempts := 10 * N 449 fails := 0 450 d := &Dialer{Timeout: 200 * time.Millisecond} 451 for i := 0; i < attempts; i++ { 452 c, err := d.Dial("tcp", ln.Addr().String()) 453 if err != nil { 454 fails++ 455 } else { 456 c.Close() 457 } 458 } 459 ln.Close() 460 wg.Wait() 461 if fails > attempts/9 { // see issues 7400 and 7541 462 t.Fatalf("too many Dial failed: %v", fails) 463 } 464 if fails > 0 { 465 t.Logf("# of failed Dials: %v", fails) 466 } 467 } 468 469 func TestTCPReadWriteAllocs(t *testing.T) { 470 switch runtime.GOOS { 471 case "plan9": 472 // The implementation of asynchronous cancelable 473 // I/O on Plan 9 allocates memory. 474 // See net/fd_io_plan9.go. 475 t.Skipf("not supported on %s", runtime.GOOS) 476 case "nacl": 477 // NaCl needs to allocate pseudo file descriptor 478 // stuff. See syscall/fd_nacl.go. 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 // Acceptor. 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 // Server connection. 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 // Client connection. 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 // TODO(brainman): do not know why it hangs. 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 // Try to connect to that address repeatedly. 646 n := 100000 647 if testing.Short() { 648 n = 1000 649 } 650 switch runtime.GOOS { 651 case "darwin", "dragonfly", "freebsd", "netbsd", "openbsd", "plan9", "solaris", "windows": 652 // Non-Linux systems take a long time to figure 653 // out that there is nothing listening on localhost. 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 // Test that >32-bit reads work on 64-bit systems. 672 // On 32-bit systems this tests that maxint reads work. 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 // just over 5 GB on 64-bit, just over 1GB on 32-bit 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 }