blob: 7f9741fe237fea13a9b406ca452c5f5990f23c6c [file] [log] [blame]
// 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();
}
}