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()
project(Catch2
VERSION 3.8.1 # CML version placeholder, don't delete
VERSION 3.9.0 # CML version placeholder, don't delete
LANGUAGES CXX
HOMEPAGE_URL "https://github.com/catchorg/Catch2"
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
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
[`--rng-seed`](#rng-seed)), and is subset invariant. What this means

View File

@@ -268,7 +268,7 @@ namespace Catch {
## 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
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
> Introduced in Catch2 X.Y.Z
> Introduced in Catch2 3.9.0
Catch2 can optionally support thread-safe assertions, that means, multiple
user-spawned threads can use the assertion macros at the same time. Due

View File

@@ -2,6 +2,7 @@
# Release notes
**Contents**<br>
[3.9.0](#390)<br>
[3.8.1](#381)<br>
[3.8.0](#380)<br>
[3.7.1](#371)<br>
@@ -67,6 +68,45 @@
[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
### Fixes

View File

@@ -169,7 +169,7 @@ Currently there are three customization options:
`assertionStarting` events. Most reporters do not, and opting out
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

View File

@@ -8,7 +8,7 @@
[Fatal errors and multiple threads](#fatal-errors-and-multiple-threads)<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.
Interacting with benchmark macros, message macros (e.g. `INFO` or `CAPTURE`),

View File

@@ -6,8 +6,8 @@
// SPDX-License-Identifier: BSL-1.0
// Catch v3.8.1
// Generated: 2025-04-08 12:33:19.863332
// Catch v3.9.0
// Generated: 2025-07-24 22:00:25.173359
// ----------------------------------------------------------
// This file is an amalgamation of multiple different files.
// You probably shouldn't edit it directly.
@@ -986,7 +986,7 @@ namespace Catch {
}
ScopedMessage::~ScopedMessage() {
if ( !uncaught_exceptions() && !m_moved ){
if ( !m_moved ){
getResultCapture().popScopedMessage(m_info);
}
}
@@ -1056,11 +1056,9 @@ namespace Catch {
m_messages.back().message += " := ";
}
Capturer::~Capturer() {
if ( !uncaught_exceptions() ){
assert( m_captured == m_messages.size() );
for( size_t i = 0; i < m_captured; ++i )
m_resultCapture.popScopedMessage( m_messages[i] );
}
assert( m_captured == m_messages.size() );
for ( size_t i = 0; i < m_captured; ++i )
m_resultCapture.popScopedMessage( m_messages[i] );
}
void Capturer::captureValue( size_t index, std::string const& value ) {
@@ -1161,7 +1159,6 @@ namespace Catch {
#include <algorithm>
#include <cassert>
#include <exception>
#include <iomanip>
@@ -1170,14 +1167,6 @@ namespace Catch {
namespace Catch {
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) {
auto reporter = Catch::getRegistryHub().getReporterRegistry().create(reporterName, CATCH_MOVE(config));
CATCH_ENFORCE(reporter, "No reporter registered with name: '" << reporterName << '\'');
@@ -1935,7 +1924,6 @@ namespace Catch {
#include <cmath>
#include <iomanip>
namespace Catch {
@@ -2283,7 +2271,7 @@ namespace Catch {
}
Version const& libraryVersion() {
static Version version( 3, 8, 1, "", 0 );
static Version version( 3, 9, 0, "", 0 );
return version;
}
@@ -4088,7 +4076,7 @@ namespace Catch {
// There is no 1-1 mapping between signals and windows exceptions.
// Windows can easily distinguish between SO and SigSegV,
// but SigInt, SigTerm, etc are handled differently.
static SignalDefs signalDefs[] = {
static constexpr SignalDefs signalDefs[] = {
{ EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" },
{ EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" },
{ EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" },
@@ -4159,7 +4147,7 @@ namespace Catch {
const char* name;
};
static SignalDefs signalDefs[] = {
static constexpr SignalDefs signalDefs[] = {
{ SIGINT, "SIGINT - Terminal interrupt signal" },
{ SIGILL, "SIGILL - Illegal instruction signal" },
{ SIGFPE, "SIGFPE - Floating point error signal" },
@@ -4323,8 +4311,6 @@ namespace Catch {
#include <cstdio>
#include <fstream>
#include <sstream>
#include <vector>
namespace Catch {
@@ -4765,7 +4751,7 @@ namespace Catch {
namespace Catch {
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
static LeakDetector leakDetector;
static const LeakDetector leakDetector;
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 {
@@ -5225,6 +5217,7 @@ namespace {
#pragma warning(disable:4146) // we negate uint32 during the rotate
#endif
// Safe rotr implementation thanks to John Regehr
CATCH2_CLANG_NO_SANITIZE_INTEGER
uint32_t rotate_right(uint32_t val, uint32_t count) {
const uint32_t mask = 31;
count &= mask;
@@ -5258,6 +5251,7 @@ namespace {
}
}
CATCH2_CLANG_NO_SANITIZE_INTEGER
SimplePcg32::result_type SimplePcg32::operator()() {
// prepare the output value
const uint32_t xorshifted = static_cast<uint32_t>(((m_state >> 18u) ^ m_state) >> 27u);
@@ -5742,23 +5736,55 @@ namespace Catch {
} // 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)
: m_runInfo(_config->name()),
m_config(_config),
m_reporter(CATCH_MOVE(reporter)),
m_lastAssertionInfo{ StringRef(), SourceLineInfo("",0), StringRef(), ResultDisposition::Normal },
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 );
m_reporter->testRunStarting(m_runInfo);
}
RunContext::~RunContext() {
updateTotalsFromAtomics();
m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, aborting()));
}
Totals RunContext::runTest(TestCaseHandle const& testCase) {
updateTotalsFromAtomics();
const Totals prevTotals = m_totals;
auto const& testInfo = testCase.getTestCaseInfo();
@@ -5813,6 +5839,7 @@ namespace Catch {
m_reporter->testCasePartialStarting(testInfo, testRuns);
updateTotalsFromAtomics();
const auto beforeRunTotals = m_totals;
runCurrentTest();
std::string oneRunCout = m_outputRedirect->getStdout();
@@ -5821,6 +5848,7 @@ namespace Catch {
redirectedCout += oneRunCout;
redirectedCerr += oneRunCerr;
updateTotalsFromAtomics();
const auto singleRunTotals = m_totals.delta(beforeRunTotals);
auto statsForOneRun = TestCaseStats(testInfo, singleRunTotals, CATCH_MOVE(oneRunCout), CATCH_MOVE(oneRunCerr), aborting());
m_reporter->testCasePartialEnded(statsForOneRun, testRuns);
@@ -5850,27 +5878,35 @@ namespace Catch {
void RunContext::assertionEnded(AssertionResult&& result) {
Detail::g_lastKnownLineInfo = result.m_info.lineInfo;
if (result.getResultType() == ResultWas::Ok) {
m_totals.assertions.passed++;
m_lastAssertionPassed = true;
m_atomicAssertionCount.passed++;
Detail::g_lastAssertionPassed = true;
} else if (result.getResultType() == ResultWas::ExplicitSkip) {
m_totals.assertions.skipped++;
m_lastAssertionPassed = true;
m_atomicAssertionCount.skipped++;
Detail::g_lastAssertionPassed = true;
} else if (!result.succeeded()) {
m_lastAssertionPassed = false;
Detail::g_lastAssertionPassed = false;
if (result.isOk()) {
}
else if( m_activeTestCase->getTestCaseInfo().okToFail() )
m_totals.assertions.failedButOk++;
else if( m_activeTestCase->getTestCaseInfo().okToFail() ) // Read from a shared state established before the threads could start, this is fine
m_atomicAssertionCount.failedButOk++;
else
m_totals.assertions.failed++;
m_atomicAssertionCount.failed++;
}
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 );
updateTotalsFromAtomics();
m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) );
}
@@ -5882,15 +5918,13 @@ namespace Catch {
// populateReaction is run if it is needed
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 ) {
auto _ = scopedDeactivate( *m_outputRedirect );
m_reporter->assertionStarting( info );
if (m_reportAssertionStarting) {
Detail::LockGuard lock( m_assertionMutex );
auto _ = scopedDeactivate( *m_outputRedirect );
m_reporter->assertionStarting( info );
}
}
bool RunContext::sectionStarted( StringRef sectionName,
@@ -5906,13 +5940,14 @@ namespace Catch {
m_activeSections.push_back(&sectionTracker);
SectionInfo sectionInfo( sectionLineInfo, static_cast<std::string>(sectionName) );
m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
Detail::g_lastKnownLineInfo = sectionLineInfo;
{
auto _ = scopedDeactivate( *m_outputRedirect );
m_reporter->sectionStarting( sectionInfo );
}
updateTotalsFromAtomics();
assertions = m_totals.assertions;
return true;
@@ -5920,12 +5955,11 @@ namespace Catch {
IGeneratorTracker*
RunContext::acquireGeneratorTracker( StringRef generatorName,
SourceLineInfo const& lineInfo ) {
using namespace Generators;
GeneratorTracker* tracker = GeneratorTracker::acquire(
auto* tracker = Generators::GeneratorTracker::acquire(
m_trackerContext,
TestCaseTracking::NameAndLocationRef(
generatorName, lineInfo ) );
m_lastAssertionInfo.lineInfo = lineInfo;
Detail::g_lastKnownLineInfo = lineInfo;
return tracker;
}
@@ -5938,7 +5972,7 @@ namespace Catch {
auto& currentTracker = m_trackerContext.currentTracker();
assert(
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>(
CATCH_MOVE(nameAndLoc), m_trackerContext, &currentTracker );
@@ -5957,12 +5991,13 @@ namespace Catch {
return false;
if (m_trackerContext.currentTracker().hasChildren())
return false;
m_totals.assertions.failed++;
m_atomicAssertionCount.failed++;
assertions.failed++;
return true;
}
void RunContext::sectionEnded(SectionEndInfo&& endInfo) {
updateTotalsFromAtomics();
Counts assertions = m_totals.assertions - endInfo.prevAssertions;
bool missingAssertions = testForMissingAssertions(assertions);
@@ -5979,9 +6014,6 @@ namespace Catch {
endInfo.durationInSeconds,
missingAssertions ) );
}
m_messages.clear();
m_messageScopes.clear();
}
void RunContext::sectionEndedEarly(SectionEndInfo&& endInfo) {
@@ -6016,8 +6048,18 @@ namespace Catch {
m_messages.push_back(message);
}
void RunContext::popScopedMessage(MessageInfo const & message) {
m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end());
void RunContext::popScopedMessage( MessageInfo const& message ) {
// 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 ) {
@@ -6031,6 +6073,18 @@ namespace Catch {
}
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);
}
@@ -6039,28 +6093,44 @@ namespace Catch {
}
void RunContext::handleFatalErrorCondition( StringRef message ) {
// 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 );
// We lock only when touching the reporters directly, to avoid
// deadlocks when we call into other functions that also want
// to lock the mutex before touching reporters.
//
// 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
m_reporter->fatalErrorEncountered( message );
// First notify reporter that bad things happened
m_reporter->fatalErrorEncountered( message );
}
// Don't rebuild the result -- the stringification itself can cause more fatal errors
// Instead, fake a result data.
AssertionResultData tempResult( ResultWas::FatalErrorCondition, { false } );
tempResult.message = static_cast<std::string>(message);
AssertionResult result(m_lastAssertionInfo, CATCH_MOVE(tempResult));
AssertionResult result( makeDummyAssertionInfo(),
CATCH_MOVE( tempResult ) );
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
// Since this is a fatal error, we have not had and won't have the opportunity to destruct them properly
while (!m_activeSections.empty()) {
auto nl = m_activeSections.back()->nameAndLocation();
SectionEndInfo endInfo{ SectionInfo(CATCH_MOVE(nl.location), CATCH_MOVE(nl.name)), {}, 0.0 };
auto const& nl = m_activeSections.back()->nameAndLocation();
SectionEndInfo endInfo{ SectionInfo(nl.location, nl.name), {}, 0.0 };
sectionEndedEarly(CATCH_MOVE(endInfo));
}
handleUnfinishedSections();
@@ -6085,32 +6155,44 @@ namespace Catch {
std::string(),
false));
m_totals.testCases.failed++;
updateTotalsFromAtomics();
m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, false));
}
bool RunContext::lastAssertionPassed() {
return m_lastAssertionPassed;
return Detail::g_lastAssertionPassed;
}
void RunContext::assertionPassed() {
m_lastAssertionPassed = true;
++m_totals.assertions.passed;
resetAssertionInfo();
m_messageScopes.clear();
void RunContext::assertionPassedFastPath(SourceLineInfo lineInfo) {
// We want to save the line info for better experience with unexpected assertions
Detail::g_lastKnownLineInfo = lineInfo;
++m_atomicAssertionCount.passed;
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 {
return m_totals.assertions.failed >= static_cast<std::size_t>(m_config->abortAfter());
return m_atomicAssertionCount.failed >= m_abortAfterXFailedAssertions;
}
void RunContext::runCurrentTest() {
auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);
m_reporter->sectionStarting(testCaseSection);
updateTotalsFromAtomics();
Counts prevAssertions = m_totals.assertions;
double duration = 0;
m_shouldReportUnexpected = true;
m_lastAssertionInfo = { "TEST_CASE"_sr, testCaseInfo.lineInfo, StringRef(), ResultDisposition::Normal };
Detail::g_lastKnownLineInfo = testCaseInfo.lineInfo;
Timer timer;
CATCH_TRY {
@@ -6127,18 +6209,23 @@ namespace Catch {
} CATCH_CATCH_ALL {
// Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions
// are reported without translation at the point of origin.
if( m_shouldReportUnexpected ) {
if ( m_shouldReportUnexpected ) {
AssertionReaction dummyReaction;
handleUnexpectedInflightException( m_lastAssertionInfo, translateActiveException(), dummyReaction );
handleUnexpectedInflightException( makeDummyAssertionInfo(),
translateActiveException(),
dummyReaction );
}
}
updateTotalsFromAtomics();
Counts assertions = m_totals.assertions - prevAssertions;
bool missingAssertions = testForMissingAssertions(assertions);
m_testCaseTracker->close();
handleUnfinishedSections();
m_messages.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);
m_reporter->sectionEnded(testCaseSectionStats);
@@ -6179,7 +6266,7 @@ namespace Catch {
if( result ) {
if (!m_includeSuccessfulResults) {
assertionPassed();
assertionPassedFastPath(info.lineInfo);
}
else {
reportExpr(info, ResultWas::Ok, &expr, negated);
@@ -6187,9 +6274,9 @@ namespace Catch {
}
else {
reportExpr(info, ResultWas::ExpressionFailed, &expr, negated );
populateReaction( reaction );
populateReaction(
reaction, info.resultDisposition & ResultDisposition::Normal );
}
resetAssertionInfo();
}
void RunContext::reportExpr(
AssertionInfo const &info,
@@ -6197,7 +6284,7 @@ namespace Catch {
ITransientExpression const *expr,
bool negated ) {
m_lastAssertionInfo = info;
Detail::g_lastKnownLineInfo = info.lineInfo;
AssertionResultData data( resultType, LazyExpression( negated ) );
AssertionResult assertionResult{ info, CATCH_MOVE( data ) };
@@ -6212,24 +6299,25 @@ namespace Catch {
std::string&& message,
AssertionReaction& reaction
) {
m_lastAssertionInfo = info;
Detail::g_lastKnownLineInfo = info.lineInfo;
AssertionResultData data( resultType, LazyExpression( false ) );
data.message = CATCH_MOVE( message );
AssertionResult assertionResult{ m_lastAssertionInfo,
AssertionResult assertionResult{ info,
CATCH_MOVE( data ) };
const auto isOk = assertionResult.isOk();
assertionEnded( CATCH_MOVE(assertionResult) );
if ( !isOk ) {
populateReaction( reaction );
populateReaction(
reaction, info.resultDisposition & ResultDisposition::Normal );
} else if ( resultType == ResultWas::ExplicitSkip ) {
// TODO: Need to handle this explicitly, as ExplicitSkip is
// considered "OK"
reaction.shouldSkip = true;
}
resetAssertionInfo();
}
void RunContext::handleUnexpectedExceptionNotThrown(
AssertionInfo const& info,
AssertionReaction& reaction
@@ -6242,49 +6330,67 @@ namespace Catch {
std::string&& message,
AssertionReaction& reaction
) {
m_lastAssertionInfo = info;
Detail::g_lastKnownLineInfo = info.lineInfo;
AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) );
data.message = CATCH_MOVE(message);
AssertionResult assertionResult{ info, CATCH_MOVE(data) };
assertionEnded( CATCH_MOVE(assertionResult) );
populateReaction( reaction );
resetAssertionInfo();
populateReaction( reaction,
info.resultDisposition & ResultDisposition::Normal );
}
void RunContext::populateReaction( AssertionReaction& reaction ) {
reaction.shouldDebugBreak = m_config->shouldDebugBreak();
reaction.shouldThrow = aborting() || (m_lastAssertionInfo.resultDisposition & ResultDisposition::Normal);
void RunContext::populateReaction( AssertionReaction& reaction,
bool has_normal_disposition ) {
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(
AssertionInfo const& info
) {
using namespace std::string_literals;
m_lastAssertionInfo = info;
Detail::g_lastKnownLineInfo = info.lineInfo;
AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) );
data.message = "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE"s;
AssertionResult assertionResult{ info, CATCH_MOVE( data ) };
assertionEnded( CATCH_MOVE(assertionResult) );
resetAssertionInfo();
}
void RunContext::handleNonExpr(
AssertionInfo const &info,
ResultWas::OfType resultType,
AssertionReaction &reaction
) {
m_lastAssertionInfo = info;
AssertionResultData data( resultType, LazyExpression( false ) );
AssertionResult assertionResult{ info, CATCH_MOVE( data ) };
const auto isOk = assertionResult.isOk();
assertionEnded( CATCH_MOVE(assertionResult) );
if ( !isOk ) { populateReaction( reaction ); }
resetAssertionInfo();
}
if ( isOk && !m_includeSuccessfulResults ) {
assertionPassedFastPath( info.lineInfo );
return;
}
assertionEnded( CATCH_MOVE(assertionResult) );
if ( !isOk ) {
populateReaction(
reaction, info.resultDisposition & ResultDisposition::Normal );
}
}
IResultCapture& getResultCapture() {
if (auto* capture = getCurrentContext().getResultCapture())
@@ -6516,7 +6622,7 @@ namespace Catch {
std::string origStr = CATCH_MOVE(str);
str.clear();
// 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());
do {
str.append(origStr, copyBegin, i-copyBegin );
@@ -6562,7 +6668,6 @@ namespace Catch {
#include <algorithm>
#include <ostream>
#include <cstring>
#include <cstdint>
namespace Catch {
StringRef::StringRef( char const* rawChars ) noexcept
@@ -8877,7 +8982,8 @@ private:
<< m_config->testSpec()
<< '\n';
}
m_stream << "RNG seed: " << getSeed() << '\n';
m_stream << "RNG seed: " << getSeed() << '\n'
<< std::flush;
}
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 }
};
}
}())) {}
}())) {
m_preferences.shouldReportAllAssertionStarts = false;
}
ConsoleReporter::~ConsoleReporter() = default;
std::string ConsoleReporter::getDescription() {
@@ -9313,8 +9422,6 @@ void ConsoleReporter::reportInvalidTestSpec( StringRef arg ) {
m_stream << "Invalid Filter: " << arg << '\n';
}
void ConsoleReporter::assertionStarting(AssertionInfo const&) {}
void ConsoleReporter::assertionEnded(AssertionStats const& _assertionStats) {
AssertionResult const& result = _assertionStats.assertionResult;
@@ -9426,7 +9533,8 @@ void ConsoleReporter::testRunStarting(TestRunInfo const& _testRunInfo) {
m_stream << m_colour->guardColour( Colour::BrightYellow ) << "Filters: "
<< m_config->testSpec() << '\n';
}
m_stream << "Randomness seeded to: " << getSeed() << '\n';
m_stream << "Randomness seeded to: " << getSeed() << '\n'
<< std::flush;
}
void ConsoleReporter::lazyPrint() {
@@ -9754,6 +9862,7 @@ namespace Catch {
#include <algorithm>
#include <cfloat>
#include <cmath>
#include <cstdio>
#include <ostream>
#include <iomanip>
@@ -9917,9 +10026,29 @@ namespace Catch {
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 ) {
ReusableStringStream rss;
rss << " " << std::setw( 2 ) << tagCount.count << " ";
rss << " " << std::setw( maxTagCountLen ) << tagCount.count << " ";
auto str = rss.str();
auto wrapper = TextFlow::Column( tagCount.all() )
.initialIndent( 0 )
@@ -10117,6 +10246,8 @@ namespace Catch {
// not, but for machine-parseable reporters I think the answer
// should be yes.
m_preferences.shouldReportAllAssertions = true;
// We only handle assertions when they end
m_preferences.shouldReportAllAssertionStarts = false;
m_objectWriters.emplace( m_stream );
m_writers.emplace( Writer::Object );
@@ -10346,7 +10477,6 @@ namespace Catch {
endObject();
}
void JsonReporter::assertionStarting( AssertionInfo const& /*assertionInfo*/ ) {}
void JsonReporter::assertionEnded( AssertionStats const& assertionStats ) {
// TODO: There is lot of different things to handle here, but
// we can fill it in later, after we show that the basic
@@ -10513,6 +10643,7 @@ namespace Catch {
{
m_preferences.shouldRedirectStdOut = true;
m_preferences.shouldReportAllAssertions = false;
m_preferences.shouldReportAllAssertionStarts = false;
m_shouldStoreSuccesfulAssertions = false;
}
@@ -10743,6 +10874,8 @@ namespace Catch {
reporterish.getPreferences().shouldRedirectStdOut;
m_preferences.shouldReportAllAssertions |=
reporterish.getPreferences().shouldReportAllAssertions;
m_preferences.shouldReportAllAssertionStarts |=
reporterish.getPreferences().shouldReportAllAssertionStarts;
}
void MultiReporter::addListener( IEventListenerPtr&& listener ) {
@@ -11300,7 +11433,8 @@ namespace Catch {
if ( m_config->testSpec().hasFilters() ) {
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 ) {
@@ -11514,6 +11648,7 @@ namespace Catch {
{
m_preferences.shouldRedirectStdOut = true;
m_preferences.shouldReportAllAssertions = true;
m_preferences.shouldReportAllAssertionStarts = false;
}
XmlReporter::~XmlReporter() = default;
@@ -11570,8 +11705,6 @@ namespace Catch {
}
}
void XmlReporter::assertionStarting( AssertionInfo const& ) { }
void XmlReporter::assertionEnded( AssertionStats const& assertionStats ) {
AssertionResult const& result = assertionStats.assertionResult;

View File

@@ -6,8 +6,8 @@
// SPDX-License-Identifier: BSL-1.0
// Catch v3.8.1
// Generated: 2025-04-08 12:33:19.851017
// Catch v3.9.0
// Generated: 2025-07-24 22:00:24.654688
// ----------------------------------------------------------
// This file is an amalgamation of multiple different files.
// You probably shouldn't edit it directly.
@@ -1100,9 +1100,7 @@ namespace Catch {
AssertionReaction &reaction ) = 0;
virtual bool lastAssertionPassed() = 0;
virtual void assertionPassed() = 0;
// Deprecated, do not use:
virtual std::string getCurrentTestName() const = 0;
@@ -1129,6 +1127,7 @@ namespace Catch {
//! Deriving classes become noncopyable and nonmovable
class NonCopyable {
public:
NonCopyable( NonCopyable const& ) = delete;
NonCopyable( NonCopyable&& ) = delete;
NonCopyable& operator=( NonCopyable const& ) = delete;
@@ -1144,7 +1143,6 @@ namespace Catch {
#endif // CATCH_NONCOPYABLE_HPP_INCLUDED
#include <chrono>
#include <iosfwd>
#include <string>
#include <vector>
@@ -1599,8 +1597,7 @@ namespace Catch {
namespace Benchmark {
namespace Detail {
template <typename T, typename U>
struct is_related
: std::is_same<std::decay_t<T>, std::decay_t<U>> {};
static constexpr bool is_related_v = std::is_same<std::decay_t<T>, std::decay_t<U>>::value;
/// 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
@@ -1641,7 +1638,7 @@ namespace Catch {
BenchmarkFunction();
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)
: f(new model<std::decay_t<Fun>>(CATCH_FORWARD(fun))) {}
@@ -1767,8 +1764,6 @@ namespace Catch {
#define CATCH_TIMING_HPP_INCLUDED
#include <type_traits>
namespace Catch {
namespace Benchmark {
template <typename Result>
@@ -2167,7 +2162,7 @@ namespace Catch {
}
// 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) {
auto const* cfg = getCurrentContext().getConfig();
if (!cfg->skipBenchmarks()) {
@@ -2496,18 +2491,14 @@ namespace Catch {
return rawMemoryToString( &object, sizeof(object) );
}
template<typename T>
class IsStreamInsertable {
template<typename Stream, typename U>
static auto test(int)
-> decltype(std::declval<Stream&>() << std::declval<U>(), std::true_type());
template<typename T,typename = void>
static constexpr bool IsStreamInsertable_v = false;
template<typename, typename>
static auto test(...)->std::false_type;
public:
static const bool value = decltype(test<std::ostream, const T&>(0))::value;
};
template <typename T>
static constexpr bool IsStreamInsertable_v<
T,
decltype( void( std::declval<std::ostream&>() << std::declval<T>() ) )> =
true;
template<typename E>
std::string convertUnknownEnumToString( E e );
@@ -2552,7 +2543,7 @@ namespace Catch {
struct StringMaker {
template <typename Fake = T>
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) {
ReusableStringStream rss;
// NB: call using the function-like syntax to avoid ambiguity with
@@ -2563,7 +2554,7 @@ namespace Catch {
template <typename Fake = T>
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 ) {
#if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER)
return Detail::convertUnstreamable(value);
@@ -2955,7 +2946,7 @@ namespace Catch {
}
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 ) {
return rangeToString( range );
}
@@ -3792,7 +3783,7 @@ namespace Catch {
WarnAbout::What warnings = WarnAbout::Nothing;
ShowDurations showDurations = ShowDurations::DefaultForReporter;
double minDuration = -1;
TestRunOrder runOrder = TestRunOrder::Declared;
TestRunOrder runOrder = TestRunOrder::Randomized;
ColourMode defaultColourMode = ColourMode::PlatformDefault;
WaitForKeypress::When waitForKeypress = WaitForKeypress::Never;
@@ -3938,6 +3929,19 @@ namespace Catch {
#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>
namespace Catch {
@@ -3953,9 +3957,11 @@ namespace Catch {
ResultWas::OfType type;
unsigned int sequence;
DEPRECATED( "Explicitly use the 'sequence' member instead" )
bool operator == (MessageInfo const& other) const {
return sequence == other.sequence;
}
DEPRECATED( "Explicitly use the 'sequence' member instead" )
bool operator < (MessageInfo const& other) const {
return sequence < other.sequence;
}
@@ -4237,15 +4243,13 @@ namespace Catch {
};
template <typename F, typename = void>
struct is_unary_function : std::false_type {};
static constexpr bool is_unary_function_v = false;
template <typename F>
struct is_unary_function<
static constexpr bool is_unary_function_v<
F,
Catch::Detail::void_t<decltype(
std::declval<F>()( fake_arg() ) )
>
> : std::true_type {};
Catch::Detail::void_t<decltype( std::declval<F>()(
fake_arg() ) )>> = true;
// Traits for extracting arg and return type of lambdas (for single
// argument lambdas)
@@ -4678,14 +4682,14 @@ namespace Catch {
template <typename T,
typename = typename std::enable_if_t<
!Detail::is_unary_function<T>::value>>
!Detail::is_unary_function_v<T>>>
ParserRefImpl( T& ref, StringRef hint ):
m_ref( std::make_shared<BoundValueRef<T>>( ref ) ),
m_hint( hint ) {}
template <typename LambdaT,
typename = typename std::enable_if_t<
Detail::is_unary_function<LambdaT>::value>>
Detail::is_unary_function_v<LambdaT>>>
ParserRefImpl( LambdaT const& ref, StringRef hint ):
m_ref( std::make_shared<BoundLambda<LambdaT>>( ref ) ),
m_hint( hint ) {}
@@ -4752,7 +4756,7 @@ namespace Catch {
template <typename LambdaT,
typename = typename std::enable_if_t<
Detail::is_unary_function<LambdaT>::value>>
Detail::is_unary_function_v<LambdaT>>>
Opt( LambdaT const& ref, StringRef hint ):
ParserRefImpl( ref, hint ) {}
@@ -4762,7 +4766,7 @@ namespace Catch {
template <typename T,
typename = typename std::enable_if_t<
!Detail::is_unary_function<T>::value>>
!Detail::is_unary_function_v<T>>>
Opt( T& ref, StringRef hint ):
ParserRefImpl( ref, hint ) {}
@@ -4932,6 +4936,14 @@ 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 {
public:
@@ -5016,7 +5028,7 @@ namespace Catch {
#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
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
#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
* 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
* operators, checking whether `T == U` are comparable with the given
@@ -5311,7 +5323,7 @@ namespace Catch {
public:
constexpr auto isBinaryExpression() const -> bool { return m_isBinaryExpression; }
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;
constexpr ITransientExpression( bool isBinaryExpression, bool result )
@@ -5912,7 +5924,7 @@ namespace Catch {
#else
// 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`).
namespace Catch {
@@ -6195,6 +6207,53 @@ static int catchInternalSectionHint = 0;
#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
// forces them to be defined prefixed with CATCH_. We also like to
// 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_SECTION( ... ) INTERNAL_CATCH_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_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)
@@ -6327,10 +6392,16 @@ static int catchInternalSectionHint = 0;
#define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
#define SECTION( ... ) INTERNAL_CATCH_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 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)
@@ -6424,6 +6495,15 @@ static int catchInternalSectionHint = 0;
#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_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__)))
@@ -6483,10 +6563,10 @@ static int catchInternalSectionHint = 0;
#define INTERNAL_CATCH_MAKE_NAMESPACE(name) INTERNAL_CATCH_MAKE_NAMESPACE2(name)
#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__))
#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__)))
#endif
@@ -6509,11 +6589,11 @@ static int catchInternalSectionHint = 0;
#define INTERNAL_CATCH_TYPE_GEN\
template<typename...> struct TypeList {};\
template<typename...Ts>\
constexpr auto get_wrapper() noexcept -> TypeList<Ts...> { return {}; }\
template<typename... Ts>\
constexpr auto get_wrapper(Catch::Detail::priority_tag<1>) noexcept -> TypeList<Ts...> { return {}; }\
template<template<typename...> class...> struct TemplateTypeList{};\
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...>\
struct append;\
template<typename...>\
@@ -6543,10 +6623,10 @@ static int catchInternalSectionHint = 0;
#define INTERNAL_CATCH_NTTP_1(signature, ...)\
template<INTERNAL_CATCH_REMOVE_PARENS(signature)> struct Nttp{};\
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...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)>\
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)>\
static void TestName()
#define INTERNAL_CATCH_NTTP_REGISTER0(TestFunc, signature)\
template<typename Type>\
void reg_test(TypeList<Type>, Catch::NameAndTags nameAndTags)\
#define INTERNAL_CATCH_TYPES_REGISTER(TestFunc)\
template<typename... Ts>\
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, ...)\
template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
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_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_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_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__)
@@ -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_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_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_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__))
@@ -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* 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]);\
(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 ) = [](){ \
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; \
static const int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
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; \
t.reg_tests(); \
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 */\
} \
};\
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
static const int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
using TestInit = typename convert<TestName, TmplList>::type; \
TestInit t; \
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 */ \
}\
};\
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__)>();\
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* 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]);\
(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 ) = [](){\
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;\
static const int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
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;\
t.reg_tests();\
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 */ \
}\
};\
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
static const int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
using TestInit = typename convert<TestNameClass, TmplList>::type;\
TestInit t;\
t.reg_tests();\
@@ -7201,6 +7282,22 @@ namespace Catch {
#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
#define CATCH_TRANSLATE_EXCEPTION_HPP_INCLUDED
@@ -7288,7 +7385,7 @@ namespace Catch {
static std::string translatorName( signature ); \
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
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 \
static std::string translatorName( signature )
@@ -7349,8 +7446,8 @@ namespace Catch {
#define CATCH_VERSION_MACROS_HPP_INCLUDED
#define CATCH_VERSION_MAJOR 3
#define CATCH_VERSION_MINOR 8
#define CATCH_VERSION_PATCH 1
#define CATCH_VERSION_MINOR 9
#define CATCH_VERSION_PATCH 0
#endif // CATCH_VERSION_MACROS_HPP_INCLUDED
@@ -7391,7 +7488,7 @@ namespace Catch {
m_msg(msg)
{}
const char* what() const noexcept override final;
const char* what() const noexcept final;
};
} // end namespace Catch
@@ -8778,26 +8875,9 @@ auto from_range(Container const& cnt) {
#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 <string>
#include <vector>
#include <iosfwd>
namespace Catch {
@@ -8893,6 +8973,11 @@ namespace Catch {
//! Catch2 should call `Reporter::assertionEnded` even for passing
//! assertions
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
#include <exception>
#include <exception> // for `std::exception` in no-exception configuration
namespace Catch {
#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
@@ -9568,7 +9653,6 @@ namespace Catch {
#define CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
#include <vector>
#include <string>
namespace Catch {
@@ -9768,8 +9852,8 @@ namespace Detail {
#ifndef CATCH_IS_PERMUTATION_HPP_INCLUDED
#define CATCH_IS_PERMUTATION_HPP_INCLUDED
#include <algorithm>
#include <iterator>
#include <type_traits>
namespace Catch {
namespace Detail {
@@ -9906,8 +9990,6 @@ namespace Catch {
#include <iosfwd>
#include <cstddef>
#include <ostream>
#include <string>
namespace Catch {
@@ -10491,6 +10573,48 @@ using TestCaseTracking::SectionTracker;
#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>
namespace Catch {
@@ -10578,18 +10702,18 @@ namespace Catch {
bool lastAssertionPassed() override;
void assertionPassed() override;
public:
// !TBD We need to do this another way!
bool aborting() const;
private:
void assertionPassedFastPath( SourceLineInfo lineInfo );
// Update the non-thread-safe m_totals from the atomic assertion counts.
void updateTotalsFromAtomics();
void runCurrentTest();
void invokeActiveTestCase();
void resetAssertionInfo();
bool testForMissingAssertions( Counts& assertions );
void assertionEnded( AssertionResult&& result );
@@ -10599,31 +10723,42 @@ namespace Catch {
ITransientExpression const *expr,
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:
void handleUnfinishedSections();
mutable Detail::Mutex m_assertionMutex;
TestRunInfo m_runInfo;
TestCaseHandle const* m_activeTestCase = nullptr;
ITracker* m_testCaseTracker = nullptr;
Optional<AssertionResult> m_lastResult;
IConfig const* m_config;
Totals m_totals;
Detail::AtomicCounts m_atomicAssertionCount;
IEventListenerPtr m_reporter;
std::vector<MessageInfo> m_messages;
std::vector<ScopedMessage> m_messageScopes; /* Keeps owners of so-called unscoped messages. */
AssertionInfo m_lastAssertionInfo;
// Owners for the UNSCOPED_X information macro
std::vector<ScopedMessage> m_messageScopes;
std::vector<SectionEndInfo> m_unfinishedSections;
std::vector<ITracker*> m_activeSections;
TrackerContext m_trackerContext;
Detail::unique_ptr<OutputRedirect> m_outputRedirect;
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;
// 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;
// Caches m_config->shouldDebugBreak() to avoid vptr calls/allow inlining
bool m_shouldDebugBreak;
};
void seedRng(IConfig const& config);
@@ -10637,7 +10772,6 @@ namespace Catch {
#define CATCH_SHARDING_HPP_INCLUDED
#include <cassert>
#include <cmath>
#include <algorithm>
namespace Catch {
@@ -11860,19 +11994,19 @@ namespace Matchers {
}
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,
std::remove_cv_t<std::remove_reference_t<T>>
>;
>::value;
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>
using is_matcher = std::is_base_of<
static constexpr bool is_matcher_v = std::is_base_of<
Catch::Matchers::MatcherUntypedBase,
std::remove_cv_t<std::remove_reference_t<T>>
>;
>::value;
template<std::size_t N, typename Arg>
@@ -11945,7 +12079,7 @@ namespace Matchers {
//! Avoids type nesting for `GenericAllOf && some matcher` case
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...>&& lhs,
MatcherRHS const& rhs) {
@@ -11954,7 +12088,7 @@ namespace Matchers {
//! Avoids type nesting for `some matcher && GenericAllOf` case
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 && (
MatcherLHS const& lhs,
MatchAllOfGeneric<MatcherTs...>&& rhs) {
@@ -11999,7 +12133,7 @@ namespace Matchers {
//! Avoids type nesting for `GenericAnyOf || some matcher` case
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...>&& lhs,
MatcherRHS const& rhs) {
@@ -12008,7 +12142,7 @@ namespace Matchers {
//! Avoids type nesting for `some matcher || GenericAnyOf` case
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 || (
MatcherLHS const& lhs,
MatchAnyOfGeneric<MatcherTs...>&& rhs) {
@@ -12048,20 +12182,20 @@ namespace Matchers {
// compose only generic matchers
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) {
return { lhs, rhs };
}
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) {
return { lhs, rhs };
}
//! Wrap provided generic matcher in generic negator
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) {
return Detail::MatchNotOfGeneric<MatcherT>{matcher};
}
@@ -12069,25 +12203,25 @@ namespace Matchers {
// compose mixed generic and non-generic matchers
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) {
return { lhs, rhs };
}
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) {
return { lhs, rhs };
}
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) {
return { lhs, rhs };
}
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) {
return { lhs, rhs };
}
@@ -12164,7 +12298,7 @@ namespace Catch {
//! Creates a matcher that accepts ranges/containers with specific size
HasSizeMatcher SizeIs(std::size_t sz);
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) {
return SizeMatchesMatcher<Matcher>{CATCH_FORWARD(m)};
}
@@ -12179,8 +12313,8 @@ namespace Catch {
#define CATCH_MATCHERS_CONTAINS_HPP_INCLUDED
#include <algorithm>
#include <functional>
#include <type_traits>
namespace Catch {
namespace Matchers {
@@ -12242,14 +12376,14 @@ namespace Catch {
* Uses `std::equal_to` to do the comparison
*/
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) {
return { CATCH_FORWARD(elem), std::equal_to<>{} };
}
//! Creates a matcher that checks whether a range contains element matching a 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) {
return { CATCH_FORWARD(matcher) };
}
@@ -12626,8 +12760,7 @@ namespace Catch {
#define CATCH_MATCHERS_RANGE_EQUALS_HPP_INCLUDED
#include <algorithm>
#include <utility>
#include <functional>
namespace Catch {
namespace Matchers {
@@ -13211,9 +13344,11 @@ namespace Catch {
public:
// GCC5 compat: we cannot use inherited constructor, because it
// doesn't implement backport of P0136
AutomakeReporter(ReporterConfig&& _config):
StreamingReporterBase(CATCH_MOVE(_config))
{}
AutomakeReporter( ReporterConfig&& _config ):
StreamingReporterBase( CATCH_MOVE( _config ) ) {
m_preferences.shouldReportAllAssertionStarts = false;
}
~AutomakeReporter() override;
static std::string getDescription() {
@@ -13240,7 +13375,10 @@ namespace Catch {
class CompactReporter final : public StreamingReporterBase {
public:
using StreamingReporterBase::StreamingReporterBase;
CompactReporter( ReporterConfig&& _config ):
StreamingReporterBase( CATCH_MOVE( _config ) ) {
m_preferences.shouldReportAllAssertionStarts = false;
}
~CompactReporter() override;
@@ -13282,8 +13420,6 @@ namespace Catch {
void noMatchingTestCases( StringRef unmatchedSpec ) override;
void reportInvalidTestSpec( StringRef arg ) override;
void assertionStarting(AssertionInfo const&) override;
void assertionEnded(AssertionStats const& _assertionStats) override;
void sectionStarting(SectionInfo const& _sectionInfo) override;
@@ -13637,7 +13773,6 @@ namespace Catch {
void sectionStarting( SectionInfo const& sectionInfo ) override;
void sectionEnded( SectionStats const& sectionStats ) override;
void assertionStarting( AssertionInfo const& assertionInfo ) override;
void assertionEnded( AssertionStats const& assertionStats ) override;
//void testRunEndedCumulative() override;
@@ -13764,6 +13899,11 @@ namespace Catch {
void updatePreferences(IEventListener const& reporterish);
public:
MultiReporter( IConfig const* config ):
IEventListener( config ) {
m_preferences.shouldReportAllAssertionStarts = false;
}
using IEventListener::IEventListener;
void addListener( IEventListenerPtr&& listener );
@@ -13899,22 +14039,24 @@ namespace Catch {
#if !defined(CATCH_CONFIG_DISABLE)
# define CATCH_REGISTER_REPORTER( name, reporterType ) \
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
namespace { \
Catch::ReporterRegistrar<reporterType> INTERNAL_CATCH_UNIQUE_NAME( \
catch_internal_RegistrarFor )( name ); \
} \
# define CATCH_REGISTER_REPORTER( name, reporterType ) \
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
namespace { \
const Catch::ReporterRegistrar<reporterType> \
INTERNAL_CATCH_UNIQUE_NAME( catch_internal_RegistrarFor )( \
name ); \
} \
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
# define CATCH_REGISTER_LISTENER( listenerType ) \
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
namespace { \
Catch::ListenerRegistrar<listenerType> INTERNAL_CATCH_UNIQUE_NAME( \
catch_internal_RegistrarFor )( #listenerType##_catch_sr ); \
} \
# define CATCH_REGISTER_LISTENER( listenerType ) \
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
namespace { \
const Catch::ListenerRegistrar<listenerType> \
INTERNAL_CATCH_UNIQUE_NAME( catch_internal_RegistrarFor )( \
#listenerType##_catch_sr ); \
} \
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
#else // CATCH_CONFIG_DISABLE
@@ -13941,6 +14083,7 @@ namespace Catch {
, xml(m_stream) {
m_preferences.shouldRedirectStdOut = true;
m_preferences.shouldReportAllAssertions = false;
m_preferences.shouldReportAllAssertionStarts = false;
m_shouldStoreSuccesfulAssertions = false;
}
@@ -13989,6 +14132,7 @@ namespace Catch {
TAPReporter( ReporterConfig&& config ):
StreamingReporterBase( CATCH_MOVE(config) ) {
m_preferences.shouldReportAllAssertions = true;
m_preferences.shouldReportAllAssertionStarts = false;
}
static std::string getDescription() {
@@ -14032,6 +14176,7 @@ namespace Catch {
: StreamingReporterBase( CATCH_MOVE(_config) )
{
m_preferences.shouldRedirectStdOut = true;
m_preferences.shouldReportAllAssertionStarts = false;
}
~TeamCityReporter() override;
@@ -14099,8 +14244,6 @@ namespace Catch {
void sectionStarting(SectionInfo const& sectionInfo) override;
void assertionStarting(AssertionInfo const&) override;
void assertionEnded(AssertionStats const& assertionStats) override;
void sectionEnded(SectionStats const& sectionStats) override;

View File

@@ -8,7 +8,7 @@
project(
'catch2',
'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',
meson_version: '>=0.54.1',
)

View File

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

View File

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