From aab9868f535e3a08e272570fed5fec3c51cd384b Mon Sep 17 00:00:00 2001 From: cparsons Date: Fri, 27 Apr 2018 13:04:59 -0700 Subject: Allow skylark rule definitions to advertise providers that targets of the rule must propagate This allows native aspects which specifically require advertised providers to be applied to skylark rules. Implementation to allow aspects to explicitly declare provider requirements will come later. RELNOTES: Skylark rule definitions may advertise providers that targets of the rule must propagate. PiperOrigin-RevId: 194581466 --- .../lib/rules/objc/BazelJ2ObjcLibraryTest.java | 53 ++++++++++ .../lib/skylark/SkylarkRuleClassFunctionsTest.java | 2 +- .../SkylarkRuleImplementationFunctionsTest.java | 117 +++++++++++++++++++++ 3 files changed, 171 insertions(+), 1 deletion(-) (limited to 'src/test/java/com/google/devtools') diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/BazelJ2ObjcLibraryTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/BazelJ2ObjcLibraryTest.java index 29db32ad0c..88d1babc68 100644 --- a/src/test/java/com/google/devtools/build/lib/rules/objc/BazelJ2ObjcLibraryTest.java +++ b/src/test/java/com/google/devtools/build/lib/rules/objc/BazelJ2ObjcLibraryTest.java @@ -884,6 +884,59 @@ public class BazelJ2ObjcLibraryTest extends J2ObjcLibraryTest { "java/com/google/dummy/_j2objc/dummy/java/com/google/dummy/dummy.m")); } + // Tests that a j2objc library can acquire java library information from a skylark rule target. + @Test + public void testJ2ObjcLibraryDepThroughSkylarkRule() throws Exception { + scratch.file("examples/inner.java"); + scratch.file("examples/outer.java"); + scratch.file( + "examples/fake_rule.bzl", + "def _fake_rule_impl(ctx):", + " myProvider = ctx.attr.deps[0][JavaInfo]", + " return struct(providers = [myProvider])", + "", + "fake_rule = rule(", + " implementation = _fake_rule_impl,", + " attrs = {'deps': attr.label_list()},", + " provides = [JavaInfo],", + ")"); + scratch.file( + "examples/BUILD", + "package(default_visibility=['//visibility:public'])", + "load('//examples:fake_rule.bzl', 'fake_rule')", + "java_library(", + " name = 'inner',", + " srcs = ['inner.java'])", + "", + "fake_rule(", + " name = 'propagator',", + " deps = [':inner'])", + "", + "java_library(", + " name = 'outer',", + " srcs = ['outer.java'],", + " deps = [':propagator'])", + "", + "j2objc_library(", + " name = 'transpile',", + " deps = [", + " ':outer',", + " ])", + "", + "objc_library(", + " name = 'lib',", + " srcs = ['lib.m'],", + " deps = [':transpile'])"); + + ConfiguredTarget objcTarget = getConfiguredTarget("//examples:lib"); + + ObjcProvider provider = objcTarget.get(ObjcProvider.SKYLARK_CONSTRUCTOR); + + // The only way that //examples:lib can see inner's archive is through the skylark rule. + assertThat(Artifact.toRootRelativePaths(provider.get(ObjcProvider.LIBRARY))) + .contains("examples/libinner_j2objc.a"); + } + @Test public void testJ2ObjcTranspiledHeaderInCompilationAction() throws Exception { scratch.file("app/lib.m"); diff --git a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleClassFunctionsTest.java b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleClassFunctionsTest.java index 10df59c01d..7bb4b39ace 100644 --- a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleClassFunctionsTest.java +++ b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleClassFunctionsTest.java @@ -1450,7 +1450,7 @@ public class SkylarkRuleClassFunctionsTest extends SkylarkTestCase { ); MoreAsserts.assertContainsEvent(ev.getEventCollector(), " Illegal argument: element in 'provides' is of unexpected type." - + " Should be list of providers, but got int. "); + + " Should be list of providers, but got item of type int. "); } @Test diff --git a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleImplementationFunctionsTest.java b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleImplementationFunctionsTest.java index 71b1ca9c92..dc8b9209c0 100644 --- a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleImplementationFunctionsTest.java +++ b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleImplementationFunctionsTest.java @@ -1313,6 +1313,123 @@ public class SkylarkRuleImplementationFunctionsTest extends SkylarkTestCase { .isEqualTo(new SkylarkKey(Label.parseAbsolute("//test:foo.bzl"), "foo_provider")); } + @Test + public void testAdvertisedProviders() throws Exception { + scratch.file( + "test/foo.bzl", + "FooInfo = provider()", + "BarInfo = provider()", + "def _impl(ctx):", + " foo = FooInfo()", + " bar = BarInfo()", + " return [foo, bar]", + "foo_rule = rule(", + " implementation = _impl,", + " provides = [FooInfo, BarInfo]", + ")"); + scratch.file( + "test/bar.bzl", + "load(':foo.bzl', 'FooInfo')", + "def _impl(ctx):", + " dep = ctx.attr.deps[0]", + " proxy = dep[FooInfo]", // The goal is to test this object + " return struct(proxy = proxy)", // so we return it here + "bar_rule = rule(", + " implementation = _impl,", + " attrs = {", + " 'deps': attr.label_list(allow_files=True),", + " }", + ")"); + scratch.file( + "test/BUILD", + "load(':foo.bzl', 'foo_rule')", + "load(':bar.bzl', 'bar_rule')", + "foo_rule(name = 'dep_rule')", + "bar_rule(name = 'my_rule', deps = [':dep_rule'])"); + ConfiguredTarget configuredTarget = getConfiguredTarget("//test:my_rule"); + Object provider = configuredTarget.get("proxy"); + assertThat(provider).isInstanceOf(Info.class); + assertThat(((Info) provider).getProvider().getKey()) + .isEqualTo(new SkylarkKey(Label.parseAbsolute("//test:foo.bzl"), "FooInfo")); + } + + @Test + public void testLacksAdvertisedDeclaredProvider() throws Exception { + scratch.file( + "test/foo.bzl", + "FooInfo = provider()", + "def _impl(ctx):", + " default = DefaultInfo(", + " runfiles=ctx.runfiles(ctx.files.runs),", + " )", + " return struct(providers=[default])", + "foo_rule = rule(", + " implementation = _impl,", + " attrs = {", + " 'runs': attr.label_list(allow_files=True),", + " },", + " provides = [FooInfo, DefaultInfo]", + ")"); + scratch.file( + "test/BUILD", + "load(':foo.bzl', 'foo_rule')", + "foo_rule(name = 'my_rule', runs = ['run.file', 'run2.file'])"); + + AssertionError expected = + assertThrows(AssertionError.class, () -> getConfiguredTarget("//test:my_rule")); + assertThat(expected) + .hasMessageThat() + .contains("rule advertised the 'FooInfo' provider, " + + "but this provider was not among those returned"); + } + + @Test + public void testLacksAdvertisedNativeProvider() throws Exception { + scratch.file( + "test/foo.bzl", + "FooInfo = provider()", + "def _impl(ctx):", + " MyFooInfo = FooInfo()", + " return struct(providers=[MyFooInfo])", + "foo_rule = rule(", + " implementation = _impl,", + " provides = [FooInfo, JavaInfo]", + ")"); + scratch.file( + "test/BUILD", + "load(':foo.bzl', 'foo_rule')", + "foo_rule(name = 'my_rule')"); + + AssertionError expected = + assertThrows(AssertionError.class, () -> getConfiguredTarget("//test:my_rule")); + assertThat(expected) + .hasMessageThat() + .contains("rule advertised the 'JavaInfo' provider, " + + "but this provider was not among those returned"); + } + + @Test + public void testBadlySpecifiedProvides() throws Exception { + scratch.file( + "test/foo.bzl", + "def _impl(ctx):", + " return struct()", + "foo_rule = rule(", + " implementation = _impl,", + " provides = [1]", + ")"); + scratch.file("test/BUILD", "load(':foo.bzl', 'foo_rule')", "foo_rule(name = 'my_rule')"); + + + AssertionError expected = + assertThrows(AssertionError.class, () -> getConfiguredTarget("//test:my_rule")); + assertThat(expected) + .hasMessageThat() + .contains( + "element in 'provides' is of unexpected type. " + + "Should be list of providers, but got item of type int"); + } + @Test public void testSingleDeclaredProvider() throws Exception { scratch.file( -- cgit v1.2.3