github.com/mattn/go@v0.0.0-20171011075504-07f7db3ea99f/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 package net 6 7 import ( 8 "bufio" 9 "context" 10 "internal/poll" 11 "internal/testenv" 12 "io" 13 "runtime" 14 "sync" 15 "testing" 16 "time" 17 ) 18 19 var prohibitionaryDialArgTests = []struct { 20 network string 21 address string 22 }{ 23 {"tcp6", "127.0.0.1"}, 24 {"tcp6", "::ffff:127.0.0.1"}, 25 } 26 27 func TestProhibitionaryDialArg(t *testing.T) { 28 testenv.MustHaveExternalNetwork(t) 29 30 switch runtime.GOOS { 31 case "plan9": 32 t.Skipf("not supported on %s", runtime.GOOS) 33 } 34 if !supportsIPv4map() { 35 t.Skip("mapping ipv4 address inside ipv6 address not supported") 36 } 37 38 ln, err := Listen("tcp", "[::]:0") 39 if err != nil { 40 t.Fatal(err) 41 } 42 defer ln.Close() 43 44 _, port, err := SplitHostPort(ln.Addr().String()) 45 if err != nil { 46 t.Fatal(err) 47 } 48 49 for i, tt := range prohibitionaryDialArgTests { 50 c, err := Dial(tt.network, JoinHostPort(tt.address, port)) 51 if err == nil { 52 c.Close() 53 t.Errorf("#%d: %v", i, err) 54 } 55 } 56 } 57 58 func TestDialLocal(t *testing.T) { 59 ln, err := newLocalListener("tcp") 60 if err != nil { 61 t.Fatal(err) 62 } 63 defer ln.Close() 64 _, port, err := SplitHostPort(ln.Addr().String()) 65 if err != nil { 66 t.Fatal(err) 67 } 68 c, err := Dial("tcp", JoinHostPort("", port)) 69 if err != nil { 70 t.Fatal(err) 71 } 72 c.Close() 73 } 74 75 func TestDialerDualStackFDLeak(t *testing.T) { 76 switch runtime.GOOS { 77 case "plan9": 78 t.Skipf("%s does not have full support of socktest", runtime.GOOS) 79 case "windows": 80 t.Skipf("not implemented a way to cancel dial racers in TCP SYN-SENT state on %s", runtime.GOOS) 81 case "openbsd": 82 testenv.SkipFlaky(t, 15157) 83 } 84 if !supportsIPv4() || !supportsIPv6() { 85 t.Skip("both IPv4 and IPv6 are required") 86 } 87 88 closedPortDelay, expectClosedPortDelay := dialClosedPort() 89 if closedPortDelay > expectClosedPortDelay { 90 t.Errorf("got %v; want <= %v", closedPortDelay, expectClosedPortDelay) 91 } 92 93 before := sw.Sockets() 94 origTestHookLookupIP := testHookLookupIP 95 defer func() { testHookLookupIP = origTestHookLookupIP }() 96 testHookLookupIP = lookupLocalhost 97 handler := func(dss *dualStackServer, ln Listener) { 98 for { 99 c, err := ln.Accept() 100 if err != nil { 101 return 102 } 103 c.Close() 104 } 105 } 106 dss, err := newDualStackServer() 107 if err != nil { 108 t.Fatal(err) 109 } 110 if err := dss.buildup(handler); err != nil { 111 dss.teardown() 112 t.Fatal(err) 113 } 114 115 const N = 10 116 var wg sync.WaitGroup 117 wg.Add(N) 118 d := &Dialer{DualStack: true, Timeout: 100*time.Millisecond + closedPortDelay} 119 for i := 0; i < N; i++ { 120 go func() { 121 defer wg.Done() 122 c, err := d.Dial("tcp", JoinHostPort("localhost", dss.port)) 123 if err != nil { 124 t.Error(err) 125 return 126 } 127 c.Close() 128 }() 129 } 130 wg.Wait() 131 dss.teardown() 132 after := sw.Sockets() 133 if len(after) != len(before) { 134 t.Errorf("got %d; want %d", len(after), len(before)) 135 } 136 } 137 138 // Define a pair of blackholed (IPv4, IPv6) addresses, for which dialTCP is 139 // expected to hang until the timeout elapses. These addresses are reserved 140 // for benchmarking by RFC 6890. 141 const ( 142 slowDst4 = "198.18.0.254" 143 slowDst6 = "2001:2::254" 144 ) 145 146 // In some environments, the slow IPs may be explicitly unreachable, and fail 147 // more quickly than expected. This test hook prevents dialTCP from returning 148 // before the deadline. 149 func slowDialTCP(ctx context.Context, net string, laddr, raddr *TCPAddr) (*TCPConn, error) { 150 c, err := doDialTCP(ctx, net, 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() (actual, expected time.Duration) { 159 // Estimate the expected time for this platform. 160 // On Windows, dialing a closed port takes roughly 1 second, 161 // but other platforms should be instantaneous. 162 if runtime.GOOS == "windows" { 163 expected = 1500 * time.Millisecond 164 } else if runtime.GOOS == "darwin" { 165 expected = 150 * time.Millisecond 166 } else { 167 expected = 95 * time.Millisecond 168 } 169 170 l, err := Listen("tcp", "127.0.0.1:0") 171 if err != nil { 172 return 999 * time.Hour, expected 173 } 174 addr := l.Addr().String() 175 l.Close() 176 // On OpenBSD, interference from TestSelfConnect is mysteriously 177 // causing the first attempt to hang for a few seconds, so we throw 178 // away the first result and keep the second. 179 for i := 1; ; i++ { 180 startTime := time.Now() 181 c, err := Dial("tcp", addr) 182 if err == nil { 183 c.Close() 184 } 185 elapsed := time.Now().Sub(startTime) 186 if i == 2 { 187 return elapsed, expected 188 } 189 } 190 } 191 192 func TestDialParallel(t *testing.T) { 193 testenv.MustHaveExternalNetwork(t) 194 195 if !supportsIPv4() || !supportsIPv6() { 196 t.Skip("both IPv4 and IPv6 are required") 197 } 198 199 closedPortDelay, expectClosedPortDelay := dialClosedPort() 200 if closedPortDelay > expectClosedPortDelay { 201 t.Errorf("got %v; want <= %v", closedPortDelay, expectClosedPortDelay) 202 } 203 204 const instant time.Duration = 0 205 const fallbackDelay = 200 * time.Millisecond 206 207 // Some cases will run quickly when "connection refused" is fast, 208 // or trigger the fallbackDelay on Windows. This value holds the 209 // lesser of the two delays. 210 var closedPortOrFallbackDelay time.Duration 211 if closedPortDelay < fallbackDelay { 212 closedPortOrFallbackDelay = closedPortDelay 213 } else { 214 closedPortOrFallbackDelay = fallbackDelay 215 } 216 217 origTestHookDialTCP := testHookDialTCP 218 defer func() { testHookDialTCP = origTestHookDialTCP }() 219 testHookDialTCP = slowDialTCP 220 221 nCopies := func(s string, n int) []string { 222 out := make([]string, n) 223 for i := 0; i < n; i++ { 224 out[i] = s 225 } 226 return out 227 } 228 229 var testCases = []struct { 230 primaries []string 231 fallbacks []string 232 teardownNetwork string 233 expectOk bool 234 expectElapsed time.Duration 235 }{ 236 // These should just work on the first try. 237 {[]string{"127.0.0.1"}, []string{}, "", true, instant}, 238 {[]string{"::1"}, []string{}, "", true, instant}, 239 {[]string{"127.0.0.1", "::1"}, []string{slowDst6}, "tcp6", true, instant}, 240 {[]string{"::1", "127.0.0.1"}, []string{slowDst4}, "tcp4", true, instant}, 241 // Primary is slow; fallback should kick in. 242 {[]string{slowDst4}, []string{"::1"}, "", true, fallbackDelay}, 243 // Skip a "connection refused" in the primary thread. 244 {[]string{"127.0.0.1", "::1"}, []string{}, "tcp4", true, closedPortDelay}, 245 {[]string{"::1", "127.0.0.1"}, []string{}, "tcp6", true, closedPortDelay}, 246 // Skip a "connection refused" in the fallback thread. 247 {[]string{slowDst4, slowDst6}, []string{"::1", "127.0.0.1"}, "tcp6", true, fallbackDelay + closedPortDelay}, 248 // Primary refused, fallback without delay. 249 {[]string{"127.0.0.1"}, []string{"::1"}, "tcp4", true, closedPortOrFallbackDelay}, 250 {[]string{"::1"}, []string{"127.0.0.1"}, "tcp6", true, closedPortOrFallbackDelay}, 251 // Everything is refused. 252 {[]string{"127.0.0.1"}, []string{}, "tcp4", false, closedPortDelay}, 253 // Nothing to do; fail instantly. 254 {[]string{}, []string{}, "", false, instant}, 255 // Connecting to tons of addresses should not trip the deadline. 256 {nCopies("::1", 1000), []string{}, "", true, instant}, 257 } 258 259 handler := func(dss *dualStackServer, ln Listener) { 260 for { 261 c, err := ln.Accept() 262 if err != nil { 263 return 264 } 265 c.Close() 266 } 267 } 268 269 // Convert a list of IP strings into TCPAddrs. 270 makeAddrs := func(ips []string, port string) addrList { 271 var out addrList 272 for _, ip := range ips { 273 addr, err := ResolveTCPAddr("tcp", JoinHostPort(ip, port)) 274 if err != nil { 275 t.Fatal(err) 276 } 277 out = append(out, addr) 278 } 279 return out 280 } 281 282 for i, tt := range testCases { 283 dss, err := newDualStackServer() 284 if err != nil { 285 t.Fatal(err) 286 } 287 defer dss.teardown() 288 if err := dss.buildup(handler); err != nil { 289 t.Fatal(err) 290 } 291 if tt.teardownNetwork != "" { 292 // Destroy one of the listening sockets, creating an unreachable port. 293 dss.teardownNetwork(tt.teardownNetwork) 294 } 295 296 primaries := makeAddrs(tt.primaries, dss.port) 297 fallbacks := makeAddrs(tt.fallbacks, dss.port) 298 d := Dialer{ 299 FallbackDelay: fallbackDelay, 300 } 301 startTime := time.Now() 302 dp := &dialParam{ 303 Dialer: d, 304 network: "tcp", 305 address: "?", 306 } 307 c, err := dialParallel(context.Background(), dp, primaries, fallbacks) 308 elapsed := time.Since(startTime) 309 310 if c != nil { 311 c.Close() 312 } 313 314 if tt.expectOk && err != nil { 315 t.Errorf("#%d: got %v; want nil", i, err) 316 } else if !tt.expectOk && err == nil { 317 t.Errorf("#%d: got nil; want non-nil", i) 318 } 319 320 expectElapsedMin := tt.expectElapsed - 95*time.Millisecond 321 expectElapsedMax := tt.expectElapsed + 95*time.Millisecond 322 if !(elapsed >= expectElapsedMin) { 323 t.Errorf("#%d: got %v; want >= %v", i, elapsed, expectElapsedMin) 324 } else if !(elapsed <= expectElapsedMax) { 325 t.Errorf("#%d: got %v; want <= %v", i, elapsed, expectElapsedMax) 326 } 327 328 // Repeat each case, ensuring that it can be canceled quickly. 329 ctx, cancel := context.WithCancel(context.Background()) 330 var wg sync.WaitGroup 331 wg.Add(1) 332 go func() { 333 time.Sleep(5 * time.Millisecond) 334 cancel() 335 wg.Done() 336 }() 337 startTime = time.Now() 338 c, err = dialParallel(ctx, dp, primaries, fallbacks) 339 if c != nil { 340 c.Close() 341 } 342 elapsed = time.Now().Sub(startTime) 343 if elapsed > 100*time.Millisecond { 344 t.Errorf("#%d (cancel): got %v; want <= 100ms", i, elapsed) 345 } 346 wg.Wait() 347 } 348 } 349 350 func lookupSlowFast(ctx context.Context, fn func(context.Context, string) ([]IPAddr, error), host string) ([]IPAddr, error) { 351 switch host { 352 case "slow6loopback4": 353 // Returns a slow IPv6 address, and a local IPv4 address. 354 return []IPAddr{ 355 {IP: ParseIP(slowDst6)}, 356 {IP: ParseIP("127.0.0.1")}, 357 }, nil 358 default: 359 return fn(ctx, host) 360 } 361 } 362 363 func TestDialerFallbackDelay(t *testing.T) { 364 testenv.MustHaveExternalNetwork(t) 365 366 if !supportsIPv4() || !supportsIPv6() { 367 t.Skip("both IPv4 and IPv6 are required") 368 } 369 370 origTestHookLookupIP := testHookLookupIP 371 defer func() { testHookLookupIP = origTestHookLookupIP }() 372 testHookLookupIP = lookupSlowFast 373 374 origTestHookDialTCP := testHookDialTCP 375 defer func() { testHookDialTCP = origTestHookDialTCP }() 376 testHookDialTCP = slowDialTCP 377 378 var testCases = []struct { 379 dualstack bool 380 delay time.Duration 381 expectElapsed time.Duration 382 }{ 383 // Use a very brief delay, which should fallback immediately. 384 {true, 1 * time.Nanosecond, 0}, 385 // Use a 200ms explicit timeout. 386 {true, 200 * time.Millisecond, 200 * time.Millisecond}, 387 // The default is 300ms. 388 {true, 0, 300 * time.Millisecond}, 389 } 390 391 handler := func(dss *dualStackServer, ln Listener) { 392 for { 393 c, err := ln.Accept() 394 if err != nil { 395 return 396 } 397 c.Close() 398 } 399 } 400 dss, err := newDualStackServer() 401 if err != nil { 402 t.Fatal(err) 403 } 404 defer dss.teardown() 405 if err := dss.buildup(handler); err != nil { 406 t.Fatal(err) 407 } 408 409 for i, tt := range testCases { 410 d := &Dialer{DualStack: tt.dualstack, FallbackDelay: tt.delay} 411 412 startTime := time.Now() 413 c, err := d.Dial("tcp", JoinHostPort("slow6loopback4", dss.port)) 414 elapsed := time.Now().Sub(startTime) 415 if err == nil { 416 c.Close() 417 } else if tt.dualstack { 418 t.Error(err) 419 } 420 expectMin := tt.expectElapsed - 1*time.Millisecond 421 expectMax := tt.expectElapsed + 95*time.Millisecond 422 if !(elapsed >= expectMin) { 423 t.Errorf("#%d: got %v; want >= %v", i, elapsed, expectMin) 424 } 425 if !(elapsed <= expectMax) { 426 t.Errorf("#%d: got %v; want <= %v", i, elapsed, expectMax) 427 } 428 } 429 } 430 431 func TestDialParallelSpuriousConnection(t *testing.T) { 432 if !supportsIPv4() || !supportsIPv6() { 433 t.Skip("both IPv4 and IPv6 are required") 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(time.Now().Add(1 * time.Second)) 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 cancelation. 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 return doDialTCP(context.Background(), net, laddr, raddr) 475 } 476 477 d := Dialer{ 478 FallbackDelay: fallbackDelay, 479 } 480 dp := &dialParam{ 481 Dialer: d, 482 network: "tcp", 483 address: "?", 484 } 485 486 makeAddr := func(ip string) addrList { 487 addr, err := ResolveTCPAddr("tcp", JoinHostPort(ip, dss.port)) 488 if err != nil { 489 t.Fatal(err) 490 } 491 return addrList{addr} 492 } 493 494 // dialParallel returns one connection (and closes the other.) 495 c, err := dialParallel(context.Background(), dp, makeAddr("127.0.0.1"), makeAddr("::1")) 496 if err != nil { 497 t.Fatal(err) 498 } 499 c.Close() 500 501 // The server should've seen both connections. 502 wg.Wait() 503 } 504 505 func TestDialerPartialDeadline(t *testing.T) { 506 now := time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC) 507 var testCases = []struct { 508 now time.Time 509 deadline time.Time 510 addrs int 511 expectDeadline time.Time 512 expectErr error 513 }{ 514 // Regular division. 515 {now, now.Add(12 * time.Second), 1, now.Add(12 * time.Second), nil}, 516 {now, now.Add(12 * time.Second), 2, now.Add(6 * time.Second), nil}, 517 {now, now.Add(12 * time.Second), 3, now.Add(4 * time.Second), nil}, 518 // Bump against the 2-second sane minimum. 519 {now, now.Add(12 * time.Second), 999, now.Add(2 * time.Second), nil}, 520 // Total available is now below the sane minimum. 521 {now, now.Add(1900 * time.Millisecond), 999, now.Add(1900 * time.Millisecond), nil}, 522 // Null deadline. 523 {now, noDeadline, 1, noDeadline, nil}, 524 // Step the clock forward and cross the deadline. 525 {now.Add(-1 * time.Millisecond), now, 1, now, nil}, 526 {now.Add(0 * time.Millisecond), now, 1, noDeadline, poll.ErrTimeout}, 527 {now.Add(1 * time.Millisecond), now, 1, noDeadline, poll.ErrTimeout}, 528 } 529 for i, tt := range testCases { 530 deadline, err := partialDeadline(tt.now, tt.deadline, tt.addrs) 531 if err != tt.expectErr { 532 t.Errorf("#%d: got %v; want %v", i, err, tt.expectErr) 533 } 534 if !deadline.Equal(tt.expectDeadline) { 535 t.Errorf("#%d: got %v; want %v", i, deadline, tt.expectDeadline) 536 } 537 } 538 } 539 540 func TestDialerLocalAddr(t *testing.T) { 541 if !supportsIPv4() || !supportsIPv6() { 542 t.Skip("both IPv4 and IPv6 are required") 543 } 544 545 type test struct { 546 network, raddr string 547 laddr Addr 548 error 549 } 550 var tests = []test{ 551 {"tcp4", "127.0.0.1", nil, nil}, 552 {"tcp4", "127.0.0.1", &TCPAddr{}, nil}, 553 {"tcp4", "127.0.0.1", &TCPAddr{IP: ParseIP("0.0.0.0")}, nil}, 554 {"tcp4", "127.0.0.1", &TCPAddr{IP: ParseIP("0.0.0.0").To4()}, nil}, 555 {"tcp4", "127.0.0.1", &TCPAddr{IP: ParseIP("::")}, &AddrError{Err: "some error"}}, 556 {"tcp4", "127.0.0.1", &TCPAddr{IP: ParseIP("127.0.0.1").To4()}, nil}, 557 {"tcp4", "127.0.0.1", &TCPAddr{IP: ParseIP("127.0.0.1").To16()}, nil}, 558 {"tcp4", "127.0.0.1", &TCPAddr{IP: IPv6loopback}, errNoSuitableAddress}, 559 {"tcp4", "127.0.0.1", &UDPAddr{}, &AddrError{Err: "some error"}}, 560 {"tcp4", "127.0.0.1", &UnixAddr{}, &AddrError{Err: "some error"}}, 561 562 {"tcp6", "::1", nil, nil}, 563 {"tcp6", "::1", &TCPAddr{}, nil}, 564 {"tcp6", "::1", &TCPAddr{IP: ParseIP("0.0.0.0")}, nil}, 565 {"tcp6", "::1", &TCPAddr{IP: ParseIP("0.0.0.0").To4()}, nil}, 566 {"tcp6", "::1", &TCPAddr{IP: ParseIP("::")}, nil}, 567 {"tcp6", "::1", &TCPAddr{IP: ParseIP("127.0.0.1").To4()}, errNoSuitableAddress}, 568 {"tcp6", "::1", &TCPAddr{IP: ParseIP("127.0.0.1").To16()}, errNoSuitableAddress}, 569 {"tcp6", "::1", &TCPAddr{IP: IPv6loopback}, nil}, 570 {"tcp6", "::1", &UDPAddr{}, &AddrError{Err: "some error"}}, 571 {"tcp6", "::1", &UnixAddr{}, &AddrError{Err: "some error"}}, 572 573 {"tcp", "127.0.0.1", nil, nil}, 574 {"tcp", "127.0.0.1", &TCPAddr{}, nil}, 575 {"tcp", "127.0.0.1", &TCPAddr{IP: ParseIP("0.0.0.0")}, nil}, 576 {"tcp", "127.0.0.1", &TCPAddr{IP: ParseIP("0.0.0.0").To4()}, nil}, 577 {"tcp", "127.0.0.1", &TCPAddr{IP: ParseIP("127.0.0.1").To4()}, nil}, 578 {"tcp", "127.0.0.1", &TCPAddr{IP: ParseIP("127.0.0.1").To16()}, nil}, 579 {"tcp", "127.0.0.1", &TCPAddr{IP: IPv6loopback}, errNoSuitableAddress}, 580 {"tcp", "127.0.0.1", &UDPAddr{}, &AddrError{Err: "some error"}}, 581 {"tcp", "127.0.0.1", &UnixAddr{}, &AddrError{Err: "some error"}}, 582 583 {"tcp", "::1", nil, nil}, 584 {"tcp", "::1", &TCPAddr{}, nil}, 585 {"tcp", "::1", &TCPAddr{IP: ParseIP("0.0.0.0")}, nil}, 586 {"tcp", "::1", &TCPAddr{IP: ParseIP("0.0.0.0").To4()}, nil}, 587 {"tcp", "::1", &TCPAddr{IP: ParseIP("::")}, nil}, 588 {"tcp", "::1", &TCPAddr{IP: ParseIP("127.0.0.1").To4()}, errNoSuitableAddress}, 589 {"tcp", "::1", &TCPAddr{IP: ParseIP("127.0.0.1").To16()}, errNoSuitableAddress}, 590 {"tcp", "::1", &TCPAddr{IP: IPv6loopback}, nil}, 591 {"tcp", "::1", &UDPAddr{}, &AddrError{Err: "some error"}}, 592 {"tcp", "::1", &UnixAddr{}, &AddrError{Err: "some error"}}, 593 } 594 595 if supportsIPv4map() { 596 tests = append(tests, test{ 597 "tcp", "127.0.0.1", &TCPAddr{IP: ParseIP("::")}, nil, 598 }) 599 } else { 600 tests = append(tests, test{ 601 "tcp", "127.0.0.1", &TCPAddr{IP: ParseIP("::")}, &AddrError{Err: "some error"}, 602 }) 603 } 604 605 origTestHookLookupIP := testHookLookupIP 606 defer func() { testHookLookupIP = origTestHookLookupIP }() 607 testHookLookupIP = lookupLocalhost 608 handler := func(ls *localServer, ln Listener) { 609 for { 610 c, err := ln.Accept() 611 if err != nil { 612 return 613 } 614 c.Close() 615 } 616 } 617 var err error 618 var lss [2]*localServer 619 for i, network := range []string{"tcp4", "tcp6"} { 620 lss[i], err = newLocalServer(network) 621 if err != nil { 622 t.Fatal(err) 623 } 624 defer lss[i].teardown() 625 if err := lss[i].buildup(handler); err != nil { 626 t.Fatal(err) 627 } 628 } 629 630 for _, tt := range tests { 631 d := &Dialer{LocalAddr: tt.laddr} 632 var addr string 633 ip := ParseIP(tt.raddr) 634 if ip.To4() != nil { 635 addr = lss[0].Listener.Addr().String() 636 } 637 if ip.To16() != nil && ip.To4() == nil { 638 addr = lss[1].Listener.Addr().String() 639 } 640 c, err := d.Dial(tt.network, addr) 641 if err == nil && tt.error != nil || err != nil && tt.error == nil { 642 t.Errorf("%s %v->%s: got %v; want %v", tt.network, tt.laddr, tt.raddr, err, tt.error) 643 } 644 if err != nil { 645 if perr := parseDialError(err); perr != nil { 646 t.Error(perr) 647 } 648 continue 649 } 650 c.Close() 651 } 652 } 653 654 func TestDialerDualStack(t *testing.T) { 655 testenv.SkipFlaky(t, 13324) 656 657 if !supportsIPv4() || !supportsIPv6() { 658 t.Skip("both IPv4 and IPv6 are required") 659 } 660 661 closedPortDelay, expectClosedPortDelay := dialClosedPort() 662 if closedPortDelay > expectClosedPortDelay { 663 t.Errorf("got %v; want <= %v", closedPortDelay, expectClosedPortDelay) 664 } 665 666 origTestHookLookupIP := testHookLookupIP 667 defer func() { testHookLookupIP = origTestHookLookupIP }() 668 testHookLookupIP = lookupLocalhost 669 handler := func(dss *dualStackServer, ln Listener) { 670 for { 671 c, err := ln.Accept() 672 if err != nil { 673 return 674 } 675 c.Close() 676 } 677 } 678 679 var timeout = 150*time.Millisecond + closedPortDelay 680 for _, dualstack := range []bool{false, true} { 681 dss, err := newDualStackServer() 682 if err != nil { 683 t.Fatal(err) 684 } 685 defer dss.teardown() 686 if err := dss.buildup(handler); err != nil { 687 t.Fatal(err) 688 } 689 690 d := &Dialer{DualStack: dualstack, Timeout: timeout} 691 for range dss.lns { 692 c, err := d.Dial("tcp", JoinHostPort("localhost", dss.port)) 693 if err != nil { 694 t.Error(err) 695 continue 696 } 697 switch addr := c.LocalAddr().(*TCPAddr); { 698 case addr.IP.To4() != nil: 699 dss.teardownNetwork("tcp4") 700 case addr.IP.To16() != nil && addr.IP.To4() == nil: 701 dss.teardownNetwork("tcp6") 702 } 703 c.Close() 704 } 705 } 706 } 707 708 func TestDialerKeepAlive(t *testing.T) { 709 handler := func(ls *localServer, ln Listener) { 710 for { 711 c, err := ln.Accept() 712 if err != nil { 713 return 714 } 715 c.Close() 716 } 717 } 718 ls, err := newLocalServer("tcp") 719 if err != nil { 720 t.Fatal(err) 721 } 722 defer ls.teardown() 723 if err := ls.buildup(handler); err != nil { 724 t.Fatal(err) 725 } 726 defer func() { testHookSetKeepAlive = func() {} }() 727 728 for _, keepAlive := range []bool{false, true} { 729 got := false 730 testHookSetKeepAlive = func() { got = true } 731 var d Dialer 732 if keepAlive { 733 d.KeepAlive = 30 * time.Second 734 } 735 c, err := d.Dial("tcp", ls.Listener.Addr().String()) 736 if err != nil { 737 t.Fatal(err) 738 } 739 c.Close() 740 if got != keepAlive { 741 t.Errorf("Dialer.KeepAlive = %v: SetKeepAlive called = %v, want %v", d.KeepAlive, got, !got) 742 } 743 } 744 } 745 746 func TestDialCancel(t *testing.T) { 747 switch testenv.Builder() { 748 case "linux-arm64-buildlet": 749 t.Skip("skipping on linux-arm64-buildlet; incompatible network config? issue 15191") 750 case "": 751 testenv.MustHaveExternalNetwork(t) 752 } 753 754 if runtime.GOOS == "nacl" { 755 // nacl doesn't have external network access. 756 t.Skipf("skipping on %s", runtime.GOOS) 757 } 758 759 blackholeIPPort := JoinHostPort(slowDst4, "1234") 760 if !supportsIPv4() { 761 blackholeIPPort = JoinHostPort(slowDst6, "1234") 762 } 763 764 ticker := time.NewTicker(10 * time.Millisecond) 765 defer ticker.Stop() 766 767 const cancelTick = 5 // the timer tick we cancel the dial at 768 const timeoutTick = 100 769 770 var d Dialer 771 cancel := make(chan struct{}) 772 d.Cancel = cancel 773 errc := make(chan error, 1) 774 connc := make(chan Conn, 1) 775 go func() { 776 if c, err := d.Dial("tcp", blackholeIPPort); err != nil { 777 errc <- err 778 } else { 779 connc <- c 780 } 781 }() 782 ticks := 0 783 for { 784 select { 785 case <-ticker.C: 786 ticks++ 787 if ticks == cancelTick { 788 close(cancel) 789 } 790 if ticks == timeoutTick { 791 t.Fatal("timeout waiting for dial to fail") 792 } 793 case c := <-connc: 794 c.Close() 795 t.Fatal("unexpected successful connection") 796 case err := <-errc: 797 if perr := parseDialError(err); perr != nil { 798 t.Error(perr) 799 } 800 if ticks < cancelTick { 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 cancelation 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 if testenv.Builder() == "" { 899 testenv.MustHaveExternalNetwork(t) 900 } 901 ln, err := Listen("tcp", ":0") 902 if err != nil { 903 t.Fatal(err) 904 } 905 defer ln.Close() 906 addr := ln.Addr().String() 907 c, err := Dial("tcp", addr) 908 if err != nil { 909 t.Fatalf("for addr %q, dial error: %v", addr, err) 910 } 911 c.Close() 912 }