Search code examples
clangcode-coveragelcov

Lcov not counting function toplines


I am using lcov to generate coverage information for the project I am working on. It is mostly working, except for some reason it seems to not count the function toplines in every single case. This means that class files that have complete test coverage will still have a few lines missing and so show like 90%.

It isn't a big deal but it is kind of annoying. I wonder if anyone has any idea why.

Below I've provided a complete minimal example demonstrating this problem. When this program is run, 4 lines are 'hit' out of 6 lines, leaving me with 68.7% line coverage, despite the fact that all lines are clearly executed.

GCOV output

Summary coverage rate:
  lines......: 66.7% (4 of 6 lines)
  functions..: 100.0% (2 of 2 functions)
  branches...: no data found

Example

CMakeLists.txt

set(NAME MinTest)

project (${NAME})

cmake_minimum_required(VERSION 3.5.2)

set(CMAKE_C_FLAGS
"--coverage -O0 -g")

add_executable(
  ${NAME}
  src/main.c
)

src/main.c

void function() {
  printf("foo");
}

int main(void) {
  function();
}

runWithCoverageInfo.sh

#!/bin/bash

# $1 = source root
# $2 = build directory

if [ ! -d "coverage" ]; then
    echo "Creating coverage directory...";
    mkdir coverage;
else
    find ./coverage -name *.info -exec rm {} \;;
fi;

echo "Removing previous coverage output files...";
find $2 -name *.gcda -exec rm {} \;;

echo "Analysing baseline coverage data...";
lcov --initial --no-external --capture --base-directory $2 --directory $2 --directory $1 --output-file coverage/coverage_base.info ;

echo "Running tests...";
./MinTest;
returnCode=$?

echo "Generating coverage output";
lcov --capture  --no-external --directory $2 --directory $1 --base-directory $2 --output-file coverage/coverage_test.info --quiet ;
lcov -a coverage/coverage_base.info -a coverage/coverage_test.info -output-file coverage/coverage_total.info --quiet;
lcov --summary coverage/coverage_total.info;
genhtml coverage/coverage_total.info --output-directory coverage -quiet;

exit $returnCode;

Solution

  • Once upon a time, LCOV defaulted to providing branch coverage. It does not anymore. (At least, the version I have [1.12] does not.) So you have to explicitly tell it in your lcov and genhtml commands to generate branch reports. For example:

    lcov -d . --zerocounters
    lcov -d . --rc lcov_branch_coverage=1 --no-external --capture -o ../reports/myproj.info
    cd ../reports
    genhtml --branch-coverage myproj.info
    

    The --rc lcov_branch_coverage=1 in the LCOV command and --branch-coverage in the HTML generation command are required for branch coverage analysis/reporting.

    You could opt to put lcov_branch_coverage=1 and genhtml_branch_coverage=1 in your .lcovrc resource file if you want to always default to branch coverage. See lcovrc(5) manpage for more details, or online here: http://ltp.sourceforge.net/coverage/lcov/lcovrc.5.php