diff --git a/pkg/sandbox/mock_script_test.go b/pkg/sandbox/mock_script_test.go new file mode 100644 index 000000000..fb281b00c --- /dev/null +++ b/pkg/sandbox/mock_script_test.go @@ -0,0 +1,46 @@ +package sandbox_test + +import ( + "os" + "os/exec" + "path/filepath" + "runtime" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestMockScriptsShareExecutable(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("POSIX shell fixture") + } + dir := filepath.Join(t.TempDir(), "space ' $dir") + require.NoError(t, os.Mkdir(dir, 0o700)) + writeMockScript(t, dir, "docker", `printf '<%s>\n' "$@" +printf 'diagnostic' >&2 +(exit 7)`) + writeMockScript(t, dir, "sbx", `exec /bin/sh -c 'printf alternate; exit 9'`) + docker := filepath.Join(dir, "docker") + sbx := filepath.Join(dir, "sbx") + first, err := os.Stat(docker) + require.NoError(t, err) + second, err := os.Stat(sbx) + require.NoError(t, err) + assert.True(t, os.SameFile(first, second)) + + cmd := exec.CommandContext(t.Context(), docker, "", "two words", "$(echo literal)") + cmd.Env = []string{"PATH=" + dir} + output, err := cmd.CombinedOutput() + var exitErr *exec.ExitError + require.ErrorAs(t, err, &exitErr) + assert.Equal(t, 7, exitErr.ExitCode()) + assert.Equal(t, "<>\n\n<$(echo literal)>\ndiagnostic", string(output)) + + cmd = exec.CommandContext(t.Context(), sbx) + cmd.Env = []string{"PATH=" + dir} + output, err = cmd.Output() + require.ErrorAs(t, err, &exitErr) + assert.Equal(t, 9, exitErr.ExitCode()) + assert.Equal(t, "alternate", string(output)) +} diff --git a/pkg/sandbox/sandbox_test.go b/pkg/sandbox/sandbox_test.go index 1fab46ff6..5ddc0d282 100644 --- a/pkg/sandbox/sandbox_test.go +++ b/pkg/sandbox/sandbox_test.go @@ -375,7 +375,7 @@ func TestBuildExecCmd(t *testing.T) { } } -// writeMockScript writes a mock executable script to the given directory. +// writeMockScript uses a shared executable with per-test script bodies on POSIX. // On Windows, it converts the POSIX shell script to a basic .bat script. // // Limitations: @@ -394,10 +394,15 @@ func writeMockScript(t *testing.T, dir, name, script string) { script = strings.ReplaceAll(script, "cat ", "type ") script = strings.ReplaceAll(script, "exit 0", "exit /b 0") script = "@echo off\n" + script - } else { - script = "#!/bin/sh\n" + script + require.NoError(t, os.WriteFile(filepath.Join(dir, name), []byte(script), 0o755)) + return } - require.NoError(t, os.WriteFile(filepath.Join(dir, name), []byte(script), 0o755)) + + launcher, err := filepath.Abs("testdata/cli") + require.NoError(t, err) + binary := filepath.Join(dir, name) + require.NoError(t, os.WriteFile(binary+".script", []byte(script), 0o600)) + require.NoError(t, os.Symlink(launcher, binary)) } func TestEnsureNeverRemovesOtherSandboxes(t *testing.T) { diff --git a/pkg/sandbox/testdata/cli b/pkg/sandbox/testdata/cli new file mode 100755 index 000000000..c6afda2c9 --- /dev/null +++ b/pkg/sandbox/testdata/cli @@ -0,0 +1,2 @@ +#!/bin/sh +. "$0.script"