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