/* * Copyright 2014-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; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import com.facebook.buck.jvm.java.JavaLibraryBuilder; import com.facebook.buck.model.BuildTarget; import com.facebook.buck.model.BuildTargetFactory; import com.facebook.buck.testutil.TargetGraphFactory; import com.google.common.collect.ImmutableSet; import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; public class TargetGraphTest { private TargetNode<?, ?> nodeA; private TargetNode<?, ?> nodeB; private TargetNode<?, ?> nodeC; private TargetNode<?, ?> nodeD; private TargetNode<?, ?> nodeE; private TargetNode<?, ?> nodeF; private TargetNode<?, ?> nodeG; private TargetNode<?, ?> nodeH; private TargetNode<?, ?> nodeI; private TargetGraph targetGraph; @Rule public ExpectedException expectedException = ExpectedException.none(); @Before public void setUp() { // Creates the following target graph: // A B // /|\ / // C D E // |/| |\ // F G | H // \| // I nodeI = createTargetNode("I"); nodeH = createTargetNode("H"); nodeG = createTargetNode("G", nodeI); nodeF = createTargetNode("F"); nodeE = createTargetNode("E", nodeH, nodeI); nodeD = createTargetNode("D", nodeF, nodeG); nodeC = createTargetNode("C", nodeF); nodeB = createTargetNode("B", nodeE); nodeA = createTargetNode("A", nodeC, nodeD, nodeE); targetGraph = TargetGraphFactory.newInstance( nodeA, nodeB, nodeC, nodeD, nodeE, nodeF, nodeG, nodeH, nodeI); } @Test public void testEmptySubgraph() { ImmutableSet<TargetNode<?, ?>> roots = ImmutableSet.of(); ImmutableSet<TargetNode<?, ?>> expectedNodes = ImmutableSet.of(); checkSubgraph(roots, expectedNodes); } @Test public void testCompleteSubgraph() { ImmutableSet<TargetNode<?, ?>> roots = ImmutableSet.of(nodeA, nodeB); ImmutableSet<TargetNode<?, ?>> expectedNodes = targetGraph.getNodes(); checkSubgraph(roots, expectedNodes); } @Test public void testSubgraphWithAllRoots() { ImmutableSet<TargetNode<?, ?>> roots = targetGraph.getNodes(); ImmutableSet<TargetNode<?, ?>> expectedNodes = targetGraph.getNodes(); checkSubgraph(roots, expectedNodes); } @Test public void testSubgraphWithoutEdges() { ImmutableSet<TargetNode<?, ?>> roots = ImmutableSet.of(nodeF, nodeH, nodeI); ImmutableSet<TargetNode<?, ?>> expectedNodes = ImmutableSet.of(nodeF, nodeH, nodeI); checkSubgraph(roots, expectedNodes); } @Test public void testPartialSubgraph1() { ImmutableSet<TargetNode<?, ?>> roots = ImmutableSet.of(nodeB, nodeD, nodeH); ImmutableSet<TargetNode<?, ?>> expectedNodes = ImmutableSet.of(nodeB, nodeD, nodeE, nodeF, nodeG, nodeH, nodeI); checkSubgraph(roots, expectedNodes); } @Test public void testPartialSubgraph2() { ImmutableSet<TargetNode<?, ?>> roots = ImmutableSet.of(nodeD); ImmutableSet<TargetNode<?, ?>> expectedNodes = ImmutableSet.of(nodeD, nodeF, nodeG, nodeI); checkSubgraph(roots, expectedNodes); } @Test public void getOptionalForMissingNode() { assertThat( targetGraph.getOptional(BuildTargetFactory.newInstance("//foo:bar#baz")).isPresent(), Matchers.is(false)); } @Test public void getReportsMissingNode() { expectedException.expectMessage( "Required target for rule '//foo:bar#baz' was not found in the target graph."); targetGraph.get(BuildTargetFactory.newInstance("//foo:bar#baz")); } @Test public void getAllReportsMissingNode() { expectedException.expectMessage( "Required target for rule '//foo:bar#baz' was not found in the target graph."); // Force the Iterable to evaluate and throw. Iterable<TargetNode<?, ?>> allNodes = targetGraph.getAll(ImmutableSet.of(BuildTargetFactory.newInstance("//foo:bar#baz"))); for (TargetNode<?, ?> node : allNodes) { node.toString(); } } private void checkSubgraph( ImmutableSet<TargetNode<?, ?>> roots, ImmutableSet<TargetNode<?, ?>> expectedNodes) { TargetGraph subgraph = targetGraph.getSubgraph(roots); assertEquals( "Subgraph should contain the roots and their dependencies", expectedNodes, subgraph.getNodes()); for (TargetNode<?, ?> node : subgraph.getNodes()) { assertEquals( "Subgraph should have the same edges as the original graph", targetGraph.getOutgoingNodesFor(node), subgraph.getOutgoingNodesFor(node)); } for (TargetNode<?, ?> node : subgraph.getNodes()) { assertEquals( "subgraph.get should return a node containing the specified BuildTarget", node, subgraph.get(node.getBuildTarget())); } } private TargetNode<?, ?> createTargetNode(String name, TargetNode<?, ?>... deps) { BuildTarget buildTarget = BuildTargetFactory.newInstance("//foo: " + name); JavaLibraryBuilder targetNodeBuilder = JavaLibraryBuilder.createBuilder(buildTarget); for (TargetNode<?, ?> dep : deps) { targetNodeBuilder.addDep(dep.getBuildTarget()); } return targetNodeBuilder.build(); } }