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