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

summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorLeitwolf112026-10-24 12:41:08 +0300
committerLeitwolf112026-10-24 12:41:08 +0300
commite18f19b7dd70c99fbcf2b3fe812ee18dabc92663 (patch)
tree4cfc1a3c51ade9b8281925d1c122c12c87f8e381
parente104b694513964d5a84e77f751203cda970d741b (diff)
downloadcatch3-e18f19b7dd70c99fbcf2b3fe812ee18dabc92663.tar.gz
End the output capture when a test exits, fail on missing reports
A test that called exit() crashed its worker with SIGSEGV on Linux and macOS. The exit hook read Catch2's captured output through a scoped deactivation, which switched the capture back on; libstdc++ then flushed std::cout at exit into a capture buffer that static destruction had already freed. RunContext::endCapture() now ends the capture for good and returns what it held, so the standard streams are their own again. A JUnit, JSON or trace report that could not be written was only reported on stderr, and a run whose tests passed still exited with 0, so a build server could miss it. Such a run now exits with 1; failed tests still exit with 42. Integration tests of the runner's output move their helpers into RunnerFixtureClient.hpp and cover --version, --help, the listing modes, a bad option, exit codes 1 to 4, -v, -q, --slowest, colours, --analytics in text and JSON, and Bazel's test environment.
-rw-r--r--extras/catch_amalgamated.cpp235
-rw-r--r--extras/catch_amalgamated.hpp11
-rw-r--r--premake5.lua1
-rw-r--r--src/Progmasoft/Runner/Execution.cpp2
-rw-r--r--src/Progmasoft/Runner/Runner.cpp257
-rw-r--r--src/catch2/internal/catch_run_context.cpp4
-rw-r--r--src/catch2/internal/catch_run_context.hpp9
-rw-r--r--tests/CMakeLists.txt1
-rw-r--r--tests/Progmasoft/BUILD.bazel2
-rw-r--r--tests/Progmasoft/Runner.tests.cpp178
-rw-r--r--tests/Progmasoft/RunnerFixtureClient.hpp213
-rw-r--r--tests/Progmasoft/RunnerOutput.tests.cpp223
-rw-r--r--tests/meson.build1
-rw-r--r--xmake.lua1
14 files changed, 760 insertions, 378 deletions
diff --git a/extras/catch_amalgamated.cpp b/extras/catch_amalgamated.cpp
index 6521ef84..808e6d2f 100644
--- a/extras/catch_amalgamated.cpp
+++ b/extras/catch_amalgamated.cpp
@@ -7,7 +7,7 @@
// SPDX-License-Identifier: BSL-1.0
// Catch v3.16.1
-// Generated: 2026-10-24 10:02:49.316745
+// Generated: 2026-10-24 12:33:30.890575
// ----------------------------------------------------------
// This file is an amalgamation of multiple different files.
// You probably shouldn't edit it directly.
@@ -6499,11 +6499,11 @@ namespace Catch {
return m_atomicAssertionCount.failed >= m_abortAfterXFailedAssertions;
}
- std::string RunContext::capturedOutput() {
+ std::string RunContext::endCapture() {
if ( !m_outputRedirect->isActive() ) {
return {};
}
- auto _ = scopedDeactivate( *m_outputRedirect );
+ m_outputRedirect->deactivate();
return m_outputRedirect->getStdout() + m_outputRedirect->getStderr();
}
@@ -11003,7 +11003,7 @@ namespace Progmasoft::Catch3::Runner
{
return;
}
- const std::string output = state->context->capturedOutput();
+ const std::string output = state->context->endCapture();
std::fflush(stdout);
std::fflush(stderr);
WriteStandardError(output);
@@ -16581,9 +16581,6 @@ namespace Progmasoft::Catch3::Runner
} // namespace Progmasoft::Catch3::Runner
// Copyright (c) 2026 Progmasoft.
// SPDX-License-Identifier: MPL-2.0 WITH AdditionRef-Progmasoft-Exception-1.1
-
-
-
#include <algorithm>
#include <chrono>
#include <cstdio>
@@ -16591,6 +16588,7 @@ namespace Progmasoft::Catch3::Runner
#include <map>
#include <random>
+
namespace Progmasoft::Catch3
{
namespace
@@ -16658,19 +16656,22 @@ namespace Progmasoft::Catch3
{
options.junitPath = xml;
}
- const std::string filter =
- Runner::ReadEnvironment("TESTBRIDGE_TEST_ONLY");
+ const std::string filter
+ = Runner::ReadEnvironment("TESTBRIDGE_TEST_ONLY");
if (!filter.empty())
{
- options.testSpecs = {filter};
+ options.testSpecs = { filter };
}
- const std::string index = Runner::ReadEnvironment("TEST_SHARD_INDEX");
- const std::string total = Runner::ReadEnvironment("TEST_TOTAL_SHARDS");
- const std::string status =
- Runner::ReadEnvironment("TEST_SHARD_STATUS_FILE");
+ const std::string index
+ = Runner::ReadEnvironment("TEST_SHARD_INDEX");
+ const std::string total
+ = Runner::ReadEnvironment("TEST_TOTAL_SHARDS");
+ const std::string status
+ = Runner::ReadEnvironment("TEST_SHARD_STATUS_FILE");
if (!index.empty() && !total.empty())
{
- auto parsed = Runner::ParseOptions({"--shard=" + index + "/" + total});
+ auto parsed = Runner::ParseOptions(
+ { "--shard=" + index + "/" + total });
if (parsed)
{
options.shard = parsed->shard;
@@ -16683,29 +16684,32 @@ namespace Progmasoft::Catch3
}
else
{
- notes.push_back("ignoring Bazel's shard " + index + "/" +
- total + ": " + parsed.GetError().Message());
+ notes.push_back("ignoring Bazel's shard " + index + "/"
+ + total + ": "
+ + parsed.GetError().Message());
}
}
- const std::string seed = Runner::ReadEnvironment("TEST_RANDOM_SEED");
+ const std::string seed
+ = Runner::ReadEnvironment("TEST_RANDOM_SEED");
if (!seed.empty())
{
- auto parsed = Runner::ParseOptions({"--seed=" + seed});
+ auto parsed = Runner::ParseOptions({ "--seed=" + seed });
if (parsed)
{
options.seed = parsed->seed;
options.seedGiven = true;
}
}
- const std::string outputs =
- Runner::ReadEnvironment("TEST_UNDECLARED_OUTPUTS_DIR");
+ const std::string outputs
+ = Runner::ReadEnvironment("TEST_UNDECLARED_OUTPUTS_DIR");
if (!outputs.empty() && options.jsonPath.empty())
{
- options.jsonPath =
- (std::filesystem::path{outputs} / "catch3.json").string();
+ options.jsonPath
+ = (std::filesystem::path{ outputs } / "catch3.json")
+ .string();
}
- if (options.historyDirectory.empty() &&
- !Runner::HasEnvironment("CATCH3_HISTORY"))
+ if (options.historyDirectory.empty()
+ && !Runner::HasEnvironment("CATCH3_HISTORY"))
{
// A sandboxed test has nowhere lasting to keep history.
options.historyEnabled = false;
@@ -16720,8 +16724,8 @@ namespace Progmasoft::Catch3
{
return options.historyDirectory;
}
- const std::string fromEnvironment =
- Runner::ReadEnvironment("CATCH3_HISTORY");
+ const std::string fromEnvironment
+ = Runner::ReadEnvironment("CATCH3_HISTORY");
if (!fromEnvironment.empty())
{
return fromEnvironment;
@@ -16772,7 +16776,8 @@ namespace Progmasoft::Catch3
if (entry.timeout)
{
test.Set("timeoutSeconds",
- static_cast<double>(entry.timeout->count()) / 1000.0);
+ static_cast<double>(entry.timeout->count())
+ / 1000.0);
}
if (entry.retries)
{
@@ -16816,7 +16821,8 @@ namespace Progmasoft::Catch3
case Runner::ListFormat::kNames:
for (const std::size_t index : matched)
{
- std::printf("%s\n", catalog.Tests()[index].name.c_str());
+ std::printf("%s\n",
+ catalog.Tests()[index].name.c_str());
}
break;
case Runner::ListFormat::kText:
@@ -16895,15 +16901,15 @@ namespace Progmasoft::Catch3
const auto median = [](std::vector<std::int64_t> values) {
if (values.empty())
{
- return std::int64_t{0};
+ return std::int64_t{ 0 };
}
std::sort(values.begin(), values.end());
return values[values.size() / 2];
};
row.failureRate = row.runs == 0
? 0.0
- : static_cast<double>(failures) /
- static_cast<double>(row.runs);
+ : static_cast<double>(failures)
+ / static_cast<double>(row.runs);
row.flakyEvents = test.FlakyEvents(20);
row.median = test.DurationPercentile(0.5).value_or(0);
row.recentMedian = median(recent);
@@ -16928,17 +16934,26 @@ namespace Progmasoft::Catch3
ordered.resize(std::min(count, ordered.size()));
return ordered;
};
- const auto flaky =
- top([](const Row &row) { return static_cast<double>(row.flakyEvents); }, 10);
- const auto failing =
- top([](const Row &row) { return row.failureRate; }, 10);
- const auto slowest =
- top([](const Row &row) { return static_cast<double>(row.median); }, 10);
+ const auto flaky = top(
+ [](const Row &row) {
+ return static_cast<double>(row.flakyEvents);
+ },
+ 10);
+ const auto failing = top(
+ [](const Row &row) {
+ return row.failureRate;
+ },
+ 10);
+ const auto slowest = top(
+ [](const Row &row) {
+ return static_cast<double>(row.median);
+ },
+ 10);
const auto slower = top(
[](const Row &row) {
return row.olderMedian > 0
- ? static_cast<double>(row.recentMedian) /
- static_cast<double>(row.olderMedian)
+ ? static_cast<double>(row.recentMedian)
+ / static_cast<double>(row.olderMedian)
: 0.0;
},
10);
@@ -16980,7 +16995,9 @@ namespace Progmasoft::Catch3
{
if (row->flakyEvents > 0)
{
- std::printf(" %3zu %s\n", row->flakyEvents, row->key.c_str());
+ std::printf(" %3zu %s\n",
+ row->flakyEvents,
+ row->key.c_str());
}
}
std::printf("\nin quarantine:\n");
@@ -16988,7 +17005,9 @@ namespace Progmasoft::Catch3
{
if (!row.quarantine.empty())
{
- std::printf(" %s: %s\n", row.key.c_str(), row.quarantine.c_str());
+ std::printf(" %s: %s\n",
+ row.key.c_str(),
+ row.quarantine.c_str());
}
}
std::printf("\nfailing most often:\n");
@@ -17008,11 +17027,12 @@ namespace Progmasoft::Catch3
FormatMicroseconds(row->median).c_str(),
row->key.c_str());
}
- std::printf("\ngetting slower (last 5 runs against the 15 before):\n");
+ std::printf(
+ "\ngetting slower (last 5 runs against the 15 before):\n");
for (const Row *row : slower)
{
- if (row->olderMedian > 0 &&
- row->recentMedian > row->olderMedian * 3 / 2)
+ if (row->olderMedian > 0
+ && row->recentMedian > row->olderMedian * 3 / 2)
{
std::printf(" %10s -> %-10s %s\n",
FormatMicroseconds(row->olderMedian).c_str(),
@@ -17028,7 +17048,7 @@ namespace Progmasoft::Catch3
{
for (const auto &entry : catalog.Tests())
{
- const std::filesystem::path file{entry.file};
+ const std::filesystem::path file{ entry.file };
if (file.is_absolute())
{
return file.parent_path();
@@ -17051,8 +17071,8 @@ namespace Progmasoft::Catch3
{
const std::filesystem::path program = Runner::CurrentExecutable(
arguments.empty() ? nullptr : arguments.front().c_str());
- const std::string programName =
- program.empty() ? "tests" : program.stem().string();
+ const std::string programName
+ = program.empty() ? "tests" : program.stem().string();
std::vector<std::string> rest;
if (arguments.size() > 1)
{
@@ -17109,7 +17129,8 @@ namespace Progmasoft::Catch3
PrintError(catalog.GetError().Message());
return Catch::UnspecifiedErrorExitCode;
}
- const Catch::Config config{Runner::ToConfigData(options, programName)};
+ const Catch::Config config{ Runner::ToConfigData(options,
+ programName) };
const auto &invalid = config.testSpec().getInvalidSpecs();
if (!invalid.empty())
{
@@ -17121,8 +17142,8 @@ namespace Progmasoft::Catch3
}
std::vector<std::string> unmatched;
auto matched = catalog->Match(config, unmatched);
- if (options.mode == Runner::Mode::kListTests ||
- options.mode == Runner::Mode::kListTags)
+ if (options.mode == Runner::Mode::kListTests
+ || options.mode == Runner::Mode::kListTags)
{
if (options.shard.count > 1)
{
@@ -17149,10 +17170,12 @@ namespace Progmasoft::Catch3
return List(options, *catalog, matched, programName);
}
- const std::filesystem::path historyFile = Runner::HistoryFile(
- HistoryDirectory(options, program), programName);
+ const std::filesystem::path historyFile
+ = Runner::HistoryFile(HistoryDirectory(options, program),
+ programName);
Runner::History history;
- if (options.historyEnabled || options.mode == Runner::Mode::kAnalytics)
+ if (options.historyEnabled
+ || options.mode == Runner::Mode::kAnalytics)
{
auto loaded = Runner::History::Load(historyFile);
if (loaded)
@@ -17161,8 +17184,8 @@ namespace Progmasoft::Catch3
}
else
{
- notes.push_back("the history could not be read: " +
- loaded.GetError().Message());
+ notes.push_back("the history could not be read: "
+ + loaded.GetError().Message());
}
}
if (options.mode == Runner::Mode::kAnalytics)
@@ -17189,14 +17212,14 @@ namespace Progmasoft::Catch3
{
changes = std::move(*read);
}
- else if (options.selection == Runner::Selection::kChanged ||
- options.selection == Runner::Selection::kSmart)
+ else if (options.selection == Runner::Selection::kChanged
+ || options.selection == Runner::Selection::kSmart)
{
notes.push_back(read.GetError().Message());
}
};
- if (options.selection == Runner::Selection::kChanged ||
- options.selection == Runner::Selection::kSmart)
+ if (options.selection == Runner::Selection::kChanged
+ || options.selection == Runner::Selection::kSmart)
{
readChanges();
}
@@ -17216,17 +17239,20 @@ namespace Progmasoft::Catch3
}
notes.insert(notes.end(), plan->notes.begin(), plan->notes.end());
- Runner::ConsoleReport console{options, stdout};
- const std::size_t workers =
- options.inProcess
- ? 1
- : std::max<std::size_t>(
- 1,
- std::min<std::size_t>(
- options.jobs == 0 ? Runner::HardwareThreads()
- : options.jobs,
- plan->tests.size()));
- console.RunStarting(plan->tests.size(), workers, options.seed, notes);
+ Runner::ConsoleReport console{ options, stdout };
+ const std::size_t workers
+ = options.inProcess
+ ? 1
+ : std::max<std::size_t>(
+ 1,
+ std::min<std::size_t>(
+ options.jobs == 0 ? Runner::HardwareThreads()
+ : options.jobs,
+ plan->tests.size()));
+ console.RunStarting(plan->tests.size(),
+ workers,
+ options.seed,
+ notes);
std::string guard = options.exitGuardPath;
if (BazelTest() && guard.empty())
@@ -17237,8 +17263,8 @@ namespace Progmasoft::Catch3
{
if (auto status = Runner::CreatePrivateFile(guard); !status)
{
- PrintError("the exit guard file: " +
- status.GetError().Message());
+ PrintError("the exit guard file: "
+ + status.GetError().Message());
return Catch::UnspecifiedErrorExitCode;
}
}
@@ -17256,14 +17282,20 @@ namespace Progmasoft::Catch3
events.testFinished = [&](const TestResult &test) {
console.TestFinished(test);
};
- events.retrying = [&](const TestResult &test, const Attempt &attempt) {
- console.Retrying(test, attempt);
- };
- auto outcome = Runner::RunPlan(
- options, *plan, *catalog, program.string(), programName, events);
- run.wallMicroseconds = std::chrono::duration_cast<std::chrono::microseconds>(
- std::chrono::steady_clock::now() - started)
- .count();
+ events.retrying
+ = [&](const TestResult &test, const Attempt &attempt) {
+ console.Retrying(test, attempt);
+ };
+ auto outcome = Runner::RunPlan(options,
+ *plan,
+ *catalog,
+ program.string(),
+ programName,
+ events);
+ run.wallMicroseconds
+ = std::chrono::duration_cast<std::chrono::microseconds>(
+ std::chrono::steady_clock::now() - started)
+ .count();
run.workers = outcome.workers;
run.tests = std::move(outcome.tests);
for (auto &kept : plan->kept)
@@ -17272,10 +17304,12 @@ namespace Progmasoft::Catch3
}
run.notes = std::move(outcome.notes);
- const bool anyFailure = std::any_of(
- run.tests.begin(), run.tests.end(), [](const TestResult &test) {
- return IsFailure(test.outcome) || test.flaky;
- });
+ const bool anyFailure
+ = std::any_of(run.tests.begin(),
+ run.tests.end(),
+ [](const TestResult &test) {
+ return IsFailure(test.outcome) || test.flaky;
+ });
if (anyFailure)
{
readChanges();
@@ -17289,31 +17323,40 @@ namespace Progmasoft::Catch3
Runner::Analyze(run, analysis);
console.RunEnded(run);
+ // A report that was asked for and is missing would let a build
+ // server miss the run, so it fails the run.
+ bool reportMissing = false;
if (!options.junitPath.empty())
{
if (auto status = Runner::WriteFileAtomically(
- options.junitPath, JUnitXmlWriter::ToString(run));
+ options.junitPath,
+ JUnitXmlWriter::ToString(run));
!status)
{
PrintError(status.GetError().Message());
+ reportMissing = true;
}
}
if (!options.jsonPath.empty())
{
if (auto status = Runner::WriteFileAtomically(
- options.jsonPath, Runner::ToJson(run).ToPrettyString());
+ options.jsonPath,
+ Runner::ToJson(run).ToPrettyString());
!status)
{
PrintError(status.GetError().Message());
+ reportMissing = true;
}
}
if (!options.tracePath.empty())
{
- if (auto status = Runner::WriteFileAtomically(
- options.tracePath, Runner::TraceJson(run));
+ if (auto status
+ = Runner::WriteFileAtomically(options.tracePath,
+ Runner::TraceJson(run));
!status)
{
PrintError(status.GetError().Message());
+ reportMissing = true;
}
}
if (options.historyEnabled && !run.tests.empty())
@@ -17355,8 +17398,8 @@ namespace Progmasoft::Catch3
{
return Catch::UnmatchedTestSpecExitCode;
}
- const bool quarantineCounts =
- options.quarantine == Runner::QuarantineMode::kReport;
+ const bool quarantineCounts
+ = options.quarantine == Runner::QuarantineMode::kReport;
bool failed = false;
std::size_t ran = 0;
std::size_t skipped = 0;
@@ -17367,14 +17410,18 @@ namespace Progmasoft::Catch3
++ran;
}
skipped += test.outcome == Outcome::kSkipped ? 1 : 0;
- failed = failed || test.FailsRun() ||
- (quarantineCounts && test.quarantined &&
- IsFailure(test.outcome));
+ failed = failed || test.FailsRun()
+ || (quarantineCounts && test.quarantined
+ && IsFailure(test.outcome));
}
if (failed)
{
return Catch::TestFailureExitCode;
}
+ if (reportMissing)
+ {
+ return Catch::UnspecifiedErrorExitCode;
+ }
if (run.tests.empty() && !options.allowNoTests)
{
return Catch::NoTestsRunExitCode;
diff --git a/extras/catch_amalgamated.hpp b/extras/catch_amalgamated.hpp
index 8d730b62..7fcefe70 100644
--- a/extras/catch_amalgamated.hpp
+++ b/extras/catch_amalgamated.hpp
@@ -7,7 +7,7 @@
// SPDX-License-Identifier: BSL-1.0
// Catch v3.16.1
-// Generated: 2026-10-24 10:02:48.985091
+// Generated: 2026-10-24 12:33:30.737192
// ----------------------------------------------------------
// This file is an amalgamation of multiple different files.
// You probably shouldn't edit it directly.
@@ -9896,9 +9896,12 @@ namespace Catch {
// !TBD We need to do this another way!
bool aborting() const;
- //! What the running test printed so far and was captured; for a
- //! process that ends inside a test, whose end is never reported.
- std::string capturedOutput();
+ //! Ends the capture of the running test's output and returns what
+ //! it captured; for a process that ends inside a test, whose end is
+ //! never reported. The standard streams are their own again, so
+ //! flushing them at exit no longer reaches the capture buffers,
+ //! which may be gone by then.
+ std::string endCapture();
private:
void assertionPassedFastPath( SourceLineInfo lineInfo );
diff --git a/premake5.lua b/premake5.lua
index 9d191077..316b4009 100644
--- a/premake5.lua
+++ b/premake5.lua
@@ -94,6 +94,7 @@ project "ProgmasoftPropertyTests"
"tests/Progmasoft/RunnerPlanner.tests.cpp",
"tests/Progmasoft/RunnerOptions.tests.cpp",
"tests/Progmasoft/RunnerAnalysis.tests.cpp",
+ "tests/Progmasoft/RunnerOutput.tests.cpp",
"tests/Progmasoft/Snapshot.tests.cpp",
"tests/Progmasoft/Stateful.tests.cpp",
"tests/Progmasoft/Strategy.tests.cpp",
diff --git a/src/Progmasoft/Runner/Execution.cpp b/src/Progmasoft/Runner/Execution.cpp
index ab1e92c4..77a4771a 100644
--- a/src/Progmasoft/Runner/Execution.cpp
+++ b/src/Progmasoft/Runner/Execution.cpp
@@ -507,7 +507,7 @@ namespace Progmasoft::Catch3::Runner
{
return;
}
- const std::string output = state->context->capturedOutput();
+ const std::string output = state->context->endCapture();
std::fflush(stdout);
std::fflush(stderr);
WriteStandardError(output);
diff --git a/src/Progmasoft/Runner/Runner.cpp b/src/Progmasoft/Runner/Runner.cpp
index f85af36b..c4a6feb9 100644
--- a/src/Progmasoft/Runner/Runner.cpp
+++ b/src/Progmasoft/Runner/Runner.cpp
@@ -1,24 +1,9 @@
// Copyright (c) 2026 Progmasoft.
// SPDX-License-Identifier: MPL-2.0 WITH AdditionRef-Progmasoft-Exception-1.1
-#include "Analysis.hpp"
-#include "Catalog.hpp"
-#include "Console.hpp"
-#include "Execution.hpp"
-#include "Files.hpp"
-#include "Git.hpp"
-#include "Hash.hpp"
-#include "History.hpp"
-#include "Json.hpp"
-#include "Options.hpp"
-#include "Planner.hpp"
-#include "Process.hpp"
-#include "ResultsJson.hpp"
-#include "Scheduler.hpp"
-
#include <Progmasoft/Catch3/Runner.hpp>
#include <Progmasoft/Catch3/Version.hpp>
#include <Progmasoft/Catch3/XmlWriter.hpp>
-
+#include <algorithm>
#include <catch2/catch_config.hpp>
#include <catch2/catch_session.hpp>
#include <catch2/catch_user_config.hpp>
@@ -28,14 +13,27 @@
#include <catch2/internal/catch_context.hpp>
#include <catch2/internal/catch_startup_exception_registry.hpp>
#include <catch2/internal/catch_test_case_registry_impl.hpp>
-
-#include <algorithm>
#include <chrono>
#include <cstdio>
#include <exception>
#include <map>
#include <random>
+#include "Analysis.hpp"
+#include "Catalog.hpp"
+#include "Console.hpp"
+#include "Execution.hpp"
+#include "Files.hpp"
+#include "Git.hpp"
+#include "Hash.hpp"
+#include "History.hpp"
+#include "Json.hpp"
+#include "Options.hpp"
+#include "Planner.hpp"
+#include "Process.hpp"
+#include "ResultsJson.hpp"
+#include "Scheduler.hpp"
+
namespace Progmasoft::Catch3
{
namespace
@@ -103,19 +101,22 @@ namespace Progmasoft::Catch3
{
options.junitPath = xml;
}
- const std::string filter =
- Runner::ReadEnvironment("TESTBRIDGE_TEST_ONLY");
+ const std::string filter
+ = Runner::ReadEnvironment("TESTBRIDGE_TEST_ONLY");
if (!filter.empty())
{
- options.testSpecs = {filter};
+ options.testSpecs = { filter };
}
- const std::string index = Runner::ReadEnvironment("TEST_SHARD_INDEX");
- const std::string total = Runner::ReadEnvironment("TEST_TOTAL_SHARDS");
- const std::string status =
- Runner::ReadEnvironment("TEST_SHARD_STATUS_FILE");
+ const std::string index
+ = Runner::ReadEnvironment("TEST_SHARD_INDEX");
+ const std::string total
+ = Runner::ReadEnvironment("TEST_TOTAL_SHARDS");
+ const std::string status
+ = Runner::ReadEnvironment("TEST_SHARD_STATUS_FILE");
if (!index.empty() && !total.empty())
{
- auto parsed = Runner::ParseOptions({"--shard=" + index + "/" + total});
+ auto parsed = Runner::ParseOptions(
+ { "--shard=" + index + "/" + total });
if (parsed)
{
options.shard = parsed->shard;
@@ -128,29 +129,32 @@ namespace Progmasoft::Catch3
}
else
{
- notes.push_back("ignoring Bazel's shard " + index + "/" +
- total + ": " + parsed.GetError().Message());
+ notes.push_back("ignoring Bazel's shard " + index + "/"
+ + total + ": "
+ + parsed.GetError().Message());
}
}
- const std::string seed = Runner::ReadEnvironment("TEST_RANDOM_SEED");
+ const std::string seed
+ = Runner::ReadEnvironment("TEST_RANDOM_SEED");
if (!seed.empty())
{
- auto parsed = Runner::ParseOptions({"--seed=" + seed});
+ auto parsed = Runner::ParseOptions({ "--seed=" + seed });
if (parsed)
{
options.seed = parsed->seed;
options.seedGiven = true;
}
}
- const std::string outputs =
- Runner::ReadEnvironment("TEST_UNDECLARED_OUTPUTS_DIR");
+ const std::string outputs
+ = Runner::ReadEnvironment("TEST_UNDECLARED_OUTPUTS_DIR");
if (!outputs.empty() && options.jsonPath.empty())
{
- options.jsonPath =
- (std::filesystem::path{outputs} / "catch3.json").string();
+ options.jsonPath
+ = (std::filesystem::path{ outputs } / "catch3.json")
+ .string();
}
- if (options.historyDirectory.empty() &&
- !Runner::HasEnvironment("CATCH3_HISTORY"))
+ if (options.historyDirectory.empty()
+ && !Runner::HasEnvironment("CATCH3_HISTORY"))
{
// A sandboxed test has nowhere lasting to keep history.
options.historyEnabled = false;
@@ -165,8 +169,8 @@ namespace Progmasoft::Catch3
{
return options.historyDirectory;
}
- const std::string fromEnvironment =
- Runner::ReadEnvironment("CATCH3_HISTORY");
+ const std::string fromEnvironment
+ = Runner::ReadEnvironment("CATCH3_HISTORY");
if (!fromEnvironment.empty())
{
return fromEnvironment;
@@ -217,7 +221,8 @@ namespace Progmasoft::Catch3
if (entry.timeout)
{
test.Set("timeoutSeconds",
- static_cast<double>(entry.timeout->count()) / 1000.0);
+ static_cast<double>(entry.timeout->count())
+ / 1000.0);
}
if (entry.retries)
{
@@ -261,7 +266,8 @@ namespace Progmasoft::Catch3
case Runner::ListFormat::kNames:
for (const std::size_t index : matched)
{
- std::printf("%s\n", catalog.Tests()[index].name.c_str());
+ std::printf("%s\n",
+ catalog.Tests()[index].name.c_str());
}
break;
case Runner::ListFormat::kText:
@@ -340,15 +346,15 @@ namespace Progmasoft::Catch3
const auto median = [](std::vector<std::int64_t> values) {
if (values.empty())
{
- return std::int64_t{0};
+ return std::int64_t{ 0 };
}
std::sort(values.begin(), values.end());
return values[values.size() / 2];
};
row.failureRate = row.runs == 0
? 0.0
- : static_cast<double>(failures) /
- static_cast<double>(row.runs);
+ : static_cast<double>(failures)
+ / static_cast<double>(row.runs);
row.flakyEvents = test.FlakyEvents(20);
row.me