/*
* 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.addthis.hydra.util;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class TestDirectedGraph {
@Test
public void testAddEdge() {
DirectedGraph<String> graph = new DirectedGraph<>();
assertFalse(graph.testEdge("foo", "bar"));
assertFalse(graph.testEdgeReverse("foo", "bar"));
graph.addEdge("foo", "bar");
assertTrue(graph.testEdge("foo", "bar"));
assertTrue(graph.testEdgeReverse("foo", "bar"));
graph = new DirectedGraph<>();
graph.addEdge("foo", "foo");
assertTrue(graph.testEdge("foo", "foo"));
assertTrue(graph.testEdgeReverse("foo", "foo"));
}
@Test
public void testRemoveEdge() {
DirectedGraph<String> graph = new DirectedGraph<>();
graph.addEdge("foo", "bar");
assertTrue(graph.testEdge("foo", "bar"));
assertTrue(graph.testEdgeReverse("foo", "bar"));
graph.removeEdge("foo", "bar");
assertFalse(graph.testEdge("foo", "bar"));
assertFalse(graph.testEdgeReverse("foo", "bar"));
graph = new DirectedGraph<>();
graph.addEdge("foo", "foo");
assertTrue(graph.testEdge("foo", "foo"));
assertTrue(graph.testEdgeReverse("foo", "foo"));
graph.removeEdge("foo", "foo");
assertFalse(graph.testEdge("foo", "foo"));
assertFalse(graph.testEdgeReverse("foo", "foo"));
}
@Test
public void testRemoveNode() {
DirectedGraph<String> graph = new DirectedGraph<>();
graph.addEdge("foo", "bar");
graph.addEdge("foo", "baz");
graph.addEdge("quux", "foo");
graph.removeNode("foo");
assertFalse(graph.testEdge("foo", "bar"));
assertFalse(graph.testEdgeReverse("foo", "bar"));
assertFalse(graph.testEdge("foo", "baz"));
assertFalse(graph.testEdgeReverse("foo", "baz"));
assertFalse(graph.testEdge("quux", "foo"));
assertFalse(graph.testEdgeReverse("quux", "foo"));
graph = new DirectedGraph<>();
graph.addEdge("foo", "foo");
graph.removeNode("foo");
assertFalse(graph.testEdge("foo", "foo"));
assertFalse(graph.testEdgeReverse("foo", "foo"));
}
@Test
public void testForwardClosure() {
DirectedGraph<String> graph = new DirectedGraph<>();
graph.addEdge("D", "D");
graph.addEdge("D", "F");
graph.addEdge("D", "G");
graph.addEdge("G", "H");
graph.addEdge("H", "F");
graph.addEdge("F", "D");
graph.addEdge("A", "B");
graph.addEdge("B", "G");
String[] resultArray = {"D", "F", "G", "H"};
Set<String> results = new HashSet<>(Arrays.asList(resultArray));
assertEquals(results, graph.sinksClosure("D"));
}
@Test
public void testBackwardClosure() {
DirectedGraph<String> graph = new DirectedGraph<>();
graph.addEdge("D", "D");
graph.addEdge("D", "F");
graph.addEdge("D", "G");
graph.addEdge("G", "H");
graph.addEdge("H", "F");
graph.addEdge("A", "B");
graph.addEdge("B", "G");
String[] resultArray = {"A", "B", "G", "D"};
Set<String> results = new HashSet<>(Arrays.asList(resultArray));
assertEquals(results, graph.sourcesClosure("G"));
}
@Test
public void testTarjansAlgorithm() {
DirectedGraph<String> graph = new DirectedGraph<>();
graph.addEdge("B", "A");
graph.addEdge("A", "C");
graph.addEdge("C", "B");
graph.addEdge("D", "C");
graph.addEdge("D", "B");
graph.addEdge("E", "B");
graph.addEdge("E", "G");
graph.addEdge("G", "E");
graph.addEdge("F", "E");
graph.addEdge("F", "D");
graph.addEdge("D", "F");
graph.addEdge("H", "G");
graph.addEdge("H", "F");
Set<Set<String>> components = graph.stronglyConnectedComponents();
assertEquals(4, components.size());
String[] component1 = {"C", "B", "A"};
String[] component2 = {"E", "G"};
String[] component3 = {"H"};
String[] component4 = {"D", "F"};
assertTrue(components.contains(new HashSet<>(Arrays.asList(component1))));
assertTrue(components.contains(new HashSet<>(Arrays.asList(component2))));
assertTrue(components.contains(new HashSet<>(Arrays.asList(component3))));
assertTrue(components.contains(new HashSet<>(Arrays.asList(component4))));
}
@Test
public void testFindAllCycles() {
DirectedGraph<String> graph = new DirectedGraph<>();
graph.addEdge("B", "A");
graph.addEdge("A", "C");
graph.addEdge("C", "B");
graph.addEdge("D", "C");
graph.addEdge("D", "B");
graph.addEdge("E", "B");
graph.addEdge("E", "G");
graph.addEdge("G", "E");
graph.addEdge("F", "E");
graph.addEdge("F", "D");
graph.addEdge("D", "F");
graph.addEdge("H", "G");
graph.addEdge("H", "F");
Set<Set<String>> components = graph.allCycles();
assertEquals(3, components.size());
String[] component1 = {"C", "B", "A"};
String[] component2 = {"E", "G"};
String[] component3 = {"D", "F"};
assertTrue(components.contains(new HashSet<>(Arrays.asList(component1))));
assertTrue(components.contains(new HashSet<>(Arrays.asList(component2))));
assertTrue(components.contains(new HashSet<>(Arrays.asList(component3))));
}
@Test
public void testFindBackwardCycles() {
DirectedGraph<String> graph = new DirectedGraph<>();
graph.addEdge("A", "B");
graph.addEdge("B", "C");
graph.addEdge("C", "B");
graph.addEdge("D", "A");
graph.addEdge("D", "E");
graph.addEdge("E", "D");
Set<Set<String>> components = graph.sourcesCycles("A");
assertEquals(1, components.size());
String[] component1 = {"D", "E"};
assertTrue(components.contains(new HashSet<>(Arrays.asList(component1))));
}
}