aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2016-02-05 14:59:46 -0800
committerIan Lance Taylor <iant@golang.org>2016-02-06 23:33:23 +0000
commit54b4b946b67ab28fc8695f1fa26b98f21d366fdb (patch)
treece03692f0c1e52ae0ddb8336dac7970675a1eec6
parentfd9fd4c39d92f6f177d22b39e8ee000ae01a9511 (diff)
downloadgo-54b4b946b67ab28fc8695f1fa26b98f21d366fdb.tar.gz
go-54b4b946b67ab28fc8695f1fa26b98f21d366fdb.zip
net/http: deflake TestCloseNotifierPipelined
The test sends two HTTP/1.1 pipelined requests. The first is completedly by the second, and as such triggers an immediate call to the CloseNotify channel. The second calls the CloseNotify channel after the overall connection is closed. The test was passing fine on gc because the code would enter the select loop before running the handler, so the send on gotReq would always be seen first. On gccgo the code would sometimes enter the select loop after the handler had already finished, meaning that the select could choose between gotReq and sawClose. If it picked sawClose, it would never close the overall connection, and the httptest server would hang. The same hang could be induced with gc by adding a time.Sleep immediately before the select loop. Deflake the test by 1) don't close the overall connection until both requests have been seen; 2) don't exit the loop until both closes have been seen. Fixes #14231. Change-Id: I9d20c309125422ce60ac545f78bcfa337aec1c7d Reviewed-on: https://go-review.googlesource.com/19281 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
-rw-r--r--src/net/http/serve_test.go16
1 files changed, 13 insertions, 3 deletions
diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go
index f8cad802d4..f7df776389 100644
--- a/src/net/http/serve_test.go
+++ b/src/net/http/serve_test.go
@@ -2416,7 +2416,7 @@ func TestCloseNotifierPipelined(t *testing.T) {
if err != nil {
t.Fatalf("error dialing: %v", err)
}
- diec := make(chan bool, 2)
+ diec := make(chan bool, 1)
go func() {
const req = "GET / HTTP/1.1\r\nConnection: keep-alive\r\nHost: foo\r\n\r\n"
_, err = io.WriteString(conn, req+req) // two requests
@@ -2426,13 +2426,23 @@ func TestCloseNotifierPipelined(t *testing.T) {
<-diec
conn.Close()
}()
+ reqs := 0
+ closes := 0
For:
for {
select {
case <-gotReq:
- diec <- true
+ reqs++
+ if reqs > 2 {
+ t.Fatal("too many requests")
+ } else if reqs > 1 {
+ diec <- true
+ }
case <-sawClose:
- break For
+ closes++
+ if closes > 1 {
+ break For
+ }
case <-time.After(5 * time.Second):
ts.CloseClientConnections()
t.Fatal("timeout")