<feed xmlns='http://www.w3.org/2005/Atom'>
<title>catch3, branch fix/version-tool-semver</title>
<subtitle>Progmasoft Catch3: an independently maintained C++17 test framework with a parallel runner, property checks, snapshots and structured results.</subtitle>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/catch3/'/>
<entry>
<title>Number versions MAJOR.MINOR.PATCH in the version tool</title>
<updated>2026-11-14T19:03:45+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-11-14T19:03:45+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/catch3/commit/?id=2d21d2e0f9c6e0789e9c55d6cba611234dc61a60'/>
<id>2d21d2e0f9c6e0789e9c55d6cba611234dc61a60</id>
<content type='text'>
Progmasoft repositories use Semantic Versioning since 2026-11-12, but
//tools:version still knew the four-number counters: given 0.4.0 it
wrote 0.4.0.0 everywhere, and --next stepped the fourth number.

- A Version is three numbers; ParseVersion takes exactly three, without
  leading zeros, and FormatVersion writes three.
- --next is the next patch release. It also follows a four-number
  version as the rule says: the fourth number goes and the patch rises,
  so 0.3.0.2 is followed by 0.3.1.
- ReleaseNotesOf finds a section by the version it was published as.
  Its fallback for "D = 0" read the fourth element of what is now a
  three-element array; it is gone.
- Tests for the new parsing, NextPatch and release-note lookup;
  docs/contributing.md and the tool's usage say what the tool does.

Claude-Session: https://claude.ai/code/session_01Ji7xZMYjc4zankoc7hGBE1
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Progmasoft repositories use Semantic Versioning since 2026-11-12, but
//tools:version still knew the four-number counters: given 0.4.0 it
wrote 0.4.0.0 everywhere, and --next stepped the fourth number.

- A Version is three numbers; ParseVersion takes exactly three, without
  leading zeros, and FormatVersion writes three.
- --next is the next patch release. It also follows a four-number
  version as the rule says: the fourth number goes and the patch rises,
  so 0.3.0.2 is followed by 0.3.1.
- ReleaseNotesOf finds a section by the version it was published as.
  Its fallback for "D = 0" read the fourth element of what is now a
  three-element array; it is gone.
- Tests for the new parsing, NextPatch and release-note lookup;
  docs/contributing.md and the tool's usage say what the tool does.

Claude-Session: https://claude.ai/code/session_01Ji7xZMYjc4zankoc7hGBE1
</pre>
</div>
</content>
</entry>
<entry>
<title>Merge pull request #39 from Progmasoft/feature/per-test-coverage</title>
<updated>2026-11-14T13:46:04+00:00</updated>
<author>
<name>Leitwolf</name>
</author>
<published>2026-11-14T13:46:04+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/catch3/commit/?id=94a996a3ceafa9f0004ffc28a7de5c543cdb51c2'/>
<id>94a996a3ceafa9f0004ffc28a7de5c543cdb51c2</id>
<content type='text'>
Keep per-test coverage with --coverage (roadmap step 4)</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Keep per-test coverage with --coverage (roadmap step 4)</pre>
</div>
</content>
</entry>
<entry>
<title>Make the start lock a never-destroyed object</title>
<updated>2026-11-13T21:56:32+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-11-13T21:56:32+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/catch3/commit/?id=5ad02bccfcb925df02d1273901b6e248d477c5fa'/>
<id>5ad02bccfcb925df02d1273901b6e248d477c5fa</id>
<content type='text'>
A function-local static std::mutex has an exit-time destructor, which
the macOS build rejects with -Wexit-time-destructors. The lock is now
allocated once and never destroyed, which also keeps it usable by a
thread that starts a child while the process exits.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
A function-local static std::mutex has an exit-time destructor, which
the macOS build rejects with -Wexit-time-destructors. The lock is now
allocated once and never destroyed, which also keeps it usable by a
thread that starts a child while the process exits.
</pre>
</div>
</content>
</entry>
<entry>
<title>Merge branch 'devel' into feature/per-test-coverage</title>
<updated>2026-11-13T20:24:25+00:00</updated>
<author>
<name>Leitwolf</name>
</author>
<published>2026-11-13T20:24:25+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/catch3/commit/?id=826735e00bfac9967a7979eae5a42cb49eac851b'/>
<id>826735e00bfac9967a7979eae5a42cb49eac851b</id>
<content type='text'>
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
</pre>
</div>
</content>
</entry>
<entry>
<title>Start child processes one at a time; run gcov without a directory</title>
<updated>2026-11-13T20:24:10+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-11-13T20:24:10+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/catch3/commit/?id=b26486d68ece48a1dfdb208a9f3f1bd8acab0382'/>
<id>b26486d68ece48a1dfdb208a9f3f1bd8acab0382</id>
<content type='text'>
Reading the coverage profiles on several threads broke an assumption of
ChildProcess::Start on POSIX: it changes the working directory of the
whole process around posix_spawn. Two gcov runs started at once could
both run in one test's directory, so on the GCC job the map of
"Subtracts one" showed what "Adds one" reached.

