diff --git a/thirdparty/catch2/cmake/modules/extras/Catch.cmake b/thirdparty/catch2/cmake/modules/extras/Catch.cmake index e080665b7ae..cef73def2d8 100644 --- a/thirdparty/catch2/cmake/modules/extras/Catch.cmake +++ b/thirdparty/catch2/cmake/modules/extras/Catch.cmake @@ -38,6 +38,7 @@ same as the Catch name; see also ``TEST_PREFIX`` and ``TEST_SUFFIX``. [OUTPUT_PREFIX prefix] [OUTPUT_SUFFIX suffix] [DISCOVERY_MODE ] + [SKIP_IS_FAILURE] ) ``catch_discover_tests`` sets up a post-build command on the test executable @@ -131,7 +132,7 @@ same as the Catch name; see also ``TEST_PREFIX`` and ``TEST_SUFFIX``. of test cases from the test executable and when the tests are executed themselves. This requires cmake/ctest >= 3.22. - `DISCOVERY_MODE mode`` + ``DISCOVERY_MODE mode`` Provides control over when ``catch_discover_tests`` performs test discovery. By default, ``POST_BUILD`` sets up a post-build command to perform test discovery at build time. In certain scenarios, like cross-compiling, this ``POST_BUILD`` @@ -144,6 +145,9 @@ same as the Catch name; see also ``TEST_PREFIX`` and ``TEST_SUFFIX``. calling ``catch_discover_tests``. This provides a mechanism for globally selecting a preferred test discovery behavior without having to modify each call site. + ``SKIP_IS_FAILURE`` + Disables skipped test detection. + #]=======================================================================] #------------------------------------------------------------------------------ @@ -151,7 +155,7 @@ function(catch_discover_tests TARGET) cmake_parse_arguments( "" - "" + "SKIP_IS_FAILURE" "TEST_PREFIX;TEST_SUFFIX;WORKING_DIRECTORY;TEST_LIST;REPORTER;OUTPUT_DIR;OUTPUT_PREFIX;OUTPUT_SUFFIX;DISCOVERY_MODE" "TEST_SPEC;EXTRA_ARGS;PROPERTIES;DL_PATHS;DL_FRAMEWORK_PATHS" ${ARGN} @@ -192,6 +196,9 @@ function(catch_discover_tests TARGET) TARGET ${TARGET} PROPERTY CROSSCOMPILING_EMULATOR ) + if (NOT _SKIP_IS_FAILURE) + set(_PROPERTIES ${_PROPERTIES} SKIP_RETURN_CODE 4) + endif() if(_DISCOVERY_MODE STREQUAL "POST_BUILD") add_custom_command( @@ -260,7 +267,6 @@ function(catch_discover_tests TARGET) " CTEST_FILE" " [==[" "${ctest_tests_file}" "]==]" "\n" " TEST_DL_PATHS" " [==[" "${_DL_PATHS}" "]==]" "\n" " TEST_DL_FRAMEWORK_PATHS" " [==[" "${_DL_FRAMEWORK_PATHS}" "]==]" "\n" - " CTEST_FILE" " [==[" "${CTEST_FILE}" "]==]" "\n" " )" "\n" " endif()" "\n" " include(\"${ctest_tests_file}\")" "\n" diff --git a/thirdparty/catch2/src/main/native/cpp/catch2/benchmark/detail/catch_stats.cpp b/thirdparty/catch2/src/main/native/cpp/catch2/benchmark/detail/catch_stats.cpp index e6de359c444..2a5a2e038ea 100644 --- a/thirdparty/catch2/src/main/native/cpp/catch2/benchmark/detail/catch_stats.cpp +++ b/thirdparty/catch2/src/main/native/cpp/catch2/benchmark/detail/catch_stats.cpp @@ -178,7 +178,7 @@ namespace Catch { double diff = b - m; return a + diff * diff; } ) / - ( last - first ); + static_cast( last - first ); return std::sqrt( variance ); } @@ -213,7 +213,7 @@ namespace Catch { double* first, double* last ) { auto count = last - first; - double idx = (count - 1) * k / static_cast(q); + double idx = static_cast((count - 1) * k) / static_cast(q); int j = static_cast(idx); double g = idx - j; std::nth_element(first, first + j, last); @@ -316,10 +316,10 @@ namespace Catch { double accel = sum_cubes / ( 6 * std::pow( sum_squares, 1.5 ) ); long n = static_cast( resample.size() ); - double prob_n = + double prob_n = static_cast( std::count_if( resample.begin(), resample.end(), - [point]( double x ) { return x < point; } ) / + [point]( double x ) { return x < point; } )) / static_cast( n ); // degenerate case with uniform samples if ( Catch::Detail::directCompare( prob_n, 0. ) ) { diff --git a/thirdparty/catch2/src/main/native/cpp/catch2/catch_assertion_result.cpp b/thirdparty/catch2/src/main/native/cpp/catch2/catch_assertion_result.cpp index 61d4fd068a9..dba86229f4d 100644 --- a/thirdparty/catch2/src/main/native/cpp/catch2/catch_assertion_result.cpp +++ b/thirdparty/catch2/src/main/native/cpp/catch2/catch_assertion_result.cpp @@ -11,7 +11,7 @@ namespace Catch { - AssertionResultData::AssertionResultData(ResultWas::OfType _resultType, LazyExpression const & _lazyExpression): + AssertionResultData::AssertionResultData(ResultWas::OfType _resultType, LazyExpression const& _lazyExpression): lazyExpression(_lazyExpression), resultType(_resultType) {} diff --git a/thirdparty/catch2/src/main/native/cpp/catch2/catch_session.cpp b/thirdparty/catch2/src/main/native/cpp/catch2/catch_session.cpp index f1ed5f9cc55..a4a410c96c4 100644 --- a/thirdparty/catch2/src/main/native/cpp/catch2/catch_session.cpp +++ b/thirdparty/catch2/src/main/native/cpp/catch2/catch_session.cpp @@ -34,7 +34,13 @@ namespace Catch { namespace { - const int MaxExitCode = 255; + 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)); @@ -198,8 +204,7 @@ namespace Catch { } int Session::applyCommandLine( int argc, char const * const * argv ) { - if( m_startupExceptions ) - return 1; + if ( m_startupExceptions ) { return UnspecifiedErrorExitCode; } auto result = m_cli.parse( Clara::Args( argc, argv ) ); @@ -215,7 +220,7 @@ namespace Catch { << TextFlow::Column( result.errorMessage() ).indent( 2 ) << "\n\n"; errStream->stream() << "Run with -? for usage\n\n" << std::flush; - return MaxExitCode; + return UnspecifiedErrorExitCode; } if( m_configData.showHelp ) @@ -285,8 +290,7 @@ namespace Catch { } int Session::runInternal() { - if( m_startupExceptions ) - return 1; + if ( m_startupExceptions ) { return UnspecifiedErrorExitCode; } if (m_configData.showHelp || m_configData.libIdentify) { return 0; @@ -297,7 +301,7 @@ namespace Catch { << ") must be greater than the shard index (" << m_configData.shardIndex << ")\n" << std::flush; - return 1; + return UnspecifiedErrorExitCode; } CATCH_TRY { @@ -320,7 +324,7 @@ namespace Catch { for ( auto const& spec : invalidSpecs ) { reporter->reportInvalidTestSpec( spec ); } - return 1; + return InvalidTestSpecExitCode; } @@ -334,29 +338,29 @@ namespace Catch { if ( tests.hadUnmatchedTestSpecs() && m_config->warnAboutUnmatchedTestSpecs() ) { - return 3; + // UnmatchedTestSpecExitCode + return UnmatchedTestSpecExitCode; } if ( totals.testCases.total() == 0 && !m_config->zeroTestsCountAsSuccess() ) { - return 2; + return NoTestsRunExitCode; } if ( totals.testCases.total() > 0 && totals.testCases.total() == totals.testCases.skipped && !m_config->zeroTestsCountAsSuccess() ) { - return 4; + return AllTestsSkippedExitCode; } - // Note that on unices only the lower 8 bits are usually used, clamping - // the return value to 255 prevents false negative when some multiple - // of 256 tests has failed - return (std::min) (MaxExitCode, static_cast(totals.assertions.failed)); + if ( totals.assertions.failed ) { return TestFailureExitCode; } + return 0; + } #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) catch( std::exception& ex ) { Catch::cerr() << ex.what() << '\n' << std::flush; - return MaxExitCode; + return UnspecifiedErrorExitCode; } #endif } diff --git a/thirdparty/catch2/src/main/native/cpp/catch2/catch_test_case_info.cpp b/thirdparty/catch2/src/main/native/cpp/catch2/catch_test_case_info.cpp index 2a4fbd339ba..9d64e532a6f 100644 --- a/thirdparty/catch2/src/main/native/cpp/catch2/catch_test_case_info.cpp +++ b/thirdparty/catch2/src/main/native/cpp/catch2/catch_test_case_info.cpp @@ -22,26 +22,26 @@ namespace Catch { static_assert(sizeof(TestCaseProperties) == sizeof(TCP_underlying_type), "The size of the TestCaseProperties is different from the assumed size"); - TestCaseProperties operator|(TestCaseProperties lhs, TestCaseProperties rhs) { + constexpr TestCaseProperties operator|(TestCaseProperties lhs, TestCaseProperties rhs) { return static_cast( static_cast(lhs) | static_cast(rhs) ); } - TestCaseProperties& operator|=(TestCaseProperties& lhs, TestCaseProperties rhs) { + constexpr TestCaseProperties& operator|=(TestCaseProperties& lhs, TestCaseProperties rhs) { lhs = static_cast( static_cast(lhs) | static_cast(rhs) ); return lhs; } - TestCaseProperties operator&(TestCaseProperties lhs, TestCaseProperties rhs) { + constexpr TestCaseProperties operator&(TestCaseProperties lhs, TestCaseProperties rhs) { return static_cast( static_cast(lhs) & static_cast(rhs) ); } - bool applies(TestCaseProperties tcp) { + constexpr bool applies(TestCaseProperties tcp) { static_assert(static_cast(TestCaseProperties::None) == 0, "TestCaseProperties::None must be equal to 0"); return tcp != TestCaseProperties::None; @@ -80,7 +80,7 @@ namespace Catch { return "Anonymous test case " + std::to_string(++counter); } - StringRef extractFilenamePart(StringRef filename) { + constexpr StringRef extractFilenamePart(StringRef filename) { size_t lastDot = filename.size(); while (lastDot > 0 && filename[lastDot - 1] != '.') { --lastDot; @@ -98,7 +98,7 @@ namespace Catch { } // Returns the upper bound on size of extra tags ([#file]+[.]) - size_t sizeOfExtraTags(StringRef filepath) { + constexpr size_t sizeOfExtraTags(StringRef filepath) { // [.] is 3, [#] is another 3 const size_t extras = 3 + 3; return extractFilenamePart(filepath).size() + extras; @@ -259,8 +259,4 @@ namespace Catch { return lhs.tags < rhs.tags; } - TestCaseInfo const& TestCaseHandle::getTestCaseInfo() const { - return *m_info; - } - } // end namespace Catch diff --git a/thirdparty/catch2/src/main/native/cpp/catch2/catch_timer.cpp b/thirdparty/catch2/src/main/native/cpp/catch2/catch_timer.cpp index d75ea70c8b4..efdd8b7d0cb 100644 --- a/thirdparty/catch2/src/main/native/cpp/catch2/catch_timer.cpp +++ b/thirdparty/catch2/src/main/native/cpp/catch2/catch_timer.cpp @@ -13,7 +13,7 @@ namespace Catch { namespace { static auto getCurrentNanosecondsSinceEpoch() -> uint64_t { - return std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count(); + return std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); } } // end unnamed namespace @@ -30,7 +30,7 @@ namespace Catch { return static_cast(getElapsedMicroseconds()/1000); } auto Timer::getElapsedSeconds() const -> double { - return getElapsedMicroseconds()/1000000.0; + return static_cast(getElapsedMicroseconds())/1000000.0; } diff --git a/thirdparty/catch2/src/main/native/cpp/catch2/catch_tostring.cpp b/thirdparty/catch2/src/main/native/cpp/catch2/catch_tostring.cpp index 3f034d1aaa8..83327cfb59f 100644 --- a/thirdparty/catch2/src/main/native/cpp/catch2/catch_tostring.cpp +++ b/thirdparty/catch2/src/main/native/cpp/catch2/catch_tostring.cpp @@ -22,7 +22,10 @@ namespace Detail { const int hexThreshold = 255; struct Endianness { - enum Arch { Big, Little }; + enum Arch : uint8_t { + Big, + Little + }; static Arch which() { int one = 1; diff --git a/thirdparty/catch2/src/main/native/cpp/catch2/catch_version.cpp b/thirdparty/catch2/src/main/native/cpp/catch2/catch_version.cpp index 63a9ec86326..1701f3adf5b 100644 --- a/thirdparty/catch2/src/main/native/cpp/catch2/catch_version.cpp +++ b/thirdparty/catch2/src/main/native/cpp/catch2/catch_version.cpp @@ -36,7 +36,7 @@ namespace Catch { } Version const& libraryVersion() { - static Version version( 3, 6, 0, "", 0 ); + static Version version( 3, 7, 1, "", 0 ); return version; } diff --git a/thirdparty/catch2/src/main/native/cpp/catch2/internal/catch_assertion_handler.cpp b/thirdparty/catch2/src/main/native/cpp/catch2/internal/catch_assertion_handler.cpp index f650a7073a2..9a28e79c216 100644 --- a/thirdparty/catch2/src/main/native/cpp/catch2/internal/catch_assertion_handler.cpp +++ b/thirdparty/catch2/src/main/native/cpp/catch2/internal/catch_assertion_handler.cpp @@ -28,8 +28,8 @@ namespace Catch { void AssertionHandler::handleExpr( ITransientExpression const& expr ) { m_resultCapture.handleExpr( m_assertionInfo, expr, m_reaction ); } - void AssertionHandler::handleMessage(ResultWas::OfType resultType, StringRef message) { - m_resultCapture.handleMessage( m_assertionInfo, resultType, message, m_reaction ); + void AssertionHandler::handleMessage(ResultWas::OfType resultType, std::string&& message) { + m_resultCapture.handleMessage( m_assertionInfo, resultType, CATCH_MOVE(message), m_reaction ); } auto AssertionHandler::allowThrows() const -> bool { diff --git a/thirdparty/catch2/src/main/native/cpp/catch2/internal/catch_clara.cpp b/thirdparty/catch2/src/main/native/cpp/catch2/internal/catch_clara.cpp index c76089eea10..f9dd9138575 100644 --- a/thirdparty/catch2/src/main/native/cpp/catch2/internal/catch_clara.cpp +++ b/thirdparty/catch2/src/main/native/cpp/catch2/internal/catch_clara.cpp @@ -76,7 +76,7 @@ namespace Catch { { TokenType::Argument, next.substr( delimiterPos + 1, next.size() ) } ); } else { - if ( next[1] != '-' && next.size() > 2 ) { + if ( next.size() > 1 && next[1] != '-' && next.size() > 2 ) { // Combined short args, e.g. "-ab" for "-a -b" for ( size_t i = 1; i < next.size(); ++i ) { m_tokenBuffer.push_back( diff --git a/thirdparty/catch2/src/main/native/cpp/catch2/internal/catch_console_colour.cpp b/thirdparty/catch2/src/main/native/cpp/catch2/internal/catch_console_colour.cpp index b19e01ecce0..142de9e65ed 100644 --- a/thirdparty/catch2/src/main/native/cpp/catch2/internal/catch_console_colour.cpp +++ b/thirdparty/catch2/src/main/native/cpp/catch2/internal/catch_console_colour.cpp @@ -161,7 +161,7 @@ namespace { #endif // Windows/ ANSI/ None -#if defined( CATCH_PLATFORM_LINUX ) || defined( CATCH_PLATFORM_MAC ) +#if defined( CATCH_PLATFORM_LINUX ) || defined( CATCH_PLATFORM_MAC ) || defined( __GLIBC__ ) # define CATCH_INTERNAL_HAS_ISATTY # include #endif diff --git a/thirdparty/catch2/src/main/native/cpp/catch2/internal/catch_context.cpp b/thirdparty/catch2/src/main/native/cpp/catch2/internal/catch_context.cpp index 3b1cc277475..8acf1eda62b 100644 --- a/thirdparty/catch2/src/main/native/cpp/catch2/internal/catch_context.cpp +++ b/thirdparty/catch2/src/main/native/cpp/catch2/internal/catch_context.cpp @@ -27,12 +27,6 @@ namespace Catch { return *Context::currentContext; } - void Context::setResultCapture( IResultCapture* resultCapture ) { - m_resultCapture = resultCapture; - } - - void Context::setConfig( IConfig const* config ) { m_config = config; } - SimplePcg32& sharedRng() { static SimplePcg32 s_rng; return s_rng; diff --git a/thirdparty/catch2/src/main/native/cpp/catch2/internal/catch_output_redirect.cpp b/thirdparty/catch2/src/main/native/cpp/catch2/internal/catch_output_redirect.cpp index 02f7c982689..245e1376cf6 100644 --- a/thirdparty/catch2/src/main/native/cpp/catch2/internal/catch_output_redirect.cpp +++ b/thirdparty/catch2/src/main/native/cpp/catch2/internal/catch_output_redirect.cpp @@ -5,142 +5,335 @@ // https://www.boost.org/LICENSE_1_0.txt) // SPDX-License-Identifier: BSL-1.0 -#include +#include #include +#include +#include +#include #include #include #include +#include #include -#if defined(CATCH_CONFIG_NEW_CAPTURE) - #if defined(_MSC_VER) - #include //_dup and _dup2 - #define dup _dup - #define dup2 _dup2 - #define fileno _fileno - #else - #include // dup and dup2 - #endif +#if defined( CATCH_CONFIG_NEW_CAPTURE ) +# if defined( _MSC_VER ) +# include //_dup and _dup2 +# define dup _dup +# define dup2 _dup2 +# define fileno _fileno +# else +# include // dup and dup2 +# endif #endif - namespace Catch { - RedirectedStream::RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream ) - : m_originalStream( originalStream ), - m_redirectionStream( redirectionStream ), - m_prevBuf( m_originalStream.rdbuf() ) - { - m_originalStream.rdbuf( m_redirectionStream.rdbuf() ); - } + namespace { + //! A no-op implementation, used if no reporter wants output + //! redirection. + class NoopRedirect : public OutputRedirect { + void activateImpl() override {} + void deactivateImpl() override {} + std::string getStdout() override { return {}; } + std::string getStderr() override { return {}; } + void clearBuffers() override {} + }; - RedirectedStream::~RedirectedStream() { - m_originalStream.rdbuf( m_prevBuf ); - } + /** + * Redirects specific stream's rdbuf with another's. + * + * Redirection can be stopped and started on-demand, assumes + * that the underlying stream's rdbuf aren't changed by other + * users. + */ + class RedirectedStreamNew { + std::ostream& m_originalStream; + std::ostream& m_redirectionStream; + std::streambuf* m_prevBuf; - RedirectedStdOut::RedirectedStdOut() : m_cout( Catch::cout(), m_rss.get() ) {} - auto RedirectedStdOut::str() const -> std::string { return m_rss.str(); } + public: + RedirectedStreamNew( std::ostream& originalStream, + std::ostream& redirectionStream ): + m_originalStream( originalStream ), + m_redirectionStream( redirectionStream ), + m_prevBuf( m_originalStream.rdbuf() ) {} - RedirectedStdErr::RedirectedStdErr() - : m_cerr( Catch::cerr(), m_rss.get() ), - m_clog( Catch::clog(), m_rss.get() ) - {} - auto RedirectedStdErr::str() const -> std::string { return m_rss.str(); } + void startRedirect() { + m_originalStream.rdbuf( m_redirectionStream.rdbuf() ); + } + void stopRedirect() { m_originalStream.rdbuf( m_prevBuf ); } + }; - RedirectedStreams::RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr) - : m_redirectedCout(redirectedCout), - m_redirectedCerr(redirectedCerr) - {} + /** + * Redirects the `std::cout`, `std::cerr`, `std::clog` streams, + * but does not touch the actual `stdout`/`stderr` file descriptors. + */ + class StreamRedirect : public OutputRedirect { + ReusableStringStream m_redirectedOut, m_redirectedErr; + RedirectedStreamNew m_cout, m_cerr, m_clog; - RedirectedStreams::~RedirectedStreams() { - m_redirectedCout += m_redirectedStdOut.str(); - m_redirectedCerr += m_redirectedStdErr.str(); - } + public: + StreamRedirect(): + m_cout( Catch::cout(), m_redirectedOut.get() ), + m_cerr( Catch::cerr(), m_redirectedErr.get() ), + m_clog( Catch::clog(), m_redirectedErr.get() ) {} -#if defined(CATCH_CONFIG_NEW_CAPTURE) + void activateImpl() override { + m_cout.startRedirect(); + m_cerr.startRedirect(); + m_clog.startRedirect(); + } + void deactivateImpl() override { + m_cout.stopRedirect(); + m_cerr.stopRedirect(); + m_clog.stopRedirect(); + } + std::string getStdout() override { return m_redirectedOut.str(); } + std::string getStderr() override { return m_redirectedErr.str(); } + void clearBuffers() override { + m_redirectedOut.str( "" ); + m_redirectedErr.str( "" ); + } + }; -#if defined(_MSC_VER) - TempFile::TempFile() { - if (tmpnam_s(m_buffer)) { - CATCH_RUNTIME_ERROR("Could not get a temp filename"); - } - if (fopen_s(&m_file, m_buffer, "w+")) { - char buffer[100]; - if (strerror_s(buffer, errno)) { - CATCH_RUNTIME_ERROR("Could not translate errno to a string"); +#if defined( CATCH_CONFIG_NEW_CAPTURE ) + + // Windows's implementation of std::tmpfile is terrible (it tries + // to create a file inside system folder, thus requiring elevated + // privileges for the binary), so we have to use tmpnam(_s) and + // create the file ourselves there. + class TempFile { + public: + TempFile( TempFile const& ) = delete; + TempFile& operator=( TempFile const& ) = delete; + TempFile( TempFile&& ) = delete; + TempFile& operator=( TempFile&& ) = delete; + +# if defined( _MSC_VER ) + TempFile() { + if ( tmpnam_s( m_buffer ) ) { + CATCH_RUNTIME_ERROR( "Could not get a temp filename" ); + } + if ( fopen_s( &m_file, m_buffer, "wb+" ) ) { + char buffer[100]; + if ( strerror_s( buffer, errno ) ) { + CATCH_RUNTIME_ERROR( + "Could not translate errno to a string" ); + } + CATCH_RUNTIME_ERROR( "Could not open the temp file: '" + << m_buffer + << "' because: " << buffer ); + } + } +# else + TempFile() { + m_file = std::tmpfile(); + if ( !m_file ) { + CATCH_RUNTIME_ERROR( "Could not create a temp file." ); + } + } +# endif + + ~TempFile() { + // TBD: What to do about errors here? + std::fclose( m_file ); + // We manually create the file on Windows only, on Linux + // it will be autodeleted +# if defined( _MSC_VER ) + std::remove( m_buffer ); +# endif + } + + std::FILE* getFile() { return m_file; } + std::string getContents() { + ReusableStringStream sstr; + constexpr long buffer_size = 100; + char buffer[buffer_size + 1] = {}; + long current_pos = ftell( m_file ); + CATCH_ENFORCE( current_pos >= 0, + "ftell failed, errno: " << errno ); + std::rewind( m_file ); + while ( current_pos > 0 ) { + auto read_characters = + std::fread( buffer, + 1, + std::min( buffer_size, current_pos ), + m_file ); + buffer[read_characters] = '\0'; + sstr << buffer; + current_pos -= static_cast( read_characters ); + } + return sstr.str(); + } + + void clear() { std::rewind( m_file ); } + + private: + std::FILE* m_file = nullptr; + char m_buffer[L_tmpnam] = { 0 }; + }; + + /** + * Redirects the actual `stdout`/`stderr` file descriptors. + * + * Works by replacing the file descriptors numbered 1 and 2 + * with an open temporary file. + */ + class FileRedirect : public OutputRedirect { + TempFile m_outFile, m_errFile; + int m_originalOut = -1; + int m_originalErr = -1; + + // Flushes cout/cerr/clog streams and stdout/stderr FDs + void flushEverything() { + Catch::cout() << std::flush; + fflush( stdout ); + // Since we support overriding these streams, we flush cerr + // even though std::cerr is unbuffered + Catch::cerr() << std::flush; + Catch::clog() << std::flush; + fflush( stderr ); + } + + public: + FileRedirect(): + m_originalOut( dup( fileno( stdout ) ) ), + m_originalErr( dup( fileno( stderr ) ) ) { + CATCH_ENFORCE( m_originalOut >= 0, "Could not dup stdout" ); + CATCH_ENFORCE( m_originalErr >= 0, "Could not dup stderr" ); } - CATCH_RUNTIME_ERROR("Could not open the temp file: '" << m_buffer << "' because: " << buffer); + + std::string getStdout() override { return m_outFile.getContents(); } + std::string getStderr() override { return m_errFile.getContents(); } + void clearBuffers() override { + m_outFile.clear(); + m_errFile.clear(); + } + + void activateImpl() override { + // We flush before starting redirect, to ensure that we do + // not capture the end of message sent before activation. + flushEverything(); + + int ret; + ret = dup2( fileno( m_outFile.getFile() ), fileno( stdout ) ); + CATCH_ENFORCE( ret >= 0, + "dup2 to stdout has failed, errno: " << errno ); + ret = dup2( fileno( m_errFile.getFile() ), fileno( stderr ) ); + CATCH_ENFORCE( ret >= 0, + "dup2 to stderr has failed, errno: " << errno ); + } + void deactivateImpl() override { + // We flush before ending redirect, to ensure that we + // capture all messages sent while the redirect was active. + flushEverything(); + + int ret; + ret = dup2( m_originalOut, fileno( stdout ) ); + CATCH_ENFORCE( + ret >= 0, + "dup2 of original stdout has failed, errno: " << errno ); + ret = dup2( m_originalErr, fileno( stderr ) ); + CATCH_ENFORCE( + ret >= 0, + "dup2 of original stderr has failed, errno: " << errno ); + } + }; + +#endif // CATCH_CONFIG_NEW_CAPTURE + + } // end namespace + + bool isRedirectAvailable( OutputRedirect::Kind kind ) { + switch ( kind ) { + // These two are always available + case OutputRedirect::None: + case OutputRedirect::Streams: + return true; +#if defined( CATCH_CONFIG_NEW_CAPTURE ) + case OutputRedirect::FileDescriptors: + return true; +#endif + default: + return false; } } + + Detail::unique_ptr makeOutputRedirect( bool actual ) { + if ( actual ) { + // TODO: Clean this up later +#if defined( CATCH_CONFIG_NEW_CAPTURE ) + return Detail::make_unique(); #else - TempFile::TempFile() { - m_file = std::tmpfile(); - if (!m_file) { - CATCH_RUNTIME_ERROR("Could not create a temp file."); + return Detail::make_unique(); +#endif + } else { + return Detail::make_unique(); } } -#endif + RedirectGuard scopedActivate( OutputRedirect& redirectImpl ) { + return RedirectGuard( true, redirectImpl ); + } - TempFile::~TempFile() { - // TBD: What to do about errors here? - std::fclose(m_file); - // We manually create the file on Windows only, on Linux - // it will be autodeleted -#if defined(_MSC_VER) - std::remove(m_buffer); -#endif + RedirectGuard scopedDeactivate( OutputRedirect& redirectImpl ) { + return RedirectGuard( false, redirectImpl ); } + OutputRedirect::~OutputRedirect() = default; - FILE* TempFile::getFile() { - return m_file; - } + RedirectGuard::RedirectGuard( bool activate, OutputRedirect& redirectImpl ): + m_redirect( &redirectImpl ), + m_activate( activate ), + m_previouslyActive( redirectImpl.isActive() ) { - std::string TempFile::getContents() { - std::stringstream sstr; - char buffer[100] = {}; - std::rewind(m_file); - while (std::fgets(buffer, sizeof(buffer), m_file)) { - sstr << buffer; - } - return sstr.str(); - } + // Skip cases where there is no actual state change. + if ( m_activate == m_previouslyActive ) { return; } - OutputRedirect::OutputRedirect(std::string& stdout_dest, std::string& stderr_dest) : - m_originalStdout(dup(1)), - m_originalStderr(dup(2)), - m_stdoutDest(stdout_dest), - m_stderrDest(stderr_dest) { - dup2(fileno(m_stdoutFile.getFile()), 1); - dup2(fileno(m_stderrFile.getFile()), 2); + if ( m_activate ) { + m_redirect->activate(); + } else { + m_redirect->deactivate(); + } } - OutputRedirect::~OutputRedirect() { - Catch::cout() << std::flush; - fflush(stdout); - // Since we support overriding these streams, we flush cerr - // even though std::cerr is unbuffered - Catch::cerr() << std::flush; - Catch::clog() << std::flush; - fflush(stderr); + RedirectGuard::~RedirectGuard() noexcept( false ) { + if ( m_moved ) { return; } + // Skip cases where there is no actual state change. + if ( m_activate == m_previouslyActive ) { return; } - dup2(m_originalStdout, 1); - dup2(m_originalStderr, 2); + if ( m_activate ) { + m_redirect->deactivate(); + } else { + m_redirect->activate(); + } + } - m_stdoutDest += m_stdoutFile.getContents(); - m_stderrDest += m_stderrFile.getContents(); + RedirectGuard::RedirectGuard( RedirectGuard&& rhs ) noexcept: + m_redirect( rhs.m_redirect ), + m_activate( rhs.m_activate ), + m_previouslyActive( rhs.m_previouslyActive ), + m_moved( false ) { + rhs.m_moved = true; } -#endif // CATCH_CONFIG_NEW_CAPTURE + RedirectGuard& RedirectGuard::operator=( RedirectGuard&& rhs ) noexcept { + m_redirect = rhs.m_redirect; + m_activate = rhs.m_activate; + m_previouslyActive = rhs.m_previouslyActive; + m_moved = false; + rhs.m_moved = true; + return *this; + } } // namespace Catch -#if defined(CATCH_CONFIG_NEW_CAPTURE) - #if defined(_MSC_VER) - #undef dup - #undef dup2 - #undef fileno - #endif +#if defined( CATCH_CONFIG_NEW_CAPTURE ) +# if defined( _MSC_VER ) +# undef dup +# undef dup2 +# undef fileno +# endif #endif diff --git a/thirdparty/catch2/src/main/native/cpp/catch2/internal/catch_random_number_generator.cpp b/thirdparty/catch2/src/main/native/cpp/catch2/internal/catch_random_number_generator.cpp index 6a79dff39a0..c88cd8f2d18 100644 --- a/thirdparty/catch2/src/main/native/cpp/catch2/internal/catch_random_number_generator.cpp +++ b/thirdparty/catch2/src/main/native/cpp/catch2/internal/catch_random_number_generator.cpp @@ -52,7 +52,7 @@ namespace { SimplePcg32::result_type SimplePcg32::operator()() { // prepare the output value const uint32_t xorshifted = static_cast(((m_state >> 18u) ^ m_state) >> 27u); - const auto output = rotate_right(xorshifted, m_state >> 59u); + const auto output = rotate_right(xorshifted, static_cast(m_state >> 59u)); // advance state m_state = m_state * 6364136223846793005ULL + s_inc; diff --git a/thirdparty/catch2/src/main/native/cpp/catch2/internal/catch_result_type.cpp b/thirdparty/catch2/src/main/native/cpp/catch2/internal/catch_result_type.cpp deleted file mode 100644 index 6cedce71692..00000000000 --- a/thirdparty/catch2/src/main/native/cpp/catch2/internal/catch_result_type.cpp +++ /dev/null @@ -1,26 +0,0 @@ - -// Copyright Catch2 Authors -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE.txt or copy at -// https://www.boost.org/LICENSE_1_0.txt) - -// SPDX-License-Identifier: BSL-1.0 -#include - -namespace Catch { - - bool isOk( ResultWas::OfType resultType ) { - return ( resultType & ResultWas::FailureBit ) == 0; - } - bool isJustInfo( int flags ) { - return flags == ResultWas::Info; - } - - ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { - return static_cast( static_cast( lhs ) | static_cast( rhs ) ); - } - - bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; } - bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; } - -} // end namespace Catch diff --git a/thirdparty/catch2/src/main/native/cpp/catch2/internal/catch_run_context.cpp b/thirdparty/catch2/src/main/native/cpp/catch2/internal/catch_run_context.cpp index 8711352c30e..2a102fbeec7 100644 --- a/thirdparty/catch2/src/main/native/cpp/catch2/internal/catch_run_context.cpp +++ b/thirdparty/catch2/src/main/native/cpp/catch2/internal/catch_run_context.cpp @@ -170,6 +170,7 @@ namespace Catch { 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 ) { getCurrentMutableContext().setResultCapture( this ); @@ -236,15 +237,17 @@ namespace Catch { m_reporter->testCasePartialStarting(testInfo, testRuns); const auto beforeRunTotals = m_totals; - std::string oneRunCout, oneRunCerr; - runCurrentTest(oneRunCout, oneRunCerr); + runCurrentTest(); + std::string oneRunCout = m_outputRedirect->getStdout(); + std::string oneRunCerr = m_outputRedirect->getStderr(); + m_outputRedirect->clearBuffers(); redirectedCout += oneRunCout; redirectedCerr += oneRunCerr; const auto singleRunTotals = m_totals.delta(beforeRunTotals); auto statsForOneRun = TestCaseStats(testInfo, singleRunTotals, CATCH_MOVE(oneRunCout), CATCH_MOVE(oneRunCerr), aborting()); - m_reporter->testCasePartialEnded(statsForOneRun, testRuns); + ++testRuns; } while (!m_testCaseTracker->isSuccessfullyCompleted() && !aborting()); @@ -289,7 +292,10 @@ namespace Catch { m_lastAssertionPassed = true; } - m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals)); + { + auto _ = scopedDeactivate( *m_outputRedirect ); + m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ); + } if ( result.getResultType() != ResultWas::Warning ) { m_messageScopes.clear(); @@ -306,6 +312,7 @@ namespace Catch { } void RunContext::notifyAssertionStarted( AssertionInfo const& info ) { + auto _ = scopedDeactivate( *m_outputRedirect ); m_reporter->assertionStarting( info ); } @@ -324,7 +331,10 @@ namespace Catch { SectionInfo sectionInfo( sectionLineInfo, static_cast(sectionName) ); m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; - m_reporter->sectionStarting(sectionInfo); + { + auto _ = scopedDeactivate( *m_outputRedirect ); + m_reporter->sectionStarting( sectionInfo ); + } assertions = m_totals.assertions; @@ -384,7 +394,15 @@ namespace Catch { m_activeSections.pop_back(); } - m_reporter->sectionEnded(SectionStats(CATCH_MOVE(endInfo.sectionInfo), assertions, endInfo.durationInSeconds, missingAssertions)); + { + auto _ = scopedDeactivate( *m_outputRedirect ); + m_reporter->sectionEnded( + SectionStats( CATCH_MOVE( endInfo.sectionInfo ), + assertions, + endInfo.durationInSeconds, + missingAssertions ) ); + } + m_messages.clear(); m_messageScopes.clear(); } @@ -401,15 +419,19 @@ namespace Catch { } void RunContext::benchmarkPreparing( StringRef name ) { - m_reporter->benchmarkPreparing(name); + auto _ = scopedDeactivate( *m_outputRedirect ); + m_reporter->benchmarkPreparing( name ); } void RunContext::benchmarkStarting( BenchmarkInfo const& info ) { + auto _ = scopedDeactivate( *m_outputRedirect ); m_reporter->benchmarkStarting( info ); } void RunContext::benchmarkEnded( BenchmarkStats<> const& stats ) { + auto _ = scopedDeactivate( *m_outputRedirect ); m_reporter->benchmarkEnded( stats ); } void RunContext::benchmarkFailed( StringRef error ) { + auto _ = scopedDeactivate( *m_outputRedirect ); m_reporter->benchmarkFailed( error ); } @@ -440,8 +462,13 @@ 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 ); + // First notify reporter that bad things happened - m_reporter->fatalErrorEncountered(message); + m_reporter->fatalErrorEncountered( message ); // Don't rebuild the result -- the stringification itself can cause more fatal errors // Instead, fake a result data. @@ -468,7 +495,7 @@ namespace Catch { Counts assertions; assertions.failed = 1; SectionStats testCaseSectionStats(CATCH_MOVE(testCaseSection), assertions, 0, false); - m_reporter->sectionEnded(testCaseSectionStats); + m_reporter->sectionEnded( testCaseSectionStats ); auto const& testInfo = m_activeTestCase->getTestCaseInfo(); @@ -499,7 +526,7 @@ namespace Catch { return m_totals.assertions.failed >= static_cast(m_config->abortAfter()); } - void RunContext::runCurrentTest(std::string & redirectedCout, std::string & redirectedCerr) { + void RunContext::runCurrentTest() { auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name); m_reporter->sectionStarting(testCaseSection); @@ -510,18 +537,8 @@ namespace Catch { Timer timer; CATCH_TRY { - if (m_reporter->getPreferences().shouldRedirectStdOut) { -#if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) - RedirectedStreams redirectedStreams(redirectedCout, redirectedCerr); - - timer.start(); - invokeActiveTestCase(); -#else - OutputRedirect r(redirectedCout, redirectedCerr); - timer.start(); - invokeActiveTestCase(); -#endif - } else { + { + auto _ = scopedActivate( *m_outputRedirect ); timer.start(); invokeActiveTestCase(); } @@ -566,11 +583,12 @@ namespace Catch { void RunContext::handleUnfinishedSections() { // If sections ended prematurely due to an exception we stored their // infos here so we can tear them down outside the unwind process. - for (auto it = m_unfinishedSections.rbegin(), - itEnd = m_unfinishedSections.rend(); - it != itEnd; - ++it) - sectionEnded(CATCH_MOVE(*it)); + for ( auto it = m_unfinishedSections.rbegin(), + itEnd = m_unfinishedSections.rend(); + it != itEnd; + ++it ) { + sectionEnded( CATCH_MOVE( *it ) ); + } m_unfinishedSections.clear(); } @@ -614,13 +632,13 @@ namespace Catch { void RunContext::handleMessage( AssertionInfo const& info, ResultWas::OfType resultType, - StringRef message, + std::string&& message, AssertionReaction& reaction ) { m_lastAssertionInfo = info; AssertionResultData data( resultType, LazyExpression( false ) ); - data.message = static_cast(message); + data.message = CATCH_MOVE( message ); AssertionResult assertionResult{ m_lastAssertionInfo, CATCH_MOVE( data ) }; diff --git a/thirdparty/catch2/src/main/native/cpp/catch2/internal/catch_test_registry.cpp b/thirdparty/catch2/src/main/native/cpp/catch2/internal/catch_test_registry.cpp index 07e44617e18..d017c50e7ad 100644 --- a/thirdparty/catch2/src/main/native/cpp/catch2/internal/catch_test_registry.cpp +++ b/thirdparty/catch2/src/main/native/cpp/catch2/internal/catch_test_registry.cpp @@ -54,7 +54,7 @@ namespace Catch { TestType m_testAsFunction; public: - TestInvokerAsFunction( TestType testAsFunction ) noexcept: + constexpr TestInvokerAsFunction( TestType testAsFunction ) noexcept: m_testAsFunction( testAsFunction ) {} void invoke() const override { m_testAsFunction(); } diff --git a/thirdparty/catch2/src/main/native/cpp/catch2/internal/catch_xmlwriter.cpp b/thirdparty/catch2/src/main/native/cpp/catch2/internal/catch_xmlwriter.cpp index 6c1d45df489..ccf63a56e5c 100644 --- a/thirdparty/catch2/src/main/native/cpp/catch2/internal/catch_xmlwriter.cpp +++ b/thirdparty/catch2/src/main/native/cpp/catch2/internal/catch_xmlwriter.cpp @@ -53,36 +53,16 @@ namespace { os.flags(f); } - bool shouldNewline(XmlFormatting fmt) { + constexpr bool shouldNewline(XmlFormatting fmt) { return !!(static_cast>(fmt & XmlFormatting::Newline)); } - bool shouldIndent(XmlFormatting fmt) { + constexpr bool shouldIndent(XmlFormatting fmt) { return !!(static_cast>(fmt & XmlFormatting::Indent)); } } // anonymous namespace - XmlFormatting operator | (XmlFormatting lhs, XmlFormatting rhs) { - return static_cast( - static_cast>(lhs) | - static_cast>(rhs) - ); - } - - XmlFormatting operator & (XmlFormatting lhs, XmlFormatting rhs) { - return static_cast( - static_cast>(lhs) & - static_cast>(rhs) - ); - } - - - XmlEncode::XmlEncode( StringRef str, ForWhat forWhat ) - : m_str( str ), - m_forWhat( forWhat ) - {} - void XmlEncode::encodeTo( std::ostream& os ) const { // Apostrophe escaping not necessary if we always use " to write attributes // (see: http://www.w3.org/TR/xml/#syntax) diff --git a/thirdparty/catch2/src/main/native/cpp/catch2/reporters/catch_reporter_console.cpp b/thirdparty/catch2/src/main/native/cpp/catch2/reporters/catch_reporter_console.cpp index c5678548d57..9529f39aa30 100644 --- a/thirdparty/catch2/src/main/native/cpp/catch2/reporters/catch_reporter_console.cpp +++ b/thirdparty/catch2/src/main/native/cpp/catch2/reporters/catch_reporter_console.cpp @@ -214,7 +214,7 @@ struct RowBreak {}; struct OutputFlush {}; class Duration { - enum class Unit { + enum class Unit : uint8_t { Auto, Nanoseconds, Microseconds, @@ -286,7 +286,10 @@ class Duration { }; } // end anon namespace -enum class Justification { Left, Right }; +enum class Justification : uint8_t { + Left, + Right +}; struct ColumnInfo { std::string name; diff --git a/thirdparty/catch2/src/main/native/cpp/catch2/reporters/catch_reporter_junit.cpp b/thirdparty/catch2/src/main/native/cpp/catch2/reporters/catch_reporter_junit.cpp index 4589365ce83..27bdfe28f7e 100644 --- a/thirdparty/catch2/src/main/native/cpp/catch2/reporters/catch_reporter_junit.cpp +++ b/thirdparty/catch2/src/main/native/cpp/catch2/reporters/catch_reporter_junit.cpp @@ -88,7 +88,7 @@ namespace Catch { xml( m_stream ) { m_preferences.shouldRedirectStdOut = true; - m_preferences.shouldReportAllAssertions = true; + m_preferences.shouldReportAllAssertions = false; m_shouldStoreSuccesfulAssertions = false; } @@ -198,7 +198,7 @@ namespace Catch { if( !rootName.empty() ) name = rootName + '/' + name; - if( sectionNode.hasAnyAssertions() + if ( sectionNode.stats.assertions.total() > 0 || !sectionNode.stdOut.empty() || !sectionNode.stdErr.empty() ) { XmlWriter::ScopedElement e = xml.scopedElement( "testcase" ); diff --git a/thirdparty/catch2/src/main/native/cpp/catch2/reporters/catch_reporter_sonarqube.cpp b/thirdparty/catch2/src/main/native/cpp/catch2/reporters/catch_reporter_sonarqube.cpp index 9c391b1f4f2..2c3eb1cd79c 100644 --- a/thirdparty/catch2/src/main/native/cpp/catch2/reporters/catch_reporter_sonarqube.cpp +++ b/thirdparty/catch2/src/main/native/cpp/catch2/reporters/catch_reporter_sonarqube.cpp @@ -73,9 +73,9 @@ namespace Catch { if (!rootName.empty()) name = rootName + '/' + name; - if ( sectionNode.hasAnyAssertions() + if ( sectionNode.stats.assertions.total() > 0 || !sectionNode.stdOut.empty() - || !sectionNode.stdErr.empty() ) { + || !sectionNode.stdErr.empty() ) { XmlWriter::ScopedElement e = xml.scopedElement("testCase"); xml.writeAttribute("name"_sr, name); xml.writeAttribute("duration"_sr, static_cast(sectionNode.stats.durationInSeconds * 1000)); diff --git a/thirdparty/catch2/src/main/native/include/catch2/benchmark/catch_outlier_classification.hpp b/thirdparty/catch2/src/main/native/include/catch2/benchmark/catch_outlier_classification.hpp index e31d65d4a24..b9a11782a0d 100644 --- a/thirdparty/catch2/src/main/native/include/catch2/benchmark/catch_outlier_classification.hpp +++ b/thirdparty/catch2/src/main/native/include/catch2/benchmark/catch_outlier_classification.hpp @@ -19,7 +19,7 @@ namespace Catch { int high_mild = 0; // 1.5 to 3 times IQR above Q3 int high_severe = 0; // more than 3 times IQR above Q3 - int total() const { + constexpr int total() const { return low_severe + low_mild + high_mild + high_severe; } }; diff --git a/thirdparty/catch2/src/main/native/include/catch2/catch_all.hpp b/thirdparty/catch2/src/main/native/include/catch2/catch_all.hpp index f2cc8536590..57159955079 100644 --- a/thirdparty/catch2/src/main/native/include/catch2/catch_all.hpp +++ b/thirdparty/catch2/src/main/native/include/catch2/catch_all.hpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -47,7 +48,6 @@ #include #include #include -#include #include #include #include diff --git a/thirdparty/catch2/src/main/native/include/catch2/internal/catch_case_sensitive.hpp b/thirdparty/catch2/src/main/native/include/catch2/catch_case_sensitive.hpp similarity index 100% rename from thirdparty/catch2/src/main/native/include/catch2/internal/catch_case_sensitive.hpp rename to thirdparty/catch2/src/main/native/include/catch2/catch_case_sensitive.hpp diff --git a/thirdparty/catch2/src/main/native/include/catch2/catch_message.hpp b/thirdparty/catch2/src/main/native/include/catch2/catch_message.hpp index 05325ee8f57..0a738341c21 100644 --- a/thirdparty/catch2/src/main/native/include/catch2/catch_message.hpp +++ b/thirdparty/catch2/src/main/native/include/catch2/catch_message.hpp @@ -94,7 +94,7 @@ namespace Catch { do { \ Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::StringRef(), resultDisposition ); \ catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \ - INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + catchAssertionHandler.complete(); \ } while( false ) /////////////////////////////////////////////////////////////////////////////// diff --git a/thirdparty/catch2/src/main/native/include/catch2/catch_test_case_info.hpp b/thirdparty/catch2/src/main/native/include/catch2/catch_test_case_info.hpp index 00b393b2eed..3466660c0ac 100644 --- a/thirdparty/catch2/src/main/native/include/catch2/catch_test_case_info.hpp +++ b/thirdparty/catch2/src/main/native/include/catch2/catch_test_case_info.hpp @@ -109,22 +109,24 @@ namespace Catch { TestCaseInfo* m_info; ITestInvoker* m_invoker; public: - TestCaseHandle(TestCaseInfo* info, ITestInvoker* invoker) : + constexpr TestCaseHandle(TestCaseInfo* info, ITestInvoker* invoker) : m_info(info), m_invoker(invoker) {} - void prepareTestCase() const { + void prepareTestCase() const { m_invoker->prepareTestCase(); } - void tearDownTestCase() const { - m_invoker->tearDownTestCase(); + void tearDownTestCase() const { + m_invoker->tearDownTestCase(); } void invoke() const { m_invoker->invoke(); } - TestCaseInfo const& getTestCaseInfo() const; + constexpr TestCaseInfo const& getTestCaseInfo() const { + return *m_info; + } }; Detail::unique_ptr diff --git a/thirdparty/catch2/src/main/native/include/catch2/catch_translate_exception.hpp b/thirdparty/catch2/src/main/native/include/catch2/catch_translate_exception.hpp index 5a4dc5e376e..2bf8d36079c 100644 --- a/thirdparty/catch2/src/main/native/include/catch2/catch_translate_exception.hpp +++ b/thirdparty/catch2/src/main/native/include/catch2/catch_translate_exception.hpp @@ -25,7 +25,7 @@ namespace Catch { class ExceptionTranslator : public IExceptionTranslator { public: - ExceptionTranslator( std::string(*translateFunction)( T const& ) ) + constexpr ExceptionTranslator( std::string(*translateFunction)( T const& ) ) : m_translateFunction( translateFunction ) {} diff --git a/thirdparty/catch2/src/main/native/include/catch2/catch_user_config.hpp.in b/thirdparty/catch2/src/main/native/include/catch2/catch_user_config.hpp.in index 10d61937f1a..3acda68849e 100644 --- a/thirdparty/catch2/src/main/native/include/catch2/catch_user_config.hpp.in +++ b/thirdparty/catch2/src/main/native/include/catch2/catch_user_config.hpp.in @@ -178,6 +178,15 @@ #endif +#cmakedefine CATCH_CONFIG_USE_BUILTIN_CONSTANT_P +#cmakedefine CATCH_CONFIG_NO_USE_BUILTIN_CONSTANT_P + +#if defined( CATCH_CONFIG_USE_BUILTIN_CONSTANT_P ) && \ + defined( CATCH_CONFIG_NO_USE_BUILTIN_CONSTANT_P ) +# error Cannot force USE_BUILTIN_CONSTANT_P to both ON and OFF +#endif + + // ------ // Simple toggle defines // their value is never used and they cannot be overridden diff --git a/thirdparty/catch2/src/main/native/include/catch2/catch_version_macros.hpp b/thirdparty/catch2/src/main/native/include/catch2/catch_version_macros.hpp index b95580bd873..88b5d0d02bf 100644 --- a/thirdparty/catch2/src/main/native/include/catch2/catch_version_macros.hpp +++ b/thirdparty/catch2/src/main/native/include/catch2/catch_version_macros.hpp @@ -9,7 +9,7 @@ #define CATCH_VERSION_MACROS_HPP_INCLUDED #define CATCH_VERSION_MAJOR 3 -#define CATCH_VERSION_MINOR 6 -#define CATCH_VERSION_PATCH 0 +#define CATCH_VERSION_MINOR 7 +#define CATCH_VERSION_PATCH 1 #endif // CATCH_VERSION_MACROS_HPP_INCLUDED diff --git a/thirdparty/catch2/src/main/native/include/catch2/generators/catch_generators_range.hpp b/thirdparty/catch2/src/main/native/include/catch2/generators/catch_generators_range.hpp index b67c1590ee4..55d673c2369 100644 --- a/thirdparty/catch2/src/main/native/include/catch2/generators/catch_generators_range.hpp +++ b/thirdparty/catch2/src/main/native/include/catch2/generators/catch_generators_range.hpp @@ -91,7 +91,7 @@ class IteratorGenerator final : public IGenerator { template ::value_type> + typename ResultType = std::remove_const_t::value_type>> GeneratorWrapper from_range(InputIterator from, InputSentinel to) { return GeneratorWrapper(Catch::Detail::make_unique>(from, to)); } diff --git a/thirdparty/catch2/src/main/native/include/catch2/interfaces/catch_interfaces_capture.hpp b/thirdparty/catch2/src/main/native/include/catch2/interfaces/catch_interfaces_capture.hpp index a1876a4cad8..9e5431d2479 100644 --- a/thirdparty/catch2/src/main/native/include/catch2/interfaces/catch_interfaces_capture.hpp +++ b/thirdparty/catch2/src/main/native/include/catch2/interfaces/catch_interfaces_capture.hpp @@ -9,7 +9,6 @@ #define CATCH_INTERFACES_CAPTURE_HPP_INCLUDED #include -#include #include #include @@ -77,7 +76,7 @@ namespace Catch { virtual void handleMessage ( AssertionInfo const& info, ResultWas::OfType resultType, - StringRef message, + std::string&& message, AssertionReaction& reaction ) = 0; virtual void handleUnexpectedExceptionNotThrown ( AssertionInfo const& info, diff --git a/thirdparty/catch2/src/main/native/include/catch2/internal/catch_assertion_handler.hpp b/thirdparty/catch2/src/main/native/include/catch2/internal/catch_assertion_handler.hpp index 01dd7801d19..c71c6898fd0 100644 --- a/thirdparty/catch2/src/main/native/include/catch2/internal/catch_assertion_handler.hpp +++ b/thirdparty/catch2/src/main/native/include/catch2/internal/catch_assertion_handler.hpp @@ -42,12 +42,12 @@ namespace Catch { template - void handleExpr( ExprLhs const& expr ) { + constexpr void handleExpr( ExprLhs const& expr ) { handleExpr( expr.makeUnaryExpr() ); } void handleExpr( ITransientExpression const& expr ); - void handleMessage(ResultWas::OfType resultType, StringRef message); + void handleMessage(ResultWas::OfType resultType, std::string&& message); void handleExceptionThrownAsExpected(); void handleUnexpectedExceptionNotThrown(); diff --git a/thirdparty/catch2/src/main/native/include/catch2/internal/catch_compiler_capabilities.hpp b/thirdparty/catch2/src/main/native/include/catch2/internal/catch_compiler_capabilities.hpp index 7f09da51773..d544b00c04e 100644 --- a/thirdparty/catch2/src/main/native/include/catch2/internal/catch_compiler_capabilities.hpp +++ b/thirdparty/catch2/src/main/native/include/catch2/internal/catch_compiler_capabilities.hpp @@ -62,7 +62,7 @@ # define CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \ _Pragma( "GCC diagnostic ignored \"-Wshadow\"" ) -# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) +# define CATCH_INTERNAL_CONFIG_USE_BUILTIN_CONSTANT_P #endif @@ -86,35 +86,13 @@ // 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_CONFIG_USE_BUILTIN_CONSTANT_P # 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 -// like `std::string::~string` being called on an uninitialized value. -// -// For example, this code will likely segfault under IBM XL: -// ``` -// REQUIRE(std::string("12") + "34" == "1234") -// ``` -// -// Similarly, NVHPC's implementation of `__builtin_constant_p` has a bug which -// results in calls to the immediately evaluated lambda expressions to be -// reported as unevaluated lambdas. -// https://developer.nvidia.com/nvidia_bug/3321845. -// -// Therefore, `CATCH_INTERNAL_IGNORE_BUT_WARN` is not implemented. -# if !defined(__ibmxl__) && !defined(__CUDACC__) && !defined( __NVCOMPILER ) -# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) /* NOLINT(cppcoreguidelines-pro-type-vararg, hicpp-vararg) */ -# endif - - # define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") @@ -139,6 +117,27 @@ #endif // __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 +// like `std::string::~string` being called on an uninitialized value. +// +// For example, this code will likely segfault under IBM XL: +// ``` +// REQUIRE(std::string("12") + "34" == "1234") +// ``` +// +// Similarly, NVHPC's implementation of `__builtin_constant_p` has a bug which +// results in calls to the immediately evaluated lambda expressions to be +// reported as unevaluated lambdas. +// https://developer.nvidia.com/nvidia_bug/3321845. +// +// Therefore, `CATCH_INTERNAL_IGNORE_BUT_WARN` is not implemented. +#if defined( __ibmxl__ ) || defined( __CUDACC__ ) || defined( __NVCOMPILER ) +# define CATCH_INTERNAL_CONFIG_NO_USE_BUILTIN_CONSTANT_P +#endif + + //////////////////////////////////////////////////////////////////////////////// // We know some environments not to support full POSIX signals @@ -362,6 +361,22 @@ #endif +// The goal of this macro is to avoid evaluation of the arguments, but +// still have the compiler warn on problems inside... +#if defined( CATCH_INTERNAL_CONFIG_USE_BUILTIN_CONSTANT_P ) && \ + !defined( CATCH_INTERNAL_CONFIG_NO_USE_BUILTIN_CONSTANT_P ) && !defined(CATCH_CONFIG_USE_BUILTIN_CONSTANT_P) +#define CATCH_CONFIG_USE_BUILTIN_CONSTANT_P +#endif + +#if defined( CATCH_CONFIG_USE_BUILTIN_CONSTANT_P ) && \ + !defined( CATCH_CONFIG_NO_USE_BUILTIN_CONSTANT_P ) +# define CATCH_INTERNAL_IGNORE_BUT_WARN( ... ) \ + (void)__builtin_constant_p( __VA_ARGS__ ) /* NOLINT(cppcoreguidelines-pro-type-vararg, \ + hicpp-vararg) */ +#else +# define CATCH_INTERNAL_IGNORE_BUT_WARN( ... ) +#endif + // Even if we do not think the compiler has that warning, we still have // to provide a macro that can be used by the code. #if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION) @@ -398,13 +413,6 @@ # define CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS #endif - -// The goal of this macro is to avoid evaluation of the arguments, but -// still have the compiler warn on problems inside... -#if !defined(CATCH_INTERNAL_IGNORE_BUT_WARN) -# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) -#endif - #if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10) # undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS #elif defined(__clang__) && (__clang_major__ < 5) diff --git a/thirdparty/catch2/src/main/native/include/catch2/internal/catch_context.hpp b/thirdparty/catch2/src/main/native/include/catch2/internal/catch_context.hpp index 6ccb3b31894..4d8a5da1b6e 100644 --- a/thirdparty/catch2/src/main/native/include/catch2/internal/catch_context.hpp +++ b/thirdparty/catch2/src/main/native/include/catch2/internal/catch_context.hpp @@ -26,10 +26,15 @@ namespace Catch { friend void cleanUpContext(); public: - IResultCapture* getResultCapture() const { return m_resultCapture; } - IConfig const* getConfig() const { return m_config; } - void setResultCapture( IResultCapture* resultCapture ); - void setConfig( IConfig const* config ); + constexpr IResultCapture* getResultCapture() const { + return m_resultCapture; + } + constexpr IConfig const* getConfig() const { return m_config; } + constexpr void setResultCapture( IResultCapture* resultCapture ) { + m_resultCapture = resultCapture; + } + constexpr void setConfig( IConfig const* config ) { m_config = config; } + }; Context& getCurrentMutableContext(); diff --git a/thirdparty/catch2/src/main/native/include/catch2/internal/catch_decomposer.hpp b/thirdparty/catch2/src/main/native/include/catch2/internal/catch_decomposer.hpp index 7962c9ef08f..adce89f2a3e 100644 --- a/thirdparty/catch2/src/main/native/include/catch2/internal/catch_decomposer.hpp +++ b/thirdparty/catch2/src/main/native/include/catch2/internal/catch_decomposer.hpp @@ -157,6 +157,9 @@ namespace Catch { bool m_isBinaryExpression; bool m_result; + protected: + ~ITransientExpression() = default; + public: constexpr auto isBinaryExpression() const -> bool { return m_isBinaryExpression; } constexpr auto getResult() const -> bool { return m_result; } @@ -168,17 +171,13 @@ namespace Catch { m_result( result ) {} - ITransientExpression() = default; - ITransientExpression(ITransientExpression const&) = default; - ITransientExpression& operator=(ITransientExpression const&) = default; + constexpr ITransientExpression( ITransientExpression const& ) = default; + constexpr ITransientExpression& operator=( ITransientExpression const& ) = default; friend std::ostream& operator<<(std::ostream& out, ITransientExpression const& expr) { expr.streamReconstructedExpression(out); return out; } - - protected: - ~ITransientExpression() = default; }; void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ); diff --git a/thirdparty/catch2/src/main/native/include/catch2/internal/catch_is_permutation.hpp b/thirdparty/catch2/src/main/native/include/catch2/internal/catch_is_permutation.hpp index 708053d35c9..c77a6d3b434 100644 --- a/thirdparty/catch2/src/main/native/include/catch2/internal/catch_is_permutation.hpp +++ b/thirdparty/catch2/src/main/native/include/catch2/internal/catch_is_permutation.hpp @@ -18,6 +18,7 @@ namespace Catch { typename Sentinel, typename T, typename Comparator> + constexpr ForwardIter find_sentinel( ForwardIter start, Sentinel sentinel, T const& value, @@ -33,6 +34,7 @@ namespace Catch { typename Sentinel, typename T, typename Comparator> + constexpr std::ptrdiff_t count_sentinel( ForwardIter start, Sentinel sentinel, T const& value, @@ -46,6 +48,7 @@ namespace Catch { } template + constexpr std::enable_if_t::value, std::ptrdiff_t> sentinel_distance( ForwardIter iter, const Sentinel sentinel ) { @@ -58,8 +61,8 @@ namespace Catch { } template - std::ptrdiff_t sentinel_distance( ForwardIter first, - ForwardIter last ) { + constexpr std::ptrdiff_t sentinel_distance( ForwardIter first, + ForwardIter last ) { return std::distance( first, last ); } @@ -68,11 +71,11 @@ namespace Catch { typename ForwardIter2, typename Sentinel2, typename Comparator> - bool check_element_counts( ForwardIter1 first_1, - const Sentinel1 end_1, - ForwardIter2 first_2, - const Sentinel2 end_2, - Comparator cmp ) { + constexpr bool check_element_counts( ForwardIter1 first_1, + const Sentinel1 end_1, + ForwardIter2 first_2, + const Sentinel2 end_2, + Comparator cmp ) { auto cursor = first_1; while ( cursor != end_1 ) { if ( find_sentinel( first_1, cursor, *cursor, cmp ) == @@ -102,11 +105,11 @@ namespace Catch { typename ForwardIter2, typename Sentinel2, typename Comparator> - bool is_permutation( ForwardIter1 first_1, - const Sentinel1 end_1, - ForwardIter2 first_2, - const Sentinel2 end_2, - Comparator cmp ) { + constexpr bool is_permutation( ForwardIter1 first_1, + const Sentinel1 end_1, + ForwardIter2 first_2, + const Sentinel2 end_2, + Comparator cmp ) { // TODO: no optimization for stronger iterators, because we would also have to constrain on sentinel vs not sentinel types // TODO: Comparator has to be "both sides", e.g. a == b => b == a // This skips shared prefix of the two ranges diff --git a/thirdparty/catch2/src/main/native/include/catch2/internal/catch_lazy_expr.hpp b/thirdparty/catch2/src/main/native/include/catch2/internal/catch_lazy_expr.hpp index 36e0ac50020..c6ff2241119 100644 --- a/thirdparty/catch2/src/main/native/include/catch2/internal/catch_lazy_expr.hpp +++ b/thirdparty/catch2/src/main/native/include/catch2/internal/catch_lazy_expr.hpp @@ -22,13 +22,13 @@ namespace Catch { ITransientExpression const* m_transientExpression = nullptr; bool m_isNegated; public: - LazyExpression( bool isNegated ): + constexpr LazyExpression( bool isNegated ): m_isNegated(isNegated) {} - LazyExpression(LazyExpression const& other) = default; + constexpr LazyExpression(LazyExpression const& other) = default; LazyExpression& operator = ( LazyExpression const& ) = delete; - explicit operator bool() const { + constexpr explicit operator bool() const { return m_transientExpression != nullptr; } diff --git a/thirdparty/catch2/src/main/native/include/catch2/internal/catch_output_redirect.hpp b/thirdparty/catch2/src/main/native/include/catch2/internal/catch_output_redirect.hpp index dc89223b922..51b796baa1d 100644 --- a/thirdparty/catch2/src/main/native/include/catch2/internal/catch_output_redirect.hpp +++ b/thirdparty/catch2/src/main/native/include/catch2/internal/catch_output_redirect.hpp @@ -8,110 +8,69 @@ #ifndef CATCH_OUTPUT_REDIRECT_HPP_INCLUDED #define CATCH_OUTPUT_REDIRECT_HPP_INCLUDED -#include -#include -#include +#include -#include -#include +#include #include namespace Catch { - class RedirectedStream { - std::ostream& m_originalStream; - std::ostream& m_redirectionStream; - std::streambuf* m_prevBuf; - - public: - RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream ); - ~RedirectedStream(); - }; - - class RedirectedStdOut { - ReusableStringStream m_rss; - RedirectedStream m_cout; - public: - RedirectedStdOut(); - auto str() const -> std::string; - }; - - // StdErr has two constituent streams in C++, std::cerr and std::clog - // This means that we need to redirect 2 streams into 1 to keep proper - // order of writes - class RedirectedStdErr { - ReusableStringStream m_rss; - RedirectedStream m_cerr; - RedirectedStream m_clog; + class OutputRedirect { + bool m_redirectActive = false; + virtual void activateImpl() = 0; + virtual void deactivateImpl() = 0; public: - RedirectedStdErr(); - auto str() const -> std::string; + enum Kind { + //! No redirect (noop implementation) + None, + //! Redirect std::cout/std::cerr/std::clog streams internally + Streams, + //! Redirect the stdout/stderr file descriptors into files + FileDescriptors, + }; + + virtual ~OutputRedirect(); // = default; + + // TODO: Do we want to check that redirect is not active before retrieving the output? + virtual std::string getStdout() = 0; + virtual std::string getStderr() = 0; + virtual void clearBuffers() = 0; + bool isActive() const { return m_redirectActive; } + void activate() { + assert( !m_redirectActive && "redirect is already active" ); + activateImpl(); + m_redirectActive = true; + } + void deactivate() { + assert( m_redirectActive && "redirect is not active" ); + deactivateImpl(); + m_redirectActive = false; + } }; - class RedirectedStreams { - public: - RedirectedStreams(RedirectedStreams const&) = delete; - RedirectedStreams& operator=(RedirectedStreams const&) = delete; - RedirectedStreams(RedirectedStreams&&) = delete; - RedirectedStreams& operator=(RedirectedStreams&&) = delete; - - RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr); - ~RedirectedStreams(); - private: - std::string& m_redirectedCout; - std::string& m_redirectedCerr; - RedirectedStdOut m_redirectedStdOut; - RedirectedStdErr m_redirectedStdErr; - }; + bool isRedirectAvailable( OutputRedirect::Kind kind); + Detail::unique_ptr makeOutputRedirect( bool actual ); -#if defined(CATCH_CONFIG_NEW_CAPTURE) + class RedirectGuard { + OutputRedirect* m_redirect; + bool m_activate; + bool m_previouslyActive; + bool m_moved = false; - // Windows's implementation of std::tmpfile is terrible (it tries - // to create a file inside system folder, thus requiring elevated - // privileges for the binary), so we have to use tmpnam(_s) and - // create the file ourselves there. - class TempFile { public: - TempFile(TempFile const&) = delete; - TempFile& operator=(TempFile const&) = delete; - TempFile(TempFile&&) = delete; - TempFile& operator=(TempFile&&) = delete; - - TempFile(); - ~TempFile(); - - std::FILE* getFile(); - std::string getContents(); - - private: - std::FILE* m_file = nullptr; - #if defined(_MSC_VER) - char m_buffer[L_tmpnam] = { 0 }; - #endif - }; + RedirectGuard( bool activate, OutputRedirect& redirectImpl ); + ~RedirectGuard() noexcept( false ); + RedirectGuard( RedirectGuard const& ) = delete; + RedirectGuard& operator=( RedirectGuard const& ) = delete; - class OutputRedirect { - public: - OutputRedirect(OutputRedirect const&) = delete; - OutputRedirect& operator=(OutputRedirect const&) = delete; - OutputRedirect(OutputRedirect&&) = delete; - OutputRedirect& operator=(OutputRedirect&&) = delete; - - - OutputRedirect(std::string& stdout_dest, std::string& stderr_dest); - ~OutputRedirect(); - - private: - int m_originalStdout = -1; - int m_originalStderr = -1; - TempFile m_stdoutFile; - TempFile m_stderrFile; - std::string& m_stdoutDest; - std::string& m_stderrDest; + // C++14 needs move-able guards to return them from functions + RedirectGuard( RedirectGuard&& rhs ) noexcept; + RedirectGuard& operator=( RedirectGuard&& rhs ) noexcept; }; -#endif + RedirectGuard scopedActivate( OutputRedirect& redirectImpl ); + RedirectGuard scopedDeactivate( OutputRedirect& redirectImpl ); } // end namespace Catch diff --git a/thirdparty/catch2/src/main/native/include/catch2/internal/catch_random_integer_helpers.hpp b/thirdparty/catch2/src/main/native/include/catch2/internal/catch_random_integer_helpers.hpp index cb5e004fb75..be4bbe9203b 100644 --- a/thirdparty/catch2/src/main/native/include/catch2/internal/catch_random_integer_helpers.hpp +++ b/thirdparty/catch2/src/main/native/include/catch2/internal/catch_random_integer_helpers.hpp @@ -69,7 +69,7 @@ namespace Catch { struct ExtendedMultResult { T upper; T lower; - bool operator==( ExtendedMultResult const& rhs ) const { + constexpr bool operator==( ExtendedMultResult const& rhs ) const { return upper == rhs.upper && lower == rhs.lower; } }; @@ -187,6 +187,7 @@ namespace Catch { * get by simple casting ([0, ..., INT_MAX, INT_MIN, ..., -1]) */ template + constexpr std::enable_if_t::value, UnsignedType> transposeToNaturalOrder( UnsignedType in ) { static_assert( @@ -207,6 +208,7 @@ namespace Catch { template + constexpr std::enable_if_t::value, UnsignedType> transposeToNaturalOrder(UnsignedType in) { static_assert( diff --git a/thirdparty/catch2/src/main/native/include/catch2/internal/catch_result_type.hpp b/thirdparty/catch2/src/main/native/include/catch2/internal/catch_result_type.hpp index e66afaff005..69a6ef14139 100644 --- a/thirdparty/catch2/src/main/native/include/catch2/internal/catch_result_type.hpp +++ b/thirdparty/catch2/src/main/native/include/catch2/internal/catch_result_type.hpp @@ -33,8 +33,10 @@ namespace Catch { }; }; - bool isOk( ResultWas::OfType resultType ); - bool isJustInfo( int flags ); + constexpr bool isOk( ResultWas::OfType resultType ) { + return ( resultType & ResultWas::FailureBit ) == 0; + } + constexpr bool isJustInfo( int flags ) { return flags == ResultWas::Info; } // ResultDisposition::Flags enum @@ -46,11 +48,18 @@ namespace Catch { SuppressFail = 0x08 // Failures are reported but do not fail the test }; }; - ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ); - - bool shouldContinueOnFailure( int flags ); - inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; } - bool shouldSuppressFailure( int flags ); + constexpr ResultDisposition::Flags operator|( ResultDisposition::Flags lhs, + ResultDisposition::Flags rhs ) { + return static_cast( static_cast( lhs ) | + static_cast( rhs ) ); + } + + constexpr bool isFalseTest( int flags ) { + return ( flags & ResultDisposition::FalseTest ) != 0; + } + constexpr bool shouldSuppressFailure( int flags ) { + return ( flags & ResultDisposition::SuppressFail ) != 0; + } } // end namespace Catch diff --git a/thirdparty/catch2/src/main/native/include/catch2/internal/catch_run_context.hpp b/thirdparty/catch2/src/main/native/include/catch2/internal/catch_run_context.hpp index c749304d3b5..c66fec0ce93 100644 --- a/thirdparty/catch2/src/main/native/include/catch2/internal/catch_run_context.hpp +++ b/thirdparty/catch2/src/main/native/include/catch2/internal/catch_run_context.hpp @@ -29,6 +29,7 @@ namespace Catch { class IConfig; class IEventListener; using IEventListenerPtr = Detail::unique_ptr; + class OutputRedirect; /////////////////////////////////////////////////////////////////////////// @@ -54,7 +55,7 @@ namespace Catch { void handleMessage ( AssertionInfo const& info, ResultWas::OfType resultType, - StringRef message, + std::string&& message, AssertionReaction& reaction ) override; void handleUnexpectedExceptionNotThrown ( AssertionInfo const& info, @@ -115,7 +116,7 @@ namespace Catch { private: - void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ); + void runCurrentTest(); void invokeActiveTestCase(); void resetAssertionInfo(); @@ -148,6 +149,7 @@ namespace Catch { std::vector m_unfinishedSections; std::vector m_activeSections; TrackerContext m_trackerContext; + Detail::unique_ptr m_outputRedirect; FatalConditionHandler m_fatalConditionhandler; bool m_lastAssertionPassed = false; bool m_shouldReportUnexpected = true; diff --git a/thirdparty/catch2/src/main/native/include/catch2/internal/catch_test_macro_impl.hpp b/thirdparty/catch2/src/main/native/include/catch2/internal/catch_test_macro_impl.hpp index 0d95650fb52..ccd5bb3578a 100644 --- a/thirdparty/catch2/src/main/native/include/catch2/internal/catch_test_macro_impl.hpp +++ b/thirdparty/catch2/src/main/native/include/catch2/internal/catch_test_macro_impl.hpp @@ -38,8 +38,6 @@ #endif -#define INTERNAL_CATCH_REACT( handler ) handler.complete(); - /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \ do { /* NOLINT(bugprone-infinite-loop) */ \ @@ -52,7 +50,7 @@ catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); /* NOLINT(bugprone-chained-comparison) */ \ CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ - INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + catchAssertionHandler.complete(); \ } while( (void)0, (false) && static_cast( !!(__VA_ARGS__) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. @@ -80,7 +78,7 @@ catch( ... ) { \ catchAssertionHandler.handleUnexpectedInflightException(); \ } \ - INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + catchAssertionHandler.complete(); \ } while( false ) /////////////////////////////////////////////////////////////////////////////// @@ -101,7 +99,7 @@ } \ else \ catchAssertionHandler.handleThrowingCallSkipped(); \ - INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + catchAssertionHandler.complete(); \ } while( false ) /////////////////////////////////////////////////////////////////////////////// @@ -125,7 +123,7 @@ } \ else \ catchAssertionHandler.handleThrowingCallSkipped(); \ - INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + catchAssertionHandler.complete(); \ } while( false ) @@ -149,7 +147,7 @@ } \ else \ catchAssertionHandler.handleThrowingCallSkipped(); \ - INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + catchAssertionHandler.complete(); \ } while( false ) #endif // CATCH_CONFIG_DISABLE diff --git a/thirdparty/catch2/src/main/native/include/catch2/internal/catch_test_registry.hpp b/thirdparty/catch2/src/main/native/include/catch2/internal/catch_test_registry.hpp index e275f2b9f21..5c3a226d637 100644 --- a/thirdparty/catch2/src/main/native/include/catch2/internal/catch_test_registry.hpp +++ b/thirdparty/catch2/src/main/native/include/catch2/internal/catch_test_registry.hpp @@ -32,7 +32,8 @@ template class TestInvokerAsMethod : public ITestInvoker { void (C::*m_testAsMethod)(); public: - TestInvokerAsMethod( void (C::*testAsMethod)() ) noexcept : m_testAsMethod( testAsMethod ) {} + constexpr TestInvokerAsMethod( void ( C::*testAsMethod )() ) noexcept: + m_testAsMethod( testAsMethod ) {} void invoke() const override { C obj; @@ -53,7 +54,8 @@ class TestInvokerFixture : public ITestInvoker { Detail::unique_ptr m_fixture = nullptr; public: - TestInvokerFixture( void ( C::*testAsMethod )() const) noexcept : m_testAsMethod( testAsMethod ) {} + constexpr TestInvokerFixture( void ( C::*testAsMethod )() const ) noexcept: + m_testAsMethod( testAsMethod ) {} void prepareTestCase() override { m_fixture = Detail::make_unique(); diff --git a/thirdparty/catch2/src/main/native/include/catch2/internal/catch_uniform_integer_distribution.hpp b/thirdparty/catch2/src/main/native/include/catch2/internal/catch_uniform_integer_distribution.hpp index 3332489adca..799a93e2697 100644 --- a/thirdparty/catch2/src/main/native/include/catch2/internal/catch_uniform_integer_distribution.hpp +++ b/thirdparty/catch2/src/main/native/include/catch2/internal/catch_uniform_integer_distribution.hpp @@ -48,24 +48,24 @@ class uniform_integer_distribution { // distribution will be reused many times and this is an optimization. UnsignedIntegerType m_rejection_threshold = 0; - UnsignedIntegerType computeDistance(IntegerType a, IntegerType b) const { + static constexpr UnsignedIntegerType computeDistance(IntegerType a, IntegerType b) { // This overflows and returns 0 if a == 0 and b == TYPE_MAX. // We handle that later when generating the number. return transposeTo(b) - transposeTo(a) + 1; } - static UnsignedIntegerType computeRejectionThreshold(UnsignedIntegerType ab_distance) { + static constexpr UnsignedIntegerType computeRejectionThreshold(UnsignedIntegerType ab_distance) { // distance == 0 means that we will return all possible values from // the type's range, and that we shouldn't reject anything. if ( ab_distance == 0 ) { return 0; } return ( ~ab_distance + 1 ) % ab_distance; } - static UnsignedIntegerType transposeTo(IntegerType in) { + static constexpr UnsignedIntegerType transposeTo(IntegerType in) { return Detail::transposeToNaturalOrder( static_cast( in ) ); } - static IntegerType transposeBack(UnsignedIntegerType in) { + static constexpr IntegerType transposeBack(UnsignedIntegerType in) { return static_cast( Detail::transposeToNaturalOrder(in) ); } @@ -73,7 +73,7 @@ class uniform_integer_distribution { public: using result_type = IntegerType; - uniform_integer_distribution( IntegerType a, IntegerType b ): + constexpr uniform_integer_distribution( IntegerType a, IntegerType b ): m_a( transposeTo(a) ), m_ab_distance( computeDistance(a, b) ), m_rejection_threshold( computeRejectionThreshold(m_ab_distance) ) { @@ -81,7 +81,7 @@ class uniform_integer_distribution { } template - result_type operator()( Generator& g ) { + constexpr result_type operator()( Generator& g ) { // All possible values of result_type are valid. if ( m_ab_distance == 0 ) { return transposeBack( Detail::fillBitsFrom( g ) ); @@ -99,8 +99,8 @@ class uniform_integer_distribution { return transposeBack(m_a + emul.upper); } - result_type a() const { return transposeBack(m_a); } - result_type b() const { return transposeBack(m_ab_distance + m_a - 1); } + constexpr result_type a() const { return transposeBack(m_a); } + constexpr result_type b() const { return transposeBack(m_ab_distance + m_a - 1); } }; } // end namespace Catch diff --git a/thirdparty/catch2/src/main/native/include/catch2/internal/catch_wildcard_pattern.hpp b/thirdparty/catch2/src/main/native/include/catch2/internal/catch_wildcard_pattern.hpp index 72479ba8784..4f4108597da 100644 --- a/thirdparty/catch2/src/main/native/include/catch2/internal/catch_wildcard_pattern.hpp +++ b/thirdparty/catch2/src/main/native/include/catch2/internal/catch_wildcard_pattern.hpp @@ -8,7 +8,7 @@ #ifndef CATCH_WILDCARD_PATTERN_HPP_INCLUDED #define CATCH_WILDCARD_PATTERN_HPP_INCLUDED -#include +#include #include diff --git a/thirdparty/catch2/src/main/native/include/catch2/internal/catch_xmlwriter.hpp b/thirdparty/catch2/src/main/native/include/catch2/internal/catch_xmlwriter.hpp index ec55f3c4684..22b42c5c8ff 100644 --- a/thirdparty/catch2/src/main/native/include/catch2/internal/catch_xmlwriter.hpp +++ b/thirdparty/catch2/src/main/native/include/catch2/internal/catch_xmlwriter.hpp @@ -13,16 +13,25 @@ #include #include +#include namespace Catch { - enum class XmlFormatting { + enum class XmlFormatting : std::uint8_t { None = 0x00, Indent = 0x01, Newline = 0x02, }; - XmlFormatting operator | (XmlFormatting lhs, XmlFormatting rhs); - XmlFormatting operator & (XmlFormatting lhs, XmlFormatting rhs); + constexpr XmlFormatting operator|( XmlFormatting lhs, XmlFormatting rhs ) { + return static_cast( static_cast( lhs ) | + static_cast( rhs ) ); + } + + constexpr XmlFormatting operator&( XmlFormatting lhs, XmlFormatting rhs ) { + return static_cast( static_cast( lhs ) & + static_cast( rhs ) ); + } + /** * Helper for XML-encoding text (escaping angle brackets, quotes, etc) @@ -34,7 +43,9 @@ namespace Catch { public: enum ForWhat { ForTextNodes, ForAttributes }; - XmlEncode( StringRef str, ForWhat forWhat = ForTextNodes ); + constexpr XmlEncode( StringRef str, ForWhat forWhat = ForTextNodes ): + m_str( str ), m_forWhat( forWhat ) {} + void encodeTo( std::ostream& os ) const; diff --git a/thirdparty/catch2/src/main/native/include/catch2/matchers/catch_matchers_range_equals.hpp b/thirdparty/catch2/src/main/native/include/catch2/matchers/catch_matchers_range_equals.hpp index 95b781a430f..8130f604fdd 100644 --- a/thirdparty/catch2/src/main/native/include/catch2/matchers/catch_matchers_range_equals.hpp +++ b/thirdparty/catch2/src/main/native/include/catch2/matchers/catch_matchers_range_equals.hpp @@ -28,12 +28,14 @@ namespace Catch { public: template + constexpr RangeEqualsMatcher( TargetRangeLike2&& range, Equality2&& predicate ): m_desired( CATCH_FORWARD( range ) ), m_predicate( CATCH_FORWARD( predicate ) ) {} template + constexpr bool match( RangeLike&& rng ) const { auto rng_start = begin( rng ); const auto rng_end = end( rng ); @@ -66,12 +68,14 @@ namespace Catch { public: template + constexpr UnorderedRangeEqualsMatcher( TargetRangeLike2&& range, Equality2&& predicate ): m_desired( CATCH_FORWARD( range ) ), m_predicate( CATCH_FORWARD( predicate ) ) {} template + constexpr bool match( RangeLike&& rng ) const { using std::begin; using std::end; @@ -92,51 +96,64 @@ namespace Catch { * Creates a matcher that checks if all elements in a range are equal * to all elements in another range. * - * Uses `std::equal_to` to do the comparison + * Uses the provided predicate `predicate` to do the comparisons + * (defaulting to `std::equal_to`) */ - template - std::enable_if_t::value, - RangeEqualsMatcher>> - RangeEquals( RangeLike&& range ) { - return { CATCH_FORWARD( range ), std::equal_to<>{} }; + template {} )> + constexpr + RangeEqualsMatcher + RangeEquals( RangeLike&& range, + Equality&& predicate = std::equal_to<>{} ) { + return { CATCH_FORWARD( range ), CATCH_FORWARD( predicate ) }; } /** * Creates a matcher that checks if all elements in a range are equal - * to all elements in another range. + * to all elements in an initializer list. * - * Uses to provided predicate `predicate` to do the comparisons + * Uses the provided predicate `predicate` to do the comparisons + * (defaulting to `std::equal_to`) */ - template - RangeEqualsMatcher - RangeEquals( RangeLike&& range, Equality&& predicate ) { - return { CATCH_FORWARD( range ), CATCH_FORWARD( predicate ) }; + template {} )> + constexpr + RangeEqualsMatcher, Equality> + RangeEquals( std::initializer_list range, + Equality&& predicate = std::equal_to<>{} ) { + return { range, CATCH_FORWARD( predicate ) }; } /** * Creates a matcher that checks if all elements in a range are equal - * to all elements in another range, in some permutation + * to all elements in another range, in some permutation. * - * Uses `std::equal_to` to do the comparison + * Uses the provided predicate `predicate` to do the comparisons + * (defaulting to `std::equal_to`) */ - template - std::enable_if_t< - !Detail::is_matcher::value, - UnorderedRangeEqualsMatcher>> - UnorderedRangeEquals( RangeLike&& range ) { - return { CATCH_FORWARD( range ), std::equal_to<>{} }; + template {} )> + constexpr + UnorderedRangeEqualsMatcher + UnorderedRangeEquals( RangeLike&& range, + Equality&& predicate = std::equal_to<>{} ) { + return { CATCH_FORWARD( range ), CATCH_FORWARD( predicate ) }; } /** * Creates a matcher that checks if all elements in a range are equal - * to all elements in another range, in some permutation. + * to all elements in an initializer list, in some permutation. * - * Uses to provided predicate `predicate` to do the comparisons + * Uses the provided predicate `predicate` to do the comparisons + * (defaulting to `std::equal_to`) */ - template - UnorderedRangeEqualsMatcher - UnorderedRangeEquals( RangeLike&& range, Equality&& predicate ) { - return { CATCH_FORWARD( range ), CATCH_FORWARD( predicate ) }; + template {} )> + constexpr + UnorderedRangeEqualsMatcher, Equality> + UnorderedRangeEquals( std::initializer_list range, + Equality&& predicate = std::equal_to<>{} ) { + return { range, CATCH_FORWARD( predicate ) }; } } // namespace Matchers } // namespace Catch diff --git a/thirdparty/catch2/src/main/native/include/catch2/matchers/catch_matchers_string.hpp b/thirdparty/catch2/src/main/native/include/catch2/matchers/catch_matchers_string.hpp index 718022e31c8..61a385d0aff 100644 --- a/thirdparty/catch2/src/main/native/include/catch2/matchers/catch_matchers_string.hpp +++ b/thirdparty/catch2/src/main/native/include/catch2/matchers/catch_matchers_string.hpp @@ -8,9 +8,9 @@ #ifndef CATCH_MATCHERS_STRING_HPP_INCLUDED #define CATCH_MATCHERS_STRING_HPP_INCLUDED -#include -#include #include +#include +#include #include diff --git a/thirdparty/catch2/src/main/native/include/catch2/matchers/internal/catch_matchers_impl.hpp b/thirdparty/catch2/src/main/native/include/catch2/matchers/internal/catch_matchers_impl.hpp index 8d013fa29fc..24a3f8b6903 100644 --- a/thirdparty/catch2/src/main/native/include/catch2/matchers/internal/catch_matchers_impl.hpp +++ b/thirdparty/catch2/src/main/native/include/catch2/matchers/internal/catch_matchers_impl.hpp @@ -33,7 +33,7 @@ namespace Catch { ArgT && m_arg; MatcherT const& m_matcher; public: - MatchExpr( ArgT && arg, MatcherT const& matcher ) + constexpr MatchExpr( ArgT && arg, MatcherT const& matcher ) : ITransientExpression{ true, matcher.match( arg ) }, // not forwarding arg here on purpose m_arg( CATCH_FORWARD(arg) ), m_matcher( matcher ) @@ -63,7 +63,8 @@ namespace Catch { void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher ); template - auto makeMatchExpr( ArgT && arg, MatcherT const& matcher ) -> MatchExpr { + constexpr MatchExpr + makeMatchExpr( ArgT&& arg, MatcherT const& matcher ) { return MatchExpr( CATCH_FORWARD(arg), matcher ); } @@ -77,7 +78,7 @@ namespace Catch { INTERNAL_CATCH_TRY { \ catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher ) ); \ } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ - INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + catchAssertionHandler.complete(); \ } while( false ) @@ -87,7 +88,10 @@ namespace Catch { Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ if( catchAssertionHandler.allowThrows() ) \ try { \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \ static_cast(__VA_ARGS__ ); \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ } \ catch( exceptionType const& ex ) { \ @@ -98,7 +102,7 @@ namespace Catch { } \ else \ catchAssertionHandler.handleThrowingCallSkipped(); \ - INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + catchAssertionHandler.complete(); \ } while( false ) diff --git a/thirdparty/catch2/src/main/native/include/catch2/reporters/catch_reporter_sonarqube.hpp b/thirdparty/catch2/src/main/native/include/catch2/reporters/catch_reporter_sonarqube.hpp index 906578bb5b8..509f411e3d0 100644 --- a/thirdparty/catch2/src/main/native/include/catch2/reporters/catch_reporter_sonarqube.hpp +++ b/thirdparty/catch2/src/main/native/include/catch2/reporters/catch_reporter_sonarqube.hpp @@ -21,7 +21,7 @@ namespace Catch { : CumulativeReporterBase(CATCH_MOVE(config)) , xml(m_stream) { m_preferences.shouldRedirectStdOut = true; - m_preferences.shouldReportAllAssertions = true; + m_preferences.shouldReportAllAssertions = false; m_shouldStoreSuccesfulAssertions = false; } diff --git a/upstream_utils/catch2.py b/upstream_utils/catch2.py index adddbf8b84f..f6183612eae 100755 --- a/upstream_utils/catch2.py +++ b/upstream_utils/catch2.py @@ -52,7 +52,7 @@ def copy_upstream_src(wpilib_root): def main(): name = "catch2" url = "https://github.com/catchorg/Catch2.git" - tag = "8898cc61601af6cdd5b4548dd91ccf70ed67f3c2" + tag = "0321d2fce328b5e2ad106a8230ff20e0d5bf5501" patch_options = { "ignore_whitespace": True,