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