/*
* Copyright 2016-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.rules.query;
import static org.easymock.EasyMock.createMock;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import com.facebook.buck.jvm.java.FakeJavaLibrary;
import com.facebook.buck.jvm.java.JavaLibraryBuilder;
import com.facebook.buck.jvm.java.JavaLibraryDescriptionArg;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.BuildTargetFactory;
import com.facebook.buck.parser.BuildTargetPatternParser;
import com.facebook.buck.query.QueryBuildTarget;
import com.facebook.buck.query.QueryTarget;
import com.facebook.buck.rules.BuildRuleResolver;
import com.facebook.buck.rules.CellPathResolver;
import com.facebook.buck.rules.DefaultCellPathResolver;
import com.facebook.buck.rules.DefaultTargetNodeToBuildRuleTransformer;
import com.facebook.buck.rules.SourcePathResolver;
import com.facebook.buck.rules.SourcePathRuleFinder;
import com.facebook.buck.rules.TargetGraph;
import com.facebook.buck.rules.TargetNode;
import com.facebook.buck.testutil.TargetGraphFactory;
import com.facebook.buck.util.MoreCollectors;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Optional;
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Test;
/** Tests for the query environment available during graph enhancement */
public class GraphEnhancementQueryEnvironmentTest {
private CellPathResolver cellRoots;
private ListeningExecutorService executor;
private static final Path ROOT = Paths.get("/fake/cell/root");
@Before
public void setUp() throws Exception {
cellRoots = new DefaultCellPathResolver(ROOT, ImmutableMap.of());
executor = MoreExecutors.newDirectExecutorService();
}
@Test
public void getTargetsMatchingPatternWithoutDeps() throws Exception {
BuildTarget target = BuildTargetFactory.newInstance(ROOT, "//foo/bar:bar");
GraphEnhancementQueryEnvironment envWithoutDeps =
new GraphEnhancementQueryEnvironment(
Optional.of(createMock(BuildRuleResolver.class)),
Optional.of(createMock(TargetGraph.class)),
cellRoots,
BuildTargetPatternParser.forBaseName(target.getBaseName()),
ImmutableSet.of());
// No deps in == no deps out
assertTrue(envWithoutDeps.getTargetsMatchingPattern("$declared_deps", executor).isEmpty());
// Check that returned path is resolved
assertThat(
envWithoutDeps.getTargetsMatchingPattern("//another/target:target", executor),
Matchers.contains(
QueryBuildTarget.of(BuildTargetFactory.newInstance(ROOT, "//another/target:target"))));
// Check that the returned path is relative to the contextual path
assertThat(
envWithoutDeps.getTargetsMatchingPattern(":relative_name", executor),
Matchers.contains(
QueryBuildTarget.of(BuildTargetFactory.newInstance(ROOT, "//foo/bar:relative_name"))));
}
@Test
public void getTargetsMatchingPatternWithDeps() throws Exception {
BuildTarget target = BuildTargetFactory.newInstance(ROOT, "//foo/bar:bar");
BuildTarget dep1 = BuildTargetFactory.newInstance(ROOT, "//deps:dep1");
BuildTarget dep2 = BuildTargetFactory.newInstance(ROOT, "//deps:dep2");
GraphEnhancementQueryEnvironment env =
new GraphEnhancementQueryEnvironment(
Optional.of(createMock(BuildRuleResolver.class)),
Optional.of(createMock(TargetGraph.class)),
cellRoots,
BuildTargetPatternParser.forBaseName(target.getBaseName()),
ImmutableSet.of(dep1, dep2));
// Check that the macro resolves
assertThat(
env.getTargetsMatchingPattern("$declared_deps", executor),
Matchers.hasItems(QueryBuildTarget.of(dep1), QueryBuildTarget.of(dep2)));
}
private GraphEnhancementQueryEnvironment buildQueryEnvironmentWithGraph() {
// Set up target graph: lib -> sublib -> bottom
TargetNode<JavaLibraryDescriptionArg, ?> bottomNode =
JavaLibraryBuilder.createBuilder(BuildTargetFactory.newInstance("//:bottom")).build();
TargetNode<JavaLibraryDescriptionArg, ?> sublibNode =
JavaLibraryBuilder.createBuilder(BuildTargetFactory.newInstance("//:sublib"))
.addDep(bottomNode.getBuildTarget())
.build();
TargetNode<JavaLibraryDescriptionArg, ?> libNode =
JavaLibraryBuilder.createBuilder(BuildTargetFactory.newInstance("//:lib"))
.addDep(sublibNode.getBuildTarget())
.build();
TargetGraph targetGraph = TargetGraphFactory.newInstance(bottomNode, libNode, sublibNode);
BuildRuleResolver realResolver =
new BuildRuleResolver(targetGraph, new DefaultTargetNodeToBuildRuleTransformer());
SourcePathResolver pathResolver =
new SourcePathResolver(new SourcePathRuleFinder(realResolver));
FakeJavaLibrary bottomRule =
realResolver.addToIndex(new FakeJavaLibrary(bottomNode.getBuildTarget(), pathResolver));
bottomRule.setOutputFile("bottom.jar");
FakeJavaLibrary sublibRule =
realResolver.addToIndex(
new FakeJavaLibrary(
sublibNode.getBuildTarget(), pathResolver, ImmutableSortedSet.of(bottomRule)));
sublibRule.setOutputFile("sublib.jar");
FakeJavaLibrary libRule =
realResolver.addToIndex(
new FakeJavaLibrary(
libNode.getBuildTarget(), pathResolver, ImmutableSortedSet.of(sublibRule)));
libRule.setOutputFile("lib.jar");
return new GraphEnhancementQueryEnvironment(
Optional.of(realResolver),
Optional.of(targetGraph),
cellRoots,
BuildTargetPatternParser.forBaseName(libNode.getBuildTarget().getBaseName()),
ImmutableSet.of(sublibNode.getBuildTarget()));
}
private static QueryTarget getQueryTarget(String target) {
return QueryBuildTarget.of(BuildTargetFactory.newInstance(target));
}
@Test
public void getFwdDeps() throws Exception {
GraphEnhancementQueryEnvironment env = buildQueryEnvironmentWithGraph();
// lib -> sublib
assertThat(
env.getFwdDeps(ImmutableSet.of(getQueryTarget("//:lib"))),
Matchers.contains(getQueryTarget("//:sublib")));
// sublib -> bottom
assertThat(
env.getFwdDeps(ImmutableSet.of(getQueryTarget("//:sublib"))),
Matchers.contains(getQueryTarget("//:bottom")));
}
@Test
public void getClasspath() throws Exception {
GraphEnhancementQueryEnvironment env = buildQueryEnvironmentWithGraph();
ImmutableSet<QueryTarget> classpath =
env.getFirstOrderClasspath(ImmutableSet.of(getQueryTarget("//:lib")))
.collect(MoreCollectors.toImmutableSet());
assertThat(classpath, Matchers.hasItems(getQueryTarget("//:sublib")));
}
}