<feed xmlns='http://www.w3.org/2005/Atom'>
<title>catch3/xmake.lua, branch build/bcr</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>License Catch3's Progmasoft files under LGPL-3.0-or-later</title>
<updated>2026-11-15T11:01:10+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-11-15T11:01:10+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/catch3/commit/?id=5c865488e762dec616a0c483d0fc07250123c387'/>
<id>5c865488e762dec616a0c483d0fc07250123c387</id>
<content type='text'>
Every Progmasoft-authored file moves from MPL-2.0 WITH
AdditionRef-Progmasoft-Exception-2.0 to LGPL-3.0-or-later, from 0.5.0
on. Catch2-originated files keep BSL-1.0, and the vendored yyjson and
pugixml keep MIT.

- LICENSES/ holds the LGPL-3.0 text and the GPL-3.0 text it builds on,
  both as published by the FSF; the MPL-2.0 and Progmasoft Exception
  texts go, since no file uses them any more.
- Five files that came from Catch2 and were rewritten by Progmasoft
  (.clang-format, the issue and pull request templates, SECURITY.md)
  keep Catch2's notice next to Progmasoft's and say
  LGPL-3.0-or-later AND BSL-1.0.
- //tools:check expects the new header of Progmasoft files; the
  amalgamation notes say LGPL-3.0-or-later and the amalgamated files
  are regenerated; meson's project license is BSL-1.0 and
  LGPL-3.0-or-later.
- README gains a License section; LICENSES/README.md, contributing.md
  and progmasoft-catch3.md describe the new split and that releases
  before 0.5.0 keep the license they were published under.

Every commit to Progmasoft's files since the fork is the maintainer's.

Claude-Session: https://claude.ai/code/session_01Ji7xZMYjc4zankoc7hGBE1
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Every Progmasoft-authored file moves from MPL-2.0 WITH
AdditionRef-Progmasoft-Exception-2.0 to LGPL-3.0-or-later, from 0.5.0
on. Catch2-originated files keep BSL-1.0, and the vendored yyjson and
pugixml keep MIT.

- LICENSES/ holds the LGPL-3.0 text and the GPL-3.0 text it builds on,
  both as published by the FSF; the MPL-2.0 and Progmasoft Exception
  texts go, since no file uses them any more.
- Five files that came from Catch2 and were rewritten by Progmasoft
  (.clang-format, the issue and pull request templates, SECURITY.md)
  keep Catch2's notice next to Progmasoft's and say
  LGPL-3.0-or-later AND BSL-1.0.
- //tools:check expects the new header of Progmasoft files; the
  amalgamation notes say LGPL-3.0-or-later and the amalgamated files
  are regenerated; meson's project license is BSL-1.0 and
  LGPL-3.0-or-later.
- README gains a License section; LICENSES/README.md, contributing.md
  and progmasoft-catch3.md describe the new split and that releases
  before 0.5.0 keep the license they were published under.

Every commit to Progmasoft's files since the fork is the maintainer's.

Claude-Session: https://claude.ai/code/session_01Ji7xZMYjc4zankoc7hGBE1
</pre>
</div>
</content>
</entry>
<entry>
<title>Release Catch3 0.4.0</title>
<updated>2026-11-15T09:17:43+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-11-15T09:17:43+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/catch3/commit/?id=6f4d3fa3328d6fb78f9a41f45282c11758872c9c'/>
<id>6f4d3fa3328d6fb78f9a41f45282c11758872c9c</id>
<content type='text'>
Every place that states the version says 0.4.0, written by
bazelisk run //tools:version -- 0.4.0, and the single-file distribution
carries it. The release notes describe the release: per-test coverage
with --coverage, secret-looking variables withheld from workers unless
--pass-env names them, the repository tools in C++17 under Bazel, and
versions with three numbers again.

Claude-Session: https://claude.ai/code/session_01Ji7xZMYjc4zankoc7hGBE1
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Every place that states the version says 0.4.0, written by
bazelisk run //tools:version -- 0.4.0, and the single-file distribution
carries it. The release notes describe the release: per-test coverage
with --coverage, secret-looking variables withheld from workers unless
--pass-env names them, the repository tools in C++17 under Bazel, and
versions with three numbers again.

