Constraints of use#

The correctness of the coverage figures depends on the environment and on how the tool is invoked. Each constraint below mitigates one of the potential errors in Potential errors; the Tool Verification Report refers to them by their anchors.

CSTR-01 Qualified environment#

Use the tool only in the environment it was validated in: Linux x86_64 host, Bazel 8.6, toolchains_llvm 1.8.0 with LLVM 22.1.7 for C++, the standard Ferrocene toolchain of score_toolchains_rust 0.10.0 or newer (built by ferrocene_toolchain_builder 1.3.1 or newer) for Rust; for the gcov backend the S-CORE GCC 12.2.0 toolchain (score_bazel_cpp_toolchains) on Linux and QCC of QNX SDP 8.0 with the tests executed through score_qnx_unit_tests (see CSTR-11). Mitigates ERR-08.

CSTR-02 Maintain the scope list#

List every shipped production library or binary in score_coverage_scope. A target missing from the list is not reported at all, not even at 0 %. Add new libraries when they are created; document exclusions in writing next to the target. For large repositories, run a completeness check comparing the reachable universe against the scope. Mitigates ERR-01.

CSTR-03 Run coverage with --build_tests_only#

Always invoke bazel coverage --config=llvm_cov <targets> --build_tests_only. Without the flag Bazel builds manual-tagged or incompatible test binaries, which fails or pollutes the run. Mitigates ERR-08.

CSTR-04 Do not combine with other toolchain configs#

Never combine --config=llvm_cov with a config that registers another C++ toolchain (for example a GCC host config). The last --extra_toolchains wins resolution; a GCC toolchain produces no covmap data and the run is rejected with exit 2. Mitigates ERR-08.

CSTR-05 Keep --dynamic_mode=off#

The canonical llvm_cov config disables dynamic linking. Per-test shared objects can carry clashing instrumentation between production and test code, and the first object loaded wins, causing flaky coverage gaps. Mitigates ERR-02.

CSTR-06 Pin dependencies#

Run CI with --lockfile_mode=error so the LLVM and Ferrocene versions that produced the evidence cannot drift silently. Mitigates ERR-08 and ERR-09.

CSTR-07 Review justifications#

A justification is a reviewed engineering argument. Every entry in the YAML needs an id, a category, the platforms it applies to and a written reason, and every change to the YAML or to COV_JUSTIFIED markers is reviewed like code. Remove justifications the report flags as stale. Mitigates ERR-04 and ERR-05.

CSTR-08 Check the baseline entries#

When a file is known to be untested, confirm it appears in the LCOV (coverage_report.dat) with an SF: record and LH:0. If an expected file is missing entirely, the baseline mechanism is broken; stop and diagnose instead of accepting the percentage. Mitigates ERR-01 and ERR-07.

CSTR-09 Archive the report with the verification report#

Use --archive-dir and upload the directory as the CI artifact. The archived coverage_report.dat and justification_report/ are the evidence a module verification report cites; the HTML alone is not sufficient. Mitigates ERR-09.

CSTR-10 Treat exit code 2 as a failed run#

Exit code 2 means the tool could not produce a verdict. CI must fail on it exactly like on exit code 1. Never map it to a pass. Mitigates ERR-03.

CSTR-11 QNX: run the tests through score_qnx_unit_tests and keep the collector#

On QNX the counters are written inside the QEMU guest. Only the run_under_qnx runner of score_qnx_unit_tests (0.2.0 or newer) brings them back: it sets GCOV_PREFIX in the guest, archives the counters at exit and extracts them into Bazel’s COVERAGE_DIR. The QNX coverage config must therefore use that runner, Bazel’s own per-test collector (--coverage_output_generator=@bazel_tools//tools/test:lcov_merger) and --instrument_test_targets, exactly as in the coverage:gcov block of the integration workspace. Check that the QNX report lists the same files as the Linux report of the same tree (Rust files excepted): a missing file is a lost transport, not a coverage result. Mitigates ERR-11.