- ChildProcess::Start holds a lock while a child starts, on POSIX and
  Windows, so the directory change and the handles a child inherits never
  overlap with another start.
- gcov gets the absolute path of the data file and no working directory,
  so no directory changes while profiles are read in parallel.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Reading the coverage profiles on several threads broke an assumption of
ChildProcess::Start on POSIX: it changes the working directory of the
whole process around posix_spawn. Two gcov runs started at once could
both run in one test's directory, so on the GCC job the map of
"Subtracts one" showed what "Adds one" reached.

- ChildProcess::Start holds a lock while a child starts, on POSIX and
  Windows, so the directory change and the handles a child inherits never
  overlap with another start.
- gcov gets the absolute path of the data file and no working directory,
  so no directory changes while profiles are read in parallel.
</pre>
</div>
</content>
</entry>
<entry>
<title>Fix the coverage review findings: branches, stale reports, exit status</title>
<updated>2026-11-13T18:55:26+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-11-13T18:55:26+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/catch3/commit/?id=454cca9b63991416f4d9bd1ca350f1ae14e278e7'/>
<id>454cca9b63991416f4d9bd1ca350f1ae14e278e7</id>
<content type='text'>
- gcov is run with --branch-probabilities; without it the JSON has no
  branches, so GCC runs had none in coverage.json and coverage.lcov.
- PrepareCoverageDirectory also removes coverage.json, coverage.lcov and
  coverage.profdata of an earlier run, so a run that writes no reports
  leaves none to be read as its own.
- WriteCoverageReports returns notes and failures apart. A profile the
  tools cannot read or a report that cannot be written counts as a missing
  report and fails a run whose tests passed; no profiles or missing tools
  stay notes. The paths are announced only for the reports written.
- ProfiledAttempt takes the last attempt whose profile exists, so a final
  retry or repeat that crashed before writing one no longer hides the
  coverage of the attempt before it.
- The per-test llvm-profdata/llvm-cov and gcov runs use as many threads
  as the run had workers; results keep the order of the tests.

Tests: earlier reports removed and no failure without profiles; an
attempt without a profile gives way to an earlier one; the fixture gains a
branch taken one way, checked in the combined LCOV for both LLVM and gcov.
Amalgamation regenerated.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
- gcov is run with --branch-probabilities; without it the JSON has no
  branches, so GCC runs had none in coverage.json and coverage.lcov.
- PrepareCoverageDirectory also removes coverage.json, coverage.lcov and
  coverage.profdata of an earlier run, so a run that writes no reports
  leaves none to be read as its own.
- WriteCoverageReports returns notes and failures apart. A profile the
  tools cannot read or a report that cannot be written counts as a missing
  report and fails a run whose tests passed; no profiles or missing tools
  stay notes. The paths are announced only for the reports written.
- ProfiledAttempt takes the last attempt whose profile exists, so a final
  retry or repeat that crashed before writing one no longer hides the
  coverage of the attempt before it.