Claude-Session: https://claude.ai/code/session_01Ji7xZMYjc4zankoc7hGBE1
</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>
<entry>
<title>Release Catch3 0.3.0.2</title>
<updated>2026-11-01T18:42:34+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-11-01T18:42:34+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/catch3/commit/?id=e1b0a9d000645b5e914f00603983df16167bd053'/>
<id>e1b0a9d000645b5e914f00603983df16167bd053</id>
<content type='text'>
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
</pre>
</div>
</content>
</entry>
<entry>
<title>Add mocks that report through the assertion path</title>
<updated>2026-11-01T16:04:52+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-11-01T16:04:52+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/catch3/commit/?id=c51d15273e87267215e5877edc268e7db354187b'/>
<id>c51d15273e87267215e5877edc268e7db354187b</id>
<content type='text'>
Step 3 of the roadmap. MockFunction checks the calls of one function
against its expectations; CATCH3_MOCK_METHOD declares one for a virtual
member, and CATCH3_MOCK_FUNCTION and ScopedSeam serve free functions
behind a seam.

Expectations take values, Catch matchers, Any or Where; count calls with
Times, Between, AtLeast, AtMost, AnyTimes and Never; answer with Returns,
Does or Throws; and order calls across mocks with Sequence. A failure
goes through AssertionHandler at the line of the expectation, so every
report of the runner shows it. Met expectations count as passed
assertions. A test case that is already being left does not get unmet
expectations on top of its own failure.

Composed matchers refer to temporaries, so they are rejected at compile
time rather than left dangling. A call that fails returns a
value-initialized result, or leaves the test case when no such result
exists.

The failure paths are tested through the runner fixture, reading the
messages from its JSON report.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Step 3 of the roadmap. MockFunction checks the calls of one function
against its expectations; CATCH3_MOCK_METHOD declares one for a virtual
member, and CATCH3_MOCK_FUNCTION and ScopedSeam serve free functions
behind a seam.

Expectations take values, Catch matchers, Any or Where; count calls with
Times, Between, AtLeast, AtMost, AnyTimes and Never; answer with Returns,
Does or Throws; and order calls across mocks with Sequence. A failure
goes through AssertionHandler at the line of the expectation, so every
report of the runner shows it. Met expectations count as passed
assertions. A test case that is already being left does not get unmet
expectations on top of its own failure.

Composed matchers refer to temporaries, so they are rejected at compile
time rather than left dangling. A call that fails returns a
value-initialized result, or leaves the test case when no such result
exists.

The failure paths are tested through the runner fixture, reading the
messages from its JSON report.
</pre>
</div>
</content>
</entry>
<entry>
<title>Release Catch3 0.3.0.1</title>
<updated>2026-11-01T13:20:17+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-11-01T13:20:17+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/catch3/commit/?id=64e7fffb605cc355d258f4896c49cdec6127ed6b'/>
<id>64e7fffb605cc355d258f4896c49cdec6127ed6b</id>
<content type='text'>
Versions have four numbers from this release on.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Versions have four numbers from this release on.
</pre>
</div>
</content>
</entry>
<entry>
<title>Import the results of other test frameworks</title>
<updated>2026-11-01T11:23:09+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-11-01T11:23:09+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/catch3/commit/?id=1db203d56b7c71db3d80b477da1ad49e9ae46468'/>
<id>1db203d56b7c71db3d80b477da1ad49e9ae46468</id>
<content type='text'>
Tests Catch3 does not run had no history, flaky detection or quarantine.
--import=FILE reads a report instead of running tests and sends it through
the analysis, history and reports of a run: JUnit with Surefire's reruns,
xUnit.net v2, TRX, TAP 12 to 14, CTRF, Catch3's own --json report and
catch3-results, a small JSON Lines format for tools with none of these.

Results that share an identifier are attempts at one test, so a report of a
rerun gives a flaky test. --import-revision says what was tested: a verdict
that changes on one revision also counts as flaky. --import-name keeps the
results in a history of their own, which --analytics reads too. A TAP stream
that ends early fails instead of reading as a run that passed.

