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.
22 var prohibitionaryDialArgTests
= []struct {
26 {"tcp6", "127.0.0.1"},
27 {"tcp6", "::ffff:127.0.0.1"},
30 func TestProhibitionaryDialArg(t
*testing
.T
) {
31 testenv
.MustHaveExternalNetwork(t
)
35 t
.Skipf("not supported on %s", runtime
.GOOS
)
37 if !supportsIPv4map() {
38 t
.Skip("mapping ipv4 address inside ipv6 address not supported")
41 ln
, err
:= Listen("tcp", "[::]:0")
47 _
, port
, err
:= SplitHostPort(ln
.Addr().String())
52 for i
, tt
:= range prohibitionaryDialArgTests
{
53 c
, err
:= Dial(tt
.network
, JoinHostPort(tt
.address
, port
))
56 t
.Errorf("#%d: %v", i
, err
)
61 func TestDialLocal(t
*testing
.T
) {
62 ln
, err
:= newLocalListener("tcp")
67 _
, port
, err
:= SplitHostPort(ln
.Addr().String())
71 c
, err
:= Dial("tcp", JoinHostPort("", port
))
78 func TestDialerDualStackFDLeak(t
*testing
.T
) {
81 t
.Skipf("%s does not have full support of socktest", runtime
.GOOS
)
83 t
.Skipf("not implemented a way to cancel dial racers in TCP SYN-SENT state on %s", runtime
.GOOS
)
85 testenv
.SkipFlaky(t
, 15157)
87 if !supportsIPv4() ||
!supportsIPv6() {
88 t
.Skip("both IPv4 and IPv6 are required")
91 before
:= sw
.Sockets()
92 origTestHookLookupIP
:= testHookLookupIP
93 defer func() { testHookLookupIP
= origTestHookLookupIP
}()
94 testHookLookupIP
= lookupLocalhost
95 handler
:= func(dss
*dualStackServer
, ln Listener
) {
104 dss
, err
:= newDualStackServer()
108 if err
:= dss
.buildup(handler
); err
!= nil {
114 var wg sync
.WaitGroup
116 d
:= &Dialer
{DualStack
: true, Timeout
: 5 * time
.Second
}
117 for i
:= 0; i
< N
; i
++ {
120 c
, err
:= d
.Dial("tcp", JoinHostPort("localhost", dss
.port
))
130 after
:= sw
.Sockets()
131 if len(after
) != len(before
) {
132 t
.Errorf("got %d; want %d", len(after
), len(before
))
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.
140 slowDst4
= "198.18.0.254"
141 slowDst6
= "2001:2::254"
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.
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
166 expected
= 95 * time
.Millisecond
169 l
, err
:= Listen("tcp", "127.0.0.1:0")
171 return 999 * time
.Hour
, expected
173 addr
:= l
.Addr().String()
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.
179 startTime
:= time
.Now()
180 c
, err
:= Dial("tcp", addr
)
184 elapsed
:= time
.Now().Sub(startTime
)
186 return elapsed
, expected
191 func TestDialParallel(t
*testing
.T
) {
192 testenv
.MustHaveExternalNetwork(t
)
194 if !supportsIPv4() ||
!supportsIPv6() {
195 t
.Skip("both IPv4 and IPv6 are required")
198 closedPortDelay
, expectClosedPortDelay
:= dialClosedPort()
199 if closedPortDelay
> expectClosedPortDelay
{
200 t
.Errorf("got %v; want <= %v", closedPortDelay
, expectClosedPortDelay
)
203 const instant time
.Duration
= 0
204 const fallbackDelay
= 200 * time
.Millisecond
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
213 closedPortOrFallbackDelay
= fallbackDelay
216 origTestHookDialTCP
:= testHookDialTCP
217 defer func() { testHookDialTCP
= origTestHookDialTCP
}()
218 testHookDialTCP
= slowDialTCP
220 nCopies
:= func(s
string, n
int) []string {
221 out
:= make([]string, n
)
222 for i
:= 0; i
< n
; i
++ {
228 var testCases
= []struct {
231 teardownNetwork
string
233 expectElapsed time
.Duration
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
},
258 handler
:= func(dss
*dualStackServer
, ln Listener
) {
260 c
, err
:= ln
.Accept()
268 // Convert a list of IP strings into TCPAddrs.
269 makeAddrs
:= func(ips
[]string, port
string) addrList
{
271 for _
, ip
:= range ips
{
272 addr
, err
:= ResolveTCPAddr("tcp", JoinHostPort(ip
, port
))
276 out
= append(out
, addr
)
281 for i
, tt
:= range testCases
{
282 dss
, err
:= newDualStackServer()
287 if err
:= dss
.buildup(handler
); err
!= nil {
290 if tt
.teardownNetwork
!= "" {
291 // Destroy one of the listening sockets, creating an unreachable port.
292 dss
.teardownNetwork(tt
.teardownNetwork
)
295 primaries
:= makeAddrs(tt
.primaries
, dss
.port
)
296 fallbacks
:= makeAddrs(tt
.fallbacks
, dss
.port
)
298 FallbackDelay
: fallbackDelay
,
300 startTime
:= time
.Now()
306 c
, err
:= sd
.dialParallel(context
.Background(), primaries
, fallbacks
)
307 elapsed
:= time
.Since(startTime
)
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
)
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
)
327 // Repeat each case, ensuring that it can be canceled quickly.
328 ctx
, cancel
:= context
.WithCancel(context
.Background())
329 var wg sync
.WaitGroup
332 time
.Sleep(5 * time
.Millisecond
)
336 startTime
= time
.Now()
337 c
, err
= sd
.dialParallel(ctx
, primaries
, fallbacks
)
341 elapsed
= time
.Now().Sub(startTime
)
342 if elapsed
> 100*time
.Millisecond
{
343 t
.Errorf("#%d (cancel): got %v; want <= 100ms", i
, elapsed
)
349 func lookupSlowFast(ctx context
.Context
, fn
func(context
.Context
, string) ([]IPAddr
, error
), host
string) ([]IPAddr
, error
) {
351 case "slow6loopback4":
352 // Returns a slow IPv6 address, and a local IPv4 address.
354 {IP
: ParseIP(slowDst6
)},
355 {IP
: ParseIP("127.0.0.1")},
362 func TestDialerFallbackDelay(t
*testing
.T
) {
363 testenv
.MustHaveExternalNetwork(t
)
365 if !supportsIPv4() ||
!supportsIPv6() {
366 t
.Skip("both IPv4 and IPv6 are required")
369 origTestHookLookupIP
:= testHookLookupIP
370 defer func() { testHookLookupIP
= origTestHookLookupIP
}()
371 testHookLookupIP
= lookupSlowFast
373 origTestHookDialTCP
:= testHookDialTCP
374 defer func() { testHookDialTCP
= origTestHookDialTCP
}()
375 testHookDialTCP
= slowDialTCP
377 var testCases
= []struct {
380 expectElapsed time
.Duration
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
},
390 handler
:= func(dss
*dualStackServer
, ln Listener
) {
392 c
, err
:= ln
.Accept()
399 dss
, err
:= newDualStackServer()
404 if err
:= dss
.buildup(handler
); err
!= nil {
408 for i
, tt
:= range testCases
{
409 d
:= &Dialer
{DualStack
: tt
.dualstack
, FallbackDelay
: tt
.delay
}
411 startTime
:= time
.Now()
412 c
, err
:= d
.Dial("tcp", JoinHostPort("slow6loopback4", dss
.port
))
413 elapsed
:= time
.Now().Sub(startTime
)
416 } else if tt
.dualstack
{
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
)
424 if !(elapsed
<= expectMax
) {
425 t
.Errorf("#%d: got %v; want <= %v", i
, elapsed
, expectMax
)
430 func TestDialParallelSpuriousConnection(t
*testing
.T
) {
431 if !supportsIPv4() ||
!supportsIPv6() {
432 t
.Skip("both IPv4 and IPv6 are required")
435 var wg sync
.WaitGroup
437 handler
:= func(dss
*dualStackServer
, ln Listener
) {
438 // Accept one connection per address.
439 c
, err
:= ln
.Accept()
443 // The client should close itself, without sending data.
444 c
.SetReadDeadline(time
.Now().Add(1 * time
.Second
))
446 if _
, err
:= c
.Read(b
[:]); err
!= io
.EOF
{
447 t
.Errorf("got %v; want %v", err
, io
.EOF
)
452 dss
, err
:= newDualStackServer()
457 if err
:= dss
.buildup(handler
); err
!= nil {
461 const fallbackDelay
= 100 * time
.Millisecond
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)
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
)
478 FallbackDelay
: fallbackDelay
,
486 makeAddr
:= func(ip
string) addrList
{
487 addr
, err
:= ResolveTCPAddr("tcp", JoinHostPort(ip
, dss
.port
))
491 return addrList
{addr
}
494 // dialParallel returns one connection (and closes the other.)
495 c
, err
:= sd
.dialParallel(context
.Background(), makeAddr("127.0.0.1"), makeAddr("::1"))
501 // The server should've seen both connections.
505 func TestDialerPartialDeadline(t
*testing
.T
) {
506 now
:= time
.Date(2000, time
.January
, 1, 0, 0, 0, 0, time
.UTC
)
507 var testCases
= []struct {
511 expectDeadline time
.Time
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},
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
},
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
)
534 if !deadline
.Equal(tt
.expectDeadline
) {
535 t
.Errorf("#%d: got %v; want %v", i
, deadline
, tt
.expectDeadline
)
540 func TestDialerLocalAddr(t
*testing
.T
) {
541 if !supportsIPv4() ||
!supportsIPv6() {
542 t
.Skip("both IPv4 and IPv6 are required")
546 network
, raddr
string
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"}},
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"}},
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"}},
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"}},
595 if supportsIPv4map() {
596 tests
= append(tests
, test
{
597 "tcp", "127.0.0.1", &TCPAddr
{IP
: ParseIP("::")}, nil,
600 tests
= append(tests
, test
{
601 "tcp", "127.0.0.1", &TCPAddr
{IP
: ParseIP("::")}, &AddrError
{Err
: "some error"},
605 origTestHookLookupIP
:= testHookLookupIP
606 defer func() { testHookLookupIP
= origTestHookLookupIP
}()
607 testHookLookupIP
= lookupLocalhost
608 handler
:= func(ls
*localServer
, ln Listener
) {
610 c
, err
:= ln
.Accept()
618 var lss
[2]*localServer
619 for i
, network
:= range []string{"tcp4", "tcp6"} {
620 lss
[i
], err
= newLocalServer(network
)
624 defer lss
[i
].teardown()
625 if err
:= lss
[i
].buildup(handler
); err
!= nil {
630 for _
, tt
:= range tests
{
631 d
:= &Dialer
{LocalAddr
: tt
.laddr
}
633 ip
:= ParseIP(tt
.raddr
)
635 addr
= lss
[0].Listener
.Addr().String()
637 if ip
.To16() != nil && ip
.To4() == nil {
638 addr
= lss
[1].Listener
.Addr().String()
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")
647 t
.Errorf("%s %v->%s: got %v; want %v", tt
.network
, tt
.laddr
, tt
.raddr
, err
, tt
.error
)
651 if perr
:= parseDialError(err
); perr
!= nil {
660 func TestDialerDualStack(t
*testing
.T
) {
661 testenv
.SkipFlaky(t
, 13324)
663 if !supportsIPv4() ||
!supportsIPv6() {
664 t
.Skip("both IPv4 and IPv6 are required")
667 closedPortDelay
, expectClosedPortDelay
:= dialClosedPort()
668 if closedPortDelay
> expectClosedPortDelay
{
669 t
.Errorf("got %v; want <= %v", closedPortDelay
, expectClosedPortDelay
)
672 origTestHookLookupIP
:= testHookLookupIP
673 defer func() { testHookLookupIP
= origTestHookLookupIP
}()
674 testHookLookupIP
= lookupLocalhost
675 handler
:= func(dss
*dualStackServer
, ln Listener
) {
677 c
, err
:= ln
.Accept()
685 var timeout
= 150*time
.Millisecond
+ closedPortDelay
686 for _
, dualstack
:= range []bool{false, true} {
687 dss
, err
:= newDualStackServer()
692 if err
:= dss
.buildup(handler
); err
!= nil {
696 d
:= &Dialer
{DualStack
: dualstack
, Timeout
: timeout
}
698 c
, err
:= d
.Dial("tcp", JoinHostPort("localhost", dss
.port
))
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")
714 func TestDialerKeepAlive(t
*testing
.T
) {
715 handler
:= func(ls
*localServer
, ln Listener
) {
717 c
, err
:= ln
.Accept()
724 ls
, err
:= newLocalServer("tcp")
729 if err
:= ls
.buildup(handler
); err
!= nil {
732 defer func() { testHookSetKeepAlive
= func() {} }()
734 for _
, keepAlive
:= range []bool{false, true} {
736 testHookSetKeepAlive
= func() { got
= true }
739 d
.KeepAlive
= 30 * time
.Second
741 c
, err
:= d
.Dial("tcp", ls
.Listener
.Addr().String())
746 if got
!= keepAlive
{
747 t
.Errorf("Dialer.KeepAlive = %v: SetKeepAlive called = %v, want %v", d
.KeepAlive
, got
, !got
)
752 func TestDialCancel(t
*testing
.T
) {
753 switch testenv
.Builder() {
754 case "linux-arm64-buildlet":
755 t
.Skip("skipping on linux-arm64-buildlet; incompatible network config? issue 15191")
757 mustHaveExternalNetwork(t
)
759 if runtime
.GOOS
== "nacl" {
760 // nacl doesn't have external network access.
761 t
.Skipf("skipping on %s", runtime
.GOOS
)
764 blackholeIPPort
:= JoinHostPort(slowDst4
, "1234")
766 blackholeIPPort
= JoinHostPort(slowDst6
, "1234")
769 ticker
:= time
.NewTicker(10 * time
.Millisecond
)
772 const cancelTick
= 5 // the timer tick we cancel the dial at
773 const timeoutTick
= 100
776 cancel
:= make(chan struct{})
778 errc
:= make(chan error
, 1)
779 connc
:= make(chan Conn
, 1)
781 if c
, err
:= d
.Dial("tcp", blackholeIPPort
); err
!= nil {
792 if ticks
== cancelTick
{
795 if ticks
== timeoutTick
{
796 t
.Fatal("timeout waiting for dial to fail")
800 t
.Fatal("unexpected successful connection")
802 if perr
:= parseDialError(err
); perr
!= nil {
805 if ticks
< cancelTick
{
806 t
.Fatalf("dial error after %d ticks (%d before cancel sent): %v",
807 ticks
, cancelTick
-ticks
, err
)
809 if oe
, ok
:= err
.(*OpError
); !ok || oe
.Err
!= errCanceled
{
810 t
.Fatalf("dial error = %v (%T); want OpError with Err == errCanceled", err
, err
)
817 func TestCancelAfterDial(t
*testing
.T
) {
819 t
.Skip("avoiding time.Sleep")
822 ln
, err
:= newLocalListener("tcp")
827 var wg sync
.WaitGroup
834 // Echo back the first line of each incoming connection.
837 c
, err
:= ln
.Accept()
841 rb
:= bufio
.NewReader(c
)
842 line
, err
:= rb
.ReadString('\n')
848 if _
, err
:= c
.Write([]byte(line
)); err
!= nil {
857 cancel
:= make(chan struct{})
858 d
:= &Dialer
{Cancel
: cancel
}
859 c
, err
:= d
.Dial("tcp", ln
.Addr().String())
861 // Immediately after dialing, request cancelation and sleep.
862 // Before Issue 15078 was fixed, this would cause subsequent operations
863 // to fail with an i/o timeout roughly 50% of the time.
865 time
.Sleep(10 * time
.Millisecond
)
872 // Send some data to confirm that the connection is still alive.
873 const message
= "echo!\n"
874 if _
, err
:= c
.Write([]byte(message
)); err
!= nil {
878 // The server should echo the line, and close the connection.
879 rb
:= bufio
.NewReader(c
)
880 line
, err
:= rb
.ReadString('\n')
885 t
.Errorf("got %q; want %q", line
, message
)
887 if _
, err
:= rb
.ReadByte(); err
!= io
.EOF
{
888 t
.Errorf("got %v; want %v", err
, io
.EOF
)
892 // This bug manifested about 50% of the time, so try it a few times.
893 for i
:= 0; i
< 10; i
++ {
898 // Issue 18806: it should always be possible to net.Dial a
899 // net.Listener().Addr().String when the listen address was ":n", even
900 // if the machine has halfway configured IPv6 such that it can bind on
901 // "::" not connect back to that same address.
902 func TestDialListenerAddr(t
*testing
.T
) {
903 mustHaveExternalNetwork(t
)
904 ln
, err
:= Listen("tcp", ":0")
909 addr
:= ln
.Addr().String()
910 c
, err
:= Dial("tcp", addr
)
912 t
.Fatalf("for addr %q, dial error: %v", addr
, err
)
917 func TestDialerControl(t
*testing
.T
) {
918 switch runtime
.GOOS
{
919 case "nacl", "plan9":
920 t
.Skipf("not supported on %s", runtime
.GOOS
)
923 t
.Run("StreamDial", func(t
*testing
.T
) {
924 for _
, network
:= range []string{"tcp", "tcp4", "tcp6", "unix", "unixpacket"} {
925 if !testableNetwork(network
) {
928 ln
, err
:= newLocalListener(network
)
934 d
:= Dialer
{Control
: controlOnConnSetup
}
935 c
, err
:= d
.Dial(network
, ln
.Addr().String())
943 t
.Run("PacketDial", func(t
*testing
.T
) {
944 for _
, network
:= range []string{"udp", "udp4", "udp6", "unixgram"} {
945 if !testableNetwork(network
) {
948 c1
, err
:= newLocalPacketListener(network
)
953 if network
== "unixgram" {
954 defer os
.Remove(c1
.LocalAddr().String())
957 d
:= Dialer
{Control
: controlOnConnSetup
}
958 c2
, err
:= d
.Dial(network
, c1
.LocalAddr().String())
968 // mustHaveExternalNetwork is like testenv.MustHaveExternalNetwork
969 // except that it won't skip testing on non-iOS builders.
970 func mustHaveExternalNetwork(t
*testing
.T
) {
972 ios
:= runtime
.GOOS
== "darwin" && (runtime
.GOARCH
== "arm" || runtime
.GOARCH
== "arm64")
973 if testenv
.Builder() == "" || ios
{
974 testenv
.MustHaveExternalNetwork(t
)