runtime: correct facilities names in s390 CPU support
[gcc.git] / libgo / go / net / dial_test.go
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
7 package net
8
9 import (
10 "bufio"
11 "context"
12 "internal/poll"
13 "internal/testenv"
14 "io"
15 "os"
16 "runtime"
17 "sync"
18 "testing"
19 "time"
20 )
21
22 var prohibitionaryDialArgTests = []struct {
23 network string
24 address string
25 }{
26 {"tcp6", "127.0.0.1"},
27 {"tcp6", "::ffff:127.0.0.1"},
28 }
29
30 func 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
61 func 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
78 func 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.
139 const (
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.
147 func 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
157 func 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
191 func 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
349 func 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
362 func 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
430 func 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 cancellation.
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
505 func 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
540 func 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
660 func 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
714 func 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
759 func 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
824 func 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 cancellation 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.
909 func 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
924 func 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-mobile builders.
977 func mustHaveExternalNetwork(t *testing.T) {
978 t.Helper()
979 mobile := runtime.GOOS == "android" || runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64")
980 if testenv.Builder() == "" || mobile {
981 testenv.MustHaveExternalNetwork(t)
982 }
983 }