Author: Mason Wright
Email:
[email protected]
Date: Fri, 4 Jul 2025 18:13:36 -0600
include/catch_amalgamated.hpp
aae562ac1350480e4889aabb35899f776c5b59e9
Fixed issue with parsing only pseudo-classes
Clone
-
.gitignore
-
Makefile
-
config
-
include/catch_amalgamated.cpp
-
include/catch_amalgamated.hpp
-
include/grim.h
-
include/parser.h
-
index.html
-
main.cc
-
src/adapter.cc
-
src/events.cc
M
src/grim.cc
-
src/parser.cc
-
style.css
-
tests/css_selector.cc
-
tests/html_node.cc
-
tests/html_parser.cc
Commits
b966b2a517365074e5c381dbdea05b3221dc0198
e840f1eeb0ae26af69e1ae146ea9938e28e9f1af
e4e05418a640eaed08cd1ec7cd8644eb1dbcca50
4e01ba8ad2c3361fa4be3d896288020948b58b5e
aae562ac1350480e4889aabb35899f776c5b59e9
6c3ae0e31eb0893f20e3872117f92cc6b9a942af
350e7d88bb2feb9db00c6e032cc6623f215b7adf
95e6c70d23e99ffcf70e5bbe12503496e5d8f232
e188783659b9bc3b9993a647e93ed110e7f41db6
5e4c38ff3c212cdd9881427ef3f8c2706539a190
e50ea9e1356a74af18fdd171337ef9dc931e1f4e
8f2e83556d12aaebe8e8597ea6923804b0eb7a43
1627c585128af263181053ab2cf1a4cdcd14ee21
def3513f75b325464ad88a33c741c4ca80572b77
a21501590980a905fa9b902897d700a42a08b7f0
56074a6bfe4498d092f3a227297c8c20e2bb962c
d9cf1485b7ae0614130494f0e73237921323b9a1
80f04b134ae32ad8a9d526007b33dd02f6600f05
23d6c65f9368d3c622a55a3068a6b2f1efa0c8d4
09c195df02536b6a796bd648fce9669397b96109
f2b5c8202fbc904e2ed78260e3fdbd55164799d2
4bfba076120f389994fc46a98e8b7a2622314400
e36ac5417e10ee9b9f94f340e1ccf28afc5705ea
d00dc89a86dd7e2fcfd4618bc3a1c8cfba9e3c3d
d9eef16adaf292f3748db5fb5aa98463de10d712
18ff2ec1bfc1cf9fcd17c1acb05c3b41f8f0ed83
9e7fd2980d723437ea621b78d395fa72ca3f4922
Diff
// 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 // Catch v3.5.4 // Generated: 2024-04-10 12:03:45.785902 // ---------------------------------------------------------- // This file is an amalgamation of multiple different files. // You probably shouldn't edit it directly. // ---------------------------------------------------------- #ifndef CATCH_AMALGAMATED_HPP_INCLUDED #define CATCH_AMALGAMATED_HPP_INCLUDED /** \file * This is a convenience header for Catch2. It includes **all** of Catch2 headers. * * Generally the Catch2 users should use specific includes they need, * but this header can be used instead for ease-of-experimentation, or * just plain convenience, at the cost of (significantly) increased * compilation times. * * When a new header is added to either the top level folder, or to the * corresponding internal subfolder, it should be added here. Headers * added to the various subparts (e.g. matchers, generators, etc...), * should go their respective catch-all headers. */ #ifndef CATCH_ALL_HPP_INCLUDED #define CATCH_ALL_HPP_INCLUDED /** \file * This is a convenience header for Catch2's benchmarking. It includes * **all** of Catch2 headers related to benchmarking. * * Generally the Catch2 users should use specific includes they need, * but this header can be used instead for ease-of-experimentation, or * just plain convenience, at the cost of (significantly) increased * compilation times. * * When a new header is added to either the `benchmark` folder, or to * the corresponding internal (detail) subfolder, it should be added here. */ #ifndef CATCH_BENCHMARK_ALL_HPP_INCLUDED #define CATCH_BENCHMARK_ALL_HPP_INCLUDED // Adapted from donated nonius code. #ifndef CATCH_BENCHMARK_HPP_INCLUDED #define CATCH_BENCHMARK_HPP_INCLUDED #ifndef CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED #define CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED // Detect a number of compiler features - by compiler // The following features are defined: // // CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported? // CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported? // CATCH_CONFIG_DISABLE_EXCEPTIONS : Are exceptions enabled? // **************** // Note to maintainers: if new toggles are added please document them // in configuration.md, too // **************** // In general each macro has a _NO_
form // (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature. // Many features, at point of detection, define an _INTERNAL_ macro, so they // can be combined, en-mass, with the _NO_ forms later. #ifndef CATCH_PLATFORM_HPP_INCLUDED #define CATCH_PLATFORM_HPP_INCLUDED // See e.g.: // https://opensource.apple.com/source/CarbonHeaders/CarbonHeaders-18.1/TargetConditionals.h.auto.html #ifdef __APPLE__ # ifndef __has_extension # define __has_extension(x) 0 # endif # include
# if (defined(TARGET_OS_OSX) && TARGET_OS_OSX == 1) || \ (defined(TARGET_OS_MAC) && TARGET_OS_MAC == 1) # define CATCH_PLATFORM_MAC # elif (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1) # define CATCH_PLATFORM_IPHONE # endif #elif defined(linux) || defined(__linux) || defined(__linux__) # define CATCH_PLATFORM_LINUX #elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__) # define CATCH_PLATFORM_WINDOWS # if defined( WINAPI_FAMILY ) && ( WINAPI_FAMILY == WINAPI_FAMILY_APP ) # define CATCH_PLATFORM_WINDOWS_UWP # endif #elif defined(__ORBIS__) || defined(__PROSPERO__) # define CATCH_PLATFORM_PLAYSTATION #endif #endif // CATCH_PLATFORM_HPP_INCLUDED #ifdef __cplusplus # if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) # define CATCH_CPP17_OR_GREATER # endif # if (__cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) # define CATCH_CPP20_OR_GREATER # endif #endif // Only GCC compiler should be used in this block, so other compilers trying to // mask themselves as GCC should be ignored. #if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__) && !defined(__LCC__) && !defined(__NVCOMPILER) # define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" ) # define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" ) // This only works on GCC 9+. so we have to also add a global suppression of Wparentheses // for older versions of GCC. # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ _Pragma( "GCC diagnostic ignored \"-Wparentheses\"" ) # define CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT \ _Pragma( "GCC diagnostic ignored \"-Wunused-result\"" ) # define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ _Pragma( "GCC diagnostic ignored \"-Wunused-variable\"" ) # define CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \ _Pragma( "GCC diagnostic ignored \"-Wuseless-cast\"" ) # define CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \ _Pragma( "GCC diagnostic ignored \"-Wshadow\"" ) # define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) #endif #if defined(__NVCOMPILER) # define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "diag push" ) # define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "diag pop" ) # define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS _Pragma( "diag_suppress declared_but_not_referenced" ) #endif #if defined(__CUDACC__) && !defined(__clang__) # ifdef __NVCC_DIAG_PRAGMA_SUPPORT__ // New pragmas introduced in CUDA 11.5+ # 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" ) # else # define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS _Pragma( "diag_suppress 177" ) # endif #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 // 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\"") # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) # define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" ) # define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ _Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" ) # define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ _Pragma( "clang diagnostic ignored \"-Wunused-template\"" ) # define CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS \ _Pragma( "clang diagnostic ignored \"-Wcomma\"" ) # define CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \ _Pragma( "clang diagnostic ignored \"-Wshadow\"" ) #endif // __clang__ //////////////////////////////////////////////////////////////////////////////// // We know some environments not to support full POSIX signals #if defined( CATCH_PLATFORM_WINDOWS ) || \ defined( CATCH_PLATFORM_PLAYSTATION ) || \ defined( __CYGWIN__ ) || \ defined( __QNX__ ) || \ defined( __EMSCRIPTEN__ ) || \ defined( __DJGPP__ ) || \ defined( __OS400__ ) # define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS #else # define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS #endif //////////////////////////////////////////////////////////////////////////////// // Assume that some platforms do not support getenv. #if defined( CATCH_PLATFORM_WINDOWS_UWP ) || \ defined( CATCH_PLATFORM_PLAYSTATION ) || \ defined( _GAMING_XBOX ) # define CATCH_INTERNAL_CONFIG_NO_GETENV #else # define CATCH_INTERNAL_CONFIG_GETENV #endif //////////////////////////////////////////////////////////////////////////////// // Android somehow still does not support std::to_string #if defined(__ANDROID__) # define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING #endif //////////////////////////////////////////////////////////////////////////////// // Not all Windows environments support SEH properly #if defined(__MINGW32__) # define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH #endif //////////////////////////////////////////////////////////////////////////////// // PS4 #if defined(__ORBIS__) # define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE #endif //////////////////////////////////////////////////////////////////////////////// // Cygwin #ifdef __CYGWIN__ // Required for some versions of Cygwin to declare gettimeofday // see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin # define _BSD_SOURCE // some versions of cygwin (most) do not support std::to_string. Use the libstd check. // https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813 # if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \ && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF)) # define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING # endif #endif // __CYGWIN__ //////////////////////////////////////////////////////////////////////////////// // Visual C++ #if defined(_MSC_VER) // We want to defer to nvcc-specific warning suppression if we are compiled // with nvcc masquerading for MSVC. # if !defined( __CUDACC__ ) # define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ __pragma( warning( push ) ) # define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ __pragma( warning( pop ) ) # endif // Universal Windows platform does not support SEH // Or console colours (or console at all...) # if defined(CATCH_PLATFORM_WINDOWS_UWP) # define CATCH_INTERNAL_CONFIG_NO_COLOUR_WIN32 # else # define CATCH_INTERNAL_CONFIG_WINDOWS_SEH # endif // MSVC traditional preprocessor needs some workaround for __VA_ARGS__ // _MSVC_TRADITIONAL == 0 means new conformant preprocessor // _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor # if !defined(__clang__) // Handle Clang masquerading for msvc # if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) # define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR # endif // MSVC_TRADITIONAL # endif // __clang__ #endif // _MSC_VER #if defined(_REENTRANT) || defined(_MSC_VER) // Enable async processing, as -pthread is specified or no additional linking is required # define CATCH_INTERNAL_CONFIG_USE_ASYNC #endif // _MSC_VER //////////////////////////////////////////////////////////////////////////////// // Check if we are compiled with -fno-exceptions or equivalent #if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND) # define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED #endif //////////////////////////////////////////////////////////////////////////////// // Embarcadero C++Build #if defined(__BORLANDC__) #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN #endif //////////////////////////////////////////////////////////////////////////////// // RTX is a special version of Windows that is real time. // This means that it is detected as Windows, but does not provide // the same set of capabilities as real Windows does. #if defined(UNDER_RTSS) || defined(RTX64_BUILD) #define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH #define CATCH_INTERNAL_CONFIG_NO_ASYNC #define CATCH_INTERNAL_CONFIG_NO_COLOUR_WIN32 #endif #if !defined(_GLIBCXX_USE_C99_MATH_TR1) #define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER #endif // Various stdlib support checks that require __has_include #if defined(__has_include) // Check if string_view is available and usable #if __has_include(
) && defined(CATCH_CPP17_OR_GREATER) # define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW #endif // Check if optional is available and usable # if __has_include(
) && defined(CATCH_CPP17_OR_GREATER) # define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL # endif // __has_include(
) && defined(CATCH_CPP17_OR_GREATER) // Check if byte is available and usable # if __has_include(
) && defined(CATCH_CPP17_OR_GREATER) # include
# if defined(__cpp_lib_byte) && (__cpp_lib_byte > 0) # define CATCH_INTERNAL_CONFIG_CPP17_BYTE # endif # endif // __has_include(
) && defined(CATCH_CPP17_OR_GREATER) // Check if variant is available and usable # if __has_include(
) && defined(CATCH_CPP17_OR_GREATER) # if defined(__clang__) && (__clang_major__ < 8) // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852 // fix should be in clang 8, workaround in libstdc++ 8.2 # include
# if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) # define CATCH_CONFIG_NO_CPP17_VARIANT # else # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT # endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) # else # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT # endif // defined(__clang__) && (__clang_major__ < 8) # endif // __has_include(
) && defined(CATCH_CPP17_OR_GREATER) #endif // defined(__has_include) #if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH) # define CATCH_CONFIG_WINDOWS_SEH #endif // This is set by default, because we assume that unix compilers are posix-signal-compatible by default. #if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS) && !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS) # define CATCH_CONFIG_POSIX_SIGNALS #endif #if defined(CATCH_INTERNAL_CONFIG_GETENV) && !defined(CATCH_INTERNAL_CONFIG_NO_GETENV) && !defined(CATCH_CONFIG_NO_GETENV) && !defined(CATCH_CONFIG_GETENV) # define CATCH_CONFIG_GETENV #endif #if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING) # define CATCH_CONFIG_CPP11_TO_STRING #endif #if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL) # define CATCH_CONFIG_CPP17_OPTIONAL #endif #if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW) # define CATCH_CONFIG_CPP17_STRING_VIEW #endif #if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT) # define CATCH_CONFIG_CPP17_VARIANT #endif #if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && !defined(CATCH_CONFIG_NO_CPP17_BYTE) && !defined(CATCH_CONFIG_CPP17_BYTE) # define CATCH_CONFIG_CPP17_BYTE #endif #if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) # define CATCH_INTERNAL_CONFIG_NEW_CAPTURE #endif #if defined(CATCH_INTERNAL_CONFIG_NEW_CAPTURE) && !defined(CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NEW_CAPTURE) # define CATCH_CONFIG_NEW_CAPTURE #endif #if !defined( CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED ) && \ !defined( CATCH_CONFIG_DISABLE_EXCEPTIONS ) && \ !defined( CATCH_CONFIG_NO_DISABLE_EXCEPTIONS ) # define CATCH_CONFIG_DISABLE_EXCEPTIONS #endif #if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN) # define CATCH_CONFIG_POLYFILL_ISNAN #endif #if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC) # define CATCH_CONFIG_USE_ASYNC #endif #if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER) # define CATCH_CONFIG_GLOBAL_NEXTAFTER #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) # define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION #endif #if !defined(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION) # define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION #endif #if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS #endif #if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS) # define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS #endif #if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT) # define CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT #endif #if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS) # define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS #endif #if !defined(CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS) # define CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS #endif #if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS) # define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS #endif #if !defined( CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS ) # define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS #endif #if !defined( CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS ) # define CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS #endif #if !defined( CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS ) # 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) # undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS #endif #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) #define CATCH_TRY if ((true)) #define CATCH_CATCH_ALL if ((false)) #define CATCH_CATCH_ANON(type) if ((false)) #else #define CATCH_TRY try #define CATCH_CATCH_ALL catch (...) #define CATCH_CATCH_ANON(type) catch (type) #endif #if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) #define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #endif #if defined( CATCH_PLATFORM_WINDOWS ) && \ !defined( CATCH_CONFIG_COLOUR_WIN32 ) && \ !defined( CATCH_CONFIG_NO_COLOUR_WIN32 ) && \ !defined( CATCH_INTERNAL_CONFIG_NO_COLOUR_WIN32 ) # define CATCH_CONFIG_COLOUR_WIN32 #endif #if defined( CATCH_CONFIG_SHARED_LIBRARY ) && defined( _MSC_VER ) && \ !defined( CATCH_CONFIG_STATIC ) # ifdef Catch2_EXPORTS # define CATCH_EXPORT //__declspec( dllexport ) // not needed # else # define CATCH_EXPORT __declspec( dllimport ) # endif #else # define CATCH_EXPORT #endif #endif // CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED #ifndef CATCH_CONTEXT_HPP_INCLUDED #define CATCH_CONTEXT_HPP_INCLUDED namespace Catch { class IResultCapture; class IConfig; class Context { IConfig const* m_config = nullptr; IResultCapture* m_resultCapture = nullptr; CATCH_EXPORT static Context* currentContext; friend Context& getCurrentMutableContext(); friend Context const& getCurrentContext(); static void createContext(); 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 ); }; Context& getCurrentMutableContext(); inline Context const& getCurrentContext() { // We duplicate the logic from `getCurrentMutableContext` here, // to avoid paying the call overhead in debug mode. if ( !Context::currentContext ) { Context::createContext(); } // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn) return *Context::currentContext; } void cleanUpContext(); class SimplePcg32; SimplePcg32& sharedRng(); } #endif // CATCH_CONTEXT_HPP_INCLUDED #ifndef CATCH_MOVE_AND_FORWARD_HPP_INCLUDED #define CATCH_MOVE_AND_FORWARD_HPP_INCLUDED #include
//! Replacement for std::move with better compile time performance #define CATCH_MOVE(...) static_cast
&&>(__VA_ARGS__) //! Replacement for std::forward with better compile time performance #define CATCH_FORWARD(...) static_cast
(__VA_ARGS__) #endif // CATCH_MOVE_AND_FORWARD_HPP_INCLUDED #ifndef CATCH_TEST_FAILURE_EXCEPTION_HPP_INCLUDED #define CATCH_TEST_FAILURE_EXCEPTION_HPP_INCLUDED namespace Catch { //! Used to signal that an assertion macro failed struct TestFailureException{}; //! Used to signal that the remainder of a test should be skipped struct TestSkipException {}; /** * Outlines throwing of `TestFailureException` into a single TU * * Also handles `CATCH_CONFIG_DISABLE_EXCEPTIONS` for callers. */ [[noreturn]] void throw_test_failure_exception(); /** * Outlines throwing of `TestSkipException` into a single TU * * Also handles `CATCH_CONFIG_DISABLE_EXCEPTIONS` for callers. */ [[noreturn]] void throw_test_skip_exception(); } // namespace Catch #endif // CATCH_TEST_FAILURE_EXCEPTION_HPP_INCLUDED #ifndef CATCH_UNIQUE_NAME_HPP_INCLUDED #define CATCH_UNIQUE_NAME_HPP_INCLUDED /** \file * Wrapper for the CONFIG configuration option * * When generating internal unique names, there are two options. Either * we mix in the current line number, or mix in an incrementing number. * We prefer the latter, using `__COUNTER__`, but users might want to * use the former. */ #ifndef CATCH_CONFIG_COUNTER_HPP_INCLUDED #define CATCH_CONFIG_COUNTER_HPP_INCLUDED #if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L ) #define CATCH_INTERNAL_CONFIG_COUNTER #endif #if defined( CATCH_INTERNAL_CONFIG_COUNTER ) && \ !defined( CATCH_CONFIG_NO_COUNTER ) && \ !defined( CATCH_CONFIG_COUNTER ) # define CATCH_CONFIG_COUNTER #endif #endif // CATCH_CONFIG_COUNTER_HPP_INCLUDED #define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line #define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) #ifdef CATCH_CONFIG_COUNTER # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) #else # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) #endif #endif // CATCH_UNIQUE_NAME_HPP_INCLUDED #ifndef CATCH_INTERFACES_CAPTURE_HPP_INCLUDED #define CATCH_INTERFACES_CAPTURE_HPP_INCLUDED #include
#include
#ifndef CATCH_STRINGREF_HPP_INCLUDED #define CATCH_STRINGREF_HPP_INCLUDED #include
#include
#include
#include
#include
namespace Catch { /// A non-owning string class (similar to the forthcoming std::string_view) /// Note that, because a StringRef may be a substring of another string, /// it may not be null terminated. class StringRef { public: using size_type = std::size_t; using const_iterator = const char*; static constexpr size_type npos{ static_cast
( -1 ) }; private: static constexpr char const* const s_empty = ""; char const* m_start = s_empty; size_type m_size = 0; public: // construction constexpr StringRef() noexcept = default; StringRef( char const* rawChars ) noexcept; constexpr StringRef( char const* rawChars, size_type size ) noexcept : m_start( rawChars ), m_size( size ) {} StringRef( std::string const& stdString ) noexcept : m_start( stdString.c_str() ), m_size( stdString.size() ) {} explicit operator std::string() const { return std::string(m_start, m_size); } public: // operators auto operator == ( StringRef other ) const noexcept -> bool { return m_size == other.m_size && (std::memcmp( m_start, other.m_start, m_size ) == 0); } auto operator != (StringRef other) const noexcept -> bool { return !(*this == other); } constexpr auto operator[] ( size_type index ) const noexcept -> char { assert(index < m_size); return m_start[index]; } bool operator<(StringRef rhs) const noexcept; public: // named queries constexpr auto empty() const noexcept -> bool { return m_size == 0; } constexpr auto size() const noexcept -> size_type { return m_size; } // Returns a substring of [start, start + length). // If start + length > size(), then the substring is [start, size()). // If start > size(), then the substring is empty. constexpr StringRef substr(size_type start, size_type length) const noexcept { if (start < m_size) { const auto shortened_size = m_size - start; return StringRef(m_start + start, (shortened_size < length) ? shortened_size : length); } else { return StringRef(); } } // Returns the current start pointer. May not be null-terminated. constexpr char const* data() const noexcept { return m_start; } constexpr const_iterator begin() const { return m_start; } constexpr const_iterator end() const { return m_start + m_size; } friend std::string& operator += (std::string& lhs, StringRef rhs); friend std::ostream& operator << (std::ostream& os, StringRef str); friend std::string operator+(StringRef lhs, StringRef rhs); /** * Provides a three-way comparison with rhs * * Returns negative number if lhs < rhs, 0 if lhs == rhs, and a positive * number if lhs > rhs */ int compare( StringRef rhs ) const; }; constexpr auto operator ""_sr( char const* rawChars, std::size_t size ) noexcept -> StringRef { return StringRef( rawChars, size ); } } // namespace Catch constexpr auto operator ""_catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef { return Catch::StringRef( rawChars, size ); } #endif // CATCH_STRINGREF_HPP_INCLUDED #ifndef CATCH_RESULT_TYPE_HPP_INCLUDED #define CATCH_RESULT_TYPE_HPP_INCLUDED namespace Catch { // ResultWas::OfType enum struct ResultWas { enum OfType { Unknown = -1, Ok = 0, Info = 1, Warning = 2, // TODO: Should explicit skip be considered "not OK" (cf. isOk)? I.e., should it have the failure bit? ExplicitSkip = 4, FailureBit = 0x10, ExpressionFailed = FailureBit | 1, ExplicitFailure = FailureBit | 2, Exception = 0x100 | FailureBit, ThrewException = Exception | 1, DidntThrowException = Exception | 2, FatalErrorCondition = 0x200 | FailureBit }; }; bool isOk( ResultWas::OfType resultType ); bool isJustInfo( int flags ); // ResultDisposition::Flags enum struct ResultDisposition { enum Flags { Normal = 0x01, ContinueOnFailure = 0x02, // Failures fail test, but execution continues FalseTest = 0x04, // Prefix expression with ! 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 ); } // end namespace Catch #endif // CATCH_RESULT_TYPE_HPP_INCLUDED #ifndef CATCH_UNIQUE_PTR_HPP_INCLUDED #define CATCH_UNIQUE_PTR_HPP_INCLUDED #include
#include
namespace Catch { namespace Detail { /** * A reimplementation of `std::unique_ptr` for improved compilation performance * * Does not support arrays nor custom deleters. */ template
class unique_ptr { T* m_ptr; public: constexpr unique_ptr(std::nullptr_t = nullptr): m_ptr{} {} explicit constexpr unique_ptr(T* ptr): m_ptr(ptr) {} template
::value>> unique_ptr(unique_ptr
&& from): m_ptr(from.release()) {} template
::value>> unique_ptr& operator=(unique_ptr
&& from) { reset(from.release()); return *this; } unique_ptr(unique_ptr const&) = delete; unique_ptr& operator=(unique_ptr const&) = delete; unique_ptr(unique_ptr&& rhs) noexcept: m_ptr(rhs.m_ptr) { rhs.m_ptr = nullptr; } unique_ptr& operator=(unique_ptr&& rhs) noexcept { reset(rhs.release()); return *this; } ~unique_ptr() { delete m_ptr; } T& operator*() { assert(m_ptr); return *m_ptr; } T const& operator*() const { assert(m_ptr); return *m_ptr; } T* operator->() noexcept { assert(m_ptr); return m_ptr; } T const* operator->() const noexcept { assert(m_ptr); return m_ptr; } T* get() { return m_ptr; } T const* get() const { return m_ptr; } void reset(T* ptr = nullptr) { delete m_ptr; m_ptr = ptr; } T* release() { auto temp = m_ptr; m_ptr = nullptr; return temp; } explicit operator bool() const { return m_ptr; } friend void swap(unique_ptr& lhs, unique_ptr& rhs) { auto temp = lhs.m_ptr; lhs.m_ptr = rhs.m_ptr; rhs.m_ptr = temp; } }; //! Specialization to cause compile-time error for arrays template
class unique_ptr
; template
unique_ptr
make_unique(Args&&... args) { return unique_ptr
(new T(CATCH_FORWARD(args)...)); } } // end namespace Detail } // end namespace Catch #endif // CATCH_UNIQUE_PTR_HPP_INCLUDED #ifndef CATCH_BENCHMARK_STATS_FWD_HPP_INCLUDED #define CATCH_BENCHMARK_STATS_FWD_HPP_INCLUDED // Adapted from donated nonius code. #ifndef CATCH_CLOCK_HPP_INCLUDED #define CATCH_CLOCK_HPP_INCLUDED #include
namespace Catch { namespace Benchmark { using IDuration = std::chrono::nanoseconds; using FDuration = std::chrono::duration
; template
using TimePoint = typename Clock::time_point; using default_clock = std::chrono::steady_clock; } // namespace Benchmark } // namespace Catch #endif // CATCH_CLOCK_HPP_INCLUDED namespace Catch { // We cannot forward declare the type with default template argument // multiple times, so it is split out into a separate header so that // we can prevent multiple declarations in dependees template
struct BenchmarkStats; } // end namespace Catch #endif // CATCH_BENCHMARK_STATS_FWD_HPP_INCLUDED namespace Catch { class AssertionResult; struct AssertionInfo; struct SectionInfo; struct SectionEndInfo; struct MessageInfo; struct MessageBuilder; struct Counts; struct AssertionReaction; struct SourceLineInfo; class ITransientExpression; class IGeneratorTracker; struct BenchmarkInfo; namespace Generators { class GeneratorUntypedBase; using GeneratorBasePtr = Catch::Detail::unique_ptr
; } class IResultCapture { public: virtual ~IResultCapture(); virtual void notifyAssertionStarted( AssertionInfo const& info ) = 0; virtual bool sectionStarted( StringRef sectionName, SourceLineInfo const& sectionLineInfo, Counts& assertions ) = 0; virtual void sectionEnded( SectionEndInfo&& endInfo ) = 0; virtual void sectionEndedEarly( SectionEndInfo&& endInfo ) = 0; virtual IGeneratorTracker* acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) = 0; virtual IGeneratorTracker* createGeneratorTracker( StringRef generatorName, SourceLineInfo lineInfo, Generators::GeneratorBasePtr&& generator ) = 0; virtual void benchmarkPreparing( StringRef name ) = 0; virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0; virtual void benchmarkEnded( BenchmarkStats<> const& stats ) = 0; virtual void benchmarkFailed( StringRef error ) = 0; virtual void pushScopedMessage( MessageInfo const& message ) = 0; virtual void popScopedMessage( MessageInfo const& message ) = 0; virtual void emplaceUnscopedMessage( MessageBuilder&& builder ) = 0; virtual void handleFatalErrorCondition( StringRef message ) = 0; virtual void handleExpr ( AssertionInfo const& info, ITransientExpression const& expr, AssertionReaction& reaction ) = 0; virtual void handleMessage ( AssertionInfo const& info, ResultWas::OfType resultType, StringRef message, AssertionReaction& reaction ) = 0; virtual void handleUnexpectedExceptionNotThrown ( AssertionInfo const& info, AssertionReaction& reaction ) = 0; virtual void handleUnexpectedInflightException ( AssertionInfo const& info, std::string&& message, AssertionReaction& reaction ) = 0; virtual void handleIncomplete ( AssertionInfo const& info ) = 0; virtual void handleNonExpr ( AssertionInfo const &info, ResultWas::OfType resultType, AssertionReaction &reaction ) = 0; virtual bool lastAssertionPassed() = 0; virtual void assertionPassed() = 0; // Deprecated, do not use: virtual std::string getCurrentTestName() const = 0; virtual const AssertionResult* getLastResult() const = 0; virtual void exceptionEarlyReported() = 0; }; IResultCapture& getResultCapture(); } #endif // CATCH_INTERFACES_CAPTURE_HPP_INCLUDED #ifndef CATCH_INTERFACES_CONFIG_HPP_INCLUDED #define CATCH_INTERFACES_CONFIG_HPP_INCLUDED #ifndef CATCH_NONCOPYABLE_HPP_INCLUDED #define CATCH_NONCOPYABLE_HPP_INCLUDED namespace Catch { namespace Detail { //! Deriving classes become noncopyable and nonmovable class NonCopyable { NonCopyable( NonCopyable const& ) = delete; NonCopyable( NonCopyable&& ) = delete; NonCopyable& operator=( NonCopyable const& ) = delete; NonCopyable& operator=( NonCopyable&& ) = delete; protected: NonCopyable() noexcept = default; }; } // namespace Detail } // namespace Catch #endif // CATCH_NONCOPYABLE_HPP_INCLUDED #include
#include
#include
#include
namespace Catch { enum class Verbosity { Quiet = 0, Normal, High }; struct WarnAbout { enum What { Nothing = 0x00, //! A test case or leaf section did not run any assertions NoAssertions = 0x01, //! A command line test spec matched no test cases UnmatchedTestSpec = 0x02, }; }; enum class ShowDurations { DefaultForReporter, Always, Never }; enum class TestRunOrder { Declared, LexicographicallySorted, Randomized }; enum class ColourMode : std::uint8_t { //! Let Catch2 pick implementation based on platform detection PlatformDefault, //! Use ANSI colour code escapes ANSI, //! Use Win32 console colour API Win32, //! Don't use any colour None }; struct WaitForKeypress { enum When { Never, BeforeStart = 1, BeforeExit = 2, BeforeStartAndExit = BeforeStart | BeforeExit }; }; class TestSpec; class IStream; class IConfig : public Detail::NonCopyable { public: virtual ~IConfig(); virtual bool allowThrows() const = 0; virtual StringRef name() const = 0; virtual bool includeSuccessfulResults() const = 0; virtual bool shouldDebugBreak() const = 0; virtual bool warnAboutMissingAssertions() const = 0; virtual bool warnAboutUnmatchedTestSpecs() const = 0; virtual bool zeroTestsCountAsSuccess() const = 0; virtual int abortAfter() const = 0; virtual bool showInvisibles() const = 0; virtual ShowDurations showDurations() const = 0; virtual double minDuration() const = 0; virtual TestSpec const& testSpec() const = 0; virtual bool hasTestFilters() const = 0; virtual std::vector
const& getTestsOrTags() const = 0; virtual TestRunOrder runOrder() const = 0; virtual uint32_t rngSeed() const = 0; virtual unsigned int shardCount() const = 0; virtual unsigned int shardIndex() const = 0; virtual ColourMode defaultColourMode() const = 0; virtual std::vector
const& getSectionsToRun() const = 0; virtual Verbosity verbosity() const = 0; virtual bool skipBenchmarks() const = 0; virtual bool benchmarkNoAnalysis() const = 0; virtual unsigned int benchmarkSamples() const = 0; virtual double benchmarkConfidenceInterval() const = 0; virtual unsigned int benchmarkResamples() const = 0; virtual std::chrono::milliseconds benchmarkWarmupTime() const = 0; }; } #endif // CATCH_INTERFACES_CONFIG_HPP_INCLUDED #ifndef CATCH_INTERFACES_REGISTRY_HUB_HPP_INCLUDED #define CATCH_INTERFACES_REGISTRY_HUB_HPP_INCLUDED #include
namespace Catch { class TestCaseHandle; struct TestCaseInfo; class ITestCaseRegistry; class IExceptionTranslatorRegistry; class IExceptionTranslator; class ReporterRegistry; class IReporterFactory; class ITagAliasRegistry; class ITestInvoker; class IMutableEnumValuesRegistry; struct SourceLineInfo; class StartupExceptionRegistry; class EventListenerFactory; using IReporterFactoryPtr = Detail::unique_ptr
; class IRegistryHub { public: virtual ~IRegistryHub(); // = default virtual ReporterRegistry const& getReporterRegistry() const = 0; virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0; virtual IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const = 0; virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0; }; class IMutableRegistryHub { public: virtual ~IMutableRegistryHub(); // = default virtual void registerReporter( std::string const& name, IReporterFactoryPtr factory ) = 0; virtual void registerListener( Detail::unique_ptr
factory ) = 0; virtual void registerTest(Detail::unique_ptr
&& testInfo, Detail::unique_ptr
&& invoker) = 0; virtual void registerTranslator( Detail::unique_ptr
&& translator ) = 0; virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0; virtual void registerStartupException() noexcept = 0; virtual IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() = 0; }; IRegistryHub const& getRegistryHub(); IMutableRegistryHub& getMutableRegistryHub(); void cleanUp(); std::string translateActiveException(); } #endif // CATCH_INTERFACES_REGISTRY_HUB_HPP_INCLUDED #ifndef CATCH_BENCHMARK_STATS_HPP_INCLUDED #define CATCH_BENCHMARK_STATS_HPP_INCLUDED // Adapted from donated nonius code. #ifndef CATCH_ESTIMATE_HPP_INCLUDED #define CATCH_ESTIMATE_HPP_INCLUDED namespace Catch { namespace Benchmark { template
struct Estimate { Type point; Type lower_bound; Type upper_bound; double confidence_interval; }; } // namespace Benchmark } // namespace Catch #endif // CATCH_ESTIMATE_HPP_INCLUDED // Adapted from donated nonius code. #ifndef CATCH_OUTLIER_CLASSIFICATION_HPP_INCLUDED #define CATCH_OUTLIER_CLASSIFICATION_HPP_INCLUDED namespace Catch { namespace Benchmark { struct OutlierClassification { int samples_seen = 0; int low_severe = 0; // more than 3 times IQR below Q1 int low_mild = 0; // 1.5 to 3 times IQR below Q1 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 { return low_severe + low_mild + high_mild + high_severe; } }; } // namespace Benchmark } // namespace Catch #endif // CATCH_OUTLIERS_CLASSIFICATION_HPP_INCLUDED // The fwd decl & default specialization needs to be seen by VS2017 before // BenchmarkStats itself, or VS2017 will report compilation error. #include
#include
namespace Catch { struct BenchmarkInfo { std::string name; double estimatedDuration; int iterations; unsigned int samples; unsigned int resamples; double clockResolution; double clockCost; }; // We need to keep template parameter for backwards compatibility, // but we also do not want to use the template paraneter. template
struct BenchmarkStats { BenchmarkInfo info; std::vector
samples; Benchmark::Estimate
mean; Benchmark::Estimate
standardDeviation; Benchmark::OutlierClassification outliers; double outlierVariance; }; } // end namespace Catch #endif // CATCH_BENCHMARK_STATS_HPP_INCLUDED // Adapted from donated nonius code. #ifndef CATCH_ENVIRONMENT_HPP_INCLUDED #define CATCH_ENVIRONMENT_HPP_INCLUDED namespace Catch { namespace Benchmark { struct EnvironmentEstimate { FDuration mean; OutlierClassification outliers; }; struct Environment { EnvironmentEstimate clock_resolution; EnvironmentEstimate clock_cost; }; } // namespace Benchmark } // namespace Catch #endif // CATCH_ENVIRONMENT_HPP_INCLUDED // Adapted from donated nonius code. #ifndef CATCH_EXECUTION_PLAN_HPP_INCLUDED #define CATCH_EXECUTION_PLAN_HPP_INCLUDED // Adapted from donated nonius code. #ifndef CATCH_BENCHMARK_FUNCTION_HPP_INCLUDED #define CATCH_BENCHMARK_FUNCTION_HPP_INCLUDED // Adapted from donated nonius code. #ifndef CATCH_CHRONOMETER_HPP_INCLUDED #define CATCH_CHRONOMETER_HPP_INCLUDED // Adapted from donated nonius code. #ifndef CATCH_OPTIMIZER_HPP_INCLUDED #define CATCH_OPTIMIZER_HPP_INCLUDED #if defined(_MSC_VER) || defined(__IAR_SYSTEMS_ICC__) # include
// atomic_thread_fence #endif #include
namespace Catch { namespace Benchmark { #if defined(__GNUC__) || defined(__clang__) template
inline void keep_memory(T* p) { asm volatile("" : : "g"(p) : "memory"); } inline void keep_memory() { asm volatile("" : : : "memory"); } namespace Detail { inline void optimizer_barrier() { keep_memory(); } } // namespace Detail #elif defined(_MSC_VER) || defined(__IAR_SYSTEMS_ICC__) #if defined(_MSVC_VER) #pragma optimize("", off) #elif defined(__IAR_SYSTEMS_ICC__) // For IAR the pragma only affects the following function #pragma optimize=disable #endif template
inline void keep_memory(T* p) { // thanks @milleniumbug *reinterpret_cast
(p) = *reinterpret_cast
(p); } // TODO equivalent keep_memory() #if defined(_MSVC_VER) #pragma optimize("", on) #endif namespace Detail { inline void optimizer_barrier() { std::atomic_thread_fence(std::memory_order_seq_cst); } } // namespace Detail #endif template
inline void deoptimize_value(T&& x) { keep_memory(&x); } template
inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> std::enable_if_t::value> { deoptimize_value(CATCH_FORWARD(fn) (CATCH_FORWARD(args)...)); } template
inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> std::enable_if_t
::value> { CATCH_FORWARD((fn)) (CATCH_FORWARD(args)...); } } // namespace Benchmark } // namespace Catch #endif // CATCH_OPTIMIZER_HPP_INCLUDED #ifndef CATCH_META_HPP_INCLUDED #define CATCH_META_HPP_INCLUDED #include
namespace Catch { template
struct true_given : std::true_type {}; struct is_callable_tester { template
static true_given
()(std::declval
()...))> test(int); template
static std::false_type test(...); }; template
struct is_callable; template
struct is_callable
: decltype(is_callable_tester::test
(0)) {}; #if defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703 // std::result_of is deprecated in C++17 and removed in C++20. Hence, it is // replaced with std::invoke_result here. template
using FunctionReturnType = std::remove_reference_t
>>; #else template
using FunctionReturnType = std::remove_reference_t
>>; #endif } // namespace Catch namespace mpl_{ struct na; } #endif // CATCH_META_HPP_INCLUDED namespace Catch { namespace Benchmark { namespace Detail { struct ChronometerConcept { virtual void start() = 0; virtual void finish() = 0; virtual ~ChronometerConcept(); // = default; ChronometerConcept() = default; ChronometerConcept(ChronometerConcept const&) = default; ChronometerConcept& operator=(ChronometerConcept const&) = default; }; template
struct ChronometerModel final : public ChronometerConcept { void start() override { started = Clock::now(); } void finish() override { finished = Clock::now(); } IDuration elapsed() const { return std::chrono::duration_cast
( finished - started ); } TimePoint
started; TimePoint
finished; }; } // namespace Detail struct Chronometer { public: template
void measure(Fun&& fun) { measure(CATCH_FORWARD(fun), is_callable
()); } int runs() const { return repeats; } Chronometer(Detail::ChronometerConcept& meter, int repeats_) : impl(&meter) , repeats(repeats_) {} private: template
void measure(Fun&& fun, std::false_type) { measure([&fun](int) { return fun(); }, std::true_type()); } template
void measure(Fun&& fun, std::true_type) { Detail::optimizer_barrier(); impl->start(); for (int i = 0; i < repeats; ++i) invoke_deoptimized(fun, i); impl->finish(); Detail::optimizer_barrier(); } Detail::ChronometerConcept* impl; int repeats; }; } // namespace Benchmark } // namespace Catch #endif // CATCH_CHRONOMETER_HPP_INCLUDED #include
namespace Catch { namespace Benchmark { namespace Detail { template
struct is_related : std::is_same
, std::decay_t
> {}; /// We need to reinvent std::function because every piece of code that might add overhead /// in a measurement context needs to have consistent performance characteristics so that we /// can account for it in the measurement. /// Implementations of std::function with optimizations that aren't always applicable, like /// small buffer optimizations, are not uncommon. /// This is effectively an implementation of std::function without any such optimizations; /// it may be slow, but it is consistently slow. struct BenchmarkFunction { private: struct callable { virtual void call(Chronometer meter) const = 0; virtual Catch::Detail::unique_ptr
clone() const = 0; virtual ~callable(); // = default; callable() = default; callable(callable const&) = default; callable& operator=(callable const&) = default; }; template
struct model : public callable { model(Fun&& fun_) : fun(CATCH_MOVE(fun_)) {} model(Fun const& fun_) : fun(fun_) {} Catch::Detail::unique_ptr
clone() const override { return Catch::Detail::make_unique
>( *this ); } void call(Chronometer meter) const override { call(meter, is_callable
()); } void call(Chronometer meter, std::true_type) const { fun(meter); } void call(Chronometer meter, std::false_type) const { meter.measure(fun); } Fun fun; }; struct do_nothing { void operator()() const {} }; template
BenchmarkFunction(model
* c) : f(c) {} public: BenchmarkFunction() : f(new model
{ {} }) {} template
::value, int> = 0> BenchmarkFunction(Fun&& fun) : f(new model
>(CATCH_FORWARD(fun))) {} BenchmarkFunction( BenchmarkFunction&& that ) noexcept: f( CATCH_MOVE( that.f ) ) {} BenchmarkFunction(BenchmarkFunction const& that) : f(that.f->clone()) {} BenchmarkFunction& operator=( BenchmarkFunction&& that ) noexcept { f = CATCH_MOVE( that.f ); return *this; } BenchmarkFunction& operator=(BenchmarkFunction const& that) { f = that.f->clone(); return *this; } void operator()(Chronometer meter) const { f->call(meter); } private: Catch::Detail::unique_ptr
f; }; } // namespace Detail } // namespace Benchmark } // namespace Catch #endif // CATCH_BENCHMARK_FUNCTION_HPP_INCLUDED // Adapted from donated nonius code. #ifndef CATCH_REPEAT_HPP_INCLUDED #define CATCH_REPEAT_HPP_INCLUDED #include
namespace Catch { namespace Benchmark { namespace Detail { template
struct repeater { void operator()(int k) const { for (int i = 0; i < k; ++i) { fun(); } } Fun fun; }; template
repeater
> repeat(Fun&& fun) { return { CATCH_FORWARD(fun) }; } } // namespace Detail } // namespace Benchmark } // namespace Catch #endif // CATCH_REPEAT_HPP_INCLUDED // Adapted from donated nonius code. #ifndef CATCH_RUN_FOR_AT_LEAST_HPP_INCLUDED #define CATCH_RUN_FOR_AT_LEAST_HPP_INCLUDED // Adapted from donated nonius code. #ifndef CATCH_MEASURE_HPP_INCLUDED #define CATCH_MEASURE_HPP_INCLUDED // Adapted from donated nonius code. #ifndef CATCH_COMPLETE_INVOKE_HPP_INCLUDED #define CATCH_COMPLETE_INVOKE_HPP_INCLUDED namespace Catch { namespace Benchmark { namespace Detail { template
struct CompleteType { using type = T; }; template <> struct CompleteType
{ struct type {}; }; template
using CompleteType_t = typename CompleteType
::type; template
struct CompleteInvoker { template
static Result invoke(Fun&& fun, Args&&... args) { return CATCH_FORWARD(fun)(CATCH_FORWARD(args)...); } }; template <> struct CompleteInvoker
{ template
static CompleteType_t
invoke(Fun&& fun, Args&&... args) { CATCH_FORWARD(fun)(CATCH_FORWARD(args)...); return {}; } }; // invoke and not return void :( template
CompleteType_t
> complete_invoke(Fun&& fun, Args&&... args) { return CompleteInvoker
>::invoke(CATCH_FORWARD(fun), CATCH_FORWARD(args)...); } } // namespace Detail template
Detail::CompleteType_t
> user_code(Fun&& fun) { return Detail::complete_invoke(CATCH_FORWARD(fun)); } } // namespace Benchmark } // namespace Catch #endif // CATCH_COMPLETE_INVOKE_HPP_INCLUDED // Adapted from donated nonius code. #ifndef CATCH_TIMING_HPP_INCLUDED #define CATCH_TIMING_HPP_INCLUDED #include
namespace Catch { namespace Benchmark { template
struct Timing { IDuration elapsed; Result result; int iterations; }; template
using TimingOf = Timing
>>; } // namespace Benchmark } // namespace Catch #endif // CATCH_TIMING_HPP_INCLUDED namespace Catch { namespace Benchmark { namespace Detail { template
TimingOf
measure(Fun&& fun, Args&&... args) { auto start = Clock::now(); auto&& r = Detail::complete_invoke(fun, CATCH_FORWARD(args)...); auto end = Clock::now(); auto delta = end - start; return { delta, CATCH_FORWARD(r), 1 }; } } // namespace Detail } // namespace Benchmark } // namespace Catch #endif // CATCH_MEASURE_HPP_INCLUDED #include
namespace Catch { namespace Benchmark { namespace Detail { template
TimingOf
measure_one(Fun&& fun, int iters, std::false_type) { return Detail::measure
(fun, iters); } template
TimingOf
measure_one(Fun&& fun, int iters, std::true_type) { Detail::ChronometerModel
meter; auto&& result = Detail::complete_invoke(fun, Chronometer(meter, iters)); return { meter.elapsed(), CATCH_MOVE(result), iters }; } template
using run_for_at_least_argument_t = std::conditional_t
::value, Chronometer, int>; [[noreturn]] void throw_optimized_away_error(); template
TimingOf
> run_for_at_least(IDuration how_long, const int initial_iterations, Fun&& fun) { auto iters = initial_iterations; while (iters < (1 << 30)) { auto&& Timing = measure_one
(fun, iters, is_callable
()); if (Timing.elapsed >= how_long) { return { Timing.elapsed, CATCH_MOVE(Timing.result), iters }; } iters *= 2; } throw_optimized_away_error(); } } // namespace Detail } // namespace Benchmark } // namespace Catch #endif // CATCH_RUN_FOR_AT_LEAST_HPP_INCLUDED #include
namespace Catch { namespace Benchmark { struct ExecutionPlan { int iterations_per_sample; FDuration estimated_duration; Detail::BenchmarkFunction benchmark; FDuration warmup_time; int warmup_iterations; template
std::vector
run(const IConfig &cfg, Environment env) const { // warmup a bit Detail::run_for_at_least
( std::chrono::duration_cast
( warmup_time ), warmup_iterations, Detail::repeat( []() { return Clock::now(); } ) ); std::vector
times; const auto num_samples = cfg.benchmarkSamples(); times.reserve( num_samples ); for ( size_t i = 0; i < num_samples; ++i ) { Detail::ChronometerModel
model; this->benchmark( Chronometer( model, iterations_per_sample ) ); auto sample_time = model.elapsed() - env.clock_cost.mean; if ( sample_time < FDuration::zero() ) { sample_time = FDuration::zero(); } times.push_back(sample_time / iterations_per_sample); } return times; } }; } // namespace Benchmark } // namespace Catch #endif // CATCH_EXECUTION_PLAN_HPP_INCLUDED // Adapted from donated nonius code. #ifndef CATCH_ESTIMATE_CLOCK_HPP_INCLUDED #define CATCH_ESTIMATE_CLOCK_HPP_INCLUDED // Adapted from donated nonius code. #ifndef CATCH_STATS_HPP_INCLUDED #define CATCH_STATS_HPP_INCLUDED #include
namespace Catch { namespace Benchmark { namespace Detail { using sample = std::vector
; double weighted_average_quantile( int k, int q, double* first, double* last ); OutlierClassification classify_outliers( double const* first, double const* last ); double mean( double const* first, double const* last ); double normal_cdf( double x ); double erfc_inv(double x); double normal_quantile(double p); Estimate
bootstrap( double confidence_level, double* first, double* last, sample const& resample, double ( *estimator )( double const*, double const* ) ); struct bootstrap_analysis { Estimate
mean; Estimate
standard_deviation; double outlier_variance; }; bootstrap_analysis analyse_samples(double confidence_level, unsigned int n_resamples, double* first, double* last); } // namespace Detail } // namespace Benchmark } // namespace Catch #endif // CATCH_STATS_HPP_INCLUDED #include
#include
#include
namespace Catch { namespace Benchmark { namespace Detail { template
std::vector
resolution(int k) { std::vector
> times; times.reserve(static_cast
(k + 1)); for ( int i = 0; i < k + 1; ++i ) { times.push_back( Clock::now() ); } std::vector
deltas; deltas.reserve(static_cast
(k)); for ( size_t idx = 1; idx < times.size(); ++idx ) { deltas.push_back( static_cast
( ( times[idx] - times[idx - 1] ).count() ) ); } return deltas; } constexpr auto warmup_iterations = 10000; constexpr auto warmup_time = std::chrono::milliseconds(100); constexpr auto minimum_ticks = 1000; constexpr auto warmup_seed = 10000; constexpr auto clock_resolution_estimation_time = std::chrono::milliseconds(500); constexpr auto clock_cost_estimation_time_limit = std::chrono::seconds(1); constexpr auto clock_cost_estimation_tick_limit = 100000; constexpr auto clock_cost_estimation_time = std::chrono::milliseconds(10); constexpr auto clock_cost_estimation_iterations = 10000; template
int warmup() { return run_for_at_least
(warmup_time, warmup_seed, &resolution
) .iterations; } template
EnvironmentEstimate estimate_clock_resolution(int iterations) { auto r = run_for_at_least
(clock_resolution_estimation_time, iterations, &resolution
) .result; return { FDuration(mean(r.data(), r.data() + r.size())), classify_outliers(r.data(), r.data() + r.size()), }; } template
EnvironmentEstimate estimate_clock_cost(FDuration resolution) { auto time_limit = (std::min)( resolution * clock_cost_estimation_tick_limit, FDuration(clock_cost_estimation_time_limit)); auto time_clock = [](int k) { return Detail::measure
([k] { for (int i = 0; i < k; ++i) { volatile auto ignored = Clock::now(); (void)ignored; } }).elapsed; }; time_clock(1); int iters = clock_cost_estimation_iterations; auto&& r = run_for_at_least
(clock_cost_estimation_time, iters, time_clock); std::vector
times; int nsamples = static_cast
(std::ceil(time_limit / r.elapsed)); times.reserve(static_cast
(nsamples)); for ( int s = 0; s < nsamples; ++s ) { times.push_back( static_cast
( ( time_clock( r.iterations ) / r.iterations ) .count() ) ); } return { FDuration(mean(times.data(), times.data() + times.size())), classify_outliers(times.data(), times.data() + times.size()), }; } template
Environment measure_environment() { #if defined(__clang__) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wexit-time-destructors" #endif static Catch::Detail::unique_ptr
env; #if defined(__clang__) # pragma clang diagnostic pop #endif if (env) { return *env; } auto iters = Detail::warmup
(); auto resolution = Detail::estimate_clock_resolution
(iters); auto cost = Detail::estimate_clock_cost
(resolution.mean); env = Catch::Detail::make_unique
( Environment{resolution, cost} ); return *env; } } // namespace Detail } // namespace Benchmark } // namespace Catch #endif // CATCH_ESTIMATE_CLOCK_HPP_INCLUDED // Adapted from donated nonius code. #ifndef CATCH_ANALYSE_HPP_INCLUDED #define CATCH_ANALYSE_HPP_INCLUDED // Adapted from donated nonius code. #ifndef CATCH_SAMPLE_ANALYSIS_HPP_INCLUDED #define CATCH_SAMPLE_ANALYSIS_HPP_INCLUDED #include
namespace Catch { namespace Benchmark { struct SampleAnalysis { std::vector
samples; Estimate
mean; Estimate
standard_deviation; OutlierClassification outliers; double outlier_variance; }; } // namespace Benchmark } // namespace Catch #endif // CATCH_SAMPLE_ANALYSIS_HPP_INCLUDED namespace Catch { class IConfig; namespace Benchmark { namespace Detail { SampleAnalysis analyse(const IConfig &cfg, FDuration* first, FDuration* last); } // namespace Detail } // namespace Benchmark } // namespace Catch #endif // CATCH_ANALYSE_HPP_INCLUDED #include
#include
#include
#include
#include
namespace Catch { namespace Benchmark { struct Benchmark { Benchmark(std::string&& benchmarkName) : name(CATCH_MOVE(benchmarkName)) {} template
Benchmark(std::string&& benchmarkName , FUN &&func) : fun(CATCH_MOVE(func)), name(CATCH_MOVE(benchmarkName)) {} template
ExecutionPlan prepare(const IConfig &cfg, Environment env) const { auto min_time = env.clock_resolution.mean * Detail::minimum_ticks; auto run_time = std::max(min_time, std::chrono::duration_cast
(cfg.benchmarkWarmupTime())); auto&& test = Detail::run_for_at_least
(std::chrono::duration_cast
(run_time), 1, fun); int new_iters = static_cast
(std::ceil(min_time * test.iterations / test.elapsed)); return { new_iters, test.elapsed / test.iterations * new_iters * cfg.benchmarkSamples(), fun, std::chrono::duration_cast
(cfg.benchmarkWarmupTime()), Detail::warmup_iterations }; } template
void run() { static_assert( Clock::is_steady, "Benchmarking clock should be steady" ); auto const* cfg = getCurrentContext().getConfig(); auto env = Detail::measure_environment
(); getResultCapture().benchmarkPreparing(name); CATCH_TRY{ auto plan = user_code([&] { return prepare
(*cfg, env); }); BenchmarkInfo info { CATCH_MOVE(name), plan.estimated_duration.count(), plan.iterations_per_sample, cfg->benchmarkSamples(), cfg->benchmarkResamples(), env.clock_resolution.mean.count(), env.clock_cost.mean.count() }; getResultCapture().benchmarkStarting(info); auto samples = user_code([&] { return plan.template run
(*cfg, env); }); auto analysis = Detail::analyse(*cfg, samples.data(), samples.data() + samples.size()); BenchmarkStats<> stats{ CATCH_MOVE(info), CATCH_MOVE(analysis.samples), analysis.mean, analysis.standard_deviation, analysis.outliers, analysis.outlier_variance }; getResultCapture().benchmarkEnded(stats); } CATCH_CATCH_ANON (TestFailureException const&) { getResultCapture().benchmarkFailed("Benchmark failed due to failed assertion"_sr); } CATCH_CATCH_ALL{ getResultCapture().benchmarkFailed(translateActiveException()); // We let the exception go further up so that the // test case is marked as failed. std::rethrow_exception(std::current_exception()); } } // sets lambda to be used in fun *and* executes benchmark! template
::value, int> = 0> Benchmark & operator=(Fun func) { auto const* cfg = getCurrentContext().getConfig(); if (!cfg->skipBenchmarks()) { fun = Detail::BenchmarkFunction(func); run(); } return *this; } explicit operator bool() { return true; } private: Detail::BenchmarkFunction fun; std::string name; }; } } // namespace Catch #define INTERNAL_CATCH_GET_1_ARG(arg1, arg2, ...) arg1 #define INTERNAL_CATCH_GET_2_ARG(arg1, arg2, ...) arg2 #define INTERNAL_CATCH_BENCHMARK(BenchmarkName, name, benchmarkIndex)\ if( Catch::Benchmark::Benchmark BenchmarkName{name} ) \ BenchmarkName = [&](int benchmarkIndex) #define INTERNAL_CATCH_BENCHMARK_ADVANCED(BenchmarkName, name)\ if( Catch::Benchmark::Benchmark BenchmarkName{name} ) \ BenchmarkName = [&] #if defined(CATCH_CONFIG_PREFIX_ALL) #define CATCH_BENCHMARK(...) \ INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_BENCHMARK_), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,)) #define CATCH_BENCHMARK_ADVANCED(name) \ INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_BENCHMARK_), name) #else #define BENCHMARK(...) \ INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_BENCHMARK_), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,)) #define BENCHMARK_ADVANCED(name) \ INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_BENCHMARK_), name) #endif #endif // CATCH_BENCHMARK_HPP_INCLUDED // Adapted from donated nonius code. #ifndef CATCH_CONSTRUCTOR_HPP_INCLUDED #define CATCH_CONSTRUCTOR_HPP_INCLUDED #include
namespace Catch { namespace Benchmark { namespace Detail { template
struct ObjectStorage { ObjectStorage() = default; ObjectStorage(const ObjectStorage& other) { new(&data) T(other.stored_object()); } ObjectStorage(ObjectStorage&& other) { new(data) T(CATCH_MOVE(other.stored_object())); } ~ObjectStorage() { destruct_on_exit
(); } template
void construct(Args&&... args) { new (data) T(CATCH_FORWARD(args)...); } template
std::enable_if_t
destruct() { stored_object().~T(); } private: // If this is a constructor benchmark, destruct the underlying object template
void destruct_on_exit(std::enable_if_t
* = nullptr) { destruct
(); } // Otherwise, don't template
void destruct_on_exit(std::enable_if_t* = nullptr) { } #if defined( __GNUC__ ) && __GNUC__ <= 6 # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wstrict-aliasing" #endif T& stored_object() { return *reinterpret_cast
( data ); } T const& stored_object() const { return *reinterpret_cast
( data ); } #if defined( __GNUC__ ) && __GNUC__ <= 6 # pragma GCC diagnostic pop #endif alignas( T ) unsigned char data[sizeof( T )]{}; }; } // namespace Detail template
using storage_for = Detail::ObjectStorage
; template
using destructable_object = Detail::ObjectStorage
; } // namespace Benchmark } // namespace Catch #endif // CATCH_CONSTRUCTOR_HPP_INCLUDED #endif // CATCH_BENCHMARK_ALL_HPP_INCLUDED #ifndef CATCH_APPROX_HPP_INCLUDED #define CATCH_APPROX_HPP_INCLUDED #ifndef CATCH_TOSTRING_HPP_INCLUDED #define CATCH_TOSTRING_HPP_INCLUDED #include
#include
#include
#include
/** \file * Wrapper for the WCHAR configuration option * * We want to support platforms that do not provide `wchar_t`, so we * sometimes have to disable providing wchar_t overloads through Catch2, * e.g. the StringMaker specialization for `std::wstring`. */ #ifndef CATCH_CONFIG_WCHAR_HPP_INCLUDED #define CATCH_CONFIG_WCHAR_HPP_INCLUDED // We assume that WCHAR should be enabled by default, and only disabled // for a shortlist (so far only DJGPP) of compilers. #if defined(__DJGPP__) # define CATCH_INTERNAL_CONFIG_NO_WCHAR #endif // __DJGPP__ #if !defined( CATCH_INTERNAL_CONFIG_NO_WCHAR ) && \ !defined( CATCH_CONFIG_NO_WCHAR ) && \ !defined( CATCH_CONFIG_WCHAR ) # define CATCH_CONFIG_WCHAR #endif #endif // CATCH_CONFIG_WCHAR_HPP_INCLUDED #ifndef CATCH_REUSABLE_STRING_STREAM_HPP_INCLUDED #define CATCH_REUSABLE_STRING_STREAM_HPP_INCLUDED #include
#include
#include
#include
namespace Catch { class ReusableStringStream : Detail::NonCopyable { std::size_t m_index; std::ostream* m_oss; public: ReusableStringStream(); ~ReusableStringStream(); //! Returns the serialized state std::string str() const; //! Sets internal state to `str` void str(std::string const& str); #if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic push // Old versions of GCC do not understand -Wnonnull-compare #pragma GCC diagnostic ignored "-Wpragmas" // Streaming a function pointer triggers Waddress and Wnonnull-compare // on GCC, because it implicitly converts it to bool and then decides // that the check it uses (a? true : false) is tautological and cannot // be null... #pragma GCC diagnostic ignored "-Waddress" #pragma GCC diagnostic ignored "-Wnonnull-compare" #endif template
auto operator << ( T const& value ) -> ReusableStringStream& { *m_oss << value; return *this; } #if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic pop #endif auto get() -> std::ostream& { return *m_oss; } }; } #endif // CATCH_REUSABLE_STRING_STREAM_HPP_INCLUDED #ifndef CATCH_VOID_TYPE_HPP_INCLUDED #define CATCH_VOID_TYPE_HPP_INCLUDED namespace Catch { namespace Detail { template
struct make_void { using type = void; }; template
using void_t = typename make_void
::type; } // namespace Detail } // namespace Catch #endif // CATCH_VOID_TYPE_HPP_INCLUDED #ifndef CATCH_INTERFACES_ENUM_VALUES_REGISTRY_HPP_INCLUDED #define CATCH_INTERFACES_ENUM_VALUES_REGISTRY_HPP_INCLUDED #include
namespace Catch { namespace Detail { struct EnumInfo { StringRef m_name; std::vector
> m_values; ~EnumInfo(); StringRef lookup( int value ) const; }; } // namespace Detail class IMutableEnumValuesRegistry { public: virtual ~IMutableEnumValuesRegistry(); // = default; virtual Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::vector
const& values ) = 0; template
Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::initializer_list
values ) { static_assert(sizeof(int) >= sizeof(E), "Cannot serialize enum to int"); std::vector
intValues; intValues.reserve( values.size() ); for( auto enumValue : values ) intValues.push_back( static_cast
( enumValue ) ); return registerEnum( enumName, allEnums, intValues ); } }; } // Catch #endif // CATCH_INTERFACES_ENUM_VALUES_REGISTRY_HPP_INCLUDED #ifdef CATCH_CONFIG_CPP17_STRING_VIEW #include
#endif #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable:4180) // We attempt to stream a function (address) by const&, which MSVC complains about but is harmless #endif // We need a dummy global operator<< so we can bring it into Catch namespace later struct Catch_global_namespace_dummy{}; std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy); namespace Catch { // Bring in global namespace operator<< for ADL lookup in // `IsStreamInsertable` below. using ::operator<<; namespace Detail { inline std::size_t catch_strnlen(const char *str, std::size_t n) { auto ret = std::char_traits
::find(str, n, '\0'); if (ret != nullptr) { return static_cast
(ret - str); } return n; } constexpr StringRef unprintableString = "{?}"_sr; //! Encases `string in quotes, and optionally escapes invisibles std::string convertIntoString( StringRef string, bool escapeInvisibles ); //! Encases `string` in quotes, and escapes invisibles if user requested //! it via CLI std::string convertIntoString( StringRef string ); std::string rawMemoryToString( const void *object, std::size_t size ); template
std::string rawMemoryToString( const T& object ) { return rawMemoryToString( &object, sizeof(object) ); } template
class IsStreamInsertable { template
static auto test(int) -> decltype(std::declval
() << std::declval
(), std::true_type()); template
static auto test(...)->std::false_type; public: static const bool value = decltype(test
(0))::value; }; template
std::string convertUnknownEnumToString( E e ); template
std::enable_if_t< !std::is_enum
::value && !std::is_base_of