blob: a1f9d2a6fe1c2374129e41d4b84f35797d0f8e3d [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;
Carmi Grushko06f65f72015-11-02 22:42:24 +000018import static com.google.devtools.build.lib.packages.Attribute.attr;
19import static com.google.devtools.build.lib.packages.BuildType.LABEL;
20import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST;
michajlo660d17f2020-03-27 09:01:57 -070021import static org.junit.Assert.assertThrows;
Ulf Adams89179252015-04-23 18:48:39 +000022
Greg Estrenc8a127c2017-02-13 20:21:33 +000023import com.google.common.collect.ImmutableList;
dslomov99ea6b42017-04-25 17:46:17 +020024import com.google.common.collect.Iterables;
25import com.google.common.eventbus.EventBus;
Carmi Grushkodf9e5e12016-11-08 23:07:57 +000026import com.google.devtools.build.lib.actions.Artifact;
tomlu39a0a382018-06-22 09:43:23 -070027import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException;
Carmi Grushkoeaaa9d0d2015-11-17 01:54:45 +000028import com.google.devtools.build.lib.actions.util.ActionsTestUtil.NullAction;
gregce676a9572017-12-21 11:33:32 -080029import com.google.devtools.build.lib.analysis.config.HostTransition;
Florian Weikertcca703a2015-12-07 09:56:38 +000030import com.google.devtools.build.lib.analysis.util.AnalysisTestCase;
gregceb87a41f32017-11-29 07:46:25 -080031import com.google.devtools.build.lib.analysis.util.MockRule;
Ulf Adams89179252015-04-23 18:48:39 +000032import com.google.devtools.build.lib.analysis.util.TestAspects;
dslomov99ea6b42017-04-25 17:46:17 +020033import com.google.devtools.build.lib.analysis.util.TestAspects.AspectApplyingToFiles;
Carmi Grushko06f65f72015-11-02 22:42:24 +000034import com.google.devtools.build.lib.analysis.util.TestAspects.AspectInfo;
Carmi Grushko06f65f72015-11-02 22:42:24 +000035import com.google.devtools.build.lib.analysis.util.TestAspects.DummyRuleFactory;
36import com.google.devtools.build.lib.analysis.util.TestAspects.RuleInfo;
Carmi Grushkoeaaa9d0d2015-11-17 01:54:45 +000037import com.google.devtools.build.lib.cmdline.Label;
38import com.google.devtools.build.lib.collect.nestedset.NestedSet;
Carmi Grushko06f65f72015-11-02 22:42:24 +000039import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
40import com.google.devtools.build.lib.collect.nestedset.Order;
Michael Staib2707a882016-09-16 21:06:40 +000041import com.google.devtools.build.lib.events.OutputFilter.RegexOutputFilter;
Carmi Grushko06f65f72015-11-02 22:42:24 +000042import com.google.devtools.build.lib.packages.AspectDefinition;
43import com.google.devtools.build.lib.packages.AspectParameters;
mstaib807a9b22017-09-19 17:06:32 +020044import com.google.devtools.build.lib.packages.Attribute.LateBoundDefault;
Luis Fernando Pino Duquee82713d2016-04-26 16:22:38 +000045import com.google.devtools.build.lib.packages.NativeAspectClass;
janakr9c101402018-03-10 06:48:59 -080046import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndData;
janakr7a6e0022017-10-12 22:53:47 +020047import com.google.devtools.build.lib.testutil.TestConstants;
Lukacs Berki75250e62016-04-12 13:48:24 +000048import com.google.devtools.build.lib.vfs.ModifiedFileSet;
tomluee6a6862018-01-17 14:36:26 -080049import com.google.devtools.build.lib.vfs.Root;
Carmi Grushkodf9e5e12016-11-08 23:07:57 +000050import java.util.ArrayList;
51import java.util.List;
Michael Staib2707a882016-09-16 21:06:40 +000052import java.util.regex.Pattern;
Ulf Adams89179252015-04-23 18:48:39 +000053import org.junit.Test;
54import org.junit.runner.RunWith;
55import org.junit.runners.JUnit4;
56
57/**
58 * Tests for aspect creation and merging with configured targets.
59 *
60 * <p>Uses the complete analysis machinery and depends on custom rules so that behaviors related to
61 * aspects can be tested even if they aren't used by regular rules.
62 */
63@RunWith(JUnit4.class)
Florian Weikertcca703a2015-12-07 09:56:38 +000064public class AspectTest extends AnalysisTestCase {
Ulf Adams89179252015-04-23 18:48:39 +000065
Ulf Adams89179252015-04-23 18:48:39 +000066 private void pkg(String name, String... contents) throws Exception {
jhorvitzcd477f22021-05-05 10:18:22 -070067 scratch.file(name + "/BUILD", contents);
Ulf Adams89179252015-04-23 18:48:39 +000068 }
69
70 @Test
Lukacs Berkiea988b62016-08-30 12:26:18 +000071 public void testAspectAppliedToAliasWithSelect() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -080072 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.ASPECT_REQUIRING_RULE);
Lukacs Berkiea988b62016-08-30 12:26:18 +000073 pkg("a",
74 "aspect(name='a', foo=[':b'])",
75 "alias(name='b', actual=select({'//conditions:default': ':c'}))",
76 "base(name='c')");
77 ConfiguredTarget a = getConfiguredTarget("//a:a");
ulfjackc90b96d2020-01-14 02:46:41 -080078 assertThat(a.getProvider(RuleInfo.class).getData().toList())
Lukacs Berkiea988b62016-08-30 12:26:18 +000079 .containsExactly("aspect //a:c", "rule //a:a");
80 }
81
82 @Test
83 public void testAspectAppliedToChainedAliases() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -080084 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.ASPECT_REQUIRING_RULE);
Lukacs Berkiea988b62016-08-30 12:26:18 +000085 pkg("a",
86 "aspect(name='a', foo=[':b'])",
87 "alias(name='b', actual=':c')",
88 "alias(name='c', actual=':d')",
89 "alias(name='d', actual=':e')",
90 "base(name='e')");
91
92 ConfiguredTarget a = getConfiguredTarget("//a:a");
ulfjackc90b96d2020-01-14 02:46:41 -080093 assertThat(a.getProvider(RuleInfo.class).getData().toList())
Lukacs Berkiea988b62016-08-30 12:26:18 +000094 .containsExactly("aspect //a:e", "rule //a:a");
95 }
96
97 @Test
98 public void testAspectAppliedToChainedAliasesAndSelect() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -080099 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.ASPECT_REQUIRING_RULE);
Lukacs Berkiea988b62016-08-30 12:26:18 +0000100 pkg("a",
101 "aspect(name='a', foo=[':b'])",
102 "alias(name='b', actual=select({'//conditions:default': ':c'}))",
103 "alias(name='c', actual=select({'//conditions:default': ':d'}))",
104 "base(name='d')");
105 ConfiguredTarget a = getConfiguredTarget("//a:a");
ulfjackc90b96d2020-01-14 02:46:41 -0800106 assertThat(a.getProvider(RuleInfo.class).getData().toList())
Lukacs Berkiea988b62016-08-30 12:26:18 +0000107 .containsExactly("aspect //a:d", "rule //a:a");
108 }
109
110 @Test
Ulf Adams89179252015-04-23 18:48:39 +0000111 public void providersOfAspectAreMergedIntoDependency() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800112 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.ASPECT_REQUIRING_RULE);
Ulf Adams89179252015-04-23 18:48:39 +0000113 pkg("a",
114 "aspect(name='a', foo=[':b'])",
115 "aspect(name='b', foo=[])");
116
117 ConfiguredTarget a = getConfiguredTarget("//a:a");
ulfjackc90b96d2020-01-14 02:46:41 -0800118 assertThat(a.getProvider(RuleInfo.class).getData().toList())
Ulf Adams89179252015-04-23 18:48:39 +0000119 .containsExactly("aspect //a:b", "rule //a:a");
120 }
121
122 @Test
123 public void aspectIsNotCreatedIfAdvertisedProviderIsNotPresent() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800124 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.LIAR_RULE,
125 TestAspects.ASPECT_REQUIRING_PROVIDER_RULE);
Ulf Adams89179252015-04-23 18:48:39 +0000126
127 pkg("a",
128 "aspect_requiring_provider(name='a', foo=[':b'])",
129 "liar(name='b', foo=[])");
130
131 ConfiguredTarget a = getConfiguredTarget("//a:a");
ulfjackc90b96d2020-01-14 02:46:41 -0800132 assertThat(a.getProvider(RuleInfo.class).getData().toList()).containsExactly("rule //a:a");
Ulf Adams89179252015-04-23 18:48:39 +0000133 }
134
Lukacs Berki549bfce2016-04-22 15:29:12 +0000135 @Test
Dmitry Lomov6cd98972017-03-01 15:44:00 +0000136 public void aspectIsNotCreatedIfAdvertisedProviderIsNotPresentWithAlias() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800137 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.LIAR_RULE,
138 TestAspects.ASPECT_REQUIRING_PROVIDER_RULE);
Dmitry Lomov6cd98972017-03-01 15:44:00 +0000139
140 pkg("a",
141 "aspect_requiring_provider(name='a', foo=[':b'])",
142 "alias(name = 'b_alias', actual = ':b')",
143 "liar(name='b', foo=[])");
144
145 ConfiguredTarget a = getConfiguredTarget("//a:a");
ulfjackc90b96d2020-01-14 02:46:41 -0800146 assertThat(a.getProvider(RuleInfo.class).getData().toList()).containsExactly("rule //a:a");
Dmitry Lomov6cd98972017-03-01 15:44:00 +0000147 }
148
149 @Test
150 public void aspectIsNotPropagatedThroughLiars() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800151 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.LIAR_RULE,
152 TestAspects.HONEST_RULE, TestAspects.ASPECT_REQUIRING_PROVIDER_RULE);
Dmitry Lomov6cd98972017-03-01 15:44:00 +0000153
154 pkg("a",
155 "aspect_requiring_provider(name='a', foo=[':b_alias'])",
156 "alias(name = 'b_alias', actual = ':b')",
157 "liar(name='b', foo=[':c'])",
158 "honest(name = 'c', foo = [])"
159 );
160
161 ConfiguredTarget a = getConfiguredTarget("//a:a");
ulfjackc90b96d2020-01-14 02:46:41 -0800162 assertThat(a.getProvider(RuleInfo.class).getData().toList()).containsExactly("rule //a:a");
Dmitry Lomov6cd98972017-03-01 15:44:00 +0000163 }
164
165 @Test
166 public void aspectPropagatedThroughAliasRule() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800167 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.HONEST_RULE,
168 TestAspects.ASPECT_REQUIRING_PROVIDER_RULE);
Dmitry Lomov6cd98972017-03-01 15:44:00 +0000169
170 pkg("a",
171 "aspect_requiring_provider(name='a', foo=[':b_alias'])",
172 "alias(name = 'b_alias', actual = ':b')",
173 "honest(name='b', foo=[])");
174
175 ConfiguredTarget a = getConfiguredTarget("//a:a");
ulfjackc90b96d2020-01-14 02:46:41 -0800176 assertThat(a.getProvider(RuleInfo.class).getData().toList())
177 .containsExactly("rule //a:a", "aspect //a:b");
Dmitry Lomov6cd98972017-03-01 15:44:00 +0000178 }
179
180 @Test
181 public void aspectPropagatedThroughAliasRuleAndHonestRules() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800182 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.HONEST_RULE,
183 TestAspects.ASPECT_REQUIRING_PROVIDER_RULE);
Dmitry Lomov6cd98972017-03-01 15:44:00 +0000184
185 pkg("a",
186 "aspect_requiring_provider(name='a', foo=[':b'])",
187 "alias(name = 'b_alias', actual = ':b')",
188 "honest(name='b', foo=[':c'])",
189 "honest(name='c', foo=[])"
190 );
191
192 ConfiguredTarget a = getConfiguredTarget("//a:a");
ulfjackc90b96d2020-01-14 02:46:41 -0800193 assertThat(a.getProvider(RuleInfo.class).getData().toList())
194 .containsExactly("rule //a:a", "aspect //a:b", "aspect //a:c");
Dmitry Lomov6cd98972017-03-01 15:44:00 +0000195 }
196
197
198
199
200
201 @Test
Lukacs Berki75250e62016-04-12 13:48:24 +0000202 public void aspectCreationWorksThroughBind() throws Exception {
janakr7a6e0022017-10-12 22:53:47 +0200203 if (getInternalTestExecutionMode() != TestConstants.InternalTestExecutionMode.NORMAL) {
204 // TODO(b/67651960): fix or justify disabling.
205 return;
206 }
gregceb87a41f32017-11-29 07:46:25 -0800207 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.HONEST_RULE,
208 TestAspects.ASPECT_REQUIRING_PROVIDER_RULE);
Lukacs Berki75250e62016-04-12 13:48:24 +0000209 pkg("a",
210 "aspect_requiring_provider(name='a', foo=['//external:b'])",
211 "honest(name='b', foo=[])");
212
213 scratch.overwriteFile("WORKSPACE",
Greg Estrenc8a127c2017-02-13 20:21:33 +0000214 new ImmutableList.Builder<String>()
215 .addAll(analysisMock.getWorkspaceContents(mockToolsConfig))
216 .add("bind(name='b', actual='//a:b')")
217 .build());
Lukacs Berki75250e62016-04-12 13:48:24 +0000218
tomluee6a6862018-01-17 14:36:26 -0800219 skyframeExecutor.invalidateFilesUnderPathForTesting(
220 reporter, ModifiedFileSet.EVERYTHING_MODIFIED, Root.fromPath(rootDirectory));
Lukacs Berki75250e62016-04-12 13:48:24 +0000221
222 ConfiguredTarget a = getConfiguredTarget("//a:a");
ulfjackc90b96d2020-01-14 02:46:41 -0800223 assertThat(a.getProvider(RuleInfo.class).getData().toList())
Lukacs Berki75250e62016-04-12 13:48:24 +0000224 .containsExactly("rule //a:a", "aspect //a:b");
225 }
226
227
Ulf Adams89179252015-04-23 18:48:39 +0000228 @Test
229 public void aspectCreatedIfAdvertisedProviderIsPresent() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800230 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.HONEST_RULE,
231 TestAspects.ASPECT_REQUIRING_PROVIDER_RULE);
Ulf Adams89179252015-04-23 18:48:39 +0000232
233 pkg("a",
234 "aspect_requiring_provider(name='a', foo=[':b'])",
235 "honest(name='b', foo=[])");
236
237 ConfiguredTarget a = getConfiguredTarget("//a:a");
ulfjackc90b96d2020-01-14 02:46:41 -0800238 assertThat(a.getProvider(RuleInfo.class).getData().toList())
Ulf Adams89179252015-04-23 18:48:39 +0000239 .containsExactly("rule //a:a", "aspect //a:b");
240 }
241
242 @Test
Rumou Duan6f8393f2016-11-30 16:03:10 +0000243 public void aspectCreatedIfAtLeastOneSetOfAdvertisedProvidersArePresent() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800244 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.HONEST_RULE,
245 TestAspects.HONEST_RULE_2, TestAspects.ASPECT_REQUIRING_PROVIDER_SETS_RULE);
Rumou Duan6f8393f2016-11-30 16:03:10 +0000246
247 pkg("a",
248 "aspect_requiring_provider_sets(name='a', foo=[':b', ':c'])",
249 "honest(name='b', foo=[])",
250 "honest2(name='c', foo=[])");
251
252 ConfiguredTarget a = getConfiguredTarget("//a:a");
ulfjackc90b96d2020-01-14 02:46:41 -0800253 assertThat(a.getProvider(RuleInfo.class).getData().toList())
Rumou Duan6f8393f2016-11-30 16:03:10 +0000254 .containsExactly("rule //a:a", "aspect //a:b", "aspect //a:c");
255 }
256
257 @Test
Dmitry Lomov6231d082015-11-02 17:17:20 +0000258 public void aspectWithParametrizedDefinition() throws Exception {
Dmitry Lomovd1260742016-05-03 18:37:11 +0000259 setRulesAvailableInTests(
gregceb87a41f32017-11-29 07:46:25 -0800260 TestAspects.BASE_RULE,
261 TestAspects.HONEST_RULE,
262 TestAspects.PARAMETERIZED_DEFINITION_ASPECT_RULE);
Dmitry Lomov6231d082015-11-02 17:17:20 +0000263
264 pkg(
265 "a",
266 "honest(name='q', foo=[])",
267 "parametrized_definition_aspect(name='a', foo=[':b'], baz='//a:q')",
268 "honest(name='c', foo=[])",
269 "honest(name='b', foo=[':c'])");
270
271 ConfiguredTarget a = getConfiguredTarget("//a:a");
ulfjackc90b96d2020-01-14 02:46:41 -0800272 assertThat(a.getProvider(TestAspects.RuleInfo.class).getData().toList())
Dmitry Lomov6231d082015-11-02 17:17:20 +0000273 .containsExactly(
274 "rule //a:a",
275 "aspect //a:b data //a:q $dep:[ //a:q]",
276 "aspect //a:c data //a:q $dep:[ //a:q]");
277 }
278
279 @Test
Ulf Adams89179252015-04-23 18:48:39 +0000280 public void aspectInError() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800281 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.ERROR_ASPECT_RULE,
282 TestAspects.SIMPLE_RULE);
Ulf Adams89179252015-04-23 18:48:39 +0000283
284 pkg("a",
285 "simple(name='a', foo=[':b'])",
286 "error_aspect(name='b', foo=[':c'])",
287 "simple(name='c')");
288
289 reporter.removeHandler(failFastHandler);
290 // getConfiguredTarget() uses a separate code path that does not hit
291 // SkyframeBuildView#configureTargets
jcater42edea62019-05-01 08:46:18 -0700292 assertThrows(ViewCreationFailedException.class, () -> update("//a:a"));
Ulf Adams89179252015-04-23 18:48:39 +0000293 assertContainsEvent("Aspect error");
294 }
Marian Lobur2099da02015-05-12 14:42:01 +0000295
296 @Test
Marian Loburfc567b32015-09-14 08:44:25 +0000297 public void transitiveAspectInError() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800298 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.ERROR_ASPECT_RULE,
299 TestAspects.SIMPLE_RULE);
Marian Loburfc567b32015-09-14 08:44:25 +0000300
301 pkg("a",
302 "error_aspect(name='a', foo=[':b'])",
303 "error_aspect(name='b', bar=[':c'])",
304 "error_aspect(name='c', bar=[':d'])",
305 "error_aspect(name='d')");
306
307 reporter.removeHandler(failFastHandler);
308 // getConfiguredTarget() uses a separate code path that does not hit
309 // SkyframeBuildView#configureTargets
jcater42edea62019-05-01 08:46:18 -0700310 assertThrows(ViewCreationFailedException.class, () -> update("//a:a"));
Marian Loburfc567b32015-09-14 08:44:25 +0000311 assertContainsEvent("Aspect error");
312 }
313
314 @Test
Michael Staib2707a882016-09-16 21:06:40 +0000315 public void aspectDependenciesDontShowDeprecationWarnings() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800316 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.EXTRA_ATTRIBUTE_ASPECT_RULE);
Michael Staib2707a882016-09-16 21:06:40 +0000317
318 pkg("extra", "base(name='extra', deprecation='bad aspect')");
319
320 pkg("a",
321 "rule_with_extra_deps_aspect(name='a', foo=[':b'])",
322 "base(name='b')");
323
324 getConfiguredTarget("//a:a");
325 assertContainsEventWithFrequency("bad aspect", 0);
326 }
327
328 @Test
ilist4186fc32020-06-08 07:39:53 -0700329 public void aspectDependsOnPackageGroup() throws Exception {
330 setRulesAvailableInTests(
331 TestAspects.BASE_RULE, TestAspects.PACKAGE_GROUP_ATTRIBUTE_ASPECT_RULE);
332 pkg("extra", "package_group(name='extra')");
333 pkg("a", "rule_with_package_group_deps_aspect(name='a', foo=[':b'])", "base(name='b')");
334
335 getConfiguredTarget("//a:a");
336 assertContainsEventWithFrequency("bad aspect", 0);
337 }
338
339 @Test
ilistd7432e22020-06-04 13:51:45 -0700340 public void aspectWithComputedAttribute() throws Exception {
341 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.COMPUTED_ATTRIBUTE_ASPECT_RULE);
342
343 pkg("a", "rule_with_computed_deps_aspect(name='a', foo=[':b'])", "base(name='b')");
344
345 getConfiguredTarget("//a:a");
346 }
347
348 @Test
Michael Staib2707a882016-09-16 21:06:40 +0000349 public void ruleDependencyDeprecationWarningsAbsentDuringAspectEvaluations() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800350 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.ASPECT_REQUIRING_RULE);
Michael Staib2707a882016-09-16 21:06:40 +0000351
352 pkg("a", "aspect(name='a', foo=['//b:b'])");
353 pkg("b", "aspect(name='b', bar=['//d:d'])");
354 pkg("d", "base(name='d', deprecation='bad rule')");
355
356 getConfiguredTarget("//a:a");
357 assertContainsEventWithFrequency("bad rule", 1);
358 }
359
360 @Test
361 public void aspectWarningsFilteredByOutputFiltersForAssociatedRules() throws Exception {
janakr7a6e0022017-10-12 22:53:47 +0200362 if (getInternalTestExecutionMode() != TestConstants.InternalTestExecutionMode.NORMAL) {
363 // TODO(b/67651960): fix or justify disabling.
364 return;
365 }
gregceb87a41f32017-11-29 07:46:25 -0800366 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.WARNING_ASPECT_RULE);
Michael Staib2707a882016-09-16 21:06:40 +0000367 pkg("a", "warning_aspect(name='a', foo=['//b:b', '//c:c'])");
368 pkg("b", "base(name='b')");
369 pkg("c", "base(name='c')");
370
371 reporter.setOutputFilter(RegexOutputFilter.forPattern(Pattern.compile("^//b:")));
372
373 getConfiguredTarget("//a:a");
374 assertContainsEventWithFrequency("Aspect warning on //b:b", 1);
375 assertContainsEventWithFrequency("Aspect warning on //c:c", 0);
376 }
377
378 @Test
Marian Lobur2099da02015-05-12 14:42:01 +0000379 public void sameTargetInDifferentAttributes() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800380 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.ASPECT_REQUIRING_RULE,
381 TestAspects.SIMPLE_RULE);
Marian Lobur2099da02015-05-12 14:42:01 +0000382 pkg("a",
383 "aspect(name='a', foo=[':b'], bar=[':b'])",
384 "aspect(name='b', foo=[])");
385
386 ConfiguredTarget a = getConfiguredTarget("//a:a");
ulfjackc90b96d2020-01-14 02:46:41 -0800387 assertThat(a.getProvider(RuleInfo.class).getData().toList())
Marian Lobur2099da02015-05-12 14:42:01 +0000388 .containsExactly("aspect //a:b", "rule //a:a");
389 }
Marian Lobur702cad72015-09-02 09:53:58 +0000390
391 @Test
kaipi64e952c2017-05-22 17:12:08 +0200392 public void sameTargetInDifferentAttributesWithDifferentAspects() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800393 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.MULTI_ASPECT_RULE,
394 TestAspects.SIMPLE_RULE);
kaipi64e952c2017-05-22 17:12:08 +0200395 pkg("a",
396 "multi_aspect(name='a', foo=':b', bar=':b')",
397 "simple(name='b')");
398
399 ConfiguredTarget a = getConfiguredTarget("//a:a");
ulfjackc90b96d2020-01-14 02:46:41 -0800400 assertThat(a.getProvider(RuleInfo.class).getData().toList()).containsExactly("foo", "bar");
kaipi64e952c2017-05-22 17:12:08 +0200401 }
402
403 @Test
Marian Lobur702cad72015-09-02 09:53:58 +0000404 public void informationFromBaseRulePassedToAspect() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800405 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.HONEST_RULE,
406 TestAspects.ASPECT_REQUIRING_PROVIDER_RULE);
Marian Lobur702cad72015-09-02 09:53:58 +0000407 pkg("a",
408 "aspect_requiring_provider(name='a', foo=[':b'], baz='hello')",
409 "honest(name='b', foo=[])");
410
411 ConfiguredTarget a = getConfiguredTarget("//a:a");
ulfjackc90b96d2020-01-14 02:46:41 -0800412 assertThat(a.getProvider(RuleInfo.class).getData().toList())
Marian Lobur702cad72015-09-02 09:53:58 +0000413 .containsExactly("rule //a:a", "aspect //a:b data hello");
414 }
Marian Lobur86bd4fd2015-09-16 10:01:38 +0000415
Carmi Grushko06f65f72015-11-02 22:42:24 +0000416 /**
417 * Rule definitions to be used in emptyAspectAttributesAreAvailableInRuleContext().
418 */
419 public static class EmptyAspectAttributesAreAvailableInRuleContext {
janakrcd72f4b2018-02-13 16:25:36 -0800420 public static final MockRule TEST_RULE =
421 () ->
422 MockRule.ancestor(TestAspects.BASE_RULE.getClass())
423 .factory(DummyRuleFactory.class)
424 .define(
425 "testrule",
426 (builder, env) ->
427 builder.add(
428 attr("foo", LABEL_LIST)
429 .legacyAllowAnyFileType()
430 .aspect(AspectWithEmptyLateBoundAttribute.INSTANCE)));
Carmi Grushko06f65f72015-11-02 22:42:24 +0000431
Luis Fernando Pino Duquee82713d2016-04-26 16:22:38 +0000432 public static class AspectWithEmptyLateBoundAttribute extends NativeAspectClass
433 implements ConfiguredAspectFactory {
janakrcd72f4b2018-02-13 16:25:36 -0800434 static final AspectWithEmptyLateBoundAttribute INSTANCE =
435 new AspectWithEmptyLateBoundAttribute();
436
437 private AspectWithEmptyLateBoundAttribute() {}
438
Carmi Grushko06f65f72015-11-02 22:42:24 +0000439 @Override
440 public AspectDefinition getDefinition(AspectParameters params) {
Dmitry Lomovdce01702016-11-28 15:51:32 +0000441 return new AspectDefinition.Builder(this)
mstaib807a9b22017-09-19 17:06:32 +0200442 .add(attr(":late", LABEL).value(LateBoundDefault.alwaysNull()))
443 .build();
Carmi Grushko06f65f72015-11-02 22:42:24 +0000444 }
445
446 @Override
Dmitry Lomovb487ac62015-11-09 13:09:12 +0000447 public ConfiguredAspect create(
dannarke75cfb32019-01-10 14:36:24 -0800448 ConfiguredTargetAndData ctadBase,
449 RuleContext ruleContext,
450 AspectParameters parameters,
451 String toolsRepository)
tomlu39a0a382018-06-22 09:43:23 -0700452 throws InterruptedException, ActionConflictException {
jcaterd6c0dee2020-08-27 15:51:49 -0700453 Object lateBoundPrereq = ruleContext.getPrerequisite(":late");
janakrf15d08d2020-04-22 12:53:03 -0700454 return new ConfiguredAspect.Builder(ruleContext)
Carmi Grushko06f65f72015-11-02 22:42:24 +0000455 .addProvider(
Carmi Grushko261f5bb2015-12-09 19:38:38 +0000456 AspectInfo.class,
Dmitry Lomovb487ac62015-11-09 13:09:12 +0000457 new AspectInfo(
458 NestedSetBuilder.create(
459 Order.STABLE_ORDER, lateBoundPrereq != null ? "non-empty" : "empty")))
Carmi Grushko06f65f72015-11-02 22:42:24 +0000460 .build();
461 }
462 }
463 }
464
465 /**
mstaib807a9b22017-09-19 17:06:32 +0200466 * An Aspect has a late-bound attribute with no value (that is, a LateBoundDefault whose
467 * getDefault() returns `null`). Test that this attribute is available in the RuleContext which is
468 * provided to the Aspect's `create()` method.
Carmi Grushko06f65f72015-11-02 22:42:24 +0000469 */
470 @Test
471 public void emptyAspectAttributesAreAvailableInRuleContext() throws Exception {
janakrcd72f4b2018-02-13 16:25:36 -0800472 setRulesAndAspectsAvailableInTests(
473 ImmutableList.of(
474 TestAspects.SIMPLE_ASPECT,
475 EmptyAspectAttributesAreAvailableInRuleContext.AspectWithEmptyLateBoundAttribute
476 .INSTANCE),
477 ImmutableList.of(
478 TestAspects.BASE_RULE, EmptyAspectAttributesAreAvailableInRuleContext.TEST_RULE));
Carmi Grushko06f65f72015-11-02 22:42:24 +0000479 pkg("a",
480 "testrule(name='a', foo=[':b'])",
481 "testrule(name='b')");
482 ConfiguredTarget a = getConfiguredTarget("//a:a");
ulfjackc90b96d2020-01-14 02:46:41 -0800483 assertThat(a.getProvider(RuleInfo.class).getData().toList()).contains("empty");
Carmi Grushko06f65f72015-11-02 22:42:24 +0000484 }
485
Carmi Grushkoeaaa9d0d2015-11-17 01:54:45 +0000486 /**
487 * Rule definitions to be used in extraActionsAreEmitted().
488 */
489 public static class ExtraActionsAreEmitted {
janakrcd72f4b2018-02-13 16:25:36 -0800490 public static final MockRule TEST_RULE =
491 () ->
492 MockRule.ancestor(TestAspects.BASE_RULE.getClass())
493 .factory(DummyRuleFactory.class)
494 .define(
495 "testrule",
496 (builder, env) ->
497 builder
498 .add(
499 attr("foo", LABEL_LIST)
500 .legacyAllowAnyFileType()
501 .aspect(AspectThatRegistersAction.INSTANCE))
502 .add(
503 attr(":action_listener", LABEL_LIST)
jcaterffb65c82019-03-29 07:52:16 -0700504 .cfg(HostTransition.createFactory())
janakrcd72f4b2018-02-13 16:25:36 -0800505 .value(ACTION_LISTENER)));
Carmi Grushkoeaaa9d0d2015-11-17 01:54:45 +0000506
Luis Fernando Pino Duquee82713d2016-04-26 16:22:38 +0000507 public static class AspectThatRegistersAction extends NativeAspectClass
508 implements ConfiguredAspectFactory {
janakrcd72f4b2018-02-13 16:25:36 -0800509
510 static final AspectThatRegistersAction INSTANCE = new AspectThatRegistersAction();
511
512 private AspectThatRegistersAction() {}
513
Carmi Grushkoeaaa9d0d2015-11-17 01:54:45 +0000514 @Override
515 public AspectDefinition getDefinition(AspectParameters params) {
Dmitry Lomovdce01702016-11-28 15:51:32 +0000516 return new AspectDefinition.Builder(this).build();
Carmi Grushkoeaaa9d0d2015-11-17 01:54:45 +0000517 }
518
519 @Override
520 public ConfiguredAspect create(
dannarke75cfb32019-01-10 14:36:24 -0800521 ConfiguredTargetAndData ctadBase,
522 RuleContext ruleContext,
523 AspectParameters parameters,
524 String toolsRepository)
tomlu39a0a382018-06-22 09:43:23 -0700525 throws InterruptedException, ActionConflictException {
Carmi Grushkoeaaa9d0d2015-11-17 01:54:45 +0000526 ruleContext.registerAction(new NullAction(ruleContext.createOutputArtifact()));
janakrf15d08d2020-04-22 12:53:03 -0700527 return new ConfiguredAspect.Builder(ruleContext).build();
Carmi Grushkoeaaa9d0d2015-11-17 01:54:45 +0000528 }
529 }
530 }
531
532 /**
533 * Test that actions registered in an Aspect are reported as extra-actions on the attached rule.
534 * AspectThatRegistersAction registers a NullAction, whose mnemonic is "Null". We have an
535 * action_listener that targets that mnemonic, which makes sure the Aspect machinery will expose
536 * an ExtraActionArtifactsProvider.
537 * The rule //a:a doesn't have an aspect, so the only action we get is the one on //a:b
538 * (which does have an aspect).
539 */
540 @Test
541 public void extraActionsAreEmitted() throws Exception {
janakrcd72f4b2018-02-13 16:25:36 -0800542 setRulesAndAspectsAvailableInTests(
543 ImmutableList.of(
544 TestAspects.SIMPLE_ASPECT, ExtraActionsAreEmitted.AspectThatRegistersAction.INSTANCE),
545 ImmutableList.of(TestAspects.BASE_RULE, ExtraActionsAreEmitted.TEST_RULE));
Carmi Grushkoeaaa9d0d2015-11-17 01:54:45 +0000546 useConfiguration("--experimental_action_listener=//extra_actions:listener");
547 scratch.file(
548 "extra_actions/BUILD",
549 "extra_action(name='xa', cmd='echo dont-care')",
550 "action_listener(name='listener', mnemonics=['Null'], extra_actions=[':xa'])");
551 pkg("a",
552 "testrule(name='a', foo=[':b'])",
553 "testrule(name='b')");
554 update();
555
556 ConfiguredTarget a = getConfiguredTarget("//a:a");
janakr658d47f2019-05-29 11:11:30 -0700557 NestedSet<Artifact.DerivedArtifact> extraActionArtifacts =
Carmi Grushkobabd4852016-11-18 17:58:09 +0000558 a.getProvider(ExtraActionArtifactsProvider.class).getTransitiveExtraActionArtifacts();
ulfjackc90b96d2020-01-14 02:46:41 -0800559 for (Artifact artifact : extraActionArtifacts.toList()) {
Carmi Grushkobabd4852016-11-18 17:58:09 +0000560 assertThat(artifact.getOwnerLabel()).isEqualTo(Label.create("@//a", "b"));
561 }
Carmi Grushkoeaaa9d0d2015-11-17 01:54:45 +0000562 }
Dmitry Lomovbb5901b2016-09-27 08:49:26 +0000563
564 @Test
565 public void aspectPropagatesToAllAttributes() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800566 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.SIMPLE_RULE,
567 TestAspects.ALL_ATTRIBUTES_ASPECT_RULE);
Dmitry Lomovbb5901b2016-09-27 08:49:26 +0000568 pkg("a",
569 "simple(name='a', foo=[':b'], foo1=':c', txt='some text')",
570 "simple(name='b', foo=[], txt='some text')",
571 "simple(name='c', foo=[], txt='more text')",
572 "all_attributes_aspect(name='x', foo=[':a'])");
573
574 ConfiguredTarget a = getConfiguredTarget("//a:x");
ulfjackc90b96d2020-01-14 02:46:41 -0800575 assertThat(a.getProvider(RuleInfo.class).getData().toList())
576 .containsExactly("aspect //a:a", "aspect //a:b", "aspect //a:c", "rule //a:x");
Dmitry Lomovbb5901b2016-09-27 08:49:26 +0000577 }
578
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000579 /**
580 * Tests that when --experimental_extra_action_top_level_only, Blaze reports extra-actions for
581 * actions registered by Aspects injected by a top-level rule. Because we can't know whether an
582 * aspect was injected by a top-level target or one of its children, we approximate it by only
583 * reporting extra-actions from Aspects that the top-level target could have injected.
584 *
585 * <p>Here, injector1() and injector2() inject aspects into their children. null_rule() just
586 * passes the aspects to its children. The test makes sure that actions registered by aspect1
587 * (injected by injector1()) are reported to the extra-action mechanism. Actions registered by
588 * aspect2 (from injector2) are not reported, because the target under test (//x:a) doesn't inject
589 * aspect2.
590 */
591 @Test
592 public void extraActionsAreEmitted_topLevel() throws Exception {
593 useConfiguration(
594 "--experimental_action_listener=//pkg1:listener",
595 "--experimental_extra_action_top_level_only");
596
597 scratch.file(
598 "x/BUILD",
599 "load(':extension.bzl', 'injector1', 'injector2', 'null_rule')",
600 "injector1(name='a', deps=[':b'])",
601 "null_rule(name='b', deps=[':c'])",
602 "null_rule(name='c', deps=[':d'])",
603 "injector2(name = 'd', extra_deps=[':e'])",
604 "null_rule(name = 'e')");
605
606 scratch.file(
607 "x/extension.bzl",
608 "def _aspect_impl(target, ctx):",
dslomovae0b7742017-06-30 10:07:48 +0200609 " ctx.actions.do_nothing(mnemonic='Mnemonic')",
cparsons0f22a962019-04-18 10:25:37 -0700610 " return []",
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000611 "aspect1 = aspect(_aspect_impl, attr_aspects=['deps'])",
612 "aspect2 = aspect(_aspect_impl, attr_aspects=['extra_deps'])",
613 "def _rule_impl(ctx):",
cparsons0f22a962019-04-18 10:25:37 -0700614 " return []",
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000615 "injector1 = rule(_rule_impl, attrs = { 'deps' : attr.label_list(aspects = [aspect1]) })",
616 "null_rule = rule(_rule_impl, attrs = { 'deps' : attr.label_list() })",
617 "injector2 = rule(",
618 " _rule_impl, attrs = { 'extra_deps' : attr.label_list(aspects = [aspect2]) })");
619
620 scratch.file(
621 "pkg1/BUILD",
622 "extra_action(name='xa', cmd='echo dont-care')",
623 "action_listener(name='listener', mnemonics=['Mnemonic'], extra_actions=[':xa'])");
624
Googler9641a3b2020-09-30 05:28:30 -0700625 // Check: //x:d injects an aspect which produces some extra-action.
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000626 {
ulfjackc23bdac2018-06-13 03:06:16 -0700627 AnalysisResult analysisResult = update("//x:d");
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000628
629 // Get owners of all extra-action artifacts.
630 List<Label> extraArtifactOwners = new ArrayList<>();
jhorvitzcd477f22021-05-05 10:18:22 -0700631 for (Artifact artifact : analysisResult.getArtifactsToBuild()) {
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000632 if (artifact.getRootRelativePathString().endsWith(".xa")) {
633 extraArtifactOwners.add(artifact.getOwnerLabel());
634 }
635 }
636 assertThat(extraArtifactOwners).containsExactly(Label.create("@//x", "e"));
637 }
638
639 // Actual test: //x:a reports actions registered by the aspect it injects.
640 {
ulfjackc23bdac2018-06-13 03:06:16 -0700641 AnalysisResult analysisResult = update("//x:a");
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000642
643 // Get owners of all extra-action artifacts.
644 List<Label> extraArtifactOwners = new ArrayList<>();
jhorvitzcd477f22021-05-05 10:18:22 -0700645 for (Artifact artifact : analysisResult.getArtifactsToBuild()) {
Carmi Grushkodf9e5e12016-11-08 23:07:57 +0000646 if (artifact.getRootRelativePathString().endsWith(".xa")) {
647 extraArtifactOwners.add(artifact.getOwnerLabel());
648 }
649 }
650 assertThat(extraArtifactOwners)
651 .containsExactly(
652 Label.create("@//x", "b"), Label.create("@//x", "c"), Label.create("@//x", "d"));
653 }
654 }
655
Dmitry Lomovbb5901b2016-09-27 08:49:26 +0000656 @Test
Carmi Grushko905a29d2016-12-09 20:42:29 +0000657 public void extraActionsFromDifferentAspectsDontConflict() throws Exception {
658 useConfiguration(
659 "--experimental_action_listener=//pkg1:listener",
660 "--experimental_extra_action_top_level_only");
661
662 scratch.file(
663 "x/BUILD",
664 "load(':extension.bzl', 'injector1', 'injector2', 'null_rule')",
Dmitry Lomov15756522016-12-16 16:52:37 +0000665 "injector2(name='i2_a', deps = [':i1_a'])",
Carmi Grushko905a29d2016-12-09 20:42:29 +0000666 "injector1(name='i1_a', deps=[':n'], param = 'a')",
667 "injector1(name='i1_b', deps=[':n'], param = 'b')",
668 "injector2(name='i2', deps=[':n'])",
669 "null_rule(name = 'n')");
670
671 scratch.file(
672 "x/extension.bzl",
673 "def _aspect_impl(target, ctx):",
dslomovae0b7742017-06-30 10:07:48 +0200674 " ctx.actions.do_nothing(mnemonic='Mnemonic')",
cparsons0f22a962019-04-18 10:25:37 -0700675 " return []",
Carmi Grushko905a29d2016-12-09 20:42:29 +0000676 "aspect1 = aspect(_aspect_impl, attr_aspects=['deps'], attrs =",
677 " {'param': attr.string(values = ['a', 'b'])})",
678 "aspect2 = aspect(_aspect_impl, attr_aspects=['deps'])",
679 "def _rule_impl(ctx):",
cparsons0f22a962019-04-18 10:25:37 -0700680 " return []",
Carmi Grushko905a29d2016-12-09 20:42:29 +0000681 "injector1 = rule(_rule_impl, attrs =",
682 " { 'deps' : attr.label_list(aspects = [aspect1]), 'param' : attr.string() })",
683 "injector2 = rule(_rule_impl, attrs = { 'deps' : attr.label_list(aspects = [aspect2]) })",
cparsons0f22a962019-04-18 10:25:37 -0700684 "null_rule = rule(_rule_impl, attrs = { 'deps' : attr.label_list() })");
Carmi Grushko905a29d2016-12-09 20:42:29 +0000685
686 scratch.file(
687 "pkg1/BUILD",
688 "extra_action(name='xa', cmd='echo dont-care')",
689 "action_listener(name='listener', mnemonics=['Mnemonic'], extra_actions=[':xa'])");
690
Dmitry Lomov15756522016-12-16 16:52:37 +0000691 update("//x:i1_a", "//x:i1_b", "//x:i2", "//x:i2_a");
Carmi Grushko905a29d2016-12-09 20:42:29 +0000692
693 // Implicitly check that update() didn't throw an exception because of two actions producing
694 // the same outputs.
695 }
696
697 @Test
janakre23e9942019-06-11 09:39:16 -0700698 public void sharedArtifactsInAspect() throws Exception {
699 scratch.file(
700 "foo/shared_aspect.bzl",
701 "def _shared_aspect_impl(target, ctx):",
702 " shared_file = ctx.actions.declare_file('shared_file')",
703 " ctx.actions.write(output=shared_file, content='Shared content')",
704 " lib = ctx.rule.attr.lib",
705 " if lib:",
706 " result = depset([shared_file], transitive=[ctx.rule.attr.lib.prov])",
707 " else:",
708 " result = depset([shared_file])",
709 " return struct(prov=result)",
710 "",
711 "shared_aspect = aspect(implementation = _shared_aspect_impl,",
712 " attr_aspects = ['lib'])",
713 "",
714 "def _rule_impl(ctx):",
715 " pass",
716 "",
717 "simple_rule = rule(",
718 " implementation=_rule_impl,",
719 " attrs = {'lib': attr.label(providers = ['prov'],",
720 " aspects=[shared_aspect])})");
721 scratch.file(
722 "foo/BUILD",
723 "load(':shared_aspect.bzl', 'shared_aspect', 'simple_rule')",
724 "",
725 "simple_rule(name = 'top_rule', lib = ':first_dep')",
726 "simple_rule(name = 'first_dep', lib = ':second_dep')",
727 "simple_rule(name = 'second_dep')");
728 // Confirm that load is successful and doesn't crash.
729 update("//foo:top_rule");
730 }
731
732 @Test
Dmitry Lomovbb5901b2016-09-27 08:49:26 +0000733 public void aspectPropagatesToAllAttributesImplicit() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800734 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.SIMPLE_RULE,
735 TestAspects.IMPLICIT_DEP_RULE, TestAspects.ALL_ATTRIBUTES_ASPECT_RULE);
Dmitry Lomovbb5901b2016-09-27 08:49:26 +0000736 scratch.file(
737 "extra/BUILD",
738 "simple(name ='extra')"
739 );
740 pkg("a",
741 "simple(name='a', foo=[':b'], foo1=':c', txt='some text')",
742 "simple(name='b', foo=[], txt='some text')",
743 "implicit_dep(name='c')",
744 "all_attributes_aspect(name='x', foo=[':a'])");
745 update();
746
747 ConfiguredTarget a = getConfiguredTarget("//a:x");
ulfjackc90b96d2020-01-14 02:46:41 -0800748 assertThat(a.getProvider(RuleInfo.class).getData().toList())
Dmitry Lomovbb5901b2016-09-27 08:49:26 +0000749 .containsExactly(
ulfjackc90b96d2020-01-14 02:46:41 -0800750 "aspect //a:a", "aspect //a:b", "aspect //a:c", "aspect //extra:extra", "rule //a:x");
Dmitry Lomovbb5901b2016-09-27 08:49:26 +0000751 }
752
753
754 @Test
755 public void aspectPropagatesToAllAttributesLateBound() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800756 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.SIMPLE_RULE,
757 TestAspects.LATE_BOUND_DEP_RULE, TestAspects.ALL_ATTRIBUTES_ASPECT_RULE);
Dmitry Lomovbb5901b2016-09-27 08:49:26 +0000758
759 scratch.file(
760 "extra/BUILD",
761 "simple(name ='extra')"
762 );
763 pkg("a",
764 "simple(name='a', foo=[':b'], foo1=':c', txt='some text')",
765 "simple(name='b', foo=[], txt='some text')",
766 "late_bound_dep(name='c')",
767 "all_attributes_aspect(name='x', foo=[':a'])");
768 useConfiguration("--plugin=//extra:extra");
769 update();
770
771 ConfiguredTarget a = getConfiguredTarget("//a:x");
ulfjackc90b96d2020-01-14 02:46:41 -0800772 assertThat(a.getProvider(RuleInfo.class).getData().toList())
Dmitry Lomovbb5901b2016-09-27 08:49:26 +0000773 .containsExactly(
ulfjackc90b96d2020-01-14 02:46:41 -0800774 "aspect //a:a", "aspect //a:b", "aspect //a:c", "aspect //extra:extra", "rule //a:x");
Dmitry Lomovbb5901b2016-09-27 08:49:26 +0000775 }
776
Googler909910c2016-11-04 15:50:51 +0000777 /**
778 * Ensures an aspect with attr = '*' doesn't try to propagate to its own implicit attributes.
779 * Doing so leads to a dependency cycle.
780 */
781 @Test
782 public void aspectWithAllAttributesDoesNotPropagateToOwnImplicitAttributes() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800783 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.SIMPLE_RULE,
784 TestAspects.ALL_ATTRIBUTES_WITH_TOOL_ASPECT_RULE);
Googler909910c2016-11-04 15:50:51 +0000785 pkg(
786 "a",
787 "simple(name='tool')",
788 "simple(name='a')",
789 "all_attributes_with_tool_aspect(name='x', foo=[':a'])");
790
791 ConfiguredTarget a = getConfiguredTarget("//a:x");
ulfjackc90b96d2020-01-14 02:46:41 -0800792 assertThat(a.getProvider(RuleInfo.class).getData().toList())
Googler909910c2016-11-04 15:50:51 +0000793 .containsExactly("aspect //a:a", "rule //a:x");
794 }
795
796 /**
797 * Makes sure the aspect *will* propagate to its implicit attributes if there is a "regular"
798 * dependency path to it (i.e. not through its own implicit attributes).
799 */
800 @Test
801 public void aspectWithAllAttributesPropagatesToItsToolIfThereIsPath() throws Exception {
gregceb87a41f32017-11-29 07:46:25 -0800802 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.SIMPLE_RULE,
803 TestAspects.ALL_ATTRIBUTES_WITH_TOOL_ASPECT_RULE);
Googler909910c2016-11-04 15:50:51 +0000804 pkg(
805 "a",
806 "simple(name='tool')",
807 "simple(name='a', foo=[':b'], foo1=':c', txt='some text')",
808 "simple(name='b', foo=[], txt='some text')",
809 "simple(name='c', foo=[':tool'], txt='more text')",
810 "all_attributes_with_tool_aspect(name='x', foo=[':a'])");
811
812 ConfiguredTarget a = getConfiguredTarget("//a:x");
ulfjackc90b96d2020-01-14 02:46:41 -0800813 assertThat(a.getProvider(RuleInfo.class).getData().toList())
Googler909910c2016-11-04 15:50:51 +0000814 .containsExactly(
815 "aspect //a:a", "aspect //a:b", "aspect //a:c", "aspect //a:tool", "rule //a:x");
816 }
Dmitry Lomov65fde002017-02-07 17:24:04 +0000817
818 @Test
819 public void aspectTruthInAdvertisement() throws Exception {
820 reporter.removeHandler(failFastHandler); // expect errors
gregceb87a41f32017-11-29 07:46:25 -0800821 setRulesAvailableInTests(TestAspects.BASE_RULE, TestAspects.SIMPLE_RULE,
822 TestAspects.FALSE_ADVERTISEMENT_ASPECT_RULE);
Dmitry Lomov65fde002017-02-07 17:24:04 +0000823 pkg(
824 "a",
825 "simple(name = 's')",
826 "false_advertisement_aspect(name = 'x', deps = [':s'])"
827 );
828 try {
829 update("//a:x");
830 } catch (ViewCreationFailedException e) {
831 // expected.
832 }
833 assertContainsEvent(
834 "Aspect 'FalseAdvertisementAspect', applied to '//a:s',"
835 + " does not provide advertised provider 'RequiredProvider'");
836 assertContainsEvent(
837 "Aspect 'FalseAdvertisementAspect', applied to '//a:s',"
838 + " does not provide advertised provider 'advertised_provider'");
839 }
dslomov99ea6b42017-04-25 17:46:17 +0200840
841 @Test
dslomovce59d4d2017-08-04 17:32:47 +0200842 public void aspectApplyingToFiles() throws Exception {
dslomov99ea6b42017-04-25 17:46:17 +0200843 AspectApplyingToFiles aspectApplyingToFiles = new AspectApplyingToFiles();
jhorvitzcd477f22021-05-05 10:18:22 -0700844 setRulesAndAspectsAvailableInTests(ImmutableList.of(aspectApplyingToFiles), ImmutableList.of());
dslomov99ea6b42017-04-25 17:46:17 +0200845 pkg(
846 "a",
847 "java_binary(name = 'x', main_class = 'x.FooBar', srcs = ['x.java'])"
848 );
849 AnalysisResult analysisResult = update(new EventBus(), defaultFlags(),
850 ImmutableList.of(aspectApplyingToFiles.getName()),
851 "//a:x_deploy.jar");
janakrf15d08d2020-04-22 12:53:03 -0700852 ConfiguredAspect aspect = Iterables.getOnlyElement(analysisResult.getAspectsMap().values());
dslomov99ea6b42017-04-25 17:46:17 +0200853 AspectApplyingToFiles.Provider provider =
janakrf15d08d2020-04-22 12:53:03 -0700854 aspect.getProvider(AspectApplyingToFiles.Provider.class);
dslomov99ea6b42017-04-25 17:46:17 +0200855 assertThat(provider.getLabel())
856 .isEqualTo(Label.parseAbsoluteUnchecked("//a:x_deploy.jar"));
857 }
dslomovce59d4d2017-08-04 17:32:47 +0200858
859 @Test
860 public void aspectApplyingToSourceFilesIgnored() throws Exception {
861 AspectApplyingToFiles aspectApplyingToFiles = new AspectApplyingToFiles();
jhorvitzcd477f22021-05-05 10:18:22 -0700862 setRulesAndAspectsAvailableInTests(ImmutableList.of(aspectApplyingToFiles), ImmutableList.of());
dslomovce59d4d2017-08-04 17:32:47 +0200863 pkg(
864 "a",
865 "java_binary(name = 'x', main_class = 'x.FooBar', srcs = ['x.java'])"
866 );
867 scratch.file("a/x.java", "");
868 AnalysisResult analysisResult = update(new EventBus(), defaultFlags(),
869 ImmutableList.of(aspectApplyingToFiles.getName()),
870 "//a:x.java");
janakrf15d08d2020-04-22 12:53:03 -0700871 ConfiguredAspect aspect = Iterables.getOnlyElement(analysisResult.getAspectsMap().values());
872 assertThat(aspect.getProvider(AspectApplyingToFiles.Provider.class)).isNull();
dslomovce59d4d2017-08-04 17:32:47 +0200873 }
874
Googler92044992018-03-14 14:26:30 -0700875 @Test
876 public void duplicateAspectsDeduped() throws Exception {
877 AspectApplyingToFiles aspectApplyingToFiles = new AspectApplyingToFiles();
jhorvitzcd477f22021-05-05 10:18:22 -0700878 setRulesAndAspectsAvailableInTests(ImmutableList.of(aspectApplyingToFiles), ImmutableList.of());
Googler92044992018-03-14 14:26:30 -0700879 pkg("a", "java_binary(name = 'x', main_class = 'x.FooBar', srcs = ['x.java'])");
880 AnalysisResult analysisResult =
881 update(
882 new EventBus(),
883 defaultFlags(),
884 ImmutableList.of(aspectApplyingToFiles.getName(), aspectApplyingToFiles.getName()),
885 "//a:x_deploy.jar");
janakrf15d08d2020-04-22 12:53:03 -0700886 ConfiguredAspect aspect = Iterables.getOnlyElement(analysisResult.getAspectsMap().values());
Googler92044992018-03-14 14:26:30 -0700887 AspectApplyingToFiles.Provider provider =
janakrf15d08d2020-04-22 12:53:03 -0700888 aspect.getProvider(AspectApplyingToFiles.Provider.class);
Googler92044992018-03-14 14:26:30 -0700889 assertThat(provider.getLabel()).isEqualTo(Label.parseAbsoluteUnchecked("//a:x_deploy.jar"));
890 }
lberki89b86e02020-06-26 05:48:52 -0700891
892 @Test
893 public void sameConfiguredAttributeOnAspectAndRule() throws Exception {
894 scratch.file(
895 "a/a.bzl",
896 "def _a_impl(t, ctx):",
897 " return [DefaultInfo()]",
898 "def _r_impl(ctx):",
899 " return [DefaultInfo()]",
900 "a = aspect(",
901 " implementation = _a_impl,",
902 " attrs = {'_f': attr.label(",
903 " default = configuration_field(",
904 " fragment = 'cpp', name = 'cc_toolchain'))})",
905 "r = rule(",
906 " implementation = _r_impl,",
907 " attrs = {'_f': attr.label(",
908 " default = configuration_field(",
909 " fragment = 'cpp', name = 'cc_toolchain')),",
910 " 'dep': attr.label(aspects=[a])})");
911
912 scratch.file("a/BUILD", "load(':a.bzl', 'r')", "r(name='r')");
913
914 setRulesAndAspectsAvailableInTests(ImmutableList.of(), ImmutableList.of());
915 getConfiguredTarget("//a:r");
916 }
janakr6bbad592021-02-17 09:00:38 -0800917
918 @Test
919 public void topLevelConflictDetected() throws Exception {
920 String bzlFileTemplate =
921 String.join(
922 "\n",
923 "def _aspect1_impl(target, ctx):",
924 " outfile = ctx.actions.declare_file('aspect.out')",
925 " ctx.actions.run_shell(",
926 " outputs = [outfile],",
927 " progress_message = 'Action for aspect 1',",
928 " command = 'echo \"1\" > ' + outfile.path,",
929 " )",
930 " return [OutputGroupInfo(files = [outfile])]",
931 "def _aspect2_impl(target, ctx):",
932 " outfile = ctx.actions.declare_file('aspect.out')",
933 " ctx.actions.run_shell(",
934 " outputs = [outfile],",
935 " progress_message = 'Action for aspect 2',",
936 " command = 'echo \"%s\" > ' + outfile.path,",
937 " )",
938 " return [OutputGroupInfo(files = [outfile])]",
939 "aspect1 = aspect(implementation = _aspect1_impl)",
940 "aspect2 = aspect(implementation = _aspect2_impl)");
941 scratch.file("foo/aspect.bzl", String.format(bzlFileTemplate, "2"));
942 scratch.file("foo/BUILD", "sh_library(name = 'foo', srcs = ['foo.sh'])");
943 // Expect errors.
944 reporter.removeHandler(failFastHandler);
945 ViewCreationFailedException exception =
946 assertThrows(
947 ViewCreationFailedException.class,
948 () ->
949 update(
950 new EventBus(),
951 defaultFlags(),
952 ImmutableList.of("//foo:aspect.bzl%aspect1", "//foo:aspect.bzl%aspect2"),
953 "//foo:foo"));
954 assertThat(exception)
955 .hasMessageThat()
lberkifa9aabe2021-02-26 10:52:39 +0100956 .containsMatch(
957 "ConflictException: for foo/aspect.out, previous action: action 'Action for aspect .',"
958 + " attempted action: action 'Action for aspect .'");
janakr6bbad592021-02-17 09:00:38 -0800959
960 // Fix bzl file so actions are shared: analysis should succeed now.
961 scratch.overwriteFile("foo/aspect.bzl", String.format(bzlFileTemplate, "1"));
962 reporter.addHandler(failFastHandler);
963 AnalysisResult result =
964 update(
965 new EventBus(),
966 defaultFlags(),
967 ImmutableList.of("//foo:aspect.bzl%aspect1", "//foo:aspect.bzl%aspect2"),
968 "//foo:foo");
969 assertThat(result.getAspectsMap()).hasSize(2);
970
971 // Break bzl file again: we should notice.
972 scratch.overwriteFile("foo/aspect.bzl", String.format(bzlFileTemplate, "2"));
973 // Expect errors.
974 reporter.removeHandler(failFastHandler);
975 exception =
976 assertThrows(
977 ViewCreationFailedException.class,
978 () ->
979 update(
980 new EventBus(),
981 defaultFlags(),
982 ImmutableList.of("//foo:aspect.bzl%aspect1", "//foo:aspect.bzl%aspect2"),
983 "//foo:foo"));
984 assertThat(exception)
985 .hasMessageThat()
mschaller42a2de002021-03-04 07:43:44 -0800986 .containsMatch(
987 "ConflictException: for foo/aspect.out, previous action: action 'Action for aspect .',"
988 + " attempted action: action 'Action for aspect .'");
janakr6bbad592021-02-17 09:00:38 -0800989 }
Ulf Adams89179252015-04-23 18:48:39 +0000990}