修复 Windows MCP 连接拒绝分类并补充 CI 回归 (#805)

This commit is contained in:
tsuixl authored and GitHub committed 2026-10-05 07:44:11 +08:00
1 parent 189a4b95ac
commit 066ecaae7d
5 files changed
+66 -2

No files matched your search

+6
View File
@@ -81,6 +81,12 @@ jobs:
if: runner.os == 'Windows'
run: go test -run '^$' ./...
# These checks use in-memory errors and loopback test servers. Run
# the native Winsock refusal case rather than only compiling it.
- name: Windows MCP health
if: runner.os == 'Windows'
run: go test -v -count=1 -timeout 2m ./internal/library -run '^(TestNetHealth|TestCheckHTTP)$'
# Usage isolates USERPROFILE and the agent homes; execute its native
# ChangeTime checks rather than only cross-compiling the Windows API.
- name: Windows usage cache
+1 -2
View File
@@ -15,7 +15,6 @@ import (
"os/exec"
"strings"
"sync"
"syscall"
"time"
"github.com/yetone/magpie/internal/gateway"
@@ -403,7 +402,7 @@ func netHealth(ctx context.Context, err error) ServerHealth {
if ctx.Err() != nil || errors.Is(err, context.DeadlineExceeded) {
return timedOut()
}
if errors.Is(err, syscall.ECONNREFUSED) {
if errors.Is(err, connectionRefused) {
return failed("refused", err.Error())
}
var ue *url.Error
+7
View File
@@ -0,0 +1,7 @@
//go:build !windows
package library
import "syscall"
const connectionRefused = syscall.ECONNREFUSED
+45
View File
@@ -0,0 +1,45 @@
package library
import (
"context"
"errors"
"net"
"net/url"
"os"
"testing"
)
func TestNetHealth(t *testing.T) {
wrapped := &url.Error{
Op: "Post", URL: "http://127.0.0.1/mcp",
Err: &net.OpError{Op: "dial", Net: "tcp", Err: os.NewSyscallError("connect", connectionRefused)},
}
for _, test := range []struct {
name string
err error
why string
}{
{"native refusal", connectionRefused, "refused"},
{"wrapped refusal", wrapped, "refused"},
{"deadline", &url.Error{Op: "Post", Err: context.DeadlineExceeded}, "timeout"},
{"dns", &url.Error{Op: "Post", Err: &net.DNSError{Name: "missing.invalid", IsNotFound: true}}, "unreachable"},
{"other error", errors.New("network unavailable"), "unreachable"},
{"text alone", errors.New("connection refused"), "unreachable"},
} {
t.Run(test.name, func(t *testing.T) {
h := netHealth(context.Background(), test.err)
if h.State != "error" || h.Why != test.why {
t.Fatalf("got %+v, want error/%s", h, test.why)
}
if test.why == "refused" && h.Detail != test.err.Error() {
t.Fatalf("lost the original error: %q, want %q", h.Detail, test.err.Error())
}
})
}
ctx, cancel := context.WithCancel(context.Background())
cancel()
if h := netHealth(ctx, wrapped); h.Why != "timeout" {
t.Fatalf("an ended check should keep its timeout classification: %+v", h)
}
}
@@ -0,0 +1,7 @@
package library
import "golang.org/x/sys/windows"
// TCP failures carry Winsock errors. syscall.ECONNREFUSED is a different,
// compatibility errno on Windows and does not match a refused connection.
const connectionRefused = windows.WSAECONNREFUSED