Skip to content

main function missing in coverage report #40

Closed
eclipse-score/lifecycle
#804

Description

@NicolasFussberger

What

The file implementing the main function is not shown in the coverage report, even though it is part of the coverage scope. This makes the coverage report a bit misleading. The file has no existing unit test.

How to reproduce:

Acceptance Criteria (DoD)

bug accepted / rejected

How

No response

Activity

  1. NicolasFussberger commented on Oct 16, 2026

    @NicolasFussberger
    Author

    I learned now this is probably not specific to the main function, but is the same for any file which is not compiled because it has no test.

  2. dcalavrezo-qorix commented on Oct 16, 2026

    @dcalavrezo-qorix
    Contributor

    Accepted as a bug, and your follow-up is the right generalisation with one precision: the file is not missing because it has no test, it is missing because it is the own source of a cc_binary.

    What happens. main.cpp is in the scope: the lifecycle artifact lists it in unmapped_files.txt as no-data, so the aspect did collect it through the launch_manager alias. A file appears in the HTML at 0 % only when some baseline object carries coverage mapping for it. The aspect takes those baseline objects from the .a archives in a target's CcInfo linking context (coverage_scope.bzl, _coverage_scope_aspect_impl). A cc_binary links its own objects straight into the executable; main.o is in no archive and the executable itself is not collected, so there is no object with mapping for main.cpp, llvm-cov cannot list it, and it ends up in unmapped_files.txt instead of the report. Every untested library source in scope does get its 0 % row because its archive is collected; only the own sources of cc_binary targets are affected.

    Fix. Collect the coverage-built executable of a cc_binary as a baseline object, the way the aspect already does for rust_binary (CrateInfo.output). The reporter already passes all baseline objects to one llvm-cov --empty-profile call, which merges a file seen in both the executable and an archive, so no duplicate rows. Plus an end-to-end case: the consumer workspace has a rust_binary in scope but no cc_binary; adding one with an untested main.cpp pins the behaviour.

    I will put up the PR.

  3. dcalavrezo-qorix commented on Oct 16, 2026

    @dcalavrezo-qorix
    Contributor

    Fix in #44: the aspect now collects the coverage-built executable of a cc_binary as baseline object, so main.cpp appears at 0 %. The end-to-end workspace pins the case on both backends.

  4. dcalavrezo-qorix commented on Oct 16, 2026

    @dcalavrezo-qorix
    Contributor

    @NicolasFussberger could you have a look at the validation on lifecycle, eclipse-score/lifecycle#804 (draft, pinned to the fix by git_override)? Its Linux coverage artifact now lists score/launch_manager/src/daemon/src/main.cpp at 0 % and the file is gone from unmapped_files.txt. If that is what you expect, the fix goes out as 0.4.2 and lifecycle takes the version bump instead of the override.

  5. dcalavrezo-qorix commented on Oct 16, 2026

    @dcalavrezo-qorix
    Contributor

    Thanks, and good catch. Confirmed in the artifact: the LCOV says 0 of 3 lines for main.cpp, the HTML index says 100 % (3/3). The HTML is wrong.

    Cause: the HTML is produced by one llvm-cov show over the test binaries plus the baseline objects with the merged test profile. An executable brings a function called main, the one unmangled name every test binary also has. With the same structural hash as a test's main (two short, linear mains), llvm-cov attributes the test's execution counts to it, hence 100 %; with a different hash llvm-cov drops it as mismatched, which is what my end-to-end workspace shows (no row at all). The LCOV is right because baseline-only files are taken from a separate --empty-profile run. Library archives never contain main, so this did not show before.

    Fix, going into #44 before it merges: the HTML pages and index rows of baseline-only files come from their own --empty-profile run and are spliced into the report, mirroring what the LCOV path already does; the index totals, which the effective-coverage gate reads, are recomputed. The end-to-end test will check the index row of main.cpp at 0 %, not only the LCOV. I will update lifecycle#804 to the new commit when it is ready.

  6. dcalavrezo-qorix commented on Oct 16, 2026

    @dcalavrezo-qorix
    Contributor

    @NicolasFussberger the HTML is fixed on the PR branch and lifecycle#804 now points at it. Linux coverage run 38912573302 of that draft:

    functions lines branches
    score/launch_manager/src/daemon/src/main.cpp 0.00 % (0/1) 0.00 % (0/3) - (0/0)
    Totals 84.60 % (972/1149) 81.88 % (7923/9676) 71.35 % (1684/2360)

    HTML index row and LCOV agree now (LH:0), and the totals include the file. Cause and fix are in coverage_tool#44, second commit: baseline-only files are rendered in their own --empty-profile run and spliced into the index, so an executable's main can no longer pick up a test binary's counts.

  7. dcalavrezo-qorix commented on Oct 19, 2026

    @dcalavrezo-qorix
    Contributor

    Released in score_coverage 0.4.2 (https://github.com/eclipse-score/coverage_tool/releases/tag/v0.4.2), in the registry since today. lifecycle takes it in eclipse-score/lifecycle#804, which replaces the validation override with the version bump.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions