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.
19 func newLocalListener(t
*testing
.T
) Listener
{
20 ln
, err
:= Listen("tcp", "127.0.0.1:0")
22 ln
, err
= Listen("tcp6", "[::1]:0")
30 func TestDialTimeout(t
*testing
.T
) {
31 origBacklog
:= listenerBacklog
33 listenerBacklog
= origBacklog
37 ln
:= newLocalListener(t
)
40 errc
:= make(chan error
)
42 numConns
:= listenerBacklog
+ 100
44 // TODO(bradfitz): It's hard to test this in a portable
45 // way. This is unfortunate, but works for now.
48 // The kernel will start accepting TCP connections before userspace
49 // gets a chance to not accept them, so fire off a bunch to fill up
50 // the kernel's backlog. Then we test we get a failure after that.
51 for i
:= 0; i
< numConns
; i
++ {
53 _
, err
:= DialTimeout("tcp", ln
.Addr().String(), 200*time
.Millisecond
)
57 case "darwin", "windows":
58 // At least OS X 10.7 seems to accept any number of
59 // connections, ignoring listen's backlog, so resort
60 // to connecting to a hopefully-dead 127/8 address.
63 // Use an IANA reserved port (49151) instead of 80, because
64 // on our 386 builder, this Dial succeeds, connecting
65 // to an IIS web server somewhere. The data center
66 // or VM or firewall must be stealing the TCP connection.
68 // IANA Service Name and Transport Protocol Port Number Registry
69 // <http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xml>
71 c
, err
:= DialTimeout("tcp", "127.0.71.111:49151", 200*time
.Millisecond
)
73 err
= fmt
.Errorf("unexpected: connected to %s!", c
.RemoteAddr())
80 // OpenBSD may have a reject route to 127/8 except 127.0.0.1/32
81 // by default. FreeBSD likely works, but is untested.
83 // The timeout never happens on Windows. Why? Issue 3016.
84 t
.Skipf("skipping test on %q; untested.", runtime
.GOOS
)
90 case <-time
.After(15 * time
.Second
):
95 if connected
== numConns
{
96 t
.Fatal("all connections connected; expected some to time out")
99 terr
, ok
:= err
.(timeout
)
101 t
.Fatalf("got error %q; want error with timeout interface", err
)
104 t
.Fatalf("got error %q; not a timeout", err
)
106 // Pass. We saw a timeout error.
113 func TestSelfConnect(t
*testing
.T
) {
114 if runtime
.GOOS
== "windows" {
115 // TODO(brainman): do not know why it hangs.
116 t
.Skip("skipping known-broken test on windows")
118 // Test that Dial does not honor self-connects.
119 // See the comment in DialTCP.
121 // Find a port that would be used as a local address.
122 l
, err
:= Listen("tcp", "127.0.0.1:0")
126 c
, err
:= Dial("tcp", l
.Addr().String())
130 addr
:= c
.LocalAddr().String()
134 // Try to connect to that address repeatedly.
139 switch runtime
.GOOS
{
140 case "darwin", "freebsd", "netbsd", "openbsd", "plan9", "solaris", "windows":
141 // Non-Linux systems take a long time to figure
142 // out that there is nothing listening on localhost.
145 for i
:= 0; i
< n
; i
++ {
146 c
, err
:= Dial("tcp", addr
)
149 t
.Errorf("#%d: Dial %q succeeded", i
, addr
)
154 var runErrorTest
= flag
.Bool("run_error_test", false, "let TestDialError check for dns errors")
156 type DialErrorTest
struct {
162 var dialErrorTests
= []DialErrorTest
{
164 "datakit", "mh/astro/r70",
165 "dial datakit mh/astro/r70: unknown network datakit",
168 "tcp", "127.0.0.1:☺",
169 "dial tcp 127.0.0.1:☺: unknown port tcp/☺",
172 "tcp", "no-such-name.google.com.:80",
173 "dial tcp no-such-name.google.com.:80: lookup no-such-name.google.com.( on .*)?: no (.*)",
176 "tcp", "no-such-name.no-such-top-level-domain.:80",
177 "dial tcp no-such-name.no-such-top-level-domain.:80: lookup no-such-name.no-such-top-level-domain.( on .*)?: no (.*)",
180 "tcp", "no-such-name:80",
181 `dial tcp no-such-name:80: lookup no-such-name\.(.*\.)?( on .*)?: no (.*)`,
184 "tcp", "mh/astro/r70:http",
185 "dial tcp mh/astro/r70:http: lookup mh/astro/r70: invalid domain name",
188 "unix", "/etc/file-not-found",
189 "dial unix /etc/file-not-found: no such file or directory",
193 "dial unix /etc/: (permission denied|socket operation on non-socket|connection refused)",
196 "unixpacket", "/etc/file-not-found",
197 "dial unixpacket /etc/file-not-found: no such file or directory",
200 "unixpacket", "/etc/",
201 "dial unixpacket /etc/: (permission denied|socket operation on non-socket|connection refused)",
205 var duplicateErrorPattern
= `dial (.*) dial (.*)`
207 func TestDialError(t
*testing
.T
) {
209 t
.Logf("test disabled; use -run_error_test to enable")
212 for i
, tt
:= range dialErrorTests
{
213 c
, err
:= Dial(tt
.Net
, tt
.Raddr
)
218 t
.Errorf("#%d: nil error, want match for %#q", i
, tt
.Pattern
)
222 match
, _
:= regexp
.MatchString(tt
.Pattern
, s
)
224 t
.Errorf("#%d: %q, want match for %#q", i
, s
, tt
.Pattern
)
226 match
, _
= regexp
.MatchString(duplicateErrorPattern
, s
)
228 t
.Errorf("#%d: %q, duplicate error return from Dial", i
, s
)
233 var invalidDialAndListenArgTests
= []struct {
238 {"foo", "bar", &OpError
{Op
: "dial", Net
: "foo", Addr
: nil, Err
: UnknownNetworkError("foo")}},
239 {"baz", "", &OpError
{Op
: "listen", Net
: "baz", Addr
: nil, Err
: UnknownNetworkError("baz")}},
240 {"tcp", "", &OpError
{Op
: "dial", Net
: "tcp", Addr
: nil, Err
: errMissingAddress
}},
243 func TestInvalidDialAndListenArgs(t
*testing
.T
) {
244 for _
, tt
:= range invalidDialAndListenArgTests
{
246 switch tt
.err
.(*OpError
).Op
{
248 _
, err
= Dial(tt
.net
, tt
.addr
)
250 _
, err
= Listen(tt
.net
, tt
.addr
)
252 if !reflect
.DeepEqual(tt
.err
, err
) {
253 t
.Fatalf("got %#v; expected %#v", err
, tt
.err
)
258 func TestDialTimeoutFDLeak(t
*testing
.T
) {
259 if runtime
.GOOS
!= "linux" {
260 // TODO(bradfitz): test on other platforms
261 t
.Skipf("skipping test on %q", runtime
.GOOS
)
264 ln
:= newLocalListener(t
)
267 type connErr
struct {
271 dials
:= listenerBacklog
+ 100
272 // used to be listenerBacklog + 5, but was found to be unreliable, issue 4384.
273 maxGoodConnect
:= listenerBacklog
+ runtime
.NumCPU()*10
274 resc
:= make(chan connErr
)
275 for i
:= 0; i
< dials
; i
++ {
277 conn
, err
:= DialTimeout("tcp", ln
.Addr().String(), 500*time
.Millisecond
)
278 resc
<- connErr
{conn
, err
}
284 var toClose
[]io
.Closer
285 for i
:= 0; i
< dials
; i
++ {
289 if ngood
> maxGoodConnect
{
290 t
.Errorf("%d good connects; expected at most %d", ngood
, maxGoodConnect
)
292 toClose
= append(toClose
, ce
.conn
)
297 firstErr
= err
.Error()
298 } else if err
.Error() != firstErr
{
299 t
.Fatalf("inconsistent error messages: first was %q, then later %q", firstErr
, err
)
302 for _
, c
:= range toClose
{
305 for i
:= 0; i
< 100; i
++ {
306 if got
:= numFD(); got
< dials
{
310 time
.Sleep(10 * time
.Millisecond
)
312 if got
:= numFD(); got
>= dials
{
313 t
.Errorf("num fds after %d timeouts = %d; want <%d", dials
, got
, dials
)
318 if runtime
.GOOS
== "linux" {
319 f
, err
:= os
.Open("/proc/self/fd")
324 names
, err
:= f
.Readdirnames(0)
330 // All tests using this should be skipped anyway, but:
331 panic("numFDs not implemented on " + runtime
.GOOS
)
334 var testPoller
= flag
.Bool("poller", false, "platform supports runtime-integrated poller")
336 // Assert that a failed Dial attempt does not leak
337 // runtime.PollDesc structures
338 func TestDialFailPDLeak(t
*testing
.T
) {
340 t
.Skip("test disabled; use -poller to enable")
345 var old runtime
.MemStats
// used by sysdelta
346 runtime
.ReadMemStats(&old
)
347 sysdelta
:= func() uint64 {
348 var new runtime
.MemStats
349 runtime
.ReadMemStats(&new)
350 delta
:= old
.Sys
- new.Sys
354 d
:= &Dialer
{Timeout
: time
.Nanosecond
} // don't bother TCP with handshaking
356 for i
:= 0; i
< loops
; i
++ {
357 for i
:= 0; i
< count
; i
++ {
358 conn
, err
:= d
.Dial("tcp", "127.0.0.1:1")
360 t
.Error("dial should not succeed")
365 if delta
:= sysdelta(); delta
> 0 {
368 // there are always some allocations on the first loop
370 t
.Error("detected possible memory leak in runtime")
376 func TestDialer(t
*testing
.T
) {
377 ln
, err
:= Listen("tcp4", "127.0.0.1:0")
379 t
.Fatalf("Listen failed: %v", err
)
382 ch
:= make(chan error
, 1)
385 c
, err
:= ln
.Accept()
387 ch
<- fmt
.Errorf("Accept failed: %v", err
)
394 laddr
, err
:= ResolveTCPAddr("tcp4", "127.0.0.1:0")
396 t
.Fatalf("ResolveTCPAddr failed: %v", err
)
398 d
:= &Dialer
{LocalAddr
: laddr
}
399 c
, err
:= d
.Dial("tcp4", ln
.Addr().String())
401 t
.Fatalf("Dial failed: %v", err
)
404 c
.Read(make([]byte, 1))