From eea413e2942fbb59b323a2af0b1740da4d8aa93e Mon Sep 17 00:00:00 2001 From: "Nicholas S. Husin" Date: Thu, 8 Jan 2026 14:57:52 -0500 Subject: [PATCH] internal/http3: use go1.25 synctest.Test instead of go1.24 synctest.Run internal/http3 was written back in go1.24, and relies on synctest.Run and goexperiment.synctest. This prevents us from running tests with newer versions of Go. This CL updates the existing build constraint and synctest usages to go1.25 so we can still run tests using go1.25 and tip. Support for running synctest with go1.24 is not kept, since go1.26 release (and therefore x/net go.mod updating to go1.25) is expected soon. Change-Id: Iebfa82ebd1da4a06ba613ce0f45051f4691037fc Reviewed-on: https://go-review.googlesource.com/c/net/+/734940 Reviewed-by: Damien Neil Reviewed-by: Nicholas Husin LUCI-TryBot-Result: Go LUCI --- internal/http3/body.go | 2 - internal/http3/body_test.go | 4 +- internal/http3/conn.go | 2 - internal/http3/conn_test.go | 6 +-- internal/http3/errors.go | 2 - internal/http3/files_test.go | 22 ++++----- internal/http3/http3.go | 2 - internal/http3/http3_synctest_test.go | 64 --------------------------- internal/http3/http3_test.go | 11 ++++- internal/http3/qpack.go | 2 - internal/http3/qpack_decode.go | 2 - internal/http3/qpack_decode_test.go | 6 +-- internal/http3/qpack_encode.go | 2 - internal/http3/qpack_encode_test.go | 2 +- internal/http3/qpack_static.go | 2 - internal/http3/qpack_test.go | 2 +- internal/http3/quic.go | 2 - internal/http3/quic_test.go | 2 +- internal/http3/roundtrip.go | 2 - internal/http3/roundtrip_test.go | 22 ++++----- internal/http3/server.go | 2 - internal/http3/server_test.go | 6 +-- internal/http3/settings.go | 2 - internal/http3/stream.go | 2 - internal/http3/stream_test.go | 2 +- internal/http3/transport.go | 2 - internal/http3/transport_test.go | 4 +- 27 files changed, 47 insertions(+), 134 deletions(-) delete mode 100644 internal/http3/http3_synctest_test.go diff --git a/internal/http3/body.go b/internal/http3/body.go index cdde482e..868f85c4 100644 --- a/internal/http3/body.go +++ b/internal/http3/body.go @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build go1.24 - package http3 import ( diff --git a/internal/http3/body_test.go b/internal/http3/body_test.go index 599e0df8..c2288d3d 100644 --- a/internal/http3/body_test.go +++ b/internal/http3/body_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build go1.24 && goexperiment.synctest +//go:build go1.25 package http3 @@ -256,7 +256,7 @@ func TestReadData(t *testing.T) { } - runSynctestSubtest(t, test.name+"/client", func(t testing.TB) { + synctestSubtest(t, test.name+"/client", func(t *testing.T) { tc := newTestClientConn(t) tc.greet() diff --git a/internal/http3/conn.go b/internal/http3/conn.go index 5eb80311..6a3c962b 100644 --- a/internal/http3/conn.go +++ b/internal/http3/conn.go @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build go1.24 - package http3 import ( diff --git a/internal/http3/conn_test.go b/internal/http3/conn_test.go index a9afb1f9..78f19c46 100644 --- a/internal/http3/conn_test.go +++ b/internal/http3/conn_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build go1.24 && goexperiment.synctest +//go:build go1.25 package http3 @@ -142,11 +142,11 @@ func TestConnPeerCreatesBadUnidirectionalStream(t *testing.T) { func runConnTest(t *testing.T, f func(testing.TB, *testQUICConn)) { t.Helper() - runSynctestSubtest(t, "client", func(t testing.TB) { + synctestSubtest(t, "client", func(t *testing.T) { tc := newTestClientConn(t) f(t, tc.testQUICConn) }) - runSynctestSubtest(t, "server", func(t testing.TB) { + synctestSubtest(t, "server", func(t *testing.T) { ts := newTestServer(t) tc := ts.connect() f(t, tc.testQUICConn) diff --git a/internal/http3/errors.go b/internal/http3/errors.go index db46acfc..273ad014 100644 --- a/internal/http3/errors.go +++ b/internal/http3/errors.go @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build go1.24 - package http3 import "fmt" diff --git a/internal/http3/files_test.go b/internal/http3/files_test.go index 9c97a6ce..fcb4596d 100644 --- a/internal/http3/files_test.go +++ b/internal/http3/files_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build go1.24 +//go:build go1.25 package http3 @@ -13,13 +13,11 @@ import ( "testing" ) -// TestFiles checks that every file in this package has a build constraint on Go 1.24. +// TestFiles checks that every test file in this package has a build constraint +// on Go 1.25. Tests rely on synctest.Test, added in Go 1.25. // -// Package tests rely on testing/synctest, added as an experiment in Go 1.24. -// When moving internal/http3 to an importable location, we can decide whether -// to relax the constraint for non-test files. -// -// Drop this test when the x/net go.mod depends on 1.24 or newer. +// TODO(nsh): drop this test and Go 1.25 build contraints once x/net go.mod +// depends on 1.25 or newer. func TestFiles(t *testing.T) { f, err := os.Open(".") if err != nil { @@ -45,12 +43,10 @@ func TestFiles(t *testing.T) { if name == "doc.go" { continue } - if !bytes.Contains(b, []byte("//go:build go1.24")) { - t.Errorf("%v: missing constraint on go1.24", name) - } - if bytes.Contains(b, []byte(`"testing/synctest"`)) && - !bytes.Contains(b, []byte("//go:build go1.24 && goexperiment.synctest")) { - t.Errorf("%v: missing constraint on go1.24 && goexperiment.synctest", name) + if strings.HasSuffix(name, "_test.go") { + if !bytes.Contains(b, []byte("//go:build go1.25")) { + t.Errorf("%v: missing constraint on go1.25", name) + } } } } diff --git a/internal/http3/http3.go b/internal/http3/http3.go index 1f606705..edbba0ca 100644 --- a/internal/http3/http3.go +++ b/internal/http3/http3.go @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build go1.24 - package http3 import "fmt" diff --git a/internal/http3/http3_synctest_test.go b/internal/http3/http3_synctest_test.go deleted file mode 100644 index a9c0ac29..00000000 --- a/internal/http3/http3_synctest_test.go +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2024 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.24 && goexperiment.synctest - -package http3 - -import ( - "context" - "slices" - "testing" - "testing/synctest" -) - -// runSynctest runs f in a synctest.Run bubble. -// It arranges for t.Cleanup functions to run within the bubble. -// TODO: Replace with synctest.Test, which handles all this properly. -func runSynctest(t *testing.T, f func(t testing.TB)) { - synctest.Run(func() { - // Create a context within the bubble, rather than using t.Context. - ctx, cancel := context.WithCancel(context.Background()) - ct := &cleanupT{ - T: t, - ctx: ctx, - cancel: cancel, - } - defer ct.done() - f(ct) - }) -} - -// runSynctestSubtest runs f in a subtest in a synctest.Run bubble. -func runSynctestSubtest(t *testing.T, name string, f func(t testing.TB)) { - t.Run(name, func(t *testing.T) { - runSynctest(t, f) - }) -} - -// cleanupT wraps a testing.T and adds its own Cleanup method. -// Used to execute cleanup functions within a synctest bubble. -type cleanupT struct { - *testing.T - ctx context.Context - cancel context.CancelFunc - cleanups []func() -} - -// Cleanup replaces T.Cleanup. -func (t *cleanupT) Cleanup(f func()) { - t.cleanups = append(t.cleanups, f) -} - -// Context replaces T.Context. -func (t *cleanupT) Context() context.Context { - return t.ctx -} - -func (t *cleanupT) done() { - t.cancel() - for _, f := range slices.Backward(t.cleanups) { - f() - } -} diff --git a/internal/http3/http3_test.go b/internal/http3/http3_test.go index f6fb2e9b..ef6bd027 100644 --- a/internal/http3/http3_test.go +++ b/internal/http3/http3_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build go1.24 +//go:build go1.25 package http3 @@ -10,6 +10,8 @@ import ( "encoding/hex" "os" "strings" + "testing" + "testing/synctest" ) func init() { @@ -42,3 +44,10 @@ type testReader struct { } func (r testReader) Read(p []byte) (n int, err error) { return r.readFunc(p) } + +// synctestSubtest runs f in a subtest in a synctest.Run bubble. +func synctestSubtest(t *testing.T, name string, f func(t *testing.T)) { + t.Run(name, func(t *testing.T) { + synctest.Test(t, f) + }) +} diff --git a/internal/http3/qpack.go b/internal/http3/qpack.go index 8fb4860b..64ce99aa 100644 --- a/internal/http3/qpack.go +++ b/internal/http3/qpack.go @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build go1.24 - package http3 import ( diff --git a/internal/http3/qpack_decode.go b/internal/http3/qpack_decode.go index 018867af..7348ae76 100644 --- a/internal/http3/qpack_decode.go +++ b/internal/http3/qpack_decode.go @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build go1.24 - package http3 import ( diff --git a/internal/http3/qpack_decode_test.go b/internal/http3/qpack_decode_test.go index 3b9a995f..d812d6dd 100644 --- a/internal/http3/qpack_decode_test.go +++ b/internal/http3/qpack_decode_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build go1.24 && goexperiment.synctest +//go:build go1.25 package http3 @@ -102,7 +102,7 @@ func TestQPACKDecode(t *testing.T) { {mayIndex, "accept-encoding", ""}, }, }} { - runSynctestSubtest(t, test.name, func(t testing.TB) { + synctestSubtest(t, test.name, func(t *testing.T) { st1, st2 := newStreamPair(t) st1.Write(test.enc) st1.Flush() @@ -176,7 +176,7 @@ func TestQPACKDecodeErrors(t *testing.T) { name: "too high static table index", enc: unhex("0000ff23ff24"), }} { - runSynctestSubtest(t, test.name, func(t testing.TB) { + synctestSubtest(t, test.name, func(t *testing.T) { st1, st2 := newStreamPair(t) st1.Write(test.enc) st1.Flush() diff --git a/internal/http3/qpack_encode.go b/internal/http3/qpack_encode.go index 0f35e0c5..193f7f93 100644 --- a/internal/http3/qpack_encode.go +++ b/internal/http3/qpack_encode.go @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build go1.24 - package http3 type qpackEncoder struct { diff --git a/internal/http3/qpack_encode_test.go b/internal/http3/qpack_encode_test.go index f426d773..f642821d 100644 --- a/internal/http3/qpack_encode_test.go +++ b/internal/http3/qpack_encode_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build go1.24 +//go:build go1.25 package http3 diff --git a/internal/http3/qpack_static.go b/internal/http3/qpack_static.go index cb0884eb..6c0b51c5 100644 --- a/internal/http3/qpack_static.go +++ b/internal/http3/qpack_static.go @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build go1.24 - package http3 import "sync" diff --git a/internal/http3/qpack_test.go b/internal/http3/qpack_test.go index 6e16511f..29473bf2 100644 --- a/internal/http3/qpack_test.go +++ b/internal/http3/qpack_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build go1.24 +//go:build go1.25 package http3 diff --git a/internal/http3/quic.go b/internal/http3/quic.go index 6d2b1200..4f1cca17 100644 --- a/internal/http3/quic.go +++ b/internal/http3/quic.go @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build go1.24 - package http3 import ( diff --git a/internal/http3/quic_test.go b/internal/http3/quic_test.go index bc3b110f..f494811b 100644 --- a/internal/http3/quic_test.go +++ b/internal/http3/quic_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build go1.24 +//go:build go1.25 package http3 diff --git a/internal/http3/roundtrip.go b/internal/http3/roundtrip.go index bf55a131..d52c8455 100644 --- a/internal/http3/roundtrip.go +++ b/internal/http3/roundtrip.go @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build go1.24 - package http3 import ( diff --git a/internal/http3/roundtrip_test.go b/internal/http3/roundtrip_test.go index ba6a234a..230ff82c 100644 --- a/internal/http3/roundtrip_test.go +++ b/internal/http3/roundtrip_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build go1.24 && goexperiment.synctest +//go:build go1.25 package http3 @@ -18,7 +18,7 @@ import ( ) func TestRoundTripSimple(t *testing.T) { - runSynctest(t, func(t testing.TB) { + synctest.Test(t, func(t *testing.T) { tc := newTestClientConn(t) tc.greet() @@ -44,7 +44,7 @@ func TestRoundTripSimple(t *testing.T) { } func TestRoundTripWithBadHeaders(t *testing.T) { - runSynctest(t, func(t testing.TB) { + synctest.Test(t, func(t *testing.T) { tc := newTestClientConn(t) tc.greet() @@ -56,7 +56,7 @@ func TestRoundTripWithBadHeaders(t *testing.T) { } func TestRoundTripWithUnknownFrame(t *testing.T) { - runSynctest(t, func(t testing.TB) { + synctest.Test(t, func(t *testing.T) { tc := newTestClientConn(t) tc.greet() @@ -82,7 +82,7 @@ func TestRoundTripWithInvalidPushPromise(t *testing.T) { // "A client MUST treat receipt of a PUSH_PROMISE frame that contains // a larger push ID than the client has advertised as a connection error of H3_ID_ERROR." // https://www.rfc-editor.org/rfc/rfc9114.html#section-7.2.5-5 - runSynctest(t, func(t testing.TB) { + synctest.Test(t, func(t *testing.T) { tc := newTestClientConn(t) tc.greet() @@ -155,7 +155,7 @@ func TestRoundTripResponseContentLength(t *testing.T) { }, wantContentLength: -1, }} { - runSynctestSubtest(t, test.name, func(t testing.TB) { + synctestSubtest(t, test.name, func(t *testing.T) { tc := newTestClientConn(t) tc.greet() @@ -199,7 +199,7 @@ func TestRoundTripMalformedResponses(t *testing.T) { name: "no :status", respHeader: http.Header{}, }} { - runSynctestSubtest(t, test.name, func(t testing.TB) { + synctestSubtest(t, test.name, func(t *testing.T) { tc := newTestClientConn(t) tc.greet() @@ -218,7 +218,7 @@ func TestRoundTripCrumbledCookiesInResponse(t *testing.T) { // these MUST be concatenated into a single byte string [...]" // using the two-byte delimiter of "; "'' // https://www.rfc-editor.org/rfc/rfc9114.html#section-4.2.1-2 - runSynctest(t, func(t testing.TB) { + synctest.Test(t, func(t *testing.T) { tc := newTestClientConn(t) tc.greet() @@ -238,7 +238,7 @@ func TestRoundTripCrumbledCookiesInResponse(t *testing.T) { } func TestRoundTripRequestBodySent(t *testing.T) { - runSynctest(t, func(t testing.TB) { + synctest.Test(t, func(t *testing.T) { tc := newTestClientConn(t) tc.greet() @@ -290,7 +290,7 @@ func TestRoundTripRequestBodyErrors(t *testing.T) { }, ), }} { - runSynctestSubtest(t, test.name, func(t testing.TB) { + synctestSubtest(t, test.name, func(t *testing.T) { tc := newTestClientConn(t) tc.greet() @@ -323,7 +323,7 @@ func TestRoundTripRequestBodyErrors(t *testing.T) { } func TestRoundTripRequestBodyErrorAfterHeaders(t *testing.T) { - runSynctest(t, func(t testing.TB) { + synctest.Test(t, func(t *testing.T) { tc := newTestClientConn(t) tc.greet() diff --git a/internal/http3/server.go b/internal/http3/server.go index ca93c529..bdb3479b 100644 --- a/internal/http3/server.go +++ b/internal/http3/server.go @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build go1.24 - package http3 import ( diff --git a/internal/http3/server_test.go b/internal/http3/server_test.go index 8e727d25..1e0cba95 100644 --- a/internal/http3/server_test.go +++ b/internal/http3/server_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build go1.24 && goexperiment.synctest +//go:build go1.25 package http3 @@ -19,7 +19,7 @@ func TestServerReceivePushStream(t *testing.T) { // "[...] if a server receives a client-initiated push stream, // this MUST be treated as a connection error of type H3_STREAM_CREATION_ERROR." // https://www.rfc-editor.org/rfc/rfc9114.html#section-6.2.2-3 - runSynctest(t, func(t testing.TB) { + synctest.Test(t, func(t *testing.T) { ts := newTestServer(t) tc := ts.connect() tc.newStream(streamTypePush) @@ -28,7 +28,7 @@ func TestServerReceivePushStream(t *testing.T) { } func TestServerCancelPushForUnsentPromise(t *testing.T) { - runSynctest(t, func(t testing.TB) { + synctest.Test(t, func(t *testing.T) { ts := newTestServer(t) tc := ts.connect() tc.greet() diff --git a/internal/http3/settings.go b/internal/http3/settings.go index b5e562ec..b3cb2a64 100644 --- a/internal/http3/settings.go +++ b/internal/http3/settings.go @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build go1.24 - package http3 import ( diff --git a/internal/http3/stream.go b/internal/http3/stream.go index 345e2f50..93294d43 100644 --- a/internal/http3/stream.go +++ b/internal/http3/stream.go @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build go1.24 - package http3 import ( diff --git a/internal/http3/stream_test.go b/internal/http3/stream_test.go index a034cc76..036b2356 100644 --- a/internal/http3/stream_test.go +++ b/internal/http3/stream_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build go1.24 +//go:build go1.25 package http3 diff --git a/internal/http3/transport.go b/internal/http3/transport.go index b26524cb..48aaadd8 100644 --- a/internal/http3/transport.go +++ b/internal/http3/transport.go @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build go1.24 - package http3 import ( diff --git a/internal/http3/transport_test.go b/internal/http3/transport_test.go index b3008663..0b7134ad 100644 --- a/internal/http3/transport_test.go +++ b/internal/http3/transport_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build go1.24 && goexperiment.synctest +//go:build go1.25 package http3 @@ -27,7 +27,7 @@ func TestTransportServerCreatesBidirectionalStream(t *testing.T) { // "Clients MUST treat receipt of a server-initiated bidirectional // stream as a connection error of type H3_STREAM_CREATION_ERROR [...]" // https://www.rfc-editor.org/rfc/rfc9114.html#section-6.1-3 - runSynctest(t, func(t testing.TB) { + synctest.Test(t, func(t *testing.T) { tc := newTestClientConn(t) tc.greet() st := tc.newStream(streamTypeRequest)