blob: e60bfebff693cad89147fb0ad4fb48ebba15ed88 [file] [log] [blame]
Damien Martin-Guillerezf88f4d82015-09-25 13:56:55 +00001// Copyright 2015 The Bazel Authors. All rights reserved.
Ulf Adams89179252015-04-23 18:48:39 +00002//
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.
14package com.google.devtools.build.lib.analysis;
15
16import static com.google.common.truth.Truth.assertThat;
Carmi Grushkoeaaa9d0d2015-11-17 01:54:45 +000017import static com.google.devtools.build.lib.analysis.BaseRuleClasses.ACTION_LISTENER;
gregce593f7f92017-09-19 02:02:21 +020018import static com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode.TARGET;
Carmi Grushko06f65f72015-11-02 22:42:24 +000019import static com.google.devtools.build.lib.packages.Attribute.attr;
20import static com.google.devtools.build.lib.packages.BuildType.LABEL;
21import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST;
Florian Weikertfd735f32015-11-27 17:32:23 +000022import static org.junit.Assert.fail;
Ulf Adams89179252015-04-23 18:48:39 +000023
Greg Estrenc8a127c2017-02-13 20:21:33 +000024import com.google.common.collect.ImmutableList;
dslomov99ea6b42017-04-25 17:46:17 +020025import com.google.common.collect.Iterables;
26import com.google.common.eventbus.EventBus;
Carmi Grushkodf9e5e12016-11-08 23:07:57 +000027import com.google.devtools.build.lib.actions.Artifact;
Carmi Grushkoeaaa9d0d2015-11-17 01:54:45 +000028import com.google.devtools.build.lib.actions.util.ActionsTestUtil.NullAction;
dslomov99ea6b42017-04-25 17:46:17 +020029import com.google.devtools.build.lib.analysis.BuildView.AnalysisResult;
gregce676a9572017-12-21 11:33:32 -080030import com.google.devtools.build.lib.analysis.config.HostTransition;
Florian Weikertcca703a2015-12-07 09:56:38 +000031import com.google.devtools.build.lib.analysis.util.AnalysisTestCase;
gregceb87a41f32017-11-29 07:46:25 -080032import com.google.devtools.build.lib.analysis.util.MockRule;
Ulf Adams89179252015-04-23 18:48:39 +000033import com.google.devtools.build.lib.analysis.util.TestAspects;
dslomov99ea6b42017-04-25 17:46:17 +020034import com.google.devtools.build.lib.analysis.util.TestAspects.AspectApplyingToFiles;
Carmi Grushko06f65f72015-11-02 22:42:24 +000035import com.google.devtools.build.lib.analysis.util.TestAspects.AspectInfo;
Carmi Grushko06f65f72015-11-02 22:42:24 +000036import com.google.devtools.build.lib.analysis.util.TestAspects.DummyRuleFactory;
37import com.google.devtools.build.lib.analysis.util.TestAspects.RuleInfo;
Carmi Grushkoeaaa9d0d2015-11-17 01:54:45 +000038import com.google.devtools.build.lib.cmdline.Label;
39import com.google.devtools.build.lib.collect.nestedset.NestedSet;
Carmi Grushko06f65f72015-11-02 22:42:24 +000040import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
41import com.google.devtools.build.lib.collect.nestedset.Order;
Michael Staib2707a882016-09-16 21:06:40 +000042import com.google.devtools.build.lib.events.OutputFilter.RegexOutputFilter;
Carmi Grushko06f65f72015-11-02 22:42:24 +000043import com.google.devtools.build.lib.packages.AspectDefinition;
44import com.google.devtools.build.lib.packages.AspectParameters;
mstaib807a9b22017-09-19 17:06:32 +020045import com.google.devtools.build.lib.packages.Attribute.LateBoundDefault;
Luis Fernando Pino Duquee82713d2016-04-26 16:22:38 +000046import com.google.devtools.build.lib.packages.NativeAspectClass;
dslomov99ea6b42017-04-25 17:46:17 +020047import com.google.devtools.build.lib.skyframe.AspectValue;
mjhalupkab9a0baf2018-01-31 14:04:50 -080048import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndTarget;
janakr7a6e0022017-10-12 22:53:47 +020049import com.google.devtools.build.lib.testutil.TestConstants;
Lukacs Berki75250e62016-04-12 13:48:24 +000050import com.google.devtools.build.lib.vfs.ModifiedFileSet;
tomluee6a6862018-01-17 14:36:26 -080051import com.google.devtools.build.lib.vfs.Root;
Carmi Grushkodf9e5e12016-11-08 23:07:57 +000052import java.util.ArrayList;
53import java.util.List;
Michael Staib2707a882016-09-16 21:06:40 +000054import java.util.regex.Pattern;
Ulf Adams89179252015-04-23 18:48:39 +000055import org.junit.Test;
56import org.junit.runner.RunWith;
57import org.junit.runners.JUnit4;
58
59/**
60 * Tests for aspect creation and merging with configured targets.
61 *
62 * <p>Uses the complete analysis machinery and depends on custom rules so that behaviors related to
63 * aspects can be tested even if they aren't used by regular rules.
64 */
65@RunWith(JUnit4.class)
Florian Weikertcca703a2015-12-07 09:56:38 +000066public class AspectTest extends AnalysisTestCase {
Ulf Adams89179252015-04-23 18:48:39 +000067
Ulf Adams89179252015-04-23 18:48:39 +000068 private void pkg(String name, String... contents) throws Exception {
Ulf Adams01f1b462015-04-27 09:52:33 +000069 scratch.file("" + name + "/BUILD", contents);
Ulf Adams89179252015-04-23 18:48:39 +000070 }
71
72 @Test
Lukacs Berkiea988b62016-08-30 12:26:18 +000073 public void testAspectAppliedToAliasWithSelect() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -080074 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.ASPECT_REQUIRING_RULE);
Lukacs Berkiea988b62016-08-30 12:26:18 +000075 pkg("a",
76 "aspect(name='a', foo=[':b'])",
77 "alias(name='b', actual=select({'//conditions:default': ':c'}))",
78 "base(name='c')");
79 ConfiguredTarget a = getConfiguredTarget("//a:a");
80 assertThat(a.getProvider(RuleInfo.class).getData())
81 .containsExactly("aspect //a:c", "rule //a:a");
82 }
83
84 @Test
85 public void testAspectAppliedToChainedAliases() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -080086 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.ASPECT_REQUIRING_RULE);
Lukacs Berkiea988b62016-08-30 12:26:18 +000087 pkg("a",
88 "aspect(name='a', foo=[':b'])",
89 "alias(name='b', actual=':c')",
90 "alias(name='c', actual=':d')",
91 "alias(name='d', actual=':e')",
92 "base(name='e')");
93
94 ConfiguredTarget a = getConfiguredTarget("//a:a");
95 assertThat(a.getProvider(RuleInfo.class).getData())
96 .containsExactly("aspect //a:e", "rule //a:a");
97 }
98
99 @Test
100 public void testAspectAppliedToChainedAliasesAndSelect() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800101 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.ASPECT_REQUIRING_RULE);
Lukacs Berkiea988b62016-08-30 12:26:18 +0000102 pkg("a",
103 "aspect(name='a', foo=[':b'])",
104 "alias(name='b', actual=select({'//conditions:default': ':c'}))",
105 "alias(name='c', actual=select({'//conditions:default': ':d'}))",
106 "base(name='d')");
107 ConfiguredTarget a = getConfiguredTarget("//a:a");
108 assertThat(a.getProvider(RuleInfo.class).getData())
109 .containsExactly("aspect //a:d", "rule //a:a");
110 }
111
112 @Test
Ulf Adams89179252015-04-23 18:48:39 +0000113 public void providersOfAspectAreMergedIntoDependency() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800114 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.ASPECT_REQUIRING_RULE);
Ulf Adams89179252015-04-23 18:48:39 +0000115 pkg("a",
116 "aspect(name='a', foo=[':b'])",
117 "aspect(name='b', foo=[])");
118
119 ConfiguredTarget a = getConfiguredTarget("//a:a");
Carmi Grushko06f65f72015-11-02 22:42:24 +0000120 assertThat(a.getProvider(RuleInfo.class).getData())
Ulf Adams89179252015-04-23 18:48:39 +0000121 .containsExactly("aspect //a:b", "rule //a:a");
122 }
123
124 @Test
125 public void aspectIsNotCreatedIfAdvertisedProviderIsNotPresent() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800126 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.LIAR_RULE,
127 TestAspects.ASPECT_REQUIRING_PROVIDER_RULE);
Ulf Adams89179252015-04-23 18:48:39 +0000128
129 pkg("a",
130 "aspect_requiring_provider(name='a', foo=[':b'])",
131 "liar(name='b', foo=[])");
132
133 ConfiguredTarget a = getConfiguredTarget("//a:a");
Carmi Grushko06f65f72015-11-02 22:42:24 +0000134 assertThat(a.getProvider(RuleInfo.class).getData()).containsExactly("rule //a:a");
Ulf Adams89179252015-04-23 18:48:39 +0000135 }
136
Lukacs Berki549bfce2016-04-22 15:29:12 +0000137 @Test
Dmitry Lomov6cd98972017-03-01 15:44:00 +0000138 public void aspectIsNotCreatedIfAdvertisedProviderIsNotPresentWithAlias() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800139 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.LIAR_RULE,
140 TestAspects.ASPECT_REQUIRING_PROVIDER_RULE);
Dmitry Lomov6cd98972017-03-01 15:44:00 +0000141
142 pkg("a",
143 "aspect_requiring_provider(name='a', foo=[':b'])",
144 "alias(name = 'b_alias', actual = ':b')",
145 "liar(name='b', foo=[])");
146
147 ConfiguredTarget a = getConfiguredTarget("//a:a");
148 assertThat(a.getProvider(RuleInfo.class).getData()).containsExactly("rule //a:a");
149 }
150
151 @Test
152 public void aspectIsNotPropagatedThroughLiars() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800153 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.LIAR_RULE,
154 TestAspects.HONEST_RULE, TestAspects.ASPECT_REQUIRING_PROVIDER_RULE);
Dmitry Lomov6cd98972017-03-01 15:44:00 +0000155
156 pkg("a",
157 "aspect_requiring_provider(name='a', foo=[':b_alias'])",
158 "alias(name = 'b_alias', actual = ':b')",
159 "liar(name='b', foo=[':c'])",
160 "honest(name = 'c', foo = [])"
161 );
162
163 ConfiguredTarget a = getConfiguredTarget("//a:a");
164 assertThat(a.getProvider(RuleInfo.class).getData()).containsExactly("rule //a:a");
165 }
166
167 @Test
168 public void aspectPropagatedThroughAliasRule() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800169 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.HONEST_RULE,
170 TestAspects.ASPECT_REQUIRING_PROVIDER_RULE);
Dmitry Lomov6cd98972017-03-01 15:44:00 +0000171
172 pkg("a",
173 "aspect_requiring_provider(name='a', foo=[':b_alias'])",
174 "alias(name = 'b_alias', actual = ':b')",
175 "honest(name='b', foo=[])");
176
177 ConfiguredTarget a = getConfiguredTarget("//a:a");
178 assertThat(a.getProvider(RuleInfo.class).getData()).containsExactly(
179 "rule //a:a", "aspect //a:b");
180 }
181
182 @Test
183 public void aspectPropagatedThroughAliasRuleAndHonestRules() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800184 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.HONEST_RULE,
185 TestAspects.ASPECT_REQUIRING_PROVIDER_RULE);
Dmitry Lomov6cd98972017-03-01 15:44:00 +0000186
187 pkg("a",
188 "aspect_requiring_provider(name='a', foo=[':b'])",
189 "alias(name = 'b_alias', actual = ':b')",
190 "honest(name='b', foo=[':c'])",
191 "honest(name='c', foo=[])"
192 );
193
194 ConfiguredTarget a = getConfiguredTarget("//a:a");
195 assertThat(a.getProvider(RuleInfo.class).getData()).containsExactly(
196 "rule //a:a", "aspect //a:b", "aspect //a:c");
197 }
198
199
200
201
202
203 @Test
Lukacs Berki75250e62016-04-12 13:48:24 +0000204 public void aspectCreationWorksThroughBind() throws Exception {
janakr7a6e0022017-10-12 22:53:47 +0200205 if (getInternalTestExecutionMode() != TestConstants.InternalTestExecutionMode.NORMAL) {
206 // TODO(b/67651960): fix or justify disabling.
207 return;
208 }
gregceb87a41f32017-11-29 07:46:25 -0800209 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.HONEST_RULE,
210 TestAspects.ASPECT_REQUIRING_PROVIDER_RULE);
Lukacs Berki75250e62016-04-12 13:48:24 +0000211 pkg("a",
212 "aspect_requiring_provider(name='a', foo=['//external:b'])",
213 "honest(name='b', foo=[])");
214
215 scratch.overwriteFile("WORKSPACE",
Greg Estrenc8a127c2017-02-13 20:21:33 +0000216 new ImmutableList.Builder<String>()
217 .addAll(analysisMock.getWorkspaceContents(mockToolsConfig))
218 .add("bind(name='b', actual='//a:b')")
219 .build());
Lukacs Berki75250e62016-04-12 13:48:24 +0000220
tomluee6a6862018-01-17 14:36:26 -0800221 skyframeExecutor.invalidateFilesUnderPathForTesting(
222 reporter, ModifiedFileSet.EVERYTHING_MODIFIED, Root.fromPath(rootDirectory));
Lukacs Berki75250e62016-04-12 13:48:24 +0000223
224 ConfiguredTarget a = getConfiguredTarget("//a:a");
225 assertThat(a.getProvider(RuleInfo.class).getData())
226 .containsExactly("rule //a:a", "aspect //a:b");
227 }
228
229
Ulf Adams89179252015-04-23 18:48:39 +0000230 @Test
231 public void aspectCreatedIfAdvertisedProviderIsPresent() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800232 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.HONEST_RULE,
233 TestAspects.ASPECT_REQUIRING_PROVIDER_RULE);
Ulf Adams89179252015-04-23 18:48:39 +0000234
235 pkg("a",
236 "aspect_requiring_provider(name='a', foo=[':b'])",
237 "honest(name='b', foo=[])");
238
239 ConfiguredTarget a = getConfiguredTarget("//a:a");
Carmi Grushko06f65f72015-11-02 22:42:24 +0000240 assertThat(a.getProvider(RuleInfo.class).getData())
Ulf Adams89179252015-04-23 18:48:39 +0000241 .containsExactly("rule //a:a", "aspect //a:b");
242 }
243
244 @Test
Rumou Duan6f8393f2016-11-30 16:03:10 +0000245 public void aspectCreatedIfAtLeastOneSetOfAdvertisedProvidersArePresent() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800246 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.HONEST_RULE,
247 TestAspects.HONEST_RULE_2, TestAspects.ASPECT_REQUIRING_PROVIDER_SETS_RULE);
Rumou Duan6f8393f2016-11-30 16:03:10 +0000248
249 pkg("a",
250 "aspect_requiring_provider_sets(name='a', foo=[':b', ':c'])",
251 "honest(name='b', foo=[])",
252 "honest2(name='c', foo=[])");
253
254 ConfiguredTarget a = getConfiguredTarget("//a:a");
255 assertThat(a.getProvider(RuleInfo.class).getData())
256 .containsExactly("rule //a:a", "aspect //a:b", "aspect //a:c");
257 }
258
259 @Test
Dmitry Lomov6231d082015-11-02 17:17:20 +0000260 public void aspectWithParametrizedDefinition() throws Exception {
Dmitry Lomovd1260742016-05-03 18:37:11 +0000261 setRulesAvailableInTests(
gregceb87a41f32017-11-29 07:46:25 -0800262 TestAspects.BASE_RULE,
263 TestAspects.HONEST_RULE,
264 TestAspects.PARAMETERIZED_DEFINITION_ASPECT_RULE);
Dmitry Lomov6231d082015-11-02 17:17:20 +0000265
266 pkg(
267 "a",
268 "honest(name='q', foo=[])",
269 "parametrized_definition_aspect(name='a', foo=[':b'], baz='//a:q')",
270 "honest(name='c', foo=[])",
271 "honest(name='b', foo=[':c'])");
272
273 ConfiguredTarget a = getConfiguredTarget("//a:a");
274 assertThat(a.getProvider(TestAspects.RuleInfo.class).getData())
275 .containsExactly(
276 "rule //a:a",
277 "aspect //a:b data //a:q $dep:[ //a:q]",
278 "aspect //a:c data //a:q $dep:[ //a:q]");
279 }
280
281 @Test
Ulf Adams89179252015-04-23 18:48:39 +0000282 public void aspectInError() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800283 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.ERROR_ASPECT_RULE,
284 TestAspects.SIMPLE_RULE);
Ulf Adams89179252015-04-23 18:48:39 +0000285
286 pkg("a",
287 "simple(name='a', foo=[':b'])",
288 "error_aspect(name='b', foo=[':c'])",
289 "simple(name='c')");
290
291 reporter.removeHandler(failFastHandler);
292 // getConfiguredTarget() uses a separate code path that does not hit
293 // SkyframeBuildView#configureTargets
294 try {
295 update("//a:a");
296 fail();
297 } catch (ViewCreationFailedException e) {
298 // expected
299 }
300 assertContainsEvent("Aspect error");
301 }
Marian Lobur2099da02015-05-12 14:42:01 +0000302
303 @Test
Marian Loburfc567b32015-09-14 08:44:25 +0000304 public void transitiveAspectInError() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800305 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.ERROR_ASPECT_RULE,
306 TestAspects.SIMPLE_RULE);
Marian Loburfc567b32015-09-14 08:44:25 +0000307
308 pkg("a",
309 "error_aspect(name='a', foo=[':b'])",
310 "error_aspect(name='b', bar=[':c'])",
311 "error_aspect(name='c', bar=[':d'])",
312 "error_aspect(name='d')");
313
314 reporter.removeHandler(failFastHandler);
315 // getConfiguredTarget() uses a separate code path that does not hit
316 // SkyframeBuildView#configureTargets
317 try {
318 update("//a:a");
319 fail();
320 } catch (ViewCreationFailedException e) {
321 // expected
322 }
323 assertContainsEvent("Aspect error");
324 }
325
326 @Test
Michael Staib2707a882016-09-16 21:06:40 +0000327 public void aspectDependenciesDontShowDeprecationWarnings() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800328 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.EXTRA_ATTRIBUTE_ASPECT_RULE);
Michael Staib2707a882016-09-16 21:06:40 +0000329
330 pkg("extra", "base(name='extra', deprecation='bad aspect')");
331
332 pkg("a",
333 "rule_with_extra_deps_aspect(name='a', foo=[':b'])",
334 "base(name='b')");
335
336 getConfiguredTarget("//a:a");
337 assertContainsEventWithFrequency("bad aspect", 0);
338 }
339
340 @Test
341 public void ruleDependencyDeprecationWarningsAbsentDuringAspectEvaluations() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800342 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.ASPECT_REQUIRING_RULE);
Michael Staib2707a882016-09-16 21:06:40 +0000343
344 pkg("a", "aspect(name='a', foo=['//b:b'])");
345 pkg("b", "aspect(name='b', bar=['//d:d'])");
346 pkg("d", "base(name='d', deprecation='bad rule')");
347
348 getConfiguredTarget("//a:a");
349 assertContainsEventWithFrequency("bad rule", 1);
350 }
351
352 @Test
353 public void aspectWarningsFilteredByOutputFiltersForAssociatedRules() throws Exception {
janakr7a6e0022017-10-12 22:53:47 +0200354 if (getInternalTestExecutionMode() != TestConstants.InternalTestExecutionMode.NORMAL) {
355 // TODO(b/67651960): fix or justify disabling.
356 return;
357 }
gregceb87a41f32017-11-29 07:46:25 -0800358 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.WARNING_ASPECT_RULE);
Michael Staib2707a882016-09-16 21:06:40 +0000359 pkg("a", "warning_aspect(name='a', foo=['//b:b', '//c:c'])");
360 pkg("b", "base(name='b')");
361 pkg("c", "base(name='c')");
362
363 reporter.setOutputFilter(RegexOutputFilter.forPattern(Pattern.compile("^//b:")));
364
365 getConfiguredTarget("//a:a");
366 assertContainsEventWithFrequency("Aspect warning on //b:b", 1);
367 assertContainsEventWithFrequency("Aspect warning on //c:c", 0);
368 }
369
370 @Test
Marian Lobur2099da02015-05-12 14:42:01 +0000371 public void sameTargetInDifferentAttributes() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800372 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.ASPECT_REQUIRING_RULE,
373 TestAspects.SIMPLE_RULE);
Marian Lobur2099da02015-05-12 14:42:01 +0000374 pkg("a",
375 "aspect(name='a', foo=[':b'], bar=[':b'])",
376 "aspect(name='b', foo=[])");
377
378 ConfiguredTarget a = getConfiguredTarget("//a:a");
Carmi Grushko06f65f72015-11-02 22:42:24 +0000379 assertThat(a.getProvider(RuleInfo.class).getData())
Marian Lobur2099da02015-05-12 14:42:01 +0000380 .containsExactly("aspect //a:b", "rule //a:a");
381 }
Marian Lobur702cad72015-09-02 09:53:58 +0000382
383 @Test
kaipi64e952c2017-05-22 17:12:08 +0200384 public void sameTargetInDifferentAttributesWithDifferentAspects() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800385 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.MULTI_ASPECT_RULE,
386 TestAspects.SIMPLE_RULE);
kaipi64e952c2017-05-22 17:12:08 +0200387 pkg("a",
388 "multi_aspect(name='a', foo=':b', bar=':b')",
389 "simple(name='b')");
390
391 ConfiguredTarget a = getConfiguredTarget("//a:a");
392 assertThat(a.getProvider(RuleInfo.class).getData()).containsExactly("foo", "bar");
393 }
394
395 @Test
Marian Lobur702cad72015-09-02 09:53:58 +0000396 public void informationFromBaseRulePassedToAspect() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800397 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.HONEST_RULE,
398 TestAspects.ASPECT_REQUIRING_PROVIDER_RULE);
Marian Lobur702cad72015-09-02 09:53:58 +0000399 pkg("a",
400 "aspect_requiring_provider(name='a', foo=[':b'], baz='hello')",
401 "honest(name='b', foo=[])");
402
403 ConfiguredTarget a = getConfiguredTarget("//a:a");
Carmi Grushko06f65f72015-11-02 22:42:24 +0000404 assertThat(a.getProvider(RuleInfo.class).getData())
Marian Lobur702cad72015-09-02 09:53:58 +0000405 .containsExactly("rule //a:a", "aspect //a:b data hello");
406 }
Marian Lobur86bd4fd2015-09-16 10:01:38 +0000407
Carmi Grushko06f65f72015-11-02 22:42:24 +0000408 /**
409 * Rule definitions to be used in emptyAspectAttributesAreAvailableInRuleContext().
410 */
411 public static class EmptyAspectAttributesAreAvailableInRuleContext {
gregceb87a41f32017-11-29 07:46:25 -0800412 public static final MockRule TEST_RULE = () ->
413 MockRule.ancestor(TestAspects.BASE_RULE.getClass()).factory(DummyRuleFactory.class).define(
414 "testrule",
415 (builder, env) ->
416 builder
417 .add(attr("foo", LABEL_LIST).legacyAllowAnyFileType()
418 .aspect(new AspectWithEmptyLateBoundAttribute())));
Carmi Grushko06f65f72015-11-02 22:42:24 +0000419
Luis Fernando Pino Duquee82713d2016-04-26 16:22:38 +0000420 public static class AspectWithEmptyLateBoundAttribute extends NativeAspectClass
421 implements ConfiguredAspectFactory {
Carmi Grushko06f65f72015-11-02 22:42:24 +0000422 @Override
423 public AspectDefinition getDefinition(AspectParameters params) {
Dmitry Lomovdce01702016-11-28 15:51:32 +0000424 return new AspectDefinition.Builder(this)
mstaib807a9b22017-09-19 17:06:32 +0200425 .add(attr(":late", LABEL).value(LateBoundDefault.alwaysNull()))
426 .build();
Carmi Grushko06f65f72015-11-02 22:42:24 +0000427 }
428
429 @Override
Dmitry Lomovb487ac62015-11-09 13:09:12 +0000430 public ConfiguredAspect create(
mjhalupkab9a0baf2018-01-31 14:04:50 -0800431 ConfiguredTargetAndTarget ctatBase, RuleContext ruleContext, AspectParameters parameters)
Dmitry Lomovb487ac62015-11-09 13:09:12 +0000432 throws InterruptedException {
Carmi Grushko06f65f72015-11-02 22:42:24 +0000433 Object lateBoundPrereq = ruleContext.getPrerequisite(":late", TARGET);
Dmitry Lomovdce01702016-11-28 15:51:32 +0000434 return new ConfiguredAspect.Builder(this, parameters, ruleContext)
Carmi Grushko06f65f72015-11-02 22:42:24 +0000435 .addProvider(
Carmi Grushko261f5bb2015-12-09 19:38:38 +0000436 AspectInfo.class,
Dmitry Lomovb487ac62015-11-09 13:09:12 +0000437 new AspectInfo(
438 NestedSetBuilder.create(
439 Order.STABLE_ORDER, lateBoundPrereq != null ? "non-empty" : "empty")))
Carmi Grushko06f65f72015-11-02 22:42:24 +0000440 .build();
441 }
442 }
443 }
444
445 /**
mstaib807a9b22017-09-19 17:06:32 +0200446 * An Aspect has a late-bound attribute with no value (that is, a LateBoundDefault whose
447 * getDefault() returns `null`). Test that this attribute is available in the RuleContext which is
448 * provided to the Aspect's `create()` method.
Carmi Grushko06f65f72015-11-02 22:42:24 +0000449 */
450 @Test
451 public void emptyAspectAttributesAreAvailableInRuleContext() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800452 setRulesAvailableInTests(TestAspects.BASE_RULE,
453 EmptyAspectAttributesAreAvailableInRuleContext.TEST_RULE);
Carmi Grushko06f65f72015-11-02 22:42:24 +0000454 pkg("a",
455 "testrule(name='a', foo=[':b'])",
456 "testrule(name='b')");
457 ConfiguredTarget a = getConfiguredTarget("//a:a");
458 assertThat(a.getProvider(RuleInfo.class).getData()).contains("empty");
459 }
460
Carmi Grushkoeaaa9d0d2015-11-17 01:54:45 +0000461 /**
462 * Rule definitions to be used in extraActionsAreEmitted().
463 */
464 public static class ExtraActionsAreEmitted {
gregceb87a41f32017-11-29 07:46:25 -0800465 public static final MockRule TEST_RULE = () ->
466 MockRule.ancestor(TestAspects.BASE_RULE.getClass()).factory(DummyRuleFactory.class).define(
467 "testrule",
468 (builder, env) ->
469 builder
470 .add(attr("foo", LABEL_LIST).legacyAllowAnyFileType()
471 .aspect(new AspectThatRegistersAction()))
gregce676a9572017-12-21 11:33:32 -0800472 .add(attr(":action_listener", LABEL_LIST)
473 .cfg(HostTransition.INSTANCE)
474 .value(ACTION_LISTENER)));
Carmi Grushkoeaaa9d0d2015-11-17 01:54:45 +0000475
Luis Fernando Pino Duquee82713d2016-04-26 16:22:38 +0000476 public static class AspectThatRegistersAction extends NativeAspectClass
477 implements ConfiguredAspectFactory {
Carmi Grushkoeaaa9d0d2015-11-17 01:54:45 +0000478 @Override
479 public AspectDefinition getDefinition(AspectParameters params) {
Dmitry Lomovdce01702016-11-28 15:51:32 +0000480 return new AspectDefinition.Builder(this).build();
Carmi Grushkoeaaa9d0d2015-11-17 01:54:45 +0000481 }
482
Carmi Grushkoeaaa9d0d2015-11-17 01:54:45 +0000483 @Override
484 public ConfiguredAspect create(
mjhalupkab9a0baf2018-01-31 14:04:50 -0800485 ConfiguredTargetAndTarget ctatBase, RuleContext ruleContext, AspectParameters parameters)
486 throws InterruptedException {
Carmi Grushkoeaaa9d0d2015-11-17 01:54:45 +0000487 ruleContext.registerAction(new NullAction(ruleContext.createOutputArtifact()));
Dmitry Lomovdce01702016-11-28 15:51:32 +0000488 return new ConfiguredAspect.Builder(this, parameters, ruleContext).build();
Carmi Grushkoeaaa9d0d2015-11-17 01:54:45 +0000489 }
490 }
491 }
492
493 /**
494 * Test that actions registered in an Aspect are reported as extra-actions on the attached rule.
495 * AspectThatRegistersAction registers a NullAction, whose mnemonic is "Null". We have an
496 * action_listener that targets that mnemonic, which makes sure the Aspect machinery will expose
497 * an ExtraActionArtifactsProvider.
498 * The rule //a:a doesn't have an aspect, so the only action we get is the one on //a:b
499 * (which does have an aspect).
500 */
501 @Test
502 public void extraActionsAreEmitted() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800503 setRulesAvailableInTests(TestAspects.BASE_RULE, ExtraActionsAreEmitted.TEST_RULE);
Carmi Grushkoeaaa9d0d2015-11-17 01:54:45 +0000504 useConfiguration("--experimental_action_listener=//extra_actions:listener");
505 scratch.file(
506 "extra_actions/BUILD",
507 "extra_action(name='xa', cmd='echo dont-care')",
508 "action_listener(name='listener', mnemonics=['Null'], extra_actions=[':xa'])");
509 pkg("a",
510 "testrule(name='a', foo=[':b'])",
511 "testrule(name='b')");
512 update();
513
514 ConfiguredTarget a = getConfiguredTarget("//a:a");
Carmi Grushkobabd4852016-11-18 17:58:09 +0000515 NestedSet<Artifact> extraActionArtifacts =
516 a.getProvider(ExtraActionArtifactsProvider.class).getTransitiveExtraActionArtifacts();
517 for (Artifact artifact : extraActionArtifacts) {
518 assertThat(artifact.getOwnerLabel()).isEqualTo(Label.create("@//a", "b"));
519 }
Carmi Grushkoeaaa9d0d2015-11-17 01:54:45 +0000520 }
Dmitry Lomovbb5901b2016-09-27 08:49:26 +0000521
522 @Test
523 public void aspectPropagatesToAllAttributes() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800524 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.SIMPLE_RULE,
525 TestAspects.ALL_ATTRIBUTES_ASPECT_RULE);
Dmitry Lomovbb5901b2016-09-27 08:49:26 +0000526 pkg("a",
527 "simple(name='a', foo=[':b'], foo1=':c', txt='some text')",
528 "simple(name='b', foo=[], txt='some text')",
529 "simple(name='c', foo=[], txt='more text')",
530 "all_attributes_aspect(name='x', foo=[':a'])");
531
532 ConfiguredTarget a = getConfiguredTarget("//a:x");
533 assertThat(a.getProvider(RuleInfo.class).getData())
534 .containsExactly("aspect //a:a", "aspect //a:b", "aspect //a:c", "rule //a:x");
535 }
536
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000537 /**
538 * Tests that when --experimental_extra_action_top_level_only, Blaze reports extra-actions for
539 * actions registered by Aspects injected by a top-level rule. Because we can't know whether an
540 * aspect was injected by a top-level target or one of its children, we approximate it by only
541 * reporting extra-actions from Aspects that the top-level target could have injected.
542 *
543 * <p>Here, injector1() and injector2() inject aspects into their children. null_rule() just
544 * passes the aspects to its children. The test makes sure that actions registered by aspect1
545 * (injected by injector1()) are reported to the extra-action mechanism. Actions registered by
546 * aspect2 (from injector2) are not reported, because the target under test (//x:a) doesn't inject
547 * aspect2.
548 */
549 @Test
550 public void extraActionsAreEmitted_topLevel() throws Exception {
551 useConfiguration(
552 "--experimental_action_listener=//pkg1:listener",
553 "--experimental_extra_action_top_level_only");
554
555 scratch.file(
556 "x/BUILD",
557 "load(':extension.bzl', 'injector1', 'injector2', 'null_rule')",
558 "injector1(name='a', deps=[':b'])",
559 "null_rule(name='b', deps=[':c'])",
560 "null_rule(name='c', deps=[':d'])",
561 "injector2(name = 'd', extra_deps=[':e'])",
562 "null_rule(name = 'e')");
563
564 scratch.file(
565 "x/extension.bzl",
566 "def _aspect_impl(target, ctx):",
dslomovae0b7742017-06-30 10:07:48 +0200567 " ctx.actions.do_nothing(mnemonic='Mnemonic')",
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000568 " return struct()",
569 "aspect1 = aspect(_aspect_impl, attr_aspects=['deps'])",
570 "aspect2 = aspect(_aspect_impl, attr_aspects=['extra_deps'])",
571 "def _rule_impl(ctx):",
572 " return struct()",
573 "injector1 = rule(_rule_impl, attrs = { 'deps' : attr.label_list(aspects = [aspect1]) })",
574 "null_rule = rule(_rule_impl, attrs = { 'deps' : attr.label_list() })",
575 "injector2 = rule(",
576 " _rule_impl, attrs = { 'extra_deps' : attr.label_list(aspects = [aspect2]) })");
577
578 scratch.file(
579 "pkg1/BUILD",
580 "extra_action(name='xa', cmd='echo dont-care')",
581 "action_listener(name='listener', mnemonics=['Mnemonic'], extra_actions=[':xa'])");
582
583 // Sanity check: //x:d injects an aspect which produces some extra-action.
584 {
585 BuildView.AnalysisResult analysisResult = update("//x:d");
586
587 // Get owners of all extra-action artifacts.
588 List<Label> extraArtifactOwners = new ArrayList<>();
589 for (Artifact artifact : analysisResult.getAdditionalArtifactsToBuild()) {
590 if (artifact.getRootRelativePathString().endsWith(".xa")) {
591 extraArtifactOwners.add(artifact.getOwnerLabel());
592 }
593 }
594 assertThat(extraArtifactOwners).containsExactly(Label.create("@//x", "e"));
595 }
596
597 // Actual test: //x:a reports actions registered by the aspect it injects.
598 {
599 BuildView.AnalysisResult analysisResult = update("//x:a");
600
601 // Get owners of all extra-action artifacts.
602 List<Label> extraArtifactOwners = new ArrayList<>();
603 for (Artifact artifact : analysisResult.getAdditionalArtifactsToBuild()) {
604 if (artifact.getRootRelativePathString().endsWith(".xa")) {
605 extraArtifactOwners.add(artifact.getOwnerLabel());
606 }
607 }
608 assertThat(extraArtifactOwners)
609 .containsExactly(
610 Label.create("@//x", "b"), Label.create("@//x", "c"), Label.create("@//x", "d"));
611 }
612 }
613
Dmitry Lomovbb5901b2016-09-27 08:49:26 +0000614 @Test
Carmi Grushko905a29d2016-12-09 20:42:29 +0000615 public void extraActionsFromDifferentAspectsDontConflict() throws Exception {
616 useConfiguration(
617 "--experimental_action_listener=//pkg1:listener",
618 "--experimental_extra_action_top_level_only");
619
620 scratch.file(
621 "x/BUILD",
622 "load(':extension.bzl', 'injector1', 'injector2', 'null_rule')",
Dmitry Lomov15756522016-12-16 16:52:37 +0000623 "injector2(name='i2_a', deps = [':i1_a'])",
Carmi Grushko905a29d2016-12-09 20:42:29 +0000624 "injector1(name='i1_a', deps=[':n'], param = 'a')",
625 "injector1(name='i1_b', deps=[':n'], param = 'b')",
626 "injector2(name='i2', deps=[':n'])",
627 "null_rule(name = 'n')");
628
629 scratch.file(
630 "x/extension.bzl",
631 "def _aspect_impl(target, ctx):",
dslomovae0b7742017-06-30 10:07:48 +0200632 " ctx.actions.do_nothing(mnemonic='Mnemonic')",
Carmi Grushko905a29d2016-12-09 20:42:29 +0000633 " return struct()",
634 "aspect1 = aspect(_aspect_impl, attr_aspects=['deps'], attrs =",
635 " {'param': attr.string(values = ['a', 'b'])})",
636 "aspect2 = aspect(_aspect_impl, attr_aspects=['deps'])",
637 "def _rule_impl(ctx):",
638 " return struct()",
639 "injector1 = rule(_rule_impl, attrs =",
640 " { 'deps' : attr.label_list(aspects = [aspect1]), 'param' : attr.string() })",
641 "injector2 = rule(_rule_impl, attrs = { 'deps' : attr.label_list(aspects = [aspect2]) })",
642 "null_rule = rule(_rule_impl, attrs = { 'deps' : attr.label_list() })"
643 );
644
645 scratch.file(
646 "pkg1/BUILD",
647 "extra_action(name='xa', cmd='echo dont-care')",
648 "action_listener(name='listener', mnemonics=['Mnemonic'], extra_actions=[':xa'])");
649
Dmitry Lomov15756522016-12-16 16:52:37 +0000650 update("//x:i1_a", "//x:i1_b", "//x:i2", "//x:i2_a");
Carmi Grushko905a29d2016-12-09 20:42:29 +0000651
652 // Implicitly check that update() didn't throw an exception because of two actions producing
653 // the same outputs.
654 }
655
656 @Test
Dmitry Lomovbb5901b2016-09-27 08:49:26 +0000657 public void aspectPropagatesToAllAttributesImplicit() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800658 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.SIMPLE_RULE,
659 TestAspects.IMPLICIT_DEP_RULE, TestAspects.ALL_ATTRIBUTES_ASPECT_RULE);
Dmitry Lomovbb5901b2016-09-27 08:49:26 +0000660 scratch.file(
661 "extra/BUILD",
662 "simple(name ='extra')"
663 );
664 pkg("a",
665 "simple(name='a', foo=[':b'], foo1=':c', txt='some text')",
666 "simple(name='b', foo=[], txt='some text')",
667 "implicit_dep(name='c')",
668 "all_attributes_aspect(name='x', foo=[':a'])");
669 update();
670
671 ConfiguredTarget a = getConfiguredTarget("//a:x");
672 assertThat(a.getProvider(RuleInfo.class).getData())
673 .containsExactly(
674 "aspect //a:a",
675 "aspect //a:b",
676 "aspect //a:c",
677 "aspect //extra:extra",
678 "rule //a:x");
679 }
680
681
682 @Test
683 public void aspectPropagatesToAllAttributesLateBound() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800684 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.SIMPLE_RULE,
685 TestAspects.LATE_BOUND_DEP_RULE, TestAspects.ALL_ATTRIBUTES_ASPECT_RULE);
Dmitry Lomovbb5901b2016-09-27 08:49:26 +0000686
687 scratch.file(
688 "extra/BUILD",
689 "simple(name ='extra')"
690 );
691 pkg("a",
692 "simple(name='a', foo=[':b'], foo1=':c', txt='some text')",
693 "simple(name='b', foo=[], txt='some text')",
694 "late_bound_dep(name='c')",
695 "all_attributes_aspect(name='x', foo=[':a'])");
696 useConfiguration("--plugin=//extra:extra");
697 update();
698
699 ConfiguredTarget a = getConfiguredTarget("//a:x");
700 assertThat(a.getProvider(RuleInfo.class).getData())
701 .containsExactly(
702 "aspect //a:a",
703 "aspect //a:b",
704 "aspect //a:c",
705 "aspect //extra:extra",
706 "rule //a:x");
707 }
708
Googler909910c2016-11-04 15:50:51 +0000709 /**
710 * Ensures an aspect with attr = '*' doesn't try to propagate to its own implicit attributes.
711 * Doing so leads to a dependency cycle.
712 */
713 @Test
714 public void aspectWithAllAttributesDoesNotPropagateToOwnImplicitAttributes() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800715 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.SIMPLE_RULE,
716 TestAspects.ALL_ATTRIBUTES_WITH_TOOL_ASPECT_RULE);
Googler909910c2016-11-04 15:50:51 +0000717 pkg(
718 "a",
719 "simple(name='tool')",
720 "simple(name='a')",
721 "all_attributes_with_tool_aspect(name='x', foo=[':a'])");
722
723 ConfiguredTarget a = getConfiguredTarget("//a:x");
724 assertThat(a.getProvider(RuleInfo.class).getData())
725 .containsExactly("aspect //a:a", "rule //a:x");
726 }
727
728 /**
729 * Makes sure the aspect *will* propagate to its implicit attributes if there is a "regular"
730 * dependency path to it (i.e. not through its own implicit attributes).
731 */
732 @Test
733 public void aspectWithAllAttributesPropagatesToItsToolIfThereIsPath() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800734 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.SIMPLE_RULE,
735 TestAspects.ALL_ATTRIBUTES_WITH_TOOL_ASPECT_RULE);
Googler909910c2016-11-04 15:50:51 +0000736 pkg(
737 "a",
738 "simple(name='tool')",
739 "simple(name='a', foo=[':b'], foo1=':c', txt='some text')",
740 "simple(name='b', foo=[], txt='some text')",
741 "simple(name='c', foo=[':tool'], txt='more text')",
742 "all_attributes_with_tool_aspect(name='x', foo=[':a'])");
743
744 ConfiguredTarget a = getConfiguredTarget("//a:x");
745 assertThat(a.getProvider(RuleInfo.class).getData())
746 .containsExactly(
747 "aspect //a:a", "aspect //a:b", "aspect //a:c", "aspect //a:tool", "rule //a:x");
748 }
Dmitry Lomov65fde002017-02-07 17:24:04 +0000749
750 @Test
751 public void aspectTruthInAdvertisement() throws Exception {
752 reporter.removeHandler(failFastHandler); // expect errors
gregceb87a41f32017-11-29 07:46:25 -0800753 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.SIMPLE_RULE,
754 TestAspects.FALSE_ADVERTISEMENT_ASPECT_RULE);
Dmitry Lomov65fde002017-02-07 17:24:04 +0000755 pkg(
756 "a",
757 "simple(name = 's')",
758 "false_advertisement_aspect(name = 'x', deps = [':s'])"
759 );
760 try {
761 update("//a:x");
762 } catch (ViewCreationFailedException e) {
763 // expected.
764 }
765 assertContainsEvent(
766 "Aspect 'FalseAdvertisementAspect', applied to '//a:s',"
767 + " does not provide advertised provider 'RequiredProvider'");
768 assertContainsEvent(
769 "Aspect 'FalseAdvertisementAspect', applied to '//a:s',"
770 + " does not provide advertised provider 'advertised_provider'");
771 }
dslomov99ea6b42017-04-25 17:46:17 +0200772
773 @Test
dslomovce59d4d2017-08-04 17:32:47 +0200774 public void aspectApplyingToFiles() throws Exception {
dslomov99ea6b42017-04-25 17:46:17 +0200775 AspectApplyingToFiles aspectApplyingToFiles = new AspectApplyingToFiles();
776 setRulesAndAspectsAvailableInTests(
777 ImmutableList.<NativeAspectClass>of(aspectApplyingToFiles),
778 ImmutableList.<RuleDefinition>of());
779 pkg(
780 "a",
781 "java_binary(name = 'x', main_class = 'x.FooBar', srcs = ['x.java'])"
782 );
783 AnalysisResult analysisResult = update(new EventBus(), defaultFlags(),
784 ImmutableList.of(aspectApplyingToFiles.getName()),
785 "//a:x_deploy.jar");
786 AspectValue aspect = Iterables.getOnlyElement(analysisResult.getAspects());
787 AspectApplyingToFiles.Provider provider =
788 aspect.getConfiguredAspect().getProvider(AspectApplyingToFiles.Provider.class);
789 assertThat(provider.getLabel())
790 .isEqualTo(Label.parseAbsoluteUnchecked("//a:x_deploy.jar"));
791 }
dslomovce59d4d2017-08-04 17:32:47 +0200792
793 @Test
794 public void aspectApplyingToSourceFilesIgnored() throws Exception {
795 AspectApplyingToFiles aspectApplyingToFiles = new AspectApplyingToFiles();
796 setRulesAndAspectsAvailableInTests(
797 ImmutableList.<NativeAspectClass>of(aspectApplyingToFiles),
798 ImmutableList.<RuleDefinition>of());
799 pkg(
800 "a",
801 "java_binary(name = 'x', main_class = 'x.FooBar', srcs = ['x.java'])"
802 );
803 scratch.file("a/x.java", "");
804 AnalysisResult analysisResult = update(new EventBus(), defaultFlags(),
805 ImmutableList.of(aspectApplyingToFiles.getName()),
806 "//a:x.java");
807 AspectValue aspect = Iterables.getOnlyElement(analysisResult.getAspects());
808 assertThat(aspect.getConfiguredAspect().getProvider(AspectApplyingToFiles.Provider.class))
809 .isNull();
810 }
811
Ulf Adams89179252015-04-23 18:48:39 +0000812}