// getControlFlowGraph generates and returns the control-flow graph based on the array of basic blocks. func getControlFlowGraph(basicBlocks []*bblock.BasicBlock) *ControlFlowGraph { controlFlowGraph := New() var lastBlockAdded *bblock.BasicBlock startNode := &graph.Node{Value: bblock.NewBasicBlock(-1, bblock.START, 0)} exitNode := &graph.Node{Value: bblock.NewBasicBlock(-1, bblock.EXIT, 0)} for _, basicBlock := range basicBlocks { lastBlockAdded = basicBlock basicBlockNode := &graph.Node{Value: basicBlock} controlFlowGraph.InsertNode(basicBlockNode) if basicBlock.Type == bblock.RETURN_STMT { // RETURN_STMT terminates functior and methods, should therefor always have a edge to EXIT. controlFlowGraph.InsertEdge(&graph.Node{Value: basicBlock}, exitNode) } for _, successorBlock := range basicBlock.GetSuccessorBlocks() { controlFlowGraph.InsertEdge(basicBlockNode, &graph.Node{Value: successorBlock}) lastBlockAdded = successorBlock } } controlFlowGraph.InsertEdge(startNode, controlFlowGraph.Root) if lastBlockAdded.Type != bblock.RETURN_STMT { // Edge between RETURN_STMT and EXIT is already added higher up! controlFlowGraph.InsertEdge(&graph.Node{Value: lastBlockAdded}, exitNode) } controlFlowGraph.InsertEdge(exitNode, startNode) return controlFlowGraph }
func TestLooperBasicBlock(t *testing.T) { filePath := "./testcode/_looper.go" srcFile, err := ioutil.ReadFile(filePath) if err != nil { t.Fatal(err) } expectedBasicBlocks, err := bblock.GetBasicBlocksFromSourceCode(filePath, srcFile) if err != nil { t.Fatal(err) } BB0 := bblock.NewBasicBlock(0, bblock.FUNCTION_ENTRY, 8) BB1 := bblock.NewBasicBlock(1, bblock.FOR_STATEMENT, 11) BB2 := bblock.NewBasicBlock(2, bblock.FOR_BODY, 14) BB3 := bblock.NewBasicBlock(3, bblock.RETURN_STMT, 16) BB0.AddSuccessorBlock(BB1) BB1.AddSuccessorBlock(BB2, BB3) BB2.AddSuccessorBlock(BB1) correctBasicBlocks := []*bblock.BasicBlock{ BB0, BB1, BB2, BB3, } if err := verifyBasicBlocks(expectedBasicBlocks, correctBasicBlocks); err != nil { t.Fatal(err) } }
func TestIfElseBasicBlock(t *testing.T) { filePath := "./testcode/_ifelse.go" srcFile, err := ioutil.ReadFile(filePath) if err != nil { t.Fatal(err) } expectedBasicBlocks, err := bblock.GetBasicBlocksFromSourceCode(filePath, srcFile) if err != nil { t.Fatal(err) } 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, 24) BB0.AddSuccessorBlock(BB1) BB1.AddSuccessorBlock(BB2, BB3) BB2.AddSuccessorBlock(BB4) BB3.AddSuccessorBlock(BB4) correctBasicBlocks := []*bblock.BasicBlock{ BB0, BB1, BB2, BB3, BB4, } if err := verifyBasicBlocks(expectedBasicBlocks, correctBasicBlocks); err != nil { t.Fatal(err) } }
func TestSelectBasicBlock(t *testing.T) { filePath := "./testcode/_select.go" srcFile, err := ioutil.ReadFile(filePath) if err != nil { t.Fatal(err) } expectedBasicBlocks, err := bblock.GetBasicBlocksFromSourceCode(filePath, srcFile) if err != nil { t.Fatal(err) } BB0 := bblock.NewBasicBlock(0, bblock.FUNCTION_ENTRY, 12) BB1 := bblock.NewBasicBlock(1, bblock.GO_STATEMENT, 16) BB2 := bblock.NewBasicBlock(2, bblock.FOR_STATEMENT, 24) BB3 := bblock.NewBasicBlock(3, bblock.SELECT_STATEMENT, 26) BB4 := bblock.NewBasicBlock(4, bblock.COMM_CLAUSE, 28) BB5 := bblock.NewBasicBlock(5, bblock.RETURN_STMT, 31) BB6 := bblock.NewBasicBlock(6, bblock.RETURN_STMT, 34) BB0.AddSuccessorBlock(BB1) BB1.AddSuccessorBlock(BB2) BB2.AddSuccessorBlock(BB3, BB6) BB3.AddSuccessorBlock(BB2, BB4, BB5) BB4.AddSuccessorBlock(BB2) correctBasicBlocks := []*bblock.BasicBlock{ BB0, BB1, BB2, BB3, BB4, BB5, BB6, } if err := verifyBasicBlocks(expectedBasicBlocks, correctBasicBlocks); err != nil { t.Fatal(err) } }
func TestSimpleSwitchBasicBlock(t *testing.T) { filePath := "./testcode/_simpleswitch.go" srcFile, err := ioutil.ReadFile(filePath) if err != nil { t.Fatal(err) } expectedBasicBlocks, err := bblock.GetBasicBlocksFromSourceCode(filePath, srcFile) if err != nil { t.Fatal(err) } BB0 := bblock.NewBasicBlock(0, bblock.FUNCTION_ENTRY, 8) BB1 := bblock.NewBasicBlock(1, bblock.SWITCH_STATEMENT, 12) BB2 := bblock.NewBasicBlock(2, bblock.CASE_CLAUSE, 15) BB3 := bblock.NewBasicBlock(3, bblock.CASE_CLAUSE, 17) BB4 := bblock.NewBasicBlock(4, bblock.CASE_CLAUSE, 19) BB5 := bblock.NewBasicBlock(5, bblock.CASE_CLAUSE, 21) BB6 := bblock.NewBasicBlock(6, bblock.RETURN_STMT, 23) BB0.AddSuccessorBlock(BB1) BB1.AddSuccessorBlock(BB2, BB3, BB4, BB5, BB6) BB2.AddSuccessorBlock(BB6) BB3.AddSuccessorBlock(BB6) BB4.AddSuccessorBlock(BB6) BB5.AddSuccessorBlock(BB6) correctBasicBlocks := []*bblock.BasicBlock{ BB0, BB1, BB2, BB3, BB4, BB5, BB6, } if err := verifyBasicBlocks(expectedBasicBlocks, correctBasicBlocks); err != nil { t.Fatal(err) } }
func TestGreatestCommonDivisor(t *testing.T) { filePath := "./testcode/_gcd.go" srcFile, err := ioutil.ReadFile("./testcode/_gcd.go") if err != nil { t.Fatal(err) } expectedBasicBlocks, err := bblock.GetBasicBlocksFromSourceCode(filePath, srcFile) if err != nil { t.Fatal(err) } BB0 := bblock.NewBasicBlock(0, bblock.FUNCTION_ENTRY, 8) BB1 := bblock.NewBasicBlock(1, bblock.RETURN_STMT, 12) BB2 := bblock.NewBasicBlock(2, bblock.FUNCTION_ENTRY, 14) BB3 := bblock.NewBasicBlock(3, bblock.FOR_STATEMENT, 16) BB4 := bblock.NewBasicBlock(4, bblock.FOR_BODY, 19) BB5 := bblock.NewBasicBlock(5, bblock.RETURN_STMT, 20) BB0.AddSuccessorBlock(BB1) BB2.AddSuccessorBlock(BB3) BB3.AddSuccessorBlock(BB4) BB3.AddSuccessorBlock(BB5) BB4.AddSuccessorBlock(BB3) correctBasicBlocks := []*bblock.BasicBlock{ BB0, BB1, BB2, BB3, BB4, BB5, } if err := verifyBasicBlocks(expectedBasicBlocks, correctBasicBlocks); err != nil { t.Fatal(err) } }
func TestSingleBasicBlock(t *testing.T) { filePath := "./testcode/_simple.go" sourceFile, err := ioutil.ReadFile(filePath) if err != nil { t.Fatal(err) } expectedBasicBlocks, err := bblock.GetBasicBlocksFromSourceCode(filePath, sourceFile) if err != nil { t.Fatal(err) } BB0 := bblock.NewBasicBlock(0, bblock.FUNCTION_ENTRY, 8) BB1 := bblock.NewBasicBlock(1, bblock.RETURN_STMT, 11) BB0.AddSuccessorBlock(BB1) correctBasicBlocks := []*bblock.BasicBlock{BB0, BB1} if err := verifyBasicBlocks(expectedBasicBlocks, correctBasicBlocks); err != nil { t.Fatal(err) } }
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 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 TestNestedIfElseBasicBlock(t *testing.T) { filePath := "./testcode/_nestedifelse.go" srcFile, err := ioutil.ReadFile(filePath) if err != nil { t.Fatal(err) } expectedBasicBlocks, err := bblock.GetBasicBlocksFromSourceCode(filePath, srcFile) if err != nil { t.Fatal(err) } BB0 := bblock.NewBasicBlock(0, bblock.FUNCTION_ENTRY, 11) BB1 := bblock.NewBasicBlock(1, bblock.IF_CONDITION, 14) BB2 := bblock.NewBasicBlock(2, bblock.IF_CONDITION, 18) BB3 := bblock.NewBasicBlock(3, bblock.ELSE_CONDITION, 21) BB4 := bblock.NewBasicBlock(4, bblock.ELSE_BODY, 25) BB5 := bblock.NewBasicBlock(5, bblock.ELSE_CONDITION, 26) BB6 := bblock.NewBasicBlock(6, bblock.ELSE_BODY, 30) BB7 := bblock.NewBasicBlock(7, bblock.RETURN_STMT, 34) BB0.AddSuccessorBlock(BB1) BB1.AddSuccessorBlock(BB2, BB6) BB2.AddSuccessorBlock(BB3, BB4) BB3.AddSuccessorBlock(BB7) BB4.AddSuccessorBlock(BB7) BB5.AddSuccessorBlock(BB7) BB6.AddSuccessorBlock(BB7) correctBasicBlocks := []*bblock.BasicBlock{ BB0, BB1, BB2, BB3, BB4, BB5, BB6, BB7, } if err := verifyBasicBlocks(expectedBasicBlocks, correctBasicBlocks); err != nil { t.Fatal(err) } }
func TestNestedSwitchBasicBlock(t *testing.T) { filePath := "./testcode/_nestedswitch.go" srcFile, err := ioutil.ReadFile(filePath) if err != nil { t.Fatal(err) } expectedBasicBlocks, err := bblock.GetBasicBlocksFromSourceCode(filePath, srcFile) if err != nil { t.Fatal(err) } BB0 := bblock.NewBasicBlock(0, bblock.FUNCTION_ENTRY, 12) BB1 := bblock.NewBasicBlock(1, bblock.SWITCH_STATEMENT, 17) BB2 := bblock.NewBasicBlock(2, bblock.CASE_CLAUSE, 20) BB3 := bblock.NewBasicBlock(3, bblock.SWITCH_STATEMENT, 23) BB4 := bblock.NewBasicBlock(4, bblock.CASE_CLAUSE, 26) BB5 := bblock.NewBasicBlock(5, bblock.CASE_CLAUSE, 28) BB6 := bblock.NewBasicBlock(6, bblock.CASE_CLAUSE, 30) BB7 := bblock.NewBasicBlock(7, bblock.CASE_CLAUSE, 33) BB8 := bblock.NewBasicBlock(8, bblock.CASE_CLAUSE, 35) BB9 := bblock.NewBasicBlock(9, bblock.CASE_CLAUSE, 37) BB10 := bblock.NewBasicBlock(10, bblock.RETURN_STMT, 39) correctBasicBlocks := []*bblock.BasicBlock{ BB0, BB1, BB2, BB3, BB4, BB5, BB6, BB7, BB8, BB9, BB10, } BB0.AddSuccessorBlock(BB1) BB1.AddSuccessorBlock(BB2, BB3, BB7, BB8, BB9, BB10) BB2.AddSuccessorBlock(BB10) BB3.AddSuccessorBlock(BB4, BB5, BB6, BB10) BB4.AddSuccessorBlock(BB10) BB5.AddSuccessorBlock(BB10) BB6.AddSuccessorBlock(BB10) BB7.AddSuccessorBlock(BB10) BB8.AddSuccessorBlock(BB10) BB9.AddSuccessorBlock(BB10) if err := verifyBasicBlocks(expectedBasicBlocks, correctBasicBlocks); err != nil { t.Fatal(err) } }
func TestReturnSwitcherBasicBlock(t *testing.T) { filePath := "./testcode/_returnswitcher.go" srcFile, err := ioutil.ReadFile(filePath) if err != nil { t.Fatal(err) } expectedBasicBlocks, err := bblock.GetBasicBlocksFromSourceCode(filePath, srcFile) if err != nil { t.Fatal(err) } BB0 := bblock.NewBasicBlock(0, bblock.FUNCTION_ENTRY, 8) BB1 := bblock.NewBasicBlock(1, bblock.RETURN_STMT, 12) BB2 := bblock.NewBasicBlock(2, bblock.FUNCTION_ENTRY, 14) BB3 := bblock.NewBasicBlock(3, bblock.SWITCH_STATEMENT, 16) BB4 := bblock.NewBasicBlock(4, bblock.RETURN_STMT, 18) BB5 := bblock.NewBasicBlock(5, bblock.RETURN_STMT, 20) BB6 := bblock.NewBasicBlock(6, bblock.RETURN_STMT, 22) BB7 := bblock.NewBasicBlock(7, bblock.RETURN_STMT, 24) BB8 := bblock.NewBasicBlock(8, bblock.RETURN_STMT, 26) BB9 := bblock.NewBasicBlock(9, bblock.RETURN_STMT, 28) BB10 := bblock.NewBasicBlock(10, bblock.RETURN_STMT, 30) BB11 := bblock.NewBasicBlock(11, bblock.RETURN_STMT, 32) BB12 := bblock.NewBasicBlock(12, bblock.RETURN_STMT, 34) BB13 := bblock.NewBasicBlock(13, bblock.RETURN_STMT, 36) BB14 := bblock.NewBasicBlock(14, bblock.RETURN_STMT, 38) BB15 := bblock.NewBasicBlock(15, bblock.RETURN_STMT, 40) BB16 := bblock.NewBasicBlock(16, bblock.RETURN_STMT, 42) // Function main. BB0.AddSuccessorBlock(BB1) // Function monthNumberToString. BB2.AddSuccessorBlock(BB3) BB3.AddSuccessorBlock(BB4, BB5, BB6, BB7, BB8, BB9, BB10, BB11, BB12, BB13, BB14, BB15, BB16) correctBasicBlocks := []*bblock.BasicBlock{ BB0, BB1, BB2, BB3, BB4, BB5, BB6, BB7, BB8, BB9, BB10, BB11, BB12, BB13, BB14, BB15, BB16, } if err := verifyBasicBlocks(expectedBasicBlocks, correctBasicBlocks); err != nil { t.Fatal(err) } }
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) } }