package platform import ( "context" "errors" "os/exec" "strings" "testing" "time" ) func TestRunProbeCommandValidation(t *testing.T) { tests := []struct { name string want string spec probeSpec }{ {"empty command", "command is empty", probeSpec{name: "", timeout: time.Second, maxOutput: 1}}, {"zero timeout", "invalid timeout", probeSpec{name: "validation-only-command", timeout: 0, maxOutput: 1}}, {"negative timeout", "invalid timeout", probeSpec{name: "validation-only-command", timeout: -time.Second, maxOutput: 1}}, {"zero output limit", "invalid output limit", probeSpec{name: "validation-only-command", timeout: time.Second, maxOutput: 0}}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if _, err := runProbeCommand(context.Background(), tt.spec); err == nil || !strings.Contains(err.Error(), tt.want) { t.Errorf("runProbeCommand(%+v) = %v, want validation failure containing %q", tt.spec, err, tt.want) } }) } } func TestSystemProbeRunner(t *testing.T) { t.Run("successful probe returns stdout", func(t *testing.T) { out, err := systemProbeRunner{}.Run(helperProbe(t, "stdout", quickProbeTimeout, defaultProbeMaxBytes)) if err != nil { t.Fatalf("Run(helper stdout) error = %v", err) } if string(out) != "probe-stdout\n" { t.Errorf("Run(helper stdout) output = %q, want probe stdout", out) } }) t.Run("missing binary fails fast", func(t *testing.T) { _, err := systemProbeRunner{}.Run(newProbe("definitely-not-a-real-binary-mpv-manager", quickProbeTimeout)) if err == nil { t.Error("Run() with a missing binary must return an error") } }) } func TestRunProbeCommandIncludesStderr(t *testing.T) { // A failing command's stderr must be attached to the returned error so // probe failures are diagnosable from logs. spec := helperProbe(t, "stderr-failure", quickProbeTimeout, defaultProbeMaxBytes) _, err := runProbeCommand(context.Background(), spec) if err == nil { t.Fatal("runProbeCommand() = nil error, want exit status failure") } var exitError *exec.ExitError if !errors.As(err, &exitError) || exitError.ExitCode() != 3 { t.Fatalf("runProbeCommand() error = %v, want real child exit code3", err) } if !strings.Contains(err.Error(), "probe-went-wrong") { t.Errorf("runProbeCommand() error = %v, want stderr content included", err) } } func TestRunProbeCommandNilParentContext(t *testing.T) { // A nil parent context must not panic; it is normalized to Background. //lint:ignore SA1012 This regression intentionally exercises the nil-compatibility boundary. out, err := runProbeCommand(nil, helperProbe(t, "empty", quickProbeTimeout, defaultProbeMaxBytes)) if err != nil { t.Fatalf("runProbeCommand(nil, ...) error = %v", err) } if len(out) != 0 { t.Errorf("output = %q, want empty", out) } }