diff options
| author | Nicholas S. Husin <nsh@golang.org> | 2026-03-30 19:17:03 -0400 |
|---|---|---|
| committer | Nicholas Husin <nsh@golang.org> | 2026-04-10 14:18:34 -0700 |
| commit | ccf4ba99a90f6f1366daef776ae90187c9f3c6b1 (patch) | |
| tree | 379004141a9699a153e5555dc0721779513d74ef | |
| parent | 6299ca285a0a6bf7d2b1bfbb03b6c3288b846bdf (diff) | |
| download | go-ccf4ba99a90f6f1366daef776ae90187c9f3c6b1.tar.xz | |
net/http: run tests for HTTP/3 where it can already pass
By default, our test harnesses (run and runSynctest) now use http3Mode,
in addition to http1Mode and http2Mode, when no []testMode were
explicitly defined for a given test.
Tests that cannot currently pass for HTTP/3 have been modified to use
http3SkippedMode, which serves as a convenient alias for the old default
of []testMode{http1Mode, http2Mode}.
We changed the default mode and defined http3SkippedMode so we have a
clear list of TODOs in terms of how much changes are still needed before
our HTTP/3 implementation reaches basic feature parity with HTTP/1 and
HTTP/2.
For #70914
Change-Id: I719d5d66399a51f7c3d96180ebed9b606a6a6964
Reviewed-on: https://go-review.googlesource.com/c/go/+/765320
Reviewed-by: Damien Neil <dneil@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Nicholas Husin <husin@google.com>
| -rw-r--r-- | src/net/http/client_test.go | 25 | ||||
| -rw-r--r-- | src/net/http/clientconn_test.go | 12 | ||||
| -rw-r--r-- | src/net/http/clientserver_test.go | 33 | ||||
| -rw-r--r-- | src/net/http/fs_test.go | 12 | ||||
| -rw-r--r-- | src/net/http/responsecontroller_test.go | 14 | ||||
| -rw-r--r-- | src/net/http/serve_test.go | 59 | ||||
| -rw-r--r-- | src/net/http/sniff_test.go | 2 | ||||
| -rw-r--r-- | src/net/http/transport_test.go | 95 |
8 files changed, 156 insertions, 96 deletions
diff --git a/src/net/http/client_test.go b/src/net/http/client_test.go index 3d0f1aa6eb..bb4fb9db18 100644 --- a/src/net/http/client_test.go +++ b/src/net/http/client_test.go @@ -359,7 +359,7 @@ func TestPostRedirects(t *testing.T) { want := strings.Join(wantSegments, "\n") run(t, func(t *testing.T, mode testMode) { testRedirectsByMethod(t, mode, "POST", postRedirectTests, want) - }) + }, http3SkippedMode) } func TestDeleteRedirects(t *testing.T) { @@ -398,7 +398,7 @@ func TestDeleteRedirects(t *testing.T) { want := strings.Join(wantSegments, "\n") run(t, func(t *testing.T, mode testMode) { testRedirectsByMethod(t, mode, "DELETE", deleteRedirectTests, want) - }) + }, http3SkippedMode) } func testRedirectsByMethod(t *testing.T, mode testMode, method string, table []redirectTest, want string) { @@ -1201,7 +1201,7 @@ func TestStripPasswordFromError(t *testing.T) { } } -func TestClientTimeout(t *testing.T) { run(t, testClientTimeout) } +func TestClientTimeout(t *testing.T) { run(t, testClientTimeout, http3SkippedMode) } func testClientTimeout(t *testing.T, mode testMode) { var ( mu sync.Mutex @@ -1302,7 +1302,11 @@ func testClientTimeout(t *testing.T, mode testMode) { } // Client.Timeout firing before getting to the body -func TestClientTimeout_Headers(t *testing.T) { run(t, testClientTimeout_Headers) } +func TestClientTimeout_Headers(t *testing.T) { + // Running this test against our HTTP/3 implementation with race detector + // trips off TestMain's goroutine leak detection. + run(t, testClientTimeout_Headers, http3SkippedMode) +} func testClientTimeout_Headers(t *testing.T, mode testMode) { donec := make(chan bool, 1) cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) { @@ -1346,7 +1350,7 @@ func testClientTimeout_Headers(t *testing.T, mode testMode) { // Issue 16094: if Client.Timeout is set but not hit, a Timeout error shouldn't be // returned. -func TestClientTimeoutCancel(t *testing.T) { run(t, testClientTimeoutCancel) } +func TestClientTimeoutCancel(t *testing.T) { run(t, testClientTimeoutCancel, http3SkippedMode) } func testClientTimeoutCancel(t *testing.T, mode testMode) { testDone := make(chan struct{}) ctx, cancel := context.WithCancel(context.Background()) @@ -1511,7 +1515,9 @@ func TestClientRedirectResponseWithoutRequest(t *testing.T) { // Issue 35104: Since both URLs have the same host (localhost) // but different ports, sensitive headers like Cookie and Authorization // are preserved. -func TestClientCopyHeadersOnRedirect(t *testing.T) { run(t, testClientCopyHeadersOnRedirect) } +func TestClientCopyHeadersOnRedirect(t *testing.T) { + run(t, testClientCopyHeadersOnRedirect, http3SkippedMode) +} func testClientCopyHeadersOnRedirect(t *testing.T, mode testMode) { const ( ua = "some-agent/1.2" @@ -1577,7 +1583,7 @@ func testClientCopyHeadersOnRedirect(t *testing.T, mode testMode) { // Issue #70530: Once we strip a header on a redirect to a different host, // the header should stay stripped across any further redirects. func TestClientStripHeadersOnRepeatedRedirect(t *testing.T) { - run(t, testClientStripHeadersOnRepeatedRedirect) + run(t, testClientStripHeadersOnRepeatedRedirect, http3SkippedMode) } func testClientStripHeadersOnRepeatedRedirect(t *testing.T, mode testMode) { var proto string @@ -2220,7 +2226,10 @@ func TestClientPopulatesNilResponseBody(t *testing.T) { } // Issue 40382: Client calls Close multiple times on Request.Body. -func TestClientCallsCloseOnlyOnce(t *testing.T) { run(t, testClientCallsCloseOnlyOnce) } +func TestClientCallsCloseOnlyOnce(t *testing.T) { + // Trips off race detector for HTTP/3. + run(t, testClientCallsCloseOnlyOnce, http3SkippedMode) +} func testClientCallsCloseOnlyOnce(t *testing.T, mode testMode) { cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) { w.WriteHeader(StatusNoContent) diff --git a/src/net/http/clientconn_test.go b/src/net/http/clientconn_test.go index 1027d75fed..df1e2ed4e3 100644 --- a/src/net/http/clientconn_test.go +++ b/src/net/http/clientconn_test.go @@ -16,7 +16,7 @@ import ( "time" ) -func TestTransportNewClientConnRoundTrip(t *testing.T) { run(t, testTransportNewClientConnRoundTrip) } +func TestTransportNewClientConnRoundTrip(t *testing.T) { run(t, testTransportNewClientConnRoundTrip, http3SkippedMode) } func testTransportNewClientConnRoundTrip(t *testing.T, mode testMode) { cst := newClientServerTest(t, mode, http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { io.WriteString(w, req.Host) @@ -82,7 +82,7 @@ func newClientConnTest(t testing.TB, mode testMode, h http.HandlerFunc, opts ... } // TestClientConnReserveAll reserves every concurrency slot on a connection. -func TestClientConnReserveAll(t *testing.T) { runSynctest(t, testClientConnReserveAll) } +func TestClientConnReserveAll(t *testing.T) { runSynctest(t, testClientConnReserveAll, http3SkippedMode) } func testClientConnReserveAll(t *testing.T, mode testMode) { cst, cc := newClientConnTest(t, mode, nil, optFakeNet, func(s *http.Server) { s.HTTP2 = &http.HTTP2Config{ @@ -121,7 +121,7 @@ func testClientConnReserveAll(t *testing.T, mode testMode) { // TestClientConnReserveParallel starts concurrent goroutines which reserve every // concurrency slot on a connection. -func TestClientConnReserveParallel(t *testing.T) { runSynctest(t, testClientConnReserveParallel) } +func TestClientConnReserveParallel(t *testing.T) { runSynctest(t, testClientConnReserveParallel, http3SkippedMode) } func testClientConnReserveParallel(t *testing.T, mode testMode) { _, cc := newClientConnTest(t, mode, nil, optFakeNet, func(s *http.Server) { s.HTTP2 = &http.HTTP2Config{ @@ -159,7 +159,7 @@ func testClientConnReserveParallel(t *testing.T, mode testMode) { } // TestClientConnReserveRelease repeatedly reserves and releases concurrency slots. -func TestClientConnReserveRelease(t *testing.T) { runSynctest(t, testClientConnReserveRelease) } +func TestClientConnReserveRelease(t *testing.T) { runSynctest(t, testClientConnReserveRelease, http3SkippedMode) } func testClientConnReserveRelease(t *testing.T, mode testMode) { _, cc := newClientConnTest(t, mode, nil, optFakeNet, func(s *http.Server) { s.HTTP2 = &http.HTTP2Config{ @@ -323,7 +323,7 @@ func TestClientConnReserveAndConsume(t *testing.T) { t.Errorf("cc.Reserve() = %v, want success", err) } } - }) + }, http3SkippedMode) }) } @@ -331,7 +331,7 @@ func TestClientConnReserveAndConsume(t *testing.T) { // TestClientConnRoundTripBlocks verifies that RoundTrip blocks until a concurrency // slot is available on a connection. -func TestClientConnRoundTripBlocks(t *testing.T) { runSynctest(t, testClientConnRoundTripBlocks) } +func TestClientConnRoundTripBlocks(t *testing.T) { runSynctest(t, testClientConnRoundTripBlocks, http3SkippedMode) } func testClientConnRoundTripBlocks(t *testing.T, mode testMode) { var handlerCalls atomic.Int64 requestc := make(chan struct{}) diff --git a/src/net/http/clientserver_test.go b/src/net/http/clientserver_test.go index aadd8e3dc0..ca68096e2b 100644 --- a/src/net/http/clientserver_test.go +++ b/src/net/http/clientserver_test.go @@ -57,6 +57,15 @@ const ( http3Mode = testMode("h3") // HTTP/3 ) +// http3SkippedMode is a convenient alias for []testMode{http1Mode, http2Mode}, +// which was the default test mode used by run and runSynctest prior to HTTP/3 +// development. +// As we work on getting net/http tests to pass for our x/net HTTP/3 +// implementation, tests that still use http3SkippedMode are essentially a list +// of TODOs on what work needs to be done for our HTTP/3 implementation to +// reach basic feature parity with our HTTP/1 and HTTP/2 implementations +var http3SkippedMode = []testMode{http1Mode, http2Mode} + func (m testMode) Scheme() string { switch m { case http1Mode, http2UnencryptedMode: @@ -87,7 +96,7 @@ type TBRun[T any] interface { // To disable parallel execution, pass the testNotParallel option. func run[T TBRun[T]](t T, f func(t T, mode testMode), opts ...any) { t.Helper() - modes := []testMode{http1Mode, http2Mode} + modes := []testMode{http1Mode, http2Mode, http3Mode} parallel := true for _, opt := range opts { switch opt := opt.(type) { @@ -357,7 +366,9 @@ func testNewClientServerTest(t *testing.T, mode testMode, opts ...any) { } } -func TestChunkedResponseHeaders(t *testing.T) { run(t, testChunkedResponseHeaders) } +func TestChunkedResponseHeaders(t *testing.T) { + run(t, testChunkedResponseHeaders, http3SkippedMode) +} func testChunkedResponseHeaders(t *testing.T, mode testMode) { log.SetOutput(io.Discard) // is noisy otherwise defer log.SetOutput(os.Stderr) @@ -745,7 +756,7 @@ func h12requestContentLength(t *testing.T, bodyfn func() io.Reader, wantLen int6 // Tests that closing the Request.Cancel channel also while still // reading the response body. Issue 13159. -func TestCancelRequestMidBody(t *testing.T) { run(t, testCancelRequestMidBody) } +func TestCancelRequestMidBody(t *testing.T) { run(t, testCancelRequestMidBody, http3SkippedMode) } func testCancelRequestMidBody(t *testing.T, mode testMode) { unblock := make(chan bool) didFlush := make(chan bool, 1) @@ -840,7 +851,7 @@ func testTrailersClientToServer(t *testing.T, mode testMode) { func TestTrailersServerToClient(t *testing.T) { run(t, func(t *testing.T, mode testMode) { testTrailersServerToClient(t, mode, false) - }) + }, http3SkippedMode) } func TestTrailersServerToClientFlush(t *testing.T) { run(t, func(t *testing.T, mode testMode) { @@ -1039,7 +1050,7 @@ func testConnectRequest(t *testing.T, mode testMode) { } } -func TestTransportUserAgent(t *testing.T) { run(t, testTransportUserAgent) } +func TestTransportUserAgent(t *testing.T) { run(t, testTransportUserAgent, http3SkippedMode) } func testTransportUserAgent(t *testing.T, mode testMode) { cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) { fmt.Fprintf(w, "%q", r.Header["User-Agent"]) @@ -1297,7 +1308,9 @@ func testTransportGCRequest(t *testing.T, mode testMode, body bool) { } } -func TestTransportRejectsInvalidHeaders(t *testing.T) { run(t, testTransportRejectsInvalidHeaders) } +func TestTransportRejectsInvalidHeaders(t *testing.T) { + run(t, testTransportRejectsInvalidHeaders, http3SkippedMode) +} func testTransportRejectsInvalidHeaders(t *testing.T, mode testMode) { cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) { fmt.Fprintf(w, "Handler saw headers: %q", r.Header) @@ -1352,7 +1365,7 @@ func TestInterruptWithPanic(t *testing.T) { t.Run("boom", func(t *testing.T) { testInterruptWithPanic(t, mode, "boom") }) t.Run("nil", func(t *testing.T) { t.Setenv("GODEBUG", "panicnil=1"); testInterruptWithPanic(t, mode, nil) }) t.Run("ErrAbortHandler", func(t *testing.T) { testInterruptWithPanic(t, mode, ErrAbortHandler) }) - }, testNotParallel) + }, testNotParallel, http3SkippedMode) } func testInterruptWithPanic(t *testing.T, mode testMode, panicValue any) { const msg = "hello" @@ -1525,7 +1538,9 @@ func testNoSniffExpectRequestBody(t *testing.T, mode testMode) { } } -func TestServerUndeclaredTrailers(t *testing.T) { run(t, testServerUndeclaredTrailers) } +func TestServerUndeclaredTrailers(t *testing.T) { + run(t, testServerUndeclaredTrailers, http3SkippedMode) +} func testServerUndeclaredTrailers(t *testing.T, mode testMode) { cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) { w.Header().Set("Foo", "Bar") @@ -1620,7 +1635,7 @@ func testWriteHeader0(t *testing.T, mode testMode) { func TestWriteHeaderNoCodeCheck(t *testing.T) { run(t, func(t *testing.T, mode testMode) { testWriteHeaderAfterWrite(t, mode, false) - }) + }, http3SkippedMode) } func TestWriteHeaderNoCodeCheck_h1hijack(t *testing.T) { testWriteHeaderAfterWrite(t, http1Mode, true) diff --git a/src/net/http/fs_test.go b/src/net/http/fs_test.go index 32fb696fee..2dc03e13ff 100644 --- a/src/net/http/fs_test.go +++ b/src/net/http/fs_test.go @@ -709,7 +709,7 @@ func testServeIndexHtmlFS(t *testing.T, mode testMode) { } } -func TestFileServerZeroByte(t *testing.T) { run(t, testFileServerZeroByte) } +func TestFileServerZeroByte(t *testing.T) { run(t, testFileServerZeroByte, http3SkippedMode) } func testFileServerZeroByte(t *testing.T, mode testMode) { ts := newClientServerTest(t, mode, FileServer(Dir("."))).ts @@ -842,7 +842,10 @@ func (fsys fakeFS) Open(name string) (File, error) { return &fakeFile{ReadSeeker: strings.NewReader(f.contents), fi: f, path: name}, nil } -func TestDirectoryIfNotModified(t *testing.T) { run(t, testDirectoryIfNotModified) } +func TestDirectoryIfNotModified(t *testing.T) { + // HTTP/3 trips off race detector. + run(t, testDirectoryIfNotModified, http3SkippedMode) +} func testDirectoryIfNotModified(t *testing.T, mode testMode) { const indexContents = "I am a fake index.html file" fileMod := time.Unix(1000000000, 0).UTC() @@ -916,7 +919,10 @@ func mustStat(t *testing.T, fileName string) fs.FileInfo { return fi } -func TestServeContent(t *testing.T) { run(t, testServeContent) } +func TestServeContent(t *testing.T) { + // HTTP/3 trips off race detector. + run(t, testServeContent, http3SkippedMode) +} func testServeContent(t *testing.T, mode testMode) { type serveParam struct { name string diff --git a/src/net/http/responsecontroller_test.go b/src/net/http/responsecontroller_test.go index a217891026..2c85589b91 100644 --- a/src/net/http/responsecontroller_test.go +++ b/src/net/http/responsecontroller_test.go @@ -48,7 +48,7 @@ func testResponseControllerFlush(t *testing.T, mode testMode) { } } -func TestResponseControllerHijack(t *testing.T) { run(t, testResponseControllerHijack) } +func TestResponseControllerHijack(t *testing.T) { run(t, testResponseControllerHijack, http3SkippedMode) } func testResponseControllerHijack(t *testing.T, mode testMode) { const header = "X-Header" const value = "set" @@ -78,7 +78,7 @@ func testResponseControllerHijack(t *testing.T, mode testMode) { } func TestResponseControllerSetPastWriteDeadline(t *testing.T) { - run(t, testResponseControllerSetPastWriteDeadline) + run(t, testResponseControllerSetPastWriteDeadline, http3SkippedMode) } func testResponseControllerSetPastWriteDeadline(t *testing.T, mode testMode) { cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) { @@ -120,7 +120,7 @@ func testResponseControllerSetPastWriteDeadline(t *testing.T, mode testMode) { } func TestResponseControllerSetFutureWriteDeadline(t *testing.T) { - run(t, testResponseControllerSetFutureWriteDeadline) + run(t, testResponseControllerSetFutureWriteDeadline, http3SkippedMode) } func testResponseControllerSetFutureWriteDeadline(t *testing.T, mode testMode) { errc := make(chan error, 1) @@ -156,7 +156,7 @@ func testResponseControllerSetFutureWriteDeadline(t *testing.T, mode testMode) { } func TestResponseControllerSetPastReadDeadline(t *testing.T) { - run(t, testResponseControllerSetPastReadDeadline) + run(t, testResponseControllerSetPastReadDeadline, http3SkippedMode) } func testResponseControllerSetPastReadDeadline(t *testing.T, mode testMode) { readc := make(chan struct{}) @@ -220,7 +220,7 @@ func testResponseControllerSetPastReadDeadline(t *testing.T, mode testMode) { } func TestResponseControllerSetFutureReadDeadline(t *testing.T) { - run(t, testResponseControllerSetFutureReadDeadline) + run(t, testResponseControllerSetFutureReadDeadline, http3SkippedMode) } func testResponseControllerSetFutureReadDeadline(t *testing.T, mode testMode) { respBody := "response body" @@ -256,7 +256,7 @@ func (w wrapWriter) Unwrap() ResponseWriter { return w.ResponseWriter } -func TestWrappedResponseController(t *testing.T) { run(t, testWrappedResponseController) } +func TestWrappedResponseController(t *testing.T) { run(t, testWrappedResponseController, http3SkippedMode) } func testWrappedResponseController(t *testing.T, mode testMode) { cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) { w = wrapWriter{w} @@ -280,7 +280,7 @@ func testWrappedResponseController(t *testing.T, mode testMode) { } func TestResponseControllerEnableFullDuplex(t *testing.T) { - run(t, testResponseControllerEnableFullDuplex) + run(t, testResponseControllerEnableFullDuplex, http3SkippedMode) } func testResponseControllerEnableFullDuplex(t *testing.T, mode testMode) { cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, req *Request) { diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go index f2ba8705d1..d9a1898cc9 100644 --- a/src/net/http/serve_test.go +++ b/src/net/http/serve_test.go @@ -815,7 +815,7 @@ func testServerTimeoutsWithTimeout(t *testing.T, timeout time.Duration, mode tes return nil } -func TestServerReadTimeout(t *testing.T) { run(t, testServerReadTimeout) } +func TestServerReadTimeout(t *testing.T) { run(t, testServerReadTimeout, http3SkippedMode) } func testServerReadTimeout(t *testing.T, mode testMode) { respBody := "response body" for timeout := 5 * time.Millisecond; ; timeout *= 2 { @@ -900,7 +900,7 @@ func testServerNoReadTimeout(t *testing.T, mode testMode) { } } -func TestServerWriteTimeout(t *testing.T) { run(t, testServerWriteTimeout) } +func TestServerWriteTimeout(t *testing.T) { run(t, testServerWriteTimeout, http3SkippedMode) } func testServerWriteTimeout(t *testing.T, mode testMode) { for timeout := 5 * time.Millisecond; ; timeout *= 2 { errc := make(chan error, 2) @@ -965,7 +965,10 @@ func testServerWriteTimeout(t *testing.T, mode testMode) { } } -func TestServerNoWriteTimeout(t *testing.T) { run(t, testServerNoWriteTimeout) } +func TestServerNoWriteTimeout(t *testing.T) { + // Trips off race detector for HTTP/3. + run(t, testServerNoWriteTimeout, http3SkippedMode) +} func testServerNoWriteTimeout(t *testing.T, mode testMode) { for _, timeout := range []time.Duration{0, -1} { cst := newClientServerTest(t, mode, HandlerFunc(func(res ResponseWriter, req *Request) { @@ -1050,7 +1053,7 @@ func TestWriteDeadlineEnforcedPerStream(t *testing.T) { tryTimeouts(t, func(timeout time.Duration) error { return testWriteDeadlineEnforcedPerStream(t, mode, timeout) }) - }) + }, http3SkippedMode) } func testWriteDeadlineEnforcedPerStream(t *testing.T, mode testMode, timeout time.Duration) error { @@ -1548,7 +1551,7 @@ func testServerAllowsBlockingRemoteAddr(t *testing.T, mode testMode) { // TestHeadResponses verifies that all MIME type sniffing and Content-Length // counting of GET requests also happens on HEAD requests. -func TestHeadResponses(t *testing.T) { run(t, testHeadResponses) } +func TestHeadResponses(t *testing.T) { run(t, testHeadResponses, http3SkippedMode) } func testHeadResponses(t *testing.T, mode testMode) { cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) { _, err := w.Write([]byte("<html>")) @@ -2920,7 +2923,7 @@ func TestTimeoutHandlerPanicRecovery(t *testing.T) { } run(t, func(t *testing.T, mode testMode) { testHandlerPanic(t, false, mode, wrapper, "intentional death for testing") - }, testNotParallel) + }, testNotParallel, http3SkippedMode) } func TestRedirectBadPath(t *testing.T) { @@ -3093,13 +3096,13 @@ func testZeroLengthPostAndResponse(t *testing.T, mode testMode) { func TestHandlerPanicNil(t *testing.T) { run(t, func(t *testing.T, mode testMode) { testHandlerPanic(t, false, mode, nil, nil) - }, testNotParallel) + }, testNotParallel, http3SkippedMode) } func TestHandlerPanic(t *testing.T) { run(t, func(t *testing.T, mode testMode) { testHandlerPanic(t, false, mode, nil, "intentional death for testing") - }, testNotParallel) + }, testNotParallel, http3SkippedMode) } func TestHandlerPanicWithHijack(t *testing.T) { @@ -3285,7 +3288,7 @@ func TestStripPrefixNotModifyRequest(t *testing.T) { } } -func TestRequestLimit(t *testing.T) { run(t, testRequestLimit) } +func TestRequestLimit(t *testing.T) { run(t, testRequestLimit, http3SkippedMode) } func testRequestLimit(t *testing.T, mode testMode) { cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) { t.Fatalf("didn't expect to get request in Handler") @@ -3362,7 +3365,10 @@ func (r *bodyLimitReader) Close() error { return nil } -func TestRequestBodyLimit(t *testing.T) { run(t, testRequestBodyLimit) } +func TestRequestBodyLimit(t *testing.T) { + // Trips off race detector for HTTP/3. + run(t, testRequestBodyLimit, http3SkippedMode) +} func testRequestBodyLimit(t *testing.T, mode testMode) { const limit = 1 << 20 cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) { @@ -3414,7 +3420,7 @@ func testRequestBodyLimit(t *testing.T, mode testMode) { // TestClientWriteShutdown tests that if the client shuts down the write // side of their TCP connection, the server doesn't send a 400 Bad Request. -func TestClientWriteShutdown(t *testing.T) { run(t, testClientWriteShutdown) } +func TestClientWriteShutdown(t *testing.T) { run(t, testClientWriteShutdown, http3SkippedMode) } func testClientWriteShutdown(t *testing.T, mode testMode) { if runtime.GOOS == "plan9" { t.Skip("skipping test; see https://golang.org/issue/17906") @@ -4310,7 +4316,7 @@ func TestContentTypeOkayOn204(t *testing.T) { // 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) { - run(t, testTransportAndServerSharedBodyRace, testNotParallel) + run(t, testTransportAndServerSharedBodyRace, testNotParallel, http3SkippedMode) } func testTransportAndServerSharedBodyRace(t *testing.T, mode testMode) { // The proxy server in the middle of the stack for this test potentially @@ -5178,7 +5184,7 @@ func TestServerValidatesHeaders(t *testing.T) { } func TestServerRequestContextCancel_ServeHTTPDone(t *testing.T) { - run(t, testServerRequestContextCancel_ServeHTTPDone) + run(t, testServerRequestContextCancel_ServeHTTPDone, http3SkippedMode) } func testServerRequestContextCancel_ServeHTTPDone(t *testing.T, mode testMode) { ctxc := make(chan context.Context, 1) @@ -5231,7 +5237,7 @@ func testServerRequestContextCancel_ConnClose(t *testing.T, mode testMode) { } func TestServerContext_ServerContextKey(t *testing.T) { - run(t, testServerContext_ServerContextKey) + run(t, testServerContext_ServerContextKey, http3SkippedMode) } func testServerContext_ServerContextKey(t *testing.T, mode testMode) { cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) { @@ -5249,7 +5255,7 @@ func testServerContext_ServerContextKey(t *testing.T, mode testMode) { } func TestServerContext_LocalAddrContextKey(t *testing.T) { - run(t, testServerContext_LocalAddrContextKey) + run(t, testServerContext_LocalAddrContextKey, http3SkippedMode) } func testServerContext_LocalAddrContextKey(t *testing.T, mode testMode) { ch := make(chan any, 1) @@ -5944,7 +5950,7 @@ func testServerSetKeepAlivesEnabledClosesConns(t *testing.T, mode testMode) { // exact same ports from the previous connection. } -func TestServerShutdown(t *testing.T) { run(t, testServerShutdown) } +func TestServerShutdown(t *testing.T) { run(t, testServerShutdown, http3SkippedMode) } func testServerShutdown(t *testing.T, mode testMode) { var cst *clientServerTest @@ -6005,7 +6011,9 @@ func testServerShutdown(t *testing.T, mode testMode) { } } -func TestServerShutdownStateNew(t *testing.T) { runSynctest(t, testServerShutdownStateNew) } +func TestServerShutdownStateNew(t *testing.T) { + runSynctest(t, testServerShutdownStateNew, http3SkippedMode) +} func testServerShutdownStateNew(t *testing.T, mode testMode) { if testing.Short() { t.Skip("test takes 5-6 seconds; skipping in short mode") @@ -6070,7 +6078,9 @@ func TestServerCloseDeadlock(t *testing.T) { // Issue 17717: tests that Server.SetKeepAlivesEnabled is respected by // both HTTP/1 and HTTP/2. -func TestServerKeepAlivesEnabled(t *testing.T) { runSynctest(t, testServerKeepAlivesEnabled) } +func TestServerKeepAlivesEnabled(t *testing.T) { + runSynctest(t, testServerKeepAlivesEnabled, http3SkippedMode) +} func testServerKeepAlivesEnabled(t *testing.T, mode testMode) { cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {}), optFakeNet) defer cst.close() @@ -6556,7 +6566,7 @@ func TestStripPortFromHost(t *testing.T) { } } -func TestServerContexts(t *testing.T) { run(t, testServerContexts) } +func TestServerContexts(t *testing.T) { run(t, testServerContexts, http3SkippedMode) } func testServerContexts(t *testing.T, mode testMode) { type baseKey struct{} type connKey struct{} @@ -6668,7 +6678,9 @@ func testUnsupportedTransferEncodingsReturn501(t *testing.T, mode testMode) { } // Issue 31753: don't sniff when Content-Encoding is set -func TestContentEncodingNoSniffing(t *testing.T) { run(t, testContentEncodingNoSniffing) } +func TestContentEncodingNoSniffing(t *testing.T) { + run(t, testContentEncodingNoSniffing, http3SkippedMode) +} func testContentEncodingNoSniffing(t *testing.T, mode testMode) { type setting struct { name string @@ -7111,6 +7123,7 @@ func testQuerySemicolon(t *testing.T, mode testMode, query string, wantX string, } } +// HTTP/3 trips off race detector. func TestMaxBytesHandler(t *testing.T) { // Not parallel: modifies the global rstAvoidanceDelay. defer afterTest(t) @@ -7121,7 +7134,7 @@ func TestMaxBytesHandler(t *testing.T) { func(t *testing.T) { run(t, func(t *testing.T, mode testMode) { testMaxBytesHandler(t, mode, maxSize, requestSize) - }, testNotParallel) + }, testNotParallel, http3SkippedMode) }) } } @@ -7248,7 +7261,7 @@ func TestProcessing(t *testing.T) { } } -func TestParseFormCleanup(t *testing.T) { run(t, testParseFormCleanup) } +func TestParseFormCleanup(t *testing.T) { run(t, testParseFormCleanup, http3SkippedMode) } func testParseFormCleanup(t *testing.T, mode testMode) { if mode == http2Mode { t.Skip("https://go.dev/issue/20253") @@ -7371,7 +7384,7 @@ func testHeadBody(t *testing.T, mode testMode, chunked bool, method string) { // TestDisableContentLength verifies that the Content-Length is set by default // or disabled when the header is set to nil. -func TestDisableContentLength(t *testing.T) { run(t, testDisableContentLength) } +func TestDisableContentLength(t *testing.T) { run(t, testDisableContentLength, http3SkippedMode) } func testDisableContentLength(t *testing.T, mode testMode) { noCL := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) { w.Header()["Content-Length"] = nil // disable the default Content-Length response diff --git a/src/net/http/sniff_test.go b/src/net/http/sniff_test.go index 68c8a6af1e..4019ab522d 100644 --- a/src/net/http/sniff_test.go +++ b/src/net/http/sniff_test.go @@ -166,7 +166,7 @@ func (b *byteAtATimeReader) Read(p []byte) (n int, err error) { return 1, nil } -func TestContentTypeWithVariousSources(t *testing.T) { run(t, testContentTypeWithVariousSources) } +func TestContentTypeWithVariousSources(t *testing.T) { run(t, testContentTypeWithVariousSources, http3SkippedMode) } func testContentTypeWithVariousSources(t *testing.T, mode testMode) { const ( input = "\n<html>\n\t<head>\n" diff --git a/src/net/http/transport_test.go b/src/net/http/transport_test.go index ea9a19ac9a..82e621775f 100644 --- a/src/net/http/transport_test.go +++ b/src/net/http/transport_test.go @@ -200,7 +200,7 @@ func testTransportKeepAlives(t *testing.T, mode testMode) { } func TestTransportConnectionCloseOnResponse(t *testing.T) { - run(t, testTransportConnectionCloseOnResponse) + run(t, testTransportConnectionCloseOnResponse, http3SkippedMode) } func testTransportConnectionCloseOnResponse(t *testing.T, mode testMode) { ts := newClientServerTest(t, mode, hostPortHandler).ts @@ -428,7 +428,10 @@ func testTransportIdleCacheKeys(t *testing.T, mode testMode) { // Tests that the HTTP transport re-uses connections when a client // reads to the end of a response Body without closing it. -func TestTransportReadToEndReusesConn(t *testing.T) { run(t, testTransportReadToEndReusesConn) } +func TestTransportReadToEndReusesConn(t *testing.T) { + // HTTP/3 trips off race detector. + run(t, testTransportReadToEndReusesConn, http3SkippedMode) +} func testTransportReadToEndReusesConn(t *testing.T, mode testMode) { const msg = "foobar" @@ -678,7 +681,7 @@ func testTransportMaxPerHostIdleConns(t *testing.T, mode testMode) { } func TestTransportMaxConnsPerHostIncludeDialInProgress(t *testing.T) { - run(t, testTransportMaxConnsPerHostIncludeDialInProgress) + run(t, testTransportMaxConnsPerHostIncludeDialInProgress, http3SkippedMode) } func testTransportMaxConnsPerHostIncludeDialInProgress(t *testing.T, mode testMode) { ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) { @@ -1143,7 +1146,7 @@ var roundTripTests = []struct { } // Test that the modification made to the Request by the RoundTripper is cleaned up -func TestRoundTripGzip(t *testing.T) { run(t, testRoundTripGzip) } +func TestRoundTripGzip(t *testing.T) { run(t, testRoundTripGzip, http3SkippedMode) } func testRoundTripGzip(t *testing.T, mode testMode) { const responseBody = "test response body" ts := newClientServerTest(t, mode, HandlerFunc(func(rw ResponseWriter, req *Request) { @@ -1205,11 +1208,8 @@ func testRoundTripGzip(t *testing.T, mode testMode) { } -func TestTransportGzip(t *testing.T) { run(t, testTransportGzip) } +func TestTransportGzip(t *testing.T) { run(t, testTransportGzip, http3SkippedMode) } func testTransportGzip(t *testing.T, mode testMode) { - if mode == http2Mode { - t.Skip("https://go.dev/issue/56020") - } const testString = "The test string aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" const nRandBytes = 1024 * 1024 ts := newClientServerTest(t, mode, HandlerFunc(func(rw ResponseWriter, req *Request) { @@ -1975,7 +1975,7 @@ func TestTransportDialPreservesNetOpProxyError(t *testing.T) { // (A bug caused dialConn to instead write the per-request Proxy-Authorization // header through to the shared Header instance, introducing a data race.) func TestTransportProxyDialDoesNotMutateProxyConnectHeader(t *testing.T) { - run(t, testTransportProxyDialDoesNotMutateProxyConnectHeader) + run(t, testTransportProxyDialDoesNotMutateProxyConnectHeader, http3SkippedMode) } func testTransportProxyDialDoesNotMutateProxyConnectHeader(t *testing.T, mode testMode) { proxy := newClientServerTest(t, mode, NotFoundHandler()).ts @@ -2012,7 +2012,7 @@ func testTransportProxyDialDoesNotMutateProxyConnectHeader(t *testing.T, mode te // client gets the same value back. This is more cute than anything, // but checks that we don't recurse forever, and checks that // Content-Encoding is removed. -func TestTransportGzipRecursive(t *testing.T) { run(t, testTransportGzipRecursive) } +func TestTransportGzipRecursive(t *testing.T) { run(t, testTransportGzipRecursive, http3SkippedMode) } func testTransportGzipRecursive(t *testing.T, mode testMode) { ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) { w.Header().Set("Content-Encoding", "gzip") @@ -2039,7 +2039,7 @@ func testTransportGzipRecursive(t *testing.T, mode testMode) { // golang.org/issue/7750: request fails when server replies with // a short gzip body -func TestTransportGzipShort(t *testing.T) { run(t, testTransportGzipShort) } +func TestTransportGzipShort(t *testing.T) { run(t, testTransportGzipShort, http3SkippedMode) } func testTransportGzipShort(t *testing.T, mode testMode) { ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) { w.Header().Set("Content-Encoding", "gzip") @@ -2077,11 +2077,11 @@ func TestTransportPersistConnLeak(t *testing.T) { run(t, testTransportPersistConnLeak, testNotParallel) } func testTransportPersistConnLeak(t *testing.T, mode testMode) { - if mode == http2Mode { - t.Skip("flaky in HTTP/2") + if mode == http2Mode || mode == http3Mode { + t.Skip("flaky in HTTP/2 and HTTP/3") } - // Not parallel: counts goroutines + // Not parallel: counts goroutines const numReq = 25 gotReqCh := make(chan bool, numReq) unblockCh := make(chan bool, numReq) @@ -2151,8 +2151,8 @@ func TestTransportPersistConnLeakShortBody(t *testing.T) { run(t, testTransportPersistConnLeakShortBody, testNotParallel) } func testTransportPersistConnLeakShortBody(t *testing.T, mode testMode) { - if mode == http2Mode { - t.Skip("flaky in HTTP/2") + if mode == http2Mode || mode == http3Mode { + t.Skip("flaky in HTTP/2 and HTTP/3") } // Not parallel: measures goroutines. @@ -2303,7 +2303,7 @@ func (cc *contextCounter) Read() (live int64) { } func TestTransportPersistConnContextLeakMaxConnsPerHost(t *testing.T) { - run(t, testTransportPersistConnContextLeakMaxConnsPerHost) + run(t, testTransportPersistConnContextLeakMaxConnsPerHost, http3SkippedMode) } func testTransportPersistConnContextLeakMaxConnsPerHost(t *testing.T, mode testMode) { if mode == http2Mode { @@ -2363,7 +2363,7 @@ func testTransportPersistConnContextLeakMaxConnsPerHost(t *testing.T, mode testM } // This used to crash; https://golang.org/issue/3266 -func TestTransportIdleConnCrash(t *testing.T) { run(t, testTransportIdleConnCrash) } +func TestTransportIdleConnCrash(t *testing.T) { run(t, testTransportIdleConnCrash, http3SkippedMode) } func testTransportIdleConnCrash(t *testing.T, mode testMode) { var tr *Transport @@ -2421,7 +2421,8 @@ func testIssue3644(t *testing.T, mode testMode) { // the entire request body. func TestIssue3595(t *testing.T) { // Not parallel: modifies the global rstAvoidanceDelay. - run(t, testIssue3595, testNotParallel) + // HTTP/3 fails on WASM. + run(t, testIssue3595, testNotParallel, http3SkippedMode) } func testIssue3595(t *testing.T, mode testMode) { runTimeSensitiveTest(t, []time.Duration{ @@ -2552,7 +2553,9 @@ func testTransportConcurrency(t *testing.T, mode testMode) { wg.Wait() } -func TestIssue4191_InfiniteGetTimeout(t *testing.T) { run(t, testIssue4191_InfiniteGetTimeout) } +func TestIssue4191_InfiniteGetTimeout(t *testing.T) { + run(t, testIssue4191_InfiniteGetTimeout, http3SkippedMode) +} func testIssue4191_InfiniteGetTimeout(t *testing.T, mode testMode) { mux := NewServeMux() mux.HandleFunc("/get", func(w ResponseWriter, r *Request) { @@ -2654,7 +2657,9 @@ func testIssue4191_InfiniteGetToPutTimeout(t *testing.T, mode testMode) { ts.Close() } -func TestTransportResponseHeaderTimeout(t *testing.T) { run(t, testTransportResponseHeaderTimeout) } +func TestTransportResponseHeaderTimeout(t *testing.T) { + run(t, testTransportResponseHeaderTimeout, http3SkippedMode) +} func testTransportResponseHeaderTimeout(t *testing.T, mode testMode) { if testing.Short() { t.Skip("skipping timeout test in -short mode") @@ -2822,7 +2827,7 @@ func runCancelTest(t *testing.T, f func(t *testing.T, test cancelTest), opts ... } func TestTransportCancelRequest(t *testing.T) { - runCancelTest(t, testTransportCancelRequest) + runCancelTest(t, testTransportCancelRequest, http3SkippedMode) } func testTransportCancelRequest(t *testing.T, test cancelTest) { if testing.Short() { @@ -2988,7 +2993,7 @@ Get error = true // Issue 51354 func TestTransportCancelRequestWithBody(t *testing.T) { - runCancelTest(t, testTransportCancelRequestWithBody) + runCancelTest(t, testTransportCancelRequestWithBody, http3SkippedMode) } func testTransportCancelRequestWithBody(t *testing.T, test cancelTest) { if testing.Short() { @@ -3051,7 +3056,7 @@ func TestTransportCancelRequestBeforeDo(t *testing.T) { t.Run("ContextCancel", func(t *testing.T) { runCancelTestContext(t, mode, testTransportCancelRequestBeforeDo) }) - }) + }, http3SkippedMode) } func testTransportCancelRequestBeforeDo(t *testing.T, test cancelTest) { unblockc := make(chan bool) @@ -3116,7 +3121,9 @@ func testTransportCancelRequestBeforeResponseHeaders(t *testing.T, test cancelTe // golang.org/issue/3672 -- Client can't close HTTP stream // Calling Close on a Response.Body used to just read until EOF. // Now it actually closes the TCP connection. -func TestTransportCloseResponseBody(t *testing.T) { run(t, testTransportCloseResponseBody) } +func TestTransportCloseResponseBody(t *testing.T) { + run(t, testTransportCloseResponseBody, http3SkippedMode) +} func testTransportCloseResponseBody(t *testing.T, mode testMode) { writeErr := make(chan error, 1) msg := []byte("young\n") @@ -3222,7 +3229,9 @@ func TestTransportEmptyMethod(t *testing.T) { } } -func TestTransportSocketLateBinding(t *testing.T) { run(t, testTransportSocketLateBinding) } +func TestTransportSocketLateBinding(t *testing.T) { + run(t, testTransportSocketLateBinding, http3SkippedMode) +} func testTransportSocketLateBinding(t *testing.T, mode testMode) { mux := NewServeMux() fooGate := make(chan bool, 1) @@ -3439,7 +3448,9 @@ func testTransportIgnore1xxResponses(t *testing.T, mode testMode) { } } -func TestTransportLimits1xxResponses(t *testing.T) { run(t, testTransportLimits1xxResponses) } +func TestTransportLimits1xxResponses(t *testing.T) { + run(t, testTransportLimits1xxResponses, http3SkippedMode) +} func testTransportLimits1xxResponses(t *testing.T, mode testMode) { cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) { w.Header().Add("X-Header", strings.Repeat("a", 100)) @@ -3469,7 +3480,7 @@ func testTransportLimits1xxResponses(t *testing.T, mode testMode) { } func TestTransportDoesNotLimitDelivered1xxResponses(t *testing.T) { - run(t, testTransportDoesNotLimitDelivered1xxResponses) + run(t, testTransportDoesNotLimitDelivered1xxResponses, http3SkippedMode) } func testTransportDoesNotLimitDelivered1xxResponses(t *testing.T, mode testMode) { if mode == http2Mode { @@ -4221,7 +4232,7 @@ func testTransportDialTLS(t *testing.T, mode testMode) { } } -func TestTransportDialContext(t *testing.T) { run(t, testTransportDialContext) } +func TestTransportDialContext(t *testing.T) { run(t, testTransportDialContext, http3SkippedMode) } func testTransportDialContext(t *testing.T, mode testMode) { ctxKey := "some-key" ctxValue := "some-value" @@ -4483,7 +4494,7 @@ func testTransportIdleConnRacesRequest(t *testing.T, mode testMode) { } func TestTransportRemovesConnsAfterIdle(t *testing.T) { - runSynctest(t, testTransportRemovesConnsAfterIdle) + runSynctest(t, testTransportRemovesConnsAfterIdle, http3SkippedMode) } func testTransportRemovesConnsAfterIdle(t *testing.T, mode testMode) { if testing.Short() { @@ -4529,7 +4540,7 @@ func testTransportRemovesConnsAfterIdle(t *testing.T, mode testMode) { } func TestTransportRemovesConnsAfterBroken(t *testing.T) { - runSynctest(t, testTransportRemovesConnsAfterBroken) + runSynctest(t, testTransportRemovesConnsAfterBroken, http3SkippedMode) } func testTransportRemovesConnsAfterBroken(t *testing.T, mode testMode) { if testing.Short() { @@ -4636,7 +4647,7 @@ func testTransportResponseCancelRace(t *testing.T, mode testMode) { // Test for issue 19248: Content-Encoding's value is case insensitive. func TestTransportContentEncodingCaseInsensitive(t *testing.T) { - run(t, testTransportContentEncodingCaseInsensitive) + run(t, testTransportContentEncodingCaseInsensitive, http3SkippedMode) } func testTransportContentEncodingCaseInsensitive(t *testing.T, mode testMode) { for _, ce := range []string{"gzip", "GZIP"} { @@ -4845,7 +4856,7 @@ func (c *wgReadCloser) Close() error { // Issue 11745. func TestTransportPrefersResponseOverWriteError(t *testing.T) { // Not parallel: modifies the global rstAvoidanceDelay. - run(t, testTransportPrefersResponseOverWriteError, testNotParallel) + run(t, testTransportPrefersResponseOverWriteError, testNotParallel, http3SkippedMode) } func testTransportPrefersResponseOverWriteError(t *testing.T, mode testMode) { if testing.Short() { @@ -5158,7 +5169,9 @@ func testTransportReuseConnection_Gzip(t *testing.T, mode testMode, chunked bool } } -func TestTransportResponseHeaderLength(t *testing.T) { run(t, testTransportResponseHeaderLength) } +func TestTransportResponseHeaderLength(t *testing.T) { + run(t, testTransportResponseHeaderLength, http3SkippedMode) +} func testTransportResponseHeaderLength(t *testing.T, mode testMode) { if mode == http2Mode { t.Skip("HTTP/2 Transport doesn't support MaxResponseHeaderBytes") @@ -5196,14 +5209,14 @@ func testTransportResponseHeaderLength(t *testing.T, mode testMode) { func TestTransportEventTrace(t *testing.T) { run(t, func(t *testing.T, mode testMode) { testTransportEventTrace(t, mode, false) - }, testNotParallel) + }, testNotParallel, http3SkippedMode) } // test a non-nil httptrace.ClientTrace but with all hooks set to zero. func TestTransportEventTrace_NoHooks(t *testing.T) { run(t, func(t *testing.T, mode testMode) { testTransportEventTrace(t, mode, true) - }, testNotParallel) + }, testNotParallel, http3SkippedMode) } func testTransportEventTrace(t *testing.T, mode testMode, noHooks bool) { @@ -5637,7 +5650,9 @@ func testTransportMaxIdleConns(t *testing.T, mode testMode) { } } -func TestTransportIdleConnTimeout(t *testing.T) { run(t, testTransportIdleConnTimeout) } +func TestTransportIdleConnTimeout(t *testing.T) { + run(t, testTransportIdleConnTimeout, http3SkippedMode) +} func testTransportIdleConnTimeout(t *testing.T, mode testMode) { if testing.Short() { t.Skip("skipping in short mode") @@ -5820,7 +5835,7 @@ func TestTransportReturnsPeekError(t *testing.T) { } // Issue 13835: international domain names should work -func TestTransportIDNA(t *testing.T) { run(t, testTransportIDNA) } +func TestTransportIDNA(t *testing.T) { run(t, testTransportIDNA, http3SkippedMode) } func testTransportIDNA(t *testing.T, mode testMode) { const uniDomain = "гофер.го" const punyDomain = "xn--c1ae0ajs.xn--c1aw" @@ -7293,7 +7308,9 @@ func testCancelRequestWhenSharingConnection(t *testing.T, mode testMode) { wg.Wait() } -func TestHandlerAbortRacesBodyRead(t *testing.T) { run(t, testHandlerAbortRacesBodyRead) } +func TestHandlerAbortRacesBodyRead(t *testing.T) { + run(t, testHandlerAbortRacesBodyRead, http3SkippedMode) +} func testHandlerAbortRacesBodyRead(t *testing.T, mode testMode) { ts := newClientServerTest(t, mode, HandlerFunc(func(rw ResponseWriter, req *Request) { go io.Copy(io.Discard, req.Body) |
