blob: a4d7cb4edfe4f6c9b33c27abf83ff97f4f2dd37b [file] [log] [blame]
Damien Martin-Guillerezf88f4d82015-09-25 13:56:55 +00001// Copyright 2015 The Bazel Authors. All rights reserved.
Ulf Adams3b2ac8e2015-04-23 19:09:50 +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;
Florian Weikertfd735f32015-11-27 17:32:23 +000017import static org.junit.Assert.assertNotNull;
Ulf Adams3b2ac8e2015-04-23 19:09:50 +000018
Lukacs Berki7894c182016-05-10 12:07:01 +000019import com.google.common.collect.ImmutableMap;
Greg Estren373e3e22016-08-09 22:36:51 +000020import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
21import com.google.devtools.build.lib.analysis.config.BuildOptions;
Ulf Adams3b2ac8e2015-04-23 19:09:50 +000022import com.google.devtools.build.lib.analysis.config.ConfigMatchingProvider;
Florian Weikertcca703a2015-12-07 09:56:38 +000023import com.google.devtools.build.lib.analysis.util.AnalysisTestCase;
Ulf Adams3b2ac8e2015-04-23 19:09:50 +000024import com.google.devtools.build.lib.analysis.util.TestAspects;
25import com.google.devtools.build.lib.analysis.util.TestAspects.AspectRequiringRule;
Lukacs Berki6e91eb92015-09-21 09:12:37 +000026import com.google.devtools.build.lib.cmdline.Label;
Ulf Adams2ac20962016-02-01 13:04:54 +000027import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
Dmitry Lomovb487ac62015-11-09 13:09:12 +000028import com.google.devtools.build.lib.packages.Aspect;
Dmitry Lomov15756522016-12-16 16:52:37 +000029import com.google.devtools.build.lib.packages.AspectDescriptor;
Ulf Adams3b2ac8e2015-04-23 19:09:50 +000030import com.google.devtools.build.lib.packages.Attribute;
Dmitry Lomov8ff06452015-10-21 19:16:30 +000031import com.google.devtools.build.lib.packages.NativeAspectClass;
Ulf Adams2ac20962016-02-01 13:04:54 +000032import com.google.devtools.build.lib.packages.NoSuchPackageException;
33import com.google.devtools.build.lib.packages.NoSuchTargetException;
Ulf Adams3b2ac8e2015-04-23 19:09:50 +000034import com.google.devtools.build.lib.packages.NoSuchThingException;
35import com.google.devtools.build.lib.packages.Target;
Greg Estren9e26f0f2016-09-29 01:01:57 +000036import com.google.devtools.build.lib.testutil.Suite;
37import com.google.devtools.build.lib.testutil.TestSpec;
Greg Estrend5353252016-08-11 22:13:31 +000038import com.google.devtools.build.lib.util.OrderedSetMultimap;
Greg Estren373e3e22016-08-09 22:36:51 +000039import java.util.List;
40import java.util.Set;
41import javax.annotation.Nullable;
Ulf Adams3b2ac8e2015-04-23 19:09:50 +000042import org.junit.Before;
43import org.junit.Test;
44import org.junit.runner.RunWith;
45import org.junit.runners.JUnit4;
46
Ulf Adams3b2ac8e2015-04-23 19:09:50 +000047/**
48 * Tests for {@link DependencyResolver}.
49 *
50 * <p>These use custom rules so that all usual and unusual cases related to aspect processing can
51 * be tested.
52 *
53 * <p>It would be nicer is we didn't have a Skyframe executor, if we didn't have that, we'd need a
54 * way to create a configuration, a package manager and a whole lot of other things, so it's just
55 * easier this way.
56 */
57@RunWith(JUnit4.class)
Florian Weikertcca703a2015-12-07 09:56:38 +000058public class DependencyResolverTest extends AnalysisTestCase {
Ulf Adams3b2ac8e2015-04-23 19:09:50 +000059 private DependencyResolver dependencyResolver;
60
Ulf Adams3b2ac8e2015-04-23 19:09:50 +000061 @Before
Florian Weikertfd735f32015-11-27 17:32:23 +000062 public final void createResolver() throws Exception {
Ulf Adams3b2ac8e2015-04-23 19:09:50 +000063 dependencyResolver = new DependencyResolver() {
Dmitry Lomovd83af9e2017-02-23 15:44:23 +000064
Ulf Adams3b2ac8e2015-04-23 19:09:50 +000065 @Override
66 protected void invalidVisibilityReferenceHook(TargetAndConfiguration node, Label label) {
67 throw new IllegalStateException();
68 }
69
70 @Override
71 protected void invalidPackageGroupReferenceHook(TargetAndConfiguration node, Label label) {
72 throw new IllegalStateException();
73 }
74
Ulf Adams84901732016-01-28 15:05:16 +000075 @Override
76 protected void missingEdgeHook(Target from, Label to, NoSuchThingException e) {
77 throw new IllegalStateException(e);
78 }
79
Ulf Adams3b2ac8e2015-04-23 19:09:50 +000080 @Nullable
81 @Override
Ulf Adams2ac20962016-02-01 13:04:54 +000082 protected Target getTarget(Target from, Label label, NestedSetBuilder<Label> rootCauses) {
Ulf Adams3b2ac8e2015-04-23 19:09:50 +000083 try {
84 return packageManager.getTarget(reporter, label);
Ulf Adams2ac20962016-02-01 13:04:54 +000085 } catch (NoSuchPackageException | NoSuchTargetException | InterruptedException e) {
Ulf Adams3b2ac8e2015-04-23 19:09:50 +000086 throw new IllegalStateException(e);
87 }
88 }
Greg Estren373e3e22016-08-09 22:36:51 +000089
90 @Nullable
91 @Override
92 protected List<BuildConfiguration> getConfigurations(
93 Set<Class<? extends BuildConfiguration.Fragment>> fragments,
94 Iterable<BuildOptions> buildOptions) {
95 throw new UnsupportedOperationException(
96 "this functionality is covered by analysis-phase integration tests");
97 }
Ulf Adams3b2ac8e2015-04-23 19:09:50 +000098 };
99 }
100
Ulf Adams3b2ac8e2015-04-23 19:09:50 +0000101 private void pkg(String name, String... contents) throws Exception {
Ulf Adams01f1b462015-04-27 09:52:33 +0000102 scratch.file("" + name + "/BUILD", contents);
Ulf Adams3b2ac8e2015-04-23 19:09:50 +0000103 }
104
Greg Estrend5353252016-08-11 22:13:31 +0000105 private OrderedSetMultimap<Attribute, Dependency> dependentNodeMap(
Luis Fernando Pino Duquee82713d2016-04-26 16:22:38 +0000106 String targetName, NativeAspectClass aspect) throws Exception {
Ulf Adams3b2ac8e2015-04-23 19:09:50 +0000107 Target target = packageManager.getTarget(reporter, Label.parseAbsolute(targetName));
108 return dependencyResolver.dependentNodeMap(
109 new TargetAndConfiguration(target, getTargetConfiguration()),
Greg Estren00049432015-08-25 16:43:47 +0000110 getHostConfiguration(),
Luis Fernando Pino Duquee82713d2016-04-26 16:22:38 +0000111 aspect != null ? Aspect.forNative(aspect) : null,
Lukacs Berki7894c182016-05-10 12:07:01 +0000112 ImmutableMap.<Label, ConfigMatchingProvider>of());
Ulf Adams3b2ac8e2015-04-23 19:09:50 +0000113 }
114
115 @SafeVarargs
Greg Estren9e26f0f2016-09-29 01:01:57 +0000116 private final Dependency assertDep(
Greg Estrend5353252016-08-11 22:13:31 +0000117 OrderedSetMultimap<Attribute, Dependency> dependentNodeMap,
Ulf Adams3b2ac8e2015-04-23 19:09:50 +0000118 String attrName,
119 String dep,
Dmitry Lomove8040172016-04-06 14:53:43 +0000120 AspectDescriptor... aspects) {
Ulf Adams3b2ac8e2015-04-23 19:09:50 +0000121 Attribute attr = null;
122 for (Attribute candidate : dependentNodeMap.keySet()) {
123 if (candidate.getName().equals(attrName)) {
124 attr = candidate;
125 break;
126 }
127 }
128
129 assertNotNull("Attribute '" + attrName + "' not found", attr);
130 Dependency dependency = null;
131 for (Dependency candidate : dependentNodeMap.get(attr)) {
132 if (candidate.getLabel().toString().equals(dep)) {
133 dependency = candidate;
134 break;
135 }
136 }
137
138 assertNotNull("Dependency '" + dep + "' on attribute '" + attrName + "' not found", dependency);
Dmitry Lomove851fe22017-02-14 23:11:23 +0000139 assertThat(dependency.getAspects().getAllAspects()).containsExactly((Object[]) aspects);
Greg Estren9e26f0f2016-09-29 01:01:57 +0000140 return dependency;
Ulf Adams3b2ac8e2015-04-23 19:09:50 +0000141 }
142
143 @Test
144 public void hasAspectsRequiredByRule() throws Exception {
Dmitry Lomovd1260742016-05-03 18:37:11 +0000145 setRulesAvailableInTests(new AspectRequiringRule(), new TestAspects.BaseRule());
Ulf Adams3b2ac8e2015-04-23 19:09:50 +0000146 pkg("a",
147 "aspect(name='a', foo=[':b'])",
148 "aspect(name='b', foo=[])");
Greg Estrend5353252016-08-11 22:13:31 +0000149 OrderedSetMultimap<Attribute, Dependency> map = dependentNodeMap("//a:a", null);
Dmitry Lomov8ff06452015-10-21 19:16:30 +0000150 assertDep(
Dmitry Lomove8040172016-04-06 14:53:43 +0000151 map, "foo", "//a:b",
Luis Fernando Pino Duquee82713d2016-04-26 16:22:38 +0000152 new AspectDescriptor(TestAspects.SIMPLE_ASPECT));
Ulf Adams3b2ac8e2015-04-23 19:09:50 +0000153 }
154
155 @Test
156 public void hasAspectsRequiredByAspect() throws Exception {
Dmitry Lomovd1260742016-05-03 18:37:11 +0000157 setRulesAvailableInTests(new TestAspects.BaseRule(), new TestAspects.SimpleRule());
Ulf Adams3b2ac8e2015-04-23 19:09:50 +0000158 pkg("a",
159 "simple(name='a', foo=[':b'])",
160 "simple(name='b', foo=[])");
Greg Estrend5353252016-08-11 22:13:31 +0000161 OrderedSetMultimap<Attribute, Dependency> map =
Luis Fernando Pino Duquee82713d2016-04-26 16:22:38 +0000162 dependentNodeMap("//a:a", TestAspects.ATTRIBUTE_ASPECT);
Dmitry Lomov8ff06452015-10-21 19:16:30 +0000163 assertDep(
Dmitry Lomove8040172016-04-06 14:53:43 +0000164 map, "foo", "//a:b",
Luis Fernando Pino Duquee82713d2016-04-26 16:22:38 +0000165 new AspectDescriptor(TestAspects.ATTRIBUTE_ASPECT));
Ulf Adams3b2ac8e2015-04-23 19:09:50 +0000166 }
167
168 @Test
Dmitry Lomovbb5901b2016-09-27 08:49:26 +0000169 public void hasAllAttributesAspect() throws Exception {
170 setRulesAvailableInTests(new TestAspects.BaseRule(), new TestAspects.SimpleRule());
171 pkg("a",
172 "simple(name='a', foo=[':b'])",
173 "simple(name='b', foo=[])");
174 OrderedSetMultimap<Attribute, Dependency> map =
175 dependentNodeMap("//a:a", TestAspects.ALL_ATTRIBUTES_ASPECT);
176 assertDep(
177 map, "foo", "//a:b",
178 new AspectDescriptor(TestAspects.ALL_ATTRIBUTES_ASPECT));
179 }
180
181 @Test
Ulf Adams3b2ac8e2015-04-23 19:09:50 +0000182 public void hasAspectDependencies() throws Exception {
Dmitry Lomovd1260742016-05-03 18:37:11 +0000183 setRulesAvailableInTests(new TestAspects.BaseRule());
Ulf Adams3b2ac8e2015-04-23 19:09:50 +0000184 pkg("a", "base(name='a')");
185 pkg("extra", "base(name='extra')");
Greg Estrend5353252016-08-11 22:13:31 +0000186 OrderedSetMultimap<Attribute, Dependency> map =
Luis Fernando Pino Duquee82713d2016-04-26 16:22:38 +0000187 dependentNodeMap("//a:a", TestAspects.EXTRA_ATTRIBUTE_ASPECT);
Ulf Adams3b2ac8e2015-04-23 19:09:50 +0000188 assertDep(map, "$dep", "//extra:extra");
189 }
Greg Estren9e26f0f2016-09-29 01:01:57 +0000190
191 /**
192 * Null configurations should be static whether we're building with static or dynamic
193 * configurations. This is because the dynamic config logic that translates transitions into
194 * final configurations can be trivially skipped in those cases.
195 */
196 @Test
197 public void nullConfigurationsAlwaysStatic() throws Exception {
198 pkg("a",
199 "genrule(name = 'gen', srcs = ['gen.in'], cmd = '', outs = ['gen.out'])");
200 update();
201 Dependency dep = assertDep(dependentNodeMap("//a:gen", null), "srcs", "//a:gen.in");
202 assertThat(dep.hasStaticConfiguration()).isTrue();
203 assertThat(dep.getConfiguration()).isNull();
204 }
205
206 /** Runs the same test with trimmed dynamic configurations. */
207 @TestSpec(size = Suite.SMALL_TESTS)
208 @RunWith(JUnit4.class)
209 public static class WithDynamicConfigurations extends DependencyResolverTest {
210 @Override
211 protected FlagBuilder defaultFlags() {
212 return super.defaultFlags().with(Flag.DYNAMIC_CONFIGURATIONS);
213 }
214 }
215
216 /** Runs the same test with untrimmed dynamic configurations. */
217 @TestSpec(size = Suite.SMALL_TESTS)
218 @RunWith(JUnit4.class)
219 public static class WithDynamicConfigurationsNoTrim extends DependencyResolverTest {
220 @Override
221 protected FlagBuilder defaultFlags() {
222 return super.defaultFlags().with(Flag.DYNAMIC_CONFIGURATIONS_NOTRIM);
223 }
224 }
Ulf Adams3b2ac8e2015-04-23 19:09:50 +0000225}