| // Copyright 2021 The Bazel Authors. All rights reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| package com.google.devtools.build.lib.analysis.test; |
| |
| import static com.google.common.truth.Truth.assertThat; |
| |
| import com.google.common.base.Preconditions; |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.ImmutableMap; |
| import com.google.common.collect.Iterables; |
| import com.google.common.eventbus.EventBus; |
| import com.google.devtools.build.lib.actions.Artifact; |
| import com.google.devtools.build.lib.analysis.AnalysisResult; |
| import com.google.devtools.build.lib.analysis.ConfiguredAspect; |
| import com.google.devtools.build.lib.analysis.ConfiguredTarget; |
| import com.google.devtools.build.lib.analysis.TransitiveInfoCollection; |
| import com.google.devtools.build.lib.analysis.util.BuildViewTestCase; |
| import com.google.devtools.build.lib.cmdline.Label; |
| import com.google.devtools.build.lib.collect.nestedset.Depset; |
| import com.google.devtools.build.lib.packages.StarlarkProvider; |
| import com.google.devtools.build.lib.packages.StructImpl; |
| import com.google.devtools.build.lib.packages.TestTimeout; |
| import com.google.devtools.build.lib.testutil.TestConstants; |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Set; |
| import org.junit.Before; |
| import org.junit.Ignore; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.junit.runners.JUnit4; |
| |
| /** {@link com.google.devtools.build.lib.analysis.test.TestActionBuilder} tests. */ |
| @RunWith(JUnit4.class) |
| public class TestActionBuilderTest extends BuildViewTestCase { |
| |
| @Before |
| public final void createBuildFile() throws Exception { |
| analysisMock.pySupport().setup(mockToolsConfig); |
| |
| scratch.file( |
| "tests/BUILD", |
| "py_test(name = 'small_test_1',", |
| " srcs = ['small_test_1.py'],", |
| " data = [':xUnit'],", |
| " size = 'small',", |
| " tags = ['tag1'])", |
| "", |
| "sh_test(name = 'small_test_2',", |
| " srcs = ['small_test_2.sh'],", |
| " size = 'small',", |
| " tags = ['tag2'])", |
| "", |
| "sh_test(name = 'large_test_1',", |
| " srcs = ['large_test_1.sh'],", |
| " data = [':xUnit'],", |
| " size = 'large',", |
| " tags = ['tag1'])", |
| "", |
| "py_binary(name = 'notest',", |
| " srcs = ['notest.py'])", |
| "cc_library(name = 'xUnit')", |
| "", |
| "test_suite(name = 'smallTests', tags=['small'])"); |
| } |
| |
| private void assertSharded(ConfiguredTarget testRule, int expectSharding) { |
| ImmutableList<Artifact.DerivedArtifact> testStatusList = getTestStatusArtifacts(testRule); |
| if (expectSharding == 0) { |
| Artifact testResult = Iterables.getOnlyElement(testStatusList); |
| TestRunnerAction action = (TestRunnerAction) getGeneratingAction(testResult); |
| assertThat(action.isSharded()).isFalse(); |
| assertThat(action.getExecutionSettings().getTotalShards()).isSameInstanceAs(0); |
| assertThat(action.getShardNum()).isSameInstanceAs(0); |
| return; |
| } |
| |
| int totalShards = testStatusList.size(); |
| Set<Integer> shardNumbers = new HashSet<>(); |
| for (Artifact testResult : testStatusList) { |
| TestRunnerAction action = (TestRunnerAction) getGeneratingAction(testResult); |
| assertThat(action.isSharded()).isTrue(); |
| assertThat(action.getExecutionSettings().getTotalShards()).isSameInstanceAs(totalShards); |
| assertThat(action.getTestLog().getExecPath().getPathString()) |
| .endsWith( |
| String.format("shard_%d_of_%d/test.log", action.getShardNum() + 1, totalShards)); |
| shardNumbers.add(action.getShardNum()); |
| } |
| assertThat(shardNumbers).isEqualTo(sequenceSet(0, totalShards)); |
| assertThat(shardNumbers).hasSize(expectSharding); |
| } |
| |
| private static Set<Integer> sequenceSet(int start, int end) { |
| Preconditions.checkArgument(end > start); |
| Set<Integer> seqSet = new HashSet<>(); |
| for (int i = start; i < end; i++) { |
| seqSet.add(i); |
| } |
| return seqSet; |
| } |
| |
| private void writeJavaTests() throws IOException { |
| scratch.file( |
| "javatests/jt/BUILD", |
| "java_test(name = 'RGT',", |
| " srcs = ['RGT.java'])", |
| "java_test(name = 'RGT_none',", |
| " shard_count = 0,", |
| " srcs = ['RGT.java'])", |
| "java_test(name = 'RGT_many',", |
| " shard_count = 33,", |
| " srcs = ['RGT.java'])", |
| "java_test(name = 'RGT_small',", |
| " srcs = ['RGT.java'],", |
| " size = 'small')", |
| "", |
| "java_test(name = 'NoRunner',", |
| " main_class = 'NoTestRunnerTest.java',", |
| " use_testrunner = 0,", |
| " srcs = ['NoTestRunnerTest.java'])", |
| ""); |
| } |
| |
| @Test |
| public void testSharding() throws Exception { |
| useConfiguration("--test_sharding_strategy=explicit"); |
| |
| assertSharded(getConfiguredTarget("//tests:small_test_1"), 0); |
| assertSharded(getConfiguredTarget("//tests:large_test_1"), 0); |
| |
| writeJavaTests(); |
| assertSharded(getConfiguredTarget("//javatests/jt:NoRunner"), 0); |
| assertSharded(getConfiguredTarget("//javatests/jt:RGT"), 0); |
| assertSharded(getConfiguredTarget("//javatests/jt:RGT_small"), 0); |
| assertSharded(getConfiguredTarget("//javatests/jt:RGT_none"), 0); |
| |
| // Has an explicit "shard_count" attribute. |
| assertSharded(getConfiguredTarget("//javatests/jt:RGT_many"), 33); |
| } |
| |
| @Test |
| public void testShardingDisabled() throws Exception { |
| useConfiguration("--test_sharding_strategy=disabled"); |
| |
| assertSharded(getConfiguredTarget("//tests:small_test_1"), 0); |
| assertSharded(getConfiguredTarget("//tests:large_test_1"), 0); |
| |
| writeJavaTests(); |
| assertSharded(getConfiguredTarget("//javatests/jt:NoRunner"), 0); |
| assertSharded(getConfiguredTarget("//javatests/jt:RGT"), 0); |
| assertSharded(getConfiguredTarget("//javatests/jt:RGT_small"), 0); |
| assertSharded(getConfiguredTarget("//javatests/jt:RGT_none"), 0); |
| |
| // Has an explicit "shard_count" attribute. |
| assertSharded(getConfiguredTarget("//javatests/jt:RGT_many"), 0); |
| } |
| |
| @Test |
| public void testShardingForced() throws Exception { |
| useConfiguration("--test_sharding_strategy=forced=5"); |
| |
| assertSharded(getConfiguredTarget("//tests:small_test_1"), 5); |
| assertSharded(getConfiguredTarget("//tests:large_test_1"), 5); |
| |
| writeJavaTests(); |
| assertSharded(getConfiguredTarget("//javatests/jt:NoRunner"), 5); |
| assertSharded(getConfiguredTarget("//javatests/jt:RGT"), 5); |
| assertSharded(getConfiguredTarget("//javatests/jt:RGT_small"), 5); |
| assertSharded(getConfiguredTarget("//javatests/jt:RGT_none"), 5); |
| assertSharded(getConfiguredTarget("//javatests/jt:RGT_many"), 5); |
| } |
| |
| @Test |
| public void testFlakyAttributeValidation() throws Exception { |
| scratch.file("flaky/BUILD", |
| "sh_test(name = 'good_test',", |
| " srcs = ['a.sh'])", |
| "sh_test(name = 'flaky_test',", |
| " srcs = ['a.sh'],", |
| " flaky = 1)"); |
| Artifact testStatus = Iterables.getOnlyElement(getTestStatusArtifacts("//flaky:good_test")); |
| assertThat(testStatus).isNotNull(); |
| TestRunnerAction action = (TestRunnerAction) getGeneratingAction(testStatus); |
| assertThat(action.getTestProperties().isFlaky()).isFalse(); |
| |
| testStatus = Iterables.getOnlyElement(getTestStatusArtifacts("//flaky:flaky_test")); |
| assertThat(testStatus).isNotNull(); |
| action = (TestRunnerAction) getGeneratingAction(testStatus); |
| assertThat(action.getTestProperties().isFlaky()).isTrue(); |
| } |
| |
| @Test |
| public void testIllegalBooleanFlakySetting() throws Exception { |
| checkError("flaky", "bad_test", |
| "boolean is not one of [0, 1]", |
| "sh_test(name = 'bad_test',", |
| " srcs = ['a.sh'],", |
| " flaky = 2)"); |
| } |
| |
| @Test |
| public void testRunsPerTest() throws Exception { |
| useConfiguration("--runs_per_test=2"); |
| ImmutableList<Artifact.DerivedArtifact> testStatusList = |
| getTestStatusArtifacts("//tests:small_test_1"); |
| assertThat(testStatusList).hasSize(2); |
| Artifact testStatus1 = testStatusList.get(0); |
| Artifact testStatus2 = testStatusList.get(1); |
| assertThat(testStatus1).isNotNull(); |
| assertThat(testStatus2).isNotNull(); |
| assertThat(testStatus2).isNotSameInstanceAs(testStatus1); |
| assertThat(getGeneratingAction(testStatus2)) |
| .isNotSameInstanceAs(getGeneratingAction(testStatus1)); |
| assertThat(testStatus1.getRootRelativePath().getPathString()) |
| .contains("tests/small_test_1/run_1_of_2/test"); |
| assertThat(testStatus2.getRootRelativePath().getPathString()) |
| .contains("tests/small_test_1/run_2_of_2/test"); |
| } |
| |
| @Test |
| public void testRunsPerTestCanBeOverridden() throws Exception { |
| useConfiguration("--runs_per_test=1", "--runs_per_test=2"); |
| ImmutableList<Artifact.DerivedArtifact> testStatusList = |
| getTestStatusArtifacts("//tests:small_test_1"); |
| assertThat(testStatusList).hasSize(2); |
| Artifact testStatus1 = testStatusList.get(0); |
| Artifact testStatus2 = testStatusList.get(1); |
| assertThat(testStatus1).isNotNull(); |
| assertThat(testStatus2).isNotNull(); |
| assertThat(testStatus2).isNotSameInstanceAs(testStatus1); |
| assertThat(getGeneratingAction(testStatus2)) |
| .isNotSameInstanceAs(getGeneratingAction(testStatus1)); |
| assertThat(testStatus1.getRootRelativePath().getPathString()) |
| .contains("tests/small_test_1/run_1_of_2/test"); |
| assertThat(testStatus2.getRootRelativePath().getPathString()) |
| .contains("tests/small_test_1/run_2_of_2/test"); |
| } |
| |
| /** |
| * Test that test rules always construct with a standard timeout, either |
| * inferred from size or explicitly set by attribute. |
| */ |
| @Test |
| public void testTestTimeoutFlagOverridesTimeoutDefaultsValues() throws Exception { |
| scratch.file("javatests/timeouts/BUILD", |
| "java_test(name = 'small_no_timeout',", |
| " srcs = [],", |
| " size = 'small')", |
| "java_test(name = 'small_with_timeout',", |
| " srcs = [],", |
| " size = 'small',", |
| " timeout = 'long')"); |
| ImmutableList<Artifact.DerivedArtifact> testStatusList = |
| getTestStatusArtifacts("//javatests/timeouts:small_no_timeout"); |
| TestRunnerAction testAction = (TestRunnerAction) |
| getGeneratingAction(Iterables.get(testStatusList, 0)); |
| Integer timeout = testAction.getTestProperties().getTimeout().getTimeoutSeconds(); |
| assertThat(timeout).isEqualTo(TestTimeout.SHORT.getTimeoutSeconds()); |
| |
| testStatusList = getTestStatusArtifacts("//javatests/timeouts:small_with_timeout"); |
| testAction = (TestRunnerAction) getGeneratingAction(Iterables.get(testStatusList, 0)); |
| timeout = testAction.getTestProperties().getTimeout().getTimeoutSeconds(); |
| assertThat(timeout).isEqualTo(TestTimeout.LONG.getTimeoutSeconds()); |
| } |
| |
| @Test |
| public void testRunsPerTestWithSharding() throws Exception { |
| useConfiguration("--runs_per_test=2"); |
| scratch.file( |
| "javatests/jt/BUILD", |
| "java_test(name = 'RGT',", |
| " shard_count = 10,", |
| " srcs = ['RGT.java'])"); |
| ImmutableList<Artifact.DerivedArtifact> testStatusList = |
| getTestStatusArtifacts("//javatests/jt:RGT"); |
| assertThat(testStatusList).hasSize(20); |
| Artifact testStatus1 = testStatusList.get(0); |
| Artifact testStatus10 = testStatusList.get(9); |
| Artifact testStatus11 = testStatusList.get(10); |
| assertThat(testStatus1).isNotNull(); |
| assertThat(testStatus10).isNotNull(); |
| assertThat(testStatus11).isNotNull(); |
| assertThat(testStatus1.getRootRelativePath().getPathString()) |
| .contains("javatests/jt/RGT/shard_1_of_10_run_1_of_2/test"); |
| assertThat(testStatus10.getRootRelativePath().getPathString()) |
| .contains("javatests/jt/RGT/shard_5_of_10_run_2_of_2/test"); |
| assertThat(testStatus11.getRootRelativePath().getPathString()) |
| .contains("javatests/jt/RGT/shard_6_of_10_run_1_of_2/test"); |
| } |
| |
| @Test |
| public void testAspectOverNonExpandingTestSuitesVisitsImplicitTests() throws Exception { |
| scratch.file( |
| "BUILD", |
| "sh_test(name = 'test_a',", |
| " srcs = [':a.sh'])", |
| "", |
| "sh_test(name = 'test_b',", |
| " srcs = [':b.sh'])", |
| "", |
| "test_suite(name = 'suite'", |
| ")"); |
| writeLabelCollectionAspect(); |
| |
| useLoadingOptions("--noexpand_test_suites"); |
| AnalysisResult analysisResult = |
| update( |
| ImmutableList.of("//:suite"), |
| ImmutableList.of("//:aspect.bzl%a"), |
| /* keepGoing= */ false, |
| /* loadingPhaseThreads= */ 1, |
| /* doAnalysis= */ true, |
| new EventBus()); |
| ConfiguredAspect aspectValue = |
| Iterables.getOnlyElement(analysisResult.getAspectsMap().values()); |
| StarlarkProvider.Key key = |
| new StarlarkProvider.Key(Label.parseCanonicalUnchecked("//:aspect.bzl"), "StructImpl"); |
| StructImpl info = (StructImpl) aspectValue.get(key); |
| assertThat(((Depset) info.getValue("labels")).getSet(String.class).toList()) |
| .containsExactly("@@//:suite", "@@//:test_a", "@@//:test_b"); |
| } |
| |
| @Test |
| public void testAspectOverNonExpandingTestSuitesVisitsExplicitTests() throws Exception { |
| scratch.file( |
| "BUILD", |
| "sh_test(name = 'test_a',", |
| " srcs = [':a.sh'])", |
| "", |
| "sh_test(name = 'test_b',", |
| " srcs = [':b.sh'])", |
| "", |
| "test_suite(name = 'suite',", |
| " tests = [':test_b']", |
| ")"); |
| writeLabelCollectionAspect(); |
| |
| useLoadingOptions("--noexpand_test_suites"); |
| AnalysisResult analysisResult = |
| update( |
| ImmutableList.of("//:suite"), |
| ImmutableList.of("//:aspect.bzl%a"), |
| /* keepGoing= */ false, |
| /* loadingPhaseThreads= */ 1, |
| /* doAnalysis= */ true, |
| new EventBus()); |
| ConfiguredAspect aspectValue = |
| Iterables.getOnlyElement(analysisResult.getAspectsMap().values()); |
| StarlarkProvider.Key key = |
| new StarlarkProvider.Key(Label.parseCanonicalUnchecked("//:aspect.bzl"), "StructImpl"); |
| StructImpl info = (StructImpl) aspectValue.get(key); |
| assertThat(((Depset) info.getValue("labels")).getSet(String.class).toList()) |
| .containsExactly("@@//:suite", "@@//:test_b"); |
| } |
| |
| @Test |
| public void testAspectOverExpandingTestSuitesDoesNotVisitSuite() throws Exception { |
| scratch.file( |
| "BUILD", |
| "sh_test(name = 'test_a',", |
| " srcs = [':a.sh'])", |
| "", |
| "sh_test(name = 'test_b',", |
| " srcs = [':b.sh'])", |
| "", |
| "test_suite(name = 'suite',", |
| ")"); |
| writeLabelCollectionAspect(); |
| |
| AnalysisResult analysisResult = |
| update( |
| ImmutableList.of("//:suite"), |
| ImmutableList.of("//:aspect.bzl%a"), |
| /* keepGoing= */ false, |
| /* loadingPhaseThreads= */ 1, |
| /* doAnalysis= */ true, |
| new EventBus()); |
| final StarlarkProvider.Key key = |
| new StarlarkProvider.Key(Label.parseCanonicalUnchecked("//:aspect.bzl"), "StructImpl"); |
| |
| List<String> labels = new ArrayList<>(); |
| for (ConfiguredAspect a : analysisResult.getAspectsMap().values()) { |
| StructImpl info = (StructImpl) a.get(key); |
| labels.addAll(((Depset) info.getValue("labels")).getSet(String.class).toList()); |
| } |
| assertThat(labels).containsExactly("@@//:test_a", "@@//:test_b"); |
| } |
| |
| private void writeLabelCollectionAspect() throws IOException { |
| scratch.file( |
| "aspect.bzl", |
| "StructImpl = provider(fields = ['labels'])", |
| "def _impl(target,ctx):", |
| " print(target.label)", |
| " transitive = []", |
| " if hasattr(ctx.rule.attr, 'tests'):", |
| " transitive += [dep[StructImpl].labels for dep in ctx.rule.attr.tests]", |
| " if hasattr(ctx.rule.attr, '_implicit_tests'):", |
| " transitive += [dep[StructImpl].labels for dep in ctx.rule.attr._implicit_tests]", |
| " return [StructImpl(labels = depset([str(target.label)], transitive = transitive))]", |
| "", |
| "a = aspect(_impl, attr_aspects = ['tests', '_implicit_tests'])"); |
| } |
| |
| /** |
| * Regression test for bug {@link "http://b/2644860"}. |
| */ |
| @Test |
| public void testIllegalTestSizeAttributeDoesNotCrashTestSuite() throws Exception { |
| checkError("bad_size", "illegal_size_test", |
| "In rule 'illegal_size_test', size 'bad' is not a valid size", |
| "sh_test(name = 'illegal_size_test',", |
| " srcs = ['illegal.sh'],", |
| " size = 'bad')", |
| "test_suite(name = 'everything')"); |
| } |
| |
| /** |
| * Regression test for bug {@link "http://b/2644860"} but with an illegal Timeout. |
| */ |
| @Test |
| public void testIllegalTestTimeoutAttributeDoesNotCrashTestSuite() throws Exception { |
| checkError("bad_timeout", "illegal_timeout_test", |
| "In rule 'illegal_timeout_test', timeout 'unreasonable' is not a valid timeout", |
| "sh_test(name = 'illegal_timeout_test',", |
| " srcs = ['illegal.sh'],", |
| " timeout = 'unreasonable')", |
| "test_suite(name = 'everything')"); |
| } |
| |
| /** |
| * Overriding the exec group from within the test affects the way exec properties are selected. |
| */ |
| @Test |
| public void testOverrideExecGroup() throws Exception { |
| scratch.file( |
| "some_test.bzl", |
| "def _some_test_impl(ctx):", |
| " script = ctx.actions.declare_file(ctx.attr.name + '.sh')", |
| " ctx.actions.write(script, 'shell script goes here', is_executable = True)", |
| " return [", |
| " DefaultInfo(executable = script),", |
| " testing.ExecutionInfo({}, exec_group = 'custom_group'),", |
| " ]", |
| "", |
| "some_test = rule(", |
| " implementation = _some_test_impl,", |
| " exec_groups = {'custom_group': exec_group()},", |
| " test = True,", |
| ")"); |
| scratch.file( |
| "BUILD", |
| "load(':some_test.bzl', 'some_test')", |
| "some_test(", |
| " name = 'custom_exec_group_test',", |
| " exec_properties = {'test.key': 'bad', 'custom_group.key': 'good'},", |
| ")"); |
| ImmutableList<Artifact.DerivedArtifact> testStatusList = |
| getTestStatusArtifacts("//:custom_exec_group_test"); |
| TestRunnerAction testAction = (TestRunnerAction) getGeneratingAction(testStatusList.get(0)); |
| ImmutableMap<String, String> executionInfo = testAction.getExecutionInfo(); |
| assertThat(executionInfo).containsExactly("key", "good"); |
| } |
| |
| /** |
| * Overriding the exec group from within the test with --use_target_platform_for_tests. |
| * |
| * <p>This is the same test as testOverrideExecGroup with --use_target_platform_for_tests and a |
| * target platform. |
| */ |
| @Test |
| public void testOverrideTestExecGroup() throws Exception { |
| useConfiguration("--use_target_platform_for_tests=true", "--platforms=//:linux_aarch64"); |
| scratch.file( |
| "some_test.bzl", |
| "def _some_test_impl(ctx):", |
| " script = ctx.actions.declare_file(ctx.attr.name + '.sh')", |
| " ctx.actions.write(script, 'shell script goes here', is_executable = True)", |
| " return [", |
| " DefaultInfo(executable = script),", |
| " testing.ExecutionInfo({}, exec_group = 'custom_group'),", |
| " ]", |
| "", |
| "some_test = rule(", |
| " implementation = _some_test_impl,", |
| " exec_groups = {'custom_group': exec_group()},", |
| " test = True,", |
| ")"); |
| scratch.file( |
| "BUILD", |
| "load(':some_test.bzl', 'some_test')", |
| "platform(", |
| " name = 'linux_aarch64',", |
| " constraint_values = [", |
| " '" + TestConstants.CONSTRAINTS_PACKAGE_ROOT + "os:linux',", |
| " '" + TestConstants.CONSTRAINTS_PACKAGE_ROOT + "cpu:aarch64',", |
| " ],", |
| ")", |
| "some_test(", |
| " name = 'custom_exec_group_test',", |
| " exec_properties = {'test.key': 'bad', 'custom_group.key': 'good'},", |
| ")"); |
| ImmutableList<Artifact.DerivedArtifact> testStatusList = |
| getTestStatusArtifacts("//:custom_exec_group_test"); |
| TestRunnerAction testAction = (TestRunnerAction) getGeneratingAction(testStatusList.get(0)); |
| ImmutableMap<String, String> executionInfo = testAction.getExecutionInfo(); |
| assertThat(executionInfo).containsExactly("key", "good"); |
| } |
| |
| /** Adding exec_properties from the platform with --use_target_platform_for_tests. */ |
| @Test |
| public void testTargetTestExecGroup() throws Exception { |
| useConfiguration( |
| "--use_target_platform_for_tests=true", |
| "--platforms=//:linux_aarch64", |
| "--host_platform=//:linux_x86"); |
| scratch.file( |
| "some_test.bzl", |
| "def _some_test_impl(ctx):", |
| " script = ctx.actions.declare_file(ctx.attr.name + '.sh')", |
| " ctx.actions.write(script, 'shell script goes here', is_executable = True)", |
| " return [", |
| " DefaultInfo(executable = script),", |
| " ]", |
| "", |
| "some_test = rule(", |
| " implementation = _some_test_impl,", |
| " test = True,", |
| ")"); |
| scratch.file( |
| "BUILD", |
| "load(':some_test.bzl', 'some_test')", |
| "platform(", |
| " name = 'linux_x86',", |
| " constraint_values = [", |
| " '" + TestConstants.CONSTRAINTS_PACKAGE_ROOT + "os:linux',", |
| " '" + TestConstants.CONSTRAINTS_PACKAGE_ROOT + "cpu:x86_64',", |
| " ],", |
| " exec_properties = {'keyhost': 'bad'},", |
| ")", |
| "platform(", |
| " name = 'linux_aarch64',", |
| " constraint_values = [", |
| " '" + TestConstants.CONSTRAINTS_PACKAGE_ROOT + "os:linux',", |
| " '" + TestConstants.CONSTRAINTS_PACKAGE_ROOT + "cpu:aarch64',", |
| " ],", |
| " exec_properties = {'key2': 'good'},", |
| ")", |
| "some_test(", |
| " name = 'exec_group_test',", |
| " exec_properties = {'key': 'bad'},", |
| ")"); |
| ImmutableList<Artifact.DerivedArtifact> testStatusList = |
| getTestStatusArtifacts("//:exec_group_test"); |
| TestRunnerAction testAction = (TestRunnerAction) getGeneratingAction(testStatusList.get(0)); |
| assertThat(testAction.getExecutionPlatform().label().getName()).isEqualTo("linux_aarch64"); |
| |
| ImmutableMap<String, String> executionInfo = testAction.getExecutionInfo(); |
| assertThat(executionInfo).containsExactly("key2", "good"); |
| } |
| |
| /** Adding test specific exec_properties with --use_target_platform_for_tests. */ |
| @Test |
| @Ignore("https://github.com/bazelbuild/bazel/issues/17466") |
| public void testTargetTestExecGroupInheritance() throws Exception { |
| useConfiguration( |
| "--use_target_platform_for_tests=true", |
| "--platforms=//:linux_aarch64", |
| "--host_platform=//:linux_x86"); |
| scratch.file( |
| "some_test.bzl", |
| "def _some_test_impl(ctx):", |
| " script = ctx.actions.declare_file(ctx.attr.name + '.sh')", |
| " ctx.actions.write(script, 'shell script goes here', is_executable = True)", |
| " return [", |
| " DefaultInfo(executable = script),", |
| " ]", |
| "", |
| "some_test = rule(", |
| " implementation = _some_test_impl,", |
| " test = True,", |
| ")"); |
| scratch.file( |
| "BUILD", |
| "load(':some_test.bzl', 'some_test')", |
| "platform(", |
| " name = 'linux_x86',", |
| " constraint_values = [", |
| " '" + TestConstants.CONSTRAINTS_PACKAGE_ROOT + "os:linux',", |
| " '" + TestConstants.CONSTRAINTS_PACKAGE_ROOT + "cpu:x86_64',", |
| " ],", |
| " exec_properties = {'keyhost': 'bad'},", |
| ")", |
| "platform(", |
| " name = 'linux_aarch64',", |
| " constraint_values = [", |
| " '" + TestConstants.CONSTRAINTS_PACKAGE_ROOT + "os:linux',", |
| " '" + TestConstants.CONSTRAINTS_PACKAGE_ROOT + "cpu:aarch64',", |
| " ],", |
| " exec_properties = {'key2': 'good'},", |
| ")", |
| "some_test(", |
| " name = 'exec_group_test',", |
| " exec_properties = {'test.key': 'good', 'key': 'bad'},", |
| ")"); |
| ImmutableList<Artifact.DerivedArtifact> testStatusList = |
| getTestStatusArtifacts("//:exec_group_test"); |
| TestRunnerAction testAction = (TestRunnerAction) getGeneratingAction(testStatusList.get(0)); |
| assertThat(testAction.getExecutionPlatform().label().getName()).isEqualTo("linux_aarch64"); |
| |
| ImmutableMap<String, String> executionInfo = testAction.getExecutionInfo(); |
| assertThat(executionInfo).containsExactly("key2", "good", "key", "good"); |
| } |
| |
| @Test |
| public void testNonExecutableCoverageReportGenerator() throws Exception { |
| useConfiguration( |
| "--coverage_report_generator=//bad_gen:bad_cov_gen", "--collect_code_coverage"); |
| checkError( |
| "bad_gen", |
| "some_test", |
| "--coverage_report_generator does not refer to an executable target", |
| "sh_library(name = 'bad_cov_gen')", |
| "cc_test(name = 'some_test')"); |
| } |
| |
| private ImmutableList<Artifact.DerivedArtifact> getTestStatusArtifacts(String label) |
| throws Exception { |
| ConfiguredTarget target = getConfiguredTarget(label); |
| return target.getProvider(TestProvider.class).getTestParams().getTestStatusArtifacts(); |
| } |
| |
| private ImmutableList<Artifact.DerivedArtifact> getTestStatusArtifacts( |
| TransitiveInfoCollection target) { |
| return target.getProvider(TestProvider.class).getTestParams().getTestStatusArtifacts(); |
| } |
| } |