diff --git a/src/main/java/com/google/devtools/build/lib/analysis/BUILD b/src/main/java/com/google/devtools/build/lib/analysis/BUILD index b630ac7daeac91..6f8804f361056f 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/BUILD +++ b/src/main/java/com/google/devtools/build/lib/analysis/BUILD @@ -1025,6 +1025,7 @@ java_library( name = "run_environment_info", srcs = ["RunEnvironmentInfo.java"], deps = [ + "//src/main/java/com/google/devtools/build/lib/actions", "//src/main/java/com/google/devtools/build/lib/concurrent", "//src/main/java/com/google/devtools/build/lib/packages", "//src/main/java/com/google/devtools/build/lib/starlarkbuildapi", diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTargetBuilder.java b/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTargetBuilder.java index 8a6a9728894f70..c13d5c98bdcafe 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTargetBuilder.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTargetBuilder.java @@ -474,6 +474,7 @@ private TestProvider initializeTestProvider(FilesToRunProvider filesToRunProvide if (environmentProvider != null) { testActionBuilder.addExtraEnv(environmentProvider.getEnvironment()); testActionBuilder.addExtraInheritedEnv(environmentProvider.getInheritedEnvironment()); + testActionBuilder.setStarlarkTargetArgs(environmentProvider.getArguments()); } TestParams testParams = diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RunEnvironmentInfo.java b/src/main/java/com/google/devtools/build/lib/analysis/RunEnvironmentInfo.java index 57b1c26f6c0b84..49a8af60636d58 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/RunEnvironmentInfo.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/RunEnvironmentInfo.java @@ -17,15 +17,20 @@ import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.google.devtools.build.lib.actions.CommandLine; import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; import com.google.devtools.build.lib.packages.BuiltinProvider; import com.google.devtools.build.lib.packages.NativeInfo; import com.google.devtools.build.lib.starlarkbuildapi.RunEnvironmentInfoApi; + +import java.util.ArrayList; import java.util.List; import java.util.Map; +import javax.annotation.Nullable; import net.starlark.java.eval.Dict; import net.starlark.java.eval.EvalException; import net.starlark.java.eval.Sequence; +import net.starlark.java.eval.Starlark; import net.starlark.java.eval.StarlarkList; /** @@ -40,16 +45,19 @@ public final class RunEnvironmentInfo extends NativeInfo implements RunEnvironme private final ImmutableMap environment; private final ImmutableList inheritedEnvironment; + @Nullable private final CommandLine arguments; private final boolean shouldErrorOnNonExecutableRule; /** Constructs a new provider with the given fixed and inherited environment variables. */ public RunEnvironmentInfo( Map environment, List inheritedEnvironment, + @Nullable CommandLine arguments, boolean shouldErrorOnNonExecutableRule) { this.environment = ImmutableMap.copyOf(Preconditions.checkNotNull(environment)); this.inheritedEnvironment = ImmutableList.copyOf(Preconditions.checkNotNull(inheritedEnvironment)); + this.arguments = arguments; this.shouldErrorOnNonExecutableRule = shouldErrorOnNonExecutableRule; } @@ -76,6 +84,11 @@ public ImmutableList getInheritedEnvironment() { return inheritedEnvironment; } + @Nullable + public CommandLine getArguments() { + return arguments; + } + /** * Returns whether advertising this provider on a non-executable (and thus non-test) rule should * result in an error or a warning. The latter is required to not break testing.TestEnvironment, @@ -95,11 +108,12 @@ private RunEnvironmentInfoProvider() { @Override public RunEnvironmentInfoApi constructor( - Dict environment, Sequence inheritedEnvironment) throws EvalException { + Dict environment, Sequence inheritedEnvironment, Object arguments) throws EvalException { return new RunEnvironmentInfo( Dict.cast(environment, String.class, String.class, "environment"), StarlarkList.immutableCopyOf( Sequence.cast(inheritedEnvironment, String.class, "inherited_environment")), + arguments == Starlark.NONE ? null : CommandLine.of(Sequence.cast(arguments, String.class, "arguments")), /* shouldErrorOnNonExecutableRule= */ true); } } diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RunfilesSupport.java b/src/main/java/com/google/devtools/build/lib/analysis/RunfilesSupport.java index ef668a7974a8be..00c3497c015861 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/RunfilesSupport.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/RunfilesSupport.java @@ -420,6 +420,20 @@ public static RunfilesSupport withExecutable( computeActionEnvironment(ruleContext)); } + /** + * Creates and returns a {@link RunfilesSupport} object for the given rule and executable without + * computing arguments based on the value of the "args" attribute. + */ + public static RunfilesSupport withExecutableNoArgs( + RuleContext ruleContext, Runfiles runfiles, Artifact executable) { + return RunfilesSupport.create( + ruleContext, + executable, + runfiles, + CommandLine.EMPTY, + computeActionEnvironment(ruleContext)); + } + /** * Creates and returns a {@link RunfilesSupport} object for the given rule and executable. Note * that this method calls back into the passed in rule to obtain the runfiles. diff --git a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkRuleConfiguredTargetUtil.java b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkRuleConfiguredTargetUtil.java index 3a18f0afb86a14..7e4dabe06f40b0 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkRuleConfiguredTargetUtil.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkRuleConfiguredTargetUtil.java @@ -343,30 +343,40 @@ private static void addProviders( } } + DefaultInfo defaultInfo = null; boolean defaultProviderProvidedExplicitly = false; + boolean starlarkArgsProvided = false; for (Info declaredProvider : declaredProviders.values()) { if (getProviderKey(declaredProvider).equals(DefaultInfo.PROVIDER.getKey())) { - parseDefaultProviderFields((DefaultInfo) declaredProvider, context, builder); + defaultInfo = (DefaultInfo) declaredProvider; defaultProviderProvidedExplicitly = true; - } else if (getProviderKey(declaredProvider).equals(RunEnvironmentInfo.PROVIDER.getKey()) - && !(context.isExecutable() || context.getRuleContext().isTestTarget())) { - String message = - "Returning RunEnvironmentInfo from a non-executable, non-test target has no effect"; - RunEnvironmentInfo runEnvironmentInfo = (RunEnvironmentInfo) declaredProvider; - if (runEnvironmentInfo.shouldErrorOnNonExecutableRule()) { - context.getRuleContext().ruleError(message); - } else { - context.getRuleContext().ruleWarning(message); - builder.addStarlarkDeclaredProvider(declaredProvider); + } else if (getProviderKey(declaredProvider).equals(RunEnvironmentInfo.PROVIDER.getKey())) { + if (((RunEnvironmentInfo) declaredProvider).getArguments() != null) { + // Ensure that RunfilesSupport does not parse the "args" attribute, the rule handles it in + // a custom way. + starlarkArgsProvided = true; + } + if (!(context.isExecutable() || context.getRuleContext().isTestTarget())) { + String message = + "Returning RunEnvironmentInfo from a non-executable, non-test target has no effect"; + RunEnvironmentInfo runEnvironmentInfo = (RunEnvironmentInfo) declaredProvider; + if (runEnvironmentInfo.shouldErrorOnNonExecutableRule()) { + context.getRuleContext().ruleError(message); + } else { + context.getRuleContext().ruleWarning(message); + } } + builder.addStarlarkDeclaredProvider(declaredProvider); } else { builder.addStarlarkDeclaredProvider(declaredProvider); } } - if (!defaultProviderProvidedExplicitly) { - parseDefaultProviderFields(oldStyleProviders, context, builder); + if (defaultProviderProvidedExplicitly) { + parseDefaultProviderFields(defaultInfo, context, builder, starlarkArgsProvided); + } else { + parseDefaultProviderFields(oldStyleProviders, context, builder, starlarkArgsProvided); } for (String field : oldStyleProviders.getFieldNames()) { @@ -491,7 +501,10 @@ private static Provider.Key getProviderKey(Info info) throws EvalException { * throws an {@link EvalException} if there are unknown fields. */ private static void parseDefaultProviderFields( - StructImpl info, StarlarkRuleContext context, RuleConfiguredTargetBuilder builder) + StructImpl info, + StarlarkRuleContext context, + RuleConfiguredTargetBuilder builder, + boolean starlarkArgsProvided) throws EvalException { Depset files = null; Runfiles statelessRunfiles = null; @@ -591,7 +604,8 @@ private static void parseDefaultProviderFields( files, statelessRunfiles, dataRunfiles, - defaultRunfiles); + defaultRunfiles, + starlarkArgsProvided); } private static void addSimpleProviders( @@ -601,7 +615,8 @@ private static void addSimpleProviders( @Nullable Depset files, Runfiles statelessRunfiles, Runfiles dataRunfiles, - Runfiles defaultRunfiles) + Runfiles defaultRunfiles, + boolean starlarkArgsProvided) throws EvalException { // TODO(bazel-team) if both 'files' and 'executable' are provided, 'files' overrides @@ -643,8 +658,13 @@ private static void addSimpleProviders( RunfilesSupport runfilesSupport = null; if (!computedDefaultRunfiles.isEmpty()) { Preconditions.checkNotNull(executable, "executable must not be null"); - runfilesSupport = - RunfilesSupport.withExecutable(ruleContext, computedDefaultRunfiles, executable); + if (starlarkArgsProvided) { + runfilesSupport = RunfilesSupport.withExecutableNoArgs( + ruleContext, computedDefaultRunfiles, executable); + } else { + runfilesSupport = + RunfilesSupport.withExecutable(ruleContext, computedDefaultRunfiles, executable); + } assertExecutableSymlinkPresent(runfilesSupport.getRunfiles(), executable); } builder.setRunfilesSupport(runfilesSupport, executable); diff --git a/src/main/java/com/google/devtools/build/lib/analysis/test/TestActionBuilder.java b/src/main/java/com/google/devtools/build/lib/analysis/test/TestActionBuilder.java index 69539f7b5857fb..4dc81ba22602f4 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/test/TestActionBuilder.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/test/TestActionBuilder.java @@ -25,6 +25,7 @@ import com.google.devtools.build.lib.actions.ActionOwner; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.actions.ArtifactRoot; +import com.google.devtools.build.lib.actions.CommandLine; import com.google.devtools.build.lib.actions.RunfilesSupplier; import com.google.devtools.build.lib.analysis.Allowlist; import com.google.devtools.build.lib.analysis.AnalysisEnvironment; @@ -98,12 +99,14 @@ public NestedSet getPackageSpecifications() { private int explicitShardCount; private final Map extraEnv; private final Set extraInheritedEnv; + @Nullable private CommandLine starlarkTargetArgs; public TestActionBuilder(RuleContext ruleContext) { this.ruleContext = ruleContext; this.extraEnv = new TreeMap<>(); this.extraInheritedEnv = new TreeSet<>(); this.additionalTools = new ImmutableList.Builder<>(); + this.starlarkTargetArgs = null; } /** @@ -180,6 +183,12 @@ public TestActionBuilder addExtraInheritedEnv(List extraInheritedEnv) { return this; } + @CanIgnoreReturnValue + public TestActionBuilder setStarlarkTargetArgs(@Nullable CommandLine starlarkTargetArgs) { + this.starlarkTargetArgs = starlarkTargetArgs; + return this; + } + /** Set the explicit shard count. Note that this may be overridden by the sharding strategy. */ @CanIgnoreReturnValue public TestActionBuilder setShardCount(int explicitShardCount) { @@ -340,6 +349,7 @@ private TestParams createTestAction(int shards) ruleContext, runfilesSupport, executable, + starlarkTargetArgs, instrumentedFileManifest, shards, runsPerTest); @@ -352,7 +362,13 @@ private TestParams createTestAction(int shards) } else { executionSettings = new TestTargetExecutionSettings( - ruleContext, runfilesSupport, executable, null, shards, runsPerTest); + ruleContext, + runfilesSupport, + executable, + starlarkTargetArgs, + null, + shards, + runsPerTest); } extraTestEnv.putAll(extraEnv); diff --git a/src/main/java/com/google/devtools/build/lib/analysis/test/TestTargetExecutionSettings.java b/src/main/java/com/google/devtools/build/lib/analysis/test/TestTargetExecutionSettings.java index 595f3342cb194d..c4e28fb59a11e4 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/test/TestTargetExecutionSettings.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/test/TestTargetExecutionSettings.java @@ -53,6 +53,7 @@ public final class TestTargetExecutionSettings { RuleContext ruleContext, RunfilesSupport runfilesSupport, Artifact executable, + @Nullable CommandLine starlarkTargetArgs, Artifact instrumentedFileManifest, int shards, int runs) @@ -62,7 +63,8 @@ public final class TestTargetExecutionSettings { BuildConfigurationValue config = ruleContext.getConfiguration(); TestConfiguration testConfig = config.getFragment(TestConfiguration.class); - CommandLine targetArgs = runfilesSupport.getArgs(); + CommandLine targetArgs = + starlarkTargetArgs != null ? starlarkTargetArgs : runfilesSupport.getArgs(); testArguments = CommandLine.concat(targetArgs, ImmutableList.copyOf(testConfig.getTestArguments())); diff --git a/src/main/java/com/google/devtools/build/lib/rules/test/StarlarkTestingModule.java b/src/main/java/com/google/devtools/build/lib/rules/test/StarlarkTestingModule.java index 20335fb6f35095..306282fdbf6e3e 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/test/StarlarkTestingModule.java +++ b/src/main/java/com/google/devtools/build/lib/rules/test/StarlarkTestingModule.java @@ -49,6 +49,7 @@ public RunEnvironmentInfo testEnvironment( Dict.cast(environment, String.class, String.class, "environment"), StarlarkList.immutableCopyOf( Sequence.cast(inheritedEnvironment, String.class, "inherited_environment")), + /* arguments= */null, /* shouldErrorOnNonExecutableRule= */ false); } diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/RunCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/RunCommand.java index 99bab5bfea0c2b..979f2a440d33ed 100644 --- a/src/main/java/com/google/devtools/build/lib/runtime/commands/RunCommand.java +++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/RunCommand.java @@ -176,19 +176,28 @@ protected BuildResult processRequest(final CommandEnvironment env, BuildRequest public void editOptions(OptionsParser optionsParser) { } /** - * Compute the arguments the binary should be run with by concatenating the arguments in its - * {@code args} attribute and the arguments on the Blaze command line. + * Compute the arguments the binary should be run with by concatenating the arguments provided by + * its {@link RunEnvironmentInfo} or, if not set, in its {@code args} attribute, and the arguments + * on the Blaze command line. */ - @Nullable private List computeArgs(ConfiguredTarget targetToRun, List commandLineArgs) throws InterruptedException, CommandLineExpansionException { List args = Lists.newArrayList(); - FilesToRunProvider provider = targetToRun.getProvider(FilesToRunProvider.class); - RunfilesSupport runfilesSupport = provider == null ? null : provider.getRunfilesSupport(); - if (runfilesSupport != null && runfilesSupport.getArgs() != null) { - CommandLine targetArgs = runfilesSupport.getArgs(); - Iterables.addAll(args, targetArgs.arguments()); + // If a Starlark rule explicitly sets arguments on RunEnvironmentInfo, these arguments take + // precedence over those obtained from the implicit "args" attribute on all rules so that + // Starlark rules can implement their own logic for this attribute. + RunEnvironmentInfo runEnvironmentInfo = + (RunEnvironmentInfo) targetToRun.get(RunEnvironmentInfo.PROVIDER.getKey()); + if (runEnvironmentInfo != null && runEnvironmentInfo.getArguments() != null) { + Iterables.addAll(args, runEnvironmentInfo.getArguments().arguments()); + } else { + FilesToRunProvider provider = targetToRun.getProvider(FilesToRunProvider.class); + RunfilesSupport runfilesSupport = provider == null ? null : provider.getRunfilesSupport(); + if (runfilesSupport != null && runfilesSupport.getArgs() != null) { + CommandLine targetArgs = runfilesSupport.getArgs(); + Iterables.addAll(args, targetArgs.arguments()); + } } args.addAll(commandLineArgs); return args; diff --git a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/RunEnvironmentInfoApi.java b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/RunEnvironmentInfoApi.java index 3de4fca081a126..3c18934ca64967 100644 --- a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/RunEnvironmentInfoApi.java +++ b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/RunEnvironmentInfoApi.java @@ -14,6 +14,7 @@ package com.google.devtools.build.lib.starlarkbuildapi; +import com.google.common.collect.ImmutableList; import com.google.devtools.build.docgen.annot.DocCategory; import com.google.devtools.build.docgen.annot.StarlarkConstructor; import com.google.devtools.build.lib.starlarkbuildapi.core.ProviderApi; @@ -26,11 +27,12 @@ import net.starlark.java.annot.StarlarkMethod; import net.starlark.java.eval.Dict; import net.starlark.java.eval.EvalException; +import net.starlark.java.eval.NoneType; import net.starlark.java.eval.Sequence; /** - * Provider containing any additional environment variables for use when running executables, either - * in test actions or when executed via the run command. + * Provider containing any additional environment variables and arguments for use when running + * executables, either in test actions or when executed via the run command. */ @StarlarkBuiltin( name = "RunEnvironmentInfo", @@ -78,7 +80,9 @@ interface RunEnvironmentInfoApiProvider extends ProviderApi { doc = "A map of string keys and values that represent environment variables and their" + " values. These will be made available when the target that returns this" - + " provider is executed, either as a test or via the run command."), + + " provider is executed, either as a test or via the run command. In the" + + " case of a test, environment variables specified on the command line via" + + " --test_env take precedence over values specified here."), @Param( name = "inherited_environment", allowedTypes = {@ParamType(type = Sequence.class, generic1 = String.class)}, @@ -91,13 +95,29 @@ interface RunEnvironmentInfoApiProvider extends ProviderApi { + " when the target that returns this provider is executed, either as a" + " test or via the run command. If a variable is contained in both " + "environment and inherited_environment, the value" - + " inherited from the shell environment will take precedence if set.") + + " inherited from the shell environment will take precedence if set."), + @Param( + name = "arguments", + allowedTypes = { + @ParamType(type = Sequence.class, generic1 = String.class), + @ParamType(type = NoneType.class) + }, + defaultValue = "None", + named = true, + positional = false, + doc = "A list of arguments. If set to a value other than None, this" + + " list will be appended to the command line when the target that returns" + + " this provider is executed, either as a test or via the run command. In" + + " this case, the arguments specified in the args attribute" + + " implicitly defined for all rules are not appended" + + " automatically.") }, selfCall = true) @StarlarkConstructor RunEnvironmentInfoApi constructor( Dict environment, // expected - Sequence inheritedEnvironment /* expected */) + Sequence inheritedEnvironment, /* expected */ + Object arguments /* Sequence or NoneType expected */) throws EvalException; } } diff --git a/src/test/java/com/google/devtools/build/lib/starlark/StarlarkIntegrationTest.java b/src/test/java/com/google/devtools/build/lib/starlark/StarlarkIntegrationTest.java index 21526932b03694..ed1c310f1fb282 100644 --- a/src/test/java/com/google/devtools/build/lib/starlark/StarlarkIntegrationTest.java +++ b/src/test/java/com/google/devtools/build/lib/starlark/StarlarkIntegrationTest.java @@ -3595,6 +3595,7 @@ public void testStarlarkRulePropagatesRunEnvironmentProvider() throws Exception "load(':rules.bzl', 'my_rule')", "my_rule(", " name = 'my_target',", + " args = ['magic'],", ")"); ConfiguredTarget starlarkTarget = getConfiguredTarget("//examples:my_target"); @@ -3602,6 +3603,44 @@ public void testStarlarkRulePropagatesRunEnvironmentProvider() throws Exception assertThat(provider.getEnvironment()).containsExactly("FIXED", "fixed"); assertThat(provider.getInheritedEnvironment()).containsExactly("INHERITED"); + assertThat(provider.getArguments()).isNotNull(); + assertThat(provider.getArguments().arguments()).containsExactly("magic"); + } + + @Test + public void testStarlarkRuleCanOverrideArgs() throws Exception { + scratch.file( + "examples/rules.bzl", + "def my_rule_impl(ctx):", + " script = ctx.actions.declare_file(ctx.attr.name)", + " ctx.actions.write(script, '', is_executable = True)", + " run_env = RunEnvironmentInfo(", + " arguments = ['from', '\\'star lark'],", + " )", + " return [", + " DefaultInfo(executable = script),", + " run_env,", + " ]", + "my_rule = rule(", + " implementation = my_rule_impl,", + " attrs = {},", + " executable = True,", + ")"); + scratch.file( + "examples/BUILD", + "load(':rules.bzl', 'my_rule')", + "my_rule(", + " name = 'my_target',", + " args = ['magic', '$(location //:invalid_should_not_be_evaluated)'],", + ")"); + + ConfiguredTarget starlarkTarget = getConfiguredTarget("//examples:my_target"); + RunEnvironmentInfo provider = starlarkTarget.get(RunEnvironmentInfo.PROVIDER); + + assertThat(provider.getEnvironment()).isEmpty(); + assertThat(provider.getInheritedEnvironment()).isEmpty(); + assertThat(provider.getArguments()).isNotNull(); + assertThat(provider.getArguments().arguments()).containsExactly("from", "'star lark"); } @Test diff --git a/src/test/shell/bazel/bazel_rules_test.sh b/src/test/shell/bazel/bazel_rules_test.sh index f4d69224e261e4..10cb6be2a0abee 100755 --- a/src/test/shell/bazel/bazel_rules_test.sh +++ b/src/test/shell/bazel/bazel_rules_test.sh @@ -593,12 +593,13 @@ EOF assert_contains "hello world" bazel-bin/pkg/hello_gen.txt } -function test_starlark_test_with_test_environment() { +function test_starlark_test_with_run_environment() { mkdir pkg cat >pkg/BUILD <<'EOF' load(":rules.bzl", "my_test") my_test( name = "my_test", + args = ["magic1", "magic2"], ) EOF @@ -608,22 +609,42 @@ EOF cat >pkg/rules.bzl <<'EOF' _SCRIPT_EXT = ".bat" _SCRIPT_CONTENT = """@ECHO OFF +set +echo "Arguments: %*" if not "%FIXED_ONLY%" == "fixed" exit /B 1 if not "%FIXED_AND_INHERITED%" == "inherited" exit /B 1 if not "%FIXED_AND_INHERITED_BUT_NOT_SET%" == "fixed" exit /B 1 if not "%INHERITED_ONLY%" == "inherited" exit /B 1 +if not "%TEST_ENV_FIXED%" == "fixed" exit /B 1 +if not "%TEST_ENV_INHERITED%" == "inherited" exit /B 1 +if not "%TEST_ENV_OVERRIDDEN%" == "overridden" exit /B 1 if defined INHERITED_BUT_UNSET exit /B 1 +if not "%1" == "starlark1" exit /B 1 +if not "%2" == "starlark2" exit /B 1 +if not "%3" == "test_arg1" exit /B 1 +if not "%4" == "test_arg2" exit /B 1 +if not "%~5" == "" exit /B 1 """ EOF else cat >pkg/rules.bzl <<'EOF' _SCRIPT_EXT = ".sh" _SCRIPT_CONTENT = """#!/bin/bash +env +echo "Arguments: $@" [[ "$FIXED_ONLY" == "fixed" \ && "$FIXED_AND_INHERITED" == "inherited" \ && "$FIXED_AND_INHERITED_BUT_NOT_SET" == "fixed" \ && "$INHERITED_ONLY" == "inherited" \ - && -z "${INHERITED_BUT_UNSET+default}" ]] + && "$TEST_ENV_FIXED" == "fixed" \ + && "$TEST_ENV_INHERITED" == "inherited" \ + && "$TEST_ENV_OVERRIDDEN" == "overridden" \ + && -z "${INHERITED_BUT_UNSET+default}" \ + && "$1" == "starlark1" \ + && "$2" == "starlark2" \ + && "$3" == "test_arg1" \ + && "$4" == "test_arg2" \ + && "$#" -eq 4 ]] """ EOF fi @@ -636,18 +657,20 @@ def _my_test_impl(ctx): content = _SCRIPT_CONTENT, is_executable = True, ) - test_env = testing.TestEnvironment( + test_env = RunEnvironmentInfo( { "FIXED_AND_INHERITED": "fixed", "FIXED_AND_INHERITED_BUT_NOT_SET": "fixed", "FIXED_ONLY": "fixed", + "TEST_ENV_OVERRIDDEN": "not_overridden", }, [ "FIXED_AND_INHERITED", "FIXED_AND_INHERITED_BUT_NOT_SET", "INHERITED_ONLY", "INHERITED_BUT_UNSET", - ] + ], + arguments = ["starlark1", "starlark2"], ) return [ DefaultInfo( @@ -663,8 +686,10 @@ my_test = rule( ) EOF - FIXED_AND_INHERITED=inherited INHERITED_ONLY=inherited \ - bazel test //pkg:my_test >$TEST_log 2>&1 || fail "Test should pass" + FIXED_AND_INHERITED=inherited INHERITED_ONLY=inherited TEST_ENV_INHERITED=inherited \ + bazel test --test_env=TEST_ENV_FIXED=fixed --test_env=TEST_ENV_INHERITED --test_env=TEST_ENV_OVERRIDDEN=overridden \ + --test_arg=test_arg1 --test_arg=test_arg2 \ + //pkg:my_test --test_output=errors >$TEST_log 2>&1 || fail "Test should pass" } function test_starlark_rule_with_run_environment() { @@ -673,6 +698,7 @@ function test_starlark_rule_with_run_environment() { load(":rules.bzl", "my_executable") my_executable( name = "my_executable", + args = ["magic1", "magic2"], ) EOF @@ -687,6 +713,9 @@ if not "%FIXED_AND_INHERITED%" == "inherited" exit /B 1 if not "%FIXED_AND_INHERITED_BUT_NOT_SET%" == "fixed" exit /B 1 if not "%INHERITED_ONLY%" == "inherited" exit /B 1 if defined INHERITED_BUT_UNSET exit /B 1 +if not "%1" == "starlark1" exit /B 1 +if not "%2" == "starlark2" exit /B 1 +if not "%~3" == "" exit /B 1 """ EOF else @@ -699,7 +728,10 @@ env && "$FIXED_AND_INHERITED" == "inherited" \ && "$FIXED_AND_INHERITED_BUT_NOT_SET" == "fixed" \ && "$INHERITED_ONLY" == "inherited" \ - && -z "${INHERITED_BUT_UNSET+default}" ]] + && -z "${INHERITED_BUT_UNSET+default}" \ + && "$1" == "starlark1" \ + && "$2" == "starlark2" \ + && "$#" -eq 2 ]] """ EOF fi @@ -723,7 +755,8 @@ def _my_executable_impl(ctx): "FIXED_AND_INHERITED_BUT_NOT_SET", "INHERITED_ONLY", "INHERITED_BUT_UNSET", - ] + ], + arguments = ["starlark1", "starlark2"], ) return [ DefaultInfo(