Skip to content

Instantly share code, notes, and snippets.

@odeke-em
Last active April 26, 2016 08:42
Show Gist options
  • Save odeke-em/7caf299cceb7cb2b5525 to your computer and use it in GitHub Desktop.
Save odeke-em/7caf299cceb7cb2b5525 to your computer and use it in GitHub Desktop.
diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go
index 4d5bcd0..356bae0 100644
--- a/src/net/http/serve_test.go
+++ b/src/net/http/serve_test.go
@@ -2786,24 +2786,32 @@ func TestContentTypeOkayOn204(t *testing.T) {
// proxy). So then two people own that Request.Body (both the server
// and the http client), and both think they can close it on failure.
// Therefore, all incoming server requests Bodies need to be thread-safe.
-func TestTransportAndServerSharedBodyRace(t *testing.T) {
+func TestTransportAndServerSharedBodyRace_h1(t *testing.T) {
+ testTransportAndServerSharedBodyRace(t, false)
+}
+
+func TestTransportAndServerSharedBodyRace_h2(t *testing.T) {
+ testTransportAndServerSharedBodyRace(t, true)
+}
+
+func testTransportAndServerSharedBodyRace(t *testing.T, h2 bool) {
defer afterTest(t)
const bodySize = 1 << 20
unblockBackend := make(chan bool)
- backend := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
+ backendCST := newClientServerTest(t, h2, HandlerFunc(func(rw ResponseWriter, req *Request) {
io.CopyN(rw, req.Body, bodySize)
<-unblockBackend
}))
- defer backend.Close()
+ defer backendCST.close()
backendRespc := make(chan *Response, 1)
- proxy := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
- req2, _ := NewRequest("POST", backend.URL, req.Body)
+ proxyCST := newClientServerTest(t, h2, HandlerFunc(func(rw ResponseWriter, req *Request) {
+ req2, _ := NewRequest("POST", backendCST.ts.URL, req.Body)
req2.ContentLength = bodySize
- bresp, err := DefaultClient.Do(req2)
+ bresp, err := backendCST.c.Do(req2)
if err != nil {
t.Errorf("Proxy outbound request: %v", err)
return
@@ -2815,27 +2823,31 @@ func TestTransportAndServerSharedBodyRace(t *testing.T) {
}
backendRespc <- bresp // to close later
- // Try to cause a race: Both the DefaultTransport and the proxy handler's Server
+ // Try to cause a race: Both the backend and proxy handler's Servers
// will try to read/close req.Body (aka req2.Body)
- DefaultTransport.(*Transport).CancelRequest(req2)
+ backendCST.c.Transport.(*Transport).CancelRequest(req2)
rw.Write([]byte("OK"))
}))
- defer proxy.Close()
+ defer proxyCST.close()
defer close(unblockBackend)
- req, _ := NewRequest("POST", proxy.URL, io.LimitReader(neverEnding('a'), bodySize))
- res, err := DefaultClient.Do(req)
+ req, _ := NewRequest("POST", proxyCST.ts.URL, io.LimitReader(neverEnding('a'), bodySize))
+ res, err := proxyCST.c.Do(req)
if err != nil {
t.Fatalf("Original request: %v", err)
}
- // Cleanup, so we don't leak goroutines.
- res.Body.Close()
+ // Connection:close doesn't exist in HTTP2
+ if !h2 {
+ // Cleanup, so we don't leak goroutines.
+ res.Body.Close()
+ }
+
select {
case res := <-backendRespc:
res.Body.Close()
default:
- // We failed earlier. (e.g. on DefaultClient.Do(req2))
+ // We failed earlier. (e.g. on backend.c.Do(req2))
}
}
$ go test
2015/12/08 20:34:34 httptest.Server blocked in Close after 5 seconds, waiting for connections:
  *tls.Conn 0xc820208000 127.0.0.1:53482 in state active
^C
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment