diff --git a/program.go b/program.go index 5160392..7e2f328 100644 --- a/program.go +++ b/program.go @@ -14,6 +14,12 @@ import ( // Callers may use errors.Is to detect this condition. var ErrProgramNotFound = coreerr.E("", "program: binary not found in PATH", nil) +// ErrProgramContextRequired is returned when Run or RunDir is called without a context. +var ErrProgramContextRequired = coreerr.E("", "program: command context is required", nil) + +// ErrProgramNameRequired is returned when Run or RunDir is called without a program name. +var ErrProgramNameRequired = coreerr.E("", "program: program name is empty", nil) + // Program represents a named executable located on the system PATH. // Create one with a Name, call Find to resolve its path, then Run or RunDir. type Program struct { @@ -48,11 +54,19 @@ func (p *Program) Run(ctx context.Context, args ...string) (string, error) { // Returns trimmed combined stdout+stderr output and any error. // If dir is empty, the process inherits the caller's working directory. func (p *Program) RunDir(ctx context.Context, dir string, args ...string) (string, error) { + if ctx == nil { + return "", coreerr.E("Program.RunDir", "program: command context is required", ErrProgramContextRequired) + } + binary := p.Path if binary == "" { binary = p.Name } + if binary == "" { + return "", coreerr.E("Program.RunDir", "program name is empty", ErrProgramNameRequired) + } + var out bytes.Buffer cmd := exec.CommandContext(ctx, binary, args...) cmd.Stdout = &out diff --git a/program_test.go b/program_test.go index 970e2de..739e516 100644 --- a/program_test.go +++ b/program_test.go @@ -78,3 +78,19 @@ func TestProgram_Run_FailingCommand(t *testing.T) { _, err := p.Run(testCtx(t)) require.Error(t, err) } + +func TestProgram_Run_NilContextRejected(t *testing.T) { + p := &process.Program{Name: "echo"} + + _, err := p.Run(nil, "test") + require.Error(t, err) + assert.ErrorIs(t, err, process.ErrProgramContextRequired) +} + +func TestProgram_RunDir_EmptyNameRejected(t *testing.T) { + p := &process.Program{} + + _, err := p.RunDir(testCtx(t), "", "test") + require.Error(t, err) + assert.ErrorIs(t, err, process.ErrProgramNameRequired) +}