github.com/code-reading/golang@v0.0.0-20220303082512-ba5bc0e589a3/go/src/net/dial_test.go (about) 1 // Copyright 2011 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 //go:build !js 6 // +build !js 7 8 package net 9 10 import ( 11 "bufio" 12 "context" 13 "internal/testenv" 14 "io" 15 "os" 16 "runtime" 17 "strings" 18 "sync" 19 "testing" 20 "time" 21 ) 22 23 var prohibitionaryDialArgTests = []struct { 24 network string 25 address string 26 }{ 27 {"tcp6", "127.0.0.1"}, 28 {"tcp6", "::ffff:127.0.0.1"}, 29 } 30 31 func TestProhibitionaryDialArg(t *testing.T) { 32 testenv.MustHaveExternalNetwork(t) 33 34 switch runtime.GOOS { 35 case "plan9": 36 t.Skipf("not supported on %s", runtime.GOOS) 37 } 38 if !supportsIPv4map() { 39 t.Skip("mapping ipv4 address inside ipv6 address not supported") 40 } 41 42 ln, err := Listen("tcp", "[::]:0") 43 if err != nil { 44 t.Fatal(err) 45 } 46 defer ln.Close() 47 48 _, port, err := SplitHostPort(ln.Addr().String()) 49 if err != nil { 50 t.Fatal(err) 51 } 52 53 for i, tt := range prohibitionaryDialArgTests { 54 c, err := Dial(tt.network, JoinHostPort(tt.address, port)) 55 if err == nil { 56 c.Close() 57 t.Errorf("#%d: %v", i, err) 58 } 59 } 60 } 61 62 func TestDialLocal(t *testing.T) { 63 ln, err := newLocalListener("tcp") 64 if err != nil { 65 t.Fatal(err) 66 } 67 defer ln.Close() 68 _, port, err := SplitHostPort(ln.Addr().String()) 69 if err != nil { 70 t.Fatal(err) 71 } 72 c, err := Dial("tcp", JoinHostPort("", port)) 73 if err != nil { 74 t.Fatal(err) 75 } 76 c.Close() 77 } 78 79 func TestDialerDualStackFDLeak(t *testing.T) { 80 switch runtime.GOOS { 81 case "plan9": 82 t.Skipf("%s does not have full support of socktest", runtime.GOOS) 83 case "windows": 84 t.Skipf("not implemented a way to cancel dial racers in TCP SYN-SENT state on %s", runtime.GOOS) 85 case "openbsd": 86 testenv.SkipFlaky(t, 15157) 87 } 88 if !supportsIPv4() || !supportsIPv6() { 89 t.Skip("both IPv4 and IPv6 are required") 90 } 91 92 before := sw.Sockets() 93 origTestHookLookupIP := testHookLookupIP 94 defer func() { testHookLookupIP = origTestHookLookupIP }() 95 testHookLookupIP = lookupLocalhost 96 handler := func(dss *dualStackServer, ln Listener) { 97 for { 98 c, err := ln.Accept() 99 if err != nil { 100 return 101 } 102 c.Close() 103 } 104 } 105 dss, err := newDualStackServer() 106 if err != nil { 107 t.Fatal(err) 108 } 109 if err := dss.buildup(handler); err != nil { 110 dss.teardown() 111 t.Fatal(err) 112 } 113 114 const N = 10 115 var wg sync.WaitGroup 116 wg.Add(N) 117 d := &Dialer{DualStack: true, Timeout: 5 * time.Second} 118 for i := 0; i < N; i++ { 119 go func() { 120 defer wg.Done() 121 c, err := d.Dial("tcp", JoinHostPort("localhost", dss.port)) 122 if err != nil { 123 t.Error(err) 124 return 125 } 126 c.Close() 127 }() 128 } 129 wg.Wait() 130 dss.teardown() 131 after := sw.Sockets() 132 if len(after) != len(before) { 133 t.Errorf("got %d; want %d", len(after), len(before)) 134 } 135 } 136 137 // Define a pair of blackholed (IPv4, IPv6) addresses, for which dialTCP is 138 // expected to hang until the timeout elapses. These addresses are reserved 139 // for benchmarking by RFC 6890. 140 const ( 141 slowDst4 = "198.18.0.254" 142 slowDst6 = "2001:2::254" 143 ) 144 145 // In some environments, the slow IPs may be explicitly unreachable, and fail 146 // more quickly than expected. This test hook prevents dialTCP from returning 147 // before the deadline. 148 func slowDialTCP(ctx context.Context, network string, laddr, raddr *TCPAddr) (*TCPConn, error) { 149 sd := &sysDialer{network: network, address: raddr.String()} 150 c, err := sd.doDialTCP(ctx, laddr, raddr) 151 if ParseIP(slowDst4).Equal(raddr.IP) || ParseIP(slowDst6).Equal(raddr.IP) { 152 // Wait for the deadline, or indefinitely if none exists. 153 <-ctx.Done() 154 } 155 return c, err 156 } 157 158 func dialClosedPort(t *testing.T) (dialLatency time.Duration) { 159 // On most platforms, dialing a closed port should be nearly instantaneous — 160 // less than a few hundred milliseconds. However, on some platforms it may be 161 // much slower: on Windows and OpenBSD, it has been observed to take up to a 162 // few seconds. 163 164 l, err := Listen("tcp", "127.0.0.1:0") 165 if err != nil { 166 t.Fatalf("dialClosedPort: Listen failed: %v", err) 167 } 168 addr := l.Addr().String() 169 l.Close() 170 171 startTime := time.Now() 172 c, err := Dial("tcp", addr) 173 if err == nil { 174 c.Close() 175 } 176 elapsed := time.Now().Sub(startTime) 177 t.Logf("dialClosedPort: measured delay %v", elapsed) 178 return elapsed 179 } 180 181 func TestDialParallel(t *testing.T) { 182 testenv.MustHaveExternalNetwork(t) 183 184 if !supportsIPv4() || !supportsIPv6() { 185 t.Skip("both IPv4 and IPv6 are required") 186 } 187 188 closedPortDelay := dialClosedPort(t) 189 190 const instant time.Duration = 0 191 const fallbackDelay = 200 * time.Millisecond 192 193 // Some cases will run quickly when "connection refused" is fast, 194 // or trigger the fallbackDelay on Windows. This value holds the 195 // lesser of the two delays. 196 var closedPortOrFallbackDelay time.Duration 197 if closedPortDelay < fallbackDelay { 198 closedPortOrFallbackDelay = closedPortDelay 199 } else { 200 closedPortOrFallbackDelay = fallbackDelay 201 } 202 203 origTestHookDialTCP := testHookDialTCP 204 defer func() { testHookDialTCP = origTestHookDialTCP }() 205 testHookDialTCP = slowDialTCP 206 207 nCopies := func(s string, n int) []string { 208 out := make([]string, n) 209 for i := 0; i < n; i++ { 210 out[i] = s 211 } 212 return out 213 } 214 215 var testCases = []struct { 216 primaries []string 217 fallbacks []string 218 teardownNetwork string 219 expectOk bool 220 expectElapsed time.Duration 221 }{ 222 // These should just work on the first try. 223 {[]string{"127.0.0.1"}, []string{}, "", true, instant}, 224 {[]string{"::1"}, []string{}, "", true, instant}, 225 {[]string{"127.0.0.1", "::1"}, []string{slowDst6}, "tcp6", true, instant}, 226 {[]string{"::1", "127.0.0.1"}, []string{slowDst4}, "tcp4", true, instant}, 227 // Primary is slow; fallback should kick in. 228 {[]string{slowDst4}, []string{"::1"}, "", true, fallbackDelay}, 229 // Skip a "connection refused" in the primary thread. 230 {[]string{"127.0.0.1", "::1"}, []string{}, "tcp4", true, closedPortDelay}, 231 {[]string{"::1", "127.0.0.1"}, []string{}, "tcp6", true, closedPortDelay}, 232 // Skip a "connection refused" in the fallback thread. 233 {[]string{slowDst4, slowDst6}, []string{"::1", "127.0.0.1"}, "tcp6", true, fallbackDelay + closedPortDelay}, 234 // Primary refused, fallback without delay. 235 {[]string{"127.0.0.1"}, []string{"::1"}, "tcp4", true, closedPortOrFallbackDelay}, 236 {[]string{"::1"}, []string{"127.0.0.1"}, "tcp6", true, closedPortOrFallbackDelay}, 237 // Everything is refused. 238 {[]string{"127.0.0.1"}, []string{}, "tcp4", false, closedPortDelay}, 239 // Nothing to do; fail instantly. 240 {[]string{}, []string{}, "", false, instant}, 241 // Connecting to tons of addresses should not trip the deadline. 242 {nCopies("::1", 1000), []string{}, "", true, instant}, 243 } 244 245 handler := func(dss *dualStackServer, ln Listener) { 246 for { 247 c, err := ln.Accept() 248 if err != nil { 249 return 250 } 251 c.Close() 252 } 253 } 254 255 // Convert a list of IP strings into TCPAddrs. 256 makeAddrs := func(ips []string, port string) addrList { 257 var out addrList 258 for _, ip := range ips { 259 addr, err := ResolveTCPAddr("tcp", JoinHostPort(ip, port)) 260 if err != nil { 261 t.Fatal(err) 262 } 263 out = append(out, addr) 264 } 265 return out 266 } 267 268 for i, tt := range testCases { 269 dss, err := newDualStackServer() 270 if err != nil { 271 t.Fatal(err) 272 } 273 defer dss.teardown() 274 if err := dss.buildup(handler); err != nil { 275 t.Fatal(err) 276 } 277 if tt.teardownNetwork != "" { 278 // Destroy one of the listening sockets, creating an unreachable port. 279 dss.teardownNetwork(tt.teardownNetwork) 280 } 281 282 primaries := makeAddrs(tt.primaries, dss.port) 283 fallbacks := makeAddrs(tt.fallbacks, dss.port) 284 d := Dialer{ 285 FallbackDelay: fallbackDelay, 286 } 287 startTime := time.Now() 288 sd := &sysDialer{ 289 Dialer: d, 290 network: "tcp", 291 address: "?", 292 } 293 c, err := sd.dialParallel(context.Background(), primaries, fallbacks) 294 elapsed := time.Since(startTime) 295 296 if c != nil { 297 c.Close() 298 } 299 300 if tt.expectOk && err != nil { 301 t.Errorf("#%d: got %v; want nil", i, err) 302 } else if !tt.expectOk && err == nil { 303 t.Errorf("#%d: got nil; want non-nil", i) 304 } 305 306 // We used to always use 95 milliseconds as the slop, 307 // but that was flaky on Windows. See issue 35616. 308 slop := 95 * time.Millisecond 309 if fifth := tt.expectElapsed / 5; fifth > slop { 310 slop = fifth 311 } 312 expectElapsedMin := tt.expectElapsed - slop 313 expectElapsedMax := tt.expectElapsed + slop 314 if elapsed < expectElapsedMin { 315 t.Errorf("#%d: got %v; want >= %v", i, elapsed, expectElapsedMin) 316 } else if elapsed > expectElapsedMax { 317 t.Errorf("#%d: got %v; want <= %v", i, elapsed, expectElapsedMax) 318 } 319 320 // Repeat each case, ensuring that it can be canceled quickly. 321 ctx, cancel := context.WithCancel(context.Background()) 322 var wg sync.WaitGroup 323 wg.Add(1) 324 go func() { 325 time.Sleep(5 * time.Millisecond) 326 cancel() 327 wg.Done() 328 }() 329 startTime = time.Now() 330 c, err = sd.dialParallel(ctx, primaries, fallbacks) 331 if c != nil { 332 c.Close() 333 } 334 elapsed = time.Now().Sub(startTime) 335 if elapsed > 100*time.Millisecond { 336 t.Errorf("#%d (cancel): got %v; want <= 100ms", i, elapsed) 337 } 338 wg.Wait() 339 } 340 } 341 342 func lookupSlowFast(ctx context.Context, fn func(context.Context, string, string) ([]IPAddr, error), network, host string) ([]IPAddr, error) { 343 switch host { 344 case "slow6loopback4": 345 // Returns a slow IPv6 address, and a local IPv4 address. 346 return []IPAddr{ 347 {IP: ParseIP(slowDst6)}, 348 {IP: ParseIP("127.0.0.1")}, 349 }, nil 350 default: 351 return fn(ctx, network, host) 352 } 353 } 354 355 func TestDialerFallbackDelay(t *testing.T) { 356 testenv.MustHaveExternalNetwork(t) 357 358 if !supportsIPv4() || !supportsIPv6() { 359 t.Skip("both IPv4 and IPv6 are required") 360 } 361 362 origTestHookLookupIP := testHookLookupIP 363 defer func() { testHookLookupIP = origTestHookLookupIP }() 364 testHookLookupIP = lookupSlowFast 365 366 origTestHookDialTCP := testHookDialTCP 367 defer func() { testHookDialTCP = origTestHookDialTCP }() 368 testHookDialTCP = slowDialTCP 369 370 var testCases = []struct { 371 dualstack bool 372 delay time.Duration 373 expectElapsed time.Duration 374 }{ 375 // Use a very brief delay, which should fallback immediately. 376 {true, 1 * time.Nanosecond, 0}, 377 // Use a 200ms explicit timeout. 378 {true, 200 * time.Millisecond, 200 * time.Millisecond}, 379 // The default is 300ms. 380 {true, 0, 300 * time.Millisecond}, 381 } 382 383 handler := func(dss *dualStackServer, ln Listener) { 384 for { 385 c, err := ln.Accept() 386 if err != nil { 387 return 388 } 389 c.Close() 390 } 391 } 392 dss, err := newDualStackServer() 393 if err != nil { 394 t.Fatal(err) 395 } 396 defer dss.teardown() 397 if err := dss.buildup(handler); err != nil { 398 t.Fatal(err) 399 } 400 401 for i, tt := range testCases { 402 d := &Dialer{DualStack: tt.dualstack, FallbackDelay: tt.delay} 403 404 startTime := time.Now() 405 c, err := d.Dial("tcp", JoinHostPort("slow6loopback4", dss.port)) 406 elapsed := time.Now().Sub(startTime) 407 if err == nil { 408 c.Close() 409 } else if tt.dualstack { 410 t.Error(err) 411 } 412 expectMin := tt.expectElapsed - 1*time.Millisecond 413 expectMax := tt.expectElapsed + 95*time.Millisecond 414 if elapsed < expectMin { 415 t.Errorf("#%d: got %v; want >= %v", i, elapsed, expectMin) 416 } 417 if elapsed > expectMax { 418 t.Errorf("#%d: got %v; want <= %v", i, elapsed, expectMax) 419 } 420 } 421 } 422 423 func TestDialParallelSpuriousConnection(t *testing.T) { 424 if !supportsIPv4() || !supportsIPv6() { 425 t.Skip("both IPv4 and IPv6 are required") 426 } 427 428 var readDeadline time.Time 429 if td, ok := t.Deadline(); ok { 430 const arbitraryCleanupMargin = 1 * time.Second 431 readDeadline = td.Add(-arbitraryCleanupMargin) 432 } else { 433 readDeadline = time.Now().Add(5 * time.Second) 434 } 435 436 var wg sync.WaitGroup 437 wg.Add(2) 438 handler := func(dss *dualStackServer, ln Listener) { 439 // Accept one connection per address. 440 c, err := ln.Accept() 441 if err != nil { 442 t.Fatal(err) 443 } 444 // The client should close itself, without sending data. 445 c.SetReadDeadline(readDeadline) 446 var b [1]byte 447 if _, err := c.Read(b[:]); err != io.EOF { 448 t.Errorf("got %v; want %v", err, io.EOF) 449 } 450 c.Close() 451 wg.Done() 452 } 453 dss, err := newDualStackServer() 454 if err != nil { 455 t.Fatal(err) 456 } 457 defer dss.teardown() 458 if err := dss.buildup(handler); err != nil { 459 t.Fatal(err) 460 } 461 462 const fallbackDelay = 100 * time.Millisecond 463 464 origTestHookDialTCP := testHookDialTCP 465 defer func() { testHookDialTCP = origTestHookDialTCP }() 466 testHookDialTCP = func(ctx context.Context, net string, laddr, raddr *TCPAddr) (*TCPConn, error) { 467 // Sleep long enough for Happy Eyeballs to kick in, and inhibit cancellation. 468 // This forces dialParallel to juggle two successful connections. 469 time.Sleep(fallbackDelay * 2) 470 471 // Now ignore the provided context (which will be canceled) and use a 472 // different one to make sure this completes with a valid connection, 473 // which we hope to be closed below: 474 sd := &sysDialer{network: net, address: raddr.String()} 475 return sd.doDialTCP(context.Background(), laddr, raddr) 476 } 477 478 d := Dialer{ 479 FallbackDelay: fallbackDelay, 480 } 481 sd := &sysDialer{ 482 Dialer: d, 483 network: "tcp", 484 address: "?", 485 } 486 487 makeAddr := func(ip string) addrList { 488 addr, err := ResolveTCPAddr("tcp", JoinHostPort(ip, dss.port)) 489 if err != nil { 490 t.Fatal(err) 491 } 492 return addrList{addr} 493 } 494 495 // dialParallel returns one connection (and closes the other.) 496 c, err := sd.dialParallel(context.Background(), makeAddr("127.0.0.1"), makeAddr("::1")) 497 if err != nil { 498 t.Fatal(err) 499 } 500 c.Close() 501 502 // The server should've seen both connections. 503 wg.Wait() 504 } 505 506 func TestDialerPartialDeadline(t *testing.T) { 507 now := time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC) 508 var testCases = []struct { 509 now time.Time 510 deadline time.Time 511 addrs int 512 expectDeadline time.Time 513 expectErr error 514 }{ 515 // Regular division. 516 {now, now.Add(12 * time.Second), 1, now.Add(12 * time.Second), nil}, 517 {now, now.Add(12 * time.Second), 2, now.Add(6 * time.Second), nil}, 518 {now, now.Add(12 * time.Second), 3, now.Add(4 * time.Second), nil}, 519 // Bump against the 2-second sane minimum. 520 {now, now.Add(12 * time.Second), 999, now.Add(2 * time.Second), nil}, 521 // Total available is now below the sane minimum. 522 {now, now.Add(1900 * time.Millisecond), 999, now.Add(1900 * time.Millisecond), nil}, 523 // Null deadline. 524 {now, noDeadline, 1, noDeadline, nil}, 525 // Step the clock forward and cross the deadline. 526 {now.Add(-1 * time.Millisecond), now, 1, now, nil}, 527 {now.Add(0 * time.Millisecond), now, 1, noDeadline, errTimeout}, 528 {now.Add(1 * time.Millisecond), now, 1, noDeadline, errTimeout}, 529 } 530 for i, tt := range testCases { 531 deadline, err := partialDeadline(tt.now, tt.deadline, tt.addrs) 532 if err != tt.expectErr { 533 t.Errorf("#%d: got %v; want %v", i, err, tt.expectErr) 534 } 535 if !deadline.Equal(tt.expectDeadline) { 536 t.Errorf("#%d: got %v; want %v", i, deadline, tt.expectDeadline) 537 } 538 } 539 } 540 541 func TestDialerLocalAddr(t *testing.T) { 542 if !supportsIPv4() || !supportsIPv6() { 543 t.Skip("both IPv4 and IPv6 are required") 544 } 545 546 type test struct { 547 network, raddr string 548 laddr Addr 549 error 550 } 551 var tests = []test{ 552 {"tcp4", "127.0.0.1", nil, nil}, 553 {"tcp4", "127.0.0.1", &TCPAddr{}, nil}, 554 {"tcp4", "127.0.0.1", &TCPAddr{IP: ParseIP("0.0.0.0")}, nil}, 555 {"tcp4", "127.0.0.1", &TCPAddr{IP: ParseIP("0.0.0.0").To4()}, nil}, 556 {"tcp4", "127.0.0.1", &TCPAddr{IP: ParseIP("::")}, &AddrError{Err: "some error"}}, 557 {"tcp4", "127.0.0.1", &TCPAddr{IP: ParseIP("127.0.0.1").To4()}, nil}, 558 {"tcp4", "127.0.0.1", &TCPAddr{IP: ParseIP("127.0.0.1").To16()}, nil}, 559 {"tcp4", "127.0.0.1", &TCPAddr{IP: IPv6loopback}, errNoSuitableAddress}, 560 {"tcp4", "127.0.0.1", &UDPAddr{}, &AddrError{Err: "some error"}}, 561 {"tcp4", "127.0.0.1", &UnixAddr{}, &AddrError{Err: "some error"}}, 562 563 {"tcp6", "::1", nil, nil}, 564 {"tcp6", "::1", &TCPAddr{}, nil}, 565 {"tcp6", "::1", &TCPAddr{IP: ParseIP("0.0.0.0")}, nil}, 566 {"tcp6", "::1", &TCPAddr{IP: ParseIP("0.0.0.0").To4()}, nil}, 567 {"tcp6", "::1", &TCPAddr{IP: ParseIP("::")}, nil}, 568 {"tcp6", "::1", &TCPAddr{IP: ParseIP("127.0.0.1").To4()}, errNoSuitableAddress}, 569 {"tcp6", "::1", &TCPAddr{IP: ParseIP("127.0.0.1").To16()}, errNoSuitableAddress}, 570 {"tcp6", "::1", &TCPAddr{IP: IPv6loopback}, nil}, 571 {"tcp6", "::1", &UDPAddr{}, &AddrError{Err: "some error"}}, 572 {"tcp6", "::1", &UnixAddr{}, &AddrError{Err: "some error"}}, 573 574 {"tcp", "127.0.0.1", nil, nil}, 575 {"tcp", "127.0.0.1", &TCPAddr{}, nil}, 576 {"tcp", "127.0.0.1", &TCPAddr{IP: ParseIP("0.0.0.0")}, nil}, 577 {"tcp", "127.0.0.1", &TCPAddr{IP: ParseIP("0.0.0.0").To4()}, nil}, 578 {"tcp", "127.0.0.1", &TCPAddr{IP: ParseIP("127.0.0.1").To4()}, nil}, 579 {"tcp", "127.0.0.1", &TCPAddr{IP: ParseIP("127.0.0.1").To16()}, nil}, 580 {"tcp", "127.0.0.1", &TCPAddr{IP: IPv6loopback}, errNoSuitableAddress}, 581 {"tcp", "127.0.0.1", &UDPAddr{}, &AddrError{Err: "some error"}}, 582 {"tcp", "127.0.0.1", &UnixAddr{}, &AddrError{Err: "some error"}}, 583 584 {"tcp", "::1", nil, nil}, 585 {"tcp", "::1", &TCPAddr{}, nil}, 586 {"tcp", "::1", &TCPAddr{IP: ParseIP("0.0.0.0")}, nil}, 587 {"tcp", "::1", &TCPAddr{IP: ParseIP("0.0.0.0").To4()}, nil}, 588 {"tcp", "::1", &TCPAddr{IP: ParseIP("::")}, nil}, 589 {"tcp", "::1", &TCPAddr{IP: ParseIP("127.0.0.1").To4()}, errNoSuitableAddress}, 590 {"tcp", "::1", &TCPAddr{IP: ParseIP("127.0.0.1").To16()}, errNoSuitableAddress}, 591 {"tcp", "::1", &TCPAddr{IP: IPv6loopback}, nil}, 592 {"tcp", "::1", &UDPAddr{}, &AddrError{Err: "some error"}}, 593 {"tcp", "::1", &UnixAddr{}, &AddrError{Err: "some error"}}, 594 } 595 596 if supportsIPv4map() { 597 tests = append(tests, test{ 598 "tcp", "127.0.0.1", &TCPAddr{IP: ParseIP("::")}, nil, 599 }) 600 } else { 601 tests = append(tests, test{ 602 "tcp", "127.0.0.1", &TCPAddr{IP: ParseIP("::")}, &AddrError{Err: "some error"}, 603 }) 604 } 605 606 origTestHookLookupIP := testHookLookupIP 607 defer func() { testHookLookupIP = origTestHookLookupIP }() 608 testHookLookupIP = lookupLocalhost 609 handler := func(ls *localServer, ln Listener) { 610 for { 611 c, err := ln.Accept() 612 if err != nil { 613 return 614 } 615 c.Close() 616 } 617 } 618 var err error 619 var lss [2]*localServer 620 for i, network := range []string{"tcp4", "tcp6"} { 621 lss[i], err = newLocalServer(network) 622 if err != nil { 623 t.Fatal(err) 624 } 625 defer lss[i].teardown() 626 if err := lss[i].buildup(handler); err != nil { 627 t.Fatal(err) 628 } 629 } 630 631 for _, tt := range tests { 632 d := &Dialer{LocalAddr: tt.laddr} 633 var addr string 634 ip := ParseIP(tt.raddr) 635 if ip.To4() != nil { 636 addr = lss[0].Listener.Addr().String() 637 } 638 if ip.To16() != nil && ip.To4() == nil { 639 addr = lss[1].Listener.Addr().String() 640 } 641 c, err := d.Dial(tt.network, addr) 642 if err == nil && tt.error != nil || err != nil && tt.error == nil { 643 t.Errorf("%s %v->%s: got %v; want %v", tt.network, tt.laddr, tt.raddr, err, tt.error) 644 } 645 if err != nil { 646 if perr := parseDialError(err); perr != nil { 647 t.Error(perr) 648 } 649 continue 650 } 651 c.Close() 652 } 653 } 654 655 func TestDialerDualStack(t *testing.T) { 656 testenv.SkipFlaky(t, 13324) 657 658 if !supportsIPv4() || !supportsIPv6() { 659 t.Skip("both IPv4 and IPv6 are required") 660 } 661 662 closedPortDelay := dialClosedPort(t) 663 664 origTestHookLookupIP := testHookLookupIP 665 defer func() { testHookLookupIP = origTestHookLookupIP }() 666 testHookLookupIP = lookupLocalhost 667 handler := func(dss *dualStackServer, ln Listener) { 668 for { 669 c, err := ln.Accept() 670 if err != nil { 671 return 672 } 673 c.Close() 674 } 675 } 676 677 var timeout = 150*time.Millisecond + closedPortDelay 678 for _, dualstack := range []bool{false, true} { 679 dss, err := newDualStackServer() 680 if err != nil { 681 t.Fatal(err) 682 } 683 defer dss.teardown() 684 if err := dss.buildup(handler); err != nil { 685 t.Fatal(err) 686 } 687 688 d := &Dialer{DualStack: dualstack, Timeout: timeout} 689 for range dss.lns { 690 c, err := d.Dial("tcp", JoinHostPort("localhost", dss.port)) 691 if err != nil { 692 t.Error(err) 693 continue 694 } 695 switch addr := c.LocalAddr().(*TCPAddr); { 696 case addr.IP.To4() != nil: 697 dss.teardownNetwork("tcp4") 698 case addr.IP.To16() != nil && addr.IP.To4() == nil: 699 dss.teardownNetwork("tcp6") 700 } 701 c.Close() 702 } 703 } 704 } 705 706 func TestDialerKeepAlive(t *testing.T) { 707 handler := func(ls *localServer, ln Listener) { 708 for { 709 c, err := ln.Accept() 710 if err != nil { 711 return 712 } 713 c.Close() 714 } 715 } 716 ls, err := newLocalServer("tcp") 717 if err != nil { 718 t.Fatal(err) 719 } 720 defer ls.teardown() 721 if err := ls.buildup(handler); err != nil { 722 t.Fatal(err) 723 } 724 defer func() { testHookSetKeepAlive = func(time.Duration) {} }() 725 726 tests := []struct { 727 ka time.Duration 728 expected time.Duration 729 }{ 730 {-1, -1}, 731 {0, 15 * time.Second}, 732 {5 * time.Second, 5 * time.Second}, 733 {30 * time.Second, 30 * time.Second}, 734 } 735 736 for _, test := range tests { 737 var got time.Duration = -1 738 testHookSetKeepAlive = func(d time.Duration) { got = d } 739 d := Dialer{KeepAlive: test.ka} 740 c, err := d.Dial("tcp", ls.Listener.Addr().String()) 741 if err != nil { 742 t.Fatal(err) 743 } 744 c.Close() 745 if got != test.expected { 746 t.Errorf("Dialer.KeepAlive = %v: SetKeepAlive set to %v, want %v", d.KeepAlive, got, test.expected) 747 } 748 } 749 } 750 751 func TestDialCancel(t *testing.T) { 752 mustHaveExternalNetwork(t) 753 754 blackholeIPPort := JoinHostPort(slowDst4, "1234") 755 if !supportsIPv4() { 756 blackholeIPPort = JoinHostPort(slowDst6, "1234") 757 } 758 759 ticker := time.NewTicker(10 * time.Millisecond) 760 defer ticker.Stop() 761 762 const cancelTick = 5 // the timer tick we cancel the dial at 763 const timeoutTick = 100 764 765 var d Dialer 766 cancel := make(chan struct{}) 767 d.Cancel = cancel 768 errc := make(chan error, 1) 769 connc := make(chan Conn, 1) 770 go func() { 771 if c, err := d.Dial("tcp", blackholeIPPort); err != nil { 772 errc <- err 773 } else { 774 connc <- c 775 } 776 }() 777 ticks := 0 778 for { 779 select { 780 case <-ticker.C: 781 ticks++ 782 if ticks == cancelTick { 783 close(cancel) 784 } 785 if ticks == timeoutTick { 786 t.Fatal("timeout waiting for dial to fail") 787 } 788 case c := <-connc: 789 c.Close() 790 t.Fatal("unexpected successful connection") 791 case err := <-errc: 792 if perr := parseDialError(err); perr != nil { 793 t.Error(perr) 794 } 795 if ticks < cancelTick { 796 // Using strings.Contains is ugly but 797 // may work on plan9 and windows. 798 if strings.Contains(err.Error(), "connection refused") { 799 t.Skipf("connection to %v failed fast with %v", blackholeIPPort, err) 800 } 801 t.Fatalf("dial error after %d ticks (%d before cancel sent): %v", 802 ticks, cancelTick-ticks, err) 803 } 804 if oe, ok := err.(*OpError); !ok || oe.Err != errCanceled { 805 t.Fatalf("dial error = %v (%T); want OpError with Err == errCanceled", err, err) 806 } 807 return // success. 808 } 809 } 810 } 811 812 func TestCancelAfterDial(t *testing.T) { 813 if testing.Short() { 814 t.Skip("avoiding time.Sleep") 815 } 816 817 ln, err := newLocalListener("tcp") 818 if err != nil { 819 t.Fatal(err) 820 } 821 822 var wg sync.WaitGroup 823 wg.Add(1) 824 defer func() { 825 ln.Close() 826 wg.Wait() 827 }() 828 829 // Echo back the first line of each incoming connection. 830 go func() { 831 for { 832 c, err := ln.Accept() 833 if err != nil { 834 break 835 } 836 rb := bufio.NewReader(c) 837 line, err := rb.ReadString('\n') 838 if err != nil { 839 t.Error(err) 840 c.Close() 841 continue 842 } 843 if _, err := c.Write([]byte(line)); err != nil { 844 t.Error(err) 845 } 846 c.Close() 847 } 848 wg.Done() 849 }() 850 851 try := func() { 852 cancel := make(chan struct{}) 853 d := &Dialer{Cancel: cancel} 854 c, err := d.Dial("tcp", ln.Addr().String()) 855 856 // Immediately after dialing, request cancellation and sleep. 857 // Before Issue 15078 was fixed, this would cause subsequent operations 858 // to fail with an i/o timeout roughly 50% of the time. 859 close(cancel) 860 time.Sleep(10 * time.Millisecond) 861 862 if err != nil { 863 t.Fatal(err) 864 } 865 defer c.Close() 866 867 // Send some data to confirm that the connection is still alive. 868 const message = "echo!\n" 869 if _, err := c.Write([]byte(message)); err != nil { 870 t.Fatal(err) 871 } 872 873 // The server should echo the line, and close the connection. 874 rb := bufio.NewReader(c) 875 line, err := rb.ReadString('\n') 876 if err != nil { 877 t.Fatal(err) 878 } 879 if line != message { 880 t.Errorf("got %q; want %q", line, message) 881 } 882 if _, err := rb.ReadByte(); err != io.EOF { 883 t.Errorf("got %v; want %v", err, io.EOF) 884 } 885 } 886 887 // This bug manifested about 50% of the time, so try it a few times. 888 for i := 0; i < 10; i++ { 889 try() 890 } 891 } 892 893 // Issue 18806: it should always be possible to net.Dial a 894 // net.Listener().Addr().String when the listen address was ":n", even 895 // if the machine has halfway configured IPv6 such that it can bind on 896 // "::" not connect back to that same address. 897 func TestDialListenerAddr(t *testing.T) { 898 mustHaveExternalNetwork(t) 899 ln, err := Listen("tcp", ":0") 900 if err != nil { 901 t.Fatal(err) 902 } 903 defer ln.Close() 904 addr := ln.Addr().String() 905 c, err := Dial("tcp", addr) 906 if err != nil { 907 t.Fatalf("for addr %q, dial error: %v", addr, err) 908 } 909 c.Close() 910 } 911 912 func TestDialerControl(t *testing.T) { 913 switch runtime.GOOS { 914 case "plan9": 915 t.Skipf("not supported on %s", runtime.GOOS) 916 } 917 918 t.Run("StreamDial", func(t *testing.T) { 919 for _, network := range []string{"tcp", "tcp4", "tcp6", "unix", "unixpacket"} { 920 if !testableNetwork(network) { 921 continue 922 } 923 ln, err := newLocalListener(network) 924 if err != nil { 925 t.Error(err) 926 continue 927 } 928 defer ln.Close() 929 d := Dialer{Control: controlOnConnSetup} 930 c, err := d.Dial(network, ln.Addr().String()) 931 if err != nil { 932 t.Error(err) 933 continue 934 } 935 c.Close() 936 } 937 }) 938 t.Run("PacketDial", func(t *testing.T) { 939 for _, network := range []string{"udp", "udp4", "udp6", "unixgram"} { 940 if !testableNetwork(network) { 941 continue 942 } 943 c1, err := newLocalPacketListener(network) 944 if err != nil { 945 t.Error(err) 946 continue 947 } 948 if network == "unixgram" { 949 defer os.Remove(c1.LocalAddr().String()) 950 } 951 defer c1.Close() 952 d := Dialer{Control: controlOnConnSetup} 953 c2, err := d.Dial(network, c1.LocalAddr().String()) 954 if err != nil { 955 t.Error(err) 956 continue 957 } 958 c2.Close() 959 } 960 }) 961 } 962 963 // mustHaveExternalNetwork is like testenv.MustHaveExternalNetwork 964 // except that it won't skip testing on non-mobile builders. 965 func mustHaveExternalNetwork(t *testing.T) { 966 t.Helper() 967 mobile := runtime.GOOS == "android" || runtime.GOOS == "ios" 968 if testenv.Builder() == "" || mobile { 969 testenv.MustHaveExternalNetwork(t) 970 } 971 } 972 973 type contextWithNonZeroDeadline struct { 974 context.Context 975 } 976 977 func (contextWithNonZeroDeadline) Deadline() (time.Time, bool) { 978 // Return non-zero time.Time value with false indicating that no deadline is set. 979 return time.Unix(0, 0), false 980 } 981 982 func TestDialWithNonZeroDeadline(t *testing.T) { 983 ln, err := newLocalListener("tcp") 984 if err != nil { 985 t.Fatal(err) 986 } 987 defer ln.Close() 988 _, port, err := SplitHostPort(ln.Addr().String()) 989 if err != nil { 990 t.Fatal(err) 991 } 992 993 ctx := contextWithNonZeroDeadline{Context: context.Background()} 994 var dialer Dialer 995 c, err := dialer.DialContext(ctx, "tcp", JoinHostPort("", port)) 996 if err != nil { 997 t.Fatal(err) 998 } 999 c.Close() 1000 }