From 3052089c4d25dbc7870d3670ba6717c5b6c649d3 Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Mon, 8 Jun 2026 15:11:36 +0100 Subject: [PATCH] test: fix transport error flake (#26132) `TestResolveWorkspace/TransportError` could sometimes observe an HTTP 404 from a closing test server instead of a transport error. Make the test deterministic by injecting a failing `http.RoundTripper`, and add `testutil.RoundTripperFunc` for reuse. Generated by Coder Agents.
Implementation plan # Plan: Deterministic ResolveWorkspace transport error test ## Context `TestResolveWorkspace/TransportError` relied on closing an `httptest.Server` before making a request. CI showed this can race with the request path and produce an HTTP 404 instead of a transport error. The test should inject a transport failure directly. ## Red 1. Update the transport-error case to use a custom `http.RoundTripper` that returns an error. 2. Confirm the test fails to compile until the reusable `testutil.RoundTripperFunc` helper exists. ## Green 1. Add `testutil.RoundTripperFunc` in `testutil/http.go`. 2. Implement `RoundTrip` so the function type satisfies `http.RoundTripper`. 3. Add a compile-time interface assertion for the helper. 4. Update `codersdk/workspaces_test.go` to inject a client using `testutil.RoundTripperFunc`. 5. Keep the existing assertion that transport errors do not become `*codersdk.Error`. ## Refactor 1. Run `gofmt` on touched Go files. 2. Check import cleanup and variable names after the implementation compiles. 3. Keep the change limited to the reusable helper and this test. ## Verification 1. `go test ./codersdk -run TestResolveWorkspace -count=100` 2. `go test ./testutil ./codersdk -run TestResolveWorkspace -count=1` 3. `git diff --check`
--- codersdk/workspaces_test.go | 14 ++++++++------ testutil/http.go | 9 +++++++++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/codersdk/workspaces_test.go b/codersdk/workspaces_test.go index ee03c88643..63cb99e062 100644 --- a/codersdk/workspaces_test.go +++ b/codersdk/workspaces_test.go @@ -13,8 +13,10 @@ import ( "github.com/google/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "golang.org/x/xerrors" "github.com/coder/coder/v2/codersdk" + "github.com/coder/coder/v2/testutil" ) func TestResolveWorkspace(t *testing.T) { @@ -271,13 +273,13 @@ func TestResolveWorkspace(t *testing.T) { t.Run("TransportError", func(t *testing.T) { t.Parallel() - // Close the server immediately so the transport layer fails. - srv := httptest.NewServer(http.NotFoundHandler()) - srvURL, err := url.Parse(srv.URL) + baseURL, err := url.Parse("http://example.com") require.NoError(t, err) - srv.Close() - - client := codersdk.New(srvURL) + client := codersdk.New(baseURL, codersdk.WithHTTPClient(&http.Client{ + Transport: testutil.RoundTripperFunc(func(*http.Request) (*http.Response, error) { + return nil, xerrors.New("transport error") + }), + })) _, err = client.ResolveWorkspace(t.Context(), uuid.NewString()) require.Error(t, err) diff --git a/testutil/http.go b/testutil/http.go index 653c8f642c..0a764b46a9 100644 --- a/testutil/http.go +++ b/testutil/http.go @@ -9,6 +9,15 @@ import ( "github.com/stretchr/testify/require" ) +// RoundTripperFunc adapts a function to an http.RoundTripper. +type RoundTripperFunc func(*http.Request) (*http.Response, error) + +var _ http.RoundTripper = RoundTripperFunc(nil) + +func (f RoundTripperFunc) RoundTrip(req *http.Request) (*http.Response, error) { + return f(req) +} + // RequireEventuallyResponseOK makes HTTP GET requests to the given endpoint until it returns // 200 OK with a valid JSON response that can be decoded into target, or until the context // times out. This is useful for waiting for HTTP servers to become ready during tests,