...

Source file src/net/dial_test.go

Documentation: net

		 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  //go:build !js
		 6  // +build !js
		 7  
		 8  package net
		 9  
		10  import (
		11  	"bufio"
		12  	"context"
		13  	"internal/testenv"
		14  	"io"
		15  	"os"
		16  	"runtime"
		17  	"strings"
		18  	"sync"
		19  	"testing"
		20  	"time"
		21  )
		22  
		23  var prohibitionaryDialArgTests = []struct {
		24  	network string
		25  	address string
		26  }{
		27  	{"tcp6", "127.0.0.1"},
		28  	{"tcp6", "::ffff:127.0.0.1"},
		29  }
		30  
		31  func TestProhibitionaryDialArg(t *testing.T) {
		32  	testenv.MustHaveExternalNetwork(t)
		33  
		34  	switch runtime.GOOS {
		35  	case "plan9":
		36  		t.Skipf("not supported on %s", runtime.GOOS)
		37  	}
		38  	if !supportsIPv4map() {
		39  		t.Skip("mapping ipv4 address inside ipv6 address not supported")
		40  	}
		41  
		42  	ln, err := Listen("tcp", "[::]:0")
		43  	if err != nil {
		44  		t.Fatal(err)
		45  	}
		46  	defer ln.Close()
		47  
		48  	_, port, err := SplitHostPort(ln.Addr().String())
		49  	if err != nil {
		50  		t.Fatal(err)
		51  	}
		52  
		53  	for i, tt := range prohibitionaryDialArgTests {
		54  		c, err := Dial(tt.network, JoinHostPort(tt.address, port))
		55  		if err == nil {
		56  			c.Close()
		57  			t.Errorf("#%d: %v", i, err)
		58  		}
		59  	}
		60  }
		61  
		62  func TestDialLocal(t *testing.T) {
		63  	ln, err := newLocalListener("tcp")
		64  	if err != nil {
		65  		t.Fatal(err)
		66  	}
		67  	defer ln.Close()
		68  	_, port, err := SplitHostPort(ln.Addr().String())
		69  	if err != nil {
		70  		t.Fatal(err)
		71  	}
		72  	c, err := Dial("tcp", JoinHostPort("", port))
		73  	if err != nil {
		74  		t.Fatal(err)
		75  	}
		76  	c.Close()
		77  }
		78  
		79  func TestDialerDualStackFDLeak(t *testing.T) {
		80  	switch runtime.GOOS {
		81  	case "plan9":
		82  		t.Skipf("%s does not have full support of socktest", runtime.GOOS)
		83  	case "windows":
		84  		t.Skipf("not implemented a way to cancel dial racers in TCP SYN-SENT state on %s", runtime.GOOS)
		85  	case "openbsd":
		86  		testenv.SkipFlaky(t, 15157)
		87  	}
		88  	if !supportsIPv4() || !supportsIPv6() {
		89  		t.Skip("both IPv4 and IPv6 are required")
		90  	}
		91  
		92  	before := sw.Sockets()
		93  	origTestHookLookupIP := testHookLookupIP
		94  	defer func() { testHookLookupIP = origTestHookLookupIP }()
		95  	testHookLookupIP = lookupLocalhost
		96  	handler := func(dss *dualStackServer, ln Listener) {
		97  		for {
		98  			c, err := ln.Accept()
		99  			if err != nil {
	 100  				return
	 101  			}
	 102  			c.Close()
	 103  		}
	 104  	}
	 105  	dss, err := newDualStackServer()
	 106  	if err != nil {
	 107  		t.Fatal(err)
	 108  	}
	 109  	if err := dss.buildup(handler); err != nil {
	 110  		dss.teardown()
	 111  		t.Fatal(err)
	 112  	}
	 113  
	 114  	const N = 10
	 115  	var wg sync.WaitGroup
	 116  	wg.Add(N)
	 117  	d := &Dialer{DualStack: true, Timeout: 5 * time.Second}
	 118  	for i := 0; i < N; i++ {
	 119  		go func() {
	 120  			defer wg.Done()
	 121  			c, err := d.Dial("tcp", JoinHostPort("localhost", dss.port))
	 122  			if err != nil {
	 123  				t.Error(err)
	 124  				return
	 125  			}
	 126  			c.Close()
	 127  		}()
	 128  	}
	 129  	wg.Wait()
	 130  	dss.teardown()
	 131  	after := sw.Sockets()
	 132  	if len(after) != len(before) {
	 133  		t.Errorf("got %d; want %d", len(after), len(before))
	 134  	}
	 135  }
	 136  
	 137  // Define a pair of blackholed (IPv4, IPv6) addresses, for which dialTCP is
	 138  // expected to hang until the timeout elapses. These addresses are reserved
	 139  // for benchmarking by RFC 6890.
	 140  const (
	 141  	slowDst4 = "198.18.0.254"
	 142  	slowDst6 = "2001:2::254"
	 143  )
	 144  
	 145  // In some environments, the slow IPs may be explicitly unreachable, and fail
	 146  // more quickly than expected. This test hook prevents dialTCP from returning
	 147  // before the deadline.
	 148  func slowDialTCP(ctx context.Context, network string, laddr, raddr *TCPAddr) (*TCPConn, error) {
	 149  	sd := &sysDialer{network: network, address: raddr.String()}
	 150  	c, err := sd.doDialTCP(ctx, 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(t *testing.T) (dialLatency time.Duration) {
	 159  	// On most platforms, dialing a closed port should be nearly instantaneous —
	 160  	// less than a few hundred milliseconds. However, on some platforms it may be
	 161  	// much slower: on Windows and OpenBSD, it has been observed to take up to a
	 162  	// few seconds.
	 163  
	 164  	l, err := Listen("tcp", "127.0.0.1:0")
	 165  	if err != nil {
	 166  		t.Fatalf("dialClosedPort: Listen failed: %v", err)
	 167  	}
	 168  	addr := l.Addr().String()
	 169  	l.Close()
	 170  
	 171  	startTime := time.Now()
	 172  	c, err := Dial("tcp", addr)
	 173  	if err == nil {
	 174  		c.Close()
	 175  	}
	 176  	elapsed := time.Now().Sub(startTime)
	 177  	t.Logf("dialClosedPort: measured delay %v", elapsed)
	 178  	return elapsed
	 179  }
	 180  
	 181  func TestDialParallel(t *testing.T) {
	 182  	testenv.MustHaveExternalNetwork(t)
	 183  
	 184  	if !supportsIPv4() || !supportsIPv6() {
	 185  		t.Skip("both IPv4 and IPv6 are required")
	 186  	}
	 187  
	 188  	closedPortDelay := dialClosedPort(t)
	 189  
	 190  	const instant time.Duration = 0
	 191  	const fallbackDelay = 200 * time.Millisecond
	 192  
	 193  	// Some cases will run quickly when "connection refused" is fast,
	 194  	// or trigger the fallbackDelay on Windows. This value holds the
	 195  	// lesser of the two delays.
	 196  	var closedPortOrFallbackDelay time.Duration
	 197  	if closedPortDelay < fallbackDelay {
	 198  		closedPortOrFallbackDelay = closedPortDelay
	 199  	} else {
	 200  		closedPortOrFallbackDelay = fallbackDelay
	 201  	}
	 202  
	 203  	origTestHookDialTCP := testHookDialTCP
	 204  	defer func() { testHookDialTCP = origTestHookDialTCP }()
	 205  	testHookDialTCP = slowDialTCP
	 206  
	 207  	nCopies := func(s string, n int) []string {
	 208  		out := make([]string, n)
	 209  		for i := 0; i < n; i++ {
	 210  			out[i] = s
	 211  		}
	 212  		return out
	 213  	}
	 214  
	 215  	var testCases = []struct {
	 216  		primaries			 []string
	 217  		fallbacks			 []string
	 218  		teardownNetwork string
	 219  		expectOk				bool
	 220  		expectElapsed	 time.Duration
	 221  	}{
	 222  		// These should just work on the first try.
	 223  		{[]string{"127.0.0.1"}, []string{}, "", true, instant},
	 224  		{[]string{"::1"}, []string{}, "", true, instant},
	 225  		{[]string{"127.0.0.1", "::1"}, []string{slowDst6}, "tcp6", true, instant},
	 226  		{[]string{"::1", "127.0.0.1"}, []string{slowDst4}, "tcp4", true, instant},
	 227  		// Primary is slow; fallback should kick in.
	 228  		{[]string{slowDst4}, []string{"::1"}, "", true, fallbackDelay},
	 229  		// Skip a "connection refused" in the primary thread.
	 230  		{[]string{"127.0.0.1", "::1"}, []string{}, "tcp4", true, closedPortDelay},
	 231  		{[]string{"::1", "127.0.0.1"}, []string{}, "tcp6", true, closedPortDelay},
	 232  		// Skip a "connection refused" in the fallback thread.
	 233  		{[]string{slowDst4, slowDst6}, []string{"::1", "127.0.0.1"}, "tcp6", true, fallbackDelay + closedPortDelay},
	 234  		// Primary refused, fallback without delay.
	 235  		{[]string{"127.0.0.1"}, []string{"::1"}, "tcp4", true, closedPortOrFallbackDelay},
	 236  		{[]string{"::1"}, []string{"127.0.0.1"}, "tcp6", true, closedPortOrFallbackDelay},
	 237  		// Everything is refused.
	 238  		{[]string{"127.0.0.1"}, []string{}, "tcp4", false, closedPortDelay},
	 239  		// Nothing to do; fail instantly.
	 240  		{[]string{}, []string{}, "", false, instant},
	 241  		// Connecting to tons of addresses should not trip the deadline.
	 242  		{nCopies("::1", 1000), []string{}, "", true, instant},
	 243  	}
	 244  
	 245  	handler := func(dss *dualStackServer, ln Listener) {
	 246  		for {
	 247  			c, err := ln.Accept()
	 248  			if err != nil {
	 249  				return
	 250  			}
	 251  			c.Close()
	 252  		}
	 253  	}
	 254  
	 255  	// Convert a list of IP strings into TCPAddrs.
	 256  	makeAddrs := func(ips []string, port string) addrList {
	 257  		var out addrList
	 258  		for _, ip := range ips {
	 259  			addr, err := ResolveTCPAddr("tcp", JoinHostPort(ip, port))
	 260  			if err != nil {
	 261  				t.Fatal(err)
	 262  			}
	 263  			out = append(out, addr)
	 264  		}
	 265  		return out
	 266  	}
	 267  
	 268  	for i, tt := range testCases {
	 269  		dss, err := newDualStackServer()
	 270  		if err != nil {
	 271  			t.Fatal(err)
	 272  		}
	 273  		defer dss.teardown()
	 274  		if err := dss.buildup(handler); err != nil {
	 275  			t.Fatal(err)
	 276  		}
	 277  		if tt.teardownNetwork != "" {
	 278  			// Destroy one of the listening sockets, creating an unreachable port.
	 279  			dss.teardownNetwork(tt.teardownNetwork)
	 280  		}
	 281  
	 282  		primaries := makeAddrs(tt.primaries, dss.port)
	 283  		fallbacks := makeAddrs(tt.fallbacks, dss.port)
	 284  		d := Dialer{
	 285  			FallbackDelay: fallbackDelay,
	 286  		}
	 287  		startTime := time.Now()
	 288  		sd := &sysDialer{
	 289  			Dialer:	d,
	 290  			network: "tcp",
	 291  			address: "?",
	 292  		}
	 293  		c, err := sd.dialParallel(context.Background(), primaries, fallbacks)
	 294  		elapsed := time.Since(startTime)
	 295  
	 296  		if c != nil {
	 297  			c.Close()
	 298  		}
	 299  
	 300  		if tt.expectOk && err != nil {
	 301  			t.Errorf("#%d: got %v; want nil", i, err)
	 302  		} else if !tt.expectOk && err == nil {
	 303  			t.Errorf("#%d: got nil; want non-nil", i)
	 304  		}
	 305  
	 306  		// We used to always use 95 milliseconds as the slop,
	 307  		// but that was flaky on Windows.	See issue 35616.
	 308  		slop := 95 * time.Millisecond
	 309  		if fifth := tt.expectElapsed / 5; fifth > slop {
	 310  			slop = fifth
	 311  		}
	 312  		expectElapsedMin := tt.expectElapsed - slop
	 313  		expectElapsedMax := tt.expectElapsed + slop
	 314  		if elapsed < expectElapsedMin {
	 315  			t.Errorf("#%d: got %v; want >= %v", i, elapsed, expectElapsedMin)
	 316  		} else if elapsed > expectElapsedMax {
	 317  			t.Errorf("#%d: got %v; want <= %v", i, elapsed, expectElapsedMax)
	 318  		}
	 319  
	 320  		// Repeat each case, ensuring that it can be canceled quickly.
	 321  		ctx, cancel := context.WithCancel(context.Background())
	 322  		var wg sync.WaitGroup
	 323  		wg.Add(1)
	 324  		go func() {
	 325  			time.Sleep(5 * time.Millisecond)
	 326  			cancel()
	 327  			wg.Done()
	 328  		}()
	 329  		startTime = time.Now()
	 330  		c, err = sd.dialParallel(ctx, primaries, fallbacks)
	 331  		if c != nil {
	 332  			c.Close()
	 333  		}
	 334  		elapsed = time.Now().Sub(startTime)
	 335  		if elapsed > 100*time.Millisecond {
	 336  			t.Errorf("#%d (cancel): got %v; want <= 100ms", i, elapsed)
	 337  		}
	 338  		wg.Wait()
	 339  	}
	 340  }
	 341  
	 342  func lookupSlowFast(ctx context.Context, fn func(context.Context, string, string) ([]IPAddr, error), network, host string) ([]IPAddr, error) {
	 343  	switch host {
	 344  	case "slow6loopback4":
	 345  		// Returns a slow IPv6 address, and a local IPv4 address.
	 346  		return []IPAddr{
	 347  			{IP: ParseIP(slowDst6)},
	 348  			{IP: ParseIP("127.0.0.1")},
	 349  		}, nil
	 350  	default:
	 351  		return fn(ctx, network, host)
	 352  	}
	 353  }
	 354  
	 355  func TestDialerFallbackDelay(t *testing.T) {
	 356  	testenv.MustHaveExternalNetwork(t)
	 357  
	 358  	if !supportsIPv4() || !supportsIPv6() {
	 359  		t.Skip("both IPv4 and IPv6 are required")
	 360  	}
	 361  
	 362  	origTestHookLookupIP := testHookLookupIP
	 363  	defer func() { testHookLookupIP = origTestHookLookupIP }()
	 364  	testHookLookupIP = lookupSlowFast
	 365  
	 366  	origTestHookDialTCP := testHookDialTCP
	 367  	defer func() { testHookDialTCP = origTestHookDialTCP }()
	 368  	testHookDialTCP = slowDialTCP
	 369  
	 370  	var testCases = []struct {
	 371  		dualstack		 bool
	 372  		delay				 time.Duration
	 373  		expectElapsed time.Duration
	 374  	}{
	 375  		// Use a very brief delay, which should fallback immediately.
	 376  		{true, 1 * time.Nanosecond, 0},
	 377  		// Use a 200ms explicit timeout.
	 378  		{true, 200 * time.Millisecond, 200 * time.Millisecond},
	 379  		// The default is 300ms.
	 380  		{true, 0, 300 * time.Millisecond},
	 381  	}
	 382  
	 383  	handler := func(dss *dualStackServer, ln Listener) {
	 384  		for {
	 385  			c, err := ln.Accept()
	 386  			if err != nil {
	 387  				return
	 388  			}
	 389  			c.Close()
	 390  		}
	 391  	}
	 392  	dss, err := newDualStackServer()
	 393  	if err != nil {
	 394  		t.Fatal(err)
	 395  	}
	 396  	defer dss.teardown()
	 397  	if err := dss.buildup(handler); err != nil {
	 398  		t.Fatal(err)
	 399  	}
	 400  
	 401  	for i, tt := range testCases {
	 402  		d := &Dialer{DualStack: tt.dualstack, FallbackDelay: tt.delay}
	 403  
	 404  		startTime := time.Now()
	 405  		c, err := d.Dial("tcp", JoinHostPort("slow6loopback4", dss.port))
	 406  		elapsed := time.Now().Sub(startTime)
	 407  		if err == nil {
	 408  			c.Close()
	 409  		} else if tt.dualstack {
	 410  			t.Error(err)
	 411  		}
	 412  		expectMin := tt.expectElapsed - 1*time.Millisecond
	 413  		expectMax := tt.expectElapsed + 95*time.Millisecond
	 414  		if elapsed < expectMin {
	 415  			t.Errorf("#%d: got %v; want >= %v", i, elapsed, expectMin)
	 416  		}
	 417  		if elapsed > expectMax {
	 418  			t.Errorf("#%d: got %v; want <= %v", i, elapsed, expectMax)
	 419  		}
	 420  	}
	 421  }
	 422  
	 423  func TestDialParallelSpuriousConnection(t *testing.T) {
	 424  	if !supportsIPv4() || !supportsIPv6() {
	 425  		t.Skip("both IPv4 and IPv6 are required")
	 426  	}
	 427  
	 428  	var readDeadline time.Time
	 429  	if td, ok := t.Deadline(); ok {
	 430  		const arbitraryCleanupMargin = 1 * time.Second
	 431  		readDeadline = td.Add(-arbitraryCleanupMargin)
	 432  	} else {
	 433  		readDeadline = time.Now().Add(5 * time.Second)
	 434  	}
	 435  
	 436  	var wg sync.WaitGroup
	 437  	wg.Add(2)
	 438  	handler := func(dss *dualStackServer, ln Listener) {
	 439  		// Accept one connection per address.
	 440  		c, err := ln.Accept()
	 441  		if err != nil {
	 442  			t.Fatal(err)
	 443  		}
	 444  		// The client should close itself, without sending data.
	 445  		c.SetReadDeadline(readDeadline)
	 446  		var b [1]byte
	 447  		if _, err := c.Read(b[:]); err != io.EOF {
	 448  			t.Errorf("got %v; want %v", err, io.EOF)
	 449  		}
	 450  		c.Close()
	 451  		wg.Done()
	 452  	}
	 453  	dss, err := newDualStackServer()
	 454  	if err != nil {
	 455  		t.Fatal(err)
	 456  	}
	 457  	defer dss.teardown()
	 458  	if err := dss.buildup(handler); err != nil {
	 459  		t.Fatal(err)
	 460  	}
	 461  
	 462  	const fallbackDelay = 100 * time.Millisecond
	 463  
	 464  	origTestHookDialTCP := testHookDialTCP
	 465  	defer func() { testHookDialTCP = origTestHookDialTCP }()
	 466  	testHookDialTCP = func(ctx context.Context, net string, laddr, raddr *TCPAddr) (*TCPConn, error) {
	 467  		// Sleep long enough for Happy Eyeballs to kick in, and inhibit cancellation.
	 468  		// This forces dialParallel to juggle two successful connections.
	 469  		time.Sleep(fallbackDelay * 2)
	 470  
	 471  		// Now ignore the provided context (which will be canceled) and use a
	 472  		// different one to make sure this completes with a valid connection,
	 473  		// which we hope to be closed below:
	 474  		sd := &sysDialer{network: net, address: raddr.String()}
	 475  		return sd.doDialTCP(context.Background(), laddr, raddr)
	 476  	}
	 477  
	 478  	d := Dialer{
	 479  		FallbackDelay: fallbackDelay,
	 480  	}
	 481  	sd := &sysDialer{
	 482  		Dialer:	d,
	 483  		network: "tcp",
	 484  		address: "?",
	 485  	}
	 486  
	 487  	makeAddr := func(ip string) addrList {
	 488  		addr, err := ResolveTCPAddr("tcp", JoinHostPort(ip, dss.port))
	 489  		if err != nil {
	 490  			t.Fatal(err)
	 491  		}
	 492  		return addrList{addr}
	 493  	}
	 494  
	 495  	// dialParallel returns one connection (and closes the other.)
	 496  	c, err := sd.dialParallel(context.Background(), makeAddr("127.0.0.1"), makeAddr("::1"))
	 497  	if err != nil {
	 498  		t.Fatal(err)
	 499  	}
	 500  	c.Close()
	 501  
	 502  	// The server should've seen both connections.
	 503  	wg.Wait()
	 504  }
	 505  
	 506  func TestDialerPartialDeadline(t *testing.T) {
	 507  	now := time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC)
	 508  	var testCases = []struct {
	 509  		now						time.Time
	 510  		deadline			 time.Time
	 511  		addrs					int
	 512  		expectDeadline time.Time
	 513  		expectErr			error
	 514  	}{
	 515  		// Regular division.
	 516  		{now, now.Add(12 * time.Second), 1, now.Add(12 * time.Second), nil},
	 517  		{now, now.Add(12 * time.Second), 2, now.Add(6 * time.Second), nil},
	 518  		{now, now.Add(12 * time.Second), 3, now.Add(4 * time.Second), nil},
	 519  		// Bump against the 2-second sane minimum.
	 520  		{now, now.Add(12 * time.Second), 999, now.Add(2 * time.Second), nil},
	 521  		// Total available is now below the sane minimum.
	 522  		{now, now.Add(1900 * time.Millisecond), 999, now.Add(1900 * time.Millisecond), nil},
	 523  		// Null deadline.
	 524  		{now, noDeadline, 1, noDeadline, nil},
	 525  		// Step the clock forward and cross the deadline.
	 526  		{now.Add(-1 * time.Millisecond), now, 1, now, nil},
	 527  		{now.Add(0 * time.Millisecond), now, 1, noDeadline, errTimeout},
	 528  		{now.Add(1 * time.Millisecond), now, 1, noDeadline, errTimeout},
	 529  	}
	 530  	for i, tt := range testCases {
	 531  		deadline, err := partialDeadline(tt.now, tt.deadline, tt.addrs)
	 532  		if err != tt.expectErr {
	 533  			t.Errorf("#%d: got %v; want %v", i, err, tt.expectErr)
	 534  		}
	 535  		if !deadline.Equal(tt.expectDeadline) {
	 536  			t.Errorf("#%d: got %v; want %v", i, deadline, tt.expectDeadline)
	 537  		}
	 538  	}
	 539  }
	 540  
	 541  func TestDialerLocalAddr(t *testing.T) {
	 542  	if !supportsIPv4() || !supportsIPv6() {
	 543  		t.Skip("both IPv4 and IPv6 are required")
	 544  	}
	 545  
	 546  	type test struct {
	 547  		network, raddr string
	 548  		laddr					Addr
	 549  		error
	 550  	}
	 551  	var tests = []test{
	 552  		{"tcp4", "127.0.0.1", nil, nil},
	 553  		{"tcp4", "127.0.0.1", &TCPAddr{}, nil},
	 554  		{"tcp4", "127.0.0.1", &TCPAddr{IP: ParseIP("0.0.0.0")}, nil},
	 555  		{"tcp4", "127.0.0.1", &TCPAddr{IP: ParseIP("0.0.0.0").To4()}, nil},
	 556  		{"tcp4", "127.0.0.1", &TCPAddr{IP: ParseIP("::")}, &AddrError{Err: "some error"}},
	 557  		{"tcp4", "127.0.0.1", &TCPAddr{IP: ParseIP("127.0.0.1").To4()}, nil},
	 558  		{"tcp4", "127.0.0.1", &TCPAddr{IP: ParseIP("127.0.0.1").To16()}, nil},
	 559  		{"tcp4", "127.0.0.1", &TCPAddr{IP: IPv6loopback}, errNoSuitableAddress},
	 560  		{"tcp4", "127.0.0.1", &UDPAddr{}, &AddrError{Err: "some error"}},
	 561  		{"tcp4", "127.0.0.1", &UnixAddr{}, &AddrError{Err: "some error"}},
	 562  
	 563  		{"tcp6", "::1", nil, nil},
	 564  		{"tcp6", "::1", &TCPAddr{}, nil},
	 565  		{"tcp6", "::1", &TCPAddr{IP: ParseIP("0.0.0.0")}, nil},
	 566  		{"tcp6", "::1", &TCPAddr{IP: ParseIP("0.0.0.0").To4()}, nil},
	 567  		{"tcp6", "::1", &TCPAddr{IP: ParseIP("::")}, nil},
	 568  		{"tcp6", "::1", &TCPAddr{IP: ParseIP("127.0.0.1").To4()}, errNoSuitableAddress},
	 569  		{"tcp6", "::1", &TCPAddr{IP: ParseIP("127.0.0.1").To16()}, errNoSuitableAddress},
	 570  		{"tcp6", "::1", &TCPAddr{IP: IPv6loopback}, nil},
	 571  		{"tcp6", "::1", &UDPAddr{}, &AddrError{Err: "some error"}},
	 572  		{"tcp6", "::1", &UnixAddr{}, &AddrError{Err: "some error"}},
	 573  
	 574  		{"tcp", "127.0.0.1", nil, nil},
	 575  		{"tcp", "127.0.0.1", &TCPAddr{}, nil},
	 576  		{"tcp", "127.0.0.1", &TCPAddr{IP: ParseIP("0.0.0.0")}, nil},
	 577  		{"tcp", "127.0.0.1", &TCPAddr{IP: ParseIP("0.0.0.0").To4()}, nil},
	 578  		{"tcp", "127.0.0.1", &TCPAddr{IP: ParseIP("127.0.0.1").To4()}, nil},
	 579  		{"tcp", "127.0.0.1", &TCPAddr{IP: ParseIP("127.0.0.1").To16()}, nil},
	 580  		{"tcp", "127.0.0.1", &TCPAddr{IP: IPv6loopback}, errNoSuitableAddress},
	 581  		{"tcp", "127.0.0.1", &UDPAddr{}, &AddrError{Err: "some error"}},
	 582  		{"tcp", "127.0.0.1", &UnixAddr{}, &AddrError{Err: "some error"}},
	 583  
	 584  		{"tcp", "::1", nil, nil},
	 585  		{"tcp", "::1", &TCPAddr{}, nil},
	 586  		{"tcp", "::1", &TCPAddr{IP: ParseIP("0.0.0.0")}, nil},
	 587  		{"tcp", "::1", &TCPAddr{IP: ParseIP("0.0.0.0").To4()}, nil},
	 588  		{"tcp", "::1", &TCPAddr{IP: ParseIP("::")}, nil},
	 589  		{"tcp", "::1", &TCPAddr{IP: ParseIP("127.0.0.1").To4()}, errNoSuitableAddress},
	 590  		{"tcp", "::1", &TCPAddr{IP: ParseIP("127.0.0.1").To16()}, errNoSuitableAddress},
	 591  		{"tcp", "::1", &TCPAddr{IP: IPv6loopback}, nil},
	 592  		{"tcp", "::1", &UDPAddr{}, &AddrError{Err: "some error"}},
	 593  		{"tcp", "::1", &UnixAddr{}, &AddrError{Err: "some error"}},
	 594  	}
	 595  
	 596  	if supportsIPv4map() {
	 597  		tests = append(tests, test{
	 598  			"tcp", "127.0.0.1", &TCPAddr{IP: ParseIP("::")}, nil,
	 599  		})
	 600  	} else {
	 601  		tests = append(tests, test{
	 602  			"tcp", "127.0.0.1", &TCPAddr{IP: ParseIP("::")}, &AddrError{Err: "some error"},
	 603  		})
	 604  	}
	 605  
	 606  	origTestHookLookupIP := testHookLookupIP
	 607  	defer func() { testHookLookupIP = origTestHookLookupIP }()
	 608  	testHookLookupIP = lookupLocalhost
	 609  	handler := func(ls *localServer, ln Listener) {
	 610  		for {
	 611  			c, err := ln.Accept()
	 612  			if err != nil {
	 613  				return
	 614  			}
	 615  			c.Close()
	 616  		}
	 617  	}
	 618  	var err error
	 619  	var lss [2]*localServer
	 620  	for i, network := range []string{"tcp4", "tcp6"} {
	 621  		lss[i], err = newLocalServer(network)
	 622  		if err != nil {
	 623  			t.Fatal(err)
	 624  		}
	 625  		defer lss[i].teardown()
	 626  		if err := lss[i].buildup(handler); err != nil {
	 627  			t.Fatal(err)
	 628  		}
	 629  	}
	 630  
	 631  	for _, tt := range tests {
	 632  		d := &Dialer{LocalAddr: tt.laddr}
	 633  		var addr string
	 634  		ip := ParseIP(tt.raddr)
	 635  		if ip.To4() != nil {
	 636  			addr = lss[0].Listener.Addr().String()
	 637  		}
	 638  		if ip.To16() != nil && ip.To4() == nil {
	 639  			addr = lss[1].Listener.Addr().String()
	 640  		}
	 641  		c, err := d.Dial(tt.network, addr)
	 642  		if err == nil && tt.error != nil || err != nil && tt.error == nil {
	 643  			t.Errorf("%s %v->%s: got %v; want %v", tt.network, tt.laddr, tt.raddr, err, tt.error)
	 644  		}
	 645  		if err != nil {
	 646  			if perr := parseDialError(err); perr != nil {
	 647  				t.Error(perr)
	 648  			}
	 649  			continue
	 650  		}
	 651  		c.Close()
	 652  	}
	 653  }
	 654  
	 655  func TestDialerDualStack(t *testing.T) {
	 656  	testenv.SkipFlaky(t, 13324)
	 657  
	 658  	if !supportsIPv4() || !supportsIPv6() {
	 659  		t.Skip("both IPv4 and IPv6 are required")
	 660  	}
	 661  
	 662  	closedPortDelay := dialClosedPort(t)
	 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(time.Duration) {} }()
	 725  
	 726  	tests := []struct {
	 727  		ka			 time.Duration
	 728  		expected time.Duration
	 729  	}{
	 730  		{-1, -1},
	 731  		{0, 15 * time.Second},
	 732  		{5 * time.Second, 5 * time.Second},
	 733  		{30 * time.Second, 30 * time.Second},
	 734  	}
	 735  
	 736  	for _, test := range tests {
	 737  		var got time.Duration = -1
	 738  		testHookSetKeepAlive = func(d time.Duration) { got = d }
	 739  		d := Dialer{KeepAlive: test.ka}
	 740  		c, err := d.Dial("tcp", ls.Listener.Addr().String())
	 741  		if err != nil {
	 742  			t.Fatal(err)
	 743  		}
	 744  		c.Close()
	 745  		if got != test.expected {
	 746  			t.Errorf("Dialer.KeepAlive = %v: SetKeepAlive set to %v, want %v", d.KeepAlive, got, test.expected)
	 747  		}
	 748  	}
	 749  }
	 750  
	 751  func TestDialCancel(t *testing.T) {
	 752  	mustHaveExternalNetwork(t)
	 753  
	 754  	if strings.HasPrefix(testenv.Builder(), "darwin-arm64") {
	 755  		// The darwin-arm64 machines run in an environment that's not
	 756  		// compatible with this test.
	 757  		t.Skipf("builder %q gives no route to host for 198.18.0.0", testenv.Builder())
	 758  	}
	 759  
	 760  	blackholeIPPort := JoinHostPort(slowDst4, "1234")
	 761  	if !supportsIPv4() {
	 762  		blackholeIPPort = JoinHostPort(slowDst6, "1234")
	 763  	}
	 764  
	 765  	ticker := time.NewTicker(10 * time.Millisecond)
	 766  	defer ticker.Stop()
	 767  
	 768  	const cancelTick = 5 // the timer tick we cancel the dial at
	 769  	const timeoutTick = 100
	 770  
	 771  	var d Dialer
	 772  	cancel := make(chan struct{})
	 773  	d.Cancel = cancel
	 774  	errc := make(chan error, 1)
	 775  	connc := make(chan Conn, 1)
	 776  	go func() {
	 777  		if c, err := d.Dial("tcp", blackholeIPPort); err != nil {
	 778  			errc <- err
	 779  		} else {
	 780  			connc <- c
	 781  		}
	 782  	}()
	 783  	ticks := 0
	 784  	for {
	 785  		select {
	 786  		case <-ticker.C:
	 787  			ticks++
	 788  			if ticks == cancelTick {
	 789  				close(cancel)
	 790  			}
	 791  			if ticks == timeoutTick {
	 792  				t.Fatal("timeout waiting for dial to fail")
	 793  			}
	 794  		case c := <-connc:
	 795  			c.Close()
	 796  			t.Fatal("unexpected successful connection")
	 797  		case err := <-errc:
	 798  			if perr := parseDialError(err); perr != nil {
	 799  				t.Error(perr)
	 800  			}
	 801  			if ticks < cancelTick {
	 802  				// Using strings.Contains is ugly but
	 803  				// may work on plan9 and windows.
	 804  				if strings.Contains(err.Error(), "connection refused") {
	 805  					t.Skipf("connection to %v failed fast with %v", blackholeIPPort, err)
	 806  				}
	 807  				t.Fatalf("dial error after %d ticks (%d before cancel sent): %v",
	 808  					ticks, cancelTick-ticks, err)
	 809  			}
	 810  			if oe, ok := err.(*OpError); !ok || oe.Err != errCanceled {
	 811  				t.Fatalf("dial error = %v (%T); want OpError with Err == errCanceled", err, err)
	 812  			}
	 813  			return // success.
	 814  		}
	 815  	}
	 816  }
	 817  
	 818  func TestCancelAfterDial(t *testing.T) {
	 819  	if testing.Short() {
	 820  		t.Skip("avoiding time.Sleep")
	 821  	}
	 822  
	 823  	ln, err := newLocalListener("tcp")
	 824  	if err != nil {
	 825  		t.Fatal(err)
	 826  	}
	 827  
	 828  	var wg sync.WaitGroup
	 829  	wg.Add(1)
	 830  	defer func() {
	 831  		ln.Close()
	 832  		wg.Wait()
	 833  	}()
	 834  
	 835  	// Echo back the first line of each incoming connection.
	 836  	go func() {
	 837  		for {
	 838  			c, err := ln.Accept()
	 839  			if err != nil {
	 840  				break
	 841  			}
	 842  			rb := bufio.NewReader(c)
	 843  			line, err := rb.ReadString('\n')
	 844  			if err != nil {
	 845  				t.Error(err)
	 846  				c.Close()
	 847  				continue
	 848  			}
	 849  			if _, err := c.Write([]byte(line)); err != nil {
	 850  				t.Error(err)
	 851  			}
	 852  			c.Close()
	 853  		}
	 854  		wg.Done()
	 855  	}()
	 856  
	 857  	try := func() {
	 858  		cancel := make(chan struct{})
	 859  		d := &Dialer{Cancel: cancel}
	 860  		c, err := d.Dial("tcp", ln.Addr().String())
	 861  
	 862  		// Immediately after dialing, request cancellation and sleep.
	 863  		// Before Issue 15078 was fixed, this would cause subsequent operations
	 864  		// to fail with an i/o timeout roughly 50% of the time.
	 865  		close(cancel)
	 866  		time.Sleep(10 * time.Millisecond)
	 867  
	 868  		if err != nil {
	 869  			t.Fatal(err)
	 870  		}
	 871  		defer c.Close()
	 872  
	 873  		// Send some data to confirm that the connection is still alive.
	 874  		const message = "echo!\n"
	 875  		if _, err := c.Write([]byte(message)); err != nil {
	 876  			t.Fatal(err)
	 877  		}
	 878  
	 879  		// The server should echo the line, and close the connection.
	 880  		rb := bufio.NewReader(c)
	 881  		line, err := rb.ReadString('\n')
	 882  		if err != nil {
	 883  			t.Fatal(err)
	 884  		}
	 885  		if line != message {
	 886  			t.Errorf("got %q; want %q", line, message)
	 887  		}
	 888  		if _, err := rb.ReadByte(); err != io.EOF {
	 889  			t.Errorf("got %v; want %v", err, io.EOF)
	 890  		}
	 891  	}
	 892  
	 893  	// This bug manifested about 50% of the time, so try it a few times.
	 894  	for i := 0; i < 10; i++ {
	 895  		try()
	 896  	}
	 897  }
	 898  
	 899  // Issue 18806: it should always be possible to net.Dial a
	 900  // net.Listener().Addr().String when the listen address was ":n", even
	 901  // if the machine has halfway configured IPv6 such that it can bind on
	 902  // "::" not connect back to that same address.
	 903  func TestDialListenerAddr(t *testing.T) {
	 904  	mustHaveExternalNetwork(t)
	 905  	ln, err := Listen("tcp", ":0")
	 906  	if err != nil {
	 907  		t.Fatal(err)
	 908  	}
	 909  	defer ln.Close()
	 910  	addr := ln.Addr().String()
	 911  	c, err := Dial("tcp", addr)
	 912  	if err != nil {
	 913  		t.Fatalf("for addr %q, dial error: %v", addr, err)
	 914  	}
	 915  	c.Close()
	 916  }
	 917  
	 918  func TestDialerControl(t *testing.T) {
	 919  	switch runtime.GOOS {
	 920  	case "plan9":
	 921  		t.Skipf("not supported on %s", runtime.GOOS)
	 922  	}
	 923  
	 924  	t.Run("StreamDial", func(t *testing.T) {
	 925  		for _, network := range []string{"tcp", "tcp4", "tcp6", "unix", "unixpacket"} {
	 926  			if !testableNetwork(network) {
	 927  				continue
	 928  			}
	 929  			ln, err := newLocalListener(network)
	 930  			if err != nil {
	 931  				t.Error(err)
	 932  				continue
	 933  			}
	 934  			defer ln.Close()
	 935  			d := Dialer{Control: controlOnConnSetup}
	 936  			c, err := d.Dial(network, ln.Addr().String())
	 937  			if err != nil {
	 938  				t.Error(err)
	 939  				continue
	 940  			}
	 941  			c.Close()
	 942  		}
	 943  	})
	 944  	t.Run("PacketDial", func(t *testing.T) {
	 945  		for _, network := range []string{"udp", "udp4", "udp6", "unixgram"} {
	 946  			if !testableNetwork(network) {
	 947  				continue
	 948  			}
	 949  			c1, err := newLocalPacketListener(network)
	 950  			if err != nil {
	 951  				t.Error(err)
	 952  				continue
	 953  			}
	 954  			if network == "unixgram" {
	 955  				defer os.Remove(c1.LocalAddr().String())
	 956  			}
	 957  			defer c1.Close()
	 958  			d := Dialer{Control: controlOnConnSetup}
	 959  			c2, err := d.Dial(network, c1.LocalAddr().String())
	 960  			if err != nil {
	 961  				t.Error(err)
	 962  				continue
	 963  			}
	 964  			c2.Close()
	 965  		}
	 966  	})
	 967  }
	 968  
	 969  // mustHaveExternalNetwork is like testenv.MustHaveExternalNetwork
	 970  // except that it won't skip testing on non-mobile builders.
	 971  func mustHaveExternalNetwork(t *testing.T) {
	 972  	t.Helper()
	 973  	mobile := runtime.GOOS == "android" || runtime.GOOS == "ios"
	 974  	if testenv.Builder() == "" || mobile {
	 975  		testenv.MustHaveExternalNetwork(t)
	 976  	}
	 977  }
	 978  
	 979  type contextWithNonZeroDeadline struct {
	 980  	context.Context
	 981  }
	 982  
	 983  func (contextWithNonZeroDeadline) Deadline() (time.Time, bool) {
	 984  	// Return non-zero time.Time value with false indicating that no deadline is set.
	 985  	return time.Unix(0, 0), false
	 986  }
	 987  
	 988  func TestDialWithNonZeroDeadline(t *testing.T) {
	 989  	ln, err := newLocalListener("tcp")
	 990  	if err != nil {
	 991  		t.Fatal(err)
	 992  	}
	 993  	defer ln.Close()
	 994  	_, port, err := SplitHostPort(ln.Addr().String())
	 995  	if err != nil {
	 996  		t.Fatal(err)
	 997  	}
	 998  
	 999  	ctx := contextWithNonZeroDeadline{Context: context.Background()}
	1000  	var dialer Dialer
	1001  	c, err := dialer.DialContext(ctx, "tcp", JoinHostPort("", port))
	1002  	if err != nil {
	1003  		t.Fatal(err)
	1004  	}
	1005  	c.Close()
	1006  }
	1007  

View as plain text