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