}
}
-func TestClientHead_h1(t *testing.T) { testClientHead(t, false) }
-func TestClientHead_h2(t *testing.T) { testClientHead(t, true) }
+func TestClientHead_h1(t *testing.T) { testClientHead(t, h1Mode) }
+func TestClientHead_h2(t *testing.T) { testClientHead(t, h2Mode) }
func testClientHead(t *testing.T, h2 bool) {
defer afterTest(t)
fmt.Fprintf(&j.log, format, args...)
}
-func TestStreamingGet_h1(t *testing.T) { testStreamingGet(t, false) }
-func TestStreamingGet_h2(t *testing.T) { testStreamingGet(t, true) }
+func TestStreamingGet_h1(t *testing.T) { testStreamingGet(t, h1Mode) }
+func TestStreamingGet_h2(t *testing.T) { testStreamingGet(t, h2Mode) }
func testStreamingGet(t *testing.T, h2 bool) {
defer afterTest(t)
// Verify Response.ContentLength is populated. https://golang.org/issue/4126
func TestClientHeadContentLength_h1(t *testing.T) {
- testClientHeadContentLength(t, false)
+ testClientHeadContentLength(t, h1Mode)
}
func TestClientHeadContentLength_h2(t *testing.T) {
- testClientHeadContentLength(t, true)
+ testClientHeadContentLength(t, h2Mode)
}
func testClientHeadContentLength(t *testing.T, h2 bool) {
}
}
-func TestClientRedirectEatsBody_h1(t *testing.T) {
- testClientRedirectEatsBody(t, false)
-}
-
-func TestClientRedirectEatsBody_h2(t *testing.T) {
- testClientRedirectEatsBody(t, true)
-}
-
+func TestClientRedirectEatsBody_h1(t *testing.T) { testClientRedirectEatsBody(t, h1Mode) }
+func TestClientRedirectEatsBody_h2(t *testing.T) { testClientRedirectEatsBody(t, h2Mode) }
func testClientRedirectEatsBody(t *testing.T, h2 bool) {
defer afterTest(t)
saw := make(chan string, 2)
return 0, io.EOF
}
-func TestClientTrailers(t *testing.T) {
+func TestClientTrailers_h1(t *testing.T) { testClientTrailers(t, h1Mode) }
+func TestClientTrailers_h2(t *testing.T) {
+ t.Skip("skipping in http2 mode; golang.org/issue/13557")
+ testClientTrailers(t, h2Mode)
+}
+func testClientTrailers(t *testing.T, h2 bool) {
defer afterTest(t)
- ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
w.Header().Set("Connection", "close")
w.Header().Set("Trailer", "Server-Trailer-A, Server-Trailer-B")
w.Header().Add("Trailer", "Server-Trailer-C")
w.Header().Set("Server-Trailer-A", "valuea")
w.Header().Set("Server-Trailer-C", "valuec") // skipping B
}))
- defer ts.Close()
+ defer cst.close()
var req *Request
- req, _ = NewRequest("POST", ts.URL, io.MultiReader(
+ req, _ = NewRequest("POST", cst.ts.URL, io.MultiReader(
eofReaderFunc(func() {
req.Trailer["Client-Trailer-A"] = []string{"valuea"}
}),
"Client-Trailer-B": nil, // to be set later
}
req.ContentLength = -1
- res, err := DefaultClient.Do(req)
+ res, err := cst.c.Do(req)
if err != nil {
t.Fatal(err)
}
}))
}
-func TestSetsRemoteAddr_h1(t *testing.T) { testSetsRemoteAddr(t, false) }
-func TestSetsRemoteAddr_h2(t *testing.T) { testSetsRemoteAddr(t, true) }
+func TestSetsRemoteAddr_h1(t *testing.T) { testSetsRemoteAddr(t, h1Mode) }
+func TestSetsRemoteAddr_h2(t *testing.T) { testSetsRemoteAddr(t, h2Mode) }
func testSetsRemoteAddr(t *testing.T, h2 bool) {
defer afterTest(t)
// TestHeadResponses verifies that all MIME type sniffing and Content-Length
// counting of GET requests also happens on HEAD requests.
-func TestHeadResponses_h1(t *testing.T) { testHeadResponses(t, false) }
-func TestHeadResponses_h2(t *testing.T) { testHeadResponses(t, true) }
+func TestHeadResponses_h1(t *testing.T) { testHeadResponses(t, h1Mode) }
+func TestHeadResponses_h2(t *testing.T) { testHeadResponses(t, h2Mode) }
func testHeadResponses(t *testing.T, h2 bool) {
defer afterTest(t)
}
}
-func TestTimeoutHandler_h1(t *testing.T) { testTimeoutHandler(t, false) }
-func TestTimeoutHandler_h2(t *testing.T) { testTimeoutHandler(t, true) }
-
+func TestTimeoutHandler_h1(t *testing.T) { testTimeoutHandler(t, h1Mode) }
+func TestTimeoutHandler_h2(t *testing.T) { testTimeoutHandler(t, h2Mode) }
func testTimeoutHandler(t *testing.T, h2 bool) {
defer afterTest(t)
sendHi := make(chan bool, 1)
// the previous request's body, which is not optimal for zero-lengthed bodies,
// as the client would then see http.ErrBodyReadAfterClose and not 0, io.EOF.
func TestZeroLengthPostAndResponse_h1(t *testing.T) {
- testZeroLengthPostAndResponse(t, false)
+ testZeroLengthPostAndResponse(t, h1Mode)
}
func TestZeroLengthPostAndResponse_h2(t *testing.T) {
- testZeroLengthPostAndResponse(t, true)
+ testZeroLengthPostAndResponse(t, h2Mode)
}
func testZeroLengthPostAndResponse(t *testing.T, h2 bool) {
}
}
-func TestHandlerPanicNil(t *testing.T) {
- testHandlerPanic(t, false, nil)
+func TestHandlerPanicNil_h1(t *testing.T) { testHandlerPanic(t, false, h1Mode, nil) }
+func TestHandlerPanicNil_h2(t *testing.T) {
+ t.Skip("known failure; golang.org/issue/13555")
+ testHandlerPanic(t, false, h2Mode, nil)
}
-func TestHandlerPanic(t *testing.T) {
- testHandlerPanic(t, false, "intentional death for testing")
+func TestHandlerPanic_h1(t *testing.T) {
+ testHandlerPanic(t, false, h1Mode, "intentional death for testing")
+}
+func TestHandlerPanic_h2(t *testing.T) {
+ t.Skip("known failure; golang.org/issue/13555")
+ testHandlerPanic(t, false, h2Mode, "intentional death for testing")
}
func TestHandlerPanicWithHijack(t *testing.T) {
- testHandlerPanic(t, true, "intentional death for testing")
+ // Only testing HTTP/1, and our http2 server doesn't support hijacking.
+ testHandlerPanic(t, true, h1Mode, "intentional death for testing")
}
-func testHandlerPanic(t *testing.T, withHijack bool, panicValue interface{}) {
+func testHandlerPanic(t *testing.T, withHijack, h2 bool, panicValue interface{}) {
defer afterTest(t)
// Unlike the other tests that set the log output to ioutil.Discard
// to quiet the output, this test uses a pipe. The pipe serves three
defer log.SetOutput(os.Stderr)
defer pw.Close()
- ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
if withHijack {
rwc, _, err := w.(Hijacker).Hijack()
if err != nil {
}
panic(panicValue)
}))
- defer ts.Close()
+ defer cst.close()
// Do a blocking read on the log output pipe so its logging
// doesn't bleed into the next test. But wait only 5 seconds
done <- true
}()
- _, err := Get(ts.URL)
+ _, err := cst.c.Get(cst.ts.URL)
if err == nil {
t.Logf("expected an error")
}
}
}
-func TestServerNoDate(t *testing.T) { testServerNoHeader(t, "Date") }
-func TestServerNoContentType(t *testing.T) { testServerNoHeader(t, "Content-Type") }
+func TestServerNoDate_h1(t *testing.T) { testServerNoHeader(t, h1Mode, "Date") }
+func TestServerNoDate_h2(t *testing.T) { testServerNoHeader(t, h2Mode, "Date") }
+func TestServerNoContentType_h1(t *testing.T) { testServerNoHeader(t, h1Mode, "Content-Type") }
+func TestServerNoContentType_h2(t *testing.T) { testServerNoHeader(t, h2Mode, "Content-Type") }
-func testServerNoHeader(t *testing.T, header string) {
+func testServerNoHeader(t *testing.T, h2 bool, header string) {
defer afterTest(t)
- ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
w.Header()[header] = nil
io.WriteString(w, "<html>foo</html>") // non-empty
}))
- defer ts.Close()
- res, err := Get(ts.URL)
+ defer cst.close()
+ res, err := cst.c.Get(cst.ts.URL)
if err != nil {
t.Fatal(err)
}
res.Body.Close()
}
-func TestRequestLimit(t *testing.T) {
+func TestRequestLimit_h1(t *testing.T) { testRequestLimit(t, h1Mode) }
+func TestRequestLimit_h2(t *testing.T) { testRequestLimit(t, h2Mode) }
+func testRequestLimit(t *testing.T, h2 bool) {
defer afterTest(t)
- ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
t.Fatalf("didn't expect to get request in Handler")
}))
- defer ts.Close()
- req, _ := NewRequest("GET", ts.URL, nil)
+ defer cst.close()
+ req, _ := NewRequest("GET", cst.ts.URL, nil)
var bytesPerHeader = len("header12345: val12345\r\n")
for i := 0; i < ((DefaultMaxHeaderBytes+4096)/bytesPerHeader)+1; i++ {
req.Header.Set(fmt.Sprintf("header%05d", i), fmt.Sprintf("val%05d", i))
}
- res, err := DefaultClient.Do(req)
+ res, err := cst.c.Do(req)
if err != nil {
// Some HTTP clients may fail on this undefined behavior (server replying and
// closing the connection while the request is still being written), but
t.Fatalf("Do: %v", err)
}
defer res.Body.Close()
- if res.StatusCode != 413 {
- t.Fatalf("expected 413 response status; got: %d %s", res.StatusCode, res.Status)
+ if res.StatusCode != 431 {
+ t.Fatalf("expected 431 response status; got: %d %s", res.StatusCode, res.Status)
}
}
return
}
-func TestRequestBodyLimit_h1(t *testing.T) { testRequestBodyLimit(t, false) }
-func TestRequestBodyLimit_h2(t *testing.T) { testRequestBodyLimit(t, true) }
-
+func TestRequestBodyLimit_h1(t *testing.T) { testRequestBodyLimit(t, h1Mode) }
+func TestRequestBodyLimit_h2(t *testing.T) { testRequestBodyLimit(t, h2Mode) }
func testRequestBodyLimit(t *testing.T, h2 bool) {
defer afterTest(t)
const limit = 1 << 20
<-writeErr
}
-func TestCaseSensitiveMethod_h1(t *testing.T) { testCaseSensitiveMethod(t, false) }
-func TestCaseSensitiveMethod_h2(t *testing.T) { testCaseSensitiveMethod(t, true) }
-
+func TestCaseSensitiveMethod_h1(t *testing.T) { testCaseSensitiveMethod(t, h1Mode) }
+func TestCaseSensitiveMethod_h2(t *testing.T) { testCaseSensitiveMethod(t, h2Mode) }
func testCaseSensitiveMethod(t *testing.T, h2 bool) {
defer afterTest(t)
cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
}
// See golang.org/issue/5660
-func TestServerReaderFromOrder(t *testing.T) {
+func TestServerReaderFromOrder_h1(t *testing.T) { testServerReaderFromOrder(t, h1Mode) }
+func TestServerReaderFromOrder_h2(t *testing.T) { testServerReaderFromOrder(t, h2Mode) }
+func testServerReaderFromOrder(t *testing.T, h2 bool) {
defer afterTest(t)
pr, pw := io.Pipe()
const size = 3 << 20
- ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
+ cst := newClientServerTest(t, h2, HandlerFunc(func(rw ResponseWriter, req *Request) {
rw.Header().Set("Content-Type", "text/plain") // prevent sniffing path
done := make(chan bool)
go func() {
pw.Close()
<-done
}))
- defer ts.Close()
+ defer cst.close()
- req, err := NewRequest("POST", ts.URL, io.LimitReader(neverEnding('a'), size))
+ req, err := NewRequest("POST", cst.ts.URL, io.LimitReader(neverEnding('a'), size))
if err != nil {
t.Fatal(err)
}
- res, err := DefaultClient.Do(req)
+ res, err := cst.c.Do(req)
if err != nil {
t.Fatal(err)
}
// 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, h1Mode)
+}
+func TestTransportAndServerSharedBodyRace_h2(t *testing.T) {
+ t.Skip("failing in http2 mode; golang.org/issue/13556")
+ testTransportAndServerSharedBodyRace(t, h2Mode)
+}
+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) {
+ backend := newClientServerTest(t, h2, HandlerFunc(func(rw ResponseWriter, req *Request) {
io.CopyN(rw, req.Body, bodySize)
<-unblockBackend
}))
- defer backend.Close()
+ defer backend.close()
backendRespc := make(chan *Response, 1)
- proxy := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
- req2, _ := NewRequest("POST", backend.URL, req.Body)
+ var proxy *clientServerTest
+ proxy = newClientServerTest(t, h2, HandlerFunc(func(rw ResponseWriter, req *Request) {
+ req2, _ := NewRequest("POST", backend.ts.URL, req.Body)
req2.ContentLength = bodySize
+ cancel := make(chan struct{})
+ req2.Cancel = cancel
- bresp, err := DefaultClient.Do(req2)
+ bresp, err := proxy.c.Do(req2)
if err != nil {
t.Errorf("Proxy outbound request: %v", err)
return
// Try to cause a race: Both the DefaultTransport and the proxy handler's Server
// will try to read/close req.Body (aka req2.Body)
- DefaultTransport.(*Transport).CancelRequest(req2)
+ if h2 {
+ close(cancel)
+ } else {
+ proxy.c.Transport.(*Transport).CancelRequest(req2)
+ }
rw.Write([]byte("OK"))
}))
- defer proxy.Close()
+ defer proxy.close()
defer close(unblockBackend)
- req, _ := NewRequest("POST", proxy.URL, io.LimitReader(neverEnding('a'), bodySize))
- res, err := DefaultClient.Do(req)
+ req, _ := NewRequest("POST", proxy.ts.URL, io.LimitReader(neverEnding('a'), bodySize))
+ res, err := proxy.c.Do(req)
if err != nil {
t.Fatalf("Original request: %v", err)
}
case res := <-backendRespc:
res.Body.Close()
default:
- // We failed earlier. (e.g. on DefaultClient.Do(req2))
+ // We failed earlier. (e.g. on proxy.c.Do(req2))
}
}
}
// golang.org/issue/7856
-func TestServerEmptyBodyRace(t *testing.T) {
+func TestServerEmptyBodyRace_h1(t *testing.T) { testServerEmptyBodyRace(t, h1Mode) }
+func TestServerEmptyBodyRace_h2(t *testing.T) { testServerEmptyBodyRace(t, h2Mode) }
+func testServerEmptyBodyRace(t *testing.T, h2 bool) {
defer afterTest(t)
var n int32
- ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
+ cst := newClientServerTest(t, h2, HandlerFunc(func(rw ResponseWriter, req *Request) {
atomic.AddInt32(&n, 1)
}))
- defer ts.Close()
+ defer cst.close()
var wg sync.WaitGroup
const reqs = 20
for i := 0; i < reqs; i++ {
wg.Add(1)
go func() {
defer wg.Done()
- res, err := Get(ts.URL)
+ res, err := cst.c.Get(cst.ts.URL)
if err != nil {
t.Error(err)
return
}
}
-func TestHandlerSetsBodyNil(t *testing.T) {
+func TestHandlerSetsBodyNil_h1(t *testing.T) { testHandlerSetsBodyNil(t, h1Mode) }
+func TestHandlerSetsBodyNil_h2(t *testing.T) { testHandlerSetsBodyNil(t, h2Mode) }
+func testHandlerSetsBodyNil(t *testing.T, h2 bool) {
defer afterTest(t)
- ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
r.Body = nil
fmt.Fprintf(w, "%v", r.RemoteAddr)
}))
- defer ts.Close()
+ defer cst.close()
get := func() string {
- res, err := Get(ts.URL)
+ res, err := cst.c.Get(cst.ts.URL)
if err != nil {
t.Fatal(err)
}