Add `run_shell` argument handling tests (#62)
diff --git a/tests/run_shell/BUILD b/tests/run_shell/BUILD
new file mode 100644
index 0000000..71b8d92
--- /dev/null
+++ b/tests/run_shell/BUILD
@@ -0,0 +1,155 @@
+load("@bazel_skylib//rules:diff_test.bzl", "diff_test")
+load(
+ ":exec_fixtures.bzl",
+ "run_shell_helper_script_args",
+ "run_shell_long_output",
+ "run_shell_output",
+ "run_shell_output_with_action_env",
+ "run_shell_script_args",
+)
+load(":run_shell_tests.bzl", "run_shell_test_suite")
+
+run_shell_test_suite(name = "run_shell_tests")
+
+platform(
+ name = "linux_exec",
+ constraint_values = ["@platforms//os:linux"],
+)
+
+platform(
+ name = "windows_exec",
+ constraint_values = ["@platforms//os:windows"],
+)
+
+run_shell_output(
+ name = "basic_output",
+ command = "echo 'hello world' > $1",
+)
+
+diff_test(
+ name = "basic_output_test",
+ size = "small",
+ file1 = ":basic_output",
+ file2 = "basic_output.golden",
+)
+
+run_shell_output(
+ name = "positional_arguments",
+ command = "echo \"$2 $3\" > $1",
+ extra_arguments = [
+ "foo",
+ "bar",
+ ],
+)
+
+diff_test(
+ name = "positional_arguments_test",
+ size = "small",
+ file1 = ":positional_arguments",
+ file2 = "positional_arguments.golden",
+)
+
+run_shell_output(
+ name = "env",
+ command = "echo \"$FOO\" > $1",
+ env = {"FOO": "bar"},
+)
+
+diff_test(
+ name = "env_test",
+ size = "small",
+ file1 = ":env",
+ file2 = "env.golden",
+)
+
+# positional parameters of the command string, not of the script it runs.
+# Codifies https://github.com/bazelbuild/bazel/issues/6391 (working as intended).
+run_shell_script_args(
+ name = "script_args_not_forwarded",
+ forward_arguments = False,
+)
+
+diff_test(
+ name = "script_args_not_forwarded_test",
+ size = "small",
+ file1 = ":script_args_not_forwarded",
+ file2 = "script_args_not_forwarded.golden",
+)
+
+# Explicitly forwarding with "$@" passes `arguments` through to the script.
+run_shell_script_args(
+ name = "script_args_forwarded",
+ forward_arguments = True,
+)
+
+diff_test(
+ name = "script_args_forwarded_test",
+ size = "small",
+ file1 = ":script_args_forwarded",
+ file2 = "script_args_forwarded.golden",
+)
+
+# A command referencing $1 receives `arguments` when it runs inline...
+run_shell_helper_script_args(
+ name = "helper_script_args_inline",
+ long = False,
+)
+
+diff_test(
+ name = "helper_script_args_inline_test",
+ size = "small",
+ file1 = ":helper_script_args_inline",
+ file2 = "helper_script_args_inline.golden",
+)
+
+# ...but the same command spilled into a helper script does not: $1 is empty.
+# Codifies https://github.com/bazelbuild/bazel/issues/29365 (currently open bug).
+run_shell_helper_script_args(
+ name = "helper_script_args_spilled",
+ long = True,
+)
+
+diff_test(
+ name = "helper_script_args_spilled_test",
+ size = "small",
+ file1 = ":helper_script_args_spilled",
+ file2 = "helper_script_args_spilled.golden",
+)
+
+run_shell_long_output(
+ name = "long_command",
+)
+
+diff_test(
+ name = "long_command_test",
+ size = "small",
+ file1 = ":long_command",
+ file2 = "long_command.golden",
+)
+
+run_shell_output_with_action_env(
+ name = "use_default_shell_env",
+ command = "echo \"$FROM_ACTION_ENV\" > $1",
+ use_default_shell_env = True,
+)
+
+diff_test(
+ name = "use_default_shell_env_test",
+ size = "small",
+ file1 = ":use_default_shell_env",
+ file2 = "use_default_shell_env.golden",
+)
+
+run_shell_output_with_action_env(
+ name = "fixed_env_overrides_action_env",
+ command = "echo \"$FROM_ACTION_ENV\" > $1",
+ env = {"FROM_ACTION_ENV": "fixed_env_value"},
+ use_default_shell_env = True,
+)
+
+diff_test(
+ name = "fixed_env_overrides_action_env_test",
+ size = "small",
+ file1 = ":fixed_env_overrides_action_env",
+ file2 = "fixed_env_overrides_action_env.golden",
+)
diff --git a/tests/run_shell/BUILD.bazel b/tests/run_shell/BUILD.bazel
deleted file mode 100644
index 3fb5064..0000000
--- a/tests/run_shell/BUILD.bazel
+++ /dev/null
@@ -1,99 +0,0 @@
-load("@bazel_skylib//rules:diff_test.bzl", "diff_test")
-load(
- ":exec_fixtures.bzl",
- "run_shell_long_output",
- "run_shell_output",
- "run_shell_output_with_action_env",
-)
-load(":run_shell_tests.bzl", "run_shell_test_suite")
-
-run_shell_test_suite(name = "run_shell_tests")
-
-platform(
- name = "linux_exec",
- constraint_values = ["@platforms//os:linux"],
-)
-
-platform(
- name = "windows_exec",
- constraint_values = ["@platforms//os:windows"],
-)
-
-run_shell_output(
- name = "basic_output",
- command = "echo 'hello world' > $1",
-)
-
-diff_test(
- name = "basic_output_test",
- size = "small",
- file1 = ":basic_output",
- file2 = "basic_output.golden",
-)
-
-run_shell_output(
- name = "positional_arguments",
- command = "echo \"$2 $3\" > $1",
- extra_arguments = [
- "foo",
- "bar",
- ],
-)
-
-diff_test(
- name = "positional_arguments_test",
- size = "small",
- file1 = ":positional_arguments",
- file2 = "positional_arguments.golden",
-)
-
-run_shell_output(
- name = "env",
- command = "echo \"$FOO\" > $1",
- env = {"FOO": "bar"},
-)
-
-diff_test(
- name = "env_test",
- size = "small",
- file1 = ":env",
- file2 = "env.golden",
-)
-
-run_shell_long_output(
- name = "long_command",
-)
-
-diff_test(
- name = "long_command_test",
- size = "small",
- file1 = ":long_command",
- file2 = "long_command.golden",
-)
-
-run_shell_output_with_action_env(
- name = "use_default_shell_env",
- command = "echo \"$FROM_ACTION_ENV\" > $1",
- use_default_shell_env = True,
-)
-
-diff_test(
- name = "use_default_shell_env_test",
- size = "small",
- file1 = ":use_default_shell_env",
- file2 = "use_default_shell_env.golden",
-)
-
-run_shell_output_with_action_env(
- name = "fixed_env_overrides_action_env",
- command = "echo \"$FROM_ACTION_ENV\" > $1",
- env = {"FROM_ACTION_ENV": "fixed_env_value"},
- use_default_shell_env = True,
-)
-
-diff_test(
- name = "fixed_env_overrides_action_env_test",
- size = "small",
- file1 = ":fixed_env_overrides_action_env",
- file2 = "fixed_env_overrides_action_env.golden",
-)
diff --git a/tests/run_shell/exec_fixtures.bzl b/tests/run_shell/exec_fixtures.bzl
index 71943df..64a4b18 100644
--- a/tests/run_shell/exec_fixtures.bzl
+++ b/tests/run_shell/exec_fixtures.bzl
@@ -40,6 +40,68 @@
.build()
)
+def _run_shell_script_args_impl(ctx):
+ out = ctx.actions.declare_file(ctx.label.name + ".out")
+
+ # A script that records its own positional arguments.
+ script = ctx.actions.declare_file(ctx.label.name + "_echo_args.sh")
+ ctx.actions.write(
+ output = script,
+ content = """#!/bin/bash
+set -euo pipefail
+echo "args=($*)" > "$OUT"
+""",
+ is_executable = True,
+ )
+
+ # `arguments` are passed as the positional parameters ($1, $2, ...) of the
+ # command string (with an empty $0), not to a script named within it.
+ command = script.path
+ if ctx.attr.forward_arguments:
+ command += " \"$@\""
+
+ ctx.actions.run_shell(
+ outputs = [out],
+ tools = [script],
+ command = command,
+ arguments = ["a", "b", "c"],
+ env = {"OUT": out.path},
+ mnemonic = "RunShellScriptArgs",
+ )
+ return [DefaultInfo(files = depset([out]))]
+
+run_shell_script_args = rule(
+ implementation = _run_shell_script_args_impl,
+ attrs = {
+ "forward_arguments": attr.bool(),
+ },
+)
+
+def _run_shell_helper_script_args_impl(ctx):
+ out = ctx.actions.declare_file(ctx.label.name + ".out")
+
+ command = 'echo "arg=$1" > "$OUT"'
+ if ctx.attr.long:
+ # Pad past the spill threshold with a trailing comment so the command is
+ # written to a helper script without otherwise changing its behavior.
+ command += " #" + ("x" * 70000)
+
+ ctx.actions.run_shell(
+ outputs = [out],
+ command = command,
+ arguments = ["the_argument"],
+ env = {"OUT": out.path},
+ mnemonic = "RunShellHelperScriptArgs",
+ )
+ return [DefaultInfo(files = depset([out]))]
+
+run_shell_helper_script_args = rule(
+ implementation = _run_shell_helper_script_args_impl,
+ attrs = {
+ "long": attr.bool(),
+ },
+)
+
def _run_shell_long_output_impl(ctx):
out = ctx.actions.declare_file(ctx.label.name + ".out")
diff --git a/tests/run_shell/helper_script_args_inline.golden b/tests/run_shell/helper_script_args_inline.golden
new file mode 100644
index 0000000..43a1696
--- /dev/null
+++ b/tests/run_shell/helper_script_args_inline.golden
@@ -0,0 +1 @@
+arg=the_argument
diff --git a/tests/run_shell/helper_script_args_spilled.golden b/tests/run_shell/helper_script_args_spilled.golden
new file mode 100644
index 0000000..474b415
--- /dev/null
+++ b/tests/run_shell/helper_script_args_spilled.golden
@@ -0,0 +1 @@
+arg=
diff --git a/tests/run_shell/script_args_forwarded.golden b/tests/run_shell/script_args_forwarded.golden
new file mode 100644
index 0000000..a4107e3
--- /dev/null
+++ b/tests/run_shell/script_args_forwarded.golden
@@ -0,0 +1 @@
+args=(a b c)
diff --git a/tests/run_shell/script_args_not_forwarded.golden b/tests/run_shell/script_args_not_forwarded.golden
new file mode 100644
index 0000000..210a2fc
--- /dev/null
+++ b/tests/run_shell/script_args_not_forwarded.golden
@@ -0,0 +1 @@
+args=()