This commit is contained in:
Martin Hořeňovský
2025-07-24 22:01:46 +02:00
parent b6c5a635bb
commit fee81626d2
11 changed files with 581 additions and 265 deletions

View File

@@ -34,7 +34,7 @@ if(CMAKE_BINARY_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
endif() endif()
project(Catch2 project(Catch2
VERSION 3.8.1 # CML version placeholder, don't delete VERSION 3.9.0 # CML version placeholder, don't delete
LANGUAGES CXX LANGUAGES CXX
HOMEPAGE_URL "https://github.com/catchorg/Catch2" HOMEPAGE_URL "https://github.com/catchorg/Catch2"
DESCRIPTION "A modern, C++-native, unit test framework." DESCRIPTION "A modern, C++-native, unit test framework."

View File

@@ -413,7 +413,7 @@ Tests are sorted by their name, their tags are ignored.
### rand ### rand
Randomized order. The default order. Randomized order. The default order.
> Randomized order has been made default in Catch2 X.Y.Z > Randomized order has been made default in Catch2 3.9.0
The order is dependent on Catch2's random seed (see The order is dependent on Catch2's random seed (see
[`--rng-seed`](#rng-seed)), and is subset invariant. What this means [`--rng-seed`](#rng-seed)), and is subset invariant. What this means

View File

@@ -268,7 +268,7 @@ namespace Catch {
## Disabling deprecation warnings ## Disabling deprecation warnings
> Introduced in Catch2 X.Y.Z > Introduced in Catch2 3.9.0
Catch2 has started using the C++ macro `[[deprecated]]` to mark things Catch2 has started using the C++ macro `[[deprecated]]` to mark things
that are deprecated and should not be used any more. If you need to that are deprecated and should not be used any more. If you need to
@@ -318,7 +318,7 @@ are not meant to be runnable, only "scannable".
## Experimental thread safety ## Experimental thread safety
> Introduced in Catch2 X.Y.Z > Introduced in Catch2 3.9.0
Catch2 can optionally support thread-safe assertions, that means, multiple Catch2 can optionally support thread-safe assertions, that means, multiple
user-spawned threads can use the assertion macros at the same time. Due user-spawned threads can use the assertion macros at the same time. Due

View File

@@ -2,6 +2,7 @@
# Release notes # Release notes
**Contents**<br> **Contents**<br>
[3.9.0](#390)<br>
[3.8.1](#381)<br> [3.8.1](#381)<br>
[3.8.0](#380)<br> [3.8.0](#380)<br>
[3.7.1](#371)<br> [3.7.1](#371)<br>
@@ -67,6 +68,45 @@
[Even Older versions](#even-older-versions)<br> [Even Older versions](#even-older-versions)<br>
## 3.9.0
### Improvements
* **Added experimental opt-in support for thread safe assertions**
* Read the documentation for full details
* **The default test run order has been changed to random**
* Passing assertions are significantly faster when the reporter does not ask for `assertionEnded` events on passing assertions.
* This is the default behaviour of e.g. Console or Compact reporter
* Simple `REQUIRE(true)` is 60% faster in Release and 80% faster in Debug build configuration
* Simple `REQUIRE_NOTHROW` is 230% faster in Release and 430% faster in Debug build configuration
* Simple `REQUIRE_THROWS` is ~3% faster in Release and 20% faster in Debug build configuration (throwing introduces enough overhead that the optimizations inside Catch2 are mostly irrelevant)
* Small (2-5%) improvement if the reporter asks for `assertionEnded` events for passing assertions.
* The exit code constants are part of the Session API. (#2955, #2976)
* Suppressed unsigned integer overflow checking in locations with intended overflow (#2965)
* Reporters flush output after writing metadata, e.g. rng seed (#2964)
* Added unreachable after `FAIL` and `SKIP` macros (#2941)
* This allows the compiler to understand that the execution does not continue past the macro, and avoids warnings.
* Added fast path for `assertionStarting` event when no reporter requires it
* For backwards compatibility, this fast path is opt-in
* A reporter can opt in by changing its `ReporterPreferences::shouldReportAllAssertionStarts`
* Improved last seen source location tracking to be more precise
* This is used when reporting unexpected exceptions from tests
### Fixes
* Fixed formatting of tags with more than 100 tests in the default `--list-tags` output (#2963)
* Fixed Clang-Tidy's `readability-static-accessed-through-instance` in tests
* Fixed most of Clang-Tidy's `cppcoreguidelines-avoid-non-const-global-variables` (#2582)
* The lifetime of scoped messages now strictly obeys their scope (#1759, #2019, #2959)
* Previously Catch2 would try to keep them around during unexpected exception, to provide helpful context.
* The amount of surprises the irregularities caused was not worth the occasional utility provided.
* `TEMPLATE_TEST_CASE_SIG` can handle signatures consisting of only types (#2680, #2995)
* Moved `catch_test_run_info.hpp` up from `internal/` subfolder into the main one (#2972)
### Miscellaneous
* pkg-config files are now generated at install time (#2979)
* This fixes missing debug suffix in library names
* This fixes install prefix mismatch between build config and actuall installation
## 3.8.1 ## 3.8.1
### Fixes ### Fixes

View File

@@ -169,7 +169,7 @@ Currently there are three customization options:
`assertionStarting` events. Most reporters do not, and opting out `assertionStarting` events. Most reporters do not, and opting out
explicitly enables a fast-path in Catch2's handling of assertions. explicitly enables a fast-path in Catch2's handling of assertions.
> `shouldReportAllAssertionStarts` was introduced in Catch2 X.Y.Z > `shouldReportAllAssertionStarts` was introduced in Catch2 3.9.0
### Per-reporter configuration ### Per-reporter configuration

View File

@@ -8,7 +8,7 @@
[Fatal errors and multiple threads](#fatal-errors-and-multiple-threads)<br> [Fatal errors and multiple threads](#fatal-errors-and-multiple-threads)<br>
[Performance overhead](#performance-overhead)<br> [Performance overhead](#performance-overhead)<br>
> Thread safe assertions were introduced in Catch2 X.Y.Z > Thread safe assertions were introduced in Catch2 3.9.0
Thread safety in Catch2 is currently limited to all the assertion macros. Thread safety in Catch2 is currently limited to all the assertion macros.
Interacting with benchmark macros, message macros (e.g. `INFO` or `CAPTURE`), Interacting with benchmark macros, message macros (e.g. `INFO` or `CAPTURE`),

View File

@@ -6,8 +6,8 @@
// SPDX-License-Identifier: BSL-1.0 // SPDX-License-Identifier: BSL-1.0
// Catch v3.8.1 // Catch v3.9.0
// Generated: 2025-04-08 12:33:19.863332 // Generated: 2025-07-24 22:00:25.173359
// ---------------------------------------------------------- // ----------------------------------------------------------
// This file is an amalgamation of multiple different files. // This file is an amalgamation of multiple different files.
// You probably shouldn't edit it directly. // You probably shouldn't edit it directly.
@@ -986,7 +986,7 @@ namespace Catch {
} }
ScopedMessage::~ScopedMessage() { ScopedMessage::~ScopedMessage() {
if ( !uncaught_exceptions() && !m_moved ){ if ( !m_moved ){
getResultCapture().popScopedMessage(m_info); getResultCapture().popScopedMessage(m_info);
} }
} }
@@ -1056,11 +1056,9 @@ namespace Catch {
m_messages.back().message += " := "; m_messages.back().message += " := ";
} }
Capturer::~Capturer() { Capturer::~Capturer() {
if ( !uncaught_exceptions() ){ assert( m_captured == m_messages.size() );
assert( m_captured == m_messages.size() ); for ( size_t i = 0; i < m_captured; ++i )
for( size_t i = 0; i < m_captured; ++i ) m_resultCapture.popScopedMessage( m_messages[i] );
m_resultCapture.popScopedMessage( m_messages[i] );
}
} }
void Capturer::captureValue( size_t index, std::string const& value ) { void Capturer::captureValue( size_t index, std::string const& value ) {
@@ -1161,7 +1159,6 @@ namespace Catch {
#include <algorithm>
#include <cassert> #include <cassert>
#include <exception> #include <exception>
#include <iomanip> #include <iomanip>
@@ -1170,14 +1167,6 @@ namespace Catch {
namespace Catch { namespace Catch {
namespace { namespace {
static constexpr int TestFailureExitCode = 42;
static constexpr int UnspecifiedErrorExitCode = 1;
static constexpr int AllTestsSkippedExitCode = 4;
static constexpr int NoTestsRunExitCode = 2;
static constexpr int UnmatchedTestSpecExitCode = 3;
static constexpr int InvalidTestSpecExitCode = 5;
IEventListenerPtr createReporter(std::string const& reporterName, ReporterConfig&& config) { IEventListenerPtr createReporter(std::string const& reporterName, ReporterConfig&& config) {
auto reporter = Catch::getRegistryHub().getReporterRegistry().create(reporterName, CATCH_MOVE(config)); auto reporter = Catch::getRegistryHub().getReporterRegistry().create(reporterName, CATCH_MOVE(config));
CATCH_ENFORCE(reporter, "No reporter registered with name: '" << reporterName << '\''); CATCH_ENFORCE(reporter, "No reporter registered with name: '" << reporterName << '\'');
@@ -1935,7 +1924,6 @@ namespace Catch {
#include <cmath>
#include <iomanip> #include <iomanip>
namespace Catch { namespace Catch {
@@ -2283,7 +2271,7 @@ namespace Catch {
} }
Version const& libraryVersion() { Version const& libraryVersion() {
static Version version( 3, 8, 1, "", 0 ); static Version version( 3, 9, 0, "", 0 );
return version; return version;
} }
@@ -4088,7 +4076,7 @@ namespace Catch {
// There is no 1-1 mapping between signals and windows exceptions. // There is no 1-1 mapping between signals and windows exceptions.
// Windows can easily distinguish between SO and SigSegV, // Windows can easily distinguish between SO and SigSegV,
// but SigInt, SigTerm, etc are handled differently. // but SigInt, SigTerm, etc are handled differently.
static SignalDefs signalDefs[] = { static constexpr SignalDefs signalDefs[] = {
{ EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" }, { EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" },
{ EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" }, { EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" },
{ EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" }, { EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" },
@@ -4159,7 +4147,7 @@ namespace Catch {
const char* name; const char* name;
}; };
static SignalDefs signalDefs[] = { static constexpr SignalDefs signalDefs[] = {
{ SIGINT, "SIGINT - Terminal interrupt signal" }, { SIGINT, "SIGINT - Terminal interrupt signal" },
{ SIGILL, "SIGILL - Illegal instruction signal" }, { SIGILL, "SIGILL - Illegal instruction signal" },
{ SIGFPE, "SIGFPE - Floating point error signal" }, { SIGFPE, "SIGFPE - Floating point error signal" },
@@ -4323,8 +4311,6 @@ namespace Catch {
#include <cstdio> #include <cstdio>
#include <fstream> #include <fstream>
#include <sstream>
#include <vector>
namespace Catch { namespace Catch {
@@ -4765,7 +4751,7 @@ namespace Catch {
namespace Catch { namespace Catch {
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION CATCH_INTERNAL_START_WARNINGS_SUPPRESSION
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
static LeakDetector leakDetector; static const LeakDetector leakDetector;
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
} }
@@ -5216,6 +5202,12 @@ namespace Catch {
#if defined( __clang__ )
# define CATCH2_CLANG_NO_SANITIZE_INTEGER \
__attribute__( ( no_sanitize( "unsigned-integer-overflow" ) ) )
#else
# define CATCH2_CLANG_NO_SANITIZE_INTEGER
#endif
namespace Catch { namespace Catch {
namespace { namespace {
@@ -5225,6 +5217,7 @@ namespace {
#pragma warning(disable:4146) // we negate uint32 during the rotate #pragma warning(disable:4146) // we negate uint32 during the rotate
#endif #endif
// Safe rotr implementation thanks to John Regehr // Safe rotr implementation thanks to John Regehr
CATCH2_CLANG_NO_SANITIZE_INTEGER
uint32_t rotate_right(uint32_t val, uint32_t count) { uint32_t rotate_right(uint32_t val, uint32_t count) {
const uint32_t mask = 31; const uint32_t mask = 31;
count &= mask; count &= mask;
@@ -5258,6 +5251,7 @@ namespace {
} }
} }
CATCH2_CLANG_NO_SANITIZE_INTEGER
SimplePcg32::result_type SimplePcg32::operator()() { SimplePcg32::result_type SimplePcg32::operator()() {
// prepare the output value // prepare the output value
const uint32_t xorshifted = static_cast<uint32_t>(((m_state >> 18u) ^ m_state) >> 27u); const uint32_t xorshifted = static_cast<uint32_t>(((m_state >> 18u) ^ m_state) >> 27u);
@@ -5742,23 +5736,55 @@ namespace Catch {
} // namespace } // namespace
} }
namespace Detail {
// Assertions are owned by the thread that is executing them.
// This allows for lock-free progress in common cases where we
// do not need to send the assertion events to the reporter.
// This also implies that messages are owned by their respective
// threads, and should not be shared across different threads.
//
// For simplicity, we disallow messages in multi-threaded contexts,
// but in the future we can enable them under this logic.
//
// This implies that various pieces of metadata referring to last
// assertion result/source location/message handling, etc
// should also be thread local. For now we just use naked globals
// below, in the future we will want to allocate piece of memory
// from heap, to avoid consuming too much thread-local storage.
// This is used for the "if" part of CHECKED_IF/CHECKED_ELSE
static thread_local bool g_lastAssertionPassed = false;
// Should we clear message scopes before sending off the messages to
// reporter? Set in `assertionPassedFastPath` to avoid doing the full
// clear there for performance reasons.
static thread_local bool g_clearMessageScopes = false;
// This is the source location for last encountered macro. It is
// used to provide the users with more precise location of error
// when an unexpected exception/fatal error happens.
static thread_local SourceLineInfo g_lastKnownLineInfo("DummyLocation", static_cast<size_t>(-1));
}
RunContext::RunContext(IConfig const* _config, IEventListenerPtr&& reporter) RunContext::RunContext(IConfig const* _config, IEventListenerPtr&& reporter)
: m_runInfo(_config->name()), : m_runInfo(_config->name()),
m_config(_config), m_config(_config),
m_reporter(CATCH_MOVE(reporter)), m_reporter(CATCH_MOVE(reporter)),
m_lastAssertionInfo{ StringRef(), SourceLineInfo("",0), StringRef(), ResultDisposition::Normal },
m_outputRedirect( makeOutputRedirect( m_reporter->getPreferences().shouldRedirectStdOut ) ), m_outputRedirect( makeOutputRedirect( m_reporter->getPreferences().shouldRedirectStdOut ) ),
m_includeSuccessfulResults( m_config->includeSuccessfulResults() || m_reporter->getPreferences().shouldReportAllAssertions ) m_abortAfterXFailedAssertions( m_config->abortAfter() ),
m_reportAssertionStarting( m_reporter->getPreferences().shouldReportAllAssertionStarts ),
m_includeSuccessfulResults( m_config->includeSuccessfulResults() || m_reporter->getPreferences().shouldReportAllAssertions ),
m_shouldDebugBreak( m_config->shouldDebugBreak() )
{ {
getCurrentMutableContext().setResultCapture( this ); getCurrentMutableContext().setResultCapture( this );
m_reporter->testRunStarting(m_runInfo); m_reporter->testRunStarting(m_runInfo);
} }
RunContext::~RunContext() { RunContext::~RunContext() {
updateTotalsFromAtomics();
m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, aborting())); m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, aborting()));
} }
Totals RunContext::runTest(TestCaseHandle const& testCase) { Totals RunContext::runTest(TestCaseHandle const& testCase) {
updateTotalsFromAtomics();
const Totals prevTotals = m_totals; const Totals prevTotals = m_totals;
auto const& testInfo = testCase.getTestCaseInfo(); auto const& testInfo = testCase.getTestCaseInfo();
@@ -5813,6 +5839,7 @@ namespace Catch {
m_reporter->testCasePartialStarting(testInfo, testRuns); m_reporter->testCasePartialStarting(testInfo, testRuns);
updateTotalsFromAtomics();
const auto beforeRunTotals = m_totals; const auto beforeRunTotals = m_totals;
runCurrentTest(); runCurrentTest();
std::string oneRunCout = m_outputRedirect->getStdout(); std::string oneRunCout = m_outputRedirect->getStdout();
@@ -5821,6 +5848,7 @@ namespace Catch {
redirectedCout += oneRunCout; redirectedCout += oneRunCout;
redirectedCerr += oneRunCerr; redirectedCerr += oneRunCerr;
updateTotalsFromAtomics();
const auto singleRunTotals = m_totals.delta(beforeRunTotals); const auto singleRunTotals = m_totals.delta(beforeRunTotals);
auto statsForOneRun = TestCaseStats(testInfo, singleRunTotals, CATCH_MOVE(oneRunCout), CATCH_MOVE(oneRunCerr), aborting()); auto statsForOneRun = TestCaseStats(testInfo, singleRunTotals, CATCH_MOVE(oneRunCout), CATCH_MOVE(oneRunCerr), aborting());
m_reporter->testCasePartialEnded(statsForOneRun, testRuns); m_reporter->testCasePartialEnded(statsForOneRun, testRuns);
@@ -5850,27 +5878,35 @@ namespace Catch {
void RunContext::assertionEnded(AssertionResult&& result) { void RunContext::assertionEnded(AssertionResult&& result) {
Detail::g_lastKnownLineInfo = result.m_info.lineInfo;
if (result.getResultType() == ResultWas::Ok) { if (result.getResultType() == ResultWas::Ok) {
m_totals.assertions.passed++; m_atomicAssertionCount.passed++;
m_lastAssertionPassed = true; Detail::g_lastAssertionPassed = true;
} else if (result.getResultType() == ResultWas::ExplicitSkip) { } else if (result.getResultType() == ResultWas::ExplicitSkip) {
m_totals.assertions.skipped++; m_atomicAssertionCount.skipped++;
m_lastAssertionPassed = true; Detail::g_lastAssertionPassed = true;
} else if (!result.succeeded()) { } else if (!result.succeeded()) {
m_lastAssertionPassed = false; Detail::g_lastAssertionPassed = false;
if (result.isOk()) { if (result.isOk()) {
} }
else if( m_activeTestCase->getTestCaseInfo().okToFail() ) else if( m_activeTestCase->getTestCaseInfo().okToFail() ) // Read from a shared state established before the threads could start, this is fine
m_totals.assertions.failedButOk++; m_atomicAssertionCount.failedButOk++;
else else
m_totals.assertions.failed++; m_atomicAssertionCount.failed++;
} }
else { else {
m_lastAssertionPassed = true; Detail::g_lastAssertionPassed = true;
} }
// From here, we are touching shared state and need mutex.
Detail::LockGuard lock( m_assertionMutex );
{ {
if ( Detail::g_clearMessageScopes ) {
m_messageScopes.clear();
Detail::g_clearMessageScopes = false;
}
auto _ = scopedDeactivate( *m_outputRedirect ); auto _ = scopedDeactivate( *m_outputRedirect );
updateTotalsFromAtomics();
m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ); m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) );
} }
@@ -5882,15 +5918,13 @@ namespace Catch {
// populateReaction is run if it is needed // populateReaction is run if it is needed
m_lastResult = CATCH_MOVE( result ); m_lastResult = CATCH_MOVE( result );
} }
void RunContext::resetAssertionInfo() {
m_lastAssertionInfo.macroName = StringRef();
m_lastAssertionInfo.capturedExpression = "{Unknown expression after the reported line}"_sr;
m_lastAssertionInfo.resultDisposition = ResultDisposition::Normal;
}
void RunContext::notifyAssertionStarted( AssertionInfo const& info ) { void RunContext::notifyAssertionStarted( AssertionInfo const& info ) {
auto _ = scopedDeactivate( *m_outputRedirect ); if (m_reportAssertionStarting) {
m_reporter->assertionStarting( info ); Detail::LockGuard lock( m_assertionMutex );
auto _ = scopedDeactivate( *m_outputRedirect );
m_reporter->assertionStarting( info );
}
} }
bool RunContext::sectionStarted( StringRef sectionName, bool RunContext::sectionStarted( StringRef sectionName,
@@ -5906,13 +5940,14 @@ namespace Catch {
m_activeSections.push_back(&sectionTracker); m_activeSections.push_back(&sectionTracker);
SectionInfo sectionInfo( sectionLineInfo, static_cast<std::string>(sectionName) ); SectionInfo sectionInfo( sectionLineInfo, static_cast<std::string>(sectionName) );
m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; Detail::g_lastKnownLineInfo = sectionLineInfo;
{ {
auto _ = scopedDeactivate( *m_outputRedirect ); auto _ = scopedDeactivate( *m_outputRedirect );
m_reporter->sectionStarting( sectionInfo ); m_reporter->sectionStarting( sectionInfo );
} }
updateTotalsFromAtomics();
assertions = m_totals.assertions; assertions = m_totals.assertions;
return true; return true;
@@ -5920,12 +5955,11 @@ namespace Catch {
IGeneratorTracker* IGeneratorTracker*
RunContext::acquireGeneratorTracker( StringRef generatorName, RunContext::acquireGeneratorTracker( StringRef generatorName,
SourceLineInfo const& lineInfo ) { SourceLineInfo const& lineInfo ) {
using namespace Generators; auto* tracker = Generators::GeneratorTracker::acquire(
GeneratorTracker* tracker = GeneratorTracker::acquire(
m_trackerContext, m_trackerContext,
TestCaseTracking::NameAndLocationRef( TestCaseTracking::NameAndLocationRef(
generatorName, lineInfo ) ); generatorName, lineInfo ) );
m_lastAssertionInfo.lineInfo = lineInfo; Detail::g_lastKnownLineInfo = lineInfo;
return tracker; return tracker;
} }
@@ -5938,7 +5972,7 @@ namespace Catch {
auto& currentTracker = m_trackerContext.currentTracker(); auto& currentTracker = m_trackerContext.currentTracker();
assert( assert(
currentTracker.nameAndLocation() != nameAndLoc && currentTracker.nameAndLocation() != nameAndLoc &&
"Trying to create tracker for a genreator that already has one" ); "Trying to create tracker for a generator that already has one" );
auto newTracker = Catch::Detail::make_unique<Generators::GeneratorTracker>( auto newTracker = Catch::Detail::make_unique<Generators::GeneratorTracker>(
CATCH_MOVE(nameAndLoc), m_trackerContext, &currentTracker ); CATCH_MOVE(nameAndLoc), m_trackerContext, &currentTracker );
@@ -5957,12 +5991,13 @@ namespace Catch {
return false; return false;
if (m_trackerContext.currentTracker().hasChildren()) if (m_trackerContext.currentTracker().hasChildren())
return false; return false;
m_totals.assertions.failed++; m_atomicAssertionCount.failed++;
assertions.failed++; assertions.failed++;
return true; return true;
} }
void RunContext::sectionEnded(SectionEndInfo&& endInfo) { void RunContext::sectionEnded(SectionEndInfo&& endInfo) {
updateTotalsFromAtomics();
Counts assertions = m_totals.assertions - endInfo.prevAssertions; Counts assertions = m_totals.assertions - endInfo.prevAssertions;
bool missingAssertions = testForMissingAssertions(assertions); bool missingAssertions = testForMissingAssertions(assertions);
@@ -5979,9 +6014,6 @@ namespace Catch {
endInfo.durationInSeconds, endInfo.durationInSeconds,
missingAssertions ) ); missingAssertions ) );
} }
m_messages.clear();
m_messageScopes.clear();
} }
void RunContext::sectionEndedEarly(SectionEndInfo&& endInfo) { void RunContext::sectionEndedEarly(SectionEndInfo&& endInfo) {
@@ -6016,8 +6048,18 @@ namespace Catch {
m_messages.push_back(message); m_messages.push_back(message);
} }
void RunContext::popScopedMessage(MessageInfo const & message) { void RunContext::popScopedMessage( MessageInfo const& message ) {
m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end()); // Note: On average, it would probably be better to look for the message
// backwards. However, we do not expect to have to deal with more
// messages than low single digits, so the optimization is tiny,
// and we would have to hand-write the loop to avoid terrible
// codegen of reverse iterators in debug mode.
m_messages.erase(
std::find_if( m_messages.begin(),
m_messages.end(),
[id = message.sequence]( MessageInfo const& msg ) {
return msg.sequence == id;
} ) );
} }
void RunContext::emplaceUnscopedMessage( MessageBuilder&& builder ) { void RunContext::emplaceUnscopedMessage( MessageBuilder&& builder ) {
@@ -6031,6 +6073,18 @@ namespace Catch {
} }
const AssertionResult * RunContext::getLastResult() const { const AssertionResult * RunContext::getLastResult() const {
// m_lastResult is updated inside the assertion slow-path, under
// a mutex, so the read needs to happen under mutex as well.
// TBD: The last result only makes sense if it is a thread-local
// thing, because the answer is different per thread, like
// last line info, whether last assertion passed, and so on.
//
// However, the last result was also never updated in the
// assertion fast path, so it was always somewhat broken,
// and since IResultCapture::getLastResult is deprecated,
// we will leave it as is, until it is finally removed.
Detail::LockGuard _( m_assertionMutex );
return &(*m_lastResult); return &(*m_lastResult);
} }
@@ -6039,28 +6093,44 @@ namespace Catch {
} }
void RunContext::handleFatalErrorCondition( StringRef message ) { void RunContext::handleFatalErrorCondition( StringRef message ) {
// TODO: scoped deactivate here? Just give up and do best effort? // We lock only when touching the reporters directly, to avoid
// the deactivation can break things further, OTOH so can the // deadlocks when we call into other functions that also want
// capture // to lock the mutex before touching reporters.
auto _ = scopedDeactivate( *m_outputRedirect ); //
// This does mean that we allow other threads to run while handling
// a fatal error, but this is all a best effort attempt anyway.
{
Detail::LockGuard lock( m_assertionMutex );
// TODO: scoped deactivate here? Just give up and do best effort?
// the deactivation can break things further, OTOH so can the
// capture
auto _ = scopedDeactivate( *m_outputRedirect );
// First notify reporter that bad things happened // First notify reporter that bad things happened
m_reporter->fatalErrorEncountered( message ); m_reporter->fatalErrorEncountered( message );
}
// Don't rebuild the result -- the stringification itself can cause more fatal errors // Don't rebuild the result -- the stringification itself can cause more fatal errors
// Instead, fake a result data. // Instead, fake a result data.
AssertionResultData tempResult( ResultWas::FatalErrorCondition, { false } ); AssertionResultData tempResult( ResultWas::FatalErrorCondition, { false } );
tempResult.message = static_cast<std::string>(message); tempResult.message = static_cast<std::string>(message);
AssertionResult result(m_lastAssertionInfo, CATCH_MOVE(tempResult)); AssertionResult result( makeDummyAssertionInfo(),
CATCH_MOVE( tempResult ) );
assertionEnded(CATCH_MOVE(result) ); assertionEnded(CATCH_MOVE(result) );
resetAssertionInfo();
// At this point we touch sections/test cases from this thread
// to try and end them. Technically that is not supported when
// using multiple threads, but the worst thing that can happen
// is that the process aborts harder :-D
Detail::LockGuard lock( m_assertionMutex );
// Best effort cleanup for sections that have not been destructed yet // Best effort cleanup for sections that have not been destructed yet
// Since this is a fatal error, we have not had and won't have the opportunity to destruct them properly // Since this is a fatal error, we have not had and won't have the opportunity to destruct them properly
while (!m_activeSections.empty()) { while (!m_activeSections.empty()) {
auto nl = m_activeSections.back()->nameAndLocation(); auto const& nl = m_activeSections.back()->nameAndLocation();
SectionEndInfo endInfo{ SectionInfo(CATCH_MOVE(nl.location), CATCH_MOVE(nl.name)), {}, 0.0 }; SectionEndInfo endInfo{ SectionInfo(nl.location, nl.name), {}, 0.0 };
sectionEndedEarly(CATCH_MOVE(endInfo)); sectionEndedEarly(CATCH_MOVE(endInfo));
} }
handleUnfinishedSections(); handleUnfinishedSections();
@@ -6085,32 +6155,44 @@ namespace Catch {
std::string(), std::string(),
false)); false));
m_totals.testCases.failed++; m_totals.testCases.failed++;
updateTotalsFromAtomics();
m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, false)); m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, false));
} }
bool RunContext::lastAssertionPassed() { bool RunContext::lastAssertionPassed() {
return m_lastAssertionPassed; return Detail::g_lastAssertionPassed;
} }
void RunContext::assertionPassed() { void RunContext::assertionPassedFastPath(SourceLineInfo lineInfo) {
m_lastAssertionPassed = true; // We want to save the line info for better experience with unexpected assertions
++m_totals.assertions.passed; Detail::g_lastKnownLineInfo = lineInfo;
resetAssertionInfo(); ++m_atomicAssertionCount.passed;
m_messageScopes.clear(); Detail::g_lastAssertionPassed = true;
Detail::g_clearMessageScopes = true;
}
void RunContext::updateTotalsFromAtomics() {
m_totals.assertions = Counts{
m_atomicAssertionCount.passed,
m_atomicAssertionCount.failed,
m_atomicAssertionCount.failedButOk,
m_atomicAssertionCount.skipped,
};
} }
bool RunContext::aborting() const { bool RunContext::aborting() const {
return m_totals.assertions.failed >= static_cast<std::size_t>(m_config->abortAfter()); return m_atomicAssertionCount.failed >= m_abortAfterXFailedAssertions;
} }
void RunContext::runCurrentTest() { void RunContext::runCurrentTest() {
auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name); SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);
m_reporter->sectionStarting(testCaseSection); m_reporter->sectionStarting(testCaseSection);
updateTotalsFromAtomics();
Counts prevAssertions = m_totals.assertions; Counts prevAssertions = m_totals.assertions;
double duration = 0; double duration = 0;
m_shouldReportUnexpected = true; m_shouldReportUnexpected = true;
m_lastAssertionInfo = { "TEST_CASE"_sr, testCaseInfo.lineInfo, StringRef(), ResultDisposition::Normal }; Detail::g_lastKnownLineInfo = testCaseInfo.lineInfo;
Timer timer; Timer timer;
CATCH_TRY { CATCH_TRY {
@@ -6127,18 +6209,23 @@ namespace Catch {
} CATCH_CATCH_ALL { } CATCH_CATCH_ALL {
// Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions
// are reported without translation at the point of origin. // are reported without translation at the point of origin.
if( m_shouldReportUnexpected ) { if ( m_shouldReportUnexpected ) {
AssertionReaction dummyReaction; AssertionReaction dummyReaction;
handleUnexpectedInflightException( m_lastAssertionInfo, translateActiveException(), dummyReaction ); handleUnexpectedInflightException( makeDummyAssertionInfo(),
translateActiveException(),
dummyReaction );
} }
} }
updateTotalsFromAtomics();
Counts assertions = m_totals.assertions - prevAssertions; Counts assertions = m_totals.assertions - prevAssertions;
bool missingAssertions = testForMissingAssertions(assertions); bool missingAssertions = testForMissingAssertions(assertions);
m_testCaseTracker->close(); m_testCaseTracker->close();
handleUnfinishedSections(); handleUnfinishedSections();
m_messages.clear();
m_messageScopes.clear(); m_messageScopes.clear();
// TBD: At this point, m_messages should be empty. Do we want to
// assert that this is true, or keep the defensive clear call?
m_messages.clear();
SectionStats testCaseSectionStats(CATCH_MOVE(testCaseSection), assertions, duration, missingAssertions); SectionStats testCaseSectionStats(CATCH_MOVE(testCaseSection), assertions, duration, missingAssertions);
m_reporter->sectionEnded(testCaseSectionStats); m_reporter->sectionEnded(testCaseSectionStats);
@@ -6179,7 +6266,7 @@ namespace Catch {
if( result ) { if( result ) {
if (!m_includeSuccessfulResults) { if (!m_includeSuccessfulResults) {
assertionPassed(); assertionPassedFastPath(info.lineInfo);
} }
else { else {
reportExpr(info, ResultWas::Ok, &expr, negated); reportExpr(info, ResultWas::Ok, &expr, negated);
@@ -6187,9 +6274,9 @@ namespace Catch {
} }
else { else {
reportExpr(info, ResultWas::ExpressionFailed, &expr, negated ); reportExpr(info, ResultWas::ExpressionFailed, &expr, negated );
populateReaction( reaction ); populateReaction(
reaction, info.resultDisposition & ResultDisposition::Normal );
} }
resetAssertionInfo();
} }
void RunContext::reportExpr( void RunContext::reportExpr(
AssertionInfo const &info, AssertionInfo const &info,
@@ -6197,7 +6284,7 @@ namespace Catch {
ITransientExpression const *expr, ITransientExpression const *expr,
bool negated ) { bool negated ) {
m_lastAssertionInfo = info; Detail::g_lastKnownLineInfo = info.lineInfo;
AssertionResultData data( resultType, LazyExpression( negated ) ); AssertionResultData data( resultType, LazyExpression( negated ) );
AssertionResult assertionResult{ info, CATCH_MOVE( data ) }; AssertionResult assertionResult{ info, CATCH_MOVE( data ) };
@@ -6212,24 +6299,25 @@ namespace Catch {
std::string&& message, std::string&& message,
AssertionReaction& reaction AssertionReaction& reaction
) { ) {
m_lastAssertionInfo = info; Detail::g_lastKnownLineInfo = info.lineInfo;
AssertionResultData data( resultType, LazyExpression( false ) ); AssertionResultData data( resultType, LazyExpression( false ) );
data.message = CATCH_MOVE( message ); data.message = CATCH_MOVE( message );
AssertionResult assertionResult{ m_lastAssertionInfo, AssertionResult assertionResult{ info,
CATCH_MOVE( data ) }; CATCH_MOVE( data ) };
const auto isOk = assertionResult.isOk(); const auto isOk = assertionResult.isOk();
assertionEnded( CATCH_MOVE(assertionResult) ); assertionEnded( CATCH_MOVE(assertionResult) );
if ( !isOk ) { if ( !isOk ) {
populateReaction( reaction ); populateReaction(
reaction, info.resultDisposition & ResultDisposition::Normal );
} else if ( resultType == ResultWas::ExplicitSkip ) { } else if ( resultType == ResultWas::ExplicitSkip ) {
// TODO: Need to handle this explicitly, as ExplicitSkip is // TODO: Need to handle this explicitly, as ExplicitSkip is
// considered "OK" // considered "OK"
reaction.shouldSkip = true; reaction.shouldSkip = true;
} }
resetAssertionInfo();
} }
void RunContext::handleUnexpectedExceptionNotThrown( void RunContext::handleUnexpectedExceptionNotThrown(
AssertionInfo const& info, AssertionInfo const& info,
AssertionReaction& reaction AssertionReaction& reaction
@@ -6242,49 +6330,67 @@ namespace Catch {
std::string&& message, std::string&& message,
AssertionReaction& reaction AssertionReaction& reaction
) { ) {
m_lastAssertionInfo = info; Detail::g_lastKnownLineInfo = info.lineInfo;
AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) ); AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) );
data.message = CATCH_MOVE(message); data.message = CATCH_MOVE(message);
AssertionResult assertionResult{ info, CATCH_MOVE(data) }; AssertionResult assertionResult{ info, CATCH_MOVE(data) };
assertionEnded( CATCH_MOVE(assertionResult) ); assertionEnded( CATCH_MOVE(assertionResult) );
populateReaction( reaction ); populateReaction( reaction,
resetAssertionInfo(); info.resultDisposition & ResultDisposition::Normal );
} }
void RunContext::populateReaction( AssertionReaction& reaction ) { void RunContext::populateReaction( AssertionReaction& reaction,
reaction.shouldDebugBreak = m_config->shouldDebugBreak(); bool has_normal_disposition ) {
reaction.shouldThrow = aborting() || (m_lastAssertionInfo.resultDisposition & ResultDisposition::Normal); reaction.shouldDebugBreak = m_shouldDebugBreak;
reaction.shouldThrow = aborting() || has_normal_disposition;
}
AssertionInfo RunContext::makeDummyAssertionInfo() {
const bool testCaseJustStarted =
Detail::g_lastKnownLineInfo ==
m_activeTestCase->getTestCaseInfo().lineInfo;
return AssertionInfo{
testCaseJustStarted ? "TEST_CASE"_sr : StringRef(),
Detail::g_lastKnownLineInfo,
testCaseJustStarted ? StringRef() : "{Unknown expression after the reported line}"_sr,
ResultDisposition::Normal
};
} }
void RunContext::handleIncomplete( void RunContext::handleIncomplete(
AssertionInfo const& info AssertionInfo const& info
) { ) {
using namespace std::string_literals; using namespace std::string_literals;
m_lastAssertionInfo = info; Detail::g_lastKnownLineInfo = info.lineInfo;
AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) ); AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) );
data.message = "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE"s; data.message = "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE"s;
AssertionResult assertionResult{ info, CATCH_MOVE( data ) }; AssertionResult assertionResult{ info, CATCH_MOVE( data ) };
assertionEnded( CATCH_MOVE(assertionResult) ); assertionEnded( CATCH_MOVE(assertionResult) );
resetAssertionInfo();
} }
void RunContext::handleNonExpr( void RunContext::handleNonExpr(
AssertionInfo const &info, AssertionInfo const &info,
ResultWas::OfType resultType, ResultWas::OfType resultType,
AssertionReaction &reaction AssertionReaction &reaction
) { ) {
m_lastAssertionInfo = info;
AssertionResultData data( resultType, LazyExpression( false ) ); AssertionResultData data( resultType, LazyExpression( false ) );
AssertionResult assertionResult{ info, CATCH_MOVE( data ) }; AssertionResult assertionResult{ info, CATCH_MOVE( data ) };
const auto isOk = assertionResult.isOk(); const auto isOk = assertionResult.isOk();
assertionEnded( CATCH_MOVE(assertionResult) ); if ( isOk && !m_includeSuccessfulResults ) {
if ( !isOk ) { populateReaction( reaction ); } assertionPassedFastPath( info.lineInfo );
resetAssertionInfo(); return;
} }
assertionEnded( CATCH_MOVE(assertionResult) );
if ( !isOk ) {
populateReaction(
reaction, info.resultDisposition & ResultDisposition::Normal );
}
}
IResultCapture& getResultCapture() { IResultCapture& getResultCapture() {
if (auto* capture = getCurrentContext().getResultCapture()) if (auto* capture = getCurrentContext().getResultCapture())
@@ -6516,7 +6622,7 @@ namespace Catch {
std::string origStr = CATCH_MOVE(str); std::string origStr = CATCH_MOVE(str);
str.clear(); str.clear();
// There is at least one replacement, so reserve with the best guess // There is at least one replacement, so reserve with the best guess
// we can make without actually counting the number of occurences. // we can make without actually counting the number of occurrences.
str.reserve(origStr.size() - replaceThis.size() + withThis.size()); str.reserve(origStr.size() - replaceThis.size() + withThis.size());
do { do {
str.append(origStr, copyBegin, i-copyBegin ); str.append(origStr, copyBegin, i-copyBegin );
@@ -6562,7 +6668,6 @@ namespace Catch {
#include <algorithm> #include <algorithm>
#include <ostream> #include <ostream>
#include <cstring> #include <cstring>
#include <cstdint>
namespace Catch { namespace Catch {
StringRef::StringRef( char const* rawChars ) noexcept StringRef::StringRef( char const* rawChars ) noexcept
@@ -8877,7 +8982,8 @@ private:
<< m_config->testSpec() << m_config->testSpec()
<< '\n'; << '\n';
} }
m_stream << "RNG seed: " << getSeed() << '\n'; m_stream << "RNG seed: " << getSeed() << '\n'
<< std::flush;
} }
void CompactReporter::assertionEnded( AssertionStats const& _assertionStats ) { void CompactReporter::assertionEnded( AssertionStats const& _assertionStats ) {
@@ -9298,7 +9404,10 @@ ConsoleReporter::ConsoleReporter(ReporterConfig&& config):
{ "est run time high mean high std dev", 14, Justification::Right } { "est run time high mean high std dev", 14, Justification::Right }
}; };
} }
}())) {} }())) {
m_preferences.shouldReportAllAssertionStarts = false;
}
ConsoleReporter::~ConsoleReporter() = default; ConsoleReporter::~ConsoleReporter() = default;
std::string ConsoleReporter::getDescription() { std::string ConsoleReporter::getDescription() {
@@ -9313,8 +9422,6 @@ void ConsoleReporter::reportInvalidTestSpec( StringRef arg ) {
m_stream << "Invalid Filter: " << arg << '\n'; m_stream << "Invalid Filter: " << arg << '\n';
} }
void ConsoleReporter::assertionStarting(AssertionInfo const&) {}
void ConsoleReporter::assertionEnded(AssertionStats const& _assertionStats) { void ConsoleReporter::assertionEnded(AssertionStats const& _assertionStats) {
AssertionResult const& result = _assertionStats.assertionResult; AssertionResult const& result = _assertionStats.assertionResult;
@@ -9426,7 +9533,8 @@ void ConsoleReporter::testRunStarting(TestRunInfo const& _testRunInfo) {
m_stream << m_colour->guardColour( Colour::BrightYellow ) << "Filters: " m_stream << m_colour->guardColour( Colour::BrightYellow ) << "Filters: "
<< m_config->testSpec() << '\n'; << m_config->testSpec() << '\n';
} }
m_stream << "Randomness seeded to: " << getSeed() << '\n'; m_stream << "Randomness seeded to: " << getSeed() << '\n'
<< std::flush;
} }
void ConsoleReporter::lazyPrint() { void ConsoleReporter::lazyPrint() {
@@ -9754,6 +9862,7 @@ namespace Catch {
#include <algorithm> #include <algorithm>
#include <cfloat> #include <cfloat>
#include <cmath>
#include <cstdio> #include <cstdio>
#include <ostream> #include <ostream>
#include <iomanip> #include <iomanip>
@@ -9917,9 +10026,29 @@ namespace Catch {
out << "All available tags:\n"; out << "All available tags:\n";
} }
// minimum whitespace to pad tag counts, possibly overwritten below
size_t maxTagCountLen = 2;
// determine necessary padding for tag count column
if ( ! tags.empty() ) {
const auto maxTagCount =
std::max_element( tags.begin(),
tags.end(),
[]( auto const& lhs, auto const& rhs ) {
return lhs.count < rhs.count;
} )
->count;
// more padding necessary for 3+ digits
if (maxTagCount >= 100) {
auto numDigits = 1 + std::floor( std::log10( maxTagCount ) );
maxTagCountLen = static_cast<size_t>( numDigits );
}
}
for ( auto const& tagCount : tags ) { for ( auto const& tagCount : tags ) {
ReusableStringStream rss; ReusableStringStream rss;
rss << " " << std::setw( 2 ) << tagCount.count << " "; rss << " " << std::setw( maxTagCountLen ) << tagCount.count << " ";
auto str = rss.str(); auto str = rss.str();
auto wrapper = TextFlow::Column( tagCount.all() ) auto wrapper = TextFlow::Column( tagCount.all() )
.initialIndent( 0 ) .initialIndent( 0 )
@@ -10117,6 +10246,8 @@ namespace Catch {
// not, but for machine-parseable reporters I think the answer // not, but for machine-parseable reporters I think the answer
// should be yes. // should be yes.
m_preferences.shouldReportAllAssertions = true; m_preferences.shouldReportAllAssertions = true;
// We only handle assertions when they end
m_preferences.shouldReportAllAssertionStarts = false;
m_objectWriters.emplace( m_stream ); m_objectWriters.emplace( m_stream );
m_writers.emplace( Writer::Object ); m_writers.emplace( Writer::Object );
@@ -10346,7 +10477,6 @@ namespace Catch {
endObject(); endObject();
} }
void JsonReporter::assertionStarting( AssertionInfo const& /*assertionInfo*/ ) {}
void JsonReporter::assertionEnded( AssertionStats const& assertionStats ) { void JsonReporter::assertionEnded( AssertionStats const& assertionStats ) {
// TODO: There is lot of different things to handle here, but // TODO: There is lot of different things to handle here, but
// we can fill it in later, after we show that the basic // we can fill it in later, after we show that the basic
@@ -10513,6 +10643,7 @@ namespace Catch {
{ {
m_preferences.shouldRedirectStdOut = true; m_preferences.shouldRedirectStdOut = true;
m_preferences.shouldReportAllAssertions = false; m_preferences.shouldReportAllAssertions = false;
m_preferences.shouldReportAllAssertionStarts = false;
m_shouldStoreSuccesfulAssertions = false; m_shouldStoreSuccesfulAssertions = false;
} }
@@ -10743,6 +10874,8 @@ namespace Catch {
reporterish.getPreferences().shouldRedirectStdOut; reporterish.getPreferences().shouldRedirectStdOut;
m_preferences.shouldReportAllAssertions |= m_preferences.shouldReportAllAssertions |=
reporterish.getPreferences().shouldReportAllAssertions; reporterish.getPreferences().shouldReportAllAssertions;
m_preferences.shouldReportAllAssertionStarts |=
reporterish.getPreferences().shouldReportAllAssertionStarts;
} }
void MultiReporter::addListener( IEventListenerPtr&& listener ) { void MultiReporter::addListener( IEventListenerPtr&& listener ) {
@@ -11300,7 +11433,8 @@ namespace Catch {
if ( m_config->testSpec().hasFilters() ) { if ( m_config->testSpec().hasFilters() ) {
m_stream << "# filters: " << m_config->testSpec() << '\n'; m_stream << "# filters: " << m_config->testSpec() << '\n';
} }
m_stream << "# rng-seed: " << m_config->rngSeed() << '\n'; m_stream << "# rng-seed: " << m_config->rngSeed() << '\n'
<< std::flush;
} }
void TAPReporter::noMatchingTestCases( StringRef unmatchedSpec ) { void TAPReporter::noMatchingTestCases( StringRef unmatchedSpec ) {
@@ -11514,6 +11648,7 @@ namespace Catch {
{ {
m_preferences.shouldRedirectStdOut = true; m_preferences.shouldRedirectStdOut = true;
m_preferences.shouldReportAllAssertions = true; m_preferences.shouldReportAllAssertions = true;
m_preferences.shouldReportAllAssertionStarts = false;
} }
XmlReporter::~XmlReporter() = default; XmlReporter::~XmlReporter() = default;
@@ -11570,8 +11705,6 @@ namespace Catch {
} }
} }
void XmlReporter::assertionStarting( AssertionInfo const& ) { }
void XmlReporter::assertionEnded( AssertionStats const& assertionStats ) { void XmlReporter::assertionEnded( AssertionStats const& assertionStats ) {
AssertionResult const& result = assertionStats.assertionResult; AssertionResult const& result = assertionStats.assertionResult;

View File

@@ -6,8 +6,8 @@
// SPDX-License-Identifier: BSL-1.0 // SPDX-License-Identifier: BSL-1.0
// Catch v3.8.1 // Catch v3.9.0
// Generated: 2025-04-08 12:33:19.851017 // Generated: 2025-07-24 22:00:24.654688
// ---------------------------------------------------------- // ----------------------------------------------------------
// This file is an amalgamation of multiple different files. // This file is an amalgamation of multiple different files.
// You probably shouldn't edit it directly. // You probably shouldn't edit it directly.
@@ -1100,9 +1100,7 @@ namespace Catch {
AssertionReaction &reaction ) = 0; AssertionReaction &reaction ) = 0;
virtual bool lastAssertionPassed() = 0; virtual bool lastAssertionPassed() = 0;
virtual void assertionPassed() = 0;
// Deprecated, do not use: // Deprecated, do not use:
virtual std::string getCurrentTestName() const = 0; virtual std::string getCurrentTestName() const = 0;
@@ -1129,6 +1127,7 @@ namespace Catch {
//! Deriving classes become noncopyable and nonmovable //! Deriving classes become noncopyable and nonmovable
class NonCopyable { class NonCopyable {
public:
NonCopyable( NonCopyable const& ) = delete; NonCopyable( NonCopyable const& ) = delete;
NonCopyable( NonCopyable&& ) = delete; NonCopyable( NonCopyable&& ) = delete;
NonCopyable& operator=( NonCopyable const& ) = delete; NonCopyable& operator=( NonCopyable const& ) = delete;
@@ -1144,7 +1143,6 @@ namespace Catch {
#endif // CATCH_NONCOPYABLE_HPP_INCLUDED #endif // CATCH_NONCOPYABLE_HPP_INCLUDED
#include <chrono> #include <chrono>
#include <iosfwd>
#include <string> #include <string>
#include <vector> #include <vector>
@@ -1599,8 +1597,7 @@ namespace Catch {
namespace Benchmark { namespace Benchmark {
namespace Detail { namespace Detail {
template <typename T, typename U> template <typename T, typename U>
struct is_related static constexpr bool is_related_v = std::is_same<std::decay_t<T>, std::decay_t<U>>::value;
: std::is_same<std::decay_t<T>, std::decay_t<U>> {};
/// We need to reinvent std::function because every piece of code that might add overhead /// We need to reinvent std::function because every piece of code that might add overhead
/// in a measurement context needs to have consistent performance characteristics so that we /// in a measurement context needs to have consistent performance characteristics so that we
@@ -1641,7 +1638,7 @@ namespace Catch {
BenchmarkFunction(); BenchmarkFunction();
template <typename Fun, template <typename Fun,
std::enable_if_t<!is_related<Fun, BenchmarkFunction>::value, int> = 0> std::enable_if_t<!is_related_v<Fun, BenchmarkFunction>, int> = 0>
BenchmarkFunction(Fun&& fun) BenchmarkFunction(Fun&& fun)
: f(new model<std::decay_t<Fun>>(CATCH_FORWARD(fun))) {} : f(new model<std::decay_t<Fun>>(CATCH_FORWARD(fun))) {}
@@ -1767,8 +1764,6 @@ namespace Catch {
#define CATCH_TIMING_HPP_INCLUDED #define CATCH_TIMING_HPP_INCLUDED
#include <type_traits>
namespace Catch { namespace Catch {
namespace Benchmark { namespace Benchmark {
template <typename Result> template <typename Result>
@@ -2167,7 +2162,7 @@ namespace Catch {
} }
// sets lambda to be used in fun *and* executes benchmark! // sets lambda to be used in fun *and* executes benchmark!
template <typename Fun, std::enable_if_t<!Detail::is_related<Fun, Benchmark>::value, int> = 0> template <typename Fun, std::enable_if_t<!Detail::is_related_v<Fun, Benchmark>, int> = 0>
Benchmark & operator=(Fun func) { Benchmark & operator=(Fun func) {
auto const* cfg = getCurrentContext().getConfig(); auto const* cfg = getCurrentContext().getConfig();
if (!cfg->skipBenchmarks()) { if (!cfg->skipBenchmarks()) {
@@ -2496,18 +2491,14 @@ namespace Catch {
return rawMemoryToString( &object, sizeof(object) ); return rawMemoryToString( &object, sizeof(object) );
} }
template<typename T> template<typename T,typename = void>
class IsStreamInsertable { static constexpr bool IsStreamInsertable_v = false;
template<typename Stream, typename U>
static auto test(int)
-> decltype(std::declval<Stream&>() << std::declval<U>(), std::true_type());
template<typename, typename> template <typename T>
static auto test(...)->std::false_type; static constexpr bool IsStreamInsertable_v<
T,
public: decltype( void( std::declval<std::ostream&>() << std::declval<T>() ) )> =
static const bool value = decltype(test<std::ostream, const T&>(0))::value; true;
};
template<typename E> template<typename E>
std::string convertUnknownEnumToString( E e ); std::string convertUnknownEnumToString( E e );
@@ -2552,7 +2543,7 @@ namespace Catch {
struct StringMaker { struct StringMaker {
template <typename Fake = T> template <typename Fake = T>
static static
std::enable_if_t<::Catch::Detail::IsStreamInsertable<Fake>::value, std::string> std::enable_if_t<::Catch::Detail::IsStreamInsertable_v<Fake>, std::string>
convert(const Fake& value) { convert(const Fake& value) {
ReusableStringStream rss; ReusableStringStream rss;
// NB: call using the function-like syntax to avoid ambiguity with // NB: call using the function-like syntax to avoid ambiguity with
@@ -2563,7 +2554,7 @@ namespace Catch {
template <typename Fake = T> template <typename Fake = T>
static static
std::enable_if_t<!::Catch::Detail::IsStreamInsertable<Fake>::value, std::string> std::enable_if_t<!::Catch::Detail::IsStreamInsertable_v<Fake>, std::string>
convert( const Fake& value ) { convert( const Fake& value ) {
#if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER) #if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER)
return Detail::convertUnstreamable(value); return Detail::convertUnstreamable(value);
@@ -2955,7 +2946,7 @@ namespace Catch {
} }
template<typename R> template<typename R>
struct StringMaker<R, std::enable_if_t<is_range<R>::value && !::Catch::Detail::IsStreamInsertable<R>::value>> { struct StringMaker<R, std::enable_if_t<is_range<R>::value && !::Catch::Detail::IsStreamInsertable_v<R>>> {
static std::string convert( R const& range ) { static std::string convert( R const& range ) {
return rangeToString( range ); return rangeToString( range );
} }
@@ -3792,7 +3783,7 @@ namespace Catch {
WarnAbout::What warnings = WarnAbout::Nothing; WarnAbout::What warnings = WarnAbout::Nothing;
ShowDurations showDurations = ShowDurations::DefaultForReporter; ShowDurations showDurations = ShowDurations::DefaultForReporter;
double minDuration = -1; double minDuration = -1;
TestRunOrder runOrder = TestRunOrder::Declared; TestRunOrder runOrder = TestRunOrder::Randomized;
ColourMode defaultColourMode = ColourMode::PlatformDefault; ColourMode defaultColourMode = ColourMode::PlatformDefault;
WaitForKeypress::When waitForKeypress = WaitForKeypress::Never; WaitForKeypress::When waitForKeypress = WaitForKeypress::Never;
@@ -3938,6 +3929,19 @@ namespace Catch {
#define CATCH_MESSAGE_INFO_HPP_INCLUDED #define CATCH_MESSAGE_INFO_HPP_INCLUDED
#ifndef CATCH_DEPRECATION_MACRO_HPP_INCLUDED
#define CATCH_DEPRECATION_MACRO_HPP_INCLUDED
#if !defined( CATCH_CONFIG_NO_DEPRECATION_ANNOTATIONS )
# define DEPRECATED( msg ) [[deprecated( msg )]]
#else
# define DEPRECATED( msg )
#endif
#endif // CATCH_DEPRECATION_MACRO_HPP_INCLUDED
#include <string> #include <string>
namespace Catch { namespace Catch {
@@ -3953,9 +3957,11 @@ namespace Catch {
ResultWas::OfType type; ResultWas::OfType type;
unsigned int sequence; unsigned int sequence;
DEPRECATED( "Explicitly use the 'sequence' member instead" )
bool operator == (MessageInfo const& other) const { bool operator == (MessageInfo const& other) const {
return sequence == other.sequence; return sequence == other.sequence;
} }
DEPRECATED( "Explicitly use the 'sequence' member instead" )
bool operator < (MessageInfo const& other) const { bool operator < (MessageInfo const& other) const {
return sequence < other.sequence; return sequence < other.sequence;
} }
@@ -4237,15 +4243,13 @@ namespace Catch {
}; };
template <typename F, typename = void> template <typename F, typename = void>
struct is_unary_function : std::false_type {}; static constexpr bool is_unary_function_v = false;
template <typename F> template <typename F>
struct is_unary_function< static constexpr bool is_unary_function_v<
F, F,
Catch::Detail::void_t<decltype( Catch::Detail::void_t<decltype( std::declval<F>()(
std::declval<F>()( fake_arg() ) ) fake_arg() ) )>> = true;
>
> : std::true_type {};
// Traits for extracting arg and return type of lambdas (for single // Traits for extracting arg and return type of lambdas (for single
// argument lambdas) // argument lambdas)
@@ -4678,14 +4682,14 @@ namespace Catch {
template <typename T, template <typename T,
typename = typename std::enable_if_t< typename = typename std::enable_if_t<
!Detail::is_unary_function<T>::value>> !Detail::is_unary_function_v<T>>>
ParserRefImpl( T& ref, StringRef hint ): ParserRefImpl( T& ref, StringRef hint ):
m_ref( std::make_shared<BoundValueRef<T>>( ref ) ), m_ref( std::make_shared<BoundValueRef<T>>( ref ) ),
m_hint( hint ) {} m_hint( hint ) {}
template <typename LambdaT, template <typename LambdaT,
typename = typename std::enable_if_t< typename = typename std::enable_if_t<
Detail::is_unary_function<LambdaT>::value>> Detail::is_unary_function_v<LambdaT>>>
ParserRefImpl( LambdaT const& ref, StringRef hint ): ParserRefImpl( LambdaT const& ref, StringRef hint ):
m_ref( std::make_shared<BoundLambda<LambdaT>>( ref ) ), m_ref( std::make_shared<BoundLambda<LambdaT>>( ref ) ),
m_hint( hint ) {} m_hint( hint ) {}
@@ -4752,7 +4756,7 @@ namespace Catch {
template <typename LambdaT, template <typename LambdaT,
typename = typename std::enable_if_t< typename = typename std::enable_if_t<
Detail::is_unary_function<LambdaT>::value>> Detail::is_unary_function_v<LambdaT>>>
Opt( LambdaT const& ref, StringRef hint ): Opt( LambdaT const& ref, StringRef hint ):
ParserRefImpl( ref, hint ) {} ParserRefImpl( ref, hint ) {}
@@ -4762,7 +4766,7 @@ namespace Catch {
template <typename T, template <typename T,
typename = typename std::enable_if_t< typename = typename std::enable_if_t<
!Detail::is_unary_function<T>::value>> !Detail::is_unary_function_v<T>>>
Opt( T& ref, StringRef hint ): Opt( T& ref, StringRef hint ):
ParserRefImpl( ref, hint ) {} ParserRefImpl( ref, hint ) {}
@@ -4932,6 +4936,14 @@ namespace Catch {
namespace Catch { namespace Catch {
// TODO: Use C++17 `inline` variables
constexpr int UnspecifiedErrorExitCode = 1;
constexpr int NoTestsRunExitCode = 2;
constexpr int UnmatchedTestSpecExitCode = 3;
constexpr int AllTestsSkippedExitCode = 4;
constexpr int InvalidTestSpecExitCode = 5;
constexpr int TestFailureExitCode = 42;
class Session : Detail::NonCopyable { class Session : Detail::NonCopyable {
public: public:
@@ -5016,7 +5028,7 @@ namespace Catch {
#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \ #define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \ namespace{ const Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
#endif // CATCH_TAG_ALIAS_AUTOREGISTRAR_HPP_INCLUDED #endif // CATCH_TAG_ALIAS_AUTOREGISTRAR_HPP_INCLUDED
@@ -5193,7 +5205,7 @@ namespace Detail {
* when the compiler handles `ExprLhs<T> == b`, it also tries to resolve * when the compiler handles `ExprLhs<T> == b`, it also tries to resolve
* the overload set for `b == ExprLhs<T>`. * the overload set for `b == ExprLhs<T>`.
* *
* To accomodate these use cases, decomposer ended up rather complex. * To accommodate these use cases, decomposer ended up rather complex.
* *
* 1) These types are handled by adding SFINAE overloads to our comparison * 1) These types are handled by adding SFINAE overloads to our comparison
* operators, checking whether `T == U` are comparable with the given * operators, checking whether `T == U` are comparable with the given
@@ -5311,7 +5323,7 @@ namespace Catch {
public: public:
constexpr auto isBinaryExpression() const -> bool { return m_isBinaryExpression; } constexpr auto isBinaryExpression() const -> bool { return m_isBinaryExpression; }
constexpr auto getResult() const -> bool { return m_result; } constexpr auto getResult() const -> bool { return m_result; }
//! This function **has** to be overriden by the derived class. //! This function **has** to be overridden by the derived class.
virtual void streamReconstructedExpression( std::ostream& os ) const; virtual void streamReconstructedExpression( std::ostream& os ) const;
constexpr ITransientExpression( bool isBinaryExpression, bool result ) constexpr ITransientExpression( bool isBinaryExpression, bool result )
@@ -5912,7 +5924,7 @@ namespace Catch {
#else #else
// These section definitions imply that at most one section at one level // These section definitions imply that at most one section at one level
// will be intered (because only one section's __LINE__ can be equal to // will be entered (because only one section's __LINE__ can be equal to
// the dummy `catchInternalSectionHint` variable from `TEST_CASE`). // the dummy `catchInternalSectionHint` variable from `TEST_CASE`).
namespace Catch { namespace Catch {
@@ -6195,6 +6207,53 @@ static int catchInternalSectionHint = 0;
#endif // CATCH_TEST_REGISTRY_HPP_INCLUDED #endif // CATCH_TEST_REGISTRY_HPP_INCLUDED
#ifndef CATCH_UNREACHABLE_HPP_INCLUDED
#define CATCH_UNREACHABLE_HPP_INCLUDED
/**\file
* Polyfill `std::unreachable`
*
* We need something like `std::unreachable` to tell the compiler that
* some macros, e.g. `FAIL` or `SKIP`, do not continue execution in normal
* manner, and should handle it as such, e.g. not warn if there is no return
* from non-void function after a `FAIL` or `SKIP`.
*/
#include <exception>
#if defined( __cpp_lib_unreachable ) && __cpp_lib_unreachable > 202202L
# include <utility>
namespace Catch {
namespace Detail {
using Unreachable = std::unreachable;
}
} // namespace Catch
#else // vv If we do not have std::unreachable, we implement something similar
namespace Catch {
namespace Detail {
[[noreturn]]
inline void Unreachable() noexcept {
# if defined( NDEBUG )
# if defined( _MSC_VER ) && !defined( __clang__ )
__assume( false );
# elif defined( __GNUC__ )
__builtin_unreachable();
# endif
# endif // ^^ NDEBUG
std::terminate();
}
} // namespace Detail
} // end namespace Catch
#endif
#endif // CATCH_UNREACHABLE_HPP_INCLUDED
// All of our user-facing macros support configuration toggle, that // All of our user-facing macros support configuration toggle, that
// forces them to be defined prefixed with CATCH_. We also like to // forces them to be defined prefixed with CATCH_. We also like to
// support another toggle that can minimize (disable) their implementation. // support another toggle that can minimize (disable) their implementation.
@@ -6226,10 +6285,16 @@ static int catchInternalSectionHint = 0;
#define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
#define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
#define CATCH_DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ ) #define CATCH_DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ )
#define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) #define CATCH_FAIL( ... ) do { \
INTERNAL_CATCH_MSG("CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ); \
Catch::Detail::Unreachable(); \
} while ( false )
#define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#define CATCH_SKIP( ... ) INTERNAL_CATCH_MSG( "SKIP", Catch::ResultWas::ExplicitSkip, Catch::ResultDisposition::Normal, __VA_ARGS__ ) #define CATCH_SKIP( ... ) do { \
INTERNAL_CATCH_MSG( "CATCH_SKIP", Catch::ResultWas::ExplicitSkip, Catch::ResultDisposition::Normal, __VA_ARGS__ ); \
Catch::Detail::Unreachable(); \
} while (false)
#if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE) #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)
@@ -6327,10 +6392,16 @@ static int catchInternalSectionHint = 0;
#define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
#define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
#define DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ ) #define DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ )
#define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) #define FAIL( ... ) do { \
INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ); \
Catch::Detail::Unreachable(); \
} while (false)
#define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#define SKIP( ... ) INTERNAL_CATCH_MSG( "SKIP", Catch::ResultWas::ExplicitSkip, Catch::ResultDisposition::Normal, __VA_ARGS__ ) #define SKIP( ... ) do { \
INTERNAL_CATCH_MSG( "SKIP", Catch::ResultWas::ExplicitSkip, Catch::ResultDisposition::Normal, __VA_ARGS__ ); \
Catch::Detail::Unreachable(); \
} while (false)
#if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE) #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)
@@ -6424,6 +6495,15 @@ static int catchInternalSectionHint = 0;
#endif #endif
namespace Catch {
namespace Detail {
template <int N>
struct priority_tag : priority_tag<N - 1> {};
template <>
struct priority_tag<0> {};
}
}
#define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__ #define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__
#define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__))) #define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__)))
#define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__))) #define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__)))
@@ -6483,10 +6563,10 @@ static int catchInternalSectionHint = 0;
#define INTERNAL_CATCH_MAKE_NAMESPACE(name) INTERNAL_CATCH_MAKE_NAMESPACE2(name) #define INTERNAL_CATCH_MAKE_NAMESPACE(name) INTERNAL_CATCH_MAKE_NAMESPACE2(name)
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS_GEN(__VA_ARGS__)>()) #define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS_GEN(__VA_ARGS__)>(Catch::Detail::priority_tag<1>{}))
#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)) #define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))
#else #else
#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) INTERNAL_CATCH_EXPAND_VARGS(decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS_GEN(__VA_ARGS__)>())) #define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) INTERNAL_CATCH_EXPAND_VARGS(decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS_GEN(__VA_ARGS__)>(Catch::Detail::priority_tag<1>{})))
#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))) #define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)))
#endif #endif
@@ -6509,11 +6589,11 @@ static int catchInternalSectionHint = 0;
#define INTERNAL_CATCH_TYPE_GEN\ #define INTERNAL_CATCH_TYPE_GEN\
template<typename...> struct TypeList {};\ template<typename...> struct TypeList {};\
template<typename...Ts>\ template<typename... Ts>\
constexpr auto get_wrapper() noexcept -> TypeList<Ts...> { return {}; }\ constexpr auto get_wrapper(Catch::Detail::priority_tag<1>) noexcept -> TypeList<Ts...> { return {}; }\
template<template<typename...> class...> struct TemplateTypeList{};\ template<template<typename...> class...> struct TemplateTypeList{};\
template<template<typename...> class...Cs>\ template<template<typename...> class...Cs>\
constexpr auto get_wrapper() noexcept -> TemplateTypeList<Cs...> { return {}; }\ constexpr auto get_wrapper(Catch::Detail::priority_tag<1>) noexcept -> TemplateTypeList<Cs...> { return {}; }\
template<typename...>\ template<typename...>\
struct append;\ struct append;\
template<typename...>\ template<typename...>\
@@ -6543,10 +6623,10 @@ static int catchInternalSectionHint = 0;
#define INTERNAL_CATCH_NTTP_1(signature, ...)\ #define INTERNAL_CATCH_NTTP_1(signature, ...)\
template<INTERNAL_CATCH_REMOVE_PARENS(signature)> struct Nttp{};\ template<INTERNAL_CATCH_REMOVE_PARENS(signature)> struct Nttp{};\
template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
constexpr auto get_wrapper() noexcept -> Nttp<__VA_ARGS__> { return {}; } \ constexpr auto get_wrapper(Catch::Detail::priority_tag<0>) noexcept -> Nttp<__VA_ARGS__> { return {}; } \
template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...> struct NttpTemplateTypeList{};\ template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...> struct NttpTemplateTypeList{};\
template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...Cs>\ template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...Cs>\
constexpr auto get_wrapper() noexcept -> NttpTemplateTypeList<Cs...> { return {}; } \ constexpr auto get_wrapper(Catch::Detail::priority_tag<0>) noexcept -> NttpTemplateTypeList<Cs...> { return {}; } \
\ \
template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature)>\ template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature)>\
struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>> { using type = TypeList<Container<__VA_ARGS__>>; };\ struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>> { using type = TypeList<Container<__VA_ARGS__>>; };\
@@ -6571,13 +6651,14 @@ static int catchInternalSectionHint = 0;
template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
static void TestName() static void TestName()
#define INTERNAL_CATCH_NTTP_REGISTER0(TestFunc, signature)\ #define INTERNAL_CATCH_TYPES_REGISTER(TestFunc)\
template<typename Type>\ template<typename... Ts>\
void reg_test(TypeList<Type>, Catch::NameAndTags nameAndTags)\ void reg_test(TypeList<Ts...>, Catch::NameAndTags nameAndTags)\
{\ {\
Catch::AutoReg( Catch::makeTestInvoker(&TestFunc<Type>), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), nameAndTags);\ Catch::AutoReg( Catch::makeTestInvoker(&TestFunc<Ts...>), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), nameAndTags);\
} }
#define INTERNAL_CATCH_NTTP_REGISTER0(TestFunc, signature, ...)
#define INTERNAL_CATCH_NTTP_REGISTER(TestFunc, signature, ...)\ #define INTERNAL_CATCH_NTTP_REGISTER(TestFunc, signature, ...)\
template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
void reg_test(Nttp<__VA_ARGS__>, Catch::NameAndTags nameAndTags)\ void reg_test(Nttp<__VA_ARGS__>, Catch::NameAndTags nameAndTags)\
@@ -6626,7 +6707,7 @@ static int catchInternalSectionHint = 0;
#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0)(TestName, __VA_ARGS__) #define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0)(TestName, __VA_ARGS__)
#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0)(TestName, ClassName, __VA_ARGS__) #define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0)(TestName, ClassName, __VA_ARGS__)
#define INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD0, INTERNAL_CATCH_NTTP_REGISTER_METHOD0)(TestName, __VA_ARGS__) #define INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD0, INTERNAL_CATCH_NTTP_REGISTER_METHOD0)(TestName, __VA_ARGS__)
#define INTERNAL_CATCH_NTTP_REG_GEN(TestFunc, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER0, INTERNAL_CATCH_NTTP_REGISTER0)(TestFunc, __VA_ARGS__) #define INTERNAL_CATCH_NTTP_REG_GEN(TestFunc, ...) INTERNAL_CATCH_TYPES_REGISTER(TestFunc) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER0, INTERNAL_CATCH_NTTP_REGISTER0)(TestFunc, __VA_ARGS__)
#define INTERNAL_CATCH_DEFINE_SIG_TEST(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST1, INTERNAL_CATCH_DEFINE_SIG_TEST0)(TestName, __VA_ARGS__) #define INTERNAL_CATCH_DEFINE_SIG_TEST(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST1, INTERNAL_CATCH_DEFINE_SIG_TEST0)(TestName, __VA_ARGS__)
#define INTERNAL_CATCH_DECLARE_SIG_TEST(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST1, INTERNAL_CATCH_DECLARE_SIG_TEST0)(TestName, __VA_ARGS__) #define INTERNAL_CATCH_DECLARE_SIG_TEST(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST1, INTERNAL_CATCH_DECLARE_SIG_TEST0)(TestName, __VA_ARGS__)
#define INTERNAL_CATCH_REMOVE_PARENS_GEN(...) INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_REMOVE_PARENS_11_ARG,INTERNAL_CATCH_REMOVE_PARENS_10_ARG,INTERNAL_CATCH_REMOVE_PARENS_9_ARG,INTERNAL_CATCH_REMOVE_PARENS_8_ARG,INTERNAL_CATCH_REMOVE_PARENS_7_ARG,INTERNAL_CATCH_REMOVE_PARENS_6_ARG,INTERNAL_CATCH_REMOVE_PARENS_5_ARG,INTERNAL_CATCH_REMOVE_PARENS_4_ARG,INTERNAL_CATCH_REMOVE_PARENS_3_ARG,INTERNAL_CATCH_REMOVE_PARENS_2_ARG,INTERNAL_CATCH_REMOVE_PARENS_1_ARG)(__VA_ARGS__) #define INTERNAL_CATCH_REMOVE_PARENS_GEN(...) INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_REMOVE_PARENS_11_ARG,INTERNAL_CATCH_REMOVE_PARENS_10_ARG,INTERNAL_CATCH_REMOVE_PARENS_9_ARG,INTERNAL_CATCH_REMOVE_PARENS_8_ARG,INTERNAL_CATCH_REMOVE_PARENS_7_ARG,INTERNAL_CATCH_REMOVE_PARENS_6_ARG,INTERNAL_CATCH_REMOVE_PARENS_5_ARG,INTERNAL_CATCH_REMOVE_PARENS_4_ARG,INTERNAL_CATCH_REMOVE_PARENS_3_ARG,INTERNAL_CATCH_REMOVE_PARENS_2_ARG,INTERNAL_CATCH_REMOVE_PARENS_1_ARG)(__VA_ARGS__)
@@ -6636,7 +6717,7 @@ static int catchInternalSectionHint = 0;
#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0)(TestName, __VA_ARGS__)) #define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0)(TestName, __VA_ARGS__))
#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0)(TestName, ClassName, __VA_ARGS__)) #define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0)(TestName, ClassName, __VA_ARGS__))
#define INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD0, INTERNAL_CATCH_NTTP_REGISTER_METHOD0)(TestName, __VA_ARGS__)) #define INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD0, INTERNAL_CATCH_NTTP_REGISTER_METHOD0)(TestName, __VA_ARGS__))
#define INTERNAL_CATCH_NTTP_REG_GEN(TestFunc, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER0, INTERNAL_CATCH_NTTP_REGISTER0)(TestFunc, __VA_ARGS__)) #define INTERNAL_CATCH_NTTP_REG_GEN(TestFunc, ...) INTERNAL_CATCH_TYPES_REGISTER(TestFunc) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER0, INTERNAL_CATCH_NTTP_REGISTER0)(TestFunc, __VA_ARGS__))
#define INTERNAL_CATCH_DEFINE_SIG_TEST(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST1, INTERNAL_CATCH_DEFINE_SIG_TEST0)(TestName, __VA_ARGS__)) #define INTERNAL_CATCH_DEFINE_SIG_TEST(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST1, INTERNAL_CATCH_DEFINE_SIG_TEST0)(TestName, __VA_ARGS__))
#define INTERNAL_CATCH_DECLARE_SIG_TEST(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST1, INTERNAL_CATCH_DECLARE_SIG_TEST0)(TestName, __VA_ARGS__)) #define INTERNAL_CATCH_DECLARE_SIG_TEST(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST1, INTERNAL_CATCH_DECLARE_SIG_TEST0)(TestName, __VA_ARGS__))
#define INTERNAL_CATCH_REMOVE_PARENS_GEN(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_REMOVE_PARENS_11_ARG,INTERNAL_CATCH_REMOVE_PARENS_10_ARG,INTERNAL_CATCH_REMOVE_PARENS_9_ARG,INTERNAL_CATCH_REMOVE_PARENS_8_ARG,INTERNAL_CATCH_REMOVE_PARENS_7_ARG,INTERNAL_CATCH_REMOVE_PARENS_6_ARG,INTERNAL_CATCH_REMOVE_PARENS_5_ARG,INTERNAL_CATCH_REMOVE_PARENS_4_ARG,INTERNAL_CATCH_REMOVE_PARENS_3_ARG,INTERNAL_CATCH_REMOVE_PARENS_2_ARG,INTERNAL_CATCH_REMOVE_PARENS_1_ARG)(__VA_ARGS__)) #define INTERNAL_CATCH_REMOVE_PARENS_GEN(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_REMOVE_PARENS_11_ARG,INTERNAL_CATCH_REMOVE_PARENS_10_ARG,INTERNAL_CATCH_REMOVE_PARENS_9_ARG,INTERNAL_CATCH_REMOVE_PARENS_8_ARG,INTERNAL_CATCH_REMOVE_PARENS_7_ARG,INTERNAL_CATCH_REMOVE_PARENS_6_ARG,INTERNAL_CATCH_REMOVE_PARENS_5_ARG,INTERNAL_CATCH_REMOVE_PARENS_4_ARG,INTERNAL_CATCH_REMOVE_PARENS_3_ARG,INTERNAL_CATCH_REMOVE_PARENS_2_ARG,INTERNAL_CATCH_REMOVE_PARENS_1_ARG)(__VA_ARGS__))
@@ -6765,11 +6846,11 @@ static int catchInternalSectionHint = 0;
constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\ constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\ constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\ constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\
(void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFuncName<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + '<' + std::string(types_list[index % num_types]) + '>', Tags } ), index++)... };/* NOLINT */\ (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFuncName<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + '<' + types_list[index % num_types] + '>', Tags } ), index++)... };/* NOLINT */\
} \ } \
}; \ }; \
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \ static const int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
using TestInit = typename create<TestName, decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>()), TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(INTERNAL_CATCH_REMOVE_PARENS(TypesList))>>::type; \ using TestInit = typename create<TestName, decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>(Catch::Detail::priority_tag<1>{})), TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(INTERNAL_CATCH_REMOVE_PARENS(TypesList))>>::type; \
TestInit t; \ TestInit t; \
t.reg_tests(); \ t.reg_tests(); \
return 0; \ return 0; \
@@ -6814,7 +6895,7 @@ static int catchInternalSectionHint = 0;
(void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFunc<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " INTERNAL_CATCH_STRINGIZE(TmplList) " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */\ (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFunc<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " INTERNAL_CATCH_STRINGIZE(TmplList) " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */\
} \ } \
};\ };\
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \ static const int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
using TestInit = typename convert<TestName, TmplList>::type; \ using TestInit = typename convert<TestName, TmplList>::type; \
TestInit t; \ TestInit t; \
t.reg_tests(); \ t.reg_tests(); \
@@ -6850,7 +6931,7 @@ static int catchInternalSectionHint = 0;
(void)expander{(reg_test(Types{}, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };/* NOLINT */ \ (void)expander{(reg_test(Types{}, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };/* NOLINT */ \
}\ }\
};\ };\
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ static const int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
TestNameClass<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(__VA_ARGS__)>();\ TestNameClass<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(__VA_ARGS__)>();\
return 0;\ return 0;\
}();\ }();\
@@ -6897,11 +6978,11 @@ static int catchInternalSectionHint = 0;
constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\ constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\ constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\ constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\
(void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + '<' + std::string(types_list[index % num_types]) + '>', Tags } ), index++)... };/* NOLINT */ \ (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + '<' + types_list[index % num_types] + '>', Tags } ), index++)... };/* NOLINT */ \
}\ }\
};\ };\
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ static const int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
using TestInit = typename create<TestNameClass, decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>()), TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(INTERNAL_CATCH_REMOVE_PARENS(TypesList))>>::type;\ using TestInit = typename create<TestNameClass, decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>(Catch::Detail::priority_tag<1>{})), TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(INTERNAL_CATCH_REMOVE_PARENS(TypesList))>>::type;\
TestInit t;\ TestInit t;\
t.reg_tests();\ t.reg_tests();\
return 0;\ return 0;\
@@ -6949,7 +7030,7 @@ static int catchInternalSectionHint = 0;
(void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName##_catch_sr, Catch::NameAndTags{ Name " - " INTERNAL_CATCH_STRINGIZE(TmplList) " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */ \ (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName##_catch_sr, Catch::NameAndTags{ Name " - " INTERNAL_CATCH_STRINGIZE(TmplList) " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */ \
}\ }\
};\ };\
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ static const int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
using TestInit = typename convert<TestNameClass, TmplList>::type;\ using TestInit = typename convert<TestNameClass, TmplList>::type;\
TestInit t;\ TestInit t;\
t.reg_tests();\ t.reg_tests();\
@@ -7201,6 +7282,22 @@ namespace Catch {
#endif // CATCH_TEST_CASE_INFO_HPP_INCLUDED #endif // CATCH_TEST_CASE_INFO_HPP_INCLUDED
#ifndef CATCH_TEST_RUN_INFO_HPP_INCLUDED
#define CATCH_TEST_RUN_INFO_HPP_INCLUDED
namespace Catch {
struct TestRunInfo {
constexpr TestRunInfo(StringRef _name) : name(_name) {}
StringRef name;
};
} // end namespace Catch
#endif // CATCH_TEST_RUN_INFO_HPP_INCLUDED
#ifndef CATCH_TRANSLATE_EXCEPTION_HPP_INCLUDED #ifndef CATCH_TRANSLATE_EXCEPTION_HPP_INCLUDED
#define CATCH_TRANSLATE_EXCEPTION_HPP_INCLUDED #define CATCH_TRANSLATE_EXCEPTION_HPP_INCLUDED
@@ -7288,7 +7385,7 @@ namespace Catch {
static std::string translatorName( signature ); \ static std::string translatorName( signature ); \
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); } \ namespace{ const Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); } \
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
static std::string translatorName( signature ) static std::string translatorName( signature )
@@ -7349,8 +7446,8 @@ namespace Catch {
#define CATCH_VERSION_MACROS_HPP_INCLUDED #define CATCH_VERSION_MACROS_HPP_INCLUDED
#define CATCH_VERSION_MAJOR 3 #define CATCH_VERSION_MAJOR 3
#define CATCH_VERSION_MINOR 8 #define CATCH_VERSION_MINOR 9
#define CATCH_VERSION_PATCH 1 #define CATCH_VERSION_PATCH 0
#endif // CATCH_VERSION_MACROS_HPP_INCLUDED #endif // CATCH_VERSION_MACROS_HPP_INCLUDED
@@ -7391,7 +7488,7 @@ namespace Catch {
m_msg(msg) m_msg(msg)
{} {}
const char* what() const noexcept override final; const char* what() const noexcept final;
}; };
} // end namespace Catch } // end namespace Catch
@@ -8778,26 +8875,9 @@ auto from_range(Container const& cnt) {
#define CATCH_INTERFACES_REPORTER_HPP_INCLUDED #define CATCH_INTERFACES_REPORTER_HPP_INCLUDED
#ifndef CATCH_TEST_RUN_INFO_HPP_INCLUDED
#define CATCH_TEST_RUN_INFO_HPP_INCLUDED
namespace Catch {
struct TestRunInfo {
constexpr TestRunInfo(StringRef _name) : name(_name) {}
StringRef name;
};
} // end namespace Catch
#endif // CATCH_TEST_RUN_INFO_HPP_INCLUDED
#include <map> #include <map>
#include <string> #include <string>
#include <vector> #include <vector>
#include <iosfwd>
namespace Catch { namespace Catch {
@@ -8893,6 +8973,11 @@ namespace Catch {
//! Catch2 should call `Reporter::assertionEnded` even for passing //! Catch2 should call `Reporter::assertionEnded` even for passing
//! assertions //! assertions
bool shouldReportAllAssertions = false; bool shouldReportAllAssertions = false;
//! Catch2 should call `Reporter::assertionStarting` for all assertions
// Defaults to true for backwards compatibility, but none of our current
// reporters actually want this, and it enables a fast path in assertion
// handling.
bool shouldReportAllAssertionStarts = true;
}; };
/** /**
@@ -9472,7 +9557,7 @@ namespace Catch {
#define CATCH_ENFORCE_HPP_INCLUDED #define CATCH_ENFORCE_HPP_INCLUDED
#include <exception> #include <exception> // for `std::exception` in no-exception configuration
namespace Catch { namespace Catch {
#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
@@ -9568,7 +9653,6 @@ namespace Catch {
#define CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED #define CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
#include <vector>
#include <string> #include <string>
namespace Catch { namespace Catch {
@@ -9768,8 +9852,8 @@ namespace Detail {
#ifndef CATCH_IS_PERMUTATION_HPP_INCLUDED #ifndef CATCH_IS_PERMUTATION_HPP_INCLUDED
#define CATCH_IS_PERMUTATION_HPP_INCLUDED #define CATCH_IS_PERMUTATION_HPP_INCLUDED
#include <algorithm>
#include <iterator> #include <iterator>
#include <type_traits>
namespace Catch { namespace Catch {
namespace Detail { namespace Detail {
@@ -9906,8 +9990,6 @@ namespace Catch {
#include <iosfwd> #include <iosfwd>
#include <cstddef>
#include <ostream>
#include <string> #include <string>
namespace Catch { namespace Catch {
@@ -10491,6 +10573,48 @@ using TestCaseTracking::SectionTracker;
#endif // CATCH_TEST_CASE_TRACKER_HPP_INCLUDED #endif // CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
#ifndef CATCH_THREAD_SUPPORT_HPP_INCLUDED
#define CATCH_THREAD_SUPPORT_HPP_INCLUDED
#if defined( CATCH_CONFIG_EXPERIMENTAL_THREAD_SAFE_ASSERTIONS )
# include <atomic>
# include <mutex>
#endif
namespace Catch {
namespace Detail {
#if defined( CATCH_CONFIG_EXPERIMENTAL_THREAD_SAFE_ASSERTIONS )
using Mutex = std::mutex;
using LockGuard = std::lock_guard<std::mutex>;
struct AtomicCounts {
std::atomic<std::uint64_t> passed = 0;
std::atomic<std::uint64_t> failed = 0;
std::atomic<std::uint64_t> failedButOk = 0;
std::atomic<std::uint64_t> skipped = 0;
};
#else // ^^ Use actual mutex, lock and atomics
// vv Dummy implementations for single-thread performance
struct Mutex {
void lock() {}
void unlock() {}
};
struct LockGuard {
LockGuard( Mutex ) {}
};
using AtomicCounts = Counts;
#endif
} // namespace Detail
} // namespace Catch
#endif // CATCH_THREAD_SUPPORT_HPP_INCLUDED
#include <string> #include <string>
namespace Catch { namespace Catch {
@@ -10578,18 +10702,18 @@ namespace Catch {
bool lastAssertionPassed() override; bool lastAssertionPassed() override;
void assertionPassed() override;
public: public:
// !TBD We need to do this another way! // !TBD We need to do this another way!
bool aborting() const; bool aborting() const;
private: private:
void assertionPassedFastPath( SourceLineInfo lineInfo );
// Update the non-thread-safe m_totals from the atomic assertion counts.
void updateTotalsFromAtomics();
void runCurrentTest(); void runCurrentTest();
void invokeActiveTestCase(); void invokeActiveTestCase();
void resetAssertionInfo();
bool testForMissingAssertions( Counts& assertions ); bool testForMissingAssertions( Counts& assertions );
void assertionEnded( AssertionResult&& result ); void assertionEnded( AssertionResult&& result );
@@ -10599,31 +10723,42 @@ namespace Catch {
ITransientExpression const *expr, ITransientExpression const *expr,
bool negated ); bool negated );
void populateReaction( AssertionReaction& reaction ); void populateReaction( AssertionReaction& reaction, bool has_normal_disposition );
// Creates dummy info for unexpected exceptions/fatal errors,
// where we do not have the access to one, but we still need
// to send one to the reporters.
AssertionInfo makeDummyAssertionInfo();
private: private:
void handleUnfinishedSections(); void handleUnfinishedSections();
mutable Detail::Mutex m_assertionMutex;
TestRunInfo m_runInfo; TestRunInfo m_runInfo;
TestCaseHandle const* m_activeTestCase = nullptr; TestCaseHandle const* m_activeTestCase = nullptr;
ITracker* m_testCaseTracker = nullptr; ITracker* m_testCaseTracker = nullptr;
Optional<AssertionResult> m_lastResult; Optional<AssertionResult> m_lastResult;
IConfig const* m_config; IConfig const* m_config;
Totals m_totals; Totals m_totals;
Detail::AtomicCounts m_atomicAssertionCount;
IEventListenerPtr m_reporter; IEventListenerPtr m_reporter;
std::vector<MessageInfo> m_messages; std::vector<MessageInfo> m_messages;
std::vector<ScopedMessage> m_messageScopes; /* Keeps owners of so-called unscoped messages. */ // Owners for the UNSCOPED_X information macro
AssertionInfo m_lastAssertionInfo; std::vector<ScopedMessage> m_messageScopes;
std::vector<SectionEndInfo> m_unfinishedSections; std::vector<SectionEndInfo> m_unfinishedSections;
std::vector<ITracker*> m_activeSections; std::vector<ITracker*> m_activeSections;
TrackerContext m_trackerContext; TrackerContext m_trackerContext;
Detail::unique_ptr<OutputRedirect> m_outputRedirect; Detail::unique_ptr<OutputRedirect> m_outputRedirect;
FatalConditionHandler m_fatalConditionhandler; FatalConditionHandler m_fatalConditionhandler;
bool m_lastAssertionPassed = false; // Caches m_config->abortAfter() to avoid vptr calls/allow inlining
size_t m_abortAfterXFailedAssertions;
bool m_shouldReportUnexpected = true; bool m_shouldReportUnexpected = true;
// Caches whether `assertionStarting` events should be sent to the reporter.
bool m_reportAssertionStarting;
// Caches whether `assertionEnded` events for successful assertions should be sent to the reporter
bool m_includeSuccessfulResults; bool m_includeSuccessfulResults;
// Caches m_config->shouldDebugBreak() to avoid vptr calls/allow inlining
bool m_shouldDebugBreak;
}; };
void seedRng(IConfig const& config); void seedRng(IConfig const& config);
@@ -10637,7 +10772,6 @@ namespace Catch {
#define CATCH_SHARDING_HPP_INCLUDED #define CATCH_SHARDING_HPP_INCLUDED
#include <cassert> #include <cassert>
#include <cmath>
#include <algorithm> #include <algorithm>
namespace Catch { namespace Catch {
@@ -11860,19 +11994,19 @@ namespace Matchers {
} }
template<typename T> template<typename T>
using is_generic_matcher = std::is_base_of< static constexpr bool is_generic_matcher_v = std::is_base_of<
Catch::Matchers::MatcherGenericBase, Catch::Matchers::MatcherGenericBase,
std::remove_cv_t<std::remove_reference_t<T>> std::remove_cv_t<std::remove_reference_t<T>>
>; >::value;
template<typename... Ts> template<typename... Ts>
using are_generic_matchers = Catch::Detail::conjunction<is_generic_matcher<Ts>...>; static constexpr bool are_generic_matchers_v = Catch::Detail::conjunction<std::integral_constant<bool,is_generic_matcher_v<Ts>>...>::value;
template<typename T> template<typename T>
using is_matcher = std::is_base_of< static constexpr bool is_matcher_v = std::is_base_of<
Catch::Matchers::MatcherUntypedBase, Catch::Matchers::MatcherUntypedBase,
std::remove_cv_t<std::remove_reference_t<T>> std::remove_cv_t<std::remove_reference_t<T>>
>; >::value;
template<std::size_t N, typename Arg> template<std::size_t N, typename Arg>
@@ -11945,7 +12079,7 @@ namespace Matchers {
//! Avoids type nesting for `GenericAllOf && some matcher` case //! Avoids type nesting for `GenericAllOf && some matcher` case
template<typename MatcherRHS> template<typename MatcherRHS>
friend std::enable_if_t<is_matcher<MatcherRHS>::value, friend std::enable_if_t<is_matcher_v<MatcherRHS>,
MatchAllOfGeneric<MatcherTs..., MatcherRHS>> operator && ( MatchAllOfGeneric<MatcherTs..., MatcherRHS>> operator && (
MatchAllOfGeneric<MatcherTs...>&& lhs, MatchAllOfGeneric<MatcherTs...>&& lhs,
MatcherRHS const& rhs) { MatcherRHS const& rhs) {
@@ -11954,7 +12088,7 @@ namespace Matchers {
//! Avoids type nesting for `some matcher && GenericAllOf` case //! Avoids type nesting for `some matcher && GenericAllOf` case
template<typename MatcherLHS> template<typename MatcherLHS>
friend std::enable_if_t<is_matcher<MatcherLHS>::value, friend std::enable_if_t<is_matcher_v<MatcherLHS>,
MatchAllOfGeneric<MatcherLHS, MatcherTs...>> operator && ( MatchAllOfGeneric<MatcherLHS, MatcherTs...>> operator && (
MatcherLHS const& lhs, MatcherLHS const& lhs,
MatchAllOfGeneric<MatcherTs...>&& rhs) { MatchAllOfGeneric<MatcherTs...>&& rhs) {
@@ -11999,7 +12133,7 @@ namespace Matchers {
//! Avoids type nesting for `GenericAnyOf || some matcher` case //! Avoids type nesting for `GenericAnyOf || some matcher` case
template<typename MatcherRHS> template<typename MatcherRHS>
friend std::enable_if_t<is_matcher<MatcherRHS>::value, friend std::enable_if_t<is_matcher_v<MatcherRHS>,
MatchAnyOfGeneric<MatcherTs..., MatcherRHS>> operator || ( MatchAnyOfGeneric<MatcherTs..., MatcherRHS>> operator || (
MatchAnyOfGeneric<MatcherTs...>&& lhs, MatchAnyOfGeneric<MatcherTs...>&& lhs,
MatcherRHS const& rhs) { MatcherRHS const& rhs) {
@@ -12008,7 +12142,7 @@ namespace Matchers {
//! Avoids type nesting for `some matcher || GenericAnyOf` case //! Avoids type nesting for `some matcher || GenericAnyOf` case
template<typename MatcherLHS> template<typename MatcherLHS>
friend std::enable_if_t<is_matcher<MatcherLHS>::value, friend std::enable_if_t<is_matcher_v<MatcherLHS>,
MatchAnyOfGeneric<MatcherLHS, MatcherTs...>> operator || ( MatchAnyOfGeneric<MatcherLHS, MatcherTs...>> operator || (
MatcherLHS const& lhs, MatcherLHS const& lhs,
MatchAnyOfGeneric<MatcherTs...>&& rhs) { MatchAnyOfGeneric<MatcherTs...>&& rhs) {
@@ -12048,20 +12182,20 @@ namespace Matchers {
// compose only generic matchers // compose only generic matchers
template<typename MatcherLHS, typename MatcherRHS> template<typename MatcherLHS, typename MatcherRHS>
std::enable_if_t<Detail::are_generic_matchers<MatcherLHS, MatcherRHS>::value, Detail::MatchAllOfGeneric<MatcherLHS, MatcherRHS>> std::enable_if_t<Detail::are_generic_matchers_v<MatcherLHS, MatcherRHS>, Detail::MatchAllOfGeneric<MatcherLHS, MatcherRHS>>
operator && (MatcherLHS const& lhs, MatcherRHS const& rhs) { operator && (MatcherLHS const& lhs, MatcherRHS const& rhs) {
return { lhs, rhs }; return { lhs, rhs };
} }
template<typename MatcherLHS, typename MatcherRHS> template<typename MatcherLHS, typename MatcherRHS>
std::enable_if_t<Detail::are_generic_matchers<MatcherLHS, MatcherRHS>::value, Detail::MatchAnyOfGeneric<MatcherLHS, MatcherRHS>> std::enable_if_t<Detail::are_generic_matchers_v<MatcherLHS, MatcherRHS>, Detail::MatchAnyOfGeneric<MatcherLHS, MatcherRHS>>
operator || (MatcherLHS const& lhs, MatcherRHS const& rhs) { operator || (MatcherLHS const& lhs, MatcherRHS const& rhs) {
return { lhs, rhs }; return { lhs, rhs };
} }
//! Wrap provided generic matcher in generic negator //! Wrap provided generic matcher in generic negator
template<typename MatcherT> template<typename MatcherT>
std::enable_if_t<Detail::is_generic_matcher<MatcherT>::value, Detail::MatchNotOfGeneric<MatcherT>> std::enable_if_t<Detail::is_generic_matcher_v<MatcherT>, Detail::MatchNotOfGeneric<MatcherT>>
operator ! (MatcherT const& matcher) { operator ! (MatcherT const& matcher) {
return Detail::MatchNotOfGeneric<MatcherT>{matcher}; return Detail::MatchNotOfGeneric<MatcherT>{matcher};
} }
@@ -12069,25 +12203,25 @@ namespace Matchers {
// compose mixed generic and non-generic matchers // compose mixed generic and non-generic matchers
template<typename MatcherLHS, typename ArgRHS> template<typename MatcherLHS, typename ArgRHS>
std::enable_if_t<Detail::is_generic_matcher<MatcherLHS>::value, Detail::MatchAllOfGeneric<MatcherLHS, MatcherBase<ArgRHS>>> std::enable_if_t<Detail::is_generic_matcher_v<MatcherLHS>, Detail::MatchAllOfGeneric<MatcherLHS, MatcherBase<ArgRHS>>>
operator && (MatcherLHS const& lhs, MatcherBase<ArgRHS> const& rhs) { operator && (MatcherLHS const& lhs, MatcherBase<ArgRHS> const& rhs) {
return { lhs, rhs }; return { lhs, rhs };
} }
template<typename ArgLHS, typename MatcherRHS> template<typename ArgLHS, typename MatcherRHS>
std::enable_if_t<Detail::is_generic_matcher<MatcherRHS>::value, Detail::MatchAllOfGeneric<MatcherBase<ArgLHS>, MatcherRHS>> std::enable_if_t<Detail::is_generic_matcher_v<MatcherRHS>, Detail::MatchAllOfGeneric<MatcherBase<ArgLHS>, MatcherRHS>>
operator && (MatcherBase<ArgLHS> const& lhs, MatcherRHS const& rhs) { operator && (MatcherBase<ArgLHS> const& lhs, MatcherRHS const& rhs) {
return { lhs, rhs }; return { lhs, rhs };
} }
template<typename MatcherLHS, typename ArgRHS> template<typename MatcherLHS, typename ArgRHS>
std::enable_if_t<Detail::is_generic_matcher<MatcherLHS>::value, Detail::MatchAnyOfGeneric<MatcherLHS, MatcherBase<ArgRHS>>> std::enable_if_t<Detail::is_generic_matcher_v<MatcherLHS>, Detail::MatchAnyOfGeneric<MatcherLHS, MatcherBase<ArgRHS>>>
operator || (MatcherLHS const& lhs, MatcherBase<ArgRHS> const& rhs) { operator || (MatcherLHS const& lhs, MatcherBase<ArgRHS> const& rhs) {
return { lhs, rhs }; return { lhs, rhs };
} }
template<typename ArgLHS, typename MatcherRHS> template<typename ArgLHS, typename MatcherRHS>
std::enable_if_t<Detail::is_generic_matcher<MatcherRHS>::value, Detail::MatchAnyOfGeneric<MatcherBase<ArgLHS>, MatcherRHS>> std::enable_if_t<Detail::is_generic_matcher_v<MatcherRHS>, Detail::MatchAnyOfGeneric<MatcherBase<ArgLHS>, MatcherRHS>>
operator || (MatcherBase<ArgLHS> const& lhs, MatcherRHS const& rhs) { operator || (MatcherBase<ArgLHS> const& lhs, MatcherRHS const& rhs) {
return { lhs, rhs }; return { lhs, rhs };
} }
@@ -12164,7 +12298,7 @@ namespace Catch {
//! Creates a matcher that accepts ranges/containers with specific size //! Creates a matcher that accepts ranges/containers with specific size
HasSizeMatcher SizeIs(std::size_t sz); HasSizeMatcher SizeIs(std::size_t sz);
template <typename Matcher> template <typename Matcher>
std::enable_if_t<Detail::is_matcher<Matcher>::value, std::enable_if_t<Detail::is_matcher_v<Matcher>,
SizeMatchesMatcher<Matcher>> SizeIs(Matcher&& m) { SizeMatchesMatcher<Matcher>> SizeIs(Matcher&& m) {
return SizeMatchesMatcher<Matcher>{CATCH_FORWARD(m)}; return SizeMatchesMatcher<Matcher>{CATCH_FORWARD(m)};
} }
@@ -12179,8 +12313,8 @@ namespace Catch {
#define CATCH_MATCHERS_CONTAINS_HPP_INCLUDED #define CATCH_MATCHERS_CONTAINS_HPP_INCLUDED
#include <algorithm>
#include <functional> #include <functional>
#include <type_traits>
namespace Catch { namespace Catch {
namespace Matchers { namespace Matchers {
@@ -12242,14 +12376,14 @@ namespace Catch {
* Uses `std::equal_to` to do the comparison * Uses `std::equal_to` to do the comparison
*/ */
template <typename T> template <typename T>
std::enable_if_t<!Detail::is_matcher<T>::value, std::enable_if_t<!Detail::is_matcher_v<T>,
ContainsElementMatcher<T, std::equal_to<>>> Contains(T&& elem) { ContainsElementMatcher<T, std::equal_to<>>> Contains(T&& elem) {
return { CATCH_FORWARD(elem), std::equal_to<>{} }; return { CATCH_FORWARD(elem), std::equal_to<>{} };
} }
//! Creates a matcher that checks whether a range contains element matching a matcher //! Creates a matcher that checks whether a range contains element matching a matcher
template <typename Matcher> template <typename Matcher>
std::enable_if_t<Detail::is_matcher<Matcher>::value, std::enable_if_t<Detail::is_matcher_v<Matcher>,
ContainsMatcherMatcher<Matcher>> Contains(Matcher&& matcher) { ContainsMatcherMatcher<Matcher>> Contains(Matcher&& matcher) {
return { CATCH_FORWARD(matcher) }; return { CATCH_FORWARD(matcher) };
} }
@@ -12626,8 +12760,7 @@ namespace Catch {
#define CATCH_MATCHERS_RANGE_EQUALS_HPP_INCLUDED #define CATCH_MATCHERS_RANGE_EQUALS_HPP_INCLUDED
#include <algorithm> #include <functional>
#include <utility>
namespace Catch { namespace Catch {
namespace Matchers { namespace Matchers {
@@ -13211,9 +13344,11 @@ namespace Catch {
public: public:
// GCC5 compat: we cannot use inherited constructor, because it // GCC5 compat: we cannot use inherited constructor, because it
// doesn't implement backport of P0136 // doesn't implement backport of P0136
AutomakeReporter(ReporterConfig&& _config): AutomakeReporter( ReporterConfig&& _config ):
StreamingReporterBase(CATCH_MOVE(_config)) StreamingReporterBase( CATCH_MOVE( _config ) ) {
{} m_preferences.shouldReportAllAssertionStarts = false;
}
~AutomakeReporter() override; ~AutomakeReporter() override;
static std::string getDescription() { static std::string getDescription() {
@@ -13240,7 +13375,10 @@ namespace Catch {
class CompactReporter final : public StreamingReporterBase { class CompactReporter final : public StreamingReporterBase {
public: public:
using StreamingReporterBase::StreamingReporterBase; CompactReporter( ReporterConfig&& _config ):
StreamingReporterBase( CATCH_MOVE( _config ) ) {
m_preferences.shouldReportAllAssertionStarts = false;
}
~CompactReporter() override; ~CompactReporter() override;
@@ -13282,8 +13420,6 @@ namespace Catch {
void noMatchingTestCases( StringRef unmatchedSpec ) override; void noMatchingTestCases( StringRef unmatchedSpec ) override;
void reportInvalidTestSpec( StringRef arg ) override; void reportInvalidTestSpec( StringRef arg ) override;
void assertionStarting(AssertionInfo const&) override;
void assertionEnded(AssertionStats const& _assertionStats) override; void assertionEnded(AssertionStats const& _assertionStats) override;
void sectionStarting(SectionInfo const& _sectionInfo) override; void sectionStarting(SectionInfo const& _sectionInfo) override;
@@ -13637,7 +13773,6 @@ namespace Catch {
void sectionStarting( SectionInfo const& sectionInfo ) override; void sectionStarting( SectionInfo const& sectionInfo ) override;
void sectionEnded( SectionStats const& sectionStats ) override; void sectionEnded( SectionStats const& sectionStats ) override;
void assertionStarting( AssertionInfo const& assertionInfo ) override;
void assertionEnded( AssertionStats const& assertionStats ) override; void assertionEnded( AssertionStats const& assertionStats ) override;
//void testRunEndedCumulative() override; //void testRunEndedCumulative() override;
@@ -13764,6 +13899,11 @@ namespace Catch {
void updatePreferences(IEventListener const& reporterish); void updatePreferences(IEventListener const& reporterish);
public: public:
MultiReporter( IConfig const* config ):
IEventListener( config ) {
m_preferences.shouldReportAllAssertionStarts = false;
}
using IEventListener::IEventListener; using IEventListener::IEventListener;
void addListener( IEventListenerPtr&& listener ); void addListener( IEventListenerPtr&& listener );
@@ -13899,22 +14039,24 @@ namespace Catch {
#if !defined(CATCH_CONFIG_DISABLE) #if !defined(CATCH_CONFIG_DISABLE)
# define CATCH_REGISTER_REPORTER( name, reporterType ) \ # define CATCH_REGISTER_REPORTER( name, reporterType ) \
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
namespace { \ namespace { \
Catch::ReporterRegistrar<reporterType> INTERNAL_CATCH_UNIQUE_NAME( \ const Catch::ReporterRegistrar<reporterType> \
catch_internal_RegistrarFor )( name ); \ INTERNAL_CATCH_UNIQUE_NAME( catch_internal_RegistrarFor )( \
} \ name ); \
} \
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
# define CATCH_REGISTER_LISTENER( listenerType ) \ # define CATCH_REGISTER_LISTENER( listenerType ) \
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
namespace { \ namespace { \
Catch::ListenerRegistrar<listenerType> INTERNAL_CATCH_UNIQUE_NAME( \ const Catch::ListenerRegistrar<listenerType> \
catch_internal_RegistrarFor )( #listenerType##_catch_sr ); \ INTERNAL_CATCH_UNIQUE_NAME( catch_internal_RegistrarFor )( \
} \ #listenerType##_catch_sr ); \
} \
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
#else // CATCH_CONFIG_DISABLE #else // CATCH_CONFIG_DISABLE
@@ -13941,6 +14083,7 @@ namespace Catch {
, xml(m_stream) { , xml(m_stream) {
m_preferences.shouldRedirectStdOut = true; m_preferences.shouldRedirectStdOut = true;
m_preferences.shouldReportAllAssertions = false; m_preferences.shouldReportAllAssertions = false;
m_preferences.shouldReportAllAssertionStarts = false;
m_shouldStoreSuccesfulAssertions = false; m_shouldStoreSuccesfulAssertions = false;
} }
@@ -13989,6 +14132,7 @@ namespace Catch {
TAPReporter( ReporterConfig&& config ): TAPReporter( ReporterConfig&& config ):
StreamingReporterBase( CATCH_MOVE(config) ) { StreamingReporterBase( CATCH_MOVE(config) ) {
m_preferences.shouldReportAllAssertions = true; m_preferences.shouldReportAllAssertions = true;
m_preferences.shouldReportAllAssertionStarts = false;
} }
static std::string getDescription() { static std::string getDescription() {
@@ -14032,6 +14176,7 @@ namespace Catch {
: StreamingReporterBase( CATCH_MOVE(_config) ) : StreamingReporterBase( CATCH_MOVE(_config) )
{ {
m_preferences.shouldRedirectStdOut = true; m_preferences.shouldRedirectStdOut = true;
m_preferences.shouldReportAllAssertionStarts = false;
} }
~TeamCityReporter() override; ~TeamCityReporter() override;
@@ -14099,8 +14244,6 @@ namespace Catch {
void sectionStarting(SectionInfo const& sectionInfo) override; void sectionStarting(SectionInfo const& sectionInfo) override;
void assertionStarting(AssertionInfo const&) override;
void assertionEnded(AssertionStats const& assertionStats) override; void assertionEnded(AssertionStats const& assertionStats) override;
void sectionEnded(SectionStats const& sectionStats) override; void sectionEnded(SectionStats const& sectionStats) override;

View File

@@ -8,7 +8,7 @@
project( project(
'catch2', 'catch2',
'cpp', 'cpp',
version: '3.8.1', # CML version placeholder, don't delete version: '3.9.0', # CML version placeholder, don't delete
license: 'BSL-1.0', license: 'BSL-1.0',
meson_version: '>=0.54.1', meson_version: '>=0.54.1',
) )

View File

@@ -36,7 +36,7 @@ namespace Catch {
} }
Version const& libraryVersion() { Version const& libraryVersion() {
static Version version( 3, 8, 1, "", 0 ); static Version version( 3, 9, 0, "", 0 );
return version; return version;
} }

View File

@@ -9,7 +9,7 @@
#define CATCH_VERSION_MACROS_HPP_INCLUDED #define CATCH_VERSION_MACROS_HPP_INCLUDED
#define CATCH_VERSION_MAJOR 3 #define CATCH_VERSION_MAJOR 3
#define CATCH_VERSION_MINOR 8 #define CATCH_VERSION_MINOR 9
#define CATCH_VERSION_PATCH 1 #define CATCH_VERSION_PATCH 0
#endif // CATCH_VERSION_MACROS_HPP_INCLUDED #endif // CATCH_VERSION_MACROS_HPP_INCLUDED