github.com/hlts2/go@v0.0.0-20170904000733-812b34efaed8/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 {
   165  		expected = 95 * time.Millisecond
   166  	}
   167  
   168  	l, err := Listen("tcp", "127.0.0.1:0")
   169  	if err != nil {
   170  		return 999 * time.Hour, expected
   171  	}
   172  	addr := l.Addr().String()
   173  	l.Close()
   174  	// On OpenBSD, interference from TestSelfConnect is mysteriously
   175  	// causing the first attempt to hang for a few seconds, so we throw
   176  	// away the first result and keep the second.
   177  	for i := 1; ; i++ {
   178  		startTime := time.Now()
   179  		c, err := Dial("tcp", addr)
   180  		if err == nil {
   181  			c.Close()
   182  		}
   183  		elapsed := time.Now().Sub(startTime)
   184  		if i == 2 {
   185  			return elapsed, expected
   186  		}
   187  	}
   188  }
   189  
   190  func TestDialParallel(t *testing.T) {
   191  	testenv.MustHaveExternalNetwork(t)
   192  
   193  	if !supportsIPv4() || !supportsIPv6() {
   194  		t.Skip("both IPv4 and IPv6 are required")
   195  	}
   196  
   197  	closedPortDelay, expectClosedPortDelay := dialClosedPort()
   198  	if closedPortDelay > expectClosedPortDelay {
   199  		t.Errorf("got %v; want <= %v", closedPortDelay, expectClosedPortDelay)
   200  	}
   201  
   202  	const instant time.Duration = 0
   203  	const fallbackDelay = 200 * time.Millisecond
   204  
   205  	// Some cases will run quickly when "connection refused" is fast,
   206  	// or trigger the fallbackDelay on Windows. This value holds the
   207  	// lesser of the two delays.
   208  	var closedPortOrFallbackDelay time.Duration
   209  	if closedPortDelay < fallbackDelay {
   210  		closedPortOrFallbackDelay = closedPortDelay
   211  	} else {
   212  		closedPortOrFallbackDelay = fallbackDelay
   213  	}
   214  
   215  	origTestHookDialTCP := testHookDialTCP
   216  	defer func() { testHookDialTCP = origTestHookDialTCP }()
   217  	testHookDialTCP = slowDialTCP
   218  
   219  	nCopies := func(s string, n int) []string {
   220  		out := make([]string, n)
   221  		for i := 0; i < n; i++ {
   222  			out[i] = s
   223  		}
   224  		return out
   225  	}
   226  
   227  	var testCases = []struct {
   228  		primaries       []string
   229  		fallbacks       []string
   230  		teardownNetwork string
   231  		expectOk        bool
   232  		expectElapsed   time.Duration
   233  	}{
   234  		// These should just work on the first try.
   235  		{[]string{"127.0.0.1"}, []string{}, "", true, instant},
   236  		{[]string{"::1"}, []string{}, "", true, instant},
   237  		{[]string{"127.0.0.1", "::1"}, []string{slowDst6}, "tcp6", true, instant},
   238  		{[]string{"::1", "127.0.0.1"}, []string{slowDst4}, "tcp4", true, instant},
   239  		// Primary is slow; fallback should kick in.
   240  		{[]string{slowDst4}, []string{"::1"}, "", true, fallbackDelay},
   241  		// Skip a "connection refused" in the primary thread.
   242  		{[]string{"127.0.0.1", "::1"}, []string{}, "tcp4", true, closedPortDelay},
   243  		{[]string{"::1", "127.0.0.1"}, []string{}, "tcp6", true, closedPortDelay},
   244  		// Skip a "connection refused" in the fallback thread.
   245  		{[]string{slowDst4, slowDst6}, []string{"::1", "127.0.0.1"}, "tcp6", true, fallbackDelay + closedPortDelay},
   246  		// Primary refused, fallback without delay.
   247  		{[]string{"127.0.0.1"}, []string{"::1"}, "tcp4", true, closedPortOrFallbackDelay},
   248  		{[]string{"::1"}, []string{"127.0.0.1"}, "tcp6", true, closedPortOrFallbackDelay},
   249  		// Everything is refused.
   250  		{[]string{"127.0.0.1"}, []string{}, "tcp4", false, closedPortDelay},
   251  		// Nothing to do; fail instantly.
   252  		{[]string{}, []string{}, "", false, instant},
   253  		// Connecting to tons of addresses should not trip the deadline.
   254  		{nCopies("::1", 1000), []string{}, "", true, instant},
   255  	}
   256  
   257  	handler := func(dss *dualStackServer, ln Listener) {
   258  		for {
   259  			c, err := ln.Accept()
   260  			if err != nil {
   261  				return
   262  			}
   263  			c.Close()
   264  		}
   265  	}
   266  
   267  	// Convert a list of IP strings into TCPAddrs.
   268  	makeAddrs := func(ips []string, port string) addrList {
   269  		var out addrList
   270  		for _, ip := range ips {
   271  			addr, err := ResolveTCPAddr("tcp", JoinHostPort(ip, port))
   272  			if err != nil {
   273  				t.Fatal(err)
   274  			}
   275  			out = append(out, addr)
   276  		}
   277  		return out
   278  	}
   279  
   280  	for i, tt := range testCases {
   281  		dss, err := newDualStackServer()
   282  		if err != nil {
   283  			t.Fatal(err)
   284  		}
   285  		defer dss.teardown()
   286  		if err := dss.buildup(handler); err != nil {
   287  			t.Fatal(err)
   288  		}
   289  		if tt.teardownNetwork != "" {
   290  			// Destroy one of the listening sockets, creating an unreachable port.
   291  			dss.teardownNetwork(tt.teardownNetwork)
   292  		}
   293  
   294  		primaries := makeAddrs(tt.primaries, dss.port)
   295  		fallbacks := makeAddrs(tt.fallbacks, dss.port)
   296  		d := Dialer{
   297  			FallbackDelay: fallbackDelay,
   298  		}
   299  		startTime := time.Now()
   300  		dp := &dialParam{
   301  			Dialer:  d,
   302  			network: "tcp",
   303  			address: "?",
   304  		}
   305  		c, err := dialParallel(context.Background(), dp, primaries, fallbacks)
   306  		elapsed := time.Since(startTime)
   307  
   308  		if c != nil {
   309  			c.Close()
   310  		}
   311  
   312  		if tt.expectOk && err != nil {
   313  			t.Errorf("#%d: got %v; want nil", i, err)
   314  		} else if !tt.expectOk && err == nil {
   315  			t.Errorf("#%d: got nil; want non-nil", i)
   316  		}
   317  
   318  		expectElapsedMin := tt.expectElapsed - 95*time.Millisecond
   319  		expectElapsedMax := tt.expectElapsed + 95*time.Millisecond
   320  		if !(elapsed >= expectElapsedMin) {
   321  			t.Errorf("#%d: got %v; want >= %v", i, elapsed, expectElapsedMin)
   322  		} else if !(elapsed <= expectElapsedMax) {
   323  			t.Errorf("#%d: got %v; want <= %v", i, elapsed, expectElapsedMax)
   324  		}
   325  
   326  		// Repeat each case, ensuring that it can be canceled quickly.
   327  		ctx, cancel := context.WithCancel(context.Background())
   328  		var wg sync.WaitGroup
   329  		wg.Add(1)
   330  		go func() {
   331  			time.Sleep(5 * time.Millisecond)
   332  			cancel()
   333  			wg.Done()
   334  		}()
   335  		startTime = time.Now()
   336  		c, err = dialParallel(ctx, dp, primaries, fallbacks)
   337  		if c != nil {
   338  			c.Close()
   339  		}
   340  		elapsed = time.Now().Sub(startTime)
   341  		if elapsed > 100*time.Millisecond {
   342  			t.Errorf("#%d (cancel): got %v; want <= 100ms", i, elapsed)
   343  		}
   344  		wg.Wait()
   345  	}
   346  }
   347  
   348  func lookupSlowFast(ctx context.Context, fn func(context.Context, string) ([]IPAddr, error), host string) ([]IPAddr, error) {
   349  	switch host {
   350  	case "slow6loopback4":
   351  		// Returns a slow IPv6 address, and a local IPv4 address.
   352  		return []IPAddr{
   353  			{IP: ParseIP(slowDst6)},
   354  			{IP: ParseIP("127.0.0.1")},
   355  		}, nil
   356  	default:
   357  		return fn(ctx, host)
   358  	}
   359  }
   360  
   361  func TestDialerFallbackDelay(t *testing.T) {
   362  	testenv.MustHaveExternalNetwork(t)
   363  
   364  	if !supportsIPv4() || !supportsIPv6() {
   365  		t.Skip("both IPv4 and IPv6 are required")
   366  	}
   367  
   368  	origTestHookLookupIP := testHookLookupIP
   369  	defer func() { testHookLookupIP = origTestHookLookupIP }()
   370  	testHookLookupIP = lookupSlowFast
   371  
   372  	origTestHookDialTCP := testHookDialTCP
   373  	defer func() { testHookDialTCP = origTestHookDialTCP }()
   374  	testHookDialTCP = slowDialTCP
   375  
   376  	var testCases = []struct {
   377  		dualstack     bool
   378  		delay         time.Duration
   379  		expectElapsed time.Duration
   380  	}{
   381  		// Use a very brief delay, which should fallback immediately.
   382  		{true, 1 * time.Nanosecond, 0},
   383  		// Use a 200ms explicit timeout.
   384  		{true, 200 * time.Millisecond, 200 * time.Millisecond},
   385  		// The default is 300ms.
   386  		{true, 0, 300 * time.Millisecond},
   387  	}
   388  
   389  	handler := func(dss *dualStackServer, ln Listener) {
   390  		for {
   391  			c, err := ln.Accept()
   392  			if err != nil {
   393  				return
   394  			}
   395  			c.Close()
   396  		}
   397  	}
   398  	dss, err := newDualStackServer()
   399  	if err != nil {
   400  		t.Fatal(err)
   401  	}
   402  	defer dss.teardown()
   403  	if err := dss.buildup(handler); err != nil {
   404  		t.Fatal(err)
   405  	}
   406  
   407  	for i, tt := range testCases {
   408  		d := &Dialer{DualStack: tt.dualstack, FallbackDelay: tt.delay}
   409  
   410  		startTime := time.Now()
   411  		c, err := d.Dial("tcp", JoinHostPort("slow6loopback4", dss.port))
   412  		elapsed := time.Now().Sub(startTime)
   413  		if err == nil {
   414  			c.Close()
   415  		} else if tt.dualstack {
   416  			t.Error(err)
   417  		}
   418  		expectMin := tt.expectElapsed - 1*time.Millisecond
   419  		expectMax := tt.expectElapsed + 95*time.Millisecond
   420  		if !(elapsed >= expectMin) {
   421  			t.Errorf("#%d: got %v; want >= %v", i, elapsed, expectMin)
   422  		}
   423  		if !(elapsed <= expectMax) {
   424  			t.Errorf("#%d: got %v; want <= %v", i, elapsed, expectMax)
   425  		}
   426  	}
   427  }
   428  
   429  func TestDialParallelSpuriousConnection(t *testing.T) {
   430  	if !supportsIPv4() || !supportsIPv6() {
   431  		t.Skip("both IPv4 and IPv6 are required")
   432  	}
   433  
   434  	var wg sync.WaitGroup
   435  	wg.Add(2)
   436  	handler := func(dss *dualStackServer, ln Listener) {
   437  		// Accept one connection per address.
   438  		c, err := ln.Accept()
   439  		if err != nil {
   440  			t.Fatal(err)
   441  		}
   442  		// The client should close itself, without sending data.
   443  		c.SetReadDeadline(time.Now().Add(1 * time.Second))
   444  		var b [1]byte
   445  		if _, err := c.Read(b[:]); err != io.EOF {
   446  			t.Errorf("got %v; want %v", err, io.EOF)
   447  		}
   448  		c.Close()
   449  		wg.Done()
   450  	}
   451  	dss, err := newDualStackServer()
   452  	if err != nil {
   453  		t.Fatal(err)
   454  	}
   455  	defer dss.teardown()
   456  	if err := dss.buildup(handler); err != nil {
   457  		t.Fatal(err)
   458  	}
   459  
   460  	const fallbackDelay = 100 * time.Millisecond
   461  
   462  	origTestHookDialTCP := testHookDialTCP
   463  	defer func() { testHookDialTCP = origTestHookDialTCP }()
   464  	testHookDialTCP = func(ctx context.Context, net string, laddr, raddr *TCPAddr) (*TCPConn, error) {
   465  		// Sleep long enough for Happy Eyeballs to kick in, and inhibit cancelation.
   466  		// This forces dialParallel to juggle two successful connections.
   467  		time.Sleep(fallbackDelay * 2)
   468  
   469  		// Now ignore the provided context (which will be canceled) and use a
   470  		// different one to make sure this completes with a valid connection,
   471  		// which we hope to be closed below:
   472  		return doDialTCP(context.Background(), net, laddr, raddr)
   473  	}
   474  
   475  	d := Dialer{
   476  		FallbackDelay: fallbackDelay,
   477  	}
   478  	dp := &dialParam{
   479  		Dialer:  d,
   480  		network: "tcp",
   481  		address: "?",
   482  	}
   483  
   484  	makeAddr := func(ip string) addrList {
   485  		addr, err := ResolveTCPAddr("tcp", JoinHostPort(ip, dss.port))
   486  		if err != nil {
   487  			t.Fatal(err)
   488  		}
   489  		return addrList{addr}
   490  	}
   491  
   492  	// dialParallel returns one connection (and closes the other.)
   493  	c, err := dialParallel(context.Background(), dp, makeAddr("127.0.0.1"), makeAddr("::1"))
   494  	if err != nil {
   495  		t.Fatal(err)
   496  	}
   497  	c.Close()
   498  
   499  	// The server should've seen both connections.
   500  	wg.Wait()
   501  }
   502  
   503  func TestDialerPartialDeadline(t *testing.T) {
   504  	now := time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC)
   505  	var testCases = []struct {
   506  		now            time.Time
   507  		deadline       time.Time
   508  		addrs          int
   509  		expectDeadline time.Time
   510  		expectErr      error
   511  	}{
   512  		// Regular division.
   513  		{now, now.Add(12 * time.Second), 1, now.Add(12 * time.Second), nil},
   514  		{now, now.Add(12 * time.Second), 2, now.Add(6 * time.Second), nil},
   515  		{now, now.Add(12 * time.Second), 3, now.Add(4 * time.Second), nil},
   516  		// Bump against the 2-second sane minimum.
   517  		{now, now.Add(12 * time.Second), 999, now.Add(2 * time.Second), nil},
   518  		// Total available is now below the sane minimum.
   519  		{now, now.Add(1900 * time.Millisecond), 999, now.Add(1900 * time.Millisecond), nil},
   520  		// Null deadline.
   521  		{now, noDeadline, 1, noDeadline, nil},
   522  		// Step the clock forward and cross the deadline.
   523  		{now.Add(-1 * time.Millisecond), now, 1, now, nil},
   524  		{now.Add(0 * time.Millisecond), now, 1, noDeadline, poll.ErrTimeout},
   525  		{now.Add(1 * time.Millisecond), now, 1, noDeadline, poll.ErrTimeout},
   526  	}
   527  	for i, tt := range testCases {
   528  		deadline, err := partialDeadline(tt.now, tt.deadline, tt.addrs)
   529  		if err != tt.expectErr {
   530  			t.Errorf("#%d: got %v; want %v", i, err, tt.expectErr)
   531  		}
   532  		if !deadline.Equal(tt.expectDeadline) {
   533  			t.Errorf("#%d: got %v; want %v", i, deadline, tt.expectDeadline)
   534  		}
   535  	}
   536  }
   537  
   538  func TestDialerLocalAddr(t *testing.T) {
   539  	if !supportsIPv4() || !supportsIPv6() {
   540  		t.Skip("both IPv4 and IPv6 are required")
   541  	}
   542  
   543  	type test struct {
   544  		network, raddr string
   545  		laddr          Addr
   546  		error
   547  	}
   548  	var tests = []test{
   549  		{"tcp4", "127.0.0.1", nil, nil},
   550  		{"tcp4", "127.0.0.1", &TCPAddr{}, nil},
   551  		{"tcp4", "127.0.0.1", &TCPAddr{IP: ParseIP("0.0.0.0")}, nil},
   552  		{"tcp4", "127.0.0.1", &TCPAddr{IP: ParseIP("0.0.0.0").To4()}, nil},
   553  		{"tcp4", "127.0.0.1", &TCPAddr{IP: ParseIP("::")}, &AddrError{Err: "some error"}},
   554  		{"tcp4", "127.0.0.1", &TCPAddr{IP: ParseIP("127.0.0.1").To4()}, nil},
   555  		{"tcp4", "127.0.0.1", &TCPAddr{IP: ParseIP("127.0.0.1").To16()}, nil},
   556  		{"tcp4", "127.0.0.1", &TCPAddr{IP: IPv6loopback}, errNoSuitableAddress},
   557  		{"tcp4", "127.0.0.1", &UDPAddr{}, &AddrError{Err: "some error"}},
   558  		{"tcp4", "127.0.0.1", &UnixAddr{}, &AddrError{Err: "some error"}},
   559  
   560  		{"tcp6", "::1", nil, nil},
   561  		{"tcp6", "::1", &TCPAddr{}, nil},
   562  		{"tcp6", "::1", &TCPAddr{IP: ParseIP("0.0.0.0")}, nil},
   563  		{"tcp6", "::1", &TCPAddr{IP: ParseIP("0.0.0.0").To4()}, nil},
   564  		{"tcp6", "::1", &TCPAddr{IP: ParseIP("::")}, nil},
   565  		{"tcp6", "::1", &TCPAddr{IP: ParseIP("127.0.0.1").To4()}, errNoSuitableAddress},
   566  		{"tcp6", "::1", &TCPAddr{IP: ParseIP("127.0.0.1").To16()}, errNoSuitableAddress},
   567  		{"tcp6", "::1", &TCPAddr{IP: IPv6loopback}, nil},
   568  		{"tcp6", "::1", &UDPAddr{}, &AddrError{Err: "some error"}},
   569  		{"tcp6", "::1", &UnixAddr{}, &AddrError{Err: "some error"}},
   570  
   571  		{"tcp", "127.0.0.1", nil, nil},
   572  		{"tcp", "127.0.0.1", &TCPAddr{}, nil},
   573  		{"tcp", "127.0.0.1", &TCPAddr{IP: ParseIP("0.0.0.0")}, nil},
   574  		{"tcp", "127.0.0.1", &TCPAddr{IP: ParseIP("0.0.0.0").To4()}, nil},
   575  		{"tcp", "127.0.0.1", &TCPAddr{IP: ParseIP("127.0.0.1").To4()}, nil},
   576  		{"tcp", "127.0.0.1", &TCPAddr{IP: ParseIP("127.0.0.1").To16()}, nil},
   577  		{"tcp", "127.0.0.1", &TCPAddr{IP: IPv6loopback}, errNoSuitableAddress},
   578  		{"tcp", "127.0.0.1", &UDPAddr{}, &AddrError{Err: "some error"}},
   579  		{"tcp", "127.0.0.1", &UnixAddr{}, &AddrError{Err: "some error"}},
   580  
   581  		{"tcp", "::1", nil, nil},
   582  		{"tcp", "::1", &TCPAddr{}, nil},
   583  		{"tcp", "::1", &TCPAddr{IP: ParseIP("0.0.0.0")}, nil},
   584  		{"tcp", "::1", &TCPAddr{IP: ParseIP("0.0.0.0").To4()}, nil},
   585  		{"tcp", "::1", &TCPAddr{IP: ParseIP("::")}, nil},
   586  		{"tcp", "::1", &TCPAddr{IP: ParseIP("127.0.0.1").To4()}, errNoSuitableAddress},
   587  		{"tcp", "::1", &TCPAddr{IP: ParseIP("127.0.0.1").To16()}, errNoSuitableAddress},
   588  		{"tcp", "::1", &TCPAddr{IP: IPv6loopback}, nil},
   589  		{"tcp", "::1", &UDPAddr{}, &AddrError{Err: "some error"}},
   590  		{"tcp", "::1", &UnixAddr{}, &AddrError{Err: "some error"}},
   591  	}
   592  
   593  	if supportsIPv4map() {
   594  		tests = append(tests, test{
   595  			"tcp", "127.0.0.1", &TCPAddr{IP: ParseIP("::")}, nil,
   596  		})
   597  	} else {
   598  		tests = append(tests, test{
   599  			"tcp", "127.0.0.1", &TCPAddr{IP: ParseIP("::")}, &AddrError{Err: "some error"},
   600  		})
   601  	}
   602  
   603  	origTestHookLookupIP := testHookLookupIP
   604  	defer func() { testHookLookupIP = origTestHookLookupIP }()
   605  	testHookLookupIP = lookupLocalhost
   606  	handler := func(ls *localServer, ln Listener) {
   607  		for {
   608  			c, err := ln.Accept()
   609  			if err != nil {
   610  				return
   611  			}
   612  			c.Close()
   613  		}
   614  	}
   615  	var err error
   616  	var lss [2]*localServer
   617  	for i, network := range []string{"tcp4", "tcp6"} {
   618  		lss[i], err = newLocalServer(network)
   619  		if err != nil {
   620  			t.Fatal(err)
   621  		}
   622  		defer lss[i].teardown()
   623  		if err := lss[i].buildup(handler); err != nil {
   624  			t.Fatal(err)
   625  		}
   626  	}
   627  
   628  	for _, tt := range tests {
   629  		d := &Dialer{LocalAddr: tt.laddr}
   630  		var addr string
   631  		ip := ParseIP(tt.raddr)
   632  		if ip.To4() != nil {
   633  			addr = lss[0].Listener.Addr().String()
   634  		}
   635  		if ip.To16() != nil && ip.To4() == nil {
   636  			addr = lss[1].Listener.Addr().String()
   637  		}
   638  		c, err := d.Dial(tt.network, addr)
   639  		if err == nil && tt.error != nil || err != nil && tt.error == nil {
   640  			t.Errorf("%s %v->%s: got %v; want %v", tt.network, tt.laddr, tt.raddr, err, tt.error)
   641  		}
   642  		if err != nil {
   643  			if perr := parseDialError(err); perr != nil {
   644  				t.Error(perr)
   645  			}
   646  			continue
   647  		}
   648  		c.Close()
   649  	}
   650  }
   651  
   652  func TestDialerDualStack(t *testing.T) {
   653  	testenv.SkipFlaky(t, 13324)
   654  
   655  	if !supportsIPv4() || !supportsIPv6() {
   656  		t.Skip("both IPv4 and IPv6 are required")
   657  	}
   658  
   659  	closedPortDelay, expectClosedPortDelay := dialClosedPort()
   660  	if closedPortDelay > expectClosedPortDelay {
   661  		t.Errorf("got %v; want <= %v", closedPortDelay, expectClosedPortDelay)
   662  	}
   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() {} }()
   725  
   726  	for _, keepAlive := range []bool{false, true} {
   727  		got := false
   728  		testHookSetKeepAlive = func() { got = true }
   729  		var d Dialer
   730  		if keepAlive {
   731  			d.KeepAlive = 30 * time.Second
   732  		}
   733  		c, err := d.Dial("tcp", ls.Listener.Addr().String())
   734  		if err != nil {
   735  			t.Fatal(err)
   736  		}
   737  		c.Close()
   738  		if got != keepAlive {
   739  			t.Errorf("Dialer.KeepAlive = %v: SetKeepAlive called = %v, want %v", d.KeepAlive, got, !got)
   740  		}
   741  	}
   742  }
   743  
   744  func TestDialCancel(t *testing.T) {
   745  	switch testenv.Builder() {
   746  	case "linux-arm64-buildlet":
   747  		t.Skip("skipping on linux-arm64-buildlet; incompatible network config? issue 15191")
   748  	case "":
   749  		testenv.MustHaveExternalNetwork(t)
   750  	}
   751  
   752  	if runtime.GOOS == "nacl" {
   753  		// nacl doesn't have external network access.
   754  		t.Skipf("skipping on %s", runtime.GOOS)
   755  	}
   756  
   757  	blackholeIPPort := JoinHostPort(slowDst4, "1234")
   758  	if !supportsIPv4() {
   759  		blackholeIPPort = JoinHostPort(slowDst6, "1234")
   760  	}
   761  
   762  	ticker := time.NewTicker(10 * time.Millisecond)
   763  	defer ticker.Stop()
   764  
   765  	const cancelTick = 5 // the timer tick we cancel the dial at
   766  	const timeoutTick = 100
   767  
   768  	var d Dialer
   769  	cancel := make(chan struct{})
   770  	d.Cancel = cancel
   771  	errc := make(chan error, 1)
   772  	connc := make(chan Conn, 1)
   773  	go func() {
   774  		if c, err := d.Dial("tcp", blackholeIPPort); err != nil {
   775  			errc <- err
   776  		} else {
   777  			connc <- c
   778  		}
   779  	}()
   780  	ticks := 0
   781  	for {
   782  		select {
   783  		case <-ticker.C:
   784  			ticks++
   785  			if ticks == cancelTick {
   786  				close(cancel)
   787  			}
   788  			if ticks == timeoutTick {
   789  				t.Fatal("timeout waiting for dial to fail")
   790  			}
   791  		case c := <-connc:
   792  			c.Close()
   793  			t.Fatal("unexpected successful connection")
   794  		case err := <-errc:
   795  			if perr := parseDialError(err); perr != nil {
   796  				t.Error(perr)
   797  			}
   798  			if ticks < cancelTick {
   799  				t.Fatalf("dial error after %d ticks (%d before cancel sent): %v",
   800  					ticks, cancelTick-ticks, err)
   801  			}
   802  			if oe, ok := err.(*OpError); !ok || oe.Err != errCanceled {
   803  				t.Fatalf("dial error = %v (%T); want OpError with Err == errCanceled", err, err)
   804  			}
   805  			return // success.
   806  		}
   807  	}
   808  }
   809  
   810  func TestCancelAfterDial(t *testing.T) {
   811  	if testing.Short() {
   812  		t.Skip("avoiding time.Sleep")
   813  	}
   814  
   815  	ln, err := newLocalListener("tcp")
   816  	if err != nil {
   817  		t.Fatal(err)
   818  	}
   819  
   820  	var wg sync.WaitGroup
   821  	wg.Add(1)
   822  	defer func() {
   823  		ln.Close()
   824  		wg.Wait()
   825  	}()
   826  
   827  	// Echo back the first line of each incoming connection.
   828  	go func() {
   829  		for {
   830  			c, err := ln.Accept()
   831  			if err != nil {
   832  				break
   833  			}
   834  			rb := bufio.NewReader(c)
   835  			line, err := rb.ReadString('\n')
   836  			if err != nil {
   837  				t.Error(err)
   838  				c.Close()
   839  				continue
   840  			}
   841  			if _, err := c.Write([]byte(line)); err != nil {
   842  				t.Error(err)
   843  			}
   844  			c.Close()
   845  		}
   846  		wg.Done()
   847  	}()
   848  
   849  	try := func() {
   850  		cancel := make(chan struct{})
   851  		d := &Dialer{Cancel: cancel}
   852  		c, err := d.Dial("tcp", ln.Addr().String())
   853  
   854  		// Immediately after dialing, request cancelation and sleep.
   855  		// Before Issue 15078 was fixed, this would cause subsequent operations
   856  		// to fail with an i/o timeout roughly 50% of the time.
   857  		close(cancel)
   858  		time.Sleep(10 * time.Millisecond)
   859  
   860  		if err != nil {
   861  			t.Fatal(err)
   862  		}
   863  		defer c.Close()
   864  
   865  		// Send some data to confirm that the connection is still alive.
   866  		const message = "echo!\n"
   867  		if _, err := c.Write([]byte(message)); err != nil {
   868  			t.Fatal(err)
   869  		}
   870  
   871  		// The server should echo the line, and close the connection.
   872  		rb := bufio.NewReader(c)
   873  		line, err := rb.ReadString('\n')
   874  		if err != nil {
   875  			t.Fatal(err)
   876  		}
   877  		if line != message {
   878  			t.Errorf("got %q; want %q", line, message)
   879  		}
   880  		if _, err := rb.ReadByte(); err != io.EOF {
   881  			t.Errorf("got %v; want %v", err, io.EOF)
   882  		}
   883  	}
   884  
   885  	// This bug manifested about 50% of the time, so try it a few times.
   886  	for i := 0; i < 10; i++ {
   887  		try()
   888  	}
   889  }
   890  
   891  // Issue 18806: it should always be possible to net.Dial a
   892  // net.Listener().Addr().String when the listen address was ":n", even
   893  // if the machine has halfway configured IPv6 such that it can bind on
   894  // "::" not connect back to that same address.
   895  func TestDialListenerAddr(t *testing.T) {
   896  	if testenv.Builder() == "" {
   897  		testenv.MustHaveExternalNetwork(t)
   898  	}
   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  }