2012-01-13 06:11:45 +01:00
|
|
|
// Copyright 2011 The Go Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package net
|
|
|
|
|
|
|
|
import (
|
|
|
|
"runtime"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
func newLocalListener(t *testing.T) Listener {
|
|
|
|
ln, err := Listen("tcp", "127.0.0.1:0")
|
|
|
|
if err != nil {
|
|
|
|
ln, err = Listen("tcp6", "[::1]:0")
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
return ln
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDialTimeout(t *testing.T) {
|
|
|
|
ln := newLocalListener(t)
|
|
|
|
defer ln.Close()
|
|
|
|
|
|
|
|
errc := make(chan error)
|
|
|
|
|
2012-03-02 17:38:43 +01:00
|
|
|
numConns := listenerBacklog + 10
|
2012-01-13 06:11:45 +01:00
|
|
|
|
|
|
|
// TODO(bradfitz): It's hard to test this in a portable
|
|
|
|
// way. This is unforunate, but works for now.
|
|
|
|
switch runtime.GOOS {
|
|
|
|
case "linux":
|
|
|
|
// The kernel will start accepting TCP connections before userspace
|
|
|
|
// gets a chance to not accept them, so fire off a bunch to fill up
|
|
|
|
// the kernel's backlog. Then we test we get a failure after that.
|
|
|
|
for i := 0; i < numConns; i++ {
|
|
|
|
go func() {
|
|
|
|
_, err := DialTimeout("tcp", ln.Addr().String(), 200*time.Millisecond)
|
|
|
|
errc <- err
|
|
|
|
}()
|
|
|
|
}
|
2012-03-02 17:38:43 +01:00
|
|
|
case "darwin":
|
2012-01-13 06:11:45 +01:00
|
|
|
// At least OS X 10.7 seems to accept any number of
|
|
|
|
// connections, ignoring listen's backlog, so resort
|
|
|
|
// to connecting to a hopefully-dead 127/8 address.
|
2012-02-09 09:19:58 +01:00
|
|
|
// Same for windows.
|
2012-01-13 06:11:45 +01:00
|
|
|
go func() {
|
|
|
|
_, err := DialTimeout("tcp", "127.0.71.111:80", 200*time.Millisecond)
|
|
|
|
errc <- err
|
|
|
|
}()
|
|
|
|
default:
|
2012-02-09 09:19:58 +01:00
|
|
|
// TODO(bradfitz):
|
2012-03-02 17:38:43 +01:00
|
|
|
// OpenBSD may have a reject route to 127/8 except 127.0.0.1/32
|
|
|
|
// by default. FreeBSD likely works, but is untested.
|
|
|
|
// TODO(rsc):
|
|
|
|
// The timeout never happens on Windows. Why? Issue 3016.
|
2012-01-13 06:11:45 +01:00
|
|
|
t.Logf("skipping test on %q; untested.", runtime.GOOS)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
connected := 0
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-time.After(15 * time.Second):
|
|
|
|
t.Fatal("too slow")
|
|
|
|
case err := <-errc:
|
|
|
|
if err == nil {
|
|
|
|
connected++
|
|
|
|
if connected == numConns {
|
|
|
|
t.Fatal("all connections connected; expected some to time out")
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
terr, ok := err.(timeout)
|
|
|
|
if !ok {
|
|
|
|
t.Fatalf("got error %q; want error with timeout interface", err)
|
|
|
|
}
|
|
|
|
if !terr.Timeout() {
|
|
|
|
t.Fatalf("got error %q; not a timeout", err)
|
|
|
|
}
|
|
|
|
// Pass. We saw a timeout error.
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-03-02 17:38:43 +01:00
|
|
|
|
|
|
|
func TestSelfConnect(t *testing.T) {
|
|
|
|
if runtime.GOOS == "windows" {
|
|
|
|
// TODO(brainman): do not know why it hangs.
|
|
|
|
t.Logf("skipping known-broken test on windows")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
// Test that Dial does not honor self-connects.
|
|
|
|
// See the comment in DialTCP.
|
|
|
|
|
|
|
|
// Find a port that would be used as a local address.
|
|
|
|
l, err := Listen("tcp", "127.0.0.1:0")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
c, err := Dial("tcp", l.Addr().String())
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
addr := c.LocalAddr().String()
|
|
|
|
c.Close()
|
|
|
|
l.Close()
|
|
|
|
|
|
|
|
// Try to connect to that address repeatedly.
|
|
|
|
n := 100000
|
|
|
|
if testing.Short() {
|
|
|
|
n = 1000
|
|
|
|
}
|
|
|
|
switch runtime.GOOS {
|
|
|
|
case "darwin", "freebsd", "openbsd", "windows":
|
|
|
|
// Non-Linux systems take a long time to figure
|
|
|
|
// out that there is nothing listening on localhost.
|
|
|
|
n = 100
|
|
|
|
}
|
|
|
|
for i := 0; i < n; i++ {
|
|
|
|
c, err := Dial("tcp", addr)
|
|
|
|
if err == nil {
|
|
|
|
c.Close()
|
|
|
|
t.Errorf("#%d: Dial %q succeeded", i, addr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|