- The per-test llvm-profdata/llvm-cov and gcov runs use as many threads
  as the run had workers; results keep the order of the tests.

Tests: earlier reports removed and no failure without profiles; an
attempt without a profile gives way to an earlier one; the fixture gains a
branch taken one way, checked in the combined LCOV for both LLVM and gcov.
Amalgamation regenerated.
</pre>
</div>
</content>
</entry>
<entry>
<title>Merge pull request #40 from Progmasoft/docs/guidelines-name</title>
<updated>2026-11-13T18:38:06+00:00</updated>
<author>
<name>Leitwolf</name>
</author>
<published>2026-11-13T18:38:06+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/catch3/commit/?id=586a42e35788d269871dcadbed2ec59b6b8a9203'/>
<id>586a42e35788d269871dcadbed2ec59b6b8a9203</id>
<content type='text'>
Name the style guide Progmasoft Core C++ Coding Guidelines</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Name the style guide Progmasoft Core C++ Coding Guidelines</pre>
</div>
</content>
</entry>
<entry>
<title>Convert LCOV line numbers explicitly and refresh the amalgamation</title>
<updated>2026-11-13T16:29:35+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-11-13T16:29:35+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/catch3/commit/?id=55dab34729c14c9019b7062fccd11fc22372e805'/>
<id>55dab34729c14c9019b7062fccd11fc22372e805</id>
<content type='text'>
- The 32-bit MSVC jobs failed on C4244: ParseLcov used the uint64_t it
  read as a std::size_t map key. The line number is now converted once,
  explicitly, before it is used.
- extras/catch_amalgamated.cpp is regenerated with
  bazelisk run //tools:amalgamate, so it holds CoverageReport and the
  scheduler changes; bazel run //tools:check passes locally.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
- The 32-bit MSVC jobs failed on C4244: ParseLcov used the uint64_t it
  read as a std::size_t map key. The line number is now converted once,
  explicitly, before it is used.
- extras/catch_amalgamated.cpp is regenerated with
  bazelisk run //tools:amalgamate, so it holds CoverageReport and the
  scheduler changes; bazel run //tools:check passes locally.
</pre>
</div>
</content>
</entry>
<entry>
<title>Name the style guide Progmasoft Core C++ Coding Guidelines</title>
<updated>2026-11-13T14:24:37+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-11-13T14:24:37+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/catch3/commit/?id=32edb5095ff950503eff95310654fc1070f2213a'/>
<id>32edb5095ff950503eff95310654fc1070f2213a</id>
<content type='text'>
Progmasoft/progmasoft-cpp renamed its guide from Progmasoft C++ Style.
The comments of .clang-format and the contributing guide use the new name; no rule or setting
changes.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Progmasoft/progmasoft-cpp renamed its guide from Progmasoft C++ Style.
The comments of .clang-format and the contributing guide use the new name; no rule or setting
changes.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Keep per-test coverage with --coverage (roadmap step 4)</title>
<updated>2026-11-13T04:46:08+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-11-13T04:46:08+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/catch3/commit/?id=17248837a78462596809f902dd47cf113a39670b'/>
<id>17248837a78462596809f902dd47cf113a39670b</id>
<content type='text'>
--coverage=DIR runs every attempt in a process of its own and keeps the
coverage of each test, for binaries built with LLVM source-based
coverage (Clang: -fprofile-instr-generate -fcoverage-mapping) or gcov
(GCC: --coverage).

How it works:

- The scheduler gives each attempt a fresh worker, as --isolate does,
  and sets LLVM_PROFILE_FILE and GCOV_PREFIX for it: the profile the
  process writes at exit is then the coverage of that one test, in
  DIR/profiles/t&lt;index&gt;-a&lt;attempt&gt;.profraw or a .gcov directory. Each
  runtime reads its own variable, so no symbol of either runtime is
  looked up: weak references would not pull them out of their static
  archives, and Mach-O does not allow undefined weak symbols.
