| // Copyright 2015 The Bazel Authors. All Rights Reserved. | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| package com.google.devtools.build.lib.cmdline; | |
| import static com.google.common.truth.Truth.assertThat; | |
| import static com.google.devtools.build.lib.testutil.MoreAsserts.assertThrows; | |
| import com.google.common.collect.ImmutableMap; | |
| import com.google.common.testing.EqualsTester; | |
| import com.google.devtools.build.lib.testutil.TestUtils; | |
| import com.google.devtools.build.lib.vfs.PathFragment; | |
| import java.util.regex.Pattern; | |
| import org.junit.Test; | |
| import org.junit.runner.RunWith; | |
| import org.junit.runners.JUnit4; | |
| /** | |
| * Tests for {@link Label}. | |
| */ | |
| @RunWith(JUnit4.class) | |
| public class LabelTest { | |
| private static final String INVALID_TARGET_NAME = "invalid target name"; | |
| private static final String INVALID_PACKAGE_NAME = "invalid package name"; | |
| @Test | |
| public void testAbsolute() throws Exception { | |
| { | |
| Label l = Label.parseAbsolute("//foo/bar:baz", ImmutableMap.of()); | |
| assertThat(l.getPackageName()).isEqualTo("foo/bar"); | |
| assertThat(l.getName()).isEqualTo("baz"); | |
| } | |
| { | |
| Label l = Label.parseAbsolute("//foo/bar", ImmutableMap.of()); | |
| assertThat(l.getPackageName()).isEqualTo("foo/bar"); | |
| assertThat(l.getName()).isEqualTo("bar"); | |
| } | |
| { | |
| Label l = Label.parseAbsolute("//:bar", ImmutableMap.of()); | |
| assertThat(l.getPackageName()).isEmpty(); | |
| assertThat(l.getName()).isEqualTo("bar"); | |
| } | |
| { | |
| Label l = Label.parseAbsolute("@foo", ImmutableMap.of()); | |
| assertThat(l.getPackageIdentifier().getRepository().getName()).isEqualTo("@foo"); | |
| assertThat(l.getPackageName()).isEmpty(); | |
| assertThat(l.getName()).isEqualTo("foo"); | |
| } | |
| { | |
| Label l = Label.parseAbsolute("//@foo", ImmutableMap.of()); | |
| assertThat(l.getPackageIdentifier().getRepository().getName()).isEqualTo("@"); | |
| assertThat(l.getPackageName()).isEqualTo("@foo"); | |
| assertThat(l.getName()).isEqualTo("@foo"); | |
| } | |
| { | |
| Label l = Label.parseAbsolute("//xyz/@foo:abc", ImmutableMap.of()); | |
| assertThat(l.getPackageIdentifier().getRepository().getName()).isEqualTo("@"); | |
| assertThat(l.getPackageName()).isEqualTo("xyz/@foo"); | |
| assertThat(l.getName()).isEqualTo("abc"); | |
| } | |
| } | |
| private static String parseCommandLine(String label, String prefix) throws LabelSyntaxException { | |
| return Label.parseCommandLineLabel(label, PathFragment.create(prefix)).toString(); | |
| } | |
| @Test | |
| public void testLabelResolution() throws Exception { | |
| assertThat(parseCommandLine("//absolute:label", "")).isEqualTo("//absolute:label"); | |
| assertThat(parseCommandLine("//absolute:label", "absolute")).isEqualTo("//absolute:label"); | |
| assertThat(parseCommandLine(":label", "absolute")).isEqualTo("//absolute:label"); | |
| assertThat(parseCommandLine("label", "absolute")).isEqualTo("//absolute:label"); | |
| assertThat(parseCommandLine("absolute:label", "")).isEqualTo("//absolute:label"); | |
| assertThat(parseCommandLine("path:label", "absolute")).isEqualTo("//absolute/path:label"); | |
| assertThat(parseCommandLine("path:label/path", "absolute")) | |
| .isEqualTo("//absolute/path:label/path"); | |
| assertThat(parseCommandLine("label/path", "absolute")).isEqualTo("//absolute:label/path"); | |
| } | |
| @Test | |
| public void testLabelResolutionAbsolutePath() throws Exception { | |
| assertThrows( | |
| IllegalArgumentException.class, () -> parseCommandLine("//absolute:label", "/absolute")); | |
| } | |
| @Test | |
| public void testLabelResolutionBadSyntax() throws Exception { | |
| assertThrows(LabelSyntaxException.class, () -> parseCommandLine("//absolute:A+bad:syntax", "")); | |
| } | |
| @Test | |
| public void testGetRelativeWithAbsoluteLabel() throws Exception { | |
| Label base = Label.parseAbsolute("//foo/bar:baz", ImmutableMap.of()); | |
| Label l = base.getRelativeWithRemapping("//p1/p2:target", ImmutableMap.of()); | |
| assertThat(l.getPackageName()).isEqualTo("p1/p2"); | |
| assertThat(l.getName()).isEqualTo("target"); | |
| } | |
| @Test | |
| public void testGetRelativeWithRelativeLabel() throws Exception { | |
| Label base = Label.parseAbsolute("//foo/bar:baz", ImmutableMap.of()); | |
| Label l = base.getRelativeWithRemapping(":quux", ImmutableMap.of()); | |
| assertThat(l.getPackageName()).isEqualTo("foo/bar"); | |
| assertThat(l.getName()).isEqualTo("quux"); | |
| } | |
| @Test | |
| public void testGetRelativeWithIllegalLabel() throws Exception { | |
| Label base = Label.parseAbsolute("//foo/bar:baz", ImmutableMap.of()); | |
| assertThrows( | |
| LabelSyntaxException.class, | |
| () -> base.getRelativeWithRemapping("/p1/p2:target", ImmutableMap.of())); | |
| assertThrows( | |
| LabelSyntaxException.class, | |
| () -> base.getRelativeWithRemapping("quux:", ImmutableMap.of())); | |
| assertThrows( | |
| LabelSyntaxException.class, () -> base.getRelativeWithRemapping(":", ImmutableMap.of())); | |
| assertThrows( | |
| LabelSyntaxException.class, () -> base.getRelativeWithRemapping("::", ImmutableMap.of())); | |
| } | |
| @Test | |
| public void testGetRelativeWithDifferentRepo() throws Exception { | |
| PackageIdentifier packageId = PackageIdentifier.create("@repo", PathFragment.create("foo")); | |
| Label base = Label.create(packageId, "bar"); | |
| Label relative = base.getRelativeWithRemapping("@remote//x:y", ImmutableMap.of()); | |
| assertThat(relative.getPackageIdentifier().getRepository()) | |
| .isEqualTo(RepositoryName.create("@remote")); | |
| assertThat(relative.getPackageFragment()).isEqualTo(PathFragment.create("x")); | |
| assertThat(relative.getName()).isEqualTo("y"); | |
| } | |
| @Test | |
| public void testGetRelativeWithoutRemappingBaseLabel() throws Exception { | |
| PackageIdentifier packageId = PackageIdentifier.create("@a", PathFragment.create("foo")); | |
| Label base = Label.create(packageId, "bar"); | |
| ImmutableMap<RepositoryName, RepositoryName> repoMapping = | |
| ImmutableMap.of(RepositoryName.create("@a"), RepositoryName.create("@b")); | |
| Label relative = base.getRelativeWithRemapping(":y", repoMapping); | |
| // getRelative should only remap repositories passed in the string arg and not | |
| // make changes to existing Labels | |
| Label actual = Label.parseAbsoluteUnchecked("@a//foo:y"); | |
| assertThat(relative).isEqualTo(actual); | |
| } | |
| @Test | |
| public void testGetRelativeWithDifferentRepoAndRemapping() throws Exception { | |
| PackageIdentifier packageId = PackageIdentifier.create("@repo", PathFragment.create("foo")); | |
| Label base = Label.create(packageId, "bar"); | |
| ImmutableMap<RepositoryName, RepositoryName> repoMapping = | |
| ImmutableMap.of(RepositoryName.create("@a"), RepositoryName.create("@b")); | |
| Label relative = base.getRelativeWithRemapping("@a//x:y", repoMapping); | |
| Label actual = Label.parseAbsoluteUnchecked("@b//x:y"); | |
| assertThat(relative).isEqualTo(actual); | |
| } | |
| @Test | |
| public void testGetRelativeWithRepoLocalAbsoluteLabel() throws Exception { | |
| PackageIdentifier packageId = PackageIdentifier.create("@repo", PathFragment.create("foo")); | |
| Label base = Label.create(packageId, "bar"); | |
| Label relative = base.getRelativeWithRemapping("//x:y", ImmutableMap.of()); | |
| assertThat(relative.getPackageIdentifier().getRepository()) | |
| .isEqualTo(packageId.getRepository()); | |
| assertThat(relative.getPackageFragment()).isEqualTo(PathFragment.create("x")); | |
| assertThat(relative.getName()).isEqualTo("y"); | |
| } | |
| @Test | |
| public void testGetRelativeWithLocalRepoRelativeLabel() throws Exception { | |
| PackageIdentifier packageId = PackageIdentifier.create("@repo", PathFragment.create("foo")); | |
| Label base = Label.create(packageId, "bar"); | |
| Label relative = base.getRelativeWithRemapping(":y", ImmutableMap.of()); | |
| assertThat(relative.getPackageIdentifier().getRepository()) | |
| .isEqualTo(packageId.getRepository()); | |
| assertThat(relative.getPackageFragment()).isEqualTo(PathFragment.create("foo")); | |
| assertThat(relative.getName()).isEqualTo("y"); | |
| } | |
| @Test | |
| public void testGetRelativeWithRepoAndReservedPackage() throws Exception { | |
| PackageIdentifier packageId = PackageIdentifier.create("@repo", PathFragment.create("foo")); | |
| Label base = Label.create(packageId, "bar"); | |
| Label relative = base.getRelativeWithRemapping("//conditions:default", ImmutableMap.of()); | |
| PackageIdentifier expected = PackageIdentifier.createInMainRepo("conditions"); | |
| assertThat(relative.getPackageIdentifier().getRepository()).isEqualTo(expected.getRepository()); | |
| assertThat(relative.getPackageFragment()).isEqualTo(expected.getPackageFragment()); | |
| assertThat(relative.getName()).isEqualTo("default"); | |
| } | |
| @Test | |
| public void testGetRelativeWithRemoteRepoToDefaultRepo() throws Exception { | |
| PackageIdentifier packageId = PackageIdentifier.create("@repo", PathFragment.create("foo")); | |
| Label base = Label.create(packageId, "bar"); | |
| Label relative = base.getRelativeWithRemapping("@//x:y", ImmutableMap.of()); | |
| assertThat(relative.getPackageIdentifier().getRepository()) | |
| .isEqualTo(RepositoryName.create("@")); | |
| assertThat(relative.getPackageFragment()).isEqualTo(PathFragment.create("x")); | |
| assertThat(relative.getName()).isEqualTo("y"); | |
| } | |
| @Test | |
| public void testGetRepositoryRelative() throws Exception { | |
| Label defaultBase = Label.parseAbsolute("//foo/bar:baz", ImmutableMap.of()); | |
| Label repoBase = Label.parseAbsolute("@repo//foo/bar:baz", ImmutableMap.of()); | |
| Label mainBase = Label.parseAbsolute("@//foo/bar:baz", ImmutableMap.of()); | |
| Label externalTarget = Label.parseAbsolute("//external:target", ImmutableMap.of()); | |
| Label l = defaultBase.resolveRepositoryRelative(externalTarget); | |
| assertThat(l.getPackageIdentifier().getRepository().isMain()).isTrue(); | |
| assertThat(l.getPackageName()).isEqualTo("external"); | |
| assertThat(l.getName()).isEqualTo("target"); | |
| assertThat(repoBase.resolveRepositoryRelative(externalTarget)).isEqualTo(l); | |
| assertThat(mainBase.resolveRepositoryRelative(externalTarget)).isEqualTo(l); | |
| } | |
| @Test | |
| public void testFactory() throws Exception { | |
| Label l = Label.create("foo/bar", "quux"); | |
| assertThat(l.getPackageName()).isEqualTo("foo/bar"); | |
| assertThat(l.getName()).isEqualTo("quux"); | |
| } | |
| @Test | |
| public void testIdentities() throws Exception { | |
| Label l1 = Label.parseAbsolute("//foo/bar:baz", ImmutableMap.of()); | |
| Label l2 = Label.parseAbsolute("//foo/bar:baz", ImmutableMap.of()); | |
| Label l3 = Label.parseAbsolute("//foo/bar:quux", ImmutableMap.of()); | |
| new EqualsTester() | |
| .addEqualityGroup(l1, l2) | |
| .addEqualityGroup(l3) | |
| .testEquals(); | |
| } | |
| @Test | |
| public void testToString() throws Exception { | |
| { | |
| String s = "@//foo/bar:baz"; | |
| Label l = Label.parseAbsolute(s, ImmutableMap.of()); | |
| assertThat(l.toString()).isEqualTo("//foo/bar:baz"); | |
| } | |
| { | |
| Label l = Label.parseAbsolute("//foo/bar", ImmutableMap.of()); | |
| assertThat(l.toString()).isEqualTo("//foo/bar:bar"); | |
| } | |
| { | |
| Label l = Label.parseAbsolute("@foo", ImmutableMap.of()); | |
| assertThat(l.toString()).isEqualTo("@foo//:foo"); | |
| } | |
| } | |
| @Test | |
| public void testToShorthandString() throws Exception { | |
| { | |
| Label l = Label.parseAbsolute("//bar/baz:baz", ImmutableMap.of()); | |
| assertThat(l.toShorthandString()).isEqualTo("//bar/baz"); | |
| } | |
| { | |
| Label l = Label.parseAbsolute("//bar/baz:bat", ImmutableMap.of()); | |
| assertThat(l.toShorthandString()).isEqualTo("//bar/baz:bat"); | |
| } | |
| { | |
| Label l = Label.parseAbsolute("@foo//bar/baz:baz", ImmutableMap.of()); | |
| assertThat(l.toShorthandString()).isEqualTo("@foo//bar/baz"); | |
| } | |
| { | |
| Label l = Label.parseAbsolute("@foo//bar/baz:bat", ImmutableMap.of()); | |
| assertThat(l.toShorthandString()).isEqualTo("@foo//bar/baz:bat"); | |
| } | |
| } | |
| @Test | |
| public void testDotDot() throws Exception { | |
| Label.parseAbsolute("//foo/bar:baz..gif", ImmutableMap.of()); | |
| } | |
| /** | |
| * Asserts that creating a label throws a SyntaxException. | |
| * @param label the label to create. | |
| */ | |
| private static void assertSyntaxError(String expectedError, String label) { | |
| LabelSyntaxException e = | |
| assertThrows( | |
| "Label '" + label + "' did not contain a syntax error, but was expected to", | |
| LabelSyntaxException.class, | |
| () -> Label.parseAbsolute(label, ImmutableMap.of())); | |
| assertThat(e).hasMessageThat().containsMatch(Pattern.quote(expectedError)); | |
| } | |
| @Test | |
| public void testBadCharacters() throws Exception { | |
| assertSyntaxError("target names may not contain ':'", | |
| "//foo:bar:baz"); | |
| assertSyntaxError("target names may not contain ':'", | |
| "//foo:bar:"); | |
| assertSyntaxError("target names may not contain ':'", | |
| "//foo/bar::"); | |
| } | |
| @Test | |
| public void testUplevelReferences() throws Exception { | |
| assertSyntaxError(INVALID_PACKAGE_NAME, "//foo/bar/..:baz"); | |
| assertSyntaxError(INVALID_PACKAGE_NAME, "//foo/../baz:baz"); | |
| assertSyntaxError(INVALID_PACKAGE_NAME, "//../bar/baz:baz"); | |
| assertSyntaxError(INVALID_PACKAGE_NAME, "//..:foo"); | |
| assertSyntaxError(INVALID_TARGET_NAME, "//foo:bar/../baz"); | |
| assertSyntaxError(INVALID_TARGET_NAME, "//foo:../bar/baz"); | |
| assertSyntaxError(INVALID_TARGET_NAME, "//foo:bar/baz/.."); | |
| assertSyntaxError(INVALID_TARGET_NAME, "//foo:.."); | |
| } | |
| @Test | |
| public void testDotAsAPathSegment() throws Exception { | |
| assertSyntaxError(INVALID_PACKAGE_NAME, "//foo/bar/.:baz"); | |
| assertSyntaxError(INVALID_PACKAGE_NAME, "//foo/./baz:baz"); | |
| assertSyntaxError(INVALID_PACKAGE_NAME, "//./bar/baz:baz"); | |
| assertSyntaxError(INVALID_TARGET_NAME, "//foo:bar/./baz"); | |
| assertSyntaxError(INVALID_TARGET_NAME, "//foo:./bar/baz"); | |
| // TODO(bazel-team): enable when we have removed the "Workaround" in Label | |
| // that rewrites broken Labels by removing the trailing '.' | |
| //assertSyntaxError(INVALID_PACKAGE_NAME, | |
| // "//foo:bar/baz/."); | |
| //assertSyntaxError(INVALID_PACKAGE_NAME, | |
| // "//foo:."); | |
| } | |
| @Test | |
| public void testTrailingDotSegment() throws Exception { | |
| assertThat(Label.parseAbsolute("//foo:dir", ImmutableMap.of())) | |
| .isEqualTo(Label.parseAbsolute("//foo:dir/.", ImmutableMap.of())); | |
| } | |
| @Test | |
| public void testSomeOtherBadLabels() throws Exception { | |
| assertSyntaxError("package names may not end with '/'", | |
| "//foo/:bar"); | |
| assertSyntaxError("package names may not start with '/'", "///p:foo"); | |
| assertSyntaxError("package names may not contain '//' path separators", | |
| "//a//b:foo"); | |
| } | |
| @Test | |
| public void testSomeGoodLabels() throws Exception { | |
| Label.parseAbsolute("//foo:..bar", ImmutableMap.of()); | |
| Label.parseAbsolute("//Foo:..bar", ImmutableMap.of()); | |
| Label.parseAbsolute("//-Foo:..bar", ImmutableMap.of()); | |
| Label.parseAbsolute("//00:..bar", ImmutableMap.of()); | |
| Label.parseAbsolute("//package:foo+bar", ImmutableMap.of()); | |
| Label.parseAbsolute("//package:foo_bar", ImmutableMap.of()); | |
| Label.parseAbsolute("//package:foo=bar", ImmutableMap.of()); | |
| Label.parseAbsolute("//package:foo-bar", ImmutableMap.of()); | |
| Label.parseAbsolute("//package:foo.bar", ImmutableMap.of()); | |
| Label.parseAbsolute("//package:foo@bar", ImmutableMap.of()); | |
| Label.parseAbsolute("//package:foo~bar", ImmutableMap.of()); | |
| Label.parseAbsolute("//$( ):$( )", ImmutableMap.of()); | |
| } | |
| @Test | |
| public void testDoubleSlashPathSeparator() throws Exception { | |
| assertSyntaxError("package names may not contain '//' path separators", | |
| "//foo//bar:baz"); | |
| assertSyntaxError("target names may not contain '//' path separator", | |
| "//foo:bar//baz"); | |
| } | |
| @Test | |
| public void testNonPrintableCharacters() throws Exception { | |
| assertSyntaxError( | |
| "target names may not contain non-printable characters: '\\x02'", | |
| "//foo:..\002bar"); | |
| } | |
| /** Make sure that control characters - such as CR - are escaped on output. */ | |
| @Test | |
| public void testInvalidLineEndings() throws Exception { | |
| assertSyntaxError("invalid target name '..bar\\r': " | |
| + "target names may not end with carriage returns", "//foo:..bar\r"); | |
| } | |
| @Test | |
| public void testEmptyName() throws Exception { | |
| assertSyntaxError("invalid target name '': empty target name", "//foo/bar:"); | |
| } | |
| @Test | |
| public void testSerializationSimple() throws Exception { | |
| checkSerialization("//a", 93); | |
| } | |
| @Test | |
| public void testSerializationNested() throws Exception { | |
| checkSerialization("//foo/bar:baz", 101); | |
| } | |
| @Test | |
| public void testSerializationWithoutTargetName() throws Exception { | |
| checkSerialization("//foo/bar", 101); | |
| } | |
| private void checkSerialization(String labelString, int expectedSize) throws Exception { | |
| Label a = Label.parseAbsolute(labelString, ImmutableMap.of()); | |
| byte[] sa = TestUtils.serializeObject(a); | |
| assertThat(sa).hasLength(expectedSize); | |
| Label a2 = (Label) TestUtils.deserializeObject(sa); | |
| assertThat(a2).isEqualTo(a); | |
| } | |
| @Test | |
| public void testRepoLabel() throws Exception { | |
| Label label = Label.parseAbsolute("@foo//bar/baz:bat/boo", ImmutableMap.of()); | |
| assertThat(label.toString()).isEqualTo("@foo//bar/baz:bat/boo"); | |
| } | |
| @Test | |
| public void testNoRepo() throws Exception { | |
| Label label = Label.parseAbsolute("//bar/baz:bat/boo", ImmutableMap.of()); | |
| assertThat(label.toString()).isEqualTo("//bar/baz:bat/boo"); | |
| } | |
| @Test | |
| public void testInvalidRepo() throws Exception { | |
| LabelSyntaxException e = | |
| assertThrows( | |
| LabelSyntaxException.class, | |
| () -> Label.parseAbsolute("foo//bar/baz:bat/boo", ImmutableMap.of())); | |
| assertThat(e) | |
| .hasMessageThat() | |
| .isEqualTo("invalid repository name 'foo': workspace names must start with '@'"); | |
| } | |
| @Test | |
| public void testInvalidRepoWithColon() throws Exception { | |
| LabelSyntaxException e = | |
| assertThrows( | |
| LabelSyntaxException.class, () -> Label.parseAbsolute("@foo:xyz", ImmutableMap.of())); | |
| assertThat(e) | |
| .hasMessageThat() | |
| .containsMatch("invalid repository name '@foo:xyz': workspace names may contain only"); | |
| } | |
| @Test | |
| public void testGetWorkspaceRoot() throws Exception { | |
| Label label = Label.parseAbsolute("//bar/baz", ImmutableMap.of()); | |
| assertThat(label.getWorkspaceRoot()).isEmpty(); | |
| label = Label.parseAbsolute("@repo//bar/baz", ImmutableMap.of()); | |
| assertThat(label.getWorkspaceRoot()).isEqualTo("external/repo"); | |
| } | |
| @Test | |
| public void testGetContainingDirectory() { | |
| assertThat(Label.getContainingDirectory(Label.parseAbsoluteUnchecked("//a:b"))) | |
| .isEqualTo(PathFragment.create("a")); | |
| assertThat(Label.getContainingDirectory(Label.parseAbsoluteUnchecked("//a/b:c"))) | |
| .isEqualTo(PathFragment.create("a/b")); | |
| assertThat(Label.getContainingDirectory(Label.parseAbsoluteUnchecked("//a:b/c"))) | |
| .isEqualTo(PathFragment.create("a/b")); | |
| assertThat(Label.getContainingDirectory(Label.parseAbsoluteUnchecked("//a/b/c"))) | |
| .isEqualTo(PathFragment.create("a/b/c")); | |
| } | |
| @Test | |
| public void testWorkspaceName() throws Exception { | |
| assertThat(Label.parseAbsolute("@foo//bar:baz", ImmutableMap.of()).getWorkspaceName()) | |
| .isEqualTo("foo"); | |
| assertThat(Label.parseAbsolute("//bar:baz", ImmutableMap.of()).getWorkspaceName()).isEmpty(); | |
| assertThat(Label.parseAbsolute("@//bar:baz", ImmutableMap.of()).getWorkspaceName()).isEmpty(); | |
| } | |
| } |