cparsons | e2d200f | 2018-03-06 16:15:11 -0800 | [diff] [blame] | 1 | // Copyright 2018 The Bazel Authors. All rights reserved. |
| 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | package com.google.devtools.build.lib.skylark; |
| 15 | |
| 16 | import static com.google.common.truth.Truth.assertThat; |
| 17 | |
| 18 | import com.google.common.collect.ImmutableList; |
dannark | 90e2b4b | 2018-06-27 13:35:04 -0700 | [diff] [blame] | 19 | import com.google.common.collect.ImmutableMap; |
cparsons | e2d200f | 2018-03-06 16:15:11 -0800 | [diff] [blame] | 20 | import com.google.common.collect.Iterables; |
| 21 | import com.google.devtools.build.lib.actions.ActionAnalysisMetadata; |
cparsons | bb956ec | 2018-04-11 11:22:38 -0700 | [diff] [blame] | 22 | import com.google.devtools.build.lib.actions.Artifact; |
ulfjack | c23bdac | 2018-06-13 03:06:16 -0700 | [diff] [blame] | 23 | import com.google.devtools.build.lib.analysis.AnalysisResult; |
cparsons | e2d200f | 2018-03-06 16:15:11 -0800 | [diff] [blame] | 24 | import com.google.devtools.build.lib.analysis.ConfiguredAspect; |
| 25 | import com.google.devtools.build.lib.analysis.util.AnalysisTestCase; |
| 26 | import com.google.devtools.build.lib.cmdline.Label; |
| 27 | import com.google.devtools.build.lib.packages.SkylarkProvider.SkylarkKey; |
cparsons | bb956ec | 2018-04-11 11:22:38 -0700 | [diff] [blame] | 28 | import com.google.devtools.build.lib.syntax.SkylarkDict; |
cparsons | e2d200f | 2018-03-06 16:15:11 -0800 | [diff] [blame] | 29 | import com.google.devtools.build.lib.syntax.SkylarkList; |
cparsons | bb956ec | 2018-04-11 11:22:38 -0700 | [diff] [blame] | 30 | import java.util.List; |
cparsons | e2d200f | 2018-03-06 16:15:11 -0800 | [diff] [blame] | 31 | import java.util.stream.Collectors; |
| 32 | import org.junit.Test; |
| 33 | import org.junit.runner.RunWith; |
| 34 | import org.junit.runners.JUnit4; |
| 35 | |
| 36 | /** Tests for the Skylark-accessible actions provider on rule configured targets. */ |
| 37 | @RunWith(JUnit4.class) |
| 38 | public class SkylarkActionProviderTest extends AnalysisTestCase { |
| 39 | |
| 40 | @Test |
| 41 | public void aspectGetsActionProviderForNativeRule() throws Exception { |
| 42 | scratch.file( |
| 43 | "test/aspect.bzl", |
| 44 | "foo = provider()", |
| 45 | "def _impl(target, ctx):", |
| 46 | " return [foo(actions = target.actions)]", |
| 47 | "MyAspect = aspect(implementation=_impl)"); |
| 48 | scratch.file( |
| 49 | "test/BUILD", |
| 50 | "genrule(", |
| 51 | " name = 'xxx',", |
| 52 | " cmd = 'echo \"hello\" > $@',", |
| 53 | " outs = ['mygen.out']", |
| 54 | ")"); |
| 55 | |
| 56 | AnalysisResult analysisResult = |
| 57 | update(ImmutableList.of("test/aspect.bzl%MyAspect"), "//test:xxx"); |
| 58 | |
| 59 | ConfiguredAspect configuredAspect = |
| 60 | Iterables.getOnlyElement(analysisResult.getAspects()).getConfiguredAspect(); |
| 61 | |
dannark | 90e2b4b | 2018-06-27 13:35:04 -0700 | [diff] [blame] | 62 | SkylarkKey fooKey = |
| 63 | new SkylarkKey(Label.parseAbsolute("//test:aspect.bzl", ImmutableMap.of()), "foo"); |
cparsons | e2d200f | 2018-03-06 16:15:11 -0800 | [diff] [blame] | 64 | |
| 65 | assertThat(configuredAspect.get(fooKey).getValue("actions")).isNotNull(); |
| 66 | @SuppressWarnings("unchecked") |
| 67 | SkylarkList<ActionAnalysisMetadata> actions = |
| 68 | (SkylarkList<ActionAnalysisMetadata>) configuredAspect.get(fooKey).getValue("actions"); |
| 69 | assertThat(actions).isNotEmpty(); |
| 70 | |
| 71 | ActionAnalysisMetadata action = actions.get(0); |
| 72 | assertThat(action.getMnemonic()).isEqualTo("Genrule"); |
| 73 | } |
| 74 | |
| 75 | @Test |
cparsons | bb956ec | 2018-04-11 11:22:38 -0700 | [diff] [blame] | 76 | @SuppressWarnings("unchecked") |
cparsons | e2d200f | 2018-03-06 16:15:11 -0800 | [diff] [blame] | 77 | public void aspectGetsActionProviderForSkylarkRule() throws Exception { |
| 78 | scratch.file( |
| 79 | "test/aspect.bzl", |
| 80 | "foo = provider()", |
| 81 | "def _impl(target, ctx):", |
cparsons | bb956ec | 2018-04-11 11:22:38 -0700 | [diff] [blame] | 82 | " mnemonics = [a.mnemonic for a in target.actions]", |
| 83 | " envs = [a.env for a in target.actions]", |
| 84 | " inputs = [a.inputs.to_list() for a in target.actions]", |
| 85 | " outputs = [a.outputs.to_list() for a in target.actions]", |
| 86 | " argv = [a.argv for a in target.actions]", |
| 87 | " return [foo(", |
| 88 | " actions = target.actions,", |
| 89 | " mnemonics = mnemonics,", |
| 90 | " envs = envs,", |
| 91 | " inputs = inputs,", |
| 92 | " outputs = outputs,", |
| 93 | " argv = argv", |
| 94 | " )]", |
cparsons | e2d200f | 2018-03-06 16:15:11 -0800 | [diff] [blame] | 95 | "MyAspect = aspect(implementation=_impl)"); |
| 96 | scratch.file( |
| 97 | "test/rule.bzl", |
| 98 | "def impl(ctx):", |
| 99 | " output_file0 = ctx.new_file('myfile0')", |
| 100 | " output_file1 = ctx.new_file('myfile1')", |
cparsons | bb956ec | 2018-04-11 11:22:38 -0700 | [diff] [blame] | 101 | " executable = ctx.new_file('executable')", |
| 102 | " ctx.actions.run(outputs=[output_file0], executable=executable,", |
| 103 | " mnemonic='MyAction0', env={'foo':'bar', 'pet':'puppy'})", |
| 104 | " ctx.actions.run_shell(outputs=[executable, output_file1],", |
| 105 | " command='fakecmd', mnemonic='MyAction1', env={'pet':'bunny'})", |
cparsons | e2d200f | 2018-03-06 16:15:11 -0800 | [diff] [blame] | 106 | " return None", |
| 107 | "my_rule = rule(impl)"); |
| 108 | scratch.file( |
| 109 | "test/BUILD", "load('//test:rule.bzl', 'my_rule')", "my_rule(", " name = 'xxx',", ")"); |
| 110 | |
| 111 | AnalysisResult analysisResult = |
| 112 | update(ImmutableList.of("test/aspect.bzl%MyAspect"), "//test:xxx"); |
| 113 | |
| 114 | ConfiguredAspect configuredAspect = |
| 115 | Iterables.getOnlyElement(analysisResult.getAspects()).getConfiguredAspect(); |
| 116 | |
dannark | 90e2b4b | 2018-06-27 13:35:04 -0700 | [diff] [blame] | 117 | SkylarkKey fooKey = |
| 118 | new SkylarkKey(Label.parseAbsolute("//test:aspect.bzl", ImmutableMap.of()), "foo"); |
cparsons | e2d200f | 2018-03-06 16:15:11 -0800 | [diff] [blame] | 119 | |
| 120 | assertThat(configuredAspect.get(fooKey).getValue("actions")).isNotNull(); |
cparsons | bb956ec | 2018-04-11 11:22:38 -0700 | [diff] [blame] | 121 | |
cparsons | e2d200f | 2018-03-06 16:15:11 -0800 | [diff] [blame] | 122 | SkylarkList<ActionAnalysisMetadata> actions = |
| 123 | (SkylarkList<ActionAnalysisMetadata>) configuredAspect.get(fooKey).getValue("actions"); |
| 124 | assertThat(actions).hasSize(2); |
| 125 | |
cparsons | bb956ec | 2018-04-11 11:22:38 -0700 | [diff] [blame] | 126 | SkylarkList<String> mnemonics = |
| 127 | (SkylarkList<String>) configuredAspect.get(fooKey).getValue("mnemonics"); |
| 128 | assertThat(mnemonics).containsExactly("MyAction0", "MyAction1"); |
| 129 | |
| 130 | SkylarkList<SkylarkDict<String, String>> envs = |
| 131 | (SkylarkList<SkylarkDict<String, String>>) configuredAspect.get(fooKey).getValue("envs"); |
| 132 | assertThat(envs).containsExactly( |
| 133 | SkylarkDict.of(null, "foo", "bar", "pet", "puppy"), |
| 134 | SkylarkDict.of(null, "pet", "bunny")); |
| 135 | |
| 136 | SkylarkList<SkylarkList<Artifact>> inputs = |
| 137 | (SkylarkList<SkylarkList<Artifact>>) configuredAspect.get(fooKey).getValue("inputs"); |
| 138 | assertThat(flattenArtifactNames(inputs)).containsExactly("executable"); |
| 139 | |
| 140 | SkylarkList<SkylarkList<Artifact>> outputs = |
| 141 | (SkylarkList<SkylarkList<Artifact>>) configuredAspect.get(fooKey).getValue("outputs"); |
| 142 | assertThat(flattenArtifactNames(outputs)).containsExactly("myfile0", "executable", "myfile1"); |
| 143 | |
| 144 | SkylarkList<SkylarkList<String>> argv = |
| 145 | (SkylarkList<SkylarkList<String>>) configuredAspect.get(fooKey).getValue("argv"); |
| 146 | assertThat(argv.get(0)).hasSize(1); |
| 147 | assertThat(argv.get(0).get(0)).endsWith("executable"); |
| 148 | assertThat(argv.get(1)).contains("fakecmd"); |
| 149 | } |
| 150 | |
| 151 | private static List<String> flattenArtifactNames( |
| 152 | SkylarkList<SkylarkList<Artifact>> artifactLists) { |
| 153 | return artifactLists.stream() |
| 154 | .flatMap(artifacts -> artifacts.stream()) |
| 155 | .map(artifact -> artifact.getFilename()) |
| 156 | .collect(Collectors.toList()); |
cparsons | e2d200f | 2018-03-06 16:15:11 -0800 | [diff] [blame] | 157 | } |
| 158 | } |