aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleContextTest.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleContextTest.java')
-rw-r--r--src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleContextTest.java230
1 files changed, 188 insertions, 42 deletions
diff --git a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleContextTest.java b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleContextTest.java
index 075f95aa89..6066c41a4c 100644
--- a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleContextTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleContextTest.java
@@ -36,6 +36,7 @@ import com.google.devtools.build.lib.rules.SkylarkRuleContext;
import com.google.devtools.build.lib.rules.java.JavaSourceJarsProvider;
import com.google.devtools.build.lib.rules.python.PyCommon;
import com.google.devtools.build.lib.skylark.util.SkylarkTestCase;
+import com.google.devtools.build.lib.syntax.Runtime;
import com.google.devtools.build.lib.syntax.SkylarkDict;
import com.google.devtools.build.lib.syntax.SkylarkList;
import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
@@ -1015,51 +1016,62 @@ public class SkylarkRuleContextTest extends SkylarkTestCase {
assertThat(filename).isEqualTo("../foo/bar.txt");
}
- private void setUpActionTest() throws Exception {
- scratch.file("test/rules.bzl",
- "def _testable_impl(ctx):",
- " out = ctx.outputs.out",
- " ctx.action(outputs=[out], command='echo foo123 > ' + out.path)",
- "testable_rule = rule(",
- " implementation = _testable_impl,",
- " outputs = {'out': '%{name}.txt'},",
- " _skylark_testable = True,",
- ")",
- "def _nontestable_impl(ctx):",
- " out = ctx.outputs.out",
- " ctx.action(outputs=[out], command='echo bar123 > ' + out.path)",
- "nontestable_rule = rule(",
- " implementation = _nontestable_impl,",
- " outputs = {'out': '%{name}.txt'},",
- ")",
- "def _testing_impl(ctx):",
- " pass",
- "testing_rule = rule(",
- " implementation = _testing_impl,",
- " attrs = {'dep1': attr.label(),",
- " 'dep2': attr.label(),},",
- ")");
- scratch.file("test/BUILD",
- "load(':rules.bzl', 'testable_rule', 'nontestable_rule', 'testing_rule')",
- "testable_rule(",
- " name = 'testable',",
- ")",
- "nontestable_rule(",
- " name = 'nontestable',",
- ")",
- "testing_rule(",
- " name = 'testing',",
- " dep1 = ':testable',",
- " dep2 = ':nontestable',",
- ")");
+ // Borrowed from Scratch.java.
+ private static String linesAsString(String... lines) {
+ StringBuilder builder = new StringBuilder();
+ for (String line : lines) {
+ builder.append(line);
+ builder.append('\n');
+ }
+ return builder.toString();
+ }
+
+ // The common structure of the following actions tests is a rule under test depended upon by
+ // a testing rule, where the rule under test has one output and one caller-supplied action.
+
+ private String getSimpleUnderTestDefinition(String actionLine) {
+ return linesAsString(
+ "def _undertest_impl(ctx):",
+ " out = ctx.outputs.out",
+ " " + actionLine,
+ "undertest_rule = rule(",
+ " implementation = _undertest_impl,",
+ " outputs = {'out': '%{name}.txt'},",
+ " _skylark_testable = True,",
+ ")");
}
+ private final String testingRuleDefinition =
+ linesAsString(
+ "def _testing_impl(ctx):",
+ " pass",
+ "testing_rule = rule(",
+ " implementation = _testing_impl,",
+ " attrs = {'dep': attr.label()},",
+ ")");
+
+ private final String simpleBuildDefinition =
+ linesAsString(
+ "load(':rules.bzl', 'undertest_rule', 'testing_rule')",
+ "undertest_rule(",
+ " name = 'undertest',",
+ ")",
+ "testing_rule(",
+ " name = 'testing',",
+ " dep = ':undertest',",
+ ")");
+
@Test
public void testDependencyActionsProvider() throws Exception {
- setUpActionTest();
+ scratch.file("test/rules.bzl",
+ getSimpleUnderTestDefinition(
+ "ctx.action(outputs=[out], command='echo foo123 > ' + out.path)"),
+ testingRuleDefinition);
+ scratch.file("test/BUILD",
+ simpleBuildDefinition);
SkylarkRuleContext ruleContext = createRuleContext("//test:testing");
- Object provider = evalRuleContextCode(ruleContext, "ruleContext.attr.dep1[Actions]");
+ Object provider = evalRuleContextCode(ruleContext, "ruleContext.attr.dep[Actions]");
assertThat(provider).isInstanceOf(SkylarkClassObject.class);
assertThat(((SkylarkClassObject) provider).getConstructor())
.isEqualTo(ActionsProvider.ACTIONS_PROVIDER);
@@ -1068,7 +1080,7 @@ public class SkylarkRuleContextTest extends SkylarkTestCase {
Object mapping = eval("actions.by_file");
assertThat(mapping).isInstanceOf(SkylarkDict.class);
assertThat((SkylarkDict<?, ?>) mapping).hasSize(1);
- update("file", eval("list(ruleContext.attr.dep1.files)[0]"));
+ update("file", eval("list(ruleContext.attr.dep.files)[0]"));
Object actionUnchecked = eval("actions.by_file[file]");
assertThat(actionUnchecked).isInstanceOf(ActionAnalysisMetadata.class);
}
@@ -1076,15 +1088,149 @@ public class SkylarkRuleContextTest extends SkylarkTestCase {
@Test
public void testNoAccessToDependencyActionsWithoutSkylarkTest() throws Exception {
reporter.removeHandler(failFastHandler);
- setUpActionTest();
+ scratch.file("test/rules.bzl",
+ "def _undertest_impl(ctx):",
+ " out = ctx.outputs.out",
+ " ctx.action(outputs=[out], command='echo foo123 > ' + out.path)",
+ "undertest_rule = rule(",
+ " implementation = _undertest_impl,",
+ " outputs = {'out': '%{name}.txt'},",
+ ")",
+ testingRuleDefinition);
+ scratch.file("test/BUILD",
+ simpleBuildDefinition);
SkylarkRuleContext ruleContext = createRuleContext("//test:testing");
try {
- evalRuleContextCode(ruleContext, "ruleContext.attr.dep2[Actions]");
+ evalRuleContextCode(ruleContext, "ruleContext.attr.dep[Actions]");
fail("Should have failed due to trying to access actions of a rule not marked "
+ "_skylark_testable");
} catch (Exception e) {
assertThat(e).hasMessage("Object of type Target doesn't contain declared provider Actions");
}
}
+
+ @Test
+ public void testAbstractActionInterface() throws Exception {
+ scratch.file("test/rules.bzl",
+ "def _undertest_impl(ctx):",
+ " out1 = ctx.outputs.out1",
+ " out2 = ctx.outputs.out2",
+ " ctx.file_action(output=out1, content='foo123')",
+ " ctx.action(outputs=[out2], inputs=[out1], command='cp ' + out1.path + ' ' + out2.path)",
+ " return struct(out1=out1, out2=out2)",
+ "undertest_rule = rule(",
+ " implementation = _undertest_impl,",
+ " outputs = {'out1': '%{name}1.txt',",
+ " 'out2': '%{name}2.txt'},",
+ " _skylark_testable = True,",
+ ")",
+ testingRuleDefinition);
+ scratch.file("test/BUILD",
+ simpleBuildDefinition);
+ SkylarkRuleContext ruleContext = createRuleContext("//test:testing");
+ update("ruleContext", ruleContext);
+ update("file1", eval("ruleContext.attr.dep.out1"));
+ update("file2", eval("ruleContext.attr.dep.out2"));
+ update("action1", eval("ruleContext.attr.dep[Actions].by_file[file1]"));
+ update("action2", eval("ruleContext.attr.dep[Actions].by_file[file2]"));
+
+ assertThat(eval("action1.inputs")).isInstanceOf(SkylarkNestedSet.class);
+ assertThat(eval("action1.outputs")).isInstanceOf(SkylarkNestedSet.class);
+
+ assertThat(eval("action1.argv")).isEqualTo(Runtime.NONE);
+ assertThat(eval("action2.content")).isEqualTo(Runtime.NONE);
+ assertThat(eval("action1.substitutions")).isEqualTo(Runtime.NONE);
+
+ assertThat(eval("list(action1.inputs)")).isEqualTo(eval("[]"));
+ assertThat(eval("list(action1.outputs)")).isEqualTo(eval("[file1]"));
+ assertThat(eval("list(action2.inputs)")).isEqualTo(eval("[file1]"));
+ assertThat(eval("list(action2.outputs)")).isEqualTo(eval("[file2]"));
+ }
+
+ @Test
+ public void testSpawnActionInterface() throws Exception {
+ scratch.file("test/rules.bzl",
+ getSimpleUnderTestDefinition(
+ "ctx.action(outputs=[out], command='echo foo123 > ' + out.path)"),
+ testingRuleDefinition);
+ scratch.file("test/BUILD",
+ simpleBuildDefinition);
+ SkylarkRuleContext ruleContext = createRuleContext("//test:testing");
+ update("ruleContext", ruleContext);
+ update("file", eval("list(ruleContext.attr.dep.files)[0]"));
+ update("action", eval("ruleContext.attr.dep[Actions].by_file[file]"));
+
+ assertThat(eval("type(action)")).isEqualTo("Action");
+
+ Object argvUnchecked = eval("action.argv");
+ assertThat(argvUnchecked).isInstanceOf(SkylarkList.MutableList.class);
+ SkylarkList.MutableList<?> argv = (SkylarkList.MutableList<?>) argvUnchecked;
+ assertThat(argv).hasSize(3);
+ assertThat(argv.isImmutable()).isTrue();
+ Object result = eval("action.argv[2].startswith('echo foo123')");
+ assertThat((Boolean) result).isTrue();
+ }
+
+ @Test
+ public void testFileWriteActionInterface() throws Exception {
+ scratch.file("test/rules.bzl",
+ getSimpleUnderTestDefinition(
+ "ctx.file_action(output=out, content='foo123')"),
+ testingRuleDefinition);
+ scratch.file("test/BUILD",
+ simpleBuildDefinition);
+ SkylarkRuleContext ruleContext = createRuleContext("//test:testing");
+ update("ruleContext", ruleContext);
+ update("file", eval("list(ruleContext.attr.dep.files)[0]"));
+ update("action", eval("ruleContext.attr.dep[Actions].by_file[file]"));
+
+ assertThat(eval("type(action)")).isEqualTo("Action");
+
+ Object contentUnchecked = eval("action.content");
+ assertThat(contentUnchecked).isInstanceOf(String.class);
+ assertThat(contentUnchecked).isEqualTo("foo123");
+ }
+
+ @Test
+ public void testTemplateExpansionActionInterface() throws Exception {
+ scratch.file("test/rules.bzl",
+ "def _undertest_impl(ctx):",
+ " out = ctx.outputs.out",
+ " ctx.template_action(output=out, template=ctx.file.template, substitutions={'a': 'b'})",
+ "undertest_rule = rule(",
+ " implementation = _undertest_impl,",
+ " outputs = {'out': '%{name}.txt'},",
+ " attrs = {'template': attr.label(allow_single_file=True)},",
+ " _skylark_testable = True,",
+ ")",
+ testingRuleDefinition);
+ scratch.file("test/template.txt",
+ "aaaaa",
+ "bcdef");
+ scratch.file("test/BUILD",
+ "load(':rules.bzl', 'undertest_rule', 'testing_rule')",
+ "undertest_rule(",
+ " name = 'undertest',",
+ " template = ':template.txt',",
+ ")",
+ "testing_rule(",
+ " name = 'testing',",
+ " dep = ':undertest',",
+ ")");
+ SkylarkRuleContext ruleContext = createRuleContext("//test:testing");
+ update("ruleContext", ruleContext);
+ update("file", eval("list(ruleContext.attr.dep.files)[0]"));
+ update("action", eval("ruleContext.attr.dep[Actions].by_file[file]"));
+
+ assertThat(eval("type(action)")).isEqualTo("Action");
+
+ Object contentUnchecked = eval("action.content");
+ assertThat(contentUnchecked).isInstanceOf(String.class);
+ assertThat(contentUnchecked).isEqualTo("bbbbb\nbcdef\n");
+
+ Object substitutionsUnchecked = eval("action.substitutions");
+ assertThat(substitutionsUnchecked).isInstanceOf(SkylarkDict.class);
+ assertThat(substitutionsUnchecked).isEqualTo(SkylarkDict.of(null, "a", "b"));
+ }
}