/* * 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.graph; import static org.junit.Assert.assertEquals; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.Iterables; import java.util.ArrayList; import java.util.List; import org.junit.Test; public class AbstractBreadthFirstTraversalTest { @Test public void testIsBreadthFirst() { // The dependency graph is built as follows: // // J // / / \ \ // F G H I // / \ / \ \ // E D C B A // FakeNode nodeA = createNode("A"); FakeNode nodeB = createNode("B"); FakeNode nodeC = createNode("C"); FakeNode nodeD = createNode("D"); FakeNode nodeE = createNode("E"); FakeNode nodeF = createNode("F", nodeE, nodeD); FakeNode nodeG = createNode("G"); FakeNode nodeH = createNode("H", nodeC, nodeB); FakeNode nodeI = createNode("I", nodeA); FakeNode initialNode = createNode("J", nodeF, nodeG, nodeH, nodeI); final List<FakeNode> nodeTraversalOrder = new ArrayList<>(); new AbstractBreadthFirstTraversal<FakeNode>(initialNode) { @Override public ImmutableSet<FakeNode> visit(FakeNode node) { nodeTraversalOrder.add(node); return node.getDeps(); } }.start(); assertEquals( "Dependencies should be explored breadth-first, using lexicographic ordering to break ties", ImmutableList.of( initialNode, nodeF, nodeG, nodeH, nodeI, nodeD, nodeE, nodeB, nodeC, nodeA), nodeTraversalOrder); } @Test public void testSubsetWorks() { // The dependency graph is built as follows: // // 10 // / / \ \ // 6 7 8 9 // / \ / \ \ // 5 4 3 2 1 // FakeNode node1 = createNode("1"); FakeNode node2 = createNode("2"); FakeNode node3 = createNode("3"); FakeNode node4 = createNode("4"); FakeNode node5 = createNode("5"); FakeNode node6 = createNode("6", node5, node4); FakeNode node7 = createNode("7"); FakeNode node8 = createNode("8", node3, node2); FakeNode node9 = createNode("9", node1); FakeNode initialNode = createNode("10", node6, node7, node8, node9); final List<FakeNode> nodeTraversalOrder = new ArrayList<>(); // This visitor only visits dependencies whose node names are even numbers. new AbstractBreadthFirstTraversal<FakeNode>(initialNode) { @Override public ImmutableSet<FakeNode> visit(FakeNode node) { nodeTraversalOrder.add(node); return ImmutableSet.copyOf( Iterables.filter(node.getDeps(), input -> Integer.parseInt(input.getName()) % 2 == 0)); } }.start(); assertEquals( "Dependencies should be explored breadth-first, only containing nodes whose node name is " + "an even number", ImmutableList.of(initialNode, node6, node8, node4, node2), nodeTraversalOrder); } private static class FakeNode implements Comparable<FakeNode> { protected String name; protected ImmutableSortedSet<FakeNode> deps; public FakeNode(String name, ImmutableSortedSet<FakeNode> deps) { this.name = name; this.deps = deps; } public String getName() { return name; } public ImmutableSet<FakeNode> getDeps() { return deps; } @Override public int compareTo(FakeNode other) { if (this == other) { return 0; } return this.name.compareTo(other.name); } } private FakeNode createNode(String name, FakeNode... deps) { return new FakeNode(name, ImmutableSortedSet.copyOf(deps)); } }