gitlink-cli/cmd/interactive/executor_runtime_test.go

70 lines
2.1 KiB
Go

package interactive
import (
"os"
"testing"
"github.com/gitlink-org/gitlink-cli/shortcuts/common"
)
// TestExecutor_UsesRealRuntimeContext verifies that Execute builds the
// RuntimeContext via NewRuntimeContext (which initializes Client/Format/etc.)
// rather than a bare struct literal that leaves Client == nil.
//
// Regression: previously Execute did `&common.RuntimeContext{Args: args}`,
// so any command calling ctx.CallAPI panicked with a nil pointer dereference
// inside the executor goroutine, which swallowed the execResultMsg and left
// the REPL showing no output at all.
func TestExecutor_UsesRealRuntimeContext(t *testing.T) {
called := false
s := &common.Shortcut{
Name: "probe",
Run: func(ctx *common.RuntimeContext) error {
called = true
// A real command uses ctx.Client / ctx.Format. If Execute built the
// context correctly, Client must be non-nil and Format non-empty.
if ctx.Client == nil {
t.Error("ctx.Client is nil — Execute did not use NewRuntimeContext")
}
if ctx.Format == "" {
t.Error("ctx.Format is empty — Execute did not initialize format")
}
return nil
},
}
exec := &Executor{}
out, err := exec.Execute(s, map[string]string{})
if err != nil {
t.Fatalf("Execute() error = %v", err)
}
if !called {
t.Fatal("Run was not invoked")
}
if out != "" {
t.Fatalf("expected empty output, got %q", out)
}
}
// TestExecutor_PanicDoesNotCorruptStdout verifies that if a command panics,
// Execute recovers, returns the panic as an error, and — critically — restores
// os.Stdout so the REPL is not left with stdout pointing at a closed pipe.
func TestExecutor_PanicDoesNotCorruptStdout(t *testing.T) {
original := os.Stdout
s := &common.Shortcut{
Name: "boom",
Run: func(ctx *common.RuntimeContext) error {
panic("simulated command failure")
},
}
exec := &Executor{}
_, err := exec.Execute(s, map[string]string{})
if err == nil {
t.Fatal("expected Execute to return an error for a panicking command")
}
if os.Stdout != original {
t.Fatal("os.Stdout was not restored after a panic — REPL would be left broken")
}
}