mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
chore: add NewUnstartedHTTPServer helper to disable keep-alives on test servers (#28052)
Tests that proxy or pool connections to a bare `httptest.Server` intermittently fail on Windows with a bare EOF when a stale pooled connection is reused. net/http will not retry a non-replayable request (e.g. a POST) on a closed pooled connection, so forcing a fresh connection per request eliminates the failure class. This is the same mechanism fixed in #28016 (AIGOV-430 / internal#1564), now expressed as a reusable, behavior-preserving helper. This PR adds `testutil.NewTestHTTPServer`, a known-good wrapper around `httptest.NewServer` that applies some defaults. Currently the only default is disabling keep-alives by default. - `testutil/http_server.go`: `NewHTTPServer(t, handler, opts)` started, with documented defaults, starts automatically, and handles `t.Cleanup`. - `testutil/http_server_test.go`: unit test for defaults and overriding defaults. - `enterprise/aibridgeproxyd/reload_test.go`: refactor the harness's hand-rolled server to the helper. ## Future Work - Functional options are exposed but not explicitly defined. This can be done later as required. - No lint rule or broader migration. A forcing-function analyzer covering more packages, plus wider adoption, belongs in a separate follow-up. ## Verification - `testutil` and `enterprise/aibridgeproxyd` suites pass under `-race`. - `TestProxy_HotReloadRouting` and `TestProxy_StaleTunnel` pass 10x under `-race`. - New helper unit test passes under `-race`. > Generated by a Coder agent.
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
package testutil_test
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/coder/coder/v2/testutil"
|
||||
)
|
||||
|
||||
func TestNewUnstartedHTTPServer(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
send := func(conn net.Conn) error {
|
||||
_, err := fmt.Fprintf(conn, "GET / HTTP/1.1\r\nHost: x\r\n\r\n")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resp, err := http.ReadResponse(bufio.NewReader(conn), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_ = resp.Body.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
t.Run("defaults", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
srv := testutil.NewHTTPTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}))
|
||||
|
||||
conn, err := net.Dial("tcp", srv.Listener.Addr().String())
|
||||
require.NoError(t, err, "dial")
|
||||
defer conn.Close()
|
||||
|
||||
// Keepalives should be disabled: first request succeeds, second request on the same conn fails.
|
||||
require.NoError(t, send(conn), "keepalives disabled: first request on reused connection must succeed")
|
||||
require.Error(t, send(conn), "keepalives disabled: second request on reused connection must fail")
|
||||
})
|
||||
|
||||
t.Run("override", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
srv := testutil.NewHTTPTestServer(t, http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}), func(srv *httptest.Server) {
|
||||
srv.Config.SetKeepAlivesEnabled(true)
|
||||
})
|
||||
|
||||
conn, err := net.Dial("tcp", srv.Listener.Addr().String())
|
||||
require.NoError(t, err, "dial")
|
||||
defer conn.Close()
|
||||
|
||||
// Keepalives should be enabled: multiple requests on the same conn succeed.
|
||||
require.NoError(t, send(conn), "keepalives enabled: first request on reused connection must succeed")
|
||||
require.NoError(t, send(conn), "keepalives enabled: second request on reused connection must succeed")
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user