# covdbg 1.5.1: counts lines as OpenCppCoverage does

- Published: 2026-10-28
- Author: Rene Windegger
- Canonical: https://covdbg.com/announcing-covdbg-1-5-1/

---

**covdbg 1.5.1 is available.** It closes the gaps that kept teams on OpenCppCoverage: the tests' exit code is passed on to CI, lines can be left out by pattern or marker comment, assembly is measured, and the program runs even when nothing in it is measured. Lines are now counted the way OpenCppCoverage counts them, so the numbers carry over when you switch.

**In this release:** [Fail the CI step with your tests](#fail-the-ci-step-with-your-tests) · [Exclude lines](#exclude-lines) · [Assembly](#assembly-is-measured) · [Nothing measured](#tests-run-even-when-nothing-is-measured) · [Line counts](#lines-counted-as-opencppcoverage-counts-them) · [More in 1.5.1](#more-in-151) · [Upgrading](#moving-to-151)

## Fail the CI step with your tests

covdbg exits `0` once it has measured a run and written the database, also when the tests failed. Pass `--propagate-exit-code`, or set `COVDBG_PROPAGATE_EXIT_CODE=1`, and covdbg exits with the program's exit code instead, a crash's status included:

```powershell
covdbg --propagate-exit-code --config .covdbg.yaml --output tests.covdb tests.exe
```

The database is written first, so the steps after it can still convert and upload the coverage of a failing run with `if: always()`, and the job still fails. covdbg's own errors exit `1`. Below the program's output, covdbg now says how the program exited.

See [Exit Codes](/docs/reference/cli-reference/#exit-codes).

## Exclude lines

`exclude_lines` in `.covdbg.yaml` leaves out the lines its regular expressions match, as OpenCppCoverage's `--excluded_line_regex` does. The marker comments of lcov and gcovr work without any configuration: `LCOV_EXCL_LINE`, `LCOV_EXCL_START` ... `LCOV_EXCL_STOP`, the same with `GCOVR_` and `GCOV_`, `LCOV_UNREACHABLE_*` and `GCOVR_EXCL_FUNCTION`.

```cpp
if (!handle) {
    abort(); // LCOV_EXCL_LINE
}
```

See [Excluding Lines](/docs/reference/configuration/#excluding-lines).

## Assembly is measured

Code an assembler writes outside a procedure is measured like the rest: all of NASM's, such as the `.asm` files of a statically linked OpenSSL, and MASM's after a plain label. Each public label is a function in the report.

See [Assembly Outside Procedures](/docs/reference/cli-reference/#assembly-outside-procedures).

## Tests run even when nothing is measured

When nothing passes the coverage filter, covdbg now runs the program unmeasured, as OpenCppCoverage does. It says why nothing was measured, writes an empty database and exits `2`, or with the program's exit code under `--propagate-exit-code`. Before, the program did not run at all, so a filter mistake also hid your test results.

See [Nothing Measured](/docs/reference/cli-reference/#nothing-measured).

## Lines counted as OpenCppCoverage counts them

- **A line counts as run when its first instruction runs**, as OpenCppCoverage and a debugger stepping by line count it. A line after a call that throws is no longer reported covered, and MSVC's hidden-line markers are no longer reported as lines.
- **ONE_SHOT counts each line once.** A line counts `1` when any of its blocks ran, so a line of a template instantiated for 300 types is no longer reported with 300 hits.
- **Folded functions are functions of their own.** Each function the linker folds into one (`/OPT:ICF`) is reported by its own name and with the lines of its own source. This is why coverage databases move to schema 9. See [Folded Functions](/docs/reference/cli-reference/#folded-functions).
- **Every line at one address is reported**, such as a function's opening brace and its first statement in an optimized build.
- **Each line is judged by its own file.** `files:` filters each line by the file it is in, not by the function it sits in.

## More in 1.5.1

- **The program is found as `cmd` finds it.** A program named without a path is looked up in the working directory, then on `PATH` with the extensions in `PATHEXT`, so `covdbg --follow-children ctest` works. See [Finding the Program](/docs/reference/cli-reference/#finding-the-program).
- **Crash dumps beside the database.** A measured process that crashes leaves `crash_<program>_<pid>_<YYYYMMDD>_<HHMMSS>.dmp` in the directory of the `--output` database, and no dump replaces another. `--crash-dump-dir` and `--no-crash-dumps` change that. See [Crash Dumps](/docs/reference/cli-reference/#crash-dumps).
- **Breakpoints in the program.** A `__debugbreak()` that none of the program's own handlers takes no longer ends it: covdbg continues past it, as Visual Studio's "Continue" does. `--stop-on-break` ends the program there instead. See [Breakpoints in the program](/docs/reference/cli-reference/#breakpoints-in-the-program).
- **covdbg is hidden from the processes it measures.** `IsDebuggerPresent()` returns false in them, so googletest death tests under `--follow-children` no longer wait on the C runtime's assertion dialog.
- **Cobertura packages.** A source file compiled into several measured modules is listed in the package of each, as OpenCppCoverage lists it. See [Cobertura Format](/docs/guides/report-formats/#cobertura-format).
- **Faster merging.** A run's module databases, and `covdbg merge`, merge in seconds on large projects: 4.8 s instead of 99.6 s for one library's tests with 62,000 functions.
- **Names and paths ignore case as Windows does**, in `targets:` names, `files:` and `modules:` patterns, and the source paths `covdbg merge` matches. See [Target Matching](/docs/reference/configuration/#target-matching).
- **Clearer configuration errors.** A `.covdbg.yaml` that is not valid YAML, or has a value of the wrong shape, is refused with the key, its line and column. A key covdbg does not know gets a warning, with the key it likely meant. See [Configuration File Resolution](/docs/reference/configuration/#configuration-file-resolution).

## Moving to 1.5.1

1. Install covdbg 1.5.1. In GitHub Actions, set `version: '1.5.1'` on `liasoft/setup-covdbg`, which now installs the ARM64 build on ARM64 runners such as `windows-11-arm` by itself. See [Windows on ARM runners](/docs/integrations/github-actions/#windows-on-arm-runners).
2. **Record your coverage again.** Coverage databases are now schema 9. covdbg 1.5.1 refuses databases written by 1.5.0 or earlier, and 1.5.0 refuses those of 1.5.1, so update covdbg wherever databases are merged or converted too. See [Databases from Earlier Versions](/docs/reference/cli-reference/#databases-from-earlier-versions).
3. **List the executable under `modules:`.** With `modules: include:`, the program is measured only when a pattern selects it. A list of libraries alone, such as `include: ["mylib.dll"]`, now measures the libraries without the program: add the executable's name to measure it too. See [My executable is no longer measured](/docs/reference/troubleshooting/#my-executable-is-no-longer-measured).
4. **Check rooted `files:` patterns.** `**` itself, or a pattern with a `/` that does not start with `**/`, no longer matches paths outside the config's directory, so `include: ["**"]` no longer selects the MSVC runtime and Windows SDK sources. See [File Patterns](/docs/reference/configuration/#file-patterns).
5. **Update `.gitignore` for crash dumps.** An entry for `crash_dump_*.dmp` no longer matches the new names; `crash_*.dmp` does.
6. In CI, add `--propagate-exit-code` so a failing test run fails the step.

The full list of changes is in the [changelog](/docs/changelog/).

## Try it with your project

[Download covdbg](/download/) and follow the [quick-start guide](/docs/getting-started/quick-start/). If you are moving from OpenCppCoverage and something does not carry over, email [our support team](/company/contact/#email-addresses).
