From 1f478a2f106218c5b998fa539adc417c5cdbdc07 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 16 Apr 2026 12:54:34 +0000 Subject: [PATCH 1/2] test(mcp): add connect-timeout default behaviour tests Add four tests in package mcp covering the connectTimeout defaulting logic in NewHTTPConnection: - TestNewHTTPConnection_DefaultConnectTimeout_ZeroInput Ensures that connectTimeout=0 falls back to defaultConnectTimeout (30 s). - TestNewHTTPConnection_DefaultConnectTimeout_NegativeInput Ensures that connectTimeout<0 also falls back (guards the <= 0 fix for the bug identified in #3933). - TestNewHTTPConnection_DefaultConnectTimeout_CustomValue Ensures that a positive connectTimeout is stored unchanged. - TestDefaultConnectTimeout_Value Guards the constant value so any drift from config.DefaultConnectTimeout (30 s) causes an immediate, obvious test failure rather than a silent bug. These tests directly exercise the paths fixed in fix(mcp):#3933 and provide regression coverage for future changes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- internal/mcp/connect_timeout_test.go | 87 ++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 internal/mcp/connect_timeout_test.go diff --git a/internal/mcp/connect_timeout_test.go b/internal/mcp/connect_timeout_test.go new file mode 100644 index 00000000..2004e7e5 --- /dev/null +++ b/internal/mcp/connect_timeout_test.go @@ -0,0 +1,87 @@ +package mcp + +import ( + "context" + "encoding/json" + "net/http" + "net/http/httptest" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// newMinimalTestServer returns an httptest server that responds with a minimal +// JSON-RPC initialize result so NewHTTPConnection can complete its handshake. +func newMinimalTestServer(t *testing.T) *httptest.Server { + t.Helper() + return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + resp := map[string]interface{}{ + "jsonrpc": "2.0", + "id": 1, + "result": map[string]interface{}{ + "protocolVersion": "2024-11-05", + "serverInfo": map[string]interface{}{"name": "test"}, + }, + } + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(resp) //nolint:errcheck + })) +} + +// TestNewHTTPConnection_DefaultConnectTimeout_ZeroInput verifies that a zero +// connectTimeout is replaced with defaultConnectTimeout (30 s). +func TestNewHTTPConnection_DefaultConnectTimeout_ZeroInput(t *testing.T) { + srv := newMinimalTestServer(t) + defer srv.Close() + + conn, err := NewHTTPConnection(context.Background(), "test", srv.URL, + map[string]string{"Authorization": "test"}, nil, "", 0, 0) + require.NoError(t, err) + require.NotNil(t, conn) + defer conn.Close() + + assert.Equal(t, defaultConnectTimeout, conn.connectTimeout, + "zero connectTimeout should be replaced with defaultConnectTimeout") +} + +// TestNewHTTPConnection_DefaultConnectTimeout_NegativeInput verifies that a +// negative connectTimeout is also replaced with defaultConnectTimeout. +func TestNewHTTPConnection_DefaultConnectTimeout_NegativeInput(t *testing.T) { + srv := newMinimalTestServer(t) + defer srv.Close() + + conn, err := NewHTTPConnection(context.Background(), "test", srv.URL, + map[string]string{"Authorization": "test"}, nil, "", 0, -1*time.Second) + require.NoError(t, err) + require.NotNil(t, conn) + defer conn.Close() + + assert.Equal(t, defaultConnectTimeout, conn.connectTimeout, + "negative connectTimeout should be replaced with defaultConnectTimeout") +} + +// TestNewHTTPConnection_DefaultConnectTimeout_CustomValue verifies that a +// positive connectTimeout is stored as-is without being replaced. +func TestNewHTTPConnection_DefaultConnectTimeout_CustomValue(t *testing.T) { + srv := newMinimalTestServer(t) + defer srv.Close() + + custom := 10 * time.Second + conn, err := NewHTTPConnection(context.Background(), "test", srv.URL, + map[string]string{"Authorization": "test"}, nil, "", 0, custom) + require.NoError(t, err) + require.NotNil(t, conn) + defer conn.Close() + + assert.Equal(t, custom, conn.connectTimeout, + "a positive connectTimeout should be stored unchanged") +} + +// TestDefaultConnectTimeout_Value guards against the constant value drifting +// away from config.DefaultConnectTimeout (30 s) unintentionally. +func TestDefaultConnectTimeout_Value(t *testing.T) { + assert.Equal(t, 30*time.Second, defaultConnectTimeout, + "defaultConnectTimeout must remain 30 s to stay in sync with config.DefaultConnectTimeout") +} From 9b7bfbcacc5cc8bef156b3b3ae27bef7b0464be5 Mon Sep 17 00:00:00 2001 From: Landon Cox Date: Thu, 16 Apr 2026 07:48:44 -0700 Subject: [PATCH 2/2] Update internal/mcp/connect_timeout_test.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- internal/mcp/connect_timeout_test.go | 35 +++++++++++++++++++--------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/internal/mcp/connect_timeout_test.go b/internal/mcp/connect_timeout_test.go index 2004e7e5..c5509353 100644 --- a/internal/mcp/connect_timeout_test.go +++ b/internal/mcp/connect_timeout_test.go @@ -12,21 +12,34 @@ import ( "github.com/stretchr/testify/require" ) -// newMinimalTestServer returns an httptest server that responds with a minimal -// JSON-RPC initialize result so NewHTTPConnection can complete its handshake. +// newMinimalTestServer returns an httptest server that responds with the +// minimal HTTP semantics needed for NewHTTPConnection to complete its SDK +// transport handshake reliably. func newMinimalTestServer(t *testing.T) *httptest.Server { t.Helper() return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - resp := map[string]interface{}{ - "jsonrpc": "2.0", - "id": 1, - "result": map[string]interface{}{ - "protocolVersion": "2024-11-05", - "serverInfo": map[string]interface{}{"name": "test"}, - }, + switch r.Method { + case http.MethodGet: + w.Header().Set("Content-Type", "text/event-stream") + w.WriteHeader(http.StatusOK) + return + case http.MethodPost: + resp := map[string]interface{}{ + "jsonrpc": "2.0", + "id": 1, + "result": map[string]interface{}{ + "protocolVersion": "2024-11-05", + "serverInfo": map[string]interface{}{"name": "test"}, + }, + } + w.Header().Set("Content-Type", "application/json") + w.Header().Set("Mcp-Session-Id", "test-session") + json.NewEncoder(w).Encode(resp) //nolint:errcheck + return + default: + w.WriteHeader(http.StatusMethodNotAllowed) + return } - w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(resp) //nolint:errcheck })) }