diff --git a/CMakeLists.txt b/CMakeLists.txt
index c02705596b..7233477fb0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -37,7 +37,7 @@ endif()
project(Catch2
- VERSION 3.0.1 # CML version placeholder, don't delete
+ VERSION 3.1.0 # CML version placeholder, don't delete
LANGUAGES CXX
# HOMEPAGE_URL is not supported until CMake version 3.12, which
# we do not target yet.
diff --git a/docs/cmake-integration.md b/docs/cmake-integration.md
index 9637be9b02..dc3efc9d9f 100644
--- a/docs/cmake-integration.md
+++ b/docs/cmake-integration.md
@@ -262,7 +262,7 @@ ParseAndAddCatchTests(bar)
### `CatchShardTests.cmake`
-> `CatchShardTests.cmake` was introduced in Catch2 X.Y.Z.
+> `CatchShardTests.cmake` was introduced in Catch2 3.1.0.
`CatchShardTests.cmake` provides a function
`catch_add_sharded_tests(TEST_BINARY)` that splits tests from `TEST_BINARY`
diff --git a/docs/configuration.md b/docs/configuration.md
index d857e79240..9fd7f58b6d 100644
--- a/docs/configuration.md
+++ b/docs/configuration.md
@@ -103,7 +103,7 @@ Catch2 will register a `JUnit` reporter writing to a path pointed by `XML_OUTPUT
> `CATCH_CONFIG_BAZEL_SUPPORT` was [introduced](https://github.com/catchorg/Catch2/pull/2399) in Catch2 3.0.1.
-> `CATCH_CONFIG_BAZEL_SUPPORT` was [deprecated](https://github.com/catchorg/Catch2/pull/2459) in Catch2 X.Y.Z.
+> `CATCH_CONFIG_BAZEL_SUPPORT` was [deprecated](https://github.com/catchorg/Catch2/pull/2459) in Catch2 3.1.0.
## C++11 toggles
diff --git a/docs/release-notes.md b/docs/release-notes.md
index 3a5de2762e..da2c598ceb 100644
--- a/docs/release-notes.md
+++ b/docs/release-notes.md
@@ -2,6 +2,7 @@
# Release notes
**Contents**
+[3.1.0](#310)
[3.0.1](#301)
[2.13.7](#2137)
[2.13.6](#2136)
@@ -49,6 +50,45 @@
[Even Older versions](#even-older-versions)
+## 3.1.0
+
+### Improvements
+* Improved suppression of `-Wparentheses` for older GCCs
+ * Turns out that even GCC 9 does not properly handle `_Pragma`s in the C++ frontend.
+* Added type constraints onto `random` generator (#2433)
+ * These constraints copy what the standard says for the underlying `std::uniform_int_distribution`
+* Suppressed -Wunused-variable from nvcc (#2306, #2427)
+* Suppressed -Wunused-variable from MinGW (#2132)
+* Added All/Any/NoneTrue range matchers (#2319)
+ * These check that all/any/none of boolean values in a range are true.
+* The JUnit reporter now normalizes classnames from C++ namespaces to Java-like namespaces (#2468)
+ * This provides better support for other JUnit based tools.
+* The Bazel support now understands `BAZEL_TEST` environment variable (#2459)
+ * The `CATCH_CONFIG_BAZEL_SUPPORT` configuration option is also still supported.
+* Returned support for compiling Catch2 with GCC 5 (#2448)
+ * This required removing inherited constructors from Catch2's internals.
+ * I recommend updating to a newer GCC anyway.
+* `catch_discover_tests` now has a new options for setting library load path(s) when running the Catch2 binary (#2467)
+
+
+### Fixes
+* Fixed crash when listing listeners without any registered listeners (#2442)
+* Fixed nvcc compilation error in constructor benchmarking helper (#2477)
+* Catch2's CMakeList supports pre-3.12 CMake again (#2428)
+ * The gain from requiring CMake 3.12 was very minor, but y'all should really update to newer CMake
+
+
+### Miscellaneous
+* Fixed SelfTest build on MinGW (#2447)
+* The in-repo conan recipe exports the CMake helper (#2460)
+* Added experimental CMake script to showcase using test case sharding together with CTest
+ * Compared to `catch_discover_tests`, it supports very limited number of options and customization
+* Added documentation page on best practices when running Catch2 tests
+* Catch2 can be built as a dynamic library (#2397, #2398)
+ * Note that Catch2 does not have visibility annotations, and you are responsible for ensuring correct visibility built into the resulting library.
+
+
+
## 3.0.1
**Catch2 now uses statically compiled library as its distribution model.
diff --git a/extras/catch_amalgamated.cpp b/extras/catch_amalgamated.cpp
index bd8c8119ba..ecda2301b3 100644
--- a/extras/catch_amalgamated.cpp
+++ b/extras/catch_amalgamated.cpp
@@ -5,8 +5,8 @@
// SPDX-License-Identifier: BSL-1.0
-// Catch v3.0.1
-// Generated: 2022-05-17 22:08:47.054486
+// Catch v3.1.0
+// Generated: 2022-07-17 20:14:05.885021
// ----------------------------------------------------------
// This file is an amalgamation of multiple different files.
// You probably shouldn't edit it directly.
@@ -15,6 +15,51 @@
#include "catch_amalgamated.hpp"
+
+
+namespace Catch {
+ namespace Benchmark {
+ namespace Detail {
+ ChronometerConcept::~ChronometerConcept() = default;
+ } // namespace Detail
+ } // namespace Benchmark
+} // namespace Catch
+
+
+
+
+namespace Catch {
+ namespace Benchmark {
+ namespace Detail {
+ BenchmarkFunction::callable::~callable() = default;
+ } // namespace Detail
+ } // namespace Benchmark
+} // namespace Catch
+
+
+
+#include
+
+namespace Catch {
+ namespace Benchmark {
+ namespace Detail {
+ struct optimized_away_error : std::exception {
+ const char* what() const noexcept override;
+ };
+
+ const char* optimized_away_error::what() const noexcept {
+ return "could not measure benchmark, maybe it was optimized away";
+ }
+
+ void throw_optimized_away_error() {
+ Catch::throw_exception(optimized_away_error{});
+ }
+
+ } // namespace Detail
+ } // namespace Benchmark
+} // namespace Catch
+
+
// Adapted from donated nonius code.
@@ -265,72 +310,6 @@ namespace Catch {
} // namespace Catch
-/** \file
- * This is a special TU that combines what would otherwise be a very
- * small benchmarking-related TUs into one bigger TU.
- *
- * The reason for this is compilation performance improvements by
- * avoiding reparsing headers for many small TUs, instead having this
- * one TU include bit more, but having it all parsed only once.
- *
- * To avoid heavy-tail problem with compilation times, each "subpart"
- * of Catch2 has its own combined TU like this.
- */
-
-////////////////////////////////////////////
-// vvv formerly catch_chronometer.cpp vvv //
-////////////////////////////////////////////
-
-
-namespace Catch {
- namespace Benchmark {
- namespace Detail {
- ChronometerConcept::~ChronometerConcept() = default;
- } // namespace Detail
- } // namespace Benchmark
-} // namespace Catch
-
-
-///////////////////////////////////////////////////
-// vvv formerly catch_benchmark_function.cpp vvv //
-///////////////////////////////////////////////////
-
-
-namespace Catch {
- namespace Benchmark {
- namespace Detail {
- BenchmarkFunction::callable::~callable() = default;
- } // namespace Detail
- } // namespace Benchmark
-} // namespace Catch
-
-
-/////////////////////////////////////////////////
-// vvv formerly catch_run_for_at_least.cpp vvv //
-/////////////////////////////////////////////////
-
-#include
-
-namespace Catch {
- namespace Benchmark {
- namespace Detail {
- struct optimized_away_error : std::exception {
- const char* what() const noexcept override;
- };
-
- const char* optimized_away_error::what() const noexcept {
- return "could not measure benchmark, maybe it was optimized away";
- }
-
- void throw_optimized_away_error() {
- Catch::throw_exception(optimized_away_error{});
- }
-
- } // namespace Detail
- } // namespace Benchmark
-} // namespace Catch
-
-
#include
#include
@@ -507,6 +486,28 @@ namespace Catch {
+namespace {
+ bool provideBazelReporterOutput() {
+#ifdef CATCH_CONFIG_BAZEL_SUPPORT
+ return true;
+#else
+
+# if defined( _MSC_VER )
+ // On Windows getenv throws a warning as there is no input validation,
+ // since the switch is hardcoded, this should not be an issue.
+# pragma warning( push )
+# pragma warning( disable : 4996 )
+# endif
+
+ return std::getenv( "BAZEL_TEST" ) != nullptr;
+
+# if defined( _MSC_VER )
+# pragma warning( pop )
+# endif
+#endif
+ }
+}
+
namespace Catch {
bool operator==( ProcessedReporterSpec const& lhs,
@@ -553,27 +554,27 @@ namespace Catch {
} );
}
-#if defined( CATCH_CONFIG_BAZEL_SUPPORT )
- // Register a JUnit reporter for Bazel. Bazel sets an environment
- // variable with the path to XML output. If this file is written to
- // during test, Bazel will not generate a default XML output.
- // This allows the XML output file to contain higher level of detail
- // than what is possible otherwise.
+ if(provideBazelReporterOutput()){
+ // Register a JUnit reporter for Bazel. Bazel sets an environment
+ // variable with the path to XML output. If this file is written to
+ // during test, Bazel will not generate a default XML output.
+ // This allows the XML output file to contain higher level of detail
+ // than what is possible otherwise.
# if defined( _MSC_VER )
- // On Windows getenv throws a warning as there is no input validation,
- // since the key is hardcoded, this should not be an issue.
-# pragma warning( push )
-# pragma warning( disable : 4996 )
+ // On Windows getenv throws a warning as there is no input validation,
+ // since the key is hardcoded, this should not be an issue.
+# pragma warning( push )
+# pragma warning( disable : 4996 )
# endif
- const auto bazelOutputFilePtr = std::getenv( "XML_OUTPUT_FILE" );
+ const auto bazelOutputFilePtr = std::getenv( "XML_OUTPUT_FILE" );
# if defined( _MSC_VER )
# pragma warning( pop )
# endif
- if ( bazelOutputFilePtr != nullptr ) {
- m_data.reporterSpecifications.push_back(
- { "junit", std::string( bazelOutputFilePtr ), {}, {} } );
- }
-#endif
+ if ( bazelOutputFilePtr != nullptr ) {
+ m_data.reporterSpecifications.push_back(
+ { "junit", std::string( bazelOutputFilePtr ), {}, {} } );
+ }
+ }
// We now fixup the reporter specs to handle default output spec,
@@ -1180,6 +1181,22 @@ namespace Catch {
+
+namespace Catch {
+
+ RegistrarForTagAliases::RegistrarForTagAliases(char const* alias, char const* tag, SourceLineInfo const& lineInfo) {
+ CATCH_TRY {
+ getMutableRegistryHub().registerTagAlias(alias, tag, lineInfo);
+ } CATCH_CATCH_ALL {
+ // Do not throw when constructing global objects, instead register the exception to be processed later
+ getMutableRegistryHub().registerStartupException();
+ }
+ }
+
+}
+
+
+
#include
#include
#include
@@ -1873,7 +1890,7 @@ namespace Catch {
}
Version const& libraryVersion() {
- static Version version( 3, 0, 1, "", 0 );
+ static Version version( 3, 1, 0, "", 0 );
return version;
}
@@ -1882,27 +1899,6 @@ namespace Catch {
-
-std::uint32_t Catch::Generators::Detail::getSeed() { return sharedRng()(); }
-
-
-/** \file
- * This is a special TU that combines what would otherwise be a very
- * small generator-related TUs into one bigger TU.
- *
- * The reason for this is compilation performance improvements by
- * avoiding reparsing headers for many small TUs, instead having this
- * one TU include bit more, but having it all parsed only once.
- *
- * To avoid heavy-tail problem with compilation times, each "subpart"
- * of Catch2 has its own combined TU like this.
- */
-
-////////////////////////////////////////////////////
-// vvv formerly catch_generator_exception.cpp vvv //
-////////////////////////////////////////////////////
-
-
namespace Catch {
const char* GeneratorException::what() const noexcept {
@@ -1912,9 +1908,6 @@ namespace Catch {
} // end namespace Catch
-///////////////////////////////////////////
-// vvv formerly catch_generators.cpp vvv //
-///////////////////////////////////////////
namespace Catch {
@@ -1941,81 +1934,31 @@ namespace Detail {
} // namespace Catch
-/** \file
- * This is a special TU that combines what would otherwise be a very
- * small interfaces-related TUs into one bigger TU.
- *
- * The reason for this is compilation performance improvements by
- * avoiding reparsing headers for many small TUs, instead having this
- * one TU include bit more, but having it all parsed only once.
- *
- * To avoid heavy-tail problem with compilation times, each "subpart"
- * of Catch2 has its own combined TU like this.
- */
-
-///////////////////////////////////////////////////
-// vvv formerly catch_interfaces_capture.cpp vvv //
-///////////////////////////////////////////////////
-
-
-namespace Catch {
- IResultCapture::~IResultCapture() = default;
-}
-
-
-//////////////////////////////////////////////////
-// vvv formerly catch_interfaces_config.cpp vvv //
-//////////////////////////////////////////////////
-
-
-namespace Catch {
- IConfig::~IConfig() = default;
-}
-
-/////////////////////////////////////////////////////
-// vvv formerly catch_interfaces_exception.cpp vvv //
-/////////////////////////////////////////////////////
-namespace Catch {
- IExceptionTranslator::~IExceptionTranslator() = default;
- IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() = default;
-}
+std::uint32_t Catch::Generators::Detail::getSeed() { return sharedRng()(); }
-////////////////////////////////////////////////////////
-// vvv formerly catch_interfaces_registry_hub.cpp vvv //
-////////////////////////////////////////////////////////
namespace Catch {
- IRegistryHub::~IRegistryHub() = default;
- IMutableRegistryHub::~IMutableRegistryHub() = default;
+ IResultCapture::~IResultCapture() = default;
}
-////////////////////////////////////////////////////
-// vvv formerly catch_interfaces_testcase.cpp vvv //
-////////////////////////////////////////////////////
namespace Catch {
- ITestInvoker::~ITestInvoker() = default;
- ITestCaseRegistry::~ITestCaseRegistry() = default;
+ IConfig::~IConfig() = default;
}
-namespace Catch {
- IReporterRegistry::~IReporterRegistry() = default;
-}
-
-
namespace Catch {
- IReporterFactory::~IReporterFactory() = default;
- EventListenerFactory::~EventListenerFactory() = default;
+ IExceptionTranslator::~IExceptionTranslator() = default;
+ IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() = default;
}
@@ -2046,6 +1989,14 @@ namespace Catch {
+
+namespace Catch {
+ IRegistryHub::~IRegistryHub() = default;
+ IMutableRegistryHub::~IMutableRegistryHub() = default;
+}
+
+
+
#include
#include
#include
@@ -2134,6 +2085,29 @@ namespace Catch {
+
+namespace Catch {
+ IReporterFactory::~IReporterFactory() = default;
+ EventListenerFactory::~EventListenerFactory() = default;
+}
+
+
+
+
+namespace Catch {
+ IReporterRegistry::~IReporterRegistry() = default;
+}
+
+
+
+
+namespace Catch {
+ ITestInvoker::~ITestInvoker() = default;
+ ITestCaseRegistry::~ITestCaseRegistry() = default;
+}
+
+
+
namespace Catch {
AssertionHandler::AssertionHandler
@@ -2672,248 +2646,33 @@ namespace Catch {
} // namespace Catch
-/** \file
- * This is a special TU that combines what would otherwise be a very
- * small top-level TUs into one bigger TU.
- *
- * The reason for this is compilation performance improvements by
- * avoiding reparsing headers for many small TUs, instead having this
- * one TU include bit more, but having it all parsed only once.
- *
- * To avoid heavy-tail problem with compilation times, each "subpart"
- * of Catch2 has its own combined TU like this.
- */
-
-////////////////////////////////////////////////////////
-// vvv formerly catch_tag_alias_autoregistrar.cpp vvv //
-////////////////////////////////////////////////////////
+#include
+#include
namespace Catch {
- RegistrarForTagAliases::RegistrarForTagAliases(char const* alias, char const* tag, SourceLineInfo const& lineInfo) {
- CATCH_TRY {
- getMutableRegistryHub().registerTagAlias(alias, tag, lineInfo);
- } CATCH_CATCH_ALL {
- // Do not throw when constructing global objects, instead register the exception to be processed later
- getMutableRegistryHub().registerStartupException();
- }
- }
-
-}
-
+ Clara::Parser makeCommandLineParser( ConfigData& config ) {
-//////////////////////////////////////////
-// vvv formerly catch_polyfills.cpp vvv //
-//////////////////////////////////////////
+ using namespace Clara;
-#include
+ auto const setWarning = [&]( std::string const& warning ) {
+ if ( warning == "NoAssertions" ) {
+ config.warnings = static_cast(config.warnings | WarnAbout::NoAssertions);
+ return ParserResult::ok( ParseResultType::Matched );
+ } else if ( warning == "UnmatchedTestSpec" ) {
+ config.warnings = static_cast(config.warnings | WarnAbout::UnmatchedTestSpec);
+ return ParserResult::ok( ParseResultType::Matched );
+ }
-namespace Catch {
-
-#if !defined(CATCH_CONFIG_POLYFILL_ISNAN)
- bool isnan(float f) {
- return std::isnan(f);
- }
- bool isnan(double d) {
- return std::isnan(d);
- }
-#else
- // For now we only use this for embarcadero
- bool isnan(float f) {
- return std::_isnan(f);
- }
- bool isnan(double d) {
- return std::_isnan(d);
- }
-#endif
-
-} // end namespace Catch
-
-
-////////////////////////////////////////////////////
-// vvv formerly catch_uncaught_exceptions.cpp vvv //
-////////////////////////////////////////////////////
-
-
-#include
-
-namespace Catch {
- bool uncaught_exceptions() {
-#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
- return false;
-#elif defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
- return std::uncaught_exceptions() > 0;
-#else
- return std::uncaught_exception();
-#endif
- }
-} // end namespace Catch
-
-
-////////////////////////////////////////////
-// vvv formerly catch_errno_guard.cpp vvv //
-////////////////////////////////////////////
-
-#include
-
-namespace Catch {
- ErrnoGuard::ErrnoGuard():m_oldErrno(errno){}
- ErrnoGuard::~ErrnoGuard() { errno = m_oldErrno; }
-}
-
-
-///////////////////////////////////////////
-// vvv formerly catch_decomposer.cpp vvv //
-///////////////////////////////////////////
-
-namespace Catch {
-
- ITransientExpression::~ITransientExpression() = default;
-
- void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ) {
- if( lhs.size() + rhs.size() < 40 &&
- lhs.find('\n') == std::string::npos &&
- rhs.find('\n') == std::string::npos )
- os << lhs << ' ' << op << ' ' << rhs;
- else
- os << lhs << '\n' << op << '\n' << rhs;
- }
-}
-
-
-///////////////////////////////////////////////////////////
-// vvv formerly catch_startup_exception_registry.cpp vvv //
-///////////////////////////////////////////////////////////
-
-namespace Catch {
-#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
- void StartupExceptionRegistry::add( std::exception_ptr const& exception ) noexcept {
- CATCH_TRY {
- m_exceptions.push_back(exception);
- } CATCH_CATCH_ALL {
- // If we run out of memory during start-up there's really not a lot more we can do about it
- std::terminate();
- }
- }
-
- std::vector const& StartupExceptionRegistry::getExceptions() const noexcept {
- return m_exceptions;
- }
-#endif
-
-} // end namespace Catch
-
-
-//////////////////////////////////////////////
-// vvv formerly catch_leak_detector.cpp vvv //
-//////////////////////////////////////////////
-
-
-#ifdef CATCH_CONFIG_WINDOWS_CRTDBG
-#include
-
-namespace Catch {
-
- LeakDetector::LeakDetector() {
- int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
- flag |= _CRTDBG_LEAK_CHECK_DF;
- flag |= _CRTDBG_ALLOC_MEM_DF;
- _CrtSetDbgFlag(flag);
- _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
- _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
- // Change this to leaking allocation's number to break there
- _CrtSetBreakAlloc(-1);
- }
-}
-
-#else // ^^ Windows crt debug heap enabled // Windows crt debug heap disabled vv
-
- Catch::LeakDetector::LeakDetector() {}
-
-#endif // CATCH_CONFIG_WINDOWS_CRTDBG
-
-Catch::LeakDetector::~LeakDetector() {
- Catch::cleanUp();
-}
-
-
-/////////////////////////////////////////////
-// vvv formerly catch_message_info.cpp vvv //
-/////////////////////////////////////////////
-
-
-namespace Catch {
-
- MessageInfo::MessageInfo( StringRef _macroName,
- SourceLineInfo const& _lineInfo,
- ResultWas::OfType _type )
- : macroName( _macroName ),
- lineInfo( _lineInfo ),
- type( _type ),
- sequence( ++globalCount )
- {}
-
- // This may need protecting if threading support is added
- unsigned int MessageInfo::globalCount = 0;
-
-} // end namespace Catch
-
-
-
-
-//////////////////////////////////////////
-// vvv formerly catch_lazy_expr.cpp vvv //
-//////////////////////////////////////////
-
-namespace Catch {
-
- auto operator << (std::ostream& os, LazyExpression const& lazyExpr) -> std::ostream& {
- if (lazyExpr.m_isNegated)
- os << '!';
-
- if (lazyExpr) {
- if (lazyExpr.m_isNegated && lazyExpr.m_transientExpression->isBinaryExpression())
- os << '(' << *lazyExpr.m_transientExpression << ')';
- else
- os << *lazyExpr.m_transientExpression;
- } else {
- os << "{** error - unchecked empty expression requested **}";
- }
- return os;
- }
-
-} // namespace Catch
-
-
-
-
-#include
-#include
-
-namespace Catch {
-
- Clara::Parser makeCommandLineParser( ConfigData& config ) {
-
- using namespace Clara;
-
- auto const setWarning = [&]( std::string const& warning ) {
- if ( warning == "NoAssertions" ) {
- config.warnings = static_cast(config.warnings | WarnAbout::NoAssertions);
- return ParserResult::ok( ParseResultType::Matched );
- } else if ( warning == "UnmatchedTestSpec" ) {
- config.warnings = static_cast(config.warnings | WarnAbout::UnmatchedTestSpec);
- return ParserResult::ok( ParseResultType::Matched );
- }
-
- return ParserResult ::runtimeError(
- "Unrecognised warning option: '" + warning + '\'' );
- };
- auto const loadTestNamesFromFile = [&]( std::string const& filename ) {
- std::ifstream f( filename.c_str() );
- if( !f.is_open() )
- return ParserResult::runtimeError( "Unable to load input file: '" + filename + '\'' );
+ return ParserResult ::runtimeError(
+ "Unrecognised warning option: '" + warning + '\'' );
+ };
+ auto const loadTestNamesFromFile = [&]( std::string const& filename ) {
+ std::ifstream f( filename.c_str() );
+ if( !f.is_open() )
+ return ParserResult::runtimeError( "Unable to load input file: '" + filename + '\'' );
std::string line;
while( std::getline( f, line ) ) {
@@ -3425,25 +3184,22 @@ namespace Catch {
Detail::unique_ptr makeColourImpl( ColourMode implSelection,
IStream* stream ) {
- if ( implSelection == ColourMode::None ) {
- return Detail::make_unique( stream );
- }
- if ( implSelection == ColourMode::ANSI ) {
- return Detail::make_unique( stream );
- }
#if defined( CATCH_CONFIG_COLOUR_WIN32 )
if ( implSelection == ColourMode::Win32 ) {
return Detail::make_unique( stream );
}
#endif
+ if ( implSelection == ColourMode::ANSI ) {
+ return Detail::make_unique( stream );
+ }
+ if ( implSelection == ColourMode::None ) {
+ return Detail::make_unique( stream );
+ }
- // todo: check win32 eligibility under ifdef, otherwise ansi
if ( implSelection == ColourMode::PlatformDefault) {
-#if defined (CATCH_CONFIG_COLOUR_WIN32)
+#if defined( CATCH_CONFIG_COLOUR_WIN32 )
if ( Win32ColourImpl::useImplementationForStream( *stream ) ) {
return Detail::make_unique( stream );
- } else {
- return Detail::make_unique( stream );
}
#endif
if ( ANSIColourImpl::useImplementationForStream( *stream ) ) {
@@ -3679,6 +3435,23 @@ namespace Catch {
+
+namespace Catch {
+
+ ITransientExpression::~ITransientExpression() = default;
+
+ void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ) {
+ if( lhs.size() + rhs.size() < 40 &&
+ lhs.find('\n') == std::string::npos &&
+ rhs.find('\n') == std::string::npos )
+ os << lhs << ' ' << op << ' ' << rhs;
+ else
+ os << lhs << '\n' << op << '\n' << rhs;
+ }
+}
+
+
+
#include
@@ -3779,6 +3552,16 @@ namespace Catch {
+
+#include
+
+namespace Catch {
+ ErrnoGuard::ErrnoGuard():m_oldErrno(errno){}
+ ErrnoGuard::~ErrnoGuard() { errno = m_oldErrno; }
+}
+
+
+
namespace Catch {
ExceptionTranslatorRegistry::~ExceptionTranslatorRegistry() {
@@ -4256,36 +4039,88 @@ namespace Detail {
-
namespace Catch {
- namespace {
- void listTests(IEventListener& reporter, IConfig const& config) {
- auto const& testSpec = config.testSpec();
- auto matchedTestCases = filterTests(getAllTestCasesSorted(config), testSpec, config);
- reporter.listTests(matchedTestCases);
+ auto operator << (std::ostream& os, LazyExpression const& lazyExpr) -> std::ostream& {
+ if (lazyExpr.m_isNegated)
+ os << '!';
+
+ if (lazyExpr) {
+ if (lazyExpr.m_isNegated && lazyExpr.m_transientExpression->isBinaryExpression())
+ os << '(' << *lazyExpr.m_transientExpression << ')';
+ else
+ os << *lazyExpr.m_transientExpression;
+ } else {
+ os << "{** error - unchecked empty expression requested **}";
}
+ return os;
+ }
- void listTags(IEventListener& reporter, IConfig const& config) {
- auto const& testSpec = config.testSpec();
- std::vector matchedTestCases = filterTests(getAllTestCasesSorted(config), testSpec, config);
+} // namespace Catch
- std::map tagCounts;
- for (auto const& testCase : matchedTestCases) {
- for (auto const& tagName : testCase.getTestCaseInfo().tags) {
- auto it = tagCounts.find(tagName.original);
- if (it == tagCounts.end())
- it = tagCounts.insert(std::make_pair(tagName.original, TagInfo())).first;
- it->second.add(tagName.original);
- }
- }
- std::vector infos; infos.reserve(tagCounts.size());
- for (auto& tagc : tagCounts) {
- infos.push_back(CATCH_MOVE(tagc.second));
- }
- reporter.listTags(infos);
+
+#ifdef CATCH_CONFIG_WINDOWS_CRTDBG
+#include
+
+namespace Catch {
+
+ LeakDetector::LeakDetector() {
+ int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
+ flag |= _CRTDBG_LEAK_CHECK_DF;
+ flag |= _CRTDBG_ALLOC_MEM_DF;
+ _CrtSetDbgFlag(flag);
+ _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
+ _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
+ // Change this to leaking allocation's number to break there
+ _CrtSetBreakAlloc(-1);
+ }
+}
+
+#else // ^^ Windows crt debug heap enabled // Windows crt debug heap disabled vv
+
+ Catch::LeakDetector::LeakDetector() {}
+
+#endif // CATCH_CONFIG_WINDOWS_CRTDBG
+
+Catch::LeakDetector::~LeakDetector() {
+ Catch::cleanUp();
+}
+
+
+
+
+
+namespace Catch {
+ namespace {
+
+ void listTests(IEventListener& reporter, IConfig const& config) {
+ auto const& testSpec = config.testSpec();
+ auto matchedTestCases = filterTests(getAllTestCasesSorted(config), testSpec, config);
+ reporter.listTests(matchedTestCases);
+ }
+
+ void listTags(IEventListener& reporter, IConfig const& config) {
+ auto const& testSpec = config.testSpec();
+ std::vector matchedTestCases = filterTests(getAllTestCasesSorted(config), testSpec, config);
+
+ std::map tagCounts;
+ for (auto const& testCase : matchedTestCases) {
+ for (auto const& tagName : testCase.getTestCaseInfo().tags) {
+ auto it = tagCounts.find(tagName.original);
+ if (it == tagCounts.end())
+ it = tagCounts.insert(std::make_pair(tagName.original, TagInfo())).first;
+ it->second.add(tagName.original);
+ }
+ }
+
+ std::vector infos; infos.reserve(tagCounts.size());
+ for (auto& tagc : tagCounts) {
+ infos.push_back(CATCH_MOVE(tagc.second));
+ }
+
+ reporter.listTags(infos);
}
void listReporters(IEventListener& reporter) {
@@ -4390,6 +4225,25 @@ int main (int argc, char * argv[]) {
+
+namespace Catch {
+
+ MessageInfo::MessageInfo( StringRef _macroName,
+ SourceLineInfo const& _lineInfo,
+ ResultWas::OfType _type )
+ : macroName( _macroName ),
+ lineInfo( _lineInfo ),
+ type( _type ),
+ sequence( ++globalCount )
+ {}
+
+ // This may need protecting if threading support is added
+ unsigned int MessageInfo::globalCount = 0;
+
+} // end namespace Catch
+
+
+
#include
#include
#include
@@ -4528,6 +4382,32 @@ namespace Catch {
+
+#include
+
+namespace Catch {
+
+#if !defined(CATCH_CONFIG_POLYFILL_ISNAN)
+ bool isnan(float f) {
+ return std::isnan(f);
+ }
+ bool isnan(double d) {
+ return std::isnan(d);
+ }
+#else
+ // For now we only use this for embarcadero
+ bool isnan(float f) {
+ return std::_isnan(f);
+ }
+ bool isnan(double d) {
+ return std::_isnan(d);
+ }
+#endif
+
+} // end namespace Catch
+
+
+
namespace Catch {
namespace {
@@ -4784,7 +4664,7 @@ namespace Catch {
return {};
}
- auto ret = kvPairs.emplace( kv.key, kv.value );
+ auto ret = kvPairs.emplace( std::string(kv.key), std::string(kv.value) );
if ( !ret.second ) {
// Duplicated key. We might want to handle this differently,
// e.g. by overwriting the existing value?
@@ -5387,6 +5267,11 @@ namespace Catch {
// before running the tests themselves, or the binary can crash
// without failed test being reported.
FatalConditionHandlerGuard _(&m_fatalConditionhandler);
+ // We keep having issue where some compilers warn about an unused
+ // variable, even though the type has non-trivial constructor and
+ // destructor. This is annoying and ugly, but it makes them stfu.
+ (void)_;
+
m_activeTestCase->invoke();
}
@@ -5618,6 +5503,27 @@ namespace Catch {
+namespace Catch {
+#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
+ void StartupExceptionRegistry::add( std::exception_ptr const& exception ) noexcept {
+ CATCH_TRY {
+ m_exceptions.push_back(exception);
+ } CATCH_CATCH_ALL {
+ // If we run out of memory during start-up there's really not a lot more we can do about it
+ std::terminate();
+ }
+ }
+
+ std::vector const& StartupExceptionRegistry::getExceptions() const noexcept {
+ return m_exceptions;
+ }
+#endif
+
+} // end namespace Catch
+
+
+
+
#include
@@ -6792,6 +6698,23 @@ namespace Catch {
+
+#include
+
+namespace Catch {
+ bool uncaught_exceptions() {
+#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
+ return false;
+#elif defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
+ return std::uncaught_exceptions() > 0;
+#else
+ return std::uncaught_exception();
+#endif
+ }
+} // end namespace Catch
+
+
+
namespace Catch {
WildcardPattern::WildcardPattern( std::string const& pattern,
@@ -7171,6 +7094,72 @@ namespace {
+
+
+namespace Catch {
+namespace Matchers {
+
+ std::string MatcherUntypedBase::toString() const {
+ if (m_cachedToString.empty()) {
+ m_cachedToString = describe();
+ }
+ return m_cachedToString;
+ }
+
+ MatcherUntypedBase::~MatcherUntypedBase() = default;
+
+} // namespace Matchers
+} // namespace Catch
+
+
+
+
+namespace Catch {
+namespace Matchers {
+
+ std::string IsEmptyMatcher::describe() const {
+ return "is empty";
+ }
+
+ std::string HasSizeMatcher::describe() const {
+ ReusableStringStream sstr;
+ sstr << "has size == " << m_target_size;
+ return sstr.str();
+ }
+
+ IsEmptyMatcher IsEmpty() {
+ return {};
+ }
+
+ HasSizeMatcher SizeIs(std::size_t sz) {
+ return HasSizeMatcher{ sz };
+ }
+
+} // end namespace Matchers
+} // end namespace Catch
+
+
+
+namespace Catch {
+namespace Matchers {
+
+bool ExceptionMessageMatcher::match(std::exception const& ex) const {
+ return ex.what() == m_message;
+}
+
+std::string ExceptionMessageMatcher::describe() const {
+ return "exception message matches \"" + m_message + '"';
+}
+
+ExceptionMessageMatcher Message(std::string const& message) {
+ return ExceptionMessageMatcher(message);
+}
+
+} // namespace Matchers
+} // namespace Catch
+
+
+
#include
#include
#include
@@ -7389,6 +7378,35 @@ WithinRelMatcher WithinRel(float target) {
+
+std::string Catch::Matchers::Detail::finalizeDescription(const std::string& desc) {
+ if (desc.empty()) {
+ return "matches undescribed predicate";
+ } else {
+ return "matches predicate: \"" + desc + '"';
+ }
+}
+
+
+
+namespace Catch {
+ namespace Matchers {
+ std::string AllTrueMatcher::describe() const { return "contains only true"; }
+
+ AllTrueMatcher AllTrue() { return AllTrueMatcher{}; }
+
+ std::string NoneTrueMatcher::describe() const { return "contains no true"; }
+
+ NoneTrueMatcher NoneTrue() { return NoneTrueMatcher{}; }
+
+ std::string AnyTrueMatcher::describe() const { return "contains at least one true"; }
+
+ AnyTrueMatcher AnyTrue() { return AnyTrueMatcher{}; }
+ } // namespace Matchers
+} // namespace Catch
+
+
+
#include
namespace Catch {
@@ -7528,21 +7546,7 @@ namespace Matchers {
} // namespace Catch
-/** \file
- * This is a special TU that combines what would otherwise be a very
- * small matcher-related TUs into one bigger TU.
- *
- * The reason for this is compilation performance improvements by
- * avoiding reparsing headers for many small TUs, instead having this
- * one TU include bit more, but having it all parsed only once.
- *
- * To avoid heavy-tail problem with compilation times, each "subpart"
- * of Catch2 has its own combined TU like this.
- */
-//////////////////////////////////////////////
-// vvv formerly catch_matchers_impl.cpp vvv //
-//////////////////////////////////////////////
namespace Catch {
@@ -7558,385 +7562,32 @@ namespace Catch {
} // namespace Catch
-//////////////////////////////////////////////////////////////
-// vvv formerly catch_matchers_container_properties.cpp vvv //
-//////////////////////////////////////////////////////////////
+
+#include
namespace Catch {
-namespace Matchers {
- std::string IsEmptyMatcher::describe() const {
- return "is empty";
+ AutomakeReporter::~AutomakeReporter() {}
+
+ void AutomakeReporter::testCaseEnded(TestCaseStats const& _testCaseStats) {
+ // Possible values to emit are PASS, XFAIL, SKIP, FAIL, XPASS and ERROR.
+ m_stream << ":test-result: ";
+ if (_testCaseStats.totals.assertions.allPassed()) {
+ m_stream << "PASS";
+ } else if (_testCaseStats.totals.assertions.allOk()) {
+ m_stream << "XFAIL";
+ } else {
+ m_stream << "FAIL";
+ }
+ m_stream << ' ' << _testCaseStats.testInfo->name << '\n';
+ StreamingReporterBase::testCaseEnded(_testCaseStats);
}
- std::string HasSizeMatcher::describe() const {
- ReusableStringStream sstr;
- sstr << "has size == " << m_target_size;
- return sstr.str();
- }
-
- IsEmptyMatcher IsEmpty() {
- return {};
- }
-
- HasSizeMatcher SizeIs(std::size_t sz) {
- return HasSizeMatcher{ sz };
- }
-
-} // end namespace Matchers
-} // end namespace Catch
-
-
-
-/////////////////////////////////////////
-// vvv formerly catch_matchers.cpp vvv //
-/////////////////////////////////////////
-
-
-namespace Catch {
-namespace Matchers {
-
- std::string MatcherUntypedBase::toString() const {
- if (m_cachedToString.empty()) {
- m_cachedToString = describe();
- }
- return m_cachedToString;
- }
-
- MatcherUntypedBase::~MatcherUntypedBase() = default;
-
-} // namespace Matchers
-} // namespace Catch
-
-
-
-///////////////////////////////////////////////////
-// vvv formerly catch_matchers_predicate.cpp vvv //
-///////////////////////////////////////////////////
-
-std::string Catch::Matchers::Detail::finalizeDescription(const std::string& desc) {
- if (desc.empty()) {
- return "matches undescribed predicate";
- } else {
- return "matches predicate: \"" + desc + '"';
- }
-}
-
-
-
-
-
-///////////////////////////////////////////////////
-// vvv formerly catch_matchers_exception.cpp vvv //
-///////////////////////////////////////////////////
-
-namespace Catch {
-namespace Matchers {
-
-bool ExceptionMessageMatcher::match(std::exception const& ex) const {
- return ex.what() == m_message;
-}
-
-std::string ExceptionMessageMatcher::describe() const {
- return "exception message matches \"" + m_message + '"';
-}
-
-ExceptionMessageMatcher Message(std::string const& message) {
- return ExceptionMessageMatcher(message);
-}
-
-} // namespace Matchers
-} // namespace Catch
-
-
-
-#include
-
-namespace Catch {
-
- AutomakeReporter::~AutomakeReporter() {}
-
- void AutomakeReporter::testCaseEnded(TestCaseStats const& _testCaseStats) {
- // Possible values to emit are PASS, XFAIL, SKIP, FAIL, XPASS and ERROR.
- m_stream << ":test-result: ";
- if (_testCaseStats.totals.assertions.allPassed()) {
- m_stream << "PASS";
- } else if (_testCaseStats.totals.assertions.allOk()) {
- m_stream << "XFAIL";
- } else {
- m_stream << "FAIL";
- }
- m_stream << ' ' << _testCaseStats.testInfo->name << '\n';
- StreamingReporterBase::testCaseEnded(_testCaseStats);
- }
-
- void AutomakeReporter::skipTest(TestCaseInfo const& testInfo) {
- m_stream << ":test-result: SKIP " << testInfo.name << '\n';
- }
-
-} // end namespace Catch
-
-
-/** \file
- * This is a special TU that combines what would otherwise be a very
- * small reporter-related TUs into one bigger TU.
- *
- * The reason for this is compilation performance improvements by
- * avoiding reparsing headers for many small TUs, instead having this
- * one TU include bit more, but having it all parsed only once.
- *
- * To avoid heavy-tail problem with compilation times, each "subpart"
- * of Catch2 has its own combined TU like this.
- */
-
-
-#include
-#include
-#include
-#include
-#include
-
-namespace Catch {
-
- namespace {
- void listTestNamesOnly(std::ostream& out,
- std::vector const& tests) {
- for (auto const& test : tests) {
- auto const& testCaseInfo = test.getTestCaseInfo();
-
- if (startsWith(testCaseInfo.name, '#')) {
- out << '"' << testCaseInfo.name << '"';
- } else {
- out << testCaseInfo.name;
- }
-
- out << '\n';
- }
- out << std::flush;
- }
- } // end unnamed namespace
-
-
- // Because formatting using c++ streams is stateful, drop down to C is
- // required Alternatively we could use stringstream, but its performance
- // is... not good.
- std::string getFormattedDuration( double duration ) {
- // Max exponent + 1 is required to represent the whole part
- // + 1 for decimal point
- // + 3 for the 3 decimal places
- // + 1 for null terminator
- const std::size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1;
- char buffer[maxDoubleSize];
-
- // Save previous errno, to prevent sprintf from overwriting it
- ErrnoGuard guard;
-#ifdef _MSC_VER
- size_t printedLength = static_cast(
- sprintf_s( buffer, "%.3f", duration ) );
-#else
- size_t printedLength = static_cast(
- std::snprintf( buffer, maxDoubleSize, "%.3f", duration ) );
-#endif
- return std::string( buffer, printedLength );
- }
-
- bool shouldShowDuration( IConfig const& config, double duration ) {
- if ( config.showDurations() == ShowDurations::Always ) {
- return true;
- }
- if ( config.showDurations() == ShowDurations::Never ) {
- return false;
- }
- const double min = config.minDuration();
- return min >= 0 && duration >= min;
- }
-
- std::string serializeFilters( std::vector const& filters ) {
- // We add a ' ' separator between each filter
- size_t serialized_size = filters.size() - 1;
- for (auto const& filter : filters) {
- serialized_size += filter.size();
- }
-
- std::string serialized;
- serialized.reserve(serialized_size);
- bool first = true;
-
- for (auto const& filter : filters) {
- if (!first) {
- serialized.push_back(' ');
- }
- first = false;
- serialized.append(filter);
- }
-
- return serialized;
- }
-
- std::ostream& operator<<( std::ostream& out, lineOfChars value ) {
- for ( size_t idx = 0; idx < CATCH_CONFIG_CONSOLE_WIDTH - 1; ++idx ) {
- out.put( value.c );
- }
- return out;
- }
-
- void
- defaultListReporters( std::ostream& out,
- std::vector const& descriptions,
- Verbosity verbosity ) {
- out << "Available reporters:\n";
- const auto maxNameLen =
- std::max_element( descriptions.begin(),
- descriptions.end(),
- []( ReporterDescription const& lhs,
- ReporterDescription const& rhs ) {
- return lhs.name.size() < rhs.name.size();
- } )
- ->name.size();
-
- for ( auto const& desc : descriptions ) {
- if ( verbosity == Verbosity::Quiet ) {
- out << TextFlow::Column( desc.name )
- .indent( 2 )
- .width( 5 + maxNameLen )
- << '\n';
- } else {
- out << TextFlow::Column( desc.name + ':' )
- .indent( 2 )
- .width( 5 + maxNameLen ) +
- TextFlow::Column( desc.description )
- .initialIndent( 0 )
- .indent( 2 )
- .width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen - 8 )
- << '\n';
- }
- }
- out << '\n' << std::flush;
- }
-
- void defaultListListeners( std::ostream& out,
- std::vector const& descriptions ) {
- const auto maxNameLen =
- std::max_element( descriptions.begin(),
- descriptions.end(),
- []( ListenerDescription const& lhs,
- ListenerDescription const& rhs ) {
- return lhs.name.size() < rhs.name.size();
- } )
- ->name.size();
-
- out << "Registered listeners:\n";
- for ( auto const& desc : descriptions ) {
- out << TextFlow::Column( static_cast( desc.name ) +
- ':' )
- .indent( 2 )
- .width( maxNameLen + 5 ) +
- TextFlow::Column( desc.description )
- .initialIndent( 0 )
- .indent( 2 )
- .width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen - 8 )
- << '\n';
- }
-
- out << '\n' << std::flush;
- }
-
- void defaultListTags( std::ostream& out,
- std::vector const& tags,
- bool isFiltered ) {
- if ( isFiltered ) {
- out << "Tags for matching test cases:\n";
- } else {
- out << "All available tags:\n";
- }
-
- for ( auto const& tagCount : tags ) {
- ReusableStringStream rss;
- rss << " " << std::setw( 2 ) << tagCount.count << " ";
- auto str = rss.str();
- auto wrapper = TextFlow::Column( tagCount.all() )
- .initialIndent( 0 )
- .indent( str.size() )
- .width( CATCH_CONFIG_CONSOLE_WIDTH - 10 );
- out << str << wrapper << '\n';
- }
- out << pluralise(tags.size(), "tag"_sr) << "\n\n" << std::flush;
- }
-
- void defaultListTests(std::ostream& out, ColourImpl* streamColour, std::vector const& tests, bool isFiltered, Verbosity verbosity) {
- // We special case this to provide the equivalent of old
- // `--list-test-names-only`, which could then be used by the
- // `--input-file` option.
- if (verbosity == Verbosity::Quiet) {
- listTestNamesOnly(out, tests);
- return;
- }
-
- if (isFiltered) {
- out << "Matching test cases:\n";
- } else {
- out << "All available test cases:\n";
- }
-
- for (auto const& test : tests) {
- auto const& testCaseInfo = test.getTestCaseInfo();
- Colour::Code colour = testCaseInfo.isHidden()
- ? Colour::SecondaryText
- : Colour::None;
- auto colourGuard = streamColour->guardColour( colour ).engage( out );
-
- out << TextFlow::Column(testCaseInfo.name).indent(2) << '\n';
- if (verbosity >= Verbosity::High) {
- out << TextFlow::Column(Catch::Detail::stringify(testCaseInfo.lineInfo)).indent(4) << '\n';
- }
- if (!testCaseInfo.tags.empty() &&
- verbosity > Verbosity::Quiet) {
- out << TextFlow::Column(testCaseInfo.tagsAsString()).indent(6) << '\n';
- }
- }
-
- if (isFiltered) {
- out << pluralise(tests.size(), "matching test case"_sr);
- } else {
- out << pluralise(tests.size(), "test case"_sr);
- }
- out << "\n\n" << std::flush;
+ void AutomakeReporter::skipTest(TestCaseInfo const& testInfo) {
+ m_stream << ":test-result: SKIP " << testInfo.name << '\n';
}
-} // namespace Catch
-
-
-
-namespace Catch {
-
- void EventListenerBase::fatalErrorEncountered( StringRef ) {}
-
- void EventListenerBase::benchmarkPreparing( StringRef ) {}
- void EventListenerBase::benchmarkStarting( BenchmarkInfo const& ) {}
- void EventListenerBase::benchmarkEnded( BenchmarkStats<> const& ) {}
- void EventListenerBase::benchmarkFailed( StringRef ) {}
-
- void EventListenerBase::assertionStarting( AssertionInfo const& ) {}
-
- void EventListenerBase::assertionEnded( AssertionStats const& ) {}
- void EventListenerBase::listReporters(
- std::vector const& ) {}
- void EventListenerBase::listListeners(
- std::vector const& ) {}
- void EventListenerBase::listTests( std::vector const& ) {}
- void EventListenerBase::listTags( std::vector const& ) {}
- void EventListenerBase::noMatchingTestCases( StringRef ) {}
- void EventListenerBase::reportInvalidTestSpec( StringRef ) {}
- void EventListenerBase::testRunStarting( TestRunInfo const& ) {}
- void EventListenerBase::testCaseStarting( TestCaseInfo const& ) {}
- void EventListenerBase::testCasePartialStarting(TestCaseInfo const&, uint64_t) {}
- void EventListenerBase::sectionStarting( SectionInfo const& ) {}
- void EventListenerBase::sectionEnded( SectionStats const& ) {}
- void EventListenerBase::testCasePartialEnded(TestCaseStats const&, uint64_t) {}
- void EventListenerBase::testCaseEnded( TestCaseStats const& ) {}
- void EventListenerBase::testRunEnded( TestRunStats const& ) {}
- void EventListenerBase::skipTest( TestCaseInfo const& ) {}
-} // namespace Catch
+} // end namespace Catch
@@ -8989,129 +8640,386 @@ namespace Catch {
} // namespace
- namespace Detail {
- AssertionOrBenchmarkResult::AssertionOrBenchmarkResult(
- AssertionStats const& assertion ):
- m_assertion( assertion ) {}
+ namespace Detail {
+ AssertionOrBenchmarkResult::AssertionOrBenchmarkResult(
+ AssertionStats const& assertion ):
+ m_assertion( assertion ) {}
+
+ AssertionOrBenchmarkResult::AssertionOrBenchmarkResult(
+ BenchmarkStats<> const& benchmark ):
+ m_benchmark( benchmark ) {}
+
+ bool AssertionOrBenchmarkResult::isAssertion() const {
+ return m_assertion.some();
+ }
+ bool AssertionOrBenchmarkResult::isBenchmark() const {
+ return m_benchmark.some();
+ }
+
+ AssertionStats const& AssertionOrBenchmarkResult::asAssertion() const {
+ assert(m_assertion.some());
+
+ return *m_assertion;
+ }
+ BenchmarkStats<> const& AssertionOrBenchmarkResult::asBenchmark() const {
+ assert(m_benchmark.some());
+
+ return *m_benchmark;
+ }
+
+ }
+
+ CumulativeReporterBase::~CumulativeReporterBase() = default;
+
+ void CumulativeReporterBase::benchmarkEnded(BenchmarkStats<> const& benchmarkStats) {
+ m_sectionStack.back()->assertionsAndBenchmarks.emplace_back(benchmarkStats);
+ }
+
+ void
+ CumulativeReporterBase::sectionStarting( SectionInfo const& sectionInfo ) {
+ SectionStats incompleteStats( sectionInfo, Counts(), 0, false );
+ SectionNode* node;
+ if ( m_sectionStack.empty() ) {
+ if ( !m_rootSection ) {
+ m_rootSection =
+ Detail::make_unique( incompleteStats );
+ }
+ node = m_rootSection.get();
+ } else {
+ SectionNode& parentNode = *m_sectionStack.back();
+ auto it = std::find_if( parentNode.childSections.begin(),
+ parentNode.childSections.end(),
+ BySectionInfo( sectionInfo ) );
+ if ( it == parentNode.childSections.end() ) {
+ auto newNode =
+ Detail::make_unique( incompleteStats );
+ node = newNode.get();
+ parentNode.childSections.push_back( CATCH_MOVE( newNode ) );
+ } else {
+ node = it->get();
+ }
+ }
+
+ m_deepestSection = node;
+ m_sectionStack.push_back( node );
+ }
+
+ void CumulativeReporterBase::assertionEnded(
+ AssertionStats const& assertionStats ) {
+ assert( !m_sectionStack.empty() );
+ // AssertionResult holds a pointer to a temporary DecomposedExpression,
+ // which getExpandedExpression() calls to build the expression string.
+ // Our section stack copy of the assertionResult will likely outlive the
+ // temporary, so it must be expanded or discarded now to avoid calling
+ // a destroyed object later.
+ if ( m_shouldStoreFailedAssertions &&
+ !assertionStats.assertionResult.isOk() ) {
+ static_cast(
+ assertionStats.assertionResult.getExpandedExpression() );
+ }
+ if ( m_shouldStoreSuccesfulAssertions &&
+ assertionStats.assertionResult.isOk() ) {
+ static_cast(
+ assertionStats.assertionResult.getExpandedExpression() );
+ }
+ SectionNode& sectionNode = *m_sectionStack.back();
+ sectionNode.assertionsAndBenchmarks.emplace_back( assertionStats );
+ }
+
+ void CumulativeReporterBase::sectionEnded( SectionStats const& sectionStats ) {
+ assert( !m_sectionStack.empty() );
+ SectionNode& node = *m_sectionStack.back();
+ node.stats = sectionStats;
+ m_sectionStack.pop_back();
+ }
+
+ void CumulativeReporterBase::testCaseEnded(
+ TestCaseStats const& testCaseStats ) {
+ auto node = Detail::make_unique( testCaseStats );
+ assert( m_sectionStack.size() == 0 );
+ node->children.push_back( CATCH_MOVE(m_rootSection) );
+ m_testCases.push_back( CATCH_MOVE(node) );
+
+ assert( m_deepestSection );
+ m_deepestSection->stdOut = testCaseStats.stdOut;
+ m_deepestSection->stdErr = testCaseStats.stdErr;
+ }
+
+
+ void CumulativeReporterBase::testRunEnded( TestRunStats const& testRunStats ) {
+ assert(!m_testRun && "CumulativeReporterBase assumes there can only be one test run");
+ m_testRun = Detail::make_unique( testRunStats );
+ m_testRun->children.swap( m_testCases );
+ testRunEndedCumulative();
+ }
+
+ bool CumulativeReporterBase::SectionNode::hasAnyAssertions() const {
+ return std::any_of(
+ assertionsAndBenchmarks.begin(),
+ assertionsAndBenchmarks.end(),
+ []( Detail::AssertionOrBenchmarkResult const& res ) {
+ return res.isAssertion();
+ } );
+ }
+
+} // end namespace Catch
+
+
+
+
+namespace Catch {
+
+ void EventListenerBase::fatalErrorEncountered( StringRef ) {}
+
+ void EventListenerBase::benchmarkPreparing( StringRef ) {}
+ void EventListenerBase::benchmarkStarting( BenchmarkInfo const& ) {}
+ void EventListenerBase::benchmarkEnded( BenchmarkStats<> const& ) {}
+ void EventListenerBase::benchmarkFailed( StringRef ) {}
+
+ void EventListenerBase::assertionStarting( AssertionInfo const& ) {}
+
+ void EventListenerBase::assertionEnded( AssertionStats const& ) {}
+ void EventListenerBase::listReporters(
+ std::vector const& ) {}
+ void EventListenerBase::listListeners(
+ std::vector const& ) {}
+ void EventListenerBase::listTests( std::vector const& ) {}
+ void EventListenerBase::listTags( std::vector const& ) {}
+ void EventListenerBase::noMatchingTestCases( StringRef ) {}
+ void EventListenerBase::reportInvalidTestSpec( StringRef ) {}
+ void EventListenerBase::testRunStarting( TestRunInfo const& ) {}
+ void EventListenerBase::testCaseStarting( TestCaseInfo const& ) {}
+ void EventListenerBase::testCasePartialStarting(TestCaseInfo const&, uint64_t) {}
+ void EventListenerBase::sectionStarting( SectionInfo const& ) {}
+ void EventListenerBase::sectionEnded( SectionStats const& ) {}
+ void EventListenerBase::testCasePartialEnded(TestCaseStats const&, uint64_t) {}
+ void EventListenerBase::testCaseEnded( TestCaseStats const& ) {}
+ void EventListenerBase::testRunEnded( TestRunStats const& ) {}
+ void EventListenerBase::skipTest( TestCaseInfo const& ) {}
+} // namespace Catch
+
+
+
+
+#include
+#include
+#include
+#include
+#include
+
+namespace Catch {
+
+ namespace {
+ void listTestNamesOnly(std::ostream& out,
+ std::vector const& tests) {
+ for (auto const& test : tests) {
+ auto const& testCaseInfo = test.getTestCaseInfo();
+
+ if (startsWith(testCaseInfo.name, '#')) {
+ out << '"' << testCaseInfo.name << '"';
+ } else {
+ out << testCaseInfo.name;
+ }
+
+ out << '\n';
+ }
+ out << std::flush;
+ }
+ } // end unnamed namespace
+
+
+ // Because formatting using c++ streams is stateful, drop down to C is
+ // required Alternatively we could use stringstream, but its performance
+ // is... not good.
+ std::string getFormattedDuration( double duration ) {
+ // Max exponent + 1 is required to represent the whole part
+ // + 1 for decimal point
+ // + 3 for the 3 decimal places
+ // + 1 for null terminator
+ const std::size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1;
+ char buffer[maxDoubleSize];
- AssertionOrBenchmarkResult::AssertionOrBenchmarkResult(
- BenchmarkStats<> const& benchmark ):
- m_benchmark( benchmark ) {}
+ // Save previous errno, to prevent sprintf from overwriting it
+ ErrnoGuard guard;
+#ifdef _MSC_VER
+ size_t printedLength = static_cast(
+ sprintf_s( buffer, "%.3f", duration ) );
+#else
+ size_t printedLength = static_cast(
+ std::snprintf( buffer, maxDoubleSize, "%.3f", duration ) );
+#endif
+ return std::string( buffer, printedLength );
+ }
- bool AssertionOrBenchmarkResult::isAssertion() const {
- return m_assertion.some();
+ bool shouldShowDuration( IConfig const& config, double duration ) {
+ if ( config.showDurations() == ShowDurations::Always ) {
+ return true;
}
- bool AssertionOrBenchmarkResult::isBenchmark() const {
- return m_benchmark.some();
+ if ( config.showDurations() == ShowDurations::Never ) {
+ return false;
}
+ const double min = config.minDuration();
+ return min >= 0 && duration >= min;
+ }
- AssertionStats const& AssertionOrBenchmarkResult::asAssertion() const {
- assert(m_assertion.some());
-
- return *m_assertion;
+ std::string serializeFilters( std::vector const& filters ) {
+ // We add a ' ' separator between each filter
+ size_t serialized_size = filters.size() - 1;
+ for (auto const& filter : filters) {
+ serialized_size += filter.size();
}
- BenchmarkStats<> const& AssertionOrBenchmarkResult::asBenchmark() const {
- assert(m_benchmark.some());
- return *m_benchmark;
+ std::string serialized;
+ serialized.reserve(serialized_size);
+ bool first = true;
+
+ for (auto const& filter : filters) {
+ if (!first) {
+ serialized.push_back(' ');
+ }
+ first = false;
+ serialized.append(filter);
}
+ return serialized;
}
- CumulativeReporterBase::~CumulativeReporterBase() = default;
-
- void CumulativeReporterBase::benchmarkEnded(BenchmarkStats<> const& benchmarkStats) {
- m_sectionStack.back()->assertionsAndBenchmarks.emplace_back(benchmarkStats);
+ std::ostream& operator<<( std::ostream& out, lineOfChars value ) {
+ for ( size_t idx = 0; idx < CATCH_CONFIG_CONSOLE_WIDTH - 1; ++idx ) {
+ out.put( value.c );
+ }
+ return out;
}
void
- CumulativeReporterBase::sectionStarting( SectionInfo const& sectionInfo ) {
- SectionStats incompleteStats( sectionInfo, Counts(), 0, false );
- SectionNode* node;
- if ( m_sectionStack.empty() ) {
- if ( !m_rootSection ) {
- m_rootSection =
- Detail::make_unique( incompleteStats );
- }
- node = m_rootSection.get();
- } else {
- SectionNode& parentNode = *m_sectionStack.back();
- auto it = std::find_if( parentNode.childSections.begin(),
- parentNode.childSections.end(),
- BySectionInfo( sectionInfo ) );
- if ( it == parentNode.childSections.end() ) {
- auto newNode =
- Detail::make_unique( incompleteStats );
- node = newNode.get();
- parentNode.childSections.push_back( CATCH_MOVE( newNode ) );
+ defaultListReporters( std::ostream& out,
+ std::vector const& descriptions,
+ Verbosity verbosity ) {
+ out << "Available reporters:\n";
+ const auto maxNameLen =
+ std::max_element( descriptions.begin(),
+ descriptions.end(),
+ []( ReporterDescription const& lhs,
+ ReporterDescription const& rhs ) {
+ return lhs.name.size() < rhs.name.size();
+ } )
+ ->name.size();
+
+ for ( auto const& desc : descriptions ) {
+ if ( verbosity == Verbosity::Quiet ) {
+ out << TextFlow::Column( desc.name )
+ .indent( 2 )
+ .width( 5 + maxNameLen )
+ << '\n';
} else {
- node = it->get();
+ out << TextFlow::Column( desc.name + ':' )
+ .indent( 2 )
+ .width( 5 + maxNameLen ) +
+ TextFlow::Column( desc.description )
+ .initialIndent( 0 )
+ .indent( 2 )
+ .width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen - 8 )
+ << '\n';
}
}
-
- m_deepestSection = node;
- m_sectionStack.push_back( node );
+ out << '\n' << std::flush;
}
- void CumulativeReporterBase::assertionEnded(
- AssertionStats const& assertionStats ) {
- assert( !m_sectionStack.empty() );
- // AssertionResult holds a pointer to a temporary DecomposedExpression,
- // which getExpandedExpression() calls to build the expression string.
- // Our section stack copy of the assertionResult will likely outlive the
- // temporary, so it must be expanded or discarded now to avoid calling
- // a destroyed object later.
- if ( m_shouldStoreFailedAssertions &&
- !assertionStats.assertionResult.isOk() ) {
- static_cast(
- assertionStats.assertionResult.getExpandedExpression() );
+ void defaultListListeners( std::ostream& out,
+ std::vector const& descriptions ) {
+ out << "Registered listeners:\n";
+
+ if(descriptions.empty()) {
+ return;
}
- if ( m_shouldStoreSuccesfulAssertions &&
- assertionStats.assertionResult.isOk() ) {
- static_cast(
- assertionStats.assertionResult.getExpandedExpression() );
+
+ const auto maxNameLen =
+ std::max_element( descriptions.begin(),
+ descriptions.end(),
+ []( ListenerDescription const& lhs,
+ ListenerDescription const& rhs ) {
+ return lhs.name.size() < rhs.name.size();
+ } )
+ ->name.size();
+
+ for ( auto const& desc : descriptions ) {
+ out << TextFlow::Column( static_cast( desc.name ) +
+ ':' )
+ .indent( 2 )
+ .width( maxNameLen + 5 ) +
+ TextFlow::Column( desc.description )
+ .initialIndent( 0 )
+ .indent( 2 )
+ .width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen - 8 )
+ << '\n';
}
- SectionNode& sectionNode = *m_sectionStack.back();
- sectionNode.assertionsAndBenchmarks.emplace_back( assertionStats );
- }
- void CumulativeReporterBase::sectionEnded( SectionStats const& sectionStats ) {
- assert( !m_sectionStack.empty() );
- SectionNode& node = *m_sectionStack.back();
- node.stats = sectionStats;
- m_sectionStack.pop_back();
+ out << '\n' << std::flush;
}
- void CumulativeReporterBase::testCaseEnded(
- TestCaseStats const& testCaseStats ) {
- auto node = Detail::make_unique( testCaseStats );
- assert( m_sectionStack.size() == 0 );
- node->children.push_back( CATCH_MOVE(m_rootSection) );
- m_testCases.push_back( CATCH_MOVE(node) );
+ void defaultListTags( std::ostream& out,
+ std::vector const& tags,
+ bool isFiltered ) {
+ if ( isFiltered ) {
+ out << "Tags for matching test cases:\n";
+ } else {
+ out << "All available tags:\n";
+ }
- assert( m_deepestSection );
- m_deepestSection->stdOut = testCaseStats.stdOut;
- m_deepestSection->stdErr = testCaseStats.stdErr;
+ for ( auto const& tagCount : tags ) {
+ ReusableStringStream rss;
+ rss << " " << std::setw( 2 ) << tagCount.count << " ";
+ auto str = rss.str();
+ auto wrapper = TextFlow::Column( tagCount.all() )
+ .initialIndent( 0 )
+ .indent( str.size() )
+ .width( CATCH_CONFIG_CONSOLE_WIDTH - 10 );
+ out << str << wrapper << '\n';
+ }
+ out << pluralise(tags.size(), "tag"_sr) << "\n\n" << std::flush;
}
+ void defaultListTests(std::ostream& out, ColourImpl* streamColour, std::vector const& tests, bool isFiltered, Verbosity verbosity) {
+ // We special case this to provide the equivalent of old
+ // `--list-test-names-only`, which could then be used by the
+ // `--input-file` option.
+ if (verbosity == Verbosity::Quiet) {
+ listTestNamesOnly(out, tests);
+ return;
+ }
- void CumulativeReporterBase::testRunEnded( TestRunStats const& testRunStats ) {
- assert(!m_testRun && "CumulativeReporterBase assumes there can only be one test run");
- m_testRun = Detail::make_unique( testRunStats );
- m_testRun->children.swap( m_testCases );
- testRunEndedCumulative();
- }
+ if (isFiltered) {
+ out << "Matching test cases:\n";
+ } else {
+ out << "All available test cases:\n";
+ }
- bool CumulativeReporterBase::SectionNode::hasAnyAssertions() const {
- return std::any_of(
- assertionsAndBenchmarks.begin(),
- assertionsAndBenchmarks.end(),
- []( Detail::AssertionOrBenchmarkResult const& res ) {
- return res.isAssertion();
- } );
+ for (auto const& test : tests) {
+ auto const& testCaseInfo = test.getTestCaseInfo();
+ Colour::Code colour = testCaseInfo.isHidden()
+ ? Colour::SecondaryText
+ : Colour::None;
+ auto colourGuard = streamColour->guardColour( colour ).engage( out );
+
+ out << TextFlow::Column(testCaseInfo.name).indent(2) << '\n';
+ if (verbosity >= Verbosity::High) {
+ out << TextFlow::Column(Catch::Detail::stringify(testCaseInfo.lineInfo)).indent(4) << '\n';
+ }
+ if (!testCaseInfo.tags.empty() &&
+ verbosity > Verbosity::Quiet) {
+ out << TextFlow::Column(testCaseInfo.tagsAsString()).indent(6) << '\n';
+ }
+ }
+
+ if (isFiltered) {
+ out << pluralise(tests.size(), "matching test case"_sr);
+ } else {
+ out << pluralise(tests.size(), "test case"_sr);
+ }
+ out << "\n\n" << std::flush;
}
-} // end namespace Catch
+} // namespace Catch
@@ -9168,6 +9076,15 @@ namespace Catch {
return rss.str();
}
+ static void normalizeNamespaceMarkers(std::string& str) {
+ std::size_t pos = str.find( "::" );
+ while ( pos != str.npos ) {
+ str.replace( pos, 2, "." );
+ pos += 1;
+ pos = str.find( "::", pos );
+ }
+ }
+
} // anonymous namespace
JunitReporter::JunitReporter( ReporterConfig&& _config )
@@ -9271,6 +9188,8 @@ namespace Catch {
if ( !m_config->name().empty() )
className = static_cast(m_config->name()) + '.' + className;
+ normalizeNamespaceMarkers(className);
+
writeSection( className, "", rootSection, stats.testInfo->okToFail() );
}
diff --git a/extras/catch_amalgamated.hpp b/extras/catch_amalgamated.hpp
index 5c1caa361e..757e10c5ac 100644
--- a/extras/catch_amalgamated.hpp
+++ b/extras/catch_amalgamated.hpp
@@ -5,8 +5,8 @@
// SPDX-License-Identifier: BSL-1.0
-// Catch v3.0.1
-// Generated: 2022-05-17 22:08:46.674860
+// Catch v3.1.0
+// Generated: 2022-07-17 20:14:04.055157
// ----------------------------------------------------------
// This file is an amalgamation of multiple different files.
// You probably shouldn't edit it directly.
@@ -360,11 +360,23 @@ namespace Catch {
#endif
+#if defined(__CUDACC__) && !defined(__clang__)
+# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "nv_diagnostic push" )
+# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "nv_diagnostic pop" )
+# define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS _Pragma( "nv_diag_suppress 177" )
+#endif
+
+// clang-cl defines _MSC_VER as well as __clang__, which could cause the
+// start/stop internal suppression macros to be double defined.
#if defined(__clang__) && !defined(_MSC_VER)
# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" )
# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic pop" )
+#endif // __clang__ && !_MSC_VER
+
+#if defined(__clang__)
+
// As of this writing, IBM XL's implementation of __builtin_constant_p has a bug
// which results in calls to destructors being emitted for each temporary,
// without a matching initialization. In practice, this can result in something
@@ -2320,7 +2332,7 @@ namespace Catch {
double z1 = normal_quantile((1. - confidence_level) / 2.);
auto cumn = [n]( double x ) -> long {
- return std::lround( normal_cdf( x ) * n );
+ return std::lround( normal_cdf( x ) * static_cast(n) );
};
auto a = [bias, accel](double b) { return bias + b / (1. - accel * b); };
double b1 = bias + z1;
@@ -2730,7 +2742,7 @@ namespace Catch {
}
T const& stored_object() const {
- return *static_cast(static_cast(data));
+ return *static_cast(static_cast(data));
}
@@ -5568,9 +5580,9 @@ namespace Catch {
#endif // CATCH_ASSERTION_HANDLER_HPP_INCLUDED
-// We need this suppression to leak, because it took until GCC 9
+// We need this suppression to leak, because it took until GCC 10
// for the front end to handle local suppression via _Pragma properly
-#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && __GNUC__ < 9
+#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && __GNUC__ <= 9
#pragma GCC diagnostic ignored "-Wparentheses"
#endif
@@ -5879,6 +5891,7 @@ struct AutoReg : Detail::NonCopyable {
static void TestName(); \
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
+ CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
static void TestName()
@@ -5889,6 +5902,7 @@ struct AutoReg : Detail::NonCopyable {
#define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
+ CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &QualifiedMethod ), CATCH_INTERNAL_LINEINFO, "&" #QualifiedMethod, Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
@@ -5896,6 +5910,7 @@ struct AutoReg : Detail::NonCopyable {
#define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
+ CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
namespace{ \
struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \
void test(); \
@@ -5912,6 +5927,7 @@ struct AutoReg : Detail::NonCopyable {
do { \
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
+ CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
} while(false)
@@ -7046,8 +7062,8 @@ namespace Catch {
#define CATCH_VERSION_MACROS_HPP_INCLUDED
#define CATCH_VERSION_MAJOR 3
-#define CATCH_VERSION_MINOR 0
-#define CATCH_VERSION_PATCH 1
+#define CATCH_VERSION_MINOR 1
+#define CATCH_VERSION_PATCH 0
#endif // CATCH_VERSION_MACROS_HPP_INCLUDED
@@ -7752,12 +7768,17 @@ class RandomIntegerGenerator final : public IGenerator {
}
};
-// TODO: Ideally this would be also constrained against the various char types,
-// but I don't expect users to run into that in practice.
template
-std::enable_if_t::value && !std::is_same::value,
-GeneratorWrapper>
+std::enable_if_t::value, GeneratorWrapper>
random(T a, T b) {
+ static_assert(
+ !std::is_same::value &&
+ !std::is_same::value &&
+ !std::is_same::value &&
+ !std::is_same::value &&
+ !std::is_same::value &&
+ !std::is_same::value,
+ "The requested type is not supported by the underlying random distributions from std" );
return GeneratorWrapper(
Catch::Detail::make_unique>(a, b, Detail::getSeed())
);
@@ -8097,6 +8118,9 @@ namespace Catch {
#ifndef CATCH_CONSOLE_WIDTH_HPP_INCLUDED
#define CATCH_CONSOLE_WIDTH_HPP_INCLUDED
+// This include must be kept so that user's configured value for CONSOLE_WIDTH
+// is used before we attempt to provide a default value
+
#ifndef CATCH_CONFIG_CONSOLE_WIDTH
#define CATCH_CONFIG_CONSOLE_WIDTH 80
#endif
@@ -10455,7 +10479,6 @@ namespace Catch {
class IsEmptyMatcher final : public MatcherGenericBase {
public:
- // todo: Use polyfills
template
bool match(RangeLike&& rng) const {
#if defined(CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS)
@@ -10856,7 +10879,55 @@ namespace Catch {
}
};
- // Creates a matcher that checks whether a range contains element matching a matcher
+ // Matcher for checking that all elements in range are true.
+ class AllTrueMatcher final : public MatcherGenericBase {
+ public:
+ std::string describe() const override;
+
+ template
+ bool match(RangeLike&& rng) const {
+ for (auto&& elem : rng) {
+ if (!elem) {
+ return false;
+ }
+ }
+ return true;
+ }
+ };
+
+ // Matcher for checking that no element in range is true.
+ class NoneTrueMatcher final : public MatcherGenericBase {
+ public:
+ std::string describe() const override;
+
+ template
+ bool match(RangeLike&& rng) const {
+ for (auto&& elem : rng) {
+ if (elem) {
+ return false;
+ }
+ }
+ return true;
+ }
+ };
+
+ // Matcher for checking that any element in range is true.
+ class AnyTrueMatcher final : public MatcherGenericBase {
+ public:
+ std::string describe() const override;
+
+ template
+ bool match(RangeLike&& rng) const {
+ for (auto&& elem : rng) {
+ if (elem) {
+ return true;
+ }
+ }
+ return false;
+ }
+ };
+
+ // Creates a matcher that checks whether all elements in a range match a matcher
template
AllMatchMatcher AllMatch(Matcher&& matcher) {
return { CATCH_FORWARD(matcher) };
@@ -10873,6 +10944,15 @@ namespace Catch {
AnyMatchMatcher AnyMatch(Matcher&& matcher) {
return { CATCH_FORWARD(matcher) };
}
+
+ // Creates a matcher that checks whether all elements in a range are true
+ AllTrueMatcher AllTrue();
+
+ // Creates a matcher that checks whether no element in a range is true
+ NoneTrueMatcher NoneTrue();
+
+ // Creates a matcher that checks whether any element in a range is true
+ AnyTrueMatcher AnyTrue();
}
}
@@ -11252,7 +11332,11 @@ namespace Catch {
class StreamingReporterBase : public ReporterBase {
public:
- using ReporterBase::ReporterBase;
+ // GCC5 compat: we cannot use inherited constructor, because it
+ // doesn't implement backport of P0136
+ StreamingReporterBase(ReporterConfig&& _config):
+ ReporterBase(CATCH_MOVE(_config))
+ {}
~StreamingReporterBase() override;
void benchmarkPreparing( StringRef ) override {}
@@ -11309,7 +11393,11 @@ namespace Catch {
class AutomakeReporter final : public StreamingReporterBase {
public:
- using StreamingReporterBase::StreamingReporterBase;
+ // GCC5 compat: we cannot use inherited constructor, because it
+ // doesn't implement backport of P0136
+ AutomakeReporter(ReporterConfig&& _config):
+ StreamingReporterBase(CATCH_MOVE(_config))
+ {}
~AutomakeReporter() override;
static std::string getDescription() {
@@ -11505,7 +11593,11 @@ namespace Catch {
using TestCaseNode = Node;
using TestRunNode = Node;
- using ReporterBase::ReporterBase;
+ // GCC5 compat: we cannot use inherited constructor, because it
+ // doesn't implement backport of P0136
+ CumulativeReporterBase(ReporterConfig&& _config):
+ ReporterBase(CATCH_MOVE(_config))
+ {}
~CumulativeReporterBase() override;
void benchmarkPreparing( StringRef ) override {}
diff --git a/src/catch2/catch_version.cpp b/src/catch2/catch_version.cpp
index ed5392970d..a7075f3006 100644
--- a/src/catch2/catch_version.cpp
+++ b/src/catch2/catch_version.cpp
@@ -36,7 +36,7 @@ namespace Catch {
}
Version const& libraryVersion() {
- static Version version( 3, 0, 1, "", 0 );
+ static Version version( 3, 1, 0, "", 0 );
return version;
}
diff --git a/src/catch2/catch_version_macros.hpp b/src/catch2/catch_version_macros.hpp
index 29e185673b..c7212e3a6a 100644
--- a/src/catch2/catch_version_macros.hpp
+++ b/src/catch2/catch_version_macros.hpp
@@ -9,7 +9,7 @@
#define CATCH_VERSION_MACROS_HPP_INCLUDED
#define CATCH_VERSION_MAJOR 3
-#define CATCH_VERSION_MINOR 0
-#define CATCH_VERSION_PATCH 1
+#define CATCH_VERSION_MINOR 1
+#define CATCH_VERSION_PATCH 0
#endif // CATCH_VERSION_MACROS_HPP_INCLUDED