<feed xmlns='http://www.w3.org/2005/Atom'>
<title>catch3/tools, branch feature/cpp-tools</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>Answer the review of the tools</title>
<updated>2026-11-01T19:58:30+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-11-01T19:58:30+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/catch3/commit/?id=e66db1cf17714be2ebfeab37670ef3d8965fc7cc'/>
<id>e66db1cf17714be2ebfeab37670ef3d8965fc7cc</id>
<content type='text'>
repo_info starts Git in the checkout with fixed commands, so a shell never
reads a path, reports an unknown state as null rather than clean, and
counts only files it can start. third_party reads every archive before
it changes a file and refuses two modes. version checks that the sources
make a distribution, computes every place before writing any, and
release_notes finds a three-number heading for a version with D = 0.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
repo_info starts Git in the checkout with fixed commands, so a shell never
reads a path, reports an unknown state as null rather than clean, and
counts only files it can start. third_party reads every archive before
it changes a file and refuses two modes. version checks that the sources
make a distribution, computes every place before writing any, and
release_notes finds a three-number heading for a version with D = 0.
</pre>
</div>
</content>
</entry>
<entry>
<title>Name the Bazel targets of the tools in snake_case</title>
<updated>2026-11-01T19:19:02+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-11-01T19:19:02+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/catch3/commit/?id=e32c9d107274f42b9cca700475404c80e96533c5'/>
<id>e32c9d107274f42b9cca700475404c80e96533c5</id>
<content type='text'>
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
</pre>
</div>
</content>
</entry>
<entry>
<title>Move the tools from Python to C++17 and Bazel</title>
<updated>2026-11-01T19:16:14+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-11-01T19:16:14+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/catch3/commit/?id=da3c9d0880dbd4a74e0e43f092d10f5ae42c5043'/>
<id>da3c9d0880dbd4a74e0e43f092d10f5ae42c5043</id>
<content type='text'>
The scripts in use become programs run with `bazelisk run //tools:&lt;tool&gt;`,
and arguments follow `--`:

  amalgamate     the single-file distribution; --check only compares it
  check          licenses, convenience headers, header guards, file names,
                 versions and whether the distribution is up to date
  third-party    compares third_party/ with its archives, or writes it
  version        prints the version, or moves every place that states it
  release-notes  prints a section of the release notes
  repo-info      reports the checkout and the tools on PATH; --json writes
                 it through yyjson, with the fields of Tala's repo-info

amalgamate writes what the Python script wrote, byte for byte, except for
the time of generation. That line is gone so that the output is
deterministic and --check can compare it.

MODULE.bazel now pins the archives of third_party/ by version and sha256,
so Bazel fetches and checks them instead of a tool of ours, and Renovate
reads the versions there.

Scripts nobody used are gone: fixWhitespace, updateDocumentSnippets,
buildAndTest, and updateDocumentToC, which rewrote unrelated documents.
CheckConvenienceHeaders leaves CTest, since //tools:check runs it in CI.
The Python of tests/TestScripts stays: those are tests, not tools.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The scripts in use become programs run with `bazelisk run //tools:&lt;tool&gt;`,
and arguments follow `--`:

  amalgamate     the single-file distribution; --check only compares it
  check          licenses, convenience headers, header guards, file names,
                 versions and whether the distribution is up to date
  third-party    compares third_party/ with its archives, or writes it
  version        prints the version, or moves every place that states it
  release-notes  prints a section of the release notes
  repo-info      reports the checkout and the tools on PATH; --json writes
                 it through yyjson, with the fields of Tala's repo-info

amalgamate writes what the Python script wrote, byte for byte, except for
the time of generation. That line is gone so that the output is
deterministic and --check can compare it.

MODULE.bazel now pins the archives of third_party/ by version and sha256,
so Bazel fetches and checks them instead of a tool of ours, and Renovate
reads the versions there.

