/* * Copyright 2007-2016 University Of Southern California * * 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 edu.isi.pegasus.planner.partitioner.graph; import edu.isi.pegasus.common.logging.LogManager; import edu.isi.pegasus.planner.classes.NameValue; import edu.isi.pegasus.planner.test.DefaultTestSetup; import edu.isi.pegasus.planner.test.TestSetup; import java.util.LinkedList; import org.junit.AfterClass; import static org.junit.Assert.assertEquals; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; /** * Unit test class for checking cycles in a DAG * * @author Karan Vahi */ public class CycleCheckerTest { private LogManager mLogger; private TestSetup mTestSetup; private int mTestNumber =1 ; @BeforeClass public static void setUpClass() { } @AfterClass public static void tearDownClass() { } @Before public void setUp() { mTestSetup = new DefaultTestSetup(); mTestSetup.setInputDirectory( this.getClass() ); mLogger = mTestSetup.loadLogger( mTestSetup.loadPropertiesFromFile( ".properties", new LinkedList() )); mLogger.logEventStart( "test.planner.partitioner.graph.CycleChecker", "setup", "0" ); } @Test public void testSingleNode() { mLogger.logEventStart( "test.planner.partitioner.graph.CycleChecker", "set", Integer.toString(mTestNumber++) ); Graph g = new MapGraph(); g.addNode( new GraphNode("A", "A")); CycleChecker c = new CycleChecker(g); boolean cyclic = c.hasCycles(); assertEquals( "Input Test Case should be determined cycle free", false, cyclic ); mLogger.logEventCompletion(); } @Test (expected=IllegalArgumentException.class) public void testSingleNodeCyclic() { mLogger.logEventStart( "test.planner.partitioner.graph.CycleChecker", "set", Integer.toString(mTestNumber++) ); Graph g = new MapGraph(); g.addNode( new GraphNode("A", "A")); g.addEdge( "A", "A"); CycleChecker c = new CycleChecker(g); boolean cyclic = c.hasCycles(); assertEquals( "Input Test Case should be determined to be cyclic", true, cyclic ); if( cyclic ){ //cyclic edge is null since the whole workflow constitutes a cycle NameValue cyclicEdge = c.getCyclicEdge(); assertEquals("Cyclic Edge does not match", null, cyclicEdge ); } mLogger.logEventCompletion(); } @Test public void testBlackDiamond() { mLogger.logEventStart( "test.planner.partitioner.graph.CycleChecker", "set", Integer.toString(mTestNumber++) ); Graph g = new MapGraph(); g.addNode( new GraphNode("A", "A")); g.addNode( new GraphNode("B", "B")); g.addNode( new GraphNode("C", "C")); g.addNode( new GraphNode("D", "D")); g.addEdge( "A", "B"); g.addEdge( "A", "C"); g.addEdge( "B", "D"); g.addEdge( "C", "D"); CycleChecker c = new CycleChecker(g); boolean cyclic = c.hasCycles(); assertEquals( "Input Test Case should be determined cycle free", false, cyclic ); mLogger.logEventCompletion(); } @Test public void testBlackDiamondWholeCyclic() { mLogger.logEventStart( "test.planner.partitioner.graph.CycleChecker", "set", Integer.toString(mTestNumber++) ); Graph g = new MapGraph(); g.addNode( new GraphNode("A", "A")); g.addNode( new GraphNode("B", "B")); g.addNode( new GraphNode("C", "C")); g.addNode( new GraphNode("D", "D")); g.addEdge( "A", "B"); g.addEdge( "A", "C"); g.addEdge( "B", "D"); g.addEdge( "C", "D"); g.addEdge( "D", "A"); CycleChecker c = new CycleChecker(g); boolean cyclic = c.hasCycles(); assertEquals( "Input Test Case should be determined to be cyclic", true, cyclic ); if( cyclic ){ //cyclic edge is null since the whole workflow constitutes a cycle NameValue cyclicEdge = c.getCyclicEdge(); assertEquals("Cyclic Edge does not match", null, cyclicEdge ); } mLogger.logEventCompletion(); } @Test public void testBlackDiamondCyclic() { mLogger.logEventStart( "test.planner.partitioner.graph.CycleChecker", "set", Integer.toString(mTestNumber++) ); Graph g = new MapGraph(); g.addNode( new GraphNode("A", "A")); g.addNode( new GraphNode("B", "B")); g.addNode( new GraphNode("C", "C")); g.addNode( new GraphNode("D", "D")); g.addNode( new GraphNode("E", "E")); g.addEdge( "A", "B"); g.addEdge( "A", "C"); g.addEdge( "B", "D"); g.addEdge( "C", "D"); g.addEdge( "D", "E"); g.addEdge( "E", "D"); CycleChecker c = new CycleChecker(g); boolean cyclic = c.hasCycles(); assertEquals( "Input Test Case should be determined to be cyclic", true, cyclic ); if( cyclic ){ //cyclic edge is null since the whole workflow constitutes a cycle NameValue cyclicEdge = c.getCyclicEdge(); assertEquals("Cyclic Edge does not match", new NameValue("E","D"), cyclicEdge ); } mLogger.logEventCompletion(); } @Test public void testPipeline() { mLogger.logEventStart( "test.planner.partitioner.graph.CycleChecker", "set", Integer.toString(mTestNumber++) ); Graph g = new MapGraph(); g.addNode( new GraphNode("A", "A")); g.addNode( new GraphNode("B", "B")); g.addNode( new GraphNode("C", "C")); g.addNode( new GraphNode("D", "D")); g.addNode( new GraphNode("E", "E")); g.addEdge( "A", "B"); g.addEdge( "B", "C"); g.addEdge( "C", "D"); g.addEdge( "D", "E"); CycleChecker c = new CycleChecker(g); boolean cyclic = c.hasCycles(); assertEquals( "Input Test Case should be determined cycle free", false, cyclic ); mLogger.logEventCompletion(); } @Test public void testPipelineCyclic() { mLogger.logEventStart( "test.planner.partitioner.graph.CycleChecker", "set", Integer.toString(mTestNumber++) ); Graph g = new MapGraph(); g.addNode( new GraphNode("A", "A")); g.addNode( new GraphNode("B", "B")); g.addNode( new GraphNode("C", "C")); g.addNode( new GraphNode("D", "D")); g.addNode( new GraphNode("E", "E")); g.addEdge( "A", "B"); g.addEdge( "B", "C"); g.addEdge( "C", "D"); g.addEdge( "D", "E"); g.addEdge( "E", "B"); CycleChecker c = new CycleChecker(g); boolean cyclic = c.hasCycles(); assertEquals( "Input Test Case should be determined to be cyclic", true, cyclic ); if( cyclic ){ //cyclic edge is null since the whole workflow constitutes a cycle NameValue cyclicEdge = c.getCyclicEdge(); assertEquals("Cyclic Edge does not match", new NameValue("E","B"), cyclicEdge ); } mLogger.logEventCompletion(); } @Test public void testPipelineForest() { mLogger.logEventStart( "test.planner.partitioner.graph.CycleChecker", "set", Integer.toString(mTestNumber++) ); Graph g = new MapGraph(); g.addNode( new GraphNode("A", "A")); g.addNode( new GraphNode("B", "B")); g.addNode( new GraphNode("C", "C")); g.addNode( new GraphNode("D", "D")); g.addNode( new GraphNode("E", "E")); g.addEdge( "A", "B"); g.addEdge( "B", "C"); g.addEdge( "C", "D"); g.addEdge( "D", "E"); g.addNode( new GraphNode("A'", "A'")); g.addNode( new GraphNode("B'", "B'")); g.addNode( new GraphNode("C'", "C'")); g.addNode( new GraphNode("D'", "D'")); g.addNode( new GraphNode("E'", "E'")); g.addEdge( "A'", "B'"); g.addEdge( "B'", "C'"); g.addEdge( "C'", "D'"); g.addEdge( "D'", "E'"); g.addEdge( "E'", "B'"); CycleChecker c = new CycleChecker(g); boolean cyclic = c.hasCycles(); assertEquals( "Input Test Case should be determined to be cyclic", true, cyclic ); if( cyclic ){ //cyclic edge is null since the whole workflow constitutes a cycle NameValue cyclicEdge = c.getCyclicEdge(); assertEquals("Cyclic Edge does not match", new NameValue("E'","B'"), cyclicEdge ); } mLogger.logEventCompletion(); } }