Files
pranshuparmar--witr/internal/app/exitcode_test.go
T
wehub-resource-sync 36b3af2e3d
PR Check / Code Quality: Format (push) Failing after 1s
PR Check / Code Quality: Lint (darwin) (push) Failing after 0s
PR Check / Code Quality: Lint (freebsd) (push) Failing after 1s
PR Check / Code Quality: Lint (windows) (push) Failing after 1s
PR Check / Code Quality: Lint (linux) (push) Failing after 1s
PR Check / Security: Vulnerability Scan (push) Failing after 0s
Update Documentation / update-docs (push) Failing after 2s
PR Check / Code Quality: Vendor (push) Failing after 1s
PR Check / Code Quality: Coverage (push) Failing after 0s
PR Check / Tests: Unit (macos-latest) (push) Has been cancelled
PR Check / Tests: Unit (ubuntu-24.04) (push) Has been cancelled
PR Check / Tests: Unit (ubuntu-24.04-arm) (push) Has been cancelled
PR Check / Tests: Unit (windows-latest) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:22:06 +08:00

84 lines
2.4 KiB
Go

package app
import (
"os/exec"
"path/filepath"
"runtime"
"strings"
"testing"
)
// buildWitr compiles the real witr binary once so the process exit codes can be
// characterized end to end (Execute -> runApp -> os.Exit). The exit-code
// contract drives scripting and CI integrations, so it's asserted against the
// actual binary rather than internal helpers.
func buildWitr(t *testing.T) string {
t.Helper()
gomod, err := exec.Command("go", "env", "GOMOD").Output()
if err != nil {
t.Fatalf("go env GOMOD: %v", err)
}
root := filepath.Dir(strings.TrimSpace(string(gomod)))
bin := filepath.Join(t.TempDir(), "witr")
if runtime.GOOS == "windows" {
bin += ".exe"
}
build := exec.Command("go", "build", "-o", bin, "./cmd/witr")
build.Dir = root
if out, err := build.CombinedOutput(); err != nil {
t.Fatalf("build witr: %v\n%s", err, out)
}
return bin
}
func runExit(t *testing.T, bin string, args ...string) int {
t.Helper()
err := exec.Command(bin, args...).Run()
if err == nil {
return 0
}
if ee, ok := err.(*exec.ExitError); ok {
return ee.ExitCode()
}
t.Fatalf("run witr %v: %v", args, err)
return -1
}
func TestExitCodes(t *testing.T) {
if testing.Short() {
t.Skip("builds the witr binary; skipped under -short")
}
bin := buildWitr(t)
// PID 2147483646 is far above any real PID on Linux/macOS/Windows, so the
// "not found" path is deterministic on CI runners.
const ghostPID = "2147483646"
tests := []struct {
name string
args []string
want int
}{
{"invalid pid (non-numeric)", []string{"--pid", "notanumber"}, ExitInvalidInput},
{"invalid pid (zero)", []string{"--pid", "0"}, ExitInvalidInput},
{"invalid port (out of range)", []string{"--port", "70000"}, ExitInvalidInput},
{"not found (ghost pid)", []string{"--pid", ghostPID}, ExitNotFound},
// Multi-target exit code is the highest severity among targets, not the
// first or last — assert with both orderings of a not-found(2) and an
// invalid(4) target.
{"multi: not-found then invalid", []string{"--pid", ghostPID, "--port", "70000"}, ExitInvalidInput},
{"multi: invalid then not-found", []string{"--port", "70000", "--pid", ghostPID}, ExitInvalidInput},
}
for _, tc := range tests {
tc := tc
t.Run(tc.name, func(t *testing.T) {
if got := runExit(t, bin, tc.args...); got != tc.want {
t.Errorf("witr %v exit = %d, want %d", tc.args, got, tc.want)
}
})
}
}