Using Gcov and Lcov to generate Test Coverage Stats for Cppagent

In my last post we generated Code coverage statistics for a sample c++. In this post i will be using gcov & lcov to generate similar code coverage for tests in cppagent. To use gcov we first need to compile the source files with --coverage flag. Our sample c++ program was a single file so it was easy to compile, but for cppagent they use makefiles to build the project. Hence, i started with the Makefile looking for the build instructions.

If my previous posts i discussed the steps for building the agent_test executable, which starts by running make command in test folder. So i started tracing the build steps from the Makefile in test folder. Since we run make without any parameters, the default target is going to be executed.

The first few lines of the file were as below.

# Default target executed when no arguments are given to make.

default_target: all

.PHONY : default_target

These lines specifies that the default_target for this build is all. On moving down the file we see the rules for all.

# The main all target

all: cmake_check_build_system

cd /home/subho/work/github/cppagent_new/cppagent && $(CMAKE_COMMAND) -E cmake_progress_start /home/subho/work/github/cppagent_new/cppagent/CMakeFiles /home/subho/work/github/cppagent_new/cppagent/test/CMakeFiles/progress.marks

cd /home/subho/work/github/cppagent_new/cppagent && $(MAKE) -f CMakeFiles/Makefile2 test/all

$(CMAKE_COMMAND) -E cmake_progress_start /home/subho/work/github/cppagent_new/cppagent/CMakeFiles 0

.PHONY : all

So here in the line

cd /home/subho/work/github/cppagent_new/cppagent && $(MAKE) -f CMakeFiles/Makefile2 test/all

We can see Makefile2 is invoked with target test/all.

In Makefile2 towards the end of the file we can see the test/all target build instructions as,

# Directory level rules for directory test

# Convenience name for "all" pass in the directory.

test/all: test/CMakeFiles/agent_test.dir/all

.PHONY : test/all

The rule says to run the commands defined under target test/CMakeFiles/agent_test.dir/all. These commands are:

test/CMakeFiles/agent_test.dir/all:

$(MAKE) -f test/CMakeFiles/agent_test.dir/build.make test/CMakeFiles/agent_test.dir/depend

$(MAKE) -f test/CMakeFiles/agent_test.dir/build.make test/CMakeFiles/agent_test.dir/build

$(CMAKE_COMMAND) -E cmake_progress_report /home/subho/work/github/cppagent_new/cppagent/CMakeFiles 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58

@echo "Built target agent_test"

.PHONY : test/CMakeFiles/agent_test.dir/all

The first two lines run the build.make file with target ‘test/CMakeFiles/agent_test.dir/depend‘ and ‘test/CMakeFiles/agent_test.dir/build‘ . The build.make contains all the compile instructions for each of the c++ files. This file is in ‘test/CMakeFiles/agent_test.dir’ folder along with flag.make , link.txt etc files. The  flag.make file contains all the compile flags and the ‘link.txt‘ contains the libraries flag needed by linker. On adding the --coverage flag to these files we can make the c++ source files compile with gcov linked hence .gcno files are generated when the make command is run.

After that we need to run the agent_test as usual. This will create the data files .gcda files. After that we need to gather the .gcda and .gcno files together and run the lcov and genhtml commands and then the html output will be obtained.

This slideshow requires JavaScript.

Using Gcov and Lcov to generate Test Coverage Stats for Cppagent

Using Gcov and Lcov to generate beautiful C++ code coverage statistics

We all know, testing is an important part of a project. But how efficient are your tests? How much of your codes have you tested? Here comes the role of code coverage tools. I recently got to work on a C++ project, and a code coverage tool (gcov and lcov) .

In this post i have taken a sample C++ program and will be generating the code coverage stats for the same using gcov and lcov. Here is my sample C++ program link. Its pretty simple menu driven program that does simple mathematical operations like addition, subtraction, multiplication and division depending on users choice.

In this demo i am not writing actual test-cases for the code but you can see the changes in the coverage graphs depending upon your choice.

To start with we need to install gcov. Gcov comes with gcc compiler. So if you have gcc installed then gcov will work for you. Next you need to have lcov. I am working on Fedora 21, so for me its a yum install.

$yum install lcov

Next lets start with compiling our code. Here my source file name is menu.cpp

$g++ -o menu.out --coverage menu.cpp

The –coverage option here is used to compile and link code needed for coverage analysis. You will find a menu.gcno file in the folder. Next we need to export two variables namely GCOV_PREFIX and GCOV_PREFIX_STRIP. Set GCOV_PREFIX to the folder you want the output files to be in.

$ls
menu.cpp  menu.out  menu.gcno  data    // you can see the new file menu.gcno

For me , the project is in  “/home/subho/work/lab/zzz/” and  inside this i have created a folder named data where i want the data files or .gcda file to be generated. so i set my GCOV_PREFIX to “/home/subho/work/lab/zzz/data” and the GCOV_PREFIX_STRIP equal to the the number of forward slashes or “/” in the path.

$export GCOV_PREFIX="/home/subho/work/lab/zzz/data"
$export GCOV_PREFIX_STRIP=6

now lets simply run the code.

$./menu.out

MENU
1: Add
2: Subtract
3: Multiply
4: Divide
5: Exit
Enter your choice :2
Enter two numbers: 3 4
Difference -1
MENU
1: Add
2: Subtract
3: Multiply
4: Divide
5: Exit
Enter your choice :5

Now we can see a menu.gcda file in data folder. Copy the .gcno file generated earlier to the data folder.


$cd data

$ls

menu.gcda

$cp ../menu.gcno .

$ls

menu.gcda  menu.gcno

Now that we have all the necessary files lets use lcov to read the coverage output file generated by gcov.

$lcov -t "result" -o ex_test.info -c -d .

Here ex_test.info is my output file.

-t     sets a test name

-o    to specify the output file

-c    to capture the coverage data

-d    to specify the directory where the data files needs to be searched

Now we will generate out html output for the statistics.

$genhtml -o res ex_test.info 

-o    To specify the output folder name.

Now on doing ls, you can see a folder named “res“.

$ls
ex_test.info   menu.gcda   menu.gcno   res

Now its time to enjoy the fruits of your labor 😛 . Go into the res folder and start a server or you can simply open the index.html file in your web-browser.

$cd res
$python -m "SimpleHTTPServer"     //to start a web-server  or
$firefox index.html               //to open the index.html directly using firefox browser

Now we can click on the links to check the code coverage stats. The Red lines are the ones not executed or uncovered region. The blue lines are the ones covered. Also you can look at the Line data section for the number of times the lines have been executed. 
You can look at these files in GitHub.

This slideshow requires JavaScript.

Using Gcov and Lcov to generate beautiful C++ code coverage statistics