/*
* Copyright 2012-present Facebook, Inc.
*
* 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.facebook.buck.parser;
import static com.facebook.buck.rules.TestCellBuilder.createCellRoots;
import static org.hamcrest.Matchers.hasItems;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.BuildTargetPattern;
import com.facebook.buck.model.Flavor;
import com.facebook.buck.model.InternalFlavor;
import com.facebook.buck.rules.CellPathResolver;
import com.facebook.buck.rules.DefaultCellPathResolver;
import com.google.common.collect.ImmutableMap;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
public class BuildTargetParserTest {
private final BuildTargetParser parser = BuildTargetParser.INSTANCE;
private BuildTargetPatternParser<BuildTargetPattern> fullyQualifiedParser;
@Before
public void setUpFullyQualifiedBuildTargetPatternParser() {
fullyQualifiedParser = BuildTargetPatternParser.fullyQualified();
}
@Rule public ExpectedException exception = ExpectedException.none();
@Test
public void testParseRootRule() {
// Parse "//:fb4a" with the BuildTargetParser and test all of its observers.
BuildTarget buildTarget = parser.parse("//:fb4a", fullyQualifiedParser, createCellRoots(null));
assertEquals("fb4a", buildTarget.getShortNameAndFlavorPostfix());
assertEquals("//", buildTarget.getBaseName());
assertEquals(Paths.get(""), buildTarget.getBasePath());
assertEquals("//:fb4a", buildTarget.getFullyQualifiedName());
}
@Test
public void testParseRuleWithFlavors() {
BuildTarget buildTarget =
parser.parse("//:lib#foo,bar", fullyQualifiedParser, createCellRoots(null));
// Note the sort order.
assertEquals("lib#bar,foo", buildTarget.getShortNameAndFlavorPostfix());
assertEquals("//", buildTarget.getBaseName());
assertEquals(Paths.get(""), buildTarget.getBasePath());
// Note the sort order.
assertEquals("//:lib#bar,foo", buildTarget.getFullyQualifiedName());
assertThat(
buildTarget.getFlavors(),
hasItems((Flavor) InternalFlavor.of("foo"), InternalFlavor.of("bar")));
}
@Test
public void testParseValidTargetWithDots() {
BuildTarget buildTarget =
parser.parse("//..a/b../a...b:assets", fullyQualifiedParser, createCellRoots(null));
assertEquals("assets", buildTarget.getShortNameAndFlavorPostfix());
assertEquals("//..a/b../a...b", buildTarget.getBaseName());
assertEquals(Paths.get("..a", "b..", "a...b"), buildTarget.getBasePath());
assertEquals("//..a/b../a...b:assets", buildTarget.getFullyQualifiedName());
}
@Test
public void testParsePathWithDot() {
exception.expect(BuildTargetParseException.class);
exception.expectMessage(" . ");
exception.expectMessage("(found //.:assets)");
parser.parse("//.:assets", fullyQualifiedParser, createCellRoots(null));
}
@Test
public void testParsePathWithDotDot() {
exception.expect(BuildTargetParseException.class);
exception.expectMessage(" .. ");
exception.expectMessage("(found //../facebookorca:assets)");
parser.parse("//../facebookorca:assets", fullyQualifiedParser, createCellRoots(null));
}
@Test
public void testParseAbsolutePath() {
exception.expect(BuildTargetParseException.class);
exception.expectMessage("absolute");
exception.expectMessage("(found ///facebookorca:assets)");
parser.parse("///facebookorca:assets", fullyQualifiedParser, createCellRoots(null));
}
@Test
public void testParseDoubleSlashPath() {
exception.expect(BuildTargetParseException.class);
exception.expectMessage("//");
exception.expectMessage("(found //facebook//orca:assets)");
parser.parse("//facebook//orca:assets", fullyQualifiedParser, createCellRoots(null));
}
@Test
public void testParseTrailingColon() {
try {
parser.parse("//facebook/orca:assets:", fullyQualifiedParser, createCellRoots(null));
fail("parse() should throw an exception");
} catch (BuildTargetParseException e) {
assertEquals("//facebook/orca:assets: cannot end with a colon", e.getMessage());
}
}
@Test
public void testParseNoColon() {
try {
parser.parse("//facebook/orca/assets", fullyQualifiedParser, createCellRoots(null));
fail("parse() should throw an exception");
} catch (BuildTargetParseException e) {
assertEquals(
"//facebook/orca/assets must contain exactly one colon (found 0)", e.getMessage());
}
}
@Test
public void testParseMultipleColons() {
try {
parser.parse("//facebook:orca:assets", fullyQualifiedParser, createCellRoots(null));
fail("parse() should throw an exception");
} catch (BuildTargetParseException e) {
assertEquals(
"//facebook:orca:assets must contain exactly one colon (found 2)", e.getMessage());
}
}
@Test
public void testParseFullyQualified() {
BuildTarget buildTarget =
parser.parse("//facebook/orca:assets", fullyQualifiedParser, createCellRoots(null));
assertEquals("//facebook/orca", buildTarget.getBaseName());
assertEquals("assets", buildTarget.getShortNameAndFlavorPostfix());
}
@Test
public void testParseBuildFile() {
BuildTarget buildTarget =
parser.parse(
":assets",
BuildTargetPatternParser.forBaseName("//facebook/orca"),
createCellRoots(null));
assertEquals("//facebook/orca", buildTarget.getBaseName());
assertEquals("assets", buildTarget.getShortNameAndFlavorPostfix());
}
@Test
public void testParseWithVisibilityContext() {
// Invoke the BuildTargetParser using the VISIBILITY context.
BuildTargetPatternParser<BuildTargetPattern> buildTargetPatternParser =
BuildTargetPatternParser.forVisibilityArgument();
BuildTarget target =
parser.parse("//java/com/example:", buildTargetPatternParser, createCellRoots(null));
assertEquals(
"A build target that ends with a colon should be treated as a wildcard build target "
+ "when parsed in the context of a visibility argument.",
"//java/com/example:",
target.getFullyQualifiedName());
}
@Test
public void testParseWithRepoName() {
final Path localRepoRoot = Paths.get("/opt/local/repo");
CellPathResolver cellRoots =
new DefaultCellPathResolver(
Paths.get("/opt/local/rootcell"), ImmutableMap.of("localreponame", localRepoRoot));
String targetStr = "localreponame//foo/bar:baz";
BuildTarget buildTarget = parser.parse(targetStr, fullyQualifiedParser, cellRoots);
assertEquals("localreponame//foo/bar:baz", buildTarget.getFullyQualifiedName());
assertTrue(buildTarget.getCell().isPresent());
assertEquals(localRepoRoot, buildTarget.getCellPath());
}
@Test(expected = BuildTargetParseException.class)
public void testParseFailsWithRepoNameAndRelativeTarget() throws NoSuchBuildTargetException {
String invalidTargetStr = "myRepo:baz";
parser.parse(invalidTargetStr, fullyQualifiedParser, createCellRoots(null));
}
@Test
public void testParseWithBackslash() {
String backslashStr = "//com\\microsoft\\windows:something";
BuildTarget buildTarget =
parser.parse(backslashStr, fullyQualifiedParser, createCellRoots(null));
assertEquals("//com/microsoft/windows", buildTarget.getBaseName());
}
}