- A process that runs other tests first (bisection) writes beside the
  profiles, never into one. The attempt records its profile, also in
  the JSON results.
- The profiles of an earlier run are removed when the run starts,
  because gcov adds to the .gcda files it finds.
- After the run, CoverageReport reads the last profile of every test:
  llvm-profdata and llvm-cov (PATH, xcrun on macOS, or
  CATCH3_LLVM_PROFDATA / CATCH3_LLVM_COV) export LCOV, gcov (or
  CATCH3_GCOV) writes JSON next to a copy of the .gcno. The result is
  DIR/coverage.json, the files, lines and branches each test reached,
  and DIR/coverage.lcov for the whole run. Without the tools the
  profiles stay and the run says so.
- --coverage with --in-process or --break is refused.

Tests: option parsing, LCOV reading and writing, gcov JSON, and an
integration test on CoverageFixture, a binary CMake builds with the
coverage flags of Clang or GCC: two tests reach different lines, each
map holds only its own, the LCOV report holds both, and a stale profile
of an earlier run is gone. Locally all 84 CTest tests pass with Clang,
and the coverage tests pass with GCC (built with
CATCH3_ENABLE_WERROR=OFF: Catch3 does not build with GCC's warnings as
errors, before and after this change).

CI: the Linux jobs install LLVM's coverage tools, a new job checks the
gcov path with GCC, and CATCH3_COVERAGE_REQUIRE_MAP turns a missing map
into a failure on Linux and macOS instead of a skip. MSVC has no
source-based coverage, so its builds skip those tests; the roadmap
lists step 4 as in progress until Windows with clang-cl is tested.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
--coverage=DIR runs every attempt in a process of its own and keeps the
coverage of each test, for binaries built with LLVM source-based
coverage (Clang: -fprofile-instr-generate -fcoverage-mapping) or gcov
(GCC: --coverage).

How it works:

- The scheduler gives each attempt a fresh worker, as --isolate does,
  and sets LLVM_PROFILE_FILE and GCOV_PREFIX for it: the profile the
  process writes at exit is then the coverage of that one test, in
  DIR/profiles/t&lt;index&gt;-a&lt;attempt&gt;.profraw or a .gcov directory. Each
  runtime reads its own variable, so no symbol of either runtime is
  looked up: weak references would not pull them out of their static
  archives, and Mach-O does not allow undefined weak symbols.
- A process that runs other tests first (bisection) writes beside the
  profiles, never into one. The attempt records its profile, also in
  the JSON results.
- The profiles of an earlier run are removed when the run starts,
  because gcov adds to the .gcda files it finds.
- After the run, CoverageReport reads the last profile of every test:
  llvm-profdata and llvm-cov (PATH, xcrun on macOS, or
  CATCH3_LLVM_PROFDATA / CATCH3_LLVM_COV) export LCOV, gcov (or
  CATCH3_GCOV) writes JSON next to a copy of the .gcno. The result is
  DIR/coverage.json, the files, lines and branches each test reached,
  and DIR/coverage.lcov for the whole run. Without the tools the
  profiles stay and the run says so.
- --coverage with --in-process or --break is refused.

Tests: option parsing, LCOV reading and writing, gcov JSON, and an
integration test on CoverageFixture, a binary CMake builds with the
coverage flags of Clang or GCC: two tests reach different lines, each
map holds only its own, the LCOV report holds both, and a stale profile
of an earlier run is gone. Locally all 84 CTest tests pass with Clang,
and the coverage tests pass with GCC (built with
CATCH3_ENABLE_WERROR=OFF: Catch3 does not build with GCC's warnings as
errors, before and after this change).

CI: the Linux jobs install LLVM's coverage tools, a new job checks the
gcov path with GCC, and CATCH3_COVERAGE_REQUIRE_MAP turns a missing map
into a failure on Linux and macOS instead of a skip. MSVC has no
source-based coverage, so its builds skip those tests; the roadmap
lists step 4 as in progress until Windows with clang-cl is tested.
</pre>
</div>
</content>
</entry>
</feed>
