Code coverage using gcov/lcov in Linux

In this post, code coverage stats will be generated using gcov/lcov tools of a simple program (main.cpp). This program is straight forward as listed below.

  • If executed without command line parameters, it prints out the program usage
  • If execute with parameter 1, it prints out “Executed testcase 1
  • If execute with any parameter other than 1, it prints out “Executed testcase 2

#include <cstdlib>
#include <iostream>

// sample program to demonstrate coverage
int main(int argc, char *argv[]) {
  if (argc < 2) {
    std::cout << "usage: %s <test case number> " << std::endl;
    return 0;
  }

  int testcase_num = atoi(argv[1]);

  if (testcase_num == 1)
    std::cout << "Executed testcase 1" << std::endl;
  else
    std::cout << "Executed testcase 2" << std::endl;
}

Enable coverage compile/link flags

g++ -o main -fprofile-arcs -ftest-coverage main.cpp 
OR
g++ -o main --coverage main.cpp 

Note: main.gcno gets generated during compilation

Execute the program

./main 1
output:
Executed testcase 1

Note: main.gcda gets generated during execution

Generate coverage report using gcov

gcov main.cpp

This will generated main.cpp.gcov file. But this is not very intuitive for an average person.

Generate coverage report using lcov

lcov --capture --directory . --output-file main1.info
OR 
geninfo  . -o ./main1.info

Coverage report main1.info is created using .gcno and .gcda files from current directory

Generate html report

genhtml main1.info --output-directory out

Html reports are generated in out directory and can be visualized using browser. It will display coverage percent along with functions & line coverage.

google-chrome out/index.html

Fig 1: Coverage report with testcase 1

Note: In the above coverage report, only “if” block is executed.

Merging multiple coverage files

In the above sections, coverage reports were generated by passing command line parameter 1. Now, the program is execute again with parameter 2.

./main 2
output:
Executed testcase 2

Coverage report is again generated as main2.info

lcov --capture --directory . --output-file main2.info

Both the coverage reports (main1.info, main2.info) is merged.

lcov -a main1.info -t test1 -a main2.info -t test2 -o merged.info

Finally, generated html reports for merged coverage

genhtml merged.info --output-directory out
Fig 2: Coverage report with testcase 1 & 2

In the above coverage report, both “if & else” blocks are executed.