mirror of
https://github.com/gastownhall/beads.git
synced 2026-09-14 20:17:24 +08:00
bf930078e8
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
271 lines
8.4 KiB
Go
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))
|
|
}
|