blob: 0ae750d72d7c8877e6e14d270bcf3da80dcf70f7 [file] [log] [blame]
Lukacs Berki14328eb2015-10-21 10:47:26 +00001// Copyright 2010 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
lberkiaea56b32017-05-30 12:35:33 +020016import static com.google.common.truth.Truth.assertThat;
Florian Weikertfd735f32015-11-27 17:32:23 +000017import static org.junit.Assert.fail;
18
Ulf Adams3b2ac8e2015-04-23 19:09:50 +000019import com.google.common.collect.ImmutableList;
20import com.google.common.collect.ImmutableMap;
21import com.google.devtools.build.lib.actions.Artifact;
Florian Weikertcca703a2015-12-07 09:56:38 +000022import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
Lukacs Berki6e91eb92015-09-21 09:12:37 +000023import com.google.devtools.build.lib.cmdline.Label;
Lukacs Berkia6434362015-09-15 13:56:14 +000024import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
Ulf Adams3b2ac8e2015-04-23 19:09:50 +000025import com.google.devtools.build.lib.testutil.Suite;
26import com.google.devtools.build.lib.testutil.TestSpec;
27import com.google.devtools.build.lib.vfs.PathFragment;
lberkiaea56b32017-05-30 12:35:33 +020028import java.util.Map;
Florian Weikertfd735f32015-11-27 17:32:23 +000029import org.junit.Test;
30import org.junit.runner.RunWith;
31import org.junit.runners.JUnit4;
32
lberkiaea56b32017-05-30 12:35:33 +020033/** Tests for {@link LabelExpander}. */
Ulf Adams3b2ac8e2015-04-23 19:09:50 +000034@TestSpec(size = Suite.SMALL_TESTS)
Florian Weikertfd735f32015-11-27 17:32:23 +000035@RunWith(JUnit4.class)
Florian Weikertcca703a2015-12-07 09:56:38 +000036public class LabelExpanderTest extends BuildViewTestCase {
Ulf Adams3b2ac8e2015-04-23 19:09:50 +000037 /**
38 * A dummy target that resolves labels and receives errors.
39 */
40 private ConfiguredTarget dummyTarget;
41
42 /**
43 * Artifacts generated by {@code dummyTarget} identified by their
44 * root-relative paths; to be used for mock label-to-artifact mappings.
45 */
46 private Map<String, Artifact> artifactsByName;
47
48 /**
49 * All characters that the heuristic considers to be part of a target.
50 * This is a subset of the allowed label characters. The ones left out may
51 * have a special meaning during expression expansion:
52 *
53 * <ul>
54 * <li>comma (",") - may separate labels
55 * <li>equals sign ("=") - may separate labels
56 * <li>colon (":") - can only appear in labels, not in target names
57 * </ul>
58 */
59 private static final String allowedChars = "_/.-+" + PathFragment.SEPARATOR_CHAR
60 + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
61
62 // Helper methods -----------------------------------------------------------
63
64 private void setupDummy() throws Exception {
65 dummyTarget = scratchConfiguredTarget(
66 "foo", "foo",
67 "filegroup(name = 'foo',",
68 " srcs = ['x1','x2','bar/x3', '" + allowedChars + "', 'xx11', 'x11', 'xx1'])");
69 collectArtifacts();
70 }
71
72 /**
73 * Collects all generated mock artifacts for {@code dummyTarget} and assigns
74 * the result to {@code artifactsByName}.
75 */
76 private void collectArtifacts() {
77 ImmutableMap.Builder<String, Artifact> builder = ImmutableMap.builder();
78 for (Artifact artifact : getFilesToBuild(dummyTarget)) {
79 builder.put(artifact.getRootRelativePath().toString(), artifact);
80 }
81 artifactsByName = builder.build();
82 }
83
84 /**
85 * Gets a generated artifact object for a target in package "foo" from {@code
86 * artifactsByName}.
87 */
88 private Artifact artifactFor(String targetName) {
89 return artifactsByName.get("foo/" + targetName);
90 }
91
92 /**
93 * Creates fake label in package "foo".
94 */
Lukacs Berkia6434362015-09-15 13:56:14 +000095 private static Label labelFor(String targetName) throws LabelSyntaxException {
Brian Silvermand7d6d622016-03-17 09:53:39 +000096 return Label.create("@//foo", targetName);
Ulf Adams3b2ac8e2015-04-23 19:09:50 +000097 }
98
99 /**
100 * Asserts that an expansion with a given mapping produces the expected
101 * results.
102 */
103 private void assertExpansion(String expectedResult, String expressionToExpand,
104 Map<Label, Iterable<Artifact>> mapping) throws Exception {
lberkiaea56b32017-05-30 12:35:33 +0200105 assertThat(LabelExpander.expand(expressionToExpand, mapping, dummyTarget.getLabel()))
106 .isEqualTo(expectedResult);
Ulf Adams3b2ac8e2015-04-23 19:09:50 +0000107 }
108
109 /**
110 * Asserts that an expansion with an empty mapping produces the expected
111 * results.
112 */
113 private void assertExpansion(String expected, String original) throws Exception {
114 assertExpansion(expected, original, ImmutableMap.<Label, Iterable<Artifact>>of());
115 }
116
117 // Actual tests -------------------------------------------------------------
118
119 /**
120 * Tests that if no mapping is specified, then strings expand to themselves.
121 */
Florian Weikertfd735f32015-11-27 17:32:23 +0000122 @Test
Ulf Adams3b2ac8e2015-04-23 19:09:50 +0000123 public void testStringExpandsToItselfWhenNoMappingSpecified() throws Exception {
124 setupDummy();
125 assertExpansion("", null);
126 assertExpansion("cmd", "cmd");
127 assertExpansion("//x:y,:z,w", "//x:y,:z,w");
128 assertExpansion(allowedChars, allowedChars);
129 }
130
131 /**
132 * Tests that in case of a one-to-one label-to-artifact mapping the expansion
133 * produces the expected results.
134 */
Florian Weikertfd735f32015-11-27 17:32:23 +0000135 @Test
Ulf Adams3b2ac8e2015-04-23 19:09:50 +0000136 public void testExpansion() throws Exception {
137 setupDummy();
138 assertExpansion("foo/x1", "x1", ImmutableMap.<Label, Iterable<Artifact>>of(
139 labelFor("x1"), ImmutableList.of(artifactFor("x1"))));
140
141 assertExpansion("foo/x1", ":x1", ImmutableMap.<Label, Iterable<Artifact>>of(
142 labelFor("x1"), ImmutableList.of(artifactFor("x1"))));
143
144 assertExpansion("foo/x1", "//foo:x1", ImmutableMap.<Label, Iterable<Artifact>>of(
145 labelFor("x1"), ImmutableList.of(artifactFor("x1"))));
146 }
147
148 /**
149 * Tests that label extraction works as expected - disallowed label characters
150 * are resolved to themselves.
151 */
Florian Weikertfd735f32015-11-27 17:32:23 +0000152 @Test
Ulf Adams3b2ac8e2015-04-23 19:09:50 +0000153 public void testLabelExtraction() throws Exception {
154 setupDummy();
155 assertExpansion("(foo/" + allowedChars + ")", "(//foo:" + allowedChars + ")",
156 ImmutableMap.<Label, Iterable<Artifact>>of(
157 labelFor(allowedChars), ImmutableList.of(artifactFor(allowedChars))));
158
159 assertExpansion("foo/x1,foo/x2=foo/bar/x3", "x1,x2=bar/x3",
160 ImmutableMap.<Label, Iterable<Artifact>>of(
161 labelFor("x1"), ImmutableList.of(artifactFor("x1")),
162 labelFor("x2"), ImmutableList.of(artifactFor("x2")),
163 labelFor("bar/x3"), ImmutableList.of(artifactFor("bar/x3"))));
164 }
165
166 /**
167 * Tests that an exception is thrown when the mapping is not one-to-one.
168 */
Florian Weikertfd735f32015-11-27 17:32:23 +0000169 @Test
Ulf Adams3b2ac8e2015-04-23 19:09:50 +0000170 public void testThrowsWhenMappingIsNotOneToOne() throws Exception {
171 setupDummy();
172 try {
173 LabelExpander.expand("x1", ImmutableMap.<Label, Iterable<Artifact>>of(
174 labelFor("x1"), ImmutableList.<Artifact>of()), dummyTarget.getLabel());
175
176 fail("Expected an exception.");
177 } catch (LabelExpander.NotUniqueExpansionException nuee) {
178 // was expected
179 }
180
181 try {
182 LabelExpander.expand("x1", ImmutableMap.<Label, Iterable<Artifact>>of(
183 labelFor("x1"), ImmutableList.of(artifactFor("x1"), artifactFor("x2"))),
184 dummyTarget.getLabel());
185
186 fail("Expected an exception.");
187 } catch (LabelExpander.NotUniqueExpansionException nuee) {
188 // was expected
189 }
190 }
191
192 /**
193 * Tests expanding labels that result in a SyntaxException.
194 */
Florian Weikertfd735f32015-11-27 17:32:23 +0000195 @Test
Ulf Adams3b2ac8e2015-04-23 19:09:50 +0000196 public void testIllFormedLabels() throws Exception {
197 setupDummy();
198 assertExpansion("x1:x2:x3", "x1:x2:x3",
199 ImmutableMap.<Label, Iterable<Artifact>>of(
200 labelFor("x1"), ImmutableList.of(artifactFor("x1")),
201 labelFor("x2"), ImmutableList.of(artifactFor("x2")),
202 labelFor("bar/x3"), ImmutableList.of(artifactFor("bar/x3"))));
203
204 assertExpansion("foo://x1 x1/../x2", "foo://x1 x1/../x2",
205 ImmutableMap.<Label, Iterable<Artifact>>of(
206 labelFor("x1"), ImmutableList.of(artifactFor("x1")),
207 labelFor("x2"), ImmutableList.of(artifactFor("x2")),
208 labelFor("bar/x3"), ImmutableList.of(artifactFor("bar/x3"))));
209
210 assertExpansion("//foo:/x1", "//foo:/x1",
211 ImmutableMap.<Label, Iterable<Artifact>>of(
212 labelFor("x1"), ImmutableList.of(artifactFor("x1"))));
213
214 assertExpansion("//foo:../x1", "//foo:../x1",
215 ImmutableMap.<Label, Iterable<Artifact>>of(
216 labelFor("x1"), ImmutableList.of(artifactFor("x1"))));
217
218 assertExpansion("//foo:x1/../x2", "//foo:x1/../x2",
219 ImmutableMap.<Label, Iterable<Artifact>>of(
220 labelFor("x1"), ImmutableList.of(artifactFor("x1")),
221 labelFor("x2"), ImmutableList.of(artifactFor("x2"))));
222
223 assertExpansion("//foo:x1/./x2", "//foo:x1/./x2",
224 ImmutableMap.<Label, Iterable<Artifact>>of(
225 labelFor("x1"), ImmutableList.of(artifactFor("x1")),
226 labelFor("x2"), ImmutableList.of(artifactFor("x2"))));
227
228 assertExpansion("//foo:x1//x2", "//foo:x1//x2",
229 ImmutableMap.<Label, Iterable<Artifact>>of(
230 labelFor("x1"), ImmutableList.of(artifactFor("x1")),
231 labelFor("x2"), ImmutableList.of(artifactFor("x2"))));
232
233 assertExpansion("//foo:x1/..", "//foo:x1/..",
234 ImmutableMap.<Label, Iterable<Artifact>>of(
235 labelFor("x1"), ImmutableList.of(artifactFor("x1"))));
236
237 assertExpansion("//foo:x1/", "//foo:x1/",
238 ImmutableMap.<Label, Iterable<Artifact>>of(
239 labelFor("x1"), ImmutableList.of(artifactFor("x1"))));
240
241 assertExpansion(":", ":");
242 }
243
244 /**
245 * Tests that label parsing is greedy (always extracting the longest
246 * possible label). This means that if a label is a substring of another
247 * label, it should not be expanded but be treated as part of the longer one.
248 */
Florian Weikertfd735f32015-11-27 17:32:23 +0000249 @Test
Ulf Adams3b2ac8e2015-04-23 19:09:50 +0000250 public void testLabelIsSubstringOfValidLabel() throws Exception {
251 setupDummy();
252 assertExpansion("x3=foo/bar/x3", "x3=bar/x3",
253 ImmutableMap.<Label, Iterable<Artifact>>of(
254 labelFor("bar/x3"), ImmutableList.of(artifactFor("bar/x3"))));
255
256 assertExpansion("foo/x1,foo/x11,foo/xx1,foo/xx11", "x1,x11,xx1,xx11",
257 ImmutableMap.<Label, Iterable<Artifact>>of(
258 labelFor("x1"), ImmutableList.of(artifactFor("x1")),
259 labelFor("x11"), ImmutableList.of(artifactFor("x11")),
260 labelFor("xx1"), ImmutableList.of(artifactFor("xx1")),
261 labelFor("xx11"), ImmutableList.of(artifactFor("xx11"))));
262
263 assertExpansion("//x1", "//x1",
264 ImmutableMap.<Label, Iterable<Artifact>>of(
265 labelFor("x1"), ImmutableList.of(artifactFor("x1"))));
266 }
267}