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

summaryrefslogtreecommitdiffhomepage
path: root/tools/Tools.tests.cpp
diff options
context:
space:
mode:
authorLeitwolf112026-11-01 22:16:14 +0300
committerLeitwolf112026-11-01 22:16:14 +0300
commitda3c9d0880dbd4a74e0e43f092d10f5ae42c5043 (patch)
tree4676a526585dbb0e2f6d8c9c18978ed01092c2e2 /tools/Tools.tests.cpp
parent241b5567d09d59e82bff18287c32ada480deb8c0 (diff)
downloadcatch3-da3c9d0880dbd4a74e0e43f092d10f5ae42c5043.tar.gz
Move the tools from Python to C++17 and Bazel
The scripts in use become programs run with `bazelisk run //tools:<tool>`, 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.
Diffstat (limited to 'tools/Tools.tests.cpp')
-rw-r--r--tools/Tools.tests.cpp116
1 files changed, 116 insertions, 0 deletions
diff --git a/tools/Tools.tests.cpp b/tools/Tools.tests.cpp
new file mode 100644
index 00000000..51dca951
--- /dev/null
+++ b/tools/Tools.tests.cpp
@@ -0,0 +1,116 @@
+// Copyright (c) 2026 Progmasoft.
+// SPDX-License-Identifier: MPL-2.0 WITH AdditionRef-Progmasoft-Exception-2.0
+
+#include <Progmasoft/Catch3/TestMacros.hpp>
+#include <string>
+
+#include "tools/Amalgamation.hpp"
+#include "tools/Repository.hpp"
+#include "tools/RepositoryReport.hpp"
+#include "tools/Versions.hpp"
+
+using namespace Progmasoft::Catch3::Tools;
+
+TEST_CASE("Versions have three or four numbers", "[tools]")
+{
+ CHECK(ParseVersion("0.3.0") == Version{ 0, 3, 0, 0 });
+ CHECK(ParseVersion("0.3.0.2") == Version{ 0, 3, 0, 2 });
+ for (const char *wrong :
+ { "0.3", "0.3.0.2.1", "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]")
+{
+ const auto next = [](const char *version) {
+ return FormatVersion(NextVersion(*ParseVersion(version)));
+ };
+ 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");
+}
+
+TEST_CASE("A version site is read and written in place", "[tools]")
+{
+ const VersionSite site{ "file", "version: '", "'" };
+ const std::string text = "name\n version: '1.2.3',\n version: '9'\n";
+ CHECK(ReadVersionSite(text, site) == "1.2.3");
+ CHECK(WriteVersionSite(text, site, "1.2.3.4")
+ == "name\n version: '1.2.3.4',\n version: '9'\n");
+ CHECK_FALSE(ReadVersionSite("name", site));
+ CHECK_FALSE(WriteVersionSite("name", site, "1"));
+}
+
+TEST_CASE("Release notes are found by their heading", "[tools]")
+{
+ const std::string notes = "# Release notes\n\n## 0.2\n\nNew.\n\n"
+ "### Part\n\n* One.\n\n\n## 0.1\n\nOld.\n";
+ CHECK(ReleaseNotesOf(notes, "0.2") == "New.\n\n### Part\n\n* One.\n");
+ CHECK(ReleaseNotesOf(notes, "0.1") == "Old.\n");
+ CHECK_FALSE(ReleaseNotesOf(notes, "0.3"));
+}
+
+TEST_CASE("Includes are read as they are written", "[tools]")
+{
+ const auto angled = ParseInclude(" #include <a/b.hpp> // why\n");
+ REQUIRE(angled);
+ CHECK(angled->Name == "a/b.hpp");
+ CHECK(angled->Angled);
+ const auto quoted = ParseInclude("#include \"b.hpp\"\n");
+ REQUIRE(quoted);
+ CHECK_FALSE(quoted->Angled);
+ CHECK_FALSE(ParseInclude("# include <a.hpp>\n"));
+ CHECK_FALSE(ParseInclude("// #include <a.hpp>\n"));
+ CHECK_FALSE(ParseInclude("#include MACRO\n"));
+}
+
+TEST_CASE("The engine version comes from its declaration", "[tools]")
+{
+ CHECK(ParseEngineVersion(" static Version version( 3, 16, 1, \"\", 0 );")
+ == "3.16.1");
+ CHECK(ParseEngineVersion("static Version version( 3, 17, 0, \"rc\", 2 );")
+ == "3.17.0-rc.2");
+ CHECK_FALSE(ParseEngineVersion("nothing here"));
+}
+
+TEST_CASE("A report becomes JSON", "[tools]")
+{
+ RepositoryReport report;
+ report.Root = "C:\\repos\\catch3";
+ report.Os = "windows";
+ report.Branch = "devel";
+ report.Dirty = true;
+ report.Tools.push_back({ "git", "/usr/bin/git", true });
+ report.Tools.push_back({ "ninja", "", false });
+ CHECK(ReportToJson(report) == R"({
+ "root": "C:\\repos\\catch3",
+ "os": "windows",
+ "branch": "devel",
+ "dirty": true,
+ "tools": [
+ {
+ "name": "git",
+ "path": "/usr/bin/git",
+ "available": true
+ },
+ {
+ "name": "ninja",
+ "available": false
+ }
+ ]
+}
+)");
+}
+
+TEST_CASE("Text helpers keep line ends", "[tools]")
+{
+ CHECK(SplitLines("a\nb") == std::vector<std::string>{ "a\n", "b" });
+ CHECK(SplitLines("").empty());
+ CHECK(Trimmed(" a b\r\n") == "a b");
+ CHECK(Trimmed(" \n").empty());
+}