blob: d45137029de4d87736f8b1875c2a5bcd19e55fd2 [file] [log] [blame]
Han-Wen Nienhuys5afe76c2015-10-16 13:59:03 +00001// Copyright 2015 The Bazel Authors. All Rights Reserved.
Ulf Adams89f012d2015-02-26 13:39:28 +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.
Lukacs Berki6e91eb92015-09-21 09:12:37 +000014package com.google.devtools.build.lib.cmdline;
Ulf Adams89f012d2015-02-26 13:39:28 +000015
Ulf Adams795895a2015-03-06 15:58:35 +000016import static com.google.common.truth.Truth.assertThat;
Ulf Adams89f012d2015-02-26 13:39:28 +000017import static org.junit.Assert.assertEquals;
18import static org.junit.Assert.assertFalse;
Brian Silverman22f287f2016-02-09 12:13:21 +000019import static org.junit.Assert.assertTrue;
Ulf Adams89f012d2015-02-26 13:39:28 +000020import static org.junit.Assert.fail;
21
Ulf Adams89f012d2015-02-26 13:39:28 +000022import com.google.devtools.build.lib.testutil.TestUtils;
23import com.google.devtools.build.lib.vfs.PathFragment;
24
25import org.junit.Test;
26import org.junit.runner.RunWith;
27import org.junit.runners.JUnit4;
28
29import java.util.regex.Pattern;
30
31/**
32 * Tests for {@link Label}.
33 */
34@RunWith(JUnit4.class)
35public class LabelTest {
36
Han-Wen Nienhuys5afe76c2015-10-16 13:59:03 +000037 private static final String BAD_PACKAGE_CHARS = "package names may contain only";
38 private static final String INVALID_TARGET_NAME = "invalid target name";
39 private static final String INVALID_PACKAGE_NAME = "invalid package name";
Ulf Adams89f012d2015-02-26 13:39:28 +000040
41 @Test
42 public void testAbsolute() throws Exception {
43 {
44 Label l = Label.parseAbsolute("//foo/bar:baz");
45 assertEquals("foo/bar", l.getPackageName());
46 assertEquals("baz", l.getName());
47 }
48 {
49 Label l = Label.parseAbsolute("//foo/bar");
50 assertEquals("foo/bar", l.getPackageName());
51 assertEquals("bar", l.getName());
52 }
Kristina Chodorow5284f322015-03-06 19:17:00 +000053 {
54 Label l = Label.parseAbsolute("//:bar");
55 assertEquals("", l.getPackageName());
56 assertEquals("bar", l.getName());
57 }
Ulf Adams89f012d2015-02-26 13:39:28 +000058 }
59
Lukacs Berkia6434362015-09-15 13:56:14 +000060 private static String parseCommandLine(String label, String prefix) throws LabelSyntaxException {
Ulf Adams89f012d2015-02-26 13:39:28 +000061 return Label.parseCommandLineLabel(label, new PathFragment(prefix)).toString();
62 }
63
64 @Test
65 public void testLabelResolution() throws Exception {
66 assertEquals("//absolute:label", parseCommandLine("//absolute:label", ""));
67 assertEquals("//absolute:label", parseCommandLine("//absolute:label", "absolute"));
68 assertEquals("//absolute:label", parseCommandLine(":label", "absolute"));
69 assertEquals("//absolute:label", parseCommandLine("label", "absolute"));
70 assertEquals("//absolute:label", parseCommandLine("absolute:label", ""));
71 assertEquals("//absolute/path:label", parseCommandLine("path:label", "absolute"));
72 assertEquals("//absolute/path:label/path", parseCommandLine("path:label/path", "absolute"));
73 assertEquals("//absolute:label/path", parseCommandLine("label/path", "absolute"));
74 }
75
76 @Test
77 public void testLabelResolutionAbsolutePath() throws Exception {
78 try {
79 parseCommandLine("//absolute:label", "/absolute");
80 fail();
81 } catch (IllegalArgumentException e) {
82 // Expected exception
83 }
84 }
85
86 @Test
87 public void testLabelResolutionBadSyntax() throws Exception {
88 try {
89 parseCommandLine("//absolute:A+bad%syntax", "");
90 fail();
Lukacs Berkia6434362015-09-15 13:56:14 +000091 } catch (LabelSyntaxException e) {
Ulf Adams89f012d2015-02-26 13:39:28 +000092 // Expected exception
93 }
94 }
95
96 @Test
Kristina Chodorowb6fbab72016-01-28 14:38:31 +000097 public void testGetRelativeWithAbsoluteLabel() throws Exception {
98 Label base = Label.parseAbsolute("//foo/bar:baz");
99 Label l = base.getRelative("//p1/p2:target");
100 assertEquals("p1/p2", l.getPackageName());
101 assertEquals("target", l.getName());
102 }
103
104 @Test
105 public void testGetRelativeWithRelativeLabel() throws Exception {
106 Label base = Label.parseAbsolute("//foo/bar:baz");
107 Label l = base.getRelative(":quux");
108 assertEquals("foo/bar", l.getPackageName());
109 assertEquals("quux", l.getName());
110 }
111
112 @Test
113 public void testGetRelativeWithIllegalLabel() throws Exception {
114 Label base = Label.parseAbsolute("//foo/bar:baz");
Ulf Adams89f012d2015-02-26 13:39:28 +0000115 try {
116 base.getRelative("/p1/p2:target");
117 fail();
Lukacs Berkia6434362015-09-15 13:56:14 +0000118 } catch (LabelSyntaxException e) {
Ulf Adams89f012d2015-02-26 13:39:28 +0000119 /* ok */
120 }
121 try {
122 base.getRelative("quux:");
123 fail();
Lukacs Berkia6434362015-09-15 13:56:14 +0000124 } catch (LabelSyntaxException e) {
Ulf Adams89f012d2015-02-26 13:39:28 +0000125 /* ok */
126 }
127 try {
128 base.getRelative(":");
129 fail();
Lukacs Berkia6434362015-09-15 13:56:14 +0000130 } catch (LabelSyntaxException e) {
Ulf Adams89f012d2015-02-26 13:39:28 +0000131 /* ok */
132 }
133 try {
134 base.getRelative("::");
135 fail();
Lukacs Berkia6434362015-09-15 13:56:14 +0000136 } catch (LabelSyntaxException e) {
Ulf Adams89f012d2015-02-26 13:39:28 +0000137 /* ok */
138 }
139 }
140
141 @Test
Kristina Chodorowb6fbab72016-01-28 14:38:31 +0000142 public void testGetRelativeWithDifferentRepo() throws Exception {
143 PackageIdentifier packageId = PackageIdentifier.create("@repo", new PathFragment("foo"));
144 Label base = Label.create(packageId, "bar");
145
146 Label relative = base.getRelative("@remote//x:y");
147
148 assertEquals(RepositoryName.create("@remote"), relative.getPackageIdentifier().getRepository());
149 assertEquals(new PathFragment("x"), relative.getPackageFragment());
150 assertEquals("y", relative.getName());
151 }
152
153 @Test
154 public void testGetRelativeWithRepoLocalAbsoluteLabel() throws Exception {
155 PackageIdentifier packageId = PackageIdentifier.create("@repo", new PathFragment("foo"));
156 Label base = Label.create(packageId, "bar");
157
158 Label relative = base.getRelative("//x:y");
159
160 assertEquals(packageId.getRepository(), relative.getPackageIdentifier().getRepository());
161 assertEquals(new PathFragment("x"), relative.getPackageFragment());
162 assertEquals("y", relative.getName());
163 }
164
165 @Test
166 public void testGetRelativeWithLocalRepoRelativeLabel() throws Exception {
167 PackageIdentifier packageId = PackageIdentifier.create("@repo", new PathFragment("foo"));
168 Label base = Label.create(packageId, "bar");
169
170 Label relative = base.getRelative(":y");
171
172 assertEquals(packageId.getRepository(), relative.getPackageIdentifier().getRepository());
173 assertEquals(new PathFragment("foo"), relative.getPackageFragment());
174 assertEquals("y", relative.getName());
175 }
176
177 @Test
178 public void testGetRelativeWithRepoAndReservedPackage() throws Exception {
179 PackageIdentifier packageId = PackageIdentifier.create("@repo", new PathFragment("foo"));
180 Label base = Label.create(packageId, "bar");
181
182 Label relative = base.getRelative("//conditions:default");
183
Brian Silvermand7d6d622016-03-17 09:53:39 +0000184 PackageIdentifier expected = PackageIdentifier.createInMainRepo("conditions");
Kristina Chodorowb6fbab72016-01-28 14:38:31 +0000185 assertEquals(expected.getRepository(), relative.getPackageIdentifier().getRepository());
186 assertEquals(expected.getPackageFragment(), relative.getPackageFragment());
187 assertEquals("default", relative.getName());
188 }
189
190 @Test
191 public void testGetRelativeWithRemoteRepoToDefaultRepo() throws Exception {
192 PackageIdentifier packageId = PackageIdentifier.create("@repo", new PathFragment("foo"));
193 Label base = Label.create(packageId, "bar");
194
195 Label relative = base.getRelative("@//x:y");
196
197 assertEquals(RepositoryName.create("@"), relative.getPackageIdentifier().getRepository());
198 assertEquals(new PathFragment("x"), relative.getPackageFragment());
199 assertEquals("y", relative.getName());
200 }
201
202 @Test
Brian Silverman22f287f2016-02-09 12:13:21 +0000203 public void testGetRepositoryRelative() throws Exception {
204 Label defaultBase = Label.parseAbsolute("//foo/bar:baz");
205 Label repoBase = Label.parseAbsolute("@repo//foo/bar:baz");
206 Label mainBase = Label.parseAbsolute("@//foo/bar:baz");
207 Label externalTarget = Label.parseAbsolute("//external:target");
208 Label l = defaultBase.resolveRepositoryRelative(externalTarget);
Brian Silvermand7d6d622016-03-17 09:53:39 +0000209 assertTrue(l.getPackageIdentifier().getRepository().isMain());
Brian Silverman22f287f2016-02-09 12:13:21 +0000210 assertEquals("external", l.getPackageName());
211 assertEquals("target", l.getName());
212 assertEquals(l, repoBase.resolveRepositoryRelative(externalTarget));
213 assertEquals(l, mainBase.resolveRepositoryRelative(externalTarget));
214 }
215
216 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000217 public void testFactory() throws Exception {
218 Label l = Label.create("foo/bar", "quux");
219 assertEquals("foo/bar", l.getPackageName());
220 assertEquals("quux", l.getName());
221 }
222
223 @Test
224 public void testIdentities() throws Exception {
225
226 Label l1 = Label.parseAbsolute("//foo/bar:baz");
227 Label l2 = Label.parseAbsolute("//foo/bar:baz");
228 Label l3 = Label.parseAbsolute("//foo/bar:quux");
229
Ulf Adams795895a2015-03-06 15:58:35 +0000230 assertEquals(l1, l1);
231 assertEquals(l1, l2);
232 assertEquals(l2, l1);
233 assertEquals(l1, l2);
Ulf Adams89f012d2015-02-26 13:39:28 +0000234
235 assertFalse(l3.equals(l1));
236 assertFalse(l1.equals(l3));
237
238 assertEquals(l1.hashCode(), l2.hashCode());
239 }
240
241 @Test
242 public void testToString() throws Exception {
243 {
Brian Silvermand7d6d622016-03-17 09:53:39 +0000244 String s = "@//foo/bar:baz";
Ulf Adams89f012d2015-02-26 13:39:28 +0000245 Label l = Label.parseAbsolute(s);
Brian Silvermand7d6d622016-03-17 09:53:39 +0000246 assertEquals("//foo/bar:baz", l.toString());
Ulf Adams89f012d2015-02-26 13:39:28 +0000247 }
248 {
249 Label l = Label.parseAbsolute("//foo/bar");
250 assertEquals("//foo/bar:bar", l.toString());
251 }
252 }
253
254 @Test
255 public void testDotDot() throws Exception {
256 Label.parseAbsolute("//foo/bar:baz..gif");
257 }
258
259 /**
260 * Asserts that creating a label throws a SyntaxException.
261 * @param label the label to create.
262 */
263 private static void assertSyntaxError(String expectedError, String label) {
264 try {
265 Label.parseAbsolute(label);
266 fail("Label '" + label + "' did not contain a syntax error");
Lukacs Berkia6434362015-09-15 13:56:14 +0000267 } catch (LabelSyntaxException e) {
Googler2fa3ccf2015-11-10 14:30:39 +0000268 assertThat(e.getMessage()).containsMatch(Pattern.quote(expectedError));
Ulf Adams89f012d2015-02-26 13:39:28 +0000269 }
270 }
271
272 @Test
273 public void testBadCharacters() throws Exception {
274 assertSyntaxError("package names may contain only",
275 "//foo/bar baz");
276 assertSyntaxError("target names may not contain ':'",
277 "//foo:bar:baz");
278 assertSyntaxError("target names may not contain ':'",
279 "//foo:bar:");
280 assertSyntaxError("target names may not contain ':'",
281 "//foo/bar::");
282 assertSyntaxError("target names may not contain '&'",
283 "//foo:bar&");
284 assertSyntaxError("target names may not contain '$'",
285 "//foo/bar:baz$a");
286 assertSyntaxError("target names may not contain '('",
287 "//foo/bar:baz(foo)");
288 assertSyntaxError("target names may not contain ')'",
289 "//foo/bar:bazfoo)");
Janak Ramakrishnane60d55d2015-12-16 03:34:24 +0000290 // Warning: if these assertions are false, tools that assume that they can safely quote labels
291 // may need to be fixed. Please consult with bazel-dev before loosening these restrictions.
292 assertSyntaxError("target names may not contain '''", "//foo/bar:baz'foo");
293 assertSyntaxError("target names may not contain '\"'", "//foo/bar:baz\"foo");
Ulf Adams89f012d2015-02-26 13:39:28 +0000294 }
295
296 @Test
297 public void testUplevelReferences() throws Exception {
Han-Wen Nienhuys5afe76c2015-10-16 13:59:03 +0000298 assertSyntaxError(INVALID_PACKAGE_NAME, "//foo/bar/..:baz");
299 assertSyntaxError(INVALID_PACKAGE_NAME, "//foo/../baz:baz");
300 assertSyntaxError(INVALID_PACKAGE_NAME, "//../bar/baz:baz");
301 assertSyntaxError(INVALID_PACKAGE_NAME, "//..:foo");
302 assertSyntaxError(INVALID_TARGET_NAME, "//foo:bar/../baz");
303 assertSyntaxError(INVALID_TARGET_NAME, "//foo:../bar/baz");
304 assertSyntaxError(INVALID_TARGET_NAME, "//foo:bar/baz/..");
305 assertSyntaxError(INVALID_TARGET_NAME, "//foo:..");
Ulf Adams89f012d2015-02-26 13:39:28 +0000306 }
307
308 @Test
309 public void testDotAsAPathSegment() throws Exception {
Han-Wen Nienhuys5afe76c2015-10-16 13:59:03 +0000310 assertSyntaxError(INVALID_PACKAGE_NAME, "//foo/bar/.:baz");
311 assertSyntaxError(INVALID_PACKAGE_NAME, "//foo/./baz:baz");
312 assertSyntaxError(INVALID_PACKAGE_NAME, "//./bar/baz:baz");
313 assertSyntaxError(INVALID_TARGET_NAME, "//foo:bar/./baz");
314 assertSyntaxError(INVALID_TARGET_NAME, "//foo:./bar/baz");
Ulf Adams89f012d2015-02-26 13:39:28 +0000315 // TODO(bazel-team): enable when we have removed the "Workaround" in Label
316 // that rewrites broken Labels by removing the trailing '.'
Han-Wen Nienhuys5afe76c2015-10-16 13:59:03 +0000317 //assertSyntaxError(INVALID_PACKAGE_NAME,
Ulf Adams89f012d2015-02-26 13:39:28 +0000318 // "//foo:bar/baz/.");
Han-Wen Nienhuys5afe76c2015-10-16 13:59:03 +0000319 //assertSyntaxError(INVALID_PACKAGE_NAME,
Ulf Adams89f012d2015-02-26 13:39:28 +0000320 // "//foo:.");
321 }
322
323 @Test
324 public void testTrailingDotSegment() throws Exception {
Lukacs Berki6e91eb92015-09-21 09:12:37 +0000325 assertEquals(Label
326 .parseAbsolute("//foo:dir/."), Label
327 .parseAbsolute("//foo:dir"));
Ulf Adams89f012d2015-02-26 13:39:28 +0000328 }
329
330 @Test
331 public void testSomeOtherBadLabels() throws Exception {
332 assertSyntaxError("package names may not end with '/'",
333 "//foo/:bar");
Ulf Adams89f012d2015-02-26 13:39:28 +0000334 assertSyntaxError("package names may not start with '/'", "///p:foo");
335 assertSyntaxError("package names may not contain '//' path separators",
336 "//a//b:foo");
337 }
338
339 @Test
340 public void testSomeGoodLabels() throws Exception {
341 Label.parseAbsolute("//foo:..bar");
342 Label.parseAbsolute("//Foo:..bar");
343 Label.parseAbsolute("//-Foo:..bar");
344 Label.parseAbsolute("//00:..bar");
345 Label.parseAbsolute("//package:foo+bar");
346 Label.parseAbsolute("//package:foo_bar");
347 Label.parseAbsolute("//package:foo=bar");
348 Label.parseAbsolute("//package:foo-bar");
349 Label.parseAbsolute("//package:foo.bar");
350 Label.parseAbsolute("//package:foo@bar");
351 Label.parseAbsolute("//package:foo~bar");
352 }
353
354 /**
355 * Regression test: we previously expanded the set of characters which are considered label chars
356 * to include "@" (see test above). An unexpected side-effect is that "@D" in genrule(cmd) was
357 * considered to be a valid relative label! The fix is to forbid "@x" in package names.
358 */
359 @Test
360 public void testAtVersionIsIllegal() throws Exception {
361 assertSyntaxError(BAD_PACKAGE_CHARS, "//foo/bar@123:baz");
362 }
363
364 @Test
365 public void testDoubleSlashPathSeparator() throws Exception {
366 assertSyntaxError("package names may not contain '//' path separators",
367 "//foo//bar:baz");
368 assertSyntaxError("target names may not contain '//' path separator",
369 "//foo:bar//baz");
370 }
371
372 @Test
373 public void testNonPrintableCharacters() throws Exception {
374 assertSyntaxError(
375 "target names may not contain non-printable characters: '\\x02'",
376 "//foo:..\002bar");
377 }
378
379 /** Make sure that control characters - such as CR - are escaped on output. */
380 @Test
381 public void testInvalidLineEndings() throws Exception {
382 assertSyntaxError("invalid target name '..bar\\r': "
383 + "target names may not end with carriage returns", "//foo:..bar\r");
384 }
385
386 @Test
387 public void testEmptyName() throws Exception {
388 assertSyntaxError("invalid target name '': empty target name", "//foo/bar:");
389 }
390
391 @Test
392 public void testSerializationSimple() throws Exception {
Brian Silvermand7d6d622016-03-17 09:53:39 +0000393 checkSerialization("//a", 93);
Ulf Adams89f012d2015-02-26 13:39:28 +0000394 }
395
396 @Test
397 public void testSerializationNested() throws Exception {
Brian Silvermand7d6d622016-03-17 09:53:39 +0000398 checkSerialization("//foo/bar:baz", 101);
Ulf Adams89f012d2015-02-26 13:39:28 +0000399 }
400
401 @Test
402 public void testSerializationWithoutTargetName() throws Exception {
Brian Silvermand7d6d622016-03-17 09:53:39 +0000403 checkSerialization("//foo/bar", 101);
Ulf Adams89f012d2015-02-26 13:39:28 +0000404 }
405
406 private void checkSerialization(String labelString, int expectedSize) throws Exception {
407 Label a = Label.parseAbsolute(labelString);
408 byte[] sa = TestUtils.serializeObject(a);
409 assertEquals(expectedSize, sa.length);
410
411 Label a2 = (Label) TestUtils.deserializeObject(sa);
412 assertEquals(a, a2);
413 }
414
415 @Test
416 public void testRepoLabel() throws Exception {
Kristina Chodorow0f85e102015-05-22 14:03:02 +0000417 Label label = Label.parseAbsolute("@foo//bar/baz:bat/boo");
Ulf Adams89f012d2015-02-26 13:39:28 +0000418 assertEquals("@foo//bar/baz:bat/boo", label.toString());
419 }
420
421 @Test
422 public void testNoRepo() throws Exception {
Kristina Chodorow0f85e102015-05-22 14:03:02 +0000423 Label label = Label.parseAbsolute("//bar/baz:bat/boo");
Ulf Adams89f012d2015-02-26 13:39:28 +0000424 assertEquals("//bar/baz:bat/boo", label.toString());
425 }
426
427 @Test
428 public void testInvalidRepo() throws Exception {
429 try {
Kristina Chodorow0f85e102015-05-22 14:03:02 +0000430 Label.parseAbsolute("foo//bar/baz:bat/boo");
Ulf Adams89f012d2015-02-26 13:39:28 +0000431 fail();
Lukacs Berkia6434362015-09-15 13:56:14 +0000432 } catch (LabelSyntaxException e) {
Kristina Chodorowe76dd5e2015-09-18 13:45:55 +0000433 assertThat(e).hasMessage(
434 "invalid repository name 'foo': workspace names must start with '@'");
Ulf Adams89f012d2015-02-26 13:39:28 +0000435 }
436 }
Damien Martin-Guillerez7751d432016-01-15 11:22:31 +0000437
438 @Test
439 public void testGetWorkspaceRoot() throws Exception {
440 Label label = Label.parseAbsolute("//bar/baz");
441 assertThat(label.getWorkspaceRoot()).isEmpty();
442 label = Label.parseAbsolute("@repo//bar/baz");
Kristina Chodorowbdfd58a2016-06-16 20:30:57 +0000443 assertThat(label.getWorkspaceRoot()).isEqualTo("../repo");
Damien Martin-Guillerez7751d432016-01-15 11:22:31 +0000444 }
Ulf Adams89f012d2015-02-26 13:39:28 +0000445}