Scripts nobody used are gone: fixWhitespace, updateDocumentSnippets,
buildAndTest, and updateDocumentToC, which rewrote unrelated documents.
CheckConvenienceHeaders leaves CTest, since //tools:check runs it in CI.
The Python of tests/TestScripts stays: those are tests, not tools.
</pre>
</div>
</content>
</entry>
<entry>
<title>Carry mocks in the amalgamated files</title>
<updated>2026-11-01T19:05:27+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-11-01T19:05:27+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/catch3/commit/?id=241b5567d09d59e82bff18287c32ada480deb8c0'/>
<id>241b5567d09d59e82bff18287c32ada480deb8c0</id>
<content type='text'>
Mock.hpp goes into catch_amalgamated.hpp, since tests use it directly, and
Mock.cpp into catch_amalgamated.cpp. The test of the amalgamated files
now uses a mock, so a file left out fails it.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Mock.hpp goes into catch_amalgamated.hpp, since tests use it directly, and
Mock.cpp into catch_amalgamated.cpp. The test of the amalgamated files
now uses a mock, so a file left out fails it.
</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>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>Finish the move to C++17 in POSIX code and the amalgamated files</title>
<updated>2026-10-31T10:36:43+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-10-31T10:36:43+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/catch3/commit/?id=afe91797e9d50cd4712d3694a2e5fedfc0b966b1'/>
<id>afe91797e9d50cd4712d3694a2e5fedfc0b966b1</id>
<content type='text'>
A lambda in the POSIX half of Process.cpp captured a structured binding,
which needs C++20 and which a Windows build never compiles. The files in
extras still held the C++20 sources, so they are generated again, and the
generator no longer says the runner needs C++20.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
A lambda in the POSIX half of Process.cpp captured a structured binding,
which needs C++20 and which a Windows build never compiles. The files in
extras still held the C++20 sources, so they are generated again, and the
generator no longer says the runner needs C++20.
</pre>
</div>
</content>
</entry>
<entry>
<title>Make updateThirdParty.py executable</title>
<updated>2026-10-29T06:26:49+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-10-29T06:26:49+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/catch3/commit/?id=30176b75937e87eafbb4f5557eb0be9697753ddf'/>
<id>30176b75937e87eafbb4f5557eb0be9697753ddf</id>
<content type='text'>
The header and license workflow runs it as ./tools/scripts/updateThirdParty.py,
like the other scripts, and failed with 'Permission denied': the file was
created without the executable bit.

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>
The header and license workflow runs it as ./tools/scripts/updateThirdParty.py,
like the other scripts, and failed with 'Permission denied': the file was
created without the executable bit.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Read and write JSON with yyjson and JUnit XML with pugixml</title>
<updated>2026-10-25T10:57:03+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-10-25T10:57:03+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/catch3/commit/?id=45f8c539e86099cb80ecf29b0bf2b3340e141001'/>
<id>45f8c539e86099cb80ecf29b0bf2b3340e141001</id>
<content type='text'>
The runner's hand-written JSON parser and writer, and its XML escaping,
are replaced by two established MIT libraries, vendored in third_party/:
yyjson 0.13.0 and pugixml 1.16. JsonValue and the JUnit model stay as they
are.

Both are compiled into Catch3's own translation units, so a project that
links its own yyjson or pugixml is not affected:
- src/Progmasoft/Runner/Yyjson.inl includes yyjson.c into Json.cpp with
  yyjson_api defined as static, so no yyjson symbol leaves that file.
- src/Progmasoft/PugiXml.inl includes pugixml header-only into
  XmlWriter.cpp with its namespace renamed to Progmasoft_Catch3_Pugi.
- Both are read as system headers, outside the warnings Catch3 builds
  with; they are .inl files, which the header install rules leave out.

JSON keeps its behaviour: strings are bytes and come back as written
(invalid UTF-8 is allowed both ways), non-finite numbers are written as
null, documents nested deeper than 256 levels are refused while they are
converted, and whole numbers are written as integers. Fractions are now
written as the shortest text that reads back as the same double.

JUnit XML stays equivalent; pugixml writes ' and &gt; in attributes as they
are, U+FFFD as the character itself and empty elements as &lt;x /&gt;. The
tests follow.

