OSDN Git Service

net, syscall: Use native endianness for GNU/Linux netlink code.
[pf3gnuchains/gcc-fork.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 package net
6
7 import (
8         "flag"
9         "fmt"
10         "regexp"
11         "runtime"
12         "testing"
13         "time"
14 )
15
16 func 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
27 func TestDialTimeout(t *testing.T) {
28         ln := newLocalListener(t)
29         defer ln.Close()
30
31         errc := make(chan error)
32
33         numConns := listenerBacklog + 10
34
35         // TODO(bradfitz): It's hard to test this in a portable
36         // way. This is unfortunate, but works for now.
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                 }
48         case "darwin", "windows":
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.
52                 // Same for windows.
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>
61                 go func() {
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                         }
67                         errc <- err
68                 }()
69         default:
70                 // TODO(bradfitz):
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.
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 }
104
105 func 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 {
133         case "darwin", "freebsd", "openbsd", "windows":
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 }
146
147 var runErrorTest = flag.Bool("run_error_test", false, "let TestDialError check for dns errors")
148
149 type DialErrorTest struct {
150         Net     string
151         Raddr   string
152         Pattern string
153 }
154
155 var 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
198 var duplicateErrorPattern = `dial (.*) dial (.*)`
199
200 func 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 }