diff options
Diffstat (limited to 'libgo/go/net/dial_test.go')
-rw-r--r-- | libgo/go/net/dial_test.go | 80 |
1 files changed, 79 insertions, 1 deletions
diff --git a/libgo/go/net/dial_test.go b/libgo/go/net/dial_test.go index abd6b7fe920..865dd627778 100644 --- a/libgo/go/net/dial_test.go +++ b/libgo/go/net/dial_test.go @@ -7,6 +7,8 @@ package net import ( "flag" "fmt" + "io" + "os" "regexp" "runtime" "testing" @@ -55,7 +57,7 @@ func TestDialTimeout(t *testing.T) { // on our 386 builder, this Dial succeeds, connecting // to an IIS web server somewhere. The data center // or VM or firewall must be stealing the TCP connection. - // + // // IANA Service Name and Transport Protocol Port Number Registry // <http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xml> go func() { @@ -222,3 +224,79 @@ func TestDialError(t *testing.T) { } } } + +func TestDialTimeoutFDLeak(t *testing.T) { + if runtime.GOOS != "linux" { + // TODO(bradfitz): test on other platforms + t.Logf("skipping test on %s", runtime.GOOS) + return + } + + ln := newLocalListener(t) + defer ln.Close() + + type connErr struct { + conn Conn + err error + } + dials := listenerBacklog + 100 + maxGoodConnect := listenerBacklog + 5 // empirically 131 good ones (of 128). who knows? + resc := make(chan connErr) + for i := 0; i < dials; i++ { + go func() { + conn, err := DialTimeout("tcp", ln.Addr().String(), 500*time.Millisecond) + resc <- connErr{conn, err} + }() + } + + var firstErr string + var ngood int + var toClose []io.Closer + for i := 0; i < dials; i++ { + ce := <-resc + if ce.err == nil { + ngood++ + if ngood > maxGoodConnect { + t.Errorf("%d good connects; expected at most %d", ngood, maxGoodConnect) + } + toClose = append(toClose, ce.conn) + continue + } + err := ce.err + if firstErr == "" { + firstErr = err.Error() + } else if err.Error() != firstErr { + t.Fatalf("inconsistent error messages: first was %q, then later %q", firstErr, err) + } + } + for _, c := range toClose { + c.Close() + } + for i := 0; i < 100; i++ { + if got := numFD(); got < dials { + // Test passes. + return + } + time.Sleep(10 * time.Millisecond) + } + if got := numFD(); got >= dials { + t.Errorf("num fds after %d timeouts = %d; want <%d", dials, got, dials) + } +} + +func numFD() int { + if runtime.GOOS == "linux" { + f, err := os.Open("/proc/self/fd") + if err != nil { + panic(err) + } + defer f.Close() + names, err := f.Readdirnames(0) + if err != nil { + panic(err) + } + return len(names) + } + // All tests using this should be skipped anyway, but: + panic("numFDs not implemented on " + runtime.GOOS) +} |