Пример #1
0
// 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
}
Пример #2
0
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)
	}
}
Пример #3
0
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)
	}
}
Пример #4
0
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)
	}
}
Пример #5
0
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)
	}
}
Пример #6
0
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)
	}
}
Пример #7
0
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)
	}
}
Пример #8
0
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)
	}
}
Пример #9
0
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)
	}
}
Пример #10
0
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)
	}
}
Пример #11
0
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)
	}
}
Пример #12
0
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)
	}
}
Пример #13
0
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)
	}
}
Пример #14
0
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)
	}
}