fix(network): classify timeout errors as FailoverTimeout

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
LC
2026-04-16 21:13:09 +08:00
committed by lc6464
parent c3f4000817
commit 7aa2d672ce
3 changed files with 103 additions and 0 deletions
+61
View File
@@ -7,9 +7,19 @@ import (
"io"
"net"
"net/url"
"syscall"
"testing"
)
type stubNetError struct {
msg string
timeout bool
}
func (e stubNetError) Error() string { return e.msg }
func (e stubNetError) Timeout() bool { return e.timeout }
func (e stubNetError) Temporary() bool { return false }
func TestClassifyError_Nil(t *testing.T) {
result := ClassifyError(nil, "openai", "gpt-4")
if result != nil {
@@ -216,6 +226,57 @@ func TestClassifyError_NetworkTypes(t *testing.T) {
}
}
func TestClassifyError_TimeoutNetworkTypes(t *testing.T) {
tests := []struct {
name string
err error
}{
{
name: "wrapped syscall timeout",
err: fmt.Errorf("dial tcp: %w", syscall.ETIMEDOUT),
},
{
name: "net error timeout",
err: &url.Error{
Op: "Post",
URL: "https://example.com",
Err: stubNetError{msg: "i/o timeout", timeout: true},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := ClassifyError(tt.err, "openai", "gpt-4")
if result == nil {
t.Fatal("expected non-nil")
}
if result.Reason != FailoverTimeout {
t.Fatalf("reason = %q, want timeout", result.Reason)
}
})
}
}
func TestClassifyError_TimeoutPatternsWinOverNetworkContext(t *testing.T) {
patterns := []string{
`failed to send request: Post "https://example.com": dial tcp 203.0.113.10:443: i/o timeout`,
`read tcp 10.20.0.1:61279->172.65.90.20:443: i/o timeout`,
}
for _, msg := range patterns {
err := errors.New(msg)
result := ClassifyError(err, "openai", "gpt-4")
if result == nil {
t.Errorf("pattern %q: expected non-nil", msg)
continue
}
if result.Reason != FailoverTimeout {
t.Errorf("pattern %q: reason = %q, want timeout", msg, result.Reason)
}
}
}
func TestClassifyError_NetworkPatternsWinOverAuthExpired(t *testing.T) {
err := errors.New(
`Post "https://example.com": tls: failed to verify certificate: x509: certificate has expired or is not yet valid`,