From fd93143f93a9873218cd2eb783a0bff322847213 Mon Sep 17 00:00:00 2001 From: Sergio Campama Date: Fri, 9 Dec 2016 21:47:35 +0000 Subject: Add a testing Skylark module that exposes an ExecutionInfoProvider constructor. -- PiperOrigin-RevId: 141594768 MOS_MIGRATED_REVID=141594768 --- .../devtools/build/lib/analysis/AnalysisUtils.java | 19 +++++++ .../lib/analysis/RuleConfiguredTargetBuilder.java | 6 +- .../devtools/build/lib/analysis/RuleContext.java | 11 ++++ .../lib/bazel/rules/BazelRuleClassProvider.java | 15 +++++ .../devtools/build/lib/rules/cpp/CcBinary.java | 3 +- .../devtools/build/lib/rules/objc/IosTest.java | 2 +- .../lib/rules/test/ExecutionInfoProvider.java | 11 +++- .../build/lib/rules/test/SkylarkTestingModule.java | 65 ++++++++++++++++++++++ src/test/java/com/google/devtools/build/lib/BUILD | 14 +++++ .../lib/rules/test/SkylarkTestingModuleTest.java | 54 ++++++++++++++++++ 10 files changed, 194 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/google/devtools/build/lib/rules/test/SkylarkTestingModule.java create mode 100644 src/test/java/com/google/devtools/build/lib/rules/test/SkylarkTestingModuleTest.java diff --git a/src/main/java/com/google/devtools/build/lib/analysis/AnalysisUtils.java b/src/main/java/com/google/devtools/build/lib/analysis/AnalysisUtils.java index 495d5ebdd4..1abc8934e4 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/AnalysisUtils.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/AnalysisUtils.java @@ -25,6 +25,8 @@ import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.collect.nestedset.Order; import com.google.devtools.build.lib.packages.BuildType; +import com.google.devtools.build.lib.packages.SkylarkClassObject; +import com.google.devtools.build.lib.packages.SkylarkClassObjectConstructor; import com.google.devtools.build.lib.packages.TriState; import com.google.devtools.build.lib.vfs.PathFragment; @@ -76,6 +78,23 @@ public final class AnalysisUtils { return result.build(); } + /** + * Returns the list of declared providers (native and Skylark) of the specified Skylark key from a + * set of transitive info collections. + */ + public static Iterable getProviders( + Iterable prerequisites, + final SkylarkClassObjectConstructor.Key skylarkKey) { + ImmutableList.Builder result = ImmutableList.builder(); + for (TransitiveInfoCollection prerequisite : prerequisites) { + SkylarkClassObject prerequisiteProvider = prerequisite.get(skylarkKey); + if (prerequisiteProvider != null) { + result.add(prerequisiteProvider); + } + } + return result.build(); + } + /** * Returns the iterable of collections that have the specified provider. */ 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 0047976e01..78877d3425 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 @@ -224,7 +224,11 @@ public final class RuleConfiguredTargetBuilder { TestParams testParams = testActionBuilder .setFilesToRunProvider(filesToRunProvider) - .setExecutionRequirements(providersBuilder.getProvider(ExecutionInfoProvider.class)) + .setExecutionRequirements( + (ExecutionInfoProvider) + skylarkDeclaredProviders + .build() + .get(ExecutionInfoProvider.SKYLARK_CONSTRUCTOR.getKey())) .setShardCount(explicitShardCount) .build(); ImmutableList testTags = ImmutableList.copyOf(ruleContext.getRule().getRuleTags()); diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java index fad548ae71..879a1bbe18 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java @@ -71,6 +71,8 @@ import com.google.devtools.build.lib.packages.Rule; import com.google.devtools.build.lib.packages.RuleClass; import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException; import com.google.devtools.build.lib.packages.RuleErrorConsumer; +import com.google.devtools.build.lib.packages.SkylarkClassObject; +import com.google.devtools.build.lib.packages.SkylarkClassObjectConstructor; import com.google.devtools.build.lib.packages.SkylarkProviderIdentifier; import com.google.devtools.build.lib.packages.Target; import com.google.devtools.build.lib.packages.TargetUtils; @@ -837,6 +839,15 @@ public final class RuleContext extends TargetContext return AnalysisUtils.getProviders(getPrerequisites(attributeName, mode), classType); } + /** + * Returns all the declared providers (native and Skylark) for the specified constructor under the + * specified attribute of this target in the BUILD file. + */ + public Iterable getPrerequisites( + String attributeName, Mode mode, final SkylarkClassObjectConstructor.Key skylarkKey) { + return AnalysisUtils.getProviders(getPrerequisites(attributeName, mode), skylarkKey); + } + /** * Returns all the providers of the specified type that are listed under the specified attribute * of this target in the BUILD file, and that contain the specified provider. diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java index ef821707e3..5497fc8cf3 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java @@ -162,6 +162,7 @@ import com.google.devtools.build.lib.rules.repository.BindRule; import com.google.devtools.build.lib.rules.repository.LocalRepositoryRule; import com.google.devtools.build.lib.rules.repository.NewLocalRepositoryRule; import com.google.devtools.build.lib.rules.repository.WorkspaceBaseRule; +import com.google.devtools.build.lib.rules.test.SkylarkTestingModule; import com.google.devtools.build.lib.rules.test.TestSuiteRule; import com.google.devtools.build.lib.syntax.Type; import com.google.devtools.build.lib.util.ResourceFileLoader; @@ -277,6 +278,7 @@ public class BazelRuleClassProvider { OBJC_RULES.init(builder); J2OBJC_RULES.init(builder); ANDROID_STUDIO_ASPECT.init(builder); + TESTING_SUPPORT.init(builder); VARIOUS_WORKSPACE_RULES.init(builder); // This rule is a little special: it needs to depend on every configuration fragment that has @@ -383,6 +385,19 @@ public class BazelRuleClassProvider { } }; + public static final RuleSet TESTING_SUPPORT = + new RuleSet() { + @Override + public void init(Builder builder) { + builder.addSkylarkAccessibleTopLevels("testing", new SkylarkTestingModule()); + } + + @Override + public ImmutableList requires() { + return ImmutableList.of(CORE_RULES); + } + }; + public static final RuleSet SH_RULES = new RuleSet() { @Override diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java index a1fa0a807b..1cb110aab1 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java @@ -362,8 +362,7 @@ public abstract class CcBinary implements RuleConfiguredTargetFactory { // Support test execution on darwin. if (Platform.isApplePlatform(cppConfiguration.getTargetCpu()) && TargetUtils.isTestRule(ruleContext.getRule())) { - ruleBuilder.add( - ExecutionInfoProvider.class, + ruleBuilder.addNativeDeclaredProvider( new ExecutionInfoProvider(ImmutableMap.of("requires-darwin", ""))); } diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/IosTest.java b/src/main/java/com/google/devtools/build/lib/rules/objc/IosTest.java index 46ddaf45a6..d75b0b4a06 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/IosTest.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/IosTest.java @@ -226,7 +226,7 @@ public final class IosTest implements RuleConfiguredTargetFactory { .setFilesToBuild(filesToBuildBuilder.build()) .addProvider(xcodeProvider) .addProvider(RunfilesProvider.simple(runfiles)) - .addProvider(new ExecutionInfoProvider(execInfoMapBuilder.build())) + .addNativeDeclaredProvider(new ExecutionInfoProvider(execInfoMapBuilder.build())) .addProvider(InstrumentedFilesProvider.class, instrumentedFilesProvider) .addProviders(testSupport.getExtraProviders()) .setRunfilesSupport(runfilesSupport, executable) diff --git a/src/main/java/com/google/devtools/build/lib/rules/test/ExecutionInfoProvider.java b/src/main/java/com/google/devtools/build/lib/rules/test/ExecutionInfoProvider.java index 5eb084e244..37639c6ce2 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/test/ExecutionInfoProvider.java +++ b/src/main/java/com/google/devtools/build/lib/rules/test/ExecutionInfoProvider.java @@ -16,7 +16,8 @@ package com.google.devtools.build.lib.rules.test; import com.google.common.collect.ImmutableMap; import com.google.devtools.build.lib.analysis.TransitiveInfoProvider; import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; - +import com.google.devtools.build.lib.packages.SkylarkClassObject; +import com.google.devtools.build.lib.packages.SkylarkClassObjectConstructor; import java.util.Map; /** @@ -24,11 +25,17 @@ import java.util.Map; * tests). */ @Immutable -public final class ExecutionInfoProvider implements TransitiveInfoProvider { +public final class ExecutionInfoProvider extends SkylarkClassObject + implements TransitiveInfoProvider { + + /** Skylark constructor and identifier for ExecutionInfoProvider. */ + public static final SkylarkClassObjectConstructor SKYLARK_CONSTRUCTOR = + SkylarkClassObjectConstructor.createNative("ExecutionInfo"); private final ImmutableMap executionInfo; public ExecutionInfoProvider(Map requirements) { + super(SKYLARK_CONSTRUCTOR, ImmutableMap.of("requirements", requirements)); this.executionInfo = ImmutableMap.copyOf(requirements); } diff --git a/src/main/java/com/google/devtools/build/lib/rules/test/SkylarkTestingModule.java b/src/main/java/com/google/devtools/build/lib/rules/test/SkylarkTestingModule.java new file mode 100644 index 0000000000..7714d59240 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/rules/test/SkylarkTestingModule.java @@ -0,0 +1,65 @@ +// Copyright 2016 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.rules.test; + +import com.google.devtools.build.lib.skylarkinterface.Param; +import com.google.devtools.build.lib.skylarkinterface.SkylarkModule; +import com.google.devtools.build.lib.skylarkinterface.SkylarkSignature; +import com.google.devtools.build.lib.syntax.BuiltinFunction; +import com.google.devtools.build.lib.syntax.SkylarkDict; +import com.google.devtools.build.lib.syntax.SkylarkSignatureProcessor; + +/** A class that exposes testing infrastructure to skylark. */ +@SkylarkModule( + name = "testing", + doc = "Helper methods for skylark to access testing infrastructure." +) +public class SkylarkTestingModule { + + // TODO(bazel-team): Change this BuiltinFunction to be the actual + // ExecutionInfoProvider.SKYLARK_CONSTRUCTOR. + @SkylarkSignature( + name = "ExecutionInfo", + objectType = SkylarkTestingModule.class, + returnType = ExecutionInfoProvider.class, + doc = + "Creates a new execution info provider. Use this provider to specify special" + + "environments requirements needed to run tests.", + parameters = { + @Param(name = "self", type = SkylarkTestingModule.class, doc = "The 'testing' instance."), + @Param( + name = "requirements", + type = SkylarkDict.class, + named = false, + positional = true, + doc = + "A map of string keys and values to indicate special execution requirements, such as" + + " hardware platforms, etc. These keys and values are passed to the executor of" + + " the test action as parameters to configure the execution environment." + ) + } + ) + public static final BuiltinFunction NEW_EXECUTION_INFO_PROVIDER = + new BuiltinFunction("ExecutionInfo") { + @SuppressWarnings("unused") + // This method is registered statically for skylark, and never called directly. + public ExecutionInfoProvider invoke(SkylarkTestingModule self, SkylarkDict requirements) { + return new ExecutionInfoProvider(requirements); + } + }; + + static { + SkylarkSignatureProcessor.configureSkylarkFunctions(SkylarkTestingModule.class); + } +} diff --git a/src/test/java/com/google/devtools/build/lib/BUILD b/src/test/java/com/google/devtools/build/lib/BUILD index 2fd287c54f..246f9d828d 100644 --- a/src/test/java/com/google/devtools/build/lib/BUILD +++ b/src/test/java/com/google/devtools/build/lib/BUILD @@ -988,6 +988,20 @@ java_test( ], ) +java_test( + name = "test-rules-tests", + srcs = ["rules/test/SkylarkTestingModuleTest.java"], + tags = ["rules"], + test_class = "com.google.devtools.build.lib.rules.test.SkylarkTestingModuleTest", + deps = [ + ":analysis_testutil", + "//src/main/java/com/google/devtools/build/lib:build-base", + "//third_party:junit4", + "//third_party:truth", + "//third_party/protobuf", + ], +) + java_test( name = "bazel-rules-tests", srcs = glob([ diff --git a/src/test/java/com/google/devtools/build/lib/rules/test/SkylarkTestingModuleTest.java b/src/test/java/com/google/devtools/build/lib/rules/test/SkylarkTestingModuleTest.java new file mode 100644 index 0000000000..786c571f73 --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/rules/test/SkylarkTestingModuleTest.java @@ -0,0 +1,54 @@ +// Copyright 2016 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.rules.test; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.devtools.build.lib.analysis.ConfiguredTarget; +import com.google.devtools.build.lib.analysis.util.BuildViewTestCase; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for Skylark interaction with testing support. */ +@RunWith(JUnit4.class) +public class SkylarkTestingModuleTest extends BuildViewTestCase { + + @Test + public void testSkylarkRulePropagatesExecutionInfoProvider() throws Exception { + scratch.file("examples/rule/BUILD"); + scratch.file( + "examples/rule/apple_rules.bzl", + "def my_rule_impl(ctx):", + " exec_info = testing.ExecutionInfo({'requires-darwin': '1'})", + " return [exec_info]", + "my_rule = rule(implementation = my_rule_impl,", + " attrs = {},", + ")"); + scratch.file( + "examples/apple_skylark/BUILD", + "package(default_visibility = ['//visibility:public'])", + "load('/examples/rule/apple_rules', 'my_rule')", + "my_rule(", + " name = 'my_target',", + ")"); + + ConfiguredTarget skylarkTarget = getConfiguredTarget("//examples/apple_skylark:my_target"); + ExecutionInfoProvider provider = + (ExecutionInfoProvider) + skylarkTarget.get(ExecutionInfoProvider.SKYLARK_CONSTRUCTOR.getKey()); + + assertThat(provider.getExecutionInfo().get("requires-darwin")).isEqualTo("1"); + } +} -- cgit v1.2.3