The amalgamation script now accepts a relative include of the third-party
wrappers, because pugixml is included from a second directory.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Tests Catch3 does not run had no history, flaky detection or quarantine.
--import=FILE reads a report instead of running tests and sends it through
the analysis, history and reports of a run: JUnit with Surefire's reruns,
xUnit.net v2, TRX, TAP 12 to 14, CTRF, Catch3's own --json report and
catch3-results, a small JSON Lines format for tools with none of these.

Results that share an identifier are attempts at one test, so a report of a
rerun gives a flaky test. --import-revision says what was tested: a verdict
that changes on one revision also counts as flaky. --import-name keeps the
results in a history of their own, which --analytics reads too. A TAP stream
that ends early fails instead of reading as a run that passed.

The amalgamation script now accepts a relative include of the third-party
wrappers, because pugixml is included from a second directory.
</pre>
</div>
</content>
</entry>
<entry>
<title>Say C++17 everywhere the project describes itself</title>
<updated>2026-10-31T21:25:59+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-10-31T21:25:59+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/catch3/commit/?id=ff1da91edffa9ee887e9fe737fcd87ec540dfa60'/>
<id>ff1da91edffa9ee887e9fe737fcd87ec540dfa60</id>
<content type='text'>
The move to C++17 left a trail of older claims. The Runner's own
.clang-format still said c++20; the result is byte for byte the same under
either value. Premake and Xmake still compiled the library as C++20 and
the main library as C++14, which meant their CI jobs were not testing the
language the project promises. Both now use C++17 for every target.

The rest is text: the Meson pkg-config description claimed C++14, comments
in the CMake and Meson files explained requirements that no longer exist,
.clang-tidy gave C++14 as the reason for two exclusions, issue templates
asked for C++20 samples, and the example headers named -std=c++14 and
catch2-with-main. The release notes and the migration guide state the
C++17 minimum. Doxygen's brief called the project "Catch2's test API",
which presents it as Catch2. Meson declared only BSL-1.0; it now names both
licenses of the tree. The amalgamated files are regenerated.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The move to C++17 left a trail of older claims. The Runner's own
.clang-format still said c++20; the result is byte for byte the same under
either value. Premake and Xmake still compiled the library as C++20 and
the main library as C++14, which meant their CI jobs were not testing the
language the project promises. Both now use C++17 for every target.

The rest is text: the Meson pkg-config description claimed C++14, comments
in the CMake and Meson files explained requirements that no longer exist,
.clang-tidy gave C++14 as the reason for two exclusions, issue templates
asked for C++20 samples, and the example headers named -std=c++14 and
catch2-with-main. The release notes and the migration guide state the
C++17 minimum. Doxygen's brief called the project "Catch2's test API",
which presents it as Catch2. Meson declared only BSL-1.0; it now names both
licenses of the tree. The amalgamated files are regenerated.
</pre>
</div>
</content>
</entry>
<entry>
<title>Move to the Progmasoft Linking Exception, Version 2.0</title>
<updated>2026-10-31T10:42:35+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-10-31T10:42:35+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/catch3/commit/?id=31486e3217b8424809bcf129c0ef24ef5639e919'/>
<id>31486e3217b8424809bcf129c0ef24ef5639e919</id>
<content type='text'>
Version 1.1 left programs built with Progmasoft tools under MPL-2.0 duties
for the code the tools place in them, and left other cases unclear.
Version 2.0 adds a generated code permission, covers runtime and standard
libraries, compiler transformations, interfaces and examples, and settles
how a file is identified and how to tell recipients about source.

Every project SPDX expression moves to AdditionRef-Progmasoft-Exception-2.0.
The older texts stay, because released versions name them.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Version 1.1 left programs built with Progmasoft tools under MPL-2.0 duties
for the code the tools place in them, and left other cases unclear.
Version 2.0 adds a generated code permission, covers runtime and standard
libraries, compiler transformations, interfaces and examples, and settles
how a file is identified and how to tell recipients about source.

Every project SPDX expression moves to AdditionRef-Progmasoft-Exception-2.0.
The older texts stay, because released versions name them.
</pre>
</div>
</content>
</entry>
<entry>
<title>Read the options of a project from catch3.json</title>
<updated>2026-10-29T16:22:21+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-10-29T16:22:21+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/catch3/commit/?id=f41a9c3c01b4df1100e24a63987716cb4dbf28f2'/>
<id>f41a9c3c01b4df1100e24a63987716cb4dbf28f2</id>
<content type='text'>
A project can now keep the options it always wants in a catch3.json
instead of repeating them in every CTest, Bazel or CI command line.

