Skip to content

ci: the bank-sanitizers job has never passed — ctest lists no tests, and the checker hides why #690

Description

@Yaraslaut

Found during the landing sweep for PR #689, whose only failing leg turned out to be this one — pre-existing, not the branch's.

The finding

Bank example / UBSan, added by #683, has never passed. Both runs on master since it landed:

run 35643825635: failure
run 35639767288: failure

and it fails identically on PR #689. master is red on this leg right now.

What the job does and where it stops

Every step before it succeeds — Qt installs, Configure succeeds, Build succeeds — and then:

Run bash scripts/check_sanitizer_instrumentation.sh build/clang-ubsan ubsan
##[error]check_sanitizer_instrumentation: ctest listed no tests in build/clang-ubsan
         -- this check would pass having examined nothing
success  Configure (clang-ubsan, bank example + GUI)
success  Build
failure  Every ctest binary is instrumented
skipped  Test (bank's suites only)

The guard is behaving correctly — it refuses to report success having examined nothing, which is exactly what #675 added it for. The defect is that it has nothing to examine.

Verification status: reproduced on CI (three runs), contradicted locally

The same configure, run locally by the #683 lane and again during #684's review, enumerates fine:

check_sanitizer_instrumentation: 9 ctest binaries all carry __ubsan_ symbols (0 allowlisted).

So ctest --show-only finds nine binaries on a developer machine and zero on the runner, from the same preset and flags. I have not established why. What I did establish:

The checker hides the evidence, which is its own small defect

scripts/check_sanitizer_instrumentation.sh:129:

mapfile -t commands < <(
    ctest --test-dir "${build_dir}" --show-only=json-v1 2>/dev/null \
        | jq -r '.tests[]?.command[0]? // empty' | sort -u
)

2>/dev/null means "ctest failed" and "ctest found nothing" are indistinguishable to the caller. Whatever the root cause, the first fix is to stop discarding that stderr — the message we need is already being printed and thrown away.

Candidate causes, none confirmed

  1. DISCOVERY_MODE PRE_TEST — bank's three suites use it (examples/bank/CMakeLists.txt:255,318,385), so discovery runs the test binary at ctest time. If that execution fails on the runner (a missing Qt runtime path outside the Test step's environment, or UBSan aborting during static init), ctest errors and the pipeline yields nothing. Note tests/ also uses PRE_TEST and linux-sanitizers passes the same check — so PRE_TEST alone is not sufficient to explain it.
  2. noTestsAction: error in CMakePresets.json's base-test block, interacting with the above.

What would resolve it

  1. Remove the 2>/dev/null (or capture it and print on failure). One line, and it very likely names the cause on the next run.
  2. Then fix what it names.
  3. Prove it by making the job pass, not by making the check lenient. Weakening the floor to accept zero would recreate precisely the defect ci: check_sanitizer_instrumentation.sh refuses a single-target build tree, so it cannot verify the narrow case it is most needed for #675 closed.

What would change the verdict

Close as invalid if the job passes on a re-run — i.e. if all three failures were the same transient. Two consecutive master runs plus one PR run argues against that, but a re-run is cheap and would settle it.

Related

🤖 Generated with Claude Code

https://claude.ai/code/session_01VptDWG2fKr2vBnLSJcgzgW

Activity

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

    area: ciSubsystem: cibugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions