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