Where it is found: the runner looks in the working directory and in each
directory above it, up to the root of the Git repository that holds the
working directory, and reads the nearest file. Outside a repository it
looks only in the working directory, so a stray file in a home directory
never applies. --config=FILE names a file instead (relative to the
working directory) and --no-config reads none; the last of the two wins.
Workers, --help and --version read no file, so a broken file never stands
in the way of help, and workers keep taking everything from their runner.

What it says: strict JSON with "version": 1 required and "$schema"
allowed for editors. The keys are the long options of the command line,
and each value becomes the arguments it stands for and goes through the
same parser, so there is one set of checks and one set of messages; the
file and the key are named in front of them. Values are typed: switches
take true (false for the negated adaptive-timeout and bisect), counts
take whole numbers, timeout and the confidence interval take numbers,
retries and seed take a number or a word, tests and warn take arrays,
verbosity takes quiet, normal or verbose, and history takes a path or
false. Paths are relative to the directory of the file. An unknown key is
an error with a suggestion when it is close to a known one; a key that
names an option for one run (shard, section, list, replay, ...) is told
that it belongs on the command line. Repeated keys are refused.

Precedence: the file's options are applied first and the command line on
top, so the command line wins; test specs on the command line replace the
file's tests instead of widening them with "or". --verbose names the file
that was read.

Options gains --config and --no-config, a ParseOptions overload that
starts from given options, and a public EditDistance for the suggestions.
The new ProjectConfig module holds the search, the key table and
ParseCommandLine, which Runner now calls in place of ParseOptions.

Tests cover the search (nearest file, the repository boundary, outside a
repository), every key, words and defaults, relative and absolute paths,
the messages for wrong files, precedence, --config, --no-config and the
modes that read no file. A fuzzer reads arbitrary file text and checks
that the worker arguments of the result parse again. The command line
reference, the runner guide and the release notes describe the file; the
amalgamated sources are regenerated.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
A project can now keep the options it always wants in a catch3.json
instead of repeating them in every CTest, Bazel or CI command line.

Where it is found: the runner looks in the working directory and in each
directory above it, up to the root of the Git repository that holds the
working directory, and reads the nearest file. Outside a repository it
looks only in the working directory, so a stray file in a home directory
never applies. --config=FILE names a file instead (relative to the
working directory) and --no-config reads none; the last of the two wins.
Workers, --help and --version read no file, so a broken file never stands
in the way of help, and workers keep taking everything from their runner.

What it says: strict JSON with "version": 1 required and "$schema"
allowed for editors. The keys are the long options of the command line,
and each value becomes the arguments it stands for and goes through the
same parser, so there is one set of checks and one set of messages; the
file and the key are named in front of them. Values are typed: switches
take true (false for the negated adaptive-timeout and bisect), counts
take whole numbers, timeout and the confidence interval take numbers,
retries and seed take a number or a word, tests and warn take arrays,
verbosity takes quiet, normal or verbose, and history takes a path or
false. Paths are relative to the directory of the file. An unknown key is
an error with a suggestion when it is close to a known one; a key that
names an option for one run (shard, section, list, replay, ...) is told
that it belongs on the command line. Repeated keys are refused.

Precedence: the file's options are applied first and the command line on
top, so the command line wins; test specs on the command line replace the
file's tests instead of widening them with "or". --verbose names the file
that was read.

Options gains --config and --no-config, a ParseOptions overload that
starts from given options, and a public EditDistance for the suggestions.
The new ProjectConfig module holds the search, the key table and
ParseCommandLine, which Runner now calls in place of ParseOptions.

Tests cover the search (nearest file, the repository boundary, outside a
repository), every key, words and defaults, relative and absolute paths,
the messages for wrong files, precedence, --config, --no-config and the
modes that read no file. A fuzzer reads arbitrary file text and checks
that the worker arguments of the result parse again. The command line
reference, the runner guide and the release notes describe the file; the
amalgamated sources are regenerated.
</pre>
</div>
</content>
</entry>
</feed>
