From ccf4ba99a90f6f1366daef776ae90187c9f3c6b1 Mon Sep 17 00:00:00 2001 From: "Nicholas S. Husin" Date: Mon, 30 Mar 2026 19:17:03 -0400 Subject: 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 LUCI-TryBot-Result: Go LUCI Reviewed-by: Nicholas Husin --- src/net/http/clientserver_test.go | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) (limited to 'src/net/http/clientserver_test.go') 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) -- cgit v1.3