Files
gastownhall__beads/scripts/test_script_test.go
ecuthiell bf930078e8 test(scripts): report helper-only probe as skipped (#5599)
Mark the launchability probe skipped in ordinary package runs so a helper-only guard cannot be mistaken for executed coverage.

Signed-off-by: Ewen Cuthiell <ewencuthiell@gmail.com>

Agent-Signature: codex-gpt-5-unknown-reasoning on behalf of Ewen Cuthiell
2026-08-10 20:58:58 -07:00

271 lines
8.4 KiB
Go

package scripts_test
import (
"io"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"testing"
)
const (
testScriptFakeGoLogEnv = "BEADS_TEST_SCRIPT_FAKE_GO_LOG"
testScriptExpectedBinaryEnv = "BEADS_TEST_SCRIPT_EXPECTED_BINARY"
testScriptExpectedBaseEnv = "BEADS_TEST_SCRIPT_EXPECTED_BASENAME"
testScriptDriverEnv = "BEADS_TEST_SCRIPT_DRIVER"
testScriptNativeSuffixEnv = "BEADS_TEST_SCRIPT_NATIVE_SUFFIX"
testScriptLaunchProbeEnv = "BEADS_TEST_SCRIPT_LAUNCH_PROBE"
)
const testScriptFakeGo = `#!/usr/bin/env bash
set -euo pipefail
record() {
printf '%s\n' "$1" >>"$BEADS_TEST_SCRIPT_FAKE_GO_LOG"
}
case "${1:-}" in
env)
record env
if [[ $# -ne 2 || "$2" != "GOEXE" ]]; then
printf 'fake go: unsupported env arguments: %s\n' "$*" >&2
exit 90
fi
printf '%s\n' "$BEADS_TEST_SCRIPT_NATIVE_SUFFIX"
;;
build)
record build
shift
output=""
while [[ $# -gt 0 ]]; do
if [[ "$1" == "-o" ]]; then
if [[ $# -lt 2 ]]; then
printf 'fake go: -o is missing its output\n' >&2
exit 90
fi
output="$2"
shift 2
else
shift
fi
done
if [[ -z "$output" || "$output" != "$BEADS_TEST_SCRIPT_EXPECTED_BINARY" ]]; then
printf 'fake go: build output %q, want %q\n' "$output" "$BEADS_TEST_SCRIPT_EXPECTED_BINARY" >&2
exit 90
fi
cp -f -- "$BEADS_TEST_SCRIPT_DRIVER" "$output"
chmod +x "$output"
;;
test)
record test
"$BEADS_TEST_SCRIPT_DRIVER" \
-test.run '^TestTestScriptPrebuiltBinaryLaunchProbe$' \
-test.count=1
;;
*)
printf 'fake go: unsupported command: %s\n' "$*" >&2
exit 90
;;
esac
`
func TestTestScriptPrebuiltBinaryContract(t *testing.T) {
t.Run("generated path uses the native executable suffix and launches", func(t *testing.T) {
commands := runTestScriptWithFakeGo(t, "")
assertFakeGoCommands(t, commands, "env", "build", "test")
})
t.Run("caller supplied binary wins without a build", func(t *testing.T) {
fixtureRoot := filepath.Join(t.TempDir(), "caller override with spaces")
if err := os.MkdirAll(fixtureRoot, 0o755); err != nil {
t.Fatalf("create caller fixture root: %v", err)
}
callerBinary := filepath.Join(fixtureRoot, "caller supplied bd"+nativeExecutableSuffix())
copyCurrentTestExecutable(t, callerBinary)
commands := runTestScriptWithFakeGo(t, callerBinary)
assertFakeGoCommands(t, commands, "test")
})
}
// TestTestScriptPrebuiltBinaryLaunchProbe is selected only by the fake go test
// process above. Keeping the os/exec probe in a normal test avoids claiming the
// package-wide TestMain authority needed by other script-selection contracts.
func TestTestScriptPrebuiltBinaryLaunchProbe(t *testing.T) {
if os.Getenv(testScriptLaunchProbeEnv) != "1" {
t.Skip("re-exec probe runs only under the test.sh fake-go driver")
}
prebuilt := os.Getenv("BEADS_TEST_BD_BINARY")
expected := os.Getenv(testScriptExpectedBinaryEnv)
if prebuilt == "" || expected == "" || !sameTestScriptFile(prebuilt, expected) {
t.Fatalf("exported prebuilt binary %q is not expected file %q", prebuilt, expected)
}
if want := os.Getenv(testScriptExpectedBaseEnv); filepath.Base(prebuilt) != want {
t.Fatalf("exported prebuilt basename = %q, want %q", filepath.Base(prebuilt), want)
}
command := exec.Command(prebuilt, "-test.run=^$")
output, err := command.CombinedOutput()
if err != nil {
t.Fatalf("launch exported prebuilt binary through os/exec: %v\n%s", err, output)
}
}
func runTestScriptWithFakeGo(t *testing.T, callerBinary string) []string {
t.Helper()
root := filepath.Join(t.TempDir(), "test script root with spaces")
fakeBin := filepath.Join(root, "fake go bin")
testEnvRoot := filepath.Join(root, "isolated test environment")
tempRoot := filepath.Join(root, "temporary files")
for _, path := range []string{fakeBin, testEnvRoot, tempRoot} {
if err := os.MkdirAll(path, 0o755); err != nil {
t.Fatalf("create fixture directory %s: %v", path, err)
}
}
fakeGo := filepath.Join(fakeBin, "go")
if err := os.WriteFile(fakeGo, []byte(testScriptFakeGo), 0o755); err != nil {
t.Fatalf("write fake go: %v", err)
}
callLog := filepath.Join(root, "fake go calls")
if err := os.WriteFile(callLog, nil, 0o600); err != nil {
t.Fatalf("initialize fake-go call log: %v", err)
}
expected := callerBinary
if expected == "" {
expected = filepath.Join(testEnvRoot, "prebuilt-bd", "bd"+nativeExecutableSuffix())
}
bash, err := exec.LookPath("bash")
if err != nil {
t.Fatalf("bash is required to exercise scripts/test.sh: %v", err)
}
repoRoot := sourceRepoRoot(t)
env := testScriptEnvironment(testEnvRoot, tempRoot, expected, callerBinary)
fakeBinShellPath := shellPathUnderEnv(t, bash, fakeBin, env)
fakeGoShellPath := shellPathUnderEnv(t, bash, fakeGo, env)
driverShellPath := shellPathUnderEnv(t, bash, currentTestExecutable(t), env)
callLogShellPath := shellPathUnderEnv(t, bash, callLog, env)
env = append(env,
"BEADS_TEST_COMMAND_PATH="+fakeBinShellPath+":/usr/bin:/bin",
testScriptDriverEnv+"="+driverShellPath,
testScriptFakeGoLogEnv+"="+callLogShellPath,
)
cmd := exec.Command(
bash,
"--noprofile",
"--norc",
"-c",
`PATH="$BEADS_TEST_COMMAND_PATH"; export PATH; exec "$BASH" --noprofile --norc "$1" "$2"`,
"test-script",
shellPathUnderEnv(t, bash, filepath.Join(repoRoot, "scripts", "test.sh"), env),
"./cmd/bd",
)
cmd.Dir = repoRoot
cmd.Env = env
requireShellCommandPath(t, bash, repoRoot, env, "go", fakeGoShellPath)
output, runErr := cmd.CombinedOutput()
if runErr != nil {
t.Fatalf("scripts/test.sh failed: %v\n%s", runErr, output)
}
content, err := os.ReadFile(callLog)
if err != nil {
t.Fatalf("read fake-go call log: %v", err)
}
return strings.Fields(string(content))
}
func testScriptEnvironment(testEnvRoot string, tempRoot string, expected string, callerBinary string) []string {
home := filepath.Join(testEnvRoot, "home")
env := []string{
"PATH=/usr/bin:/bin",
"HOME=" + portableTestScriptPath(home),
"USERPROFILE=" + portableTestScriptPath(home),
"TMPDIR=" + portableTestScriptPath(tempRoot),
"TEMP=" + portableTestScriptPath(tempRoot),
"TMP=" + portableTestScriptPath(tempRoot),
"LC_ALL=C",
"LANG=C",
"BASH_ENV=",
"ENV=",
"CGO_ENABLED=1",
"GOFLAGS=",
"BEADS_TEST_ENV_ACTIVE=1",
"BEADS_TEST_ENV_ROOT=" + portableTestScriptPath(testEnvRoot),
testScriptExpectedBinaryEnv + "=" + portableTestScriptPath(expected),
testScriptExpectedBaseEnv + "=" + filepath.Base(expected),
testScriptNativeSuffixEnv + "=" + nativeExecutableSuffix(),
testScriptLaunchProbeEnv + "=1",
}
if callerBinary != "" {
env = append(env, "BEADS_TEST_BD_BINARY="+portableTestScriptPath(callerBinary))
}
for _, key := range []string{"SYSTEMROOT", "WINDIR", "COMSPEC", "PATHEXT"} {
if value, ok := os.LookupEnv(key); ok {
env = append(env, key+"="+value)
}
}
return env
}
func assertFakeGoCommands(t *testing.T, commands []string, want ...string) {
t.Helper()
if strings.Join(commands, " ") != strings.Join(want, " ") {
t.Fatalf("fake-go commands = %q, want %q", commands, want)
}
}
func copyCurrentTestExecutable(t *testing.T, destination string) {
t.Helper()
input, err := os.Open(currentTestExecutable(t))
if err != nil {
t.Fatalf("open current test executable: %v", err)
}
defer input.Close()
output, err := os.OpenFile(destination, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0o755)
if err != nil {
t.Fatalf("create native test executable: %v", err)
}
if _, err := io.Copy(output, input); err != nil {
_ = output.Close()
t.Fatalf("copy native test executable: %v", err)
}
if err := output.Close(); err != nil {
t.Fatalf("close native test executable: %v", err)
}
}
func currentTestExecutable(t *testing.T) string {
t.Helper()
path, err := os.Executable()
if err != nil {
t.Fatalf("resolve current test executable: %v", err)
}
return path
}
func sameTestScriptFile(first string, second string) bool {
firstInfo, firstErr := os.Stat(first)
secondInfo, secondErr := os.Stat(second)
return firstErr == nil && secondErr == nil && os.SameFile(firstInfo, secondInfo)
}
func nativeExecutableSuffix() string {
if runtime.GOOS == "windows" {
return ".exe"
}
return ""
}
func portableTestScriptPath(path string) string {
return filepath.ToSlash(filepath.Clean(path))
}