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 5package net 6 7import ( 8 "context" 9 "errors" 10 "fmt" 11 "internal/testenv" 12 "io" 13 "os" 14 "reflect" 15 "runtime" 16 "sync" 17 "testing" 18 "time" 19) 20 21func BenchmarkTCP4OneShot(b *testing.B) { 22 benchmarkTCP(b, false, false, "127.0.0.1:0") 23} 24 25func BenchmarkTCP4OneShotTimeout(b *testing.B) { 26 benchmarkTCP(b, false, true, "127.0.0.1:0") 27} 28 29func BenchmarkTCP4Persistent(b *testing.B) { 30 benchmarkTCP(b, true, false, "127.0.0.1:0") 31} 32 33func BenchmarkTCP4PersistentTimeout(b *testing.B) { 34 benchmarkTCP(b, true, true, "127.0.0.1:0") 35} 36 37func BenchmarkTCP6OneShot(b *testing.B) { 38 if !supportsIPv6() { 39 b.Skip("ipv6 is not supported") 40 } 41 benchmarkTCP(b, false, false, "[::1]:0") 42} 43 44func BenchmarkTCP6OneShotTimeout(b *testing.B) { 45 if !supportsIPv6() { 46 b.Skip("ipv6 is not supported") 47 } 48 benchmarkTCP(b, false, true, "[::1]:0") 49} 50 51func BenchmarkTCP6Persistent(b *testing.B) { 52 if !supportsIPv6() { 53 b.Skip("ipv6 is not supported") 54 } 55 benchmarkTCP(b, true, false, "[::1]:0") 56} 57 58func BenchmarkTCP6PersistentTimeout(b *testing.B) { 59 if !supportsIPv6() { 60 b.Skip("ipv6 is not supported") 61 } 62 benchmarkTCP(b, true, true, "[::1]:0") 63} 64 65func benchmarkTCP(b *testing.B, persistent, timeout bool, laddr string) { 66 testHookUninstaller.Do(uninstallTestHooks) 67 68 const msgLen = 512 69 conns := b.N 70 numConcurrent := runtime.GOMAXPROCS(-1) * 2 71 msgs := 1 72 if persistent { 73 conns = numConcurrent 74 msgs = b.N / conns 75 if msgs == 0 { 76 msgs = 1 77 } 78 if conns > b.N { 79 conns = b.N 80 } 81 } 82 sendMsg := func(c Conn, buf []byte) bool { 83 n, err := c.Write(buf) 84 if n != len(buf) || err != nil { 85 b.Log(err) 86 return false 87 } 88 return true 89 } 90 recvMsg := func(c Conn, buf []byte) bool { 91 for read := 0; read != len(buf); { 92 n, err := c.Read(buf) 93 read += n 94 if err != nil { 95 b.Log(err) 96 return false 97 } 98 } 99 return true 100 } 101 ln, err := Listen("tcp", laddr) 102 if err != nil { 103 b.Fatal(err) 104 } 105 defer ln.Close() 106 serverSem := make(chan bool, numConcurrent) 107 // Acceptor. 108 go func() { 109 for { 110 c, err := ln.Accept() 111 if err != nil { 112 break 113 } 114 serverSem <- true 115 // Server connection. 116 go func(c Conn) { 117 defer func() { 118 c.Close() 119 <-serverSem 120 }() 121 if timeout { 122 c.SetDeadline(time.Now().Add(time.Hour)) // Not intended to fire. 123 } 124 var buf [msgLen]byte 125 for m := 0; m < msgs; m++ { 126 if !recvMsg(c, buf[:]) || !sendMsg(c, buf[:]) { 127 break 128 } 129 } 130 }(c) 131 } 132 }() 133 clientSem := make(chan bool, numConcurrent) 134 for i := 0; i < conns; i++ { 135 clientSem <- true 136 // Client connection. 137 go func() { 138 defer func() { 139 <-clientSem 140 }() 141 c, err := Dial("tcp", ln.Addr().String()) 142 if err != nil { 143 b.Log(err) 144 return 145 } 146 defer c.Close() 147 if timeout { 148 c.SetDeadline(time.Now().Add(time.Hour)) // Not intended to fire. 149 } 150 var buf [msgLen]byte 151 for m := 0; m < msgs; m++ { 152 if !sendMsg(c, buf[:]) || !recvMsg(c, buf[:]) { 153 break 154 } 155 } 156 }() 157 } 158 for i := 0; i < numConcurrent; i++ { 159 clientSem <- true 160 serverSem <- true 161 } 162} 163 164func BenchmarkTCP4ConcurrentReadWrite(b *testing.B) { 165 benchmarkTCPConcurrentReadWrite(b, "127.0.0.1:0") 166} 167 168func BenchmarkTCP6ConcurrentReadWrite(b *testing.B) { 169 if !supportsIPv6() { 170 b.Skip("ipv6 is not supported") 171 } 172 benchmarkTCPConcurrentReadWrite(b, "[::1]:0") 173} 174 175func benchmarkTCPConcurrentReadWrite(b *testing.B, laddr string) { 176 testHookUninstaller.Do(uninstallTestHooks) 177 178 // The benchmark creates GOMAXPROCS client/server pairs. 179 // Each pair creates 4 goroutines: client reader/writer and server reader/writer. 180 // The benchmark stresses concurrent reading and writing to the same connection. 181 // Such pattern is used in net/http and net/rpc. 182 183 b.StopTimer() 184 185 P := runtime.GOMAXPROCS(0) 186 N := b.N / P 187 W := 1000 188 189 // Setup P client/server connections. 190 clients := make([]Conn, P) 191 servers := make([]Conn, P) 192 ln, err := Listen("tcp", laddr) 193 if err != nil { 194 b.Fatal(err) 195 } 196 defer ln.Close() 197 done := make(chan bool) 198 go func() { 199 for p := 0; p < P; p++ { 200 s, err := ln.Accept() 201 if err != nil { 202 b.Error(err) 203 return 204 } 205 servers[p] = s 206 } 207 done <- true 208 }() 209 for p := 0; p < P; p++ { 210 c, err := Dial("tcp", ln.Addr().String()) 211 if err != nil { 212 b.Fatal(err) 213 } 214 clients[p] = c 215 } 216 <-done 217 218 b.StartTimer() 219 220 var wg sync.WaitGroup 221 wg.Add(4 * P) 222 for p := 0; p < P; p++ { 223 // Client writer. 224 go func(c Conn) { 225 defer wg.Done() 226 var buf [1]byte 227 for i := 0; i < N; i++ { 228 v := byte(i) 229 for w := 0; w < W; w++ { 230 v *= v 231 } 232 buf[0] = v 233 _, err := c.Write(buf[:]) 234 if err != nil { 235 b.Error(err) 236 return 237 } 238 } 239 }(clients[p]) 240 241 // Pipe between server reader and server writer. 242 pipe := make(chan byte, 128) 243 244 // Server reader. 245 go func(s Conn) { 246 defer wg.Done() 247 var buf [1]byte 248 for i := 0; i < N; i++ { 249 _, err := s.Read(buf[:]) 250 if err != nil { 251 b.Error(err) 252 return 253 } 254 pipe <- buf[0] 255 } 256 }(servers[p]) 257 258 // Server writer. 259 go func(s Conn) { 260 defer wg.Done() 261 var buf [1]byte 262 for i := 0; i < N; i++ { 263 v := <-pipe 264 for w := 0; w < W; w++ { 265 v *= v 266 } 267 buf[0] = v 268 _, err := s.Write(buf[:]) 269 if err != nil { 270 b.Error(err) 271 return 272 } 273 } 274 s.Close() 275 }(servers[p]) 276 277 // Client reader. 278 go func(c Conn) { 279 defer wg.Done() 280 var buf [1]byte 281 for i := 0; i < N; i++ { 282 _, err := c.Read(buf[:]) 283 if err != nil { 284 b.Error(err) 285 return 286 } 287 } 288 c.Close() 289 }(clients[p]) 290 } 291 wg.Wait() 292} 293 294type resolveTCPAddrTest struct { 295 network string 296 litAddrOrName string 297 addr *TCPAddr 298 err error 299} 300 301var resolveTCPAddrTests = []resolveTCPAddrTest{ 302 {"tcp", "127.0.0.1:0", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil}, 303 {"tcp4", "127.0.0.1:65535", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 65535}, nil}, 304 305 {"tcp", "[::1]:0", &TCPAddr{IP: ParseIP("::1"), Port: 0}, nil}, 306 {"tcp6", "[::1]:65535", &TCPAddr{IP: ParseIP("::1"), Port: 65535}, nil}, 307 308 {"tcp", "[::1%en0]:1", &TCPAddr{IP: ParseIP("::1"), Port: 1, Zone: "en0"}, nil}, 309 {"tcp6", "[::1%911]:2", &TCPAddr{IP: ParseIP("::1"), Port: 2, Zone: "911"}, nil}, 310 311 {"", "127.0.0.1:0", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil}, // Go 1.0 behavior 312 {"", "[::1]:0", &TCPAddr{IP: ParseIP("::1"), Port: 0}, nil}, // Go 1.0 behavior 313 314 {"tcp", ":12345", &TCPAddr{Port: 12345}, nil}, 315 316 {"http", "127.0.0.1:0", nil, UnknownNetworkError("http")}, 317 318 {"tcp", "127.0.0.1:http", &TCPAddr{IP: ParseIP("127.0.0.1"), Port: 80}, nil}, 319 {"tcp", "[::ffff:127.0.0.1]:http", &TCPAddr{IP: ParseIP("::ffff:127.0.0.1"), Port: 80}, nil}, 320 {"tcp", "[2001:db8::1]:http", &TCPAddr{IP: ParseIP("2001:db8::1"), Port: 80}, nil}, 321 {"tcp4", "127.0.0.1:http", &TCPAddr{IP: ParseIP("127.0.0.1"), Port: 80}, nil}, 322 {"tcp4", "[::ffff:127.0.0.1]:http", &TCPAddr{IP: ParseIP("127.0.0.1"), Port: 80}, nil}, 323 {"tcp6", "[2001:db8::1]:http", &TCPAddr{IP: ParseIP("2001:db8::1"), Port: 80}, nil}, 324 325 {"tcp4", "[2001:db8::1]:http", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "2001:db8::1"}}, 326 {"tcp6", "127.0.0.1:http", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "127.0.0.1"}}, 327 {"tcp6", "[::ffff:127.0.0.1]:http", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "::ffff:127.0.0.1"}}, 328} 329 330func TestResolveTCPAddr(t *testing.T) { 331 origTestHookLookupIP := testHookLookupIP 332 defer func() { testHookLookupIP = origTestHookLookupIP }() 333 testHookLookupIP = lookupLocalhost 334 335 for _, tt := range resolveTCPAddrTests { 336 addr, err := ResolveTCPAddr(tt.network, tt.litAddrOrName) 337 if !reflect.DeepEqual(addr, tt.addr) || !reflect.DeepEqual(err, tt.err) { 338 t.Errorf("ResolveTCPAddr(%q, %q) = %#v, %v, want %#v, %v", tt.network, tt.litAddrOrName, addr, err, tt.addr, tt.err) 339 continue 340 } 341 if err == nil { 342 addr2, err := ResolveTCPAddr(addr.Network(), addr.String()) 343 if !reflect.DeepEqual(addr2, tt.addr) || err != tt.err { 344 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) 345 } 346 } 347 } 348} 349 350var tcpListenerNameTests = []struct { 351 net string 352 laddr *TCPAddr 353}{ 354 {"tcp4", &TCPAddr{IP: IPv4(127, 0, 0, 1)}}, 355 {"tcp4", &TCPAddr{}}, 356 {"tcp4", nil}, 357} 358 359func TestTCPListenerName(t *testing.T) { 360 testenv.MustHaveExternalNetwork(t) 361 362 for _, tt := range tcpListenerNameTests { 363 ln, err := ListenTCP(tt.net, tt.laddr) 364 if err != nil { 365 t.Fatal(err) 366 } 367 defer ln.Close() 368 la := ln.Addr() 369 if a, ok := la.(*TCPAddr); !ok || a.Port == 0 { 370 t.Fatalf("got %v; expected a proper address with non-zero port number", la) 371 } 372 } 373} 374 375func TestIPv6LinkLocalUnicastTCP(t *testing.T) { 376 testenv.MustHaveExternalNetwork(t) 377 378 if !supportsIPv6() { 379 t.Skip("IPv6 is not supported") 380 } 381 382 for i, tt := range ipv6LinkLocalUnicastTCPTests { 383 ln, err := Listen(tt.network, tt.address) 384 if err != nil { 385 // It might return "LookupHost returned no 386 // suitable address" error on some platforms. 387 t.Log(err) 388 continue 389 } 390 ls := (&streamListener{Listener: ln}).newLocalServer() 391 defer ls.teardown() 392 ch := make(chan error, 1) 393 handler := func(ls *localServer, ln Listener) { ls.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 427func 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 469func 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 } 477 478 ln, err := Listen("tcp", "127.0.0.1:0") 479 if err != nil { 480 t.Fatal(err) 481 } 482 defer ln.Close() 483 var server Conn 484 errc := make(chan error, 1) 485 go func() { 486 var err error 487 server, err = ln.Accept() 488 errc <- err 489 }() 490 client, err := Dial("tcp", ln.Addr().String()) 491 if err != nil { 492 t.Fatal(err) 493 } 494 defer client.Close() 495 if err := <-errc; err != nil { 496 t.Fatal(err) 497 } 498 defer server.Close() 499 500 var buf [128]byte 501 allocs := testing.AllocsPerRun(1000, func() { 502 _, err := server.Write(buf[:]) 503 if err != nil { 504 t.Fatal(err) 505 } 506 _, err = io.ReadFull(client, buf[:]) 507 if err != nil { 508 t.Fatal(err) 509 } 510 }) 511 if allocs > 0 { 512 t.Fatalf("got %v; want 0", allocs) 513 } 514 515 var bufwrt [128]byte 516 ch := make(chan bool) 517 defer close(ch) 518 go func() { 519 for <-ch { 520 _, err := server.Write(bufwrt[:]) 521 errc <- err 522 } 523 }() 524 allocs = testing.AllocsPerRun(1000, func() { 525 ch <- true 526 if _, err = io.ReadFull(client, buf[:]); err != nil { 527 t.Fatal(err) 528 } 529 if err := <-errc; err != nil { 530 t.Fatal(err) 531 } 532 }) 533 if allocs > 0 { 534 t.Fatalf("got %v; want 0", allocs) 535 } 536} 537 538func TestTCPStress(t *testing.T) { 539 const conns = 2 540 const msgLen = 512 541 msgs := int(1e4) 542 if testing.Short() { 543 msgs = 1e2 544 } 545 546 sendMsg := func(c Conn, buf []byte) bool { 547 n, err := c.Write(buf) 548 if n != len(buf) || err != nil { 549 t.Log(err) 550 return false 551 } 552 return true 553 } 554 recvMsg := func(c Conn, buf []byte) bool { 555 for read := 0; read != len(buf); { 556 n, err := c.Read(buf) 557 read += n 558 if err != nil { 559 t.Log(err) 560 return false 561 } 562 } 563 return true 564 } 565 566 ln, err := Listen("tcp", "127.0.0.1:0") 567 if err != nil { 568 t.Fatal(err) 569 } 570 done := make(chan bool) 571 // Acceptor. 572 go func() { 573 defer func() { 574 done <- true 575 }() 576 for { 577 c, err := ln.Accept() 578 if err != nil { 579 break 580 } 581 // Server connection. 582 go func(c Conn) { 583 defer c.Close() 584 var buf [msgLen]byte 585 for m := 0; m < msgs; m++ { 586 if !recvMsg(c, buf[:]) || !sendMsg(c, buf[:]) { 587 break 588 } 589 } 590 }(c) 591 } 592 }() 593 for i := 0; i < conns; i++ { 594 // Client connection. 595 go func() { 596 defer func() { 597 done <- true 598 }() 599 c, err := Dial("tcp", ln.Addr().String()) 600 if err != nil { 601 t.Log(err) 602 return 603 } 604 defer c.Close() 605 var buf [msgLen]byte 606 for m := 0; m < msgs; m++ { 607 if !sendMsg(c, buf[:]) || !recvMsg(c, buf[:]) { 608 break 609 } 610 } 611 }() 612 } 613 for i := 0; i < conns; i++ { 614 <-done 615 } 616 ln.Close() 617 <-done 618} 619 620// Test that >32-bit reads work on 64-bit systems. 621// On 32-bit systems this tests that maxint reads work. 622func TestTCPBig(t *testing.T) { 623 if !*testTCPBig { 624 t.Skip("test disabled; use -tcpbig to enable") 625 } 626 627 for _, writev := range []bool{false, true} { 628 t.Run(fmt.Sprintf("writev=%v", writev), func(t *testing.T) { 629 ln := newLocalListener(t, "tcp") 630 defer ln.Close() 631 632 x := int(1 << 30) 633 x = x*5 + 1<<20 // just over 5 GB on 64-bit, just over 1GB on 32-bit 634 done := make(chan int) 635 go func() { 636 defer close(done) 637 c, err := ln.Accept() 638 if err != nil { 639 t.Error(err) 640 return 641 } 642 buf := make([]byte, x) 643 var n int 644 if writev { 645 var n64 int64 646 n64, err = (&Buffers{buf}).WriteTo(c) 647 n = int(n64) 648 } else { 649 n, err = c.Write(buf) 650 } 651 if n != len(buf) || err != nil { 652 t.Errorf("Write(buf) = %d, %v, want %d, nil", n, err, x) 653 } 654 c.Close() 655 }() 656 657 c, err := Dial("tcp", ln.Addr().String()) 658 if err != nil { 659 t.Fatal(err) 660 } 661 buf := make([]byte, x) 662 n, err := io.ReadFull(c, buf) 663 if n != len(buf) || err != nil { 664 t.Errorf("Read(buf) = %d, %v, want %d, nil", n, err, x) 665 } 666 c.Close() 667 <-done 668 }) 669 } 670} 671 672func TestCopyPipeIntoTCP(t *testing.T) { 673 switch runtime.GOOS { 674 case "js", "wasip1": 675 t.Skipf("skipping: os.Pipe not supported on %s", runtime.GOOS) 676 } 677 678 ln := newLocalListener(t, "tcp") 679 defer ln.Close() 680 681 errc := make(chan error, 1) 682 defer func() { 683 if err := <-errc; err != nil { 684 t.Error(err) 685 } 686 }() 687 go func() { 688 c, err := ln.Accept() 689 if err != nil { 690 errc <- err 691 return 692 } 693 defer c.Close() 694 695 buf := make([]byte, 100) 696 n, err := io.ReadFull(c, buf) 697 if err != io.ErrUnexpectedEOF || n != 2 { 698 errc <- fmt.Errorf("got err=%q n=%v; want err=%q n=2", err, n, io.ErrUnexpectedEOF) 699 return 700 } 701 702 errc <- nil 703 }() 704 705 c, err := Dial("tcp", ln.Addr().String()) 706 if err != nil { 707 t.Fatal(err) 708 } 709 defer c.Close() 710 711 r, w, err := os.Pipe() 712 if err != nil { 713 t.Fatal(err) 714 } 715 defer r.Close() 716 717 errc2 := make(chan error, 1) 718 defer func() { 719 if err := <-errc2; err != nil { 720 t.Error(err) 721 } 722 }() 723 724 defer w.Close() 725 726 go func() { 727 _, err := io.Copy(c, r) 728 errc2 <- err 729 }() 730 731 // Split write into 2 packets. That makes Windows TransmitFile 732 // drop second packet. 733 packet := make([]byte, 1) 734 _, err = w.Write(packet) 735 if err != nil { 736 t.Fatal(err) 737 } 738 time.Sleep(100 * time.Millisecond) 739 _, err = w.Write(packet) 740 if err != nil { 741 t.Fatal(err) 742 } 743} 744 745func BenchmarkSetReadDeadline(b *testing.B) { 746 ln := newLocalListener(b, "tcp") 747 defer ln.Close() 748 var serv Conn 749 done := make(chan error) 750 go func() { 751 var err error 752 serv, err = ln.Accept() 753 done <- err 754 }() 755 c, err := Dial("tcp", ln.Addr().String()) 756 if err != nil { 757 b.Fatal(err) 758 } 759 defer c.Close() 760 if err := <-done; err != nil { 761 b.Fatal(err) 762 } 763 defer serv.Close() 764 c.SetWriteDeadline(time.Now().Add(2 * time.Hour)) 765 deadline := time.Now().Add(time.Hour) 766 b.ResetTimer() 767 for i := 0; i < b.N; i++ { 768 c.SetReadDeadline(deadline) 769 deadline = deadline.Add(1) 770 } 771} 772 773func TestDialTCPDefaultKeepAlive(t *testing.T) { 774 ln := newLocalListener(t, "tcp") 775 defer ln.Close() 776 777 got := time.Duration(-1) 778 testHookSetKeepAlive = func(cfg KeepAliveConfig) { got = cfg.Idle } 779 defer func() { testHookSetKeepAlive = func(KeepAliveConfig) {} }() 780 781 c, err := DialTCP("tcp", nil, ln.Addr().(*TCPAddr)) 782 if err != nil { 783 t.Fatal(err) 784 } 785 defer c.Close() 786 787 if got != 0 { 788 t.Errorf("got keepalive %v; want %v", got, defaultTCPKeepAliveIdle) 789 } 790} 791 792func TestTCPListenAfterClose(t *testing.T) { 793 // Regression test for https://go.dev/issue/50216: 794 // after calling Close on a Listener, the fake net implementation would 795 // erroneously Accept a connection dialed before the call to Close. 796 797 ln := newLocalListener(t, "tcp") 798 defer ln.Close() 799 800 var wg sync.WaitGroup 801 ctx, cancel := context.WithCancel(context.Background()) 802 803 d := &Dialer{} 804 for n := 2; n > 0; n-- { 805 wg.Add(1) 806 go func() { 807 defer wg.Done() 808 809 c, err := d.DialContext(ctx, ln.Addr().Network(), ln.Addr().String()) 810 if err == nil { 811 <-ctx.Done() 812 c.Close() 813 } 814 }() 815 } 816 817 c, err := ln.Accept() 818 if err == nil { 819 c.Close() 820 } else { 821 t.Error(err) 822 } 823 time.Sleep(10 * time.Millisecond) 824 cancel() 825 wg.Wait() 826 ln.Close() 827 828 c, err = ln.Accept() 829 if !errors.Is(err, ErrClosed) { 830 if err == nil { 831 c.Close() 832 } 833 t.Errorf("after l.Close(), l.Accept() = _, %v\nwant %v", err, ErrClosed) 834 } 835} 836