Using Code Coverage

You can use the Code Coverage tool to measure how many lines of code a program executes and to discover which lines it executes. This is useful when running test cases (e.g., in unit testing) because it finds areas of code that aren't covered by your test cases and hence, may contain hidden bugs.

After running Code Coverage, you can use the analysis results to create additional test cases that increase the lines executed by your program and execute areas previously missed.

Block coverage

The Code Coverage tool uses the gcov metrics that the gcc compiler produces. The IDE presents these metrics in terms of which lines are fully covered, partially covered, and not covered at all, as well as percentages of the overall code covered.

Although gcc produces metrics for branch coverage, the IDE doesn't provide this information.

The metrics for basic block coverage report whether a particular block of code is executed. A block of code does not have any branch point within it, so the path of execution always enters at the beginning and exits at the end.

The IDE tracks the number of times that a block of code has been executed, and uses this information to determine the total coverage for a particular file or function. It also uses this information to show line coverage, by analyzing the blocks on each line and determining the level of coverage for each line.

How the Code Coverage tool works

The Code Coverage tool works with the compiler (gcc), the C library (libc), and optionally, the remote target agent (qconn). When Code Coverage is enabled for a program, the compiler instruments the code so that at run time, each branch execution to a basic block is counted. During the build, the IDE produces data files to recreate the program's flow graph and to provide line locations of each block.

CAUTION:
Since the IDE creates secondary data files at compilation time, you must be careful when building your programs in a multi-targeted build environment, such as QNX Neutrino.
You must either:
  • ensure that the last compiled binary is the one you're collecting coverage data on,

    or:

  • enable only one architecture and one variant (debug or release).

Also, the compiler optimizations could produce unexpected results, so you should perform coverage tests on an unoptimized, debug-enabled binary.

When you build an application with the Build with Code Coverage build option enabled and then launch it using a C/C++ QNX Qconn (IP) launch configuration, the instrumented code linked into the process connects to qconn, allowing the coverage data to be read from the process's data space.

If you want to instrument a static library to measure code coverage, you must also instrument your executable binary or link the library with the Code Coverage library by using the -lgcov option in the linker command. This option links in the $QNX_HOST/usr/lib/gcc/target/version/libcov.a library.

After a coverage session has begun, you can immediately view the data. The QNX Code Coverage perspective contains a Code Coverage Sessions view that lists previous as well as current sessions. You can explore each session and browse the corresponding source files that have received coverage data.

Note: For C++ projects, Code Coverage might not work as expected because the coverage data includes other functions that are also in the source file, such as static initializer and global constructor functions. In addition, the files included by include statements aren't included in the overall coverage total; only those functions in the original source are included.

Gathering coverage data outside of the IDE

If you run a coverage-built program outside of the IDE or you launch it in the IDE with coverage disabled in the launch configuration, this makes the process write the coverage information to a data file (.gcda) at run time, rather than sending it to qconn. Later, you can import the data into the Code Coverage tool. For information about doing so, see Importing GCC coverage data.