http2: remove arbitrary timeouts in server_test.go
If the test gets completely stuck at these points, we will want a
goroutine dump in order to debug the hang, which log.Fatalf will
not produce (but a test timeout will).
If the test does not get completely stuck (as on a slow or overloaded
builder), then we should let it continue to run until the overall test
timeout, which (unlike hard-coded constants) should already take the
speed of the builder into account.
As a side-effect, this also moves some t.Fatalf calls out of
background goroutines and into the main test-function goroutines where
they belong (see golang/go#24678).
Fixes golang/go#52051.
Change-Id: I37504081e6fdf0b4c244305fc83c575e30b7b453
Reviewed-on: https://go-review.googlesource.com/c/net/+/410096
Run-TryBot: Bryan Mills <bcmills@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Bryan Mills <bcmills@google.com>
Reviewed-by: Damien Neil <dneil@google.com>
diff --git a/http2/server_test.go b/http2/server_test.go
index 40cbc43..2a677b9 100644
--- a/http2/server_test.go
+++ b/http2/server_test.go
@@ -640,11 +640,7 @@
EndHeaders: true,
})
- select {
- case <-gotReq:
- case <-time.After(2 * time.Second):
- t.Error("timeout waiting for request")
- }
+ <-gotReq
}
func TestServer_Request_Get(t *testing.T) {
@@ -1368,13 +1364,9 @@
})
<-inHandler
fn(st)
- select {
- case err := <-errc:
- if checkErr != nil {
- checkErr(err)
- }
- case <-time.After(5 * time.Second):
- t.Fatal("timeout waiting for Handler to return")
+ err := <-errc
+ if checkErr != nil {
+ checkErr(err)
}
}
@@ -1440,11 +1432,7 @@
}
wroteRST <- true
st.awaitIdle()
- select {
- case <-headerWritten:
- case <-time.After(2 * time.Second):
- t.Error("timeout waiting for header write")
- }
+ <-headerWritten
unblockHandler <- true
}
@@ -1685,21 +1673,13 @@
writeReq(st)
st.wantGoAway()
- errc := make(chan error, 1)
- go func() {
- fr, err := st.fr.ReadFrame()
- if err == nil {
- err = fmt.Errorf("got frame of type %T", fr)
- }
- errc <- err
- }()
- select {
- case err := <-errc:
- if err != io.EOF {
- t.Errorf("ReadFrame = %v; want io.EOF", err)
- }
- case <-time.After(2 * time.Second):
- t.Error("timeout waiting for disconnect")
+
+ fr, err := st.fr.ReadFrame()
+ if err == nil {
+ t.Errorf("ReadFrame got frame of type %T; want io.EOF", fr)
+ }
+ if err != io.EOF {
+ t.Errorf("ReadFrame = %v; want io.EOF", err)
}
}
@@ -1729,12 +1709,7 @@
st.greet()
writeReq(st)
-
- select {
- case <-gotReq:
- case <-time.After(2 * time.Second):
- t.Error("timeout waiting for request")
- }
+ <-gotReq
}
func getSlash(st *serverTester) { st.bodylessReq1() }
@@ -2216,20 +2191,11 @@
const maxFrameSize = 16 << 10
testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error {
w.(http.Flusher).Flush()
- errc := make(chan error, 1)
- go func() {
- _, err := w.Write(bytes.Repeat([]byte("a"), size))
- errc <- err
- }()
- select {
- case err := <-errc:
- if err == nil {
- return errors.New("unexpected nil error from Write in handler")
- }
- return nil
- case <-time.After(2 * time.Second):
- return errors.New("timeout waiting for Write in handler")
+ _, err := w.Write(bytes.Repeat([]byte("a"), size))
+ if err == nil {
+ return errors.New("unexpected nil error from Write in handler")
}
+ return nil
}, func(st *serverTester) {
if err := st.fr.WriteSettings(
Setting{SettingInitialWindowSize, 0},
@@ -2383,11 +2349,7 @@
}
// Close the connection and wait for the handler to (hopefully) notice.
st.cc.Close()
- select {
- case <-errc:
- case <-time.After(5 * time.Second):
- t.Error("timeout")
- }
+ _ = <-errc
})
}
@@ -2453,13 +2415,8 @@
// And now another stream should be able to start:
goodID := streamID()
sendReq(goodID, ":path", testPath)
- select {
- case got := <-inHandler:
- if got != goodID {
- t.Errorf("Got stream %d; want %d", got, goodID)
- }
- case <-time.After(3 * time.Second):
- t.Error("timeout waiting for handler")
+ if got := <-inHandler; got != goodID {
+ t.Errorf("Got stream %d; want %d", got, goodID)
}
}
@@ -2552,17 +2509,13 @@
// Now force the serve loop to end, via closing the connection.
st.cc.Close()
- select {
- case <-st.sc.doneServing:
- // Loop has exited.
- panMu.Lock()
- got := panicVal
- panMu.Unlock()
- if got != nil {
- t.Errorf("Got panic: %v", got)
- }
- case <-time.After(5 * time.Second):
- t.Error("timeout")
+ <-st.sc.doneServing
+
+ panMu.Lock()
+ got := panicVal
+ panMu.Unlock()
+ if got != nil {
+ t.Errorf("Got panic: %v", got)
}
})
}
@@ -2724,38 +2677,26 @@
t.Logf("Running test server for curl to hit at: %s", ts.URL)
container := curl(t, "--silent", "--http2", "--insecure", "-v", ts.URL)
defer kill(container)
- resc := make(chan interface{}, 1)
- go func() {
- res, err := dockerLogs(container)
- if err != nil {
- resc <- err
- } else {
- resc <- res
- }
- }()
- select {
- case res := <-resc:
- if err, ok := res.(error); ok {
- t.Fatal(err)
- }
- body := string(res.([]byte))
- // Search for both "key: value" and "key:value", since curl changed their format
- // Our Dockerfile contains the latest version (no space), but just in case people
- // didn't rebuild, check both.
- if !strings.Contains(body, "foo: Bar") && !strings.Contains(body, "foo:Bar") {
- t.Errorf("didn't see foo: Bar header")
- t.Logf("Got: %s", body)
- }
- if !strings.Contains(body, "client-proto: HTTP/2") && !strings.Contains(body, "client-proto:HTTP/2") {
- t.Errorf("didn't see client-proto: HTTP/2 header")
- t.Logf("Got: %s", res)
- }
- if !strings.Contains(string(res.([]byte)), msg) {
- t.Errorf("didn't see %q content", msg)
- t.Logf("Got: %s", res)
- }
- case <-time.After(3 * time.Second):
- t.Errorf("timeout waiting for curl")
+ res, err := dockerLogs(container)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ body := string(res)
+ // Search for both "key: value" and "key:value", since curl changed their format
+ // Our Dockerfile contains the latest version (no space), but just in case people
+ // didn't rebuild, check both.
+ if !strings.Contains(body, "foo: Bar") && !strings.Contains(body, "foo:Bar") {
+ t.Errorf("didn't see foo: Bar header")
+ t.Logf("Got: %s", body)
+ }
+ if !strings.Contains(body, "client-proto: HTTP/2") && !strings.Contains(body, "client-proto:HTTP/2") {
+ t.Errorf("didn't see client-proto: HTTP/2 header")
+ t.Logf("Got: %s", res)
+ }
+ if !strings.Contains(string(res), msg) {
+ t.Errorf("didn't see %q content", msg)
+ t.Logf("Got: %s", res)
}
if atomic.LoadInt32(&gotConn) == 0 {
@@ -3640,11 +3581,8 @@
req = r
}),
}})
- select {
- case <-clientDone:
- case <-time.After(5 * time.Second):
- t.Fatal("timeout waiting for handler")
- }
+ <-clientDone
+
if req.TLS == nil {
t.Fatalf("Request.TLS is nil. Got: %#v", req)
}
@@ -3825,18 +3763,12 @@
unblock := make(chan bool, 1)
defer close(unblock)
- timeOut := time.NewTimer(5 * time.Second)
- defer timeOut.Stop()
st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
// Don't read the 16KB request body. Wait until the client's
// done sending it and then return. This should cause the Server
// to then return those 16KB of flow control to the client.
tt.reqFn(r)
- select {
- case <-unblock:
- case <-timeOut.C:
- t.Fatal(tt.name, "timedout")
- }
+ <-unblock
}, optOnlyServer)
defer st.Close()
@@ -4123,11 +4055,7 @@
st.greet()
st.bodylessReq1()
- select {
- case <-handlerDone:
- case <-time.After(5 * time.Second):
- t.Fatalf("server did not shutdown?")
- }
+ <-handlerDone
hf := st.wantHeaders()
goth := st.decodeHeader(hf.HeaderBlockFragment())
wanth := [][2]string{