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) } }