func TestDepthFirstSearchInCycleGraph(t *testing.T) { //Create some nodes. a := graph.Node{Value: Letter{"A"}} b := graph.Node{Value: Letter{"B"}} c := graph.Node{Value: Letter{"C"}} d := graph.Node{Value: Letter{"D"}} e := graph.Node{Value: Letter{"E"}} f := graph.Node{Value: Letter{"F"}} g := graph.Node{Value: Letter{"G"}} directGraph := graph.NewGraph() directGraph.InsertEdge(&a, &b) directGraph.InsertEdge(&a, &c) directGraph.InsertEdge(&a, &e) directGraph.InsertEdge(&b, &d) directGraph.InsertEdge(&b, &f) directGraph.InsertEdge(&c, &g) directGraph.InsertEdge(&f, &e) expectedDepthFirstSearch := directGraph.GetDFS() correctDepthFirstSearch := []Letter{ {"A"}, {"B"}, {"D"}, {"F"}, {"E"}, {"C"}, {"G"}, } //Compare DFS with correct DFS. for index := 0; index < len(expectedDepthFirstSearch); index++ { if expectedDepthFirstSearch[index].Value.String() != correctDepthFirstSearch[index].letter { t.Errorf("Element nr. %d in DFS should be %s, not %s\n", index, correctDepthFirstSearch[index].letter, expectedDepthFirstSearch[index].Value.String()) } } }
func TestStronglyConnectedComponentsInGraph(t *testing.T) { directedGraph := graph.NewGraph() a := graph.Node{Value: Letter{"A"}} b := graph.Node{Value: Letter{"B"}} c := graph.Node{Value: Letter{"C"}} d := graph.Node{Value: Letter{"D"}} e := graph.Node{Value: Letter{"E"}} f := graph.Node{Value: Letter{"F"}} g := graph.Node{Value: Letter{"G"}} h := graph.Node{Value: Letter{"H"}} directedGraph.InsertEdge(&a, &b) directedGraph.InsertEdge(&b, &c) directedGraph.InsertEdge(&c, &d) directedGraph.InsertEdge(&d, &c) directedGraph.InsertEdge(&d, &h) directedGraph.InsertEdge(&h, &d) directedGraph.InsertEdge(&c, &g) directedGraph.InsertEdge(&h, &g) directedGraph.InsertEdge(&f, &g) directedGraph.InsertEdge(&g, &f) directedGraph.InsertEdge(&b, &f) directedGraph.InsertEdge(&e, &f) directedGraph.InsertEdge(&e, &a) directedGraph.InsertEdge(&b, &e) expectedStronglyConnectedComponents := directedGraph.GetSCComponents() correctStronglyConnectedComponents := []*graph.StronglyConnectedComponent{ { Nodes: []*graph.Node{ {Value: Letter{"F"}}, {Value: Letter{"G"}}, }}, { Nodes: []*graph.Node{ {Value: Letter{"H"}}, {Value: Letter{"C"}}, {Value: Letter{"D"}}, }}, { Nodes: []*graph.Node{ {Value: Letter{"B"}}, {Value: Letter{"A"}}, {Value: Letter{"E"}}, }}, } // Check the number of SCC sets. if len(expectedStronglyConnectedComponents) != len(correctStronglyConnectedComponents) { t.Fatalf("Number of strongly connected components be %d, but are %d!\n", len(correctStronglyConnectedComponents), len(expectedStronglyConnectedComponents)) } if !sccExists(correctStronglyConnectedComponents, expectedStronglyConnectedComponents) { t.Error("Not all SCC exists") } }
func TestIfElseControlFlowGraph(t *testing.T) { filePath := "./testcode/_ifelse.go" sourceFile, err := ioutil.ReadFile(filePath) if err != nil { t.Fatal(err) } basicBlocks, err := bblock.GetBasicBlocksFromSourceCode(filePath, sourceFile) if err != nil { t.Fatal(err) } expectedGraph := cfgraph.GetControlFlowGraph(basicBlocks) correctGraph := graph.NewGraph() START := bblock.NewBasicBlock(-1, bblock.START, 0) EXIT := bblock.NewBasicBlock(-1, bblock.EXIT, 0) BB0 := bblock.NewBasicBlock(0, bblock.FUNCTION_ENTRY, 8) BB1 := bblock.NewBasicBlock(1, bblock.IF_CONDITION, 13) BB2 := bblock.NewBasicBlock(2, bblock.ELSE_CONDITION, 16) BB3 := bblock.NewBasicBlock(3, bblock.ELSE_BODY, 20) BB4 := bblock.NewBasicBlock(4, bblock.RETURN_STMT, 23) BB0.AddSuccessorBlock(BB1) BB1.AddSuccessorBlock(BB2, BB3) BB2.AddSuccessorBlock(BB4) BB3.AddSuccessorBlock(BB4) correctBasicBlocks := []*bblock.BasicBlock{BB0, BB1, BB2, BB3, BB4} //Test basic-blocks. if err := VerifyBasicBlocks(basicBlocks, correctBasicBlocks); err != nil { t.Fatal(err) } correctGraph.InsertEdge(&graph.Node{Value: START}, &graph.Node{Value: BB0}) correctGraph.InsertEdge(&graph.Node{Value: BB0}, &graph.Node{Value: BB1}) correctGraph.InsertEdge(&graph.Node{Value: BB1}, &graph.Node{Value: BB2}) correctGraph.InsertEdge(&graph.Node{Value: BB1}, &graph.Node{Value: BB3}) correctGraph.InsertEdge(&graph.Node{Value: BB2}, &graph.Node{Value: BB4}) correctGraph.InsertEdge(&graph.Node{Value: BB3}, &graph.Node{Value: BB4}) correctGraph.InsertEdge(&graph.Node{Value: BB4}, &graph.Node{Value: EXIT}) correctGraph.InsertEdge(&graph.Node{Value: EXIT}, &graph.Node{Value: START}) if err := VerifyControlFlowGraphs(expectedGraph[0], correctGraph); err != nil { t.Fatal(err) } }
func TestDepthFirstSearchInGraph(t *testing.T) { //Create some nodes. a := graph.Node{Value: Letter{"A"}} b := graph.Node{Value: Letter{"B"}} c := graph.Node{Value: Letter{"C"}} d := graph.Node{Value: Letter{"D"}} e := graph.Node{Value: Letter{"E"}} f := graph.Node{Value: Letter{"F"}} g := graph.Node{Value: Letter{"G"}} h := graph.Node{Value: Letter{"H"}} graph := graph.NewGraph() //Add directed node-pairs to graph. graph.InsertEdge(&a, &b) graph.InsertEdge(&a, &d) graph.InsertEdge(&b, &d) graph.InsertEdge(&b, &c) graph.InsertEdge(&c, &e) graph.InsertEdge(&e, &g) graph.InsertEdge(&e, &f) graph.InsertEdge(&f, &h) expectedDepthFirstSearch := graph.GetDFS() correctDfs := []Letter{{"A"}, {"B"}, {"D"}, {"C"}, {"E"}, {"G"}, {"F"}, {"H"}} //Equal length. if len(correctDfs) != len(expectedDepthFirstSearch) { t.Errorf("Length of DFS (%d) is not equal length of correct DFS (%d)!\n", len(expectedDepthFirstSearch), len(correctDfs)) } //Check nodes in depth first search. for index, node := range expectedDepthFirstSearch { if node.String() != correctDfs[index].String() { t.Error("Faen i helvete") } } }
func TestSimpleControlFlowGraph(t *testing.T) { filePath := "./testcode/_simple.go" sourceFile, err := ioutil.ReadFile(filePath) if err != nil { t.Fatal(err) } basicBlocks, err := bblock.GetBasicBlocksFromSourceCode(filePath, sourceFile) if err != nil { t.Fatal(err) } expectedGraph := cfgraph.GetControlFlowGraph(basicBlocks) correctGraph := graph.NewGraph() START := bblock.NewBasicBlock(-1, bblock.START, 0) EXIT := bblock.NewBasicBlock(-1, bblock.EXIT, 0) BB0 := bblock.NewBasicBlock(0, bblock.FUNCTION_ENTRY, 8) BB1 := bblock.NewBasicBlock(1, bblock.RETURN_STMT, 11) BB0.AddSuccessorBlock(BB1) correctBasicBlocks := []*bblock.BasicBlock{BB0, BB1} //Test basic-blocks. if err := VerifyBasicBlocks(basicBlocks, correctBasicBlocks); err != nil { t.Fatal(err) } correctGraph.InsertEdge(&graph.Node{Value: START}, &graph.Node{Value: BB0}) correctGraph.InsertEdge(&graph.Node{Value: BB0}, &graph.Node{Value: BB1}) correctGraph.InsertEdge(&graph.Node{Value: BB1}, &graph.Node{Value: EXIT}) correctGraph.InsertEdge(&graph.Node{Value: EXIT}, &graph.Node{Value: START}) if err := VerifyControlFlowGraphs(expectedGraph[0], correctGraph); err != nil { t.Fatal(err) } }
func New() *ControlFlowGraph { return &ControlFlowGraph{graph.NewGraph()} }
func TestDirectedGraph(test *testing.T) { //Create some nodes. a := graph.Node{Value: Letter{"A"}} b := graph.Node{Value: Letter{"B"}} c := graph.Node{Value: Letter{"C"}} d := graph.Node{Value: Letter{"D"}} e := graph.Node{Value: Letter{"E"}} f := graph.Node{Value: Letter{"F"}} g := graph.Node{Value: Letter{"G"}} h := graph.Node{Value: Letter{"H"}} graph := graph.NewGraph() //Add directed node-pairs to graph. graph.InsertEdge(&a, &b) graph.InsertEdge(&a, &d) graph.InsertEdge(&b, &d) graph.InsertEdge(&b, &c) graph.InsertEdge(&c, &e) graph.InsertEdge(&e, &g) graph.InsertEdge(&e, &f) graph.InsertEdge(&f, &h) //Test number of nodes in graph. if graph.GetNumberOfNodes() != 8 { test.Fatalf("Graph should contain 8 nodes, not %d!\n", graph.GetNumberOfNodes()) } //Node A should be root node. if graph.Root.Value != a.Value { test.Errorf("Node A should be root node, not node %v\n", graph.Root.Value) } //Test node A. if a.GetInDegree() != 0 { test.Errorf("Node A in-degree should be 0, not %d\n", a.GetInDegree()) } if a.GetOutDegree() != 2 { test.Errorf("Node A out-degree should be 2, not %d\n", a.GetInDegree()) } //Test node B. if b.GetInDegree() != 1 { test.Errorf("Node A in-degree should be 1, not %d\n", b.GetInDegree()) } if b.GetOutDegree() != 2 { test.Errorf("Node A out-degree should be 2, not %d\n", b.GetInDegree()) } //Test node C. if c.GetInDegree() != 1 { test.Errorf("Node A in-degree should be 1, not %d\n", c.GetInDegree()) } if c.GetOutDegree() != 1 { test.Errorf("Node A out-degree should be 1, not %d\n", c.GetInDegree()) } //Test node D. if d.GetInDegree() != 2 { test.Errorf("Node A in-degree should be 2, not %d\n", d.GetInDegree()) } if d.GetOutDegree() != 0 { test.Errorf("Node A out-degree should be 0, not %d\n", d.GetInDegree()) } //Test node E. if e.GetInDegree() != 1 { test.Errorf("Node A in-degree should be 1, not %d\n", e.GetInDegree()) } if e.GetOutDegree() != 2 { test.Errorf("Node A out-degree should be 2, not %d\n", e.GetInDegree()) } //Test node F. if f.GetInDegree() != 1 { test.Errorf("Node A in-degree should be 1, not %d\n", f.GetInDegree()) } if f.GetOutDegree() != 1 { test.Errorf("Node A out-degree should be 1, not %d\n", f.GetInDegree()) } //Test node G. if g.GetInDegree() != 1 { test.Errorf("Node A in-degree should be 1, not %d\n", g.GetInDegree()) } if g.GetOutDegree() != 0 { test.Errorf("Node A out-degree should be 0, not %d\n", g.GetInDegree()) } //Test node H. if h.GetInDegree() != 1 { test.Errorf("Node A in-degree should be 1, not %d\n", h.GetInDegree()) } if h.GetOutDegree() != 0 { test.Errorf("Node A out-degree should be 0, not %d\n", h.GetInDegree()) } }
func TestGreatestCommonDivisorControlFlowGraph(t *testing.T) { filePath := "./testcode/_gcd.go" sourceFile, err := ioutil.ReadFile(filePath) if err != nil { t.Fatal(err) } basicBlocks, err := bblock.GetBasicBlocksFromSourceCode(filePath, sourceFile) if err != nil { t.Fatal(err) } expectedGraphs := cfgraph.GetControlFlowGraph(basicBlocks) correctGraph := []*graph.Graph{ graph.NewGraph(), // func 'gcd' graph.NewGraph(), // func 'main' } // Function 'gcd' START0 := bblock.NewBasicBlock(-1, bblock.START, 0) EXIT0 := bblock.NewBasicBlock(-1, bblock.EXIT, 0) BB0 := bblock.NewBasicBlock(0, bblock.FUNCTION_ENTRY, 8) BB1 := bblock.NewBasicBlock(1, bblock.FOR_STATEMENT, 10) BB2 := bblock.NewBasicBlock(2, bblock.FOR_BODY, 13) BB3 := bblock.NewBasicBlock(3, bblock.RETURN_STMT, 14) // Function 'main' START1 := bblock.NewBasicBlock(-1, bblock.START, 0) EXIT1 := bblock.NewBasicBlock(-1, bblock.EXIT, 0) BB4 := bblock.NewBasicBlock(4, bblock.FUNCTION_ENTRY, 17) BB5 := bblock.NewBasicBlock(5, bblock.RETURN_STMT, 21) BB0.AddSuccessorBlock(BB1) BB1.AddSuccessorBlock(BB2, BB3) BB2.AddSuccessorBlock(BB1) BB4.AddSuccessorBlock(BB5) correctBasicBlocks := []*bblock.BasicBlock{BB0, BB1, BB2, BB3, BB4, BB5} // Function 'gcd' correctGraph[0].InsertEdge(&graph.Node{Value: START0}, &graph.Node{Value: BB0}) correctGraph[0].InsertEdge(&graph.Node{Value: BB0}, &graph.Node{Value: BB1}) correctGraph[0].InsertEdge(&graph.Node{Value: BB1}, &graph.Node{Value: BB2}) correctGraph[0].InsertEdge(&graph.Node{Value: BB2}, &graph.Node{Value: BB1}) correctGraph[0].InsertEdge(&graph.Node{Value: BB1}, &graph.Node{Value: BB3}) correctGraph[0].InsertEdge(&graph.Node{Value: BB3}, &graph.Node{Value: EXIT0}) correctGraph[0].InsertEdge(&graph.Node{Value: EXIT0}, &graph.Node{Value: START0}) // Function 'main' correctGraph[1].InsertEdge(&graph.Node{Value: START1}, &graph.Node{Value: BB4}) correctGraph[1].InsertEdge(&graph.Node{Value: BB4}, &graph.Node{Value: BB5}) correctGraph[1].InsertEdge(&graph.Node{Value: BB5}, &graph.Node{Value: EXIT1}) correctGraph[1].InsertEdge(&graph.Node{Value: EXIT1}, &graph.Node{Value: START1}) // Test basic-blocks. if err := VerifyBasicBlocks(basicBlocks, correctBasicBlocks); err != nil { t.Fatal(err) } // Test control-flow graph. if err := VerifyControlFlowGraphs(expectedGraphs[0], correctGraph[0]); err != nil { t.Fatal(err) } if err := VerifyControlFlowGraphs(expectedGraphs[1], correctGraph[1]); err != nil { t.Fatal(err) } }
func TestSwitchControlFlowGraph(t *testing.T) { filePath := "./testcode/_switcher.go" sourceFile, err := ioutil.ReadFile(filePath) if err != nil { t.Fatal(err) } basicBlocks, err := bblock.GetBasicBlocksFromSourceCode(filePath, sourceFile) if err != nil { t.Fatal(err) } expectedGraphs := cfgraph.GetControlFlowGraph(basicBlocks) correctGraph := []*graph.Graph{ graph.NewGraph(), // func 'main' graph.NewGraph(), // func 'integerToString' } START := bblock.NewBasicBlock(-1, bblock.START, 0) EXIT := bblock.NewBasicBlock(-1, bblock.EXIT, 0) // Function 'main' BB0 := bblock.NewBasicBlock(0, bblock.FUNCTION_ENTRY, 8) BB1 := bblock.NewBasicBlock(1, bblock.RETURN_STMT, 11) // Function 'integerToString' BB2 := bblock.NewBasicBlock(2, bblock.FUNCTION_ENTRY, 13) BB3 := bblock.NewBasicBlock(3, bblock.SWITCH_STATEMENT, 14) BB4 := bblock.NewBasicBlock(4, bblock.RETURN_STMT, 16) BB5 := bblock.NewBasicBlock(5, bblock.RETURN_STMT, 18) BB6 := bblock.NewBasicBlock(6, bblock.RETURN_STMT, 20) BB7 := bblock.NewBasicBlock(7, bblock.RETURN_STMT, 22) BB8 := bblock.NewBasicBlock(8, bblock.RETURN_STMT, 24) BB0.AddSuccessorBlock(BB1) BB2.AddSuccessorBlock(BB3) BB3.AddSuccessorBlock(BB4, BB5, BB6, BB7, BB8) correctBasicBlocks := []*bblock.BasicBlock{BB0, BB1, BB2, BB3, BB4, BB5, BB6, BB7, BB8} //Test basic-blocks. if err := VerifyBasicBlocks(basicBlocks, correctBasicBlocks); err != nil { t.Fatal(err) } // Control flow graph for function 'main'. correctGraph[0].InsertEdge(&graph.Node{Value: START}, &graph.Node{Value: BB0}) correctGraph[0].InsertEdge(&graph.Node{Value: BB0}, &graph.Node{Value: BB1}) correctGraph[0].InsertEdge(&graph.Node{Value: BB1}, &graph.Node{Value: EXIT}) correctGraph[0].InsertEdge(&graph.Node{Value: EXIT}, &graph.Node{Value: START}) // Control flow graph for function 'integerToString'. correctGraph[1].InsertEdge(&graph.Node{Value: START}, &graph.Node{Value: BB2}) correctGraph[1].InsertEdge(&graph.Node{Value: BB2}, &graph.Node{Value: BB3}) correctGraph[1].InsertEdge(&graph.Node{Value: BB3}, &graph.Node{Value: BB4}) correctGraph[1].InsertEdge(&graph.Node{Value: BB3}, &graph.Node{Value: BB5}) correctGraph[1].InsertEdge(&graph.Node{Value: BB3}, &graph.Node{Value: BB6}) correctGraph[1].InsertEdge(&graph.Node{Value: BB3}, &graph.Node{Value: BB7}) correctGraph[1].InsertEdge(&graph.Node{Value: BB3}, &graph.Node{Value: BB8}) correctGraph[1].InsertEdge(&graph.Node{Value: BB4}, &graph.Node{Value: EXIT}) correctGraph[1].InsertEdge(&graph.Node{Value: BB5}, &graph.Node{Value: EXIT}) correctGraph[1].InsertEdge(&graph.Node{Value: BB6}, &graph.Node{Value: EXIT}) correctGraph[1].InsertEdge(&graph.Node{Value: BB7}, &graph.Node{Value: EXIT}) correctGraph[1].InsertEdge(&graph.Node{Value: BB8}, &graph.Node{Value: EXIT}) correctGraph[1].InsertEdge(&graph.Node{Value: EXIT}, &graph.Node{Value: START}) if err := VerifyControlFlowGraphs(expectedGraphs[0], correctGraph[0]); err != nil { t.Fatal(err) } if err := VerifyControlFlowGraphs(expectedGraphs[1], correctGraph[1]); err != nil { t.Fatal(err) } }