third_party/{yyjson,pugixml} each have BUILD.bazel, CMakeLists.txt,
meson.build, xmake.lua and premake5.lua, which only provide the include
directory to the library; CMake links them through BUILD_INTERFACE.

tools/scripts/updateThirdParty.py pins the version and sha256 of each
archive; --check, now a step of the header and license workflow, fails
when a vendored file differs from its archive, and --update writes them.
Renovate proposes new versions through a regex manager on that table.

The amalgamation now has a third file, catch_amalgamated_third_party.hpp,
with both wrappers and the libraries inlined; catch_amalgamated.cpp
includes it once. The documents and the release notes say so.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The runner's hand-written JSON parser and writer, and its XML escaping,
are replaced by two established MIT libraries, vendored in third_party/:
yyjson 0.13.0 and pugixml 1.16. JsonValue and the JUnit model stay as they
are.

Both are compiled into Catch3's own translation units, so a project that
links its own yyjson or pugixml is not affected:
- src/Progmasoft/Runner/Yyjson.inl includes yyjson.c into Json.cpp with
  yyjson_api defined as static, so no yyjson symbol leaves that file.
- src/Progmasoft/PugiXml.inl includes pugixml header-only into
  XmlWriter.cpp with its namespace renamed to Progmasoft_Catch3_Pugi.
- Both are read as system headers, outside the warnings Catch3 builds
  with; they are .inl files, which the header install rules leave out.

JSON keeps its behaviour: strings are bytes and come back as written
(invalid UTF-8 is allowed both ways), non-finite numbers are written as
null, documents nested deeper than 256 levels are refused while they are
converted, and whole numbers are written as integers. Fractions are now
written as the shortest text that reads back as the same double.

JUnit XML stays equivalent; pugixml writes ' and &gt; in attributes as they
are, U+FFFD as the character itself and empty elements as &lt;x /&gt;. The
tests follow.

third_party/{yyjson,pugixml} each have BUILD.bazel, CMakeLists.txt,
meson.build, xmake.lua and premake5.lua, which only provide the include
directory to the library; CMake links them through BUILD_INTERFACE.

tools/scripts/updateThirdParty.py pins the version and sha256 of each
archive; --check, now a step of the header and license workflow, fails
when a vendored file differs from its archive, and --update writes them.
Renovate proposes new versions through a regex manager on that table.

The amalgamation now has a third file, catch_amalgamated_third_party.hpp,
with both wrappers and the libraries inlined; catch_amalgamated.cpp
includes it once. The documents and the release notes say so.
</pre>
</div>
</content>
</entry>
<entry>
<title>Give Catch3 its own build names and headers</title>
<updated>2026-10-24T23:37:35+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-10-24T23:37:35+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/catch3/commit/?id=126dc333564cb72b5115d9a9242d66694694b6d0'/>
<id>126dc333564cb72b5115d9a9242d66694694b6d0</id>
<content type='text'>
Catch2 compatibility means the API tests are written in: the macros, such
as TEST_CASE and REQUIRE, and the Catch:: namespace. It does not mean
Catch2's build names or header paths. find_package(Catch2) found Catch3,
and a project using both frameworks met two packages, two sets of targets,
two Catch.cmake modules and two catch2/ header trees with the same names.

Build names:
- CMake: project and package Catch3, targets Catch3::Catch3 and
  Catch3::Catch3WithMain, libraries Catch3 and Catch3Main, options
  CATCH3_*, lib/cmake/Catch3 with Catch3Config, and pkg-config catch3 and
  catch3-with-main. The version is Catch3's, 0.3.0, compatible within a
  minor version.
- The CMake scripts are Catch3.cmake (catch3_discover_tests),
  Catch3AddTests.cmake and Catch3ShardTests.cmake
  (catch3_add_sharded_tests); the helpers they define at ctest time have a
  catch3_ prefix. ParseAndAddCatchTests.cmake, deprecated upstream, is gone.
- Bazel //:catch3 and //:catch3_main, Meson catch3 and catch3-with-main
  (with override_dependency), Xmake catch3 and catch3_main, Premake Catch3
  and Catch3WithMain. Visual Studio projects get GUIDs of their own.
