Files
Agent-System/internal/agent/fallback_test.go
T
weichen 127cfccccc feat(agent): fall back to the container backend when pi-native fails
Dev starts on pi-native and keeps pi-agent available for a failed turn. Latency tuning stays deferred.
2026-09-21 15:29:33 +00:00

64 lines
2.3 KiB
Go

package agent
import (
"context"
"errors"
"strings"
"testing"
)
type scriptBackend struct {
name string
res *Result
err error
calls int
}
func (s *scriptBackend) Name() string { return s.name }
func (s *scriptBackend) Execute(ctx context.Context, req Request) (*Result, error) {
s.calls++
return s.res, s.err
}
func TestFallbackKeepsNativeSuccess(t *testing.T) {
primary := &scriptBackend{name: "pi-native", res: &Result{Success: true, Logs: "native"}}
spare := &scriptBackend{name: "pi-agent", res: &Result{Success: true}}
got, err := (&fallbackBackend{primary: primary, fallback: spare}).Execute(context.Background(), Request{})
if err != nil || !got.Success || got.Logs != "native" || spare.calls != 0 {
t.Fatalf("got %#v err=%v spare=%d", got, err, spare.calls)
}
}
func TestFallbackUsesContainerAfterNativeFailure(t *testing.T) {
primary := &scriptBackend{name: "pi-native", res: &Result{Success: false, ErrorReason: "missing target deliverable"}}
spare := &scriptBackend{name: "pi-agent", res: &Result{Success: true, Logs: "container"}}
got, err := (&fallbackBackend{primary: primary, fallback: spare}).Execute(context.Background(), Request{})
if err != nil || !got.Success || spare.calls != 1 {
t.Fatalf("got %#v err=%v calls=%d", got, err, spare.calls)
}
if !strings.Contains(got.Logs, "served by pi-agent") || !strings.Contains(got.Logs, "missing target deliverable") {
t.Fatalf("logs %q", got.Logs)
}
}
func TestFallbackReturnsNativeWhenContainerAlsoFails(t *testing.T) {
primary := &scriptBackend{name: "pi-native", err: errors.New("native down")}
spare := &scriptBackend{name: "pi-agent", res: &Result{Success: false, ErrorReason: "runner down"}}
got, err := (&fallbackBackend{primary: primary, fallback: spare}).Execute(context.Background(), Request{})
if err == nil || err.Error() != "native down" || got != nil || spare.calls != 1 {
t.Fatalf("got %#v err=%v", got, err)
}
}
func TestFallbackStopsWhenContextCancelled(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
cancel()
primary := &scriptBackend{name: "pi-native", err: context.Canceled}
spare := &scriptBackend{name: "pi-agent", res: &Result{Success: true}}
_, err := (&fallbackBackend{primary: primary, fallback: spare}).Execute(ctx, Request{})
if !errors.Is(err, context.Canceled) || spare.calls != 0 {
t.Fatalf("err=%v spare=%d", err, spare.calls)
}
}