refactor(tests): extract common logic for fallback error handling into a helper function
This commit is contained in:
parent
7aa2d672ce
commit
2b844778ff
1 changed files with 36 additions and 41 deletions
|
|
@ -268,12 +268,21 @@ func TestFallback_UnclassifiedError(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFallback_NetworkErrorFallsBack(t *testing.T) {
|
func assertFallbackErrorFallsBack(
|
||||||
|
t *testing.T,
|
||||||
|
primaryProvider string,
|
||||||
|
primaryModel string,
|
||||||
|
initialErr error,
|
||||||
|
successContent string,
|
||||||
|
expectedReason FailoverReason,
|
||||||
|
) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
ct := NewCooldownTracker()
|
ct := NewCooldownTracker()
|
||||||
fc := NewFallbackChain(ct, nil)
|
fc := NewFallbackChain(ct, nil)
|
||||||
|
|
||||||
candidates := []FallbackCandidate{
|
candidates := []FallbackCandidate{
|
||||||
makeCandidate("minimax", "minimax-m2.7"),
|
makeCandidate(primaryProvider, primaryModel),
|
||||||
makeCandidate("anthropic", "claude"),
|
makeCandidate("anthropic", "claude"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -281,11 +290,9 @@ func TestFallback_NetworkErrorFallsBack(t *testing.T) {
|
||||||
run := func(ctx context.Context, provider, model string) (*LLMResponse, error) {
|
run := func(ctx context.Context, provider, model string) (*LLMResponse, error) {
|
||||||
attempt++
|
attempt++
|
||||||
if attempt == 1 {
|
if attempt == 1 {
|
||||||
return nil, errors.New(
|
return nil, initialErr
|
||||||
`failed to send request: Post "https://opencode.ai/zen/go/v1/chat/completions": tls: bad record MAC`,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
return &LLMResponse{Content: "fallback ok", FinishReason: "stop"}, nil
|
return &LLMResponse{Content: successContent, FinishReason: "stop"}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := fc.Execute(context.Background(), candidates, run)
|
result, err := fc.Execute(context.Background(), candidates, run)
|
||||||
|
|
@ -301,45 +308,33 @@ func TestFallback_NetworkErrorFallsBack(t *testing.T) {
|
||||||
if len(result.Attempts) != 1 {
|
if len(result.Attempts) != 1 {
|
||||||
t.Fatalf("attempts = %d, want 1 failed attempt recorded", len(result.Attempts))
|
t.Fatalf("attempts = %d, want 1 failed attempt recorded", len(result.Attempts))
|
||||||
}
|
}
|
||||||
if result.Attempts[0].Reason != FailoverNetwork {
|
if result.Attempts[0].Reason != expectedReason {
|
||||||
t.Fatalf("attempt reason = %q, want network", result.Attempts[0].Reason)
|
t.Fatalf("attempt reason = %q, want %s", result.Attempts[0].Reason, expectedReason)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFallback_NetworkErrorFallsBack(t *testing.T) {
|
||||||
|
assertFallbackErrorFallsBack(
|
||||||
|
t,
|
||||||
|
"minimax",
|
||||||
|
"minimax-m2.7",
|
||||||
|
errors.New(
|
||||||
|
`failed to send request: Post "https://opencode.ai/zen/go/v1/chat/completions": tls: bad record MAC`,
|
||||||
|
),
|
||||||
|
"fallback ok",
|
||||||
|
FailoverNetwork,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
func TestFallback_TimeoutErrorFallsBack(t *testing.T) {
|
func TestFallback_TimeoutErrorFallsBack(t *testing.T) {
|
||||||
ct := NewCooldownTracker()
|
assertFallbackErrorFallsBack(
|
||||||
fc := NewFallbackChain(ct, nil)
|
t,
|
||||||
|
"openai",
|
||||||
candidates := []FallbackCandidate{
|
"gpt-4",
|
||||||
makeCandidate("openai", "gpt-4"),
|
errors.New("failed to send request: Post \"https://example.com\": i/o timeout"),
|
||||||
makeCandidate("anthropic", "claude"),
|
"timeout fallback ok",
|
||||||
}
|
FailoverTimeout,
|
||||||
|
)
|
||||||
attempt := 0
|
|
||||||
run := func(ctx context.Context, provider, model string) (*LLMResponse, error) {
|
|
||||||
attempt++
|
|
||||||
if attempt == 1 {
|
|
||||||
return nil, errors.New("failed to send request: Post \"https://example.com\": i/o timeout")
|
|
||||||
}
|
|
||||||
return &LLMResponse{Content: "timeout fallback ok", FinishReason: "stop"}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
result, err := fc.Execute(context.Background(), candidates, run)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("expected fallback success, got error: %v", err)
|
|
||||||
}
|
|
||||||
if attempt != 2 {
|
|
||||||
t.Fatalf("attempt = %d, want 2", attempt)
|
|
||||||
}
|
|
||||||
if result.Provider != "anthropic" || result.Model != "claude" {
|
|
||||||
t.Fatalf("result = %s/%s, want anthropic/claude", result.Provider, result.Model)
|
|
||||||
}
|
|
||||||
if len(result.Attempts) != 1 {
|
|
||||||
t.Fatalf("attempts = %d, want 1 failed attempt recorded", len(result.Attempts))
|
|
||||||
}
|
|
||||||
if result.Attempts[0].Reason != FailoverTimeout {
|
|
||||||
t.Fatalf("attempt reason = %q, want timeout", result.Attempts[0].Reason)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFallback_SuccessResetsCooldown(t *testing.T) {
|
func TestFallback_SuccessResetsCooldown(t *testing.T) {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue