Code Coverage with SonarQube#

This guide explains how to build the project with gcov instrumentation, run the unit tests, and feed the resulting coverage data into SonarQube.


Prerequisites#

  • GCC toolchain with gcov (installed alongside g++)

  • CMake 3.20+

  • CUDA 12.x+ and TensorRT 10.x+

  • gcovr (required, generates SonarQube coverage reports) — install with pip install gcovr

  • sonar-scanner (for uploading results to SonarQube)


Quick Start#

A convenience script handles the full workflow — configure, build, test, and report — in a single command:

./scripts/run_coverage.sh --trt-package-dir /path/to/TensorRT

The TRT_PACKAGE_DIR can also be supplied as an environment variable:

export TRT_PACKAGE_DIR=/usr/local/TensorRT-10.x.x
./scripts/run_coverage.sh

After the script completes, coverage data is available in build_coverage/ and SonarQube can be run immediately with sonar-scanner.

Script Options#

Flag

Description

Default

--trt-package-dir <path>

Path to TensorRT installation (required unless TRT_PACKAGE_DIR is set)

--cuda-version <ver>

CUDA version to use

12.8

--build-dir <dir>

Build output directory

build_coverage

--gtest-filter <filter>

Google Test filter expression

* (all tests)

--jobs, -j <N>

Parallel build jobs

$(nproc)


Manual Workflow#

If you need finer control you can run each step individually.

1. Configure#

mkdir -p build_coverage
cmake -S . -B build_coverage \
    -DCMAKE_BUILD_TYPE=Debug \
    -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
    -DBUILD_UNIT_TESTS=ON \
    -DENABLE_COVERAGE=ON \
    -DTRT_PACKAGE_DIR=/path/to/TensorRT

The key CMake options for coverage are:

Option

Description

Default

ENABLE_COVERAGE

Enable gcov instrumentation (--coverage flags)

OFF

BUILD_UNIT_TESTS

Build the Google Test unit test binary

OFF

CMAKE_BUILD_TYPE

Must be Debug for accurate coverage

CMAKE_EXPORT_COMPILE_COMMANDS

Generate compile_commands.json (required by SonarQube)

OFF

Note: ENABLE_COVERAGE warns at configure time if CMAKE_BUILD_TYPE is not Debug, because compiler optimizations can cause misleading coverage results.

2. Build#

Build only the unit test target to keep compile times short:

cmake --build build_coverage --target unitTest -j$(nproc)

The build produces .gcno files alongside every object file. These contain the control-flow graph that gcov needs to map execution counts back to source lines.

3. Clear Stale Data#

If you are re-running tests after a previous coverage run, delete old .gcda files so results are not accumulated:

find build_coverage -name '*.gcda' -delete

4. Run Tests#

./build_coverage/unitTest \
    --gtest_output="xml:build_coverage/test_results.xml"

Running the instrumented binary produces .gcda files that record how many times each basic block was executed.

You can run a subset of tests with --gtest_filter:

./build_coverage/unitTest --gtest_filter="LoggerTest.*"

5. Generate Reports#

Use gcovr to convert the raw gcov data into reports. The SonarQube generic coverage XML (--sonarqube) is required for coverage import:

GCOVR_COMMON="--root . \
    --filter cpp/ \
    --filter unittests/ \
    --exclude 3rdParty/ \
    --exclude '.*\.cu$' \
    --gcov-ignore-errors=no_working_dir_found \
    --gcov-ignore-parse-errors=all"

# SonarQube generic coverage format (required for sonar.coverageReportPaths)
gcovr $GCOVR_COMMON \
    --sonarqube build_coverage/sonarqube-coverage.xml

# Cobertura XML (optional, for other CI integrations)
gcovr $GCOVR_COMMON \
    --xml-pretty \
    --output build_coverage/coverage.xml

# HTML with per-file detail (optional, for local viewing)
gcovr $GCOVR_COMMON \
    --html-details build_coverage/coverage.html

Open build_coverage/coverage.html in a browser for a quick local overview.


SonarQube Integration#

The project’s sonar-project.properties is pre-configured for coverage:

sonar.cfamily.compile-commands=build_coverage/compile_commands.json
sonar.coverageReportPaths=build_coverage/sonarqube-coverage.xml
  • sonar.coverageReportPaths points to the SonarQube generic coverage XML generated by gcovr --sonarqube. This is the format SonarQube uses to import line coverage data.

  • sonar.cfamily.compile-commands points to the compilation database so SonarQube can accurately parse the C++ source files.

  • build_coverage/** is not listed in sonar.sources to prevent SonarQube from scanning build artifacts (object files, HTML reports, etc.) as source code.

After a coverage build and test run, upload results with:

sonar-scanner

Tip: If your build directory is not build_coverage, override the properties on the command line:

sonar-scanner \
    -Dsonar.coverageReportPaths=my_build/sonarqube-coverage.xml \
    -Dsonar.cfamily.compile-commands=my_build/compile_commands.json

What Gets Instrumented#

  • C++ source files (.cpp) — fully instrumented with line and branch coverage.

  • CUDA files (.cu) — not instrumented. nvcc generates temporary stub files in /tmp/ during compilation that are deleted after the build. The resulting .gcno files contain unresolvable source references, which causes gcov and gcovr to fail. Coverage is therefore limited to .cpp files.

  • Third-party code (3rdParty/) — excluded from coverage reports via sonar.exclusions and gcovr --exclude filters.


CI Integration Example#

Below is a minimal CI job that produces coverage for SonarQube:

coverage:
  stage: test
  script:
    - pip install gcovr
    - ./scripts/run_coverage.sh --trt-package-dir $TRT_PACKAGE_DIR
    - sonar-scanner
  artifacts:
    paths:
      - build_coverage/sonarqube-coverage.xml
      - build_coverage/coverage.xml
      - build_coverage/coverage.html
      - build_coverage/test_results.xml
    reports:
      junit: build_coverage/test_results.xml

Troubleshooting#

gcov not found during CMake configure

gcov is part of the GCC toolchain. Install it with:

sudo apt install gcc

No .gcda files after running tests

  • Verify the binary was built with ENABLE_COVERAGE=ON (--coverage should appear in the compile commands).

  • Ensure the test binary runs to completion (or at least exits normally). Coverage data is flushed on exit().

Coverage percentages seem too low

  • Use CMAKE_BUILD_TYPE=Debug to prevent the compiler from optimizing away branches.

  • Make sure you cleared old .gcda files before the test run so you are not mixing stale data.

SonarQube shows 0% coverage

  • Confirm sonar.coverageReportPaths points to the sonarqube-coverage.xml file generated by gcovr --sonarqube.

  • Confirm sonar.cfamily.compile-commands points to a valid compile_commands.json generated by the same build.

  • Run sonar-scanner from the repository root so relative paths in sonar-project.properties resolve correctly.

  • Verify the source file paths inside sonarqube-coverage.xml match the files that SonarQube is analyzing (paths must be relative to the project root or absolute).