Read-only mirrors. Development, issues and pull requests are on GitHub.

summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorLeitwolf2026-11-15 13:53:40 +0300
committerGitHub2026-11-15 13:53:40 +0300
commit9ea8d3a88334d62711f3e9aa429c7fe4905f2ef0 (patch)
tree7a4c0aa03d636bea6a359cd6fe9501bb5c8db28e
parent13ecce487c3075e4ccc2f62b9c08597459d1a268 (diff)
parent8979c1caf2eee321cf497671805d2177980c421e (diff)
downloadcatch3-docs/no-former-language.tar.gz
Merge branch 'devel' into docs/no-former-languagedocs/no-former-language
-rw-r--r--.markdownlint.yaml9
-rw-r--r--CMakeLists.txt2
-rw-r--r--MODULE.bazel2
-rw-r--r--docs/contributing.md2
-rw-r--r--docs/release-notes.md28
-rw-r--r--extras/catch_amalgamated.cpp4
-rw-r--r--extras/catch_amalgamated.hpp2
-rw-r--r--extras/catch_amalgamated_third_party.hpp2
-rw-r--r--meson.build2
-rw-r--r--src/Progmasoft/Catch3/Version.hpp2
-rw-r--r--tools/Tools.tests.cpp40
-rw-r--r--tools/VersionMain.cpp17
-rw-r--r--tools/Versions.cpp108
-rw-r--r--tools/Versions.hpp15
-rw-r--r--xmake.lua2
15 files changed, 141 insertions, 96 deletions
diff --git a/.markdownlint.yaml b/.markdownlint.yaml
new file mode 100644
index 00000000..50376e40
--- /dev/null
+++ b/.markdownlint.yaml
@@ -0,0 +1,9 @@
+# SPDX-FileCopyrightText: 2026 Progmasoft <support@progmasoft.com>
+# SPDX-License-Identifier: MPL-2.0 WITH AdditionRef-Progmasoft-Exception-2.0
+
+# The documents keep Catch2's style: an anchor at the top of each page and a
+# contents list whose lines end in <br>.
+MD033:
+ allowed_elements:
+ - a
+ - br
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 376e47d6..890d0be9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -37,7 +37,7 @@ endif()
# The version is Catch3's; the Catch2 engine it is built on keeps its own in
# CATCH_VERSION_MAJOR and the other macros of Progmasoft/Catch3/EngineVersionMacros.hpp.
project(Catch3
- VERSION 0.3.0.2
+ VERSION 0.4.0
LANGUAGES CXX
HOMEPAGE_URL "https://github.com/Progmasoft/catch3"
DESCRIPTION "A C++ test framework with a Catch2-compatible API, a parallel runner, property testing and snapshots."
diff --git a/MODULE.bazel b/MODULE.bazel
index c4196428..6e0fb394 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -1,4 +1,4 @@
-module(name = "catch3", version = "0.3.0.2")
+module(name = "catch3", version = "0.4.0")
bazel_dep(name = "bazel_skylib", version = "1.9.0")
bazel_dep(name = "rules_cc", version = "0.2.17")
diff --git a/docs/contributing.md b/docs/contributing.md
index ac736ffd..4edecee2 100644
--- a/docs/contributing.md
+++ b/docs/contributing.md
@@ -66,7 +66,7 @@ The tools in `tools/` are C++17 and run through Bazel, with arguments after
| `//tools:amalgamate` | writes the single-file distribution; `-- --check` only compares it |
| `//tools:check` | runs the repository checks |
| `//tools:third_party` | `-- --check` compares `third_party/` with the archives `MODULE.bazel` pins, `-- --update` writes it |
-| `//tools:version` | prints the version; `-- --next` or `-- <version>` moves every place that states it, and the distribution |
+| `//tools:version` | prints the version; `-- <version>` (`MAJOR.MINOR.PATCH`) or `-- --next` (the next patch release) moves every place that states it, and the distribution |
| `//tools:release_notes` | prints a section of the release notes, of `-- <version>` or the current one |
| `//tools:repo_info` | reports the checkout and the tools on `PATH`; `-- --json` writes it as JSON |
diff --git a/docs/release-notes.md b/docs/release-notes.md
index 4e2dea80..a250fc95 100644
--- a/docs/release-notes.md
+++ b/docs/release-notes.md
@@ -7,6 +7,7 @@ based on Catch2 3.16.1; Catch2's own history is in
[its release notes](https://github.com/catchorg/Catch2/blob/devel/docs/release-notes.md).
**Contents**<br>
+[0.4.0](#040)<br>
[0.3.0.2](#0302)<br>
[0.3.0.1](#0301)<br>
[0.3.0](#030)<br>
@@ -14,6 +15,33 @@ based on Catch2 3.16.1; Catch2's own history is in
[0.1.0](#010)<br>
+## 0.4.0
+
+Released 2026-11-15.
+
+Versions of Catch3 have three numbers again from this release on:
+`MAJOR.MINOR.PATCH`, as Semantic Versioning writes them.
+
+### The Catch3 runner
+
+* `--coverage=DIR` runs every test in a process of its own and keeps what each
+ one reached: `DIR/coverage.json` maps every test to the lines it ran, and
+ `DIR/coverage.lcov` is the run combined. It reads LLVM source-based coverage
+ (Clang) and gcov (GCC). See [Per-test coverage](progmasoft-runner.md#per-test-coverage).
+* Workers and the processes the runner starts no longer inherit the variables
+ whose names look like secrets (`TOKEN`, `SECRET`, `PASSWORD` and the like).
+ `--pass-env=NAME`, which can be repeated, or `"pass-env"` in the project
+ configuration hands one to the tests that need it.
+ See [Environment variables](progmasoft-runner.md#environment-variables).
+
+### Tools
+
+* The repository tools are C++17 and run through Bazel:
+ `//tools:check`, `//tools:amalgamate`, `//tools:version`,
+ `//tools:release_notes`, `//tools:repo_info` and `//tools:third_party`.
+ They replace the Python scripts of earlier releases.
+
+
## 0.3.0.2
Released 2026-11-01.
diff --git a/extras/catch_amalgamated.cpp b/extras/catch_amalgamated.cpp
index 4b928849..3f98cd4a 100644
--- a/extras/catch_amalgamated.cpp
+++ b/extras/catch_amalgamated.cpp
@@ -6,7 +6,7 @@
// SPDX-License-Identifier: BSL-1.0
-// Catch3 v0.3.0.2, on the Catch2 v3.16.1 engine
+// Catch3 v0.4.0, on the Catch2 v3.16.1 engine
// ----------------------------------------------------------
// This file is an amalgamation of multiple different files.
// You probably shouldn't edit it directly.
@@ -2391,7 +2391,7 @@ namespace Progmasoft::Catch3
namespace Progmasoft::Catch3
{
/// The version of Catch3: of its runner, its tools and its formats.
- inline constexpr const char *kVersion = "0.3.0.2";
+ inline constexpr const char *kVersion = "0.4.0";
} // namespace Progmasoft::Catch3
// Copyright (c) 2026 Progmasoft.
// SPDX-License-Identifier: MPL-2.0 WITH AdditionRef-Progmasoft-Exception-2.0
diff --git a/extras/catch_amalgamated.hpp b/extras/catch_amalgamated.hpp
index fad2f28c..0cee5196 100644
--- a/extras/catch_amalgamated.hpp
+++ b/extras/catch_amalgamated.hpp
@@ -6,7 +6,7 @@
// SPDX-License-Identifier: BSL-1.0
-// Catch3 v0.3.0.2, on the Catch2 v3.16.1 engine
+// Catch3 v0.4.0, on the Catch2 v3.16.1 engine
// ----------------------------------------------------------
// This file is an amalgamation of multiple different files.
// You probably shouldn't edit it directly.
diff --git a/extras/catch_amalgamated_third_party.hpp b/extras/catch_amalgamated_third_party.hpp
index 5a3aa21c..b6bb783b 100644
--- a/extras/catch_amalgamated_third_party.hpp
+++ b/extras/catch_amalgamated_third_party.hpp
@@ -1,4 +1,4 @@
-// Catch3 v0.3.0.2: yyjson and pugixml for catch_amalgamated.cpp
+// Catch3 v0.4.0: yyjson and pugixml for catch_amalgamated.cpp
// ----------------------------------------------------------
// This file is an amalgamation of src/Progmasoft/Runner/Yyjson.inl,
// src/Progmasoft/PugiXml.inl and the libraries they include from
diff --git a/meson.build b/meson.build
index 1c3699e9..c8b816d7 100644
--- a/meson.build
+++ b/meson.build
@@ -8,7 +8,7 @@
project(
'catch3',
'cpp',
- version: '0.3.0.2',
+ version: '0.4.0',
license: ['BSL-1.0', 'MPL-2.0 WITH AdditionRef-Progmasoft-Exception-2.0'],
# Meson 1.1 added clang-cl support for the C++ modes used by Progmasoft tests.
meson_version: '>=1.1.0',
diff --git a/src/Progmasoft/Catch3/Version.hpp b/src/Progmasoft/Catch3/Version.hpp
index e83874f3..33ad6346 100644
--- a/src/Progmasoft/Catch3/Version.hpp
+++ b/src/Progmasoft/Catch3/Version.hpp
@@ -5,5 +5,5 @@
namespace Progmasoft::Catch3
{
/// The version of Catch3: of its runner, its tools and its formats.
- inline constexpr const char *kVersion = "0.3.0.2";
+ inline constexpr const char *kVersion = "0.4.0";
} // namespace Progmasoft::Catch3
diff --git a/tools/Tools.tests.cpp b/tools/Tools.tests.cpp
index 90e9b129..c505b966 100644
--- a/tools/Tools.tests.cpp
+++ b/tools/Tools.tests.cpp
@@ -3,6 +3,7 @@
#include <Progmasoft/Catch3/Matchers/String.hpp>
#include <Progmasoft/Catch3/TestMacros.hpp>
+#include <limits>
#include <string>
#include "tools/Amalgamation.hpp"
@@ -13,28 +14,35 @@
using namespace Progmasoft::Catch3::Tools;
using Catch::Matchers::ContainsSubstring;
-TEST_CASE("Versions have three or four numbers", "[tools]")
+TEST_CASE("Versions are MAJOR.MINOR.PATCH", "[tools]")
{
- CHECK(ParseVersion("0.3.0") == Version{ 0, 3, 0, 0 });
- CHECK(ParseVersion("0.3.0.2") == Version{ 0, 3, 0, 2 });
+ CHECK(ParseVersion("0.4.0") == Version{ 0, 4, 0 });
+ CHECK(ParseVersion("10.20.30") == Version{ 10, 20, 30 });
+ CHECK(FormatVersion(Version{ 0, 4, 0 }) == "0.4.0");
for (const char *wrong :
- { "0.3", "0.3.0.2.1", "01.3.0", "0.3.0.", "a.3.0", "", "0.3.0-rc" })
+ { "0.3", "0.3.0.2", "01.3.0", "0.3.0.", "a.3.0", "", "0.3.0-rc" })
{
INFO(wrong);
CHECK_FALSE(ParseVersion(wrong));
}
}
-TEST_CASE("The next version counts releases", "[tools]")
+TEST_CASE("The next patch release follows a SemVer or a four-number version",
+ "[tools]")
{
const auto next = [](const char *version) {
- return FormatVersion(NextVersion(*ParseVersion(version)));
+ const auto parsed = NextPatch(version);
+ return parsed ? FormatVersion(*parsed) : std::string{ "none" };
};
- CHECK(next("0.3.0") == "0.3.0.1");
- CHECK(next("0.4.0.8") == "0.4.0.9");
- CHECK(next("0.4.0.9") == "0.4.1.0");
- CHECK(next("0.4.9.9") == "0.5.0.0");
- CHECK(next("0.19.9.9") == "1.0.0.0");
+ CHECK(next("0.4.0") == "0.4.1");
+ CHECK(next("1.2.9") == "1.2.10");
+ // After the four-number versions: the fourth number goes.
+ CHECK(next("0.3.0.2") == "0.3.1");
+ CHECK(next("0.3") == "none");
+ const auto largest = std::to_string(std::numeric_limits<unsigned>::max());
+ CHECK(next(("0.4." + largest).c_str()) == "none");
+ CHECK(next(("0.3." + largest + ".2").c_str()) == "none");
+ CHECK(next("0.3.0.2.1") == "none");
}
TEST_CASE("A version site is read and written in place", "[tools]")
@@ -57,12 +65,14 @@ TEST_CASE("Release notes are found by their heading", "[tools]")
CHECK_FALSE(ReleaseNotesOf(notes, "0.3"));
}
-TEST_CASE("A release with D = 0 may be headed by three numbers", "[tools]")
+TEST_CASE("A release is found by the version it was published as", "[tools]")
{
- const std::string notes = "# Notes\n\n## 0.4.0\n\nThree.\n";
+ const std::string notes
+ = "# Notes\n\n## 0.4.0\n\nThree.\n\n\n## 0.3.0.2\n\nFour.\n";
CHECK(ReleaseNotesOf(notes, "0.4.0") == "Three.\n");
- CHECK(ReleaseNotesOf(notes, "0.4.0.0") == "Three.\n");
- CHECK_FALSE(ReleaseNotesOf(notes, "0.4.0.1"));
+ CHECK(ReleaseNotesOf(notes, "0.3.0.2") == "Four.\n");
+ CHECK_FALSE(ReleaseNotesOf(notes, "0.4.0.0"));
+ CHECK_FALSE(ReleaseNotesOf(notes, "0.3.0"));
}
TEST_CASE("Git that could not say is not a clean checkout", "[tools]")
diff --git a/tools/VersionMain.cpp b/tools/VersionMain.cpp
index 6f1c13cb..2c9c5456 100644
--- a/tools/VersionMain.cpp
+++ b/tools/VersionMain.cpp
@@ -2,8 +2,8 @@
// SPDX-License-Identifier: MPL-2.0 WITH AdditionRef-Progmasoft-Exception-2.0
// bazelisk run //tools:version prints the current version
-// bazelisk run //tools:version -- --next moves to the next version
-// bazelisk run //tools:version -- 0.3.1.0 moves to that version
+// bazelisk run //tools:version -- --next moves to the next patch release
+// bazelisk run //tools:version -- 0.4.0 moves to that version
//
// Moving writes every place that states the version, and the amalgamation.
@@ -44,16 +44,19 @@ main(int argc, char **argv)
return 0;
}
const std::string_view argument{ argv[1] };
- const auto parsed = ParseVersion(
- argument == "--next" ? *current : std::string{ argument });
+ const auto parsed
+ = argument == "--next" ? NextPatch(*current) : ParseVersion(argument);
if (!parsed)
{
- std::cerr << "not a version of three or four numbers: " << argument
+ std::cerr << (argument == "--next"
+ ? "the current version is not a release version: "
+ + *current
+ : "not a version MAJOR.MINOR.PATCH: "
+ + std::string{ argument })
<< '\n';
return 2;
}
- const auto version
- = FormatVersion(argument == "--next" ? NextVersion(*parsed) : *parsed);
+ const auto version = FormatVersion(*parsed);
// The sources have to make a distribution before anything is changed.
(void)GenerateAmalgamation(*root, problems);
if (problems.empty())
diff --git a/tools/Versions.cpp b/tools/Versions.cpp
index abc6d5b3..d3ae03cf 100644
--- a/tools/Versions.cpp
+++ b/tools/Versions.cpp
@@ -4,6 +4,7 @@
#include <algorithm>
#include <cctype>
#include <charconv>
+#include <limits>
#include <utility>
#include <vector>
@@ -17,72 +18,70 @@ namespace Progmasoft::Catch3::Tools
= "src/Progmasoft/Catch3/Version.hpp";
} // namespace
- std::optional<Version>
- ParseVersion(std::string_view text)
+ namespace
{
- Version version{};
- std::size_t count = 0;
- while (true)
+ /// The dot-separated numbers of `text`, at most `limit` of them, none
+ /// empty or with a leading zero; nothing for anything else.
+ std::optional<std::vector<unsigned>>
+ Numbers(std::string_view text, std::size_t limit)
{
- const auto dot = text.find('.');
- const auto number = text.substr(0, dot);
- if (count == version.size() || number.empty()
- || (number.size() > 1 && number.front() == '0'))
+ std::vector<unsigned> numbers;
+ while (true)
{
- return std::nullopt;
+ const auto dot = text.find('.');
+ const auto number = text.substr(0, dot);
+ if (numbers.size() == limit || number.empty()
+ || (number.size() > 1 && number.front() == '0'))
+ {
+ return std::nullopt;
+ }
+ unsigned value = 0;
+ const auto *end = number.data() + number.size();
+ const auto parsed = std::from_chars(number.data(), end, value);
+ if (parsed.ec != std::errc{} || parsed.ptr != end)
+ {
+ return std::nullopt;
+ }
+ numbers.push_back(value);
+ if (dot == std::string_view::npos)
+ {
+ return numbers;
+ }
+ text.remove_prefix(dot + 1);
}
- const auto *end = number.data() + number.size();
- const auto parsed
- = std::from_chars(number.data(), end, version[count]);
- if (parsed.ec != std::errc{} || parsed.ptr != end)
- {
- return std::nullopt;
- }
- ++count;
- if (dot == std::string_view::npos)
- {
- break;
- }
- text.remove_prefix(dot + 1);
}
- if (count < 3)
+ } // namespace
+
+ std::optional<Version>
+ ParseVersion(std::string_view text)
+ {
+ const auto numbers = Numbers(text, 3);
+ if (!numbers || numbers->size() != 3)
{
return std::nullopt;
}
- return version;
+ return Version{ (*numbers)[0], (*numbers)[1], (*numbers)[2] };
}
std::string
FormatVersion(const Version &version)
{
return std::to_string(version[0]) + "." + std::to_string(version[1])
- + "." + std::to_string(version[2]) + "."
- + std::to_string(version[3]);
+ + "." + std::to_string(version[2]);
}
- Version
- NextVersion(Version version)
+ std::optional<Version>
+ NextPatch(std::string_view current)
{
- if (version[3] < 9)
+ const auto numbers = Numbers(current, 4);
+ // A patch number at its largest has no next one; adding one would
+ // wrap around to 0 and move the version back.
+ if (!numbers || numbers->size() < 3
+ || (*numbers)[2] == std::numeric_limits<unsigned>::max())
{
- ++version[3];
- return version;
- }
- version[3] = 0;
- if (version[2] < 9)
- {
- ++version[2];
- return version;
- }
- version[2] = 0;
- if (version[1] < 19)
- {
- ++version[1];
- return version;
+ return std::nullopt;
}
- version[1] = 0;
- ++version[0];
- return version;
+ return Version{ (*numbers)[0], (*numbers)[1], (*numbers)[2] + 1 };
}
const std::array<VersionSite, 5> &
@@ -211,17 +210,10 @@ namespace Progmasoft::Catch3::Tools
std::optional<std::string>
ReleaseNotesOf(std::string_view notes, std::string_view version)
{
- auto heading = "\n## " + std::string{ version } + "\n";
- auto found = notes.find(heading);
- // A release with D = 0 may be headed by its three numbers.
- const auto parsed = ParseVersion(version);
- if (found == std::string_view::npos && parsed && (*parsed)[3] == 0)
- {
- heading = "\n## " + std::to_string((*parsed)[0]) + "."
- + std::to_string((*parsed)[1]) + "."
- + std::to_string((*parsed)[2]) + "\n";
- found = notes.find(heading);
- }
+ // Every release is headed by its version as it was published: three
+ // numbers, or four for the releases before Semantic Versioning.
+ const auto heading = "\n## " + std::string{ version } + "\n";
+ const auto found = notes.find(heading);
if (found == std::string_view::npos)
{
return std::nullopt;
diff --git a/tools/Versions.hpp b/tools/Versions.hpp
index 3a601a50..a1fdf4a6 100644
--- a/tools/Versions.hpp
+++ b/tools/Versions.hpp
@@ -12,19 +12,22 @@
namespace Progmasoft::Catch3::Tools
{
- /// A.B.C.D. A version of three numbers has D = 0.
- using Version = std::array<unsigned, 4>;
+ /// MAJOR.MINOR.PATCH, as Semantic Versioning numbers a release.
+ using Version = std::array<unsigned, 3>;
+ /// A version of exactly three numbers, none with a leading zero.
[[nodiscard]] std::optional<Version>
ParseVersion(std::string_view text);
[[nodiscard]] std::string
FormatVersion(const Version &version);
- /// The version after `version`, which counts releases: D up to 9, then C
- /// up to 9, then B up to 19, then A.
- [[nodiscard]] Version
- NextVersion(Version version);
+ /// The next patch release after `current`. `current` may also be one of
+ /// the four-number versions Catch3 had before Semantic Versioning: the
+ /// fourth number is dropped and the patch goes up, so 0.3.0.2 is followed
+ /// by 0.3.1.
+ [[nodiscard]] std::optional<Version>
+ NextPatch(std::string_view current);
/// A place that states the version: the file, and the text around it.
struct VersionSite final
diff --git a/xmake.lua b/xmake.lua
index 7fd7075f..75542e56 100644
--- a/xmake.lua
+++ b/xmake.lua
@@ -2,7 +2,7 @@
-- SPDX-License-Identifier: MPL-2.0 WITH AdditionRef-Progmasoft-Exception-2.0
set_project("Catch3")
-set_version("0.3.0.2")
+set_version("0.4.0")
set_languages("cxx17")
set_warnings("all")