- The Progmasoft::Catch3 target and package are gone: property testing
  and snapshots are part of Catch3::Catch3. Their sources now build with
  the library's warning flags, so property failures are built field by
  field (no missing initializers) and the default property name is a
  thread-local pointer to the name its scope owns (no global destructor).

Headers: the engine moved from src/catch2 to src/Progmasoft/Catch3 with
Progmasoft names, so &lt;catch2/catch_test_macros.hpp&gt; is
&lt;Progmasoft/Catch3/TestMacros.hpp&gt;, &lt;catch2/matchers/catch_matchers_string.hpp&gt;
is &lt;Progmasoft/Catch3/Matchers/String.hpp&gt;, and interface headers are named
after their interface, such as Interfaces/IConfig.hpp. Include guards
became #pragma once. The installed headers go to include/Progmasoft.
src/Progmasoft/Context.cpp is StrategyContext.cpp, so no two sources share
a file name.

tools/scripts/upstreamFiles.txt lists the files that come from Catch2.
The license check expects BSL-1.0 on them and Progmasoft's header on the
rest of src/Progmasoft; the convenience-header check, the amalgamation
script and the surrogate tests take the engine's headers from it. The
amalgamated files are regenerated. The header-guard workflow checks for
#pragma once instead of checkguard.

Documents, the README and the release notes describe the new names.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Catch2 compatibility means the API tests are written in: the macros, such
as TEST_CASE and REQUIRE, and the Catch:: namespace. It does not mean
Catch2's build names or header paths. find_package(Catch2) found Catch3,
and a project using both frameworks met two packages, two sets of targets,
two Catch.cmake modules and two catch2/ header trees with the same names.

Build names:
- CMake: project and package Catch3, targets Catch3::Catch3 and
  Catch3::Catch3WithMain, libraries Catch3 and Catch3Main, options
  CATCH3_*, lib/cmake/Catch3 with Catch3Config, and pkg-config catch3 and
  catch3-with-main. The version is Catch3's, 0.3.0, compatible within a
  minor version.
- The CMake scripts are Catch3.cmake (catch3_discover_tests),
  Catch3AddTests.cmake and Catch3ShardTests.cmake
  (catch3_add_sharded_tests); the helpers they define at ctest time have a
  catch3_ prefix. ParseAndAddCatchTests.cmake, deprecated upstream, is gone.
- Bazel //:catch3 and //:catch3_main, Meson catch3 and catch3-with-main
  (with override_dependency), Xmake catch3 and catch3_main, Premake Catch3
  and Catch3WithMain. Visual Studio projects get GUIDs of their own.
- The Progmasoft::Catch3 target and package are gone: property testing
  and snapshots are part of Catch3::Catch3. Their sources now build with
  the library's warning flags, so property failures are built field by
  field (no missing initializers) and the default property name is a
  thread-local pointer to the name its scope owns (no global destructor).

Headers: the engine moved from src/catch2 to src/Progmasoft/Catch3 with
Progmasoft names, so &lt;catch2/catch_test_macros.hpp&gt; is
&lt;Progmasoft/Catch3/TestMacros.hpp&gt;, &lt;catch2/matchers/catch_matchers_string.hpp&gt;
is &lt;Progmasoft/Catch3/Matchers/String.hpp&gt;, and interface headers are named
after their interface, such as Interfaces/IConfig.hpp. Include guards
became #pragma once. The installed headers go to include/Progmasoft.
src/Progmasoft/Context.cpp is StrategyContext.cpp, so no two sources share
a file name.

tools/scripts/upstreamFiles.txt lists the files that come from Catch2.
The license check expects BSL-1.0 on them and Progmasoft's header on the
rest of src/Progmasoft; the convenience-header check, the amalgamation
script and the surrogate tests take the engine's headers from it. The
amalgamated files are regenerated. The header-guard workflow checks for
#pragma once instead of checkguard.

Documents, the README and the release notes describe the new names.
</pre>
</div>
</content>
</entry>
</feed>
