diff options
author | 2016-11-18 15:14:56 +0000 | |
---|---|---|
committer | 2016-11-21 19:34:38 +0000 | |
commit | 8f45b7c71394f07227e507fddf736bcf6d5b0097 (patch) | |
tree | 80b4eccd7033f63b0aa50bd735437305a1fcd1d3 /src/test/java/com/google/devtools/build/lib | |
parent | bd9576a7b092114b02118c2d08c2d6ef60806858 (diff) |
Implement 'output_groups' provider.
This behavior - that 'output_groups' is a provider available
on targets and aspects - has been accidental, but people already depend
on it. This CL keeps that behavior, while fixing the bug that
two aspects could not both provide output groups.
--
MOS_MIGRATED_REVID=139578378
Diffstat (limited to 'src/test/java/com/google/devtools/build/lib')
-rw-r--r-- | src/test/java/com/google/devtools/build/lib/skylark/SkylarkAspectsTest.java | 146 | ||||
-rw-r--r-- | src/test/java/com/google/devtools/build/lib/skylark/SkylarkIntegrationTest.java | 44 |
2 files changed, 189 insertions, 1 deletions
diff --git a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkAspectsTest.java b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkAspectsTest.java index 53da165256..5f0933017e 100644 --- a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkAspectsTest.java +++ b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkAspectsTest.java @@ -296,7 +296,6 @@ public class SkylarkAspectsTest extends AnalysisTestCase { "", "MyAspect = aspect(", " implementation=_impl,", - " attr_aspects=['deps'],", ")"); scratch.file( "test/BUILD", @@ -321,6 +320,50 @@ public class SkylarkAspectsTest extends AnalysisTestCase { } @Test + public void testAspectWithOutputGroupsAsList() throws Exception { + scratch.file( + "test/aspect.bzl", + "def _impl(target, ctx):", + " g = target.output_group('_hidden_top_level" + INTERNAL_SUFFIX + "')", + " return struct(output_groups = { 'my_result' : [ f for f in g] })", + "", + "MyAspect = aspect(", + " implementation=_impl,", + ")"); + scratch.file( + "test/BUILD", + "java_library(", + " name = 'xxx',", + " srcs = ['A.java'],", + ")"); + + AnalysisResult analysisResult = + update(ImmutableList.of("test/aspect.bzl%MyAspect"), "//test:xxx"); + assertThat( + transform( + analysisResult.getTargetsToBuild(), + new Function<ConfiguredTarget, String>() { + @Nullable + @Override + public String apply(ConfiguredTarget configuredTarget) { + return configuredTarget.getLabel().toString(); + } + })) + .containsExactly("//test:xxx"); + AspectValue aspectValue = analysisResult.getAspects().iterator().next(); + OutputGroupProvider outputGroupProvider = + aspectValue.getConfiguredAspect().getProvider(OutputGroupProvider.class); + assertThat(outputGroupProvider).isNotNull(); + NestedSet<Artifact> names = outputGroupProvider.getOutputGroup("my_result"); + assertThat(names).isNotEmpty(); + NestedSet<Artifact> expectedSet = getConfiguredTarget("//test:xxx") + .getProvider(OutputGroupProvider.class) + .getOutputGroup(OutputGroupProvider.HIDDEN_TOP_LEVEL); + assertThat(names).containsExactlyElementsIn(expectedSet); + } + + + @Test public void testAspectsFromSkylarkRules() throws Exception { scratch.file( "test/aspect.bzl", @@ -617,6 +660,107 @@ public class SkylarkAspectsTest extends AnalysisTestCase { } @Test + public void outputGroupsFromTwoAspects() throws Exception { + scratch.file( + "test/aspect.bzl", + "def _a1_impl(target, ctx):", + " f = ctx.new_file(target.label.name + '_a1.txt')", + " ctx.file_action(f, 'f')", + " return struct(output_groups = { 'a1_group' : set([f]) })", + "", + "a1 = aspect(implementation=_a1_impl, attr_aspects = ['dep'])", + "def _rule_impl(ctx):", + " if not ctx.attr.dep:", + " return struct()", + " og = {k:ctx.attr.dep.output_groups[k] for k in ctx.attr.dep.output_groups}", + " return struct(output_groups = og)", + "my_rule1 = rule(_rule_impl, attrs = { 'dep' : attr.label(aspects = [a1]) })", + "def _a2_impl(target, ctx):", + " g = ctx.new_file(target.label.name + '_a2.txt')", + " ctx.file_action(g, 'f')", + " return struct(output_groups = { 'a2_group' : set([g]) })", + "", + "a2 = aspect(implementation=_a2_impl, attr_aspects = ['dep'])", + "my_rule2 = rule(_rule_impl, attrs = { 'dep' : attr.label(aspects = [a2]) })" + ); + scratch.file( + "test/BUILD", + "load(':aspect.bzl', 'my_rule1', 'my_rule2')", + "my_rule1(name = 'base')", + "my_rule1(name = 'xxx', dep = ':base')", + "my_rule2(name = 'yyy', dep = ':xxx')" + ); + + + AnalysisResult analysisResult = update("//test:yyy"); + OutputGroupProvider outputGroupProvider = + Iterables + .getOnlyElement(analysisResult.getTargetsToBuild()) + .getProvider(OutputGroupProvider.class); + assertThat(getOutputGroupContents(outputGroupProvider, "a1_group")) + .containsExactly("test/base_a1.txt"); + assertThat(getOutputGroupContents(outputGroupProvider, "a2_group")) + .containsExactly("test/xxx_a2.txt"); + } + + @Test + public void duplicateOutputGroupsFromTwoAspects() throws Exception { + scratch.file( + "test/aspect.bzl", + "def _a1_impl(target, ctx):", + " f = ctx.new_file(target.label.name + '_a1.txt')", + " ctx.file_action(f, 'f')", + " return struct(output_groups = { 'a1_group' : set([f]) })", + "", + "a1 = aspect(implementation=_a1_impl, attr_aspects = ['dep'])", + "def _rule_impl(ctx):", + " if not ctx.attr.dep:", + " return struct()", + " og = {k:ctx.attr.dep.output_groups[k] for k in ctx.attr.dep.output_groups}", + " return struct(output_groups = og)", + "my_rule1 = rule(_rule_impl, attrs = { 'dep' : attr.label(aspects = [a1]) })", + "def _a2_impl(target, ctx):", + " g = ctx.new_file(target.label.name + '_a2.txt')", + " ctx.file_action(g, 'f')", + " return struct(output_groups = { 'a1_group' : set([g]) })", + "", + "a2 = aspect(implementation=_a2_impl, attr_aspects = ['dep'])", + "my_rule2 = rule(_rule_impl, attrs = { 'dep' : attr.label(aspects = [a2]) })" + ); + scratch.file( + "test/BUILD", + "load(':aspect.bzl', 'my_rule1', 'my_rule2')", + "my_rule1(name = 'base')", + "my_rule1(name = 'xxx', dep = ':base')", + "my_rule2(name = 'yyy', dep = ':xxx')" + ); + + + reporter.removeHandler(failFastHandler); + try { + AnalysisResult analysisResult = update("//test:yyy"); + assertThat(analysisResult.hasError()).isTrue(); + assertThat(keepGoing()).isTrue(); + } catch (ViewCreationFailedException e) { + // expected. + } + assertContainsEvent("ERROR /workspace/test/BUILD:3:1: Output group a1_group provided twice"); + } + + + private static Iterable<String> getOutputGroupContents(OutputGroupProvider outputGroupProvider, + String groupName) { + return Iterables.transform(outputGroupProvider.getOutputGroup(groupName), + new Function<Artifact, String>() { + @Override + public String apply(Artifact artifact) { + return artifact.getRootRelativePathString(); + } + }); + } + + + @Test public void duplicateSkylarkProviders() throws Exception { scratch.file( "test/aspect.bzl", diff --git a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkIntegrationTest.java b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkIntegrationTest.java index f8c326fa99..9e2d5502f8 100644 --- a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkIntegrationTest.java +++ b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkIntegrationTest.java @@ -43,6 +43,7 @@ import com.google.devtools.build.lib.skyframe.PackageFunction; import com.google.devtools.build.lib.skyframe.SkyFunctions; import com.google.devtools.build.lib.skyframe.SkylarkImportLookupFunction; import com.google.devtools.build.lib.syntax.Runtime; +import com.google.devtools.build.lib.syntax.SkylarkList; import com.google.devtools.build.lib.syntax.SkylarkList.MutableList; import com.google.devtools.build.lib.syntax.SkylarkNestedSet; import com.google.devtools.build.skyframe.InMemoryMemoizingEvaluator; @@ -188,6 +189,49 @@ public class SkylarkIntegrationTest extends BuildViewTestCase { } @Test + public void testOutputGroupsAsDictionary() throws Exception { + scratch.file( + "test/skylark/extension.bzl", + "def _impl(ctx):", + " f = ctx.attr.dep.output_groups['_hidden_top_level" + INTERNAL_SUFFIX + "']", + " has_key1 = '_hidden_top_level" + INTERNAL_SUFFIX + "' in ctx.attr.dep.output_groups", + " has_key2 = 'foobar' in ctx.attr.dep.output_groups", + " all_keys = [k for k in ctx.attr.dep.output_groups]", + " return struct(result = f, ", + " has_key1 = has_key1,", + " has_key2 = has_key2,", + " all_keys = all_keys,", + " output_groups = { 'my_group' : f })", + "my_rule = rule(implementation = _impl,", + " attrs = { 'dep' : attr.label() })"); + scratch.file( + "test/skylark/BUILD", + "load('/test/skylark/extension', 'my_rule')", + "cc_binary(name = 'lib', data = ['a.txt'])", + "my_rule(name='my', dep = ':lib')"); + NestedSet<Artifact> hiddenTopLevelArtifacts = + getConfiguredTarget("//test/skylark:lib") + .getProvider(OutputGroupProvider.class) + .getOutputGroup(OutputGroupProvider.HIDDEN_TOP_LEVEL); + ConfiguredTarget myTarget = getConfiguredTarget("//test/skylark:my"); + SkylarkProviders skylarkProviders = myTarget + .getProvider(SkylarkProviders.class); + SkylarkNestedSet result = (SkylarkNestedSet) skylarkProviders.getValue("result"); + assertThat(result.getSet(Artifact.class)).containsExactlyElementsIn(hiddenTopLevelArtifacts); + assertThat(myTarget.getProvider(OutputGroupProvider.class).getOutputGroup("my_group")) + .containsExactlyElementsIn(hiddenTopLevelArtifacts); + assertThat(skylarkProviders.getValue("has_key1")).isEqualTo(Boolean.TRUE); + assertThat(skylarkProviders.getValue("has_key2")).isEqualTo(Boolean.FALSE); + assertThat((SkylarkList) skylarkProviders.getValue("all_keys")) + .containsExactly( + "_hidden_top_level" + INTERNAL_SUFFIX, + "compilation_prerequisites" + INTERNAL_SUFFIX, + "files_to_compile" + INTERNAL_SUFFIX, + "temp_files" + INTERNAL_SUFFIX); + } + + + @Test public void testOutputGroupsWithList() throws Exception { scratch.file( "test/skylark/extension.bzl", |