]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgo/go/net/dial_test.go
libgo: Update to current sources.
[thirdparty/gcc.git] / libgo / go / net / dial_test.go
CommitLineData
df4aa89a
ILT
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 (
593f74bb 8 "flag"
456fba26 9 "fmt"
593f74bb 10 "regexp"
df4aa89a
ILT
11 "runtime"
12 "testing"
13 "time"
14)
15
16func newLocalListener(t *testing.T) Listener {
17 ln, err := Listen("tcp", "127.0.0.1:0")
18 if err != nil {
19 ln, err = Listen("tcp6", "[::1]:0")
20 }
21 if err != nil {
22 t.Fatal(err)
23 }
24 return ln
25}
26
27func TestDialTimeout(t *testing.T) {
28 ln := newLocalListener(t)
29 defer ln.Close()
30
31 errc := make(chan error)
32
cbb6491d 33 numConns := listenerBacklog + 10
df4aa89a
ILT
34
35 // TODO(bradfitz): It's hard to test this in a portable
456fba26 36 // way. This is unfortunate, but works for now.
df4aa89a
ILT
37 switch runtime.GOOS {
38 case "linux":
39 // The kernel will start accepting TCP connections before userspace
40 // gets a chance to not accept them, so fire off a bunch to fill up
41 // the kernel's backlog. Then we test we get a failure after that.
42 for i := 0; i < numConns; i++ {
43 go func() {
44 _, err := DialTimeout("tcp", ln.Addr().String(), 200*time.Millisecond)
45 errc <- err
46 }()
47 }
456fba26 48 case "darwin", "windows":
df4aa89a
ILT
49 // At least OS X 10.7 seems to accept any number of
50 // connections, ignoring listen's backlog, so resort
51 // to connecting to a hopefully-dead 127/8 address.
94252f4b 52 // Same for windows.
456fba26
ILT
53 //
54 // Use an IANA reserved port (49151) instead of 80, because
55 // on our 386 builder, this Dial succeeds, connecting
56 // to an IIS web server somewhere. The data center
57 // or VM or firewall must be stealing the TCP connection.
58 //
59 // IANA Service Name and Transport Protocol Port Number Registry
60 // <http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xml>
df4aa89a 61 go func() {
456fba26
ILT
62 c, err := DialTimeout("tcp", "127.0.71.111:49151", 200*time.Millisecond)
63 if err == nil {
64 err = fmt.Errorf("unexpected: connected to %s!", c.RemoteAddr())
65 c.Close()
66 }
df4aa89a
ILT
67 errc <- err
68 }()
69 default:
94252f4b 70 // TODO(bradfitz):
cbb6491d
ILT
71 // OpenBSD may have a reject route to 127/8 except 127.0.0.1/32
72 // by default. FreeBSD likely works, but is untested.
73 // TODO(rsc):
74 // The timeout never happens on Windows. Why? Issue 3016.
df4aa89a
ILT
75 t.Logf("skipping test on %q; untested.", runtime.GOOS)
76 return
77 }
78
79 connected := 0
80 for {
81 select {
82 case <-time.After(15 * time.Second):
83 t.Fatal("too slow")
84 case err := <-errc:
85 if err == nil {
86 connected++
87 if connected == numConns {
88 t.Fatal("all connections connected; expected some to time out")
89 }
90 } else {
91 terr, ok := err.(timeout)
92 if !ok {
93 t.Fatalf("got error %q; want error with timeout interface", err)
94 }
95 if !terr.Timeout() {
96 t.Fatalf("got error %q; not a timeout", err)
97 }
98 // Pass. We saw a timeout error.
99 return
100 }
101 }
102 }
103}
cbb6491d
ILT
104
105func TestSelfConnect(t *testing.T) {
106 if runtime.GOOS == "windows" {
107 // TODO(brainman): do not know why it hangs.
108 t.Logf("skipping known-broken test on windows")
109 return
110 }
111 // Test that Dial does not honor self-connects.
112 // See the comment in DialTCP.
113
114 // Find a port that would be used as a local address.
115 l, err := Listen("tcp", "127.0.0.1:0")
116 if err != nil {
117 t.Fatal(err)
118 }
119 c, err := Dial("tcp", l.Addr().String())
120 if err != nil {
121 t.Fatal(err)
122 }
123 addr := c.LocalAddr().String()
124 c.Close()
125 l.Close()
126
127 // Try to connect to that address repeatedly.
128 n := 100000
129 if testing.Short() {
130 n = 1000
131 }
132 switch runtime.GOOS {
4ccad563 133 case "darwin", "freebsd", "netbsd", "openbsd", "plan9", "solaris", "windows":
cbb6491d
ILT
134 // Non-Linux systems take a long time to figure
135 // out that there is nothing listening on localhost.
136 n = 100
137 }
138 for i := 0; i < n; i++ {
139 c, err := Dial("tcp", addr)
140 if err == nil {
141 c.Close()
142 t.Errorf("#%d: Dial %q succeeded", i, addr)
143 }
144 }
145}
593f74bb
ILT
146
147var runErrorTest = flag.Bool("run_error_test", false, "let TestDialError check for dns errors")
148
149type DialErrorTest struct {
150 Net string
151 Raddr string
152 Pattern string
153}
154
155var dialErrorTests = []DialErrorTest{
156 {
157 "datakit", "mh/astro/r70",
158 "dial datakit mh/astro/r70: unknown network datakit",
159 },
160 {
161 "tcp", "127.0.0.1:☺",
162 "dial tcp 127.0.0.1:☺: unknown port tcp/☺",
163 },
164 {
165 "tcp", "no-such-name.google.com.:80",
166 "dial tcp no-such-name.google.com.:80: lookup no-such-name.google.com.( on .*)?: no (.*)",
167 },
168 {
169 "tcp", "no-such-name.no-such-top-level-domain.:80",
170 "dial tcp no-such-name.no-such-top-level-domain.:80: lookup no-such-name.no-such-top-level-domain.( on .*)?: no (.*)",
171 },
172 {
173 "tcp", "no-such-name:80",
174 `dial tcp no-such-name:80: lookup no-such-name\.(.*\.)?( on .*)?: no (.*)`,
175 },
176 {
177 "tcp", "mh/astro/r70:http",
178 "dial tcp mh/astro/r70:http: lookup mh/astro/r70: invalid domain name",
179 },
180 {
181 "unix", "/etc/file-not-found",
182 "dial unix /etc/file-not-found: no such file or directory",
183 },
184 {
185 "unix", "/etc/",
186 "dial unix /etc/: (permission denied|socket operation on non-socket|connection refused)",
187 },
188 {
189 "unixpacket", "/etc/file-not-found",
190 "dial unixpacket /etc/file-not-found: no such file or directory",
191 },
192 {
193 "unixpacket", "/etc/",
194 "dial unixpacket /etc/: (permission denied|socket operation on non-socket|connection refused)",
195 },
196}
197
198var duplicateErrorPattern = `dial (.*) dial (.*)`
199
200func TestDialError(t *testing.T) {
201 if !*runErrorTest {
202 t.Logf("test disabled; use -run_error_test to enable")
203 return
204 }
205 for i, tt := range dialErrorTests {
206 c, err := Dial(tt.Net, tt.Raddr)
207 if c != nil {
208 c.Close()
209 }
210 if err == nil {
211 t.Errorf("#%d: nil error, want match for %#q", i, tt.Pattern)
212 continue
213 }
214 s := err.Error()
215 match, _ := regexp.MatchString(tt.Pattern, s)
216 if !match {
217 t.Errorf("#%d: %q, want match for %#q", i, s, tt.Pattern)
218 }
219 match, _ = regexp.MatchString(duplicateErrorPattern, s)
220 if match {
221 t.Errorf("#%d: %q, duplicate error return from Dial", i, s)
222 }
223 }
224}