Release notes#
score_coverage release notes
|
status: draft
security: NO
safety: ASIL_B
|
||||
0.3.1 (unreleased)#
In plain words#
Libraries tested from a test subpackage are measured on QNX. The
first QNX report of baselibs showed score/os at 13 % where Linux showed
80 %. The tests had run; their counters were thrown away on the way back.
Bazel decides which packages take part in a coverage run by guessing from
where the tests are, and it does not look one directory up from a test
subpackage. On Linux our own merger ignores that guess; on QNX Bazel’s own
collector obeys it. The fix is one line in the coverage config,
--instrumentation_filter=^//score[/:], now required by the user manual
for both backends. The reporters warn when a report shows the pattern
(files without data in a directory that is tested from test/ or
tests/), and the integration workspace contains such a library so the
case stays covered.
Details for integrators#
Add
--instrumentation_filter=^//<root package>[/:]to thecoverage:llvm_covand QNX configs (user manual, steps 4 and 4b). Without it a library without an instrumented direct dependency is compiled without counters on both backends, and on the gcov backend every library outside the guessed filter loses its counters.New warning in both reporters (
tool_req__coverage_instrumentation_hint, potential error ERR-13);known_problemsand the architecture’s design decisions corrected: the filter is not irrelevant, it must name the module.Integration workspace:
//lib:cross_pkgtested from//lib/test, in both goldens; a gcov run with the guessed filter checks the warning.Correction to the 0.3.0 notes: headers vendored from an external repository are measured on the gcov backend once the vendoring target is inside the instrumentation filter. The 0.3.0 statement described the guessed filter, which left the vendoring target uninstrumented. The gcov golden of the integration workspace now contains the vendored header.
0.3.0 (2026-09-28)#
In plain words#
Coverage of tests that run on QNX. Until now the tool measured only what
runs on the Linux host. QNX’s compiler (QCC) is GCC-based and produces gcov
counters instead of LLVM’s coverage mapping, and the tests run inside a QEMU
virtual machine. This release adds a second backend: the QNX runner of
score_qnx_unit_tests brings the counters back, Bazel’s own collector turns
them into per-test data, and score_coverage’s new gcov reporter produces the
same report as on Linux: the same HTML archive, the same LCOV file, the same
job summary, the same justifications and gate. A module declares one more
reporter target (backend = "gcov") and one bazelrc block; see the user
manual, step 4b.
What the QNX report does not contain: Rust sources (rustc cannot produce gcov counters; they are listed as not instrumentable and measured by the Linux run) and headers a module vendors from an external repository (Bazel’s collector drops them; also measured by the Linux run). gcov counts lines differently from LLVM (no unused inline functions, no closing braces), so the two reports are compared per file, not merged.
Validated with the S-CORE GCC toolchain on Linux, which takes exactly the same
collection path as QCC on QNX, against a hand-derived ground truth; the QNX
transport itself is the one communication has used since 2026.
Details for integrators#
New
score_coverage/gcov_reporter.py(//:gcov_reporter): sums per-test LCOV records, applies the scope, adds a zero-coverage baseline from the.gcnonotes of in-scope translation units, renders HTML and summary with gcovr 8.6 (new pip dependency), writesunmapped_files.txtwith the newnot-instrumentedcategory.score_coverage_reportergainedbackendandgcov;llvm_cov/llvm_profdataare required only for the LLVM backend. Existing consumer BUILD files need no change.score_coverage_scopewrites<name>_gcno.txtand exports thegcno/gcno_filesoutput groups.Integration workspace:
coverage:gcovconfig with the S-CORE GCC toolchain,expected_lcov_gcov.datground truth, gcov checks in the end-to-end script.New requirements
tool_req__coverage_scope_gcno,tool_req__coverage_backend_select,tool_req__coverage_gcov_merge,tool_req__coverage_gcov_baseline,tool_req__coverage_gcov_html; potential errors ERR-11 and ERR-12; constraint CSTR-11.
0.2.0 (2026-09-16)#
In plain words#
This release fixes what the first baselibs reports showed, and adds one new piece of information to every report.
Third-party code no longer leaks into a module’s report. A module that wraps a third-party library (baselibs wraps OpenSSL this way) got that library’s 72 header files counted as its own code, at 0 %. They are gone. Only files a module lists itself in its build targets are part of its report.
Every link in the HTML report opens. Some rows of the report pointed at
pages that had never been generated: files that Bazel generates during the
build and files from other repositories were not readable at the moment the
report was produced. The report now brings every source file along, so every
row opens. File names in the report are the paths of the source files, no
longer build-internal paths such as bazel-out/.../_virtual_includes/....
If a justification was written against such a build-internal path, it needs
the source path now.
Untested files that the old report could not show are listed. This is the new piece. A coverage tool can only measure files that were compiled into a test or a library. A file that nothing compiles has no lines to count, and llvm-cov cannot show it, not even at 0 %. Until now such files were simply absent from the report and nobody noticed. The report now lists them, see The file unmapped_files.txt below.
Headers tested through a test-only twin target are measured. A common
pattern declares a library’s headers a second time in a test-only target with
test flags (baselibs’ futurecpp_internal). Tests then compile the headers
through that second target, and the report did not recognise the result as
belonging to the library: 172 futurecpp headers appeared untested. They are
now attributed to the library’s declared header files.
More untested files show their 0 %. A library archive with one object that contains no code (typical for header-only libraries, see below) was rejected by llvm-cov as a whole, so the other files of that library lost their 0 % entries. This is fixed; in baselibs 15 files reappeared.
The file unmapped_files.txt#
The archive of every coverage run now contains unmapped_files.txt, and the
job summary shows the same information as a table row and three collapsible
sections. It lists every file that belongs to the module’s coverage scope but
for which no coverage data exists anywhere: no test and no library contains
compiled code from it. Such a file counts in no percentage. Each line reads
<category> TAB <file>; there are three categories.
Category |
What it means |
What to do |
|---|---|---|
|
The findings. Nothing in the module compiles this file: no source includes the header, or it holds only templates that no test ever uses with a concrete type. For a public API this means no test exercises it. It also catches headers that contain nothing executable (forward declarations, type traits, test mocks); the tool cannot tell those apart from unused API. |
Look at each file: write a test that uses it, remove it if nobody needs it, or note that it holds nothing testable. |
|
A header that only announces functions. The code behind it lives in a
source file with the same name ( |
Nothing. Listed for completeness. |
|
A source file that Bazel compiled but that contains no code of its
own, only |
Nothing. Listed for completeness. |
Two things this list is not: it is not part of the coverage percentage, and
it does not say why a no-data file was never compiled. That needs a
look at the file.
Details for integrators#
Fixed (eclipse-score/coverage_tool#5): a workspace rule that forwards the
CcInfoof a third-party library (e.g. a transition wrapper around OpenSSL) no longer puts that library’s headers into the scope; only headers a workspace target declares itself count.Fixed (eclipse-score/coverage_tool#5): every index link of the HTML report points at a generated page. The reporter stages the in-scope sources from the scope’s exported files instead of reading them through the workspace directory, where generated headers and external repositories are not present at report time.
Changed: headers compiled through
strip_include_prefix/include_prefixare reported under their declared path (e.g.score/flatbuffers/include/flatbuffers/base.horexternal/flatbuffers+/include/flatbuffers/base.h), no longer under the generated_virtual_includes/path. Justifications written against a_virtual_includes/path must be updated.Changed: HTML pages live at
coverage/<canonical path>.html; the archive contains no directory of the producing machine any more.New: in-scope files that carry no coverage data at all (a header nothing includes, template-only code that is never instantiated) are no longer silently absent. The reporter writes
text_report/unmapped_files.txtand warns;generate_coverage_htmlprints them, archives the list asunmapped_files.txtand adds a row and a section to the job summary (tool_req__coverage_report_unmapped). Declaration-only headers and placeholder sources compiled without code are categorised separately and are not findings.Fixed: a library archive with one member lacking a coverage mapping (the placeholder
.cppof a header-only library) was rejected byllvm-covas a whole, so the library’s other untested files silently lost their 0 % baseline. Archive members are now inspected and only those with a mapping are passed on, the way Rust rlibs were already handled (tool_req__coverage_report_rlib_expansionv2).Fixed: a
_virtual_includes/path of a target outside the scope (test-only twin of an in-scope library) is resolved to the allowlisted header with the same path tail instead of being excluded; ambiguous tails are warned about.Fixed: the exclusion filter matches each out-of-scope compiled file exactly; an excluded
foo/bar.hno longer suppresses an in-scopesrc/foo/bar.h.score_coverage_scopegained thepath_mapandsource_filesoutput groups;score_coverage_reporterpasses them to the reporter (--path_map). Consumers only instantiate the macros; no change needed.
0.1.0 (2026-09-11)#
First release as a standalone module, extracted from @score_tooling//coverage
(tooling commit 9a61f42).
Changes relative to the pipeline in score_tooling 2.2.x:
Consumer labels move to the module root:
@score_coverage//:defs.bzl,//:merger,//:generate_coverage_html,//:enable_llvm_coverage_for_death_tests.generate_coverage_htmlis Python and returns exit code 2 for runs without a verdict; the gate compares unrounded percentages; malformed thresholds and corrupt LCOV data are rejected.Justifications match files at path-component boundaries (a justification for
bar.cppno longer applies tofoobar.cpp).gcovr reports: the index totals of gcovr 8.x are read correctly without
--lcov;summary.txtis written for gcovr reports too.The repository-bound
combined_reportandllvm_profile_wrapperhelpers are not part of the module.Headers reached through
strip_include_prefix/include_prefix(Bazel’s_virtual_includes/tree) and headers a workspace target vendors from an external repository are now part of the coverage scope; the reporter normalises the configuration-specificbazel-out/<config>/bin/prefix and suppresses the duplicate baseline entry of such headers (eclipse-score/baselibs#558).
Known problems: see Known problems.