Files
picoclaw/integration/run_integration_tests_script_test.go
afjcjsbx ec21ddc222 fix lint
2026-05-13 19:57:38 +02:00

157 lines
3.5 KiB
Go

package integration
import (
"os"
"os/exec"
"path/filepath"
"strings"
"testing"
)
func TestRunIntegrationTestsScriptExecutesSuiteCommand(t *testing.T) {
bashPath, err := exec.LookPath("bash")
if err != nil {
t.Skip("bash not available")
}
repoRoot := repoRootFromTestFile(t)
suitesRoot := filepath.Join(repoRoot, "integration", "suites")
suiteDir, err := os.MkdirTemp(suitesRoot, "runner-script-")
if err != nil {
t.Fatalf("MkdirTemp() error = %v", err)
}
t.Cleanup(func() {
_ = os.RemoveAll(suiteDir)
})
suiteName := filepath.Base(suiteDir)
err = os.WriteFile(
filepath.Join(suiteDir, "suite.env"),
[]byte("TEST_COMMAND='printf runner-ok'\n"),
0o644,
)
if err != nil {
t.Fatalf("WriteFile(suite.env) error = %v", err)
}
err = os.WriteFile(
filepath.Join(suiteDir, "docker-compose.yml"),
[]byte("services:\n fake-dependency:\n image: busybox\n"),
0o644,
)
if err != nil {
t.Fatalf("WriteFile(docker-compose.yml) error = %v", err)
}
stubDir := t.TempDir()
logPath := filepath.Join(t.TempDir(), "docker.log")
err = os.WriteFile(filepath.Join(stubDir, "docker"), []byte(`#!/bin/sh
set -eu
log_file="${DOCKER_LOG:?}"
{
printf '%s\n' '---'
for arg in "$@"; do
printf '%s\n' "$arg"
done
} >>"$log_file"
subcommand=""
for arg in "$@"; do
case "$arg" in
config|up|run|down)
subcommand="$arg"
;;
esac
done
case "$subcommand" in
config)
printf '%s\n' integration-runner fake-dependency
;;
up)
;;
run)
printf '%s\n' runner-ok
;;
down)
;;
*)
printf 'unexpected docker invocation: %s\n' "$*" >&2
exit 1
;;
esac
`), 0o755)
if err != nil {
t.Fatalf("WriteFile(docker stub) error = %v", err)
}
cmd := exec.Command(bashPath, filepath.Join(repoRoot, "scripts", "run-integration-tests.sh"), suiteName)
cmd.Dir = repoRoot
cmd.Env = append(os.Environ(),
"PATH="+stubDir+string(os.PathListSeparator)+os.Getenv("PATH"),
"DOCKER_LOG="+logPath,
)
output, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("run-integration-tests.sh error = %v\noutput:\n%s", err, output)
}
if !strings.Contains(string(output), "runner-ok") {
t.Fatalf("script output did not include runner output:\n%s", output)
}
logData, err := os.ReadFile(logPath)
if err != nil {
t.Fatalf("ReadFile(logPath) error = %v", err)
}
runArgs := findLoggedDockerInvocation(t, string(logData), "run")
if strings.Contains(strings.Join(runArgs, "\n"), "\nsh\n-c\n") {
t.Fatalf("docker compose run unexpectedly wrapped TEST_COMMAND with sh -c:\n%v", runArgs)
}
if !containsArg(runArgs, "integration-runner") {
t.Fatalf("docker compose run args missing runner service:\n%v", runArgs)
}
if !containsArg(runArgs, "printf runner-ok") {
t.Fatalf("docker compose run args missing suite command as a single argument:\n%v", runArgs)
}
}
func repoRootFromTestFile(t *testing.T) string {
t.Helper()
wd, err := os.Getwd()
if err != nil {
t.Fatalf("Getwd() error = %v", err)
}
return filepath.Dir(wd)
}
func findLoggedDockerInvocation(t *testing.T, logData, subcommand string) []string {
t.Helper()
for _, block := range strings.Split(logData, "---\n") {
block = strings.TrimSpace(block)
if block == "" {
continue
}
args := strings.Split(block, "\n")
if containsArg(args, subcommand) {
return args
}
}
t.Fatalf("did not find docker %q invocation in log:\n%s", subcommand, logData)
return nil
}
func containsArg(args []string, want string) bool {
for _, arg := range args {
if arg == want {
return true
}
}
return false
}