File indexing completed on 2025-02-16 05:12:44
0001 /* 0002 * Catch v2.13.10 0003 * Generated: 2022-10-16 11:01:23.452308 0004 * ---------------------------------------------------------- 0005 * This file has been merged from multiple headers. Please don't edit it directly 0006 * Copyright (c) 2022 Two Blue Cubes Ltd. All rights reserved. 0007 * 0008 * Distributed under the Boost Software License, Version 1.0. (See accompanying 0009 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 0010 */ 0011 #ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED 0012 #define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED 0013 // start catch.hpp 0014 0015 0016 #define CATCH_VERSION_MAJOR 2 0017 #define CATCH_VERSION_MINOR 13 0018 #define CATCH_VERSION_PATCH 10 0019 0020 #ifdef __clang__ 0021 # pragma clang system_header 0022 #elif defined __GNUC__ 0023 # pragma GCC system_header 0024 #endif 0025 0026 // start catch_suppress_warnings.h 0027 0028 #ifdef __clang__ 0029 # ifdef __ICC // icpc defines the __clang__ macro 0030 # pragma warning(push) 0031 # pragma warning(disable: 161 1682) 0032 # else // __ICC 0033 # pragma clang diagnostic push 0034 # pragma clang diagnostic ignored "-Wpadded" 0035 # pragma clang diagnostic ignored "-Wswitch-enum" 0036 # pragma clang diagnostic ignored "-Wcovered-switch-default" 0037 # endif 0038 #elif defined __GNUC__ 0039 // Because REQUIREs trigger GCC's -Wparentheses, and because still 0040 // supported version of g++ have only buggy support for _Pragmas, 0041 // Wparentheses have to be suppressed globally. 0042 # pragma GCC diagnostic ignored "-Wparentheses" // See #674 for details 0043 0044 # pragma GCC diagnostic push 0045 # pragma GCC diagnostic ignored "-Wunused-variable" 0046 # pragma GCC diagnostic ignored "-Wpadded" 0047 #endif 0048 // end catch_suppress_warnings.h 0049 #if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) 0050 # define CATCH_IMPL 0051 # define CATCH_CONFIG_ALL_PARTS 0052 #endif 0053 0054 // In the impl file, we want to have access to all parts of the headers 0055 // Can also be used to sanely support PCHs 0056 #if defined(CATCH_CONFIG_ALL_PARTS) 0057 # define CATCH_CONFIG_EXTERNAL_INTERFACES 0058 # if defined(CATCH_CONFIG_DISABLE_MATCHERS) 0059 # undef CATCH_CONFIG_DISABLE_MATCHERS 0060 # endif 0061 # if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) 0062 # define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER 0063 # endif 0064 #endif 0065 0066 #if !defined(CATCH_CONFIG_IMPL_ONLY) 0067 // start catch_platform.h 0068 0069 // See e.g.: 0070 // https://opensource.apple.com/source/CarbonHeaders/CarbonHeaders-18.1/TargetConditionals.h.auto.html 0071 #ifdef __APPLE__ 0072 # include <TargetConditionals.h> 0073 # if (defined(TARGET_OS_OSX) && TARGET_OS_OSX == 1) || \ 0074 (defined(TARGET_OS_MAC) && TARGET_OS_MAC == 1) 0075 # define CATCH_PLATFORM_MAC 0076 # elif (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1) 0077 # define CATCH_PLATFORM_IPHONE 0078 # endif 0079 0080 #elif defined(linux) || defined(__linux) || defined(__linux__) 0081 # define CATCH_PLATFORM_LINUX 0082 0083 #elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__) 0084 # define CATCH_PLATFORM_WINDOWS 0085 #endif 0086 0087 // end catch_platform.h 0088 0089 #ifdef CATCH_IMPL 0090 # ifndef CLARA_CONFIG_MAIN 0091 # define CLARA_CONFIG_MAIN_NOT_DEFINED 0092 # define CLARA_CONFIG_MAIN 0093 # endif 0094 #endif 0095 0096 // start catch_user_interfaces.h 0097 0098 namespace Catch { 0099 unsigned int rngSeed(); 0100 } 0101 0102 // end catch_user_interfaces.h 0103 // start catch_tag_alias_autoregistrar.h 0104 0105 // start catch_common.h 0106 0107 // start catch_compiler_capabilities.h 0108 0109 // Detect a number of compiler features - by compiler 0110 // The following features are defined: 0111 // 0112 // CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? 0113 // CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported? 0114 // CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported? 0115 // CATCH_CONFIG_DISABLE_EXCEPTIONS : Are exceptions enabled? 0116 // **************** 0117 // Note to maintainers: if new toggles are added please document them 0118 // in configuration.md, too 0119 // **************** 0120 0121 // In general each macro has a _NO_<feature name> form 0122 // (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature. 0123 // Many features, at point of detection, define an _INTERNAL_ macro, so they 0124 // can be combined, en-mass, with the _NO_ forms later. 0125 0126 #ifdef __cplusplus 0127 0128 # if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L) 0129 # define CATCH_CPP14_OR_GREATER 0130 # endif 0131 0132 # if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) 0133 # define CATCH_CPP17_OR_GREATER 0134 # endif 0135 0136 #endif 0137 0138 // Only GCC compiler should be used in this block, so other compilers trying to 0139 // mask themselves as GCC should be ignored. 0140 #if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__) && !defined(__LCC__) 0141 # define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" ) 0142 # define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" ) 0143 0144 # define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) 0145 0146 #endif 0147 0148 #if defined(__clang__) 0149 0150 # define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" ) 0151 # define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic pop" ) 0152 0153 // As of this writing, IBM XL's implementation of __builtin_constant_p has a bug 0154 // which results in calls to destructors being emitted for each temporary, 0155 // without a matching initialization. In practice, this can result in something 0156 // like `std::string::~string` being called on an uninitialized value. 0157 // 0158 // For example, this code will likely segfault under IBM XL: 0159 // ``` 0160 // REQUIRE(std::string("12") + "34" == "1234") 0161 // ``` 0162 // 0163 // Therefore, `CATCH_INTERNAL_IGNORE_BUT_WARN` is not implemented. 0164 # if !defined(__ibmxl__) && !defined(__CUDACC__) 0165 # define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) /* NOLINT(cppcoreguidelines-pro-type-vararg, hicpp-vararg) */ 0166 # endif 0167 0168 # define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 0169 _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ 0170 _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") 0171 0172 # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ 0173 _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) 0174 0175 # define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ 0176 _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" ) 0177 0178 # define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ 0179 _Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" ) 0180 0181 # define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 0182 _Pragma( "clang diagnostic ignored \"-Wunused-template\"" ) 0183 0184 #endif // __clang__ 0185 0186 //////////////////////////////////////////////////////////////////////////////// 0187 // Assume that non-Windows platforms support posix signals by default 0188 #if !defined(CATCH_PLATFORM_WINDOWS) 0189 #define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS 0190 #endif 0191 0192 //////////////////////////////////////////////////////////////////////////////// 0193 // We know some environments not to support full POSIX signals 0194 #if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__) 0195 #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS 0196 #endif 0197 0198 #ifdef __OS400__ 0199 # define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS 0200 # define CATCH_CONFIG_COLOUR_NONE 0201 #endif 0202 0203 //////////////////////////////////////////////////////////////////////////////// 0204 // Android somehow still does not support std::to_string 0205 #if defined(__ANDROID__) 0206 # define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING 0207 # define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE 0208 #endif 0209 0210 //////////////////////////////////////////////////////////////////////////////// 0211 // Not all Windows environments support SEH properly 0212 #if defined(__MINGW32__) 0213 # define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH 0214 #endif 0215 0216 //////////////////////////////////////////////////////////////////////////////// 0217 // PS4 0218 #if defined(__ORBIS__) 0219 # define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE 0220 #endif 0221 0222 //////////////////////////////////////////////////////////////////////////////// 0223 // Cygwin 0224 #ifdef __CYGWIN__ 0225 0226 // Required for some versions of Cygwin to declare gettimeofday 0227 // see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin 0228 # define _BSD_SOURCE 0229 // some versions of cygwin (most) do not support std::to_string. Use the libstd check. 0230 // https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813 0231 # if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \ 0232 && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF)) 0233 0234 # define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING 0235 0236 # endif 0237 #endif // __CYGWIN__ 0238 0239 //////////////////////////////////////////////////////////////////////////////// 0240 // Visual C++ 0241 #if defined(_MSC_VER) 0242 0243 // Universal Windows platform does not support SEH 0244 // Or console colours (or console at all...) 0245 # if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) 0246 # define CATCH_CONFIG_COLOUR_NONE 0247 # else 0248 # define CATCH_INTERNAL_CONFIG_WINDOWS_SEH 0249 # endif 0250 0251 # if !defined(__clang__) // Handle Clang masquerading for msvc 0252 0253 // MSVC traditional preprocessor needs some workaround for __VA_ARGS__ 0254 // _MSVC_TRADITIONAL == 0 means new conformant preprocessor 0255 // _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor 0256 # if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) 0257 # define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 0258 # endif // MSVC_TRADITIONAL 0259 0260 // Only do this if we're not using clang on Windows, which uses `diagnostic push` & `diagnostic pop` 0261 # define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) ) 0262 # define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) ) 0263 # endif // __clang__ 0264 0265 #endif // _MSC_VER 0266 0267 #if defined(_REENTRANT) || defined(_MSC_VER) 0268 // Enable async processing, as -pthread is specified or no additional linking is required 0269 # define CATCH_INTERNAL_CONFIG_USE_ASYNC 0270 #endif // _MSC_VER 0271 0272 //////////////////////////////////////////////////////////////////////////////// 0273 // Check if we are compiled with -fno-exceptions or equivalent 0274 #if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND) 0275 # define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED 0276 #endif 0277 0278 //////////////////////////////////////////////////////////////////////////////// 0279 // DJGPP 0280 #ifdef __DJGPP__ 0281 # define CATCH_INTERNAL_CONFIG_NO_WCHAR 0282 #endif // __DJGPP__ 0283 0284 //////////////////////////////////////////////////////////////////////////////// 0285 // Embarcadero C++Build 0286 #if defined(__BORLANDC__) 0287 #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN 0288 #endif 0289 0290 //////////////////////////////////////////////////////////////////////////////// 0291 0292 // Use of __COUNTER__ is suppressed during code analysis in 0293 // CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly 0294 // handled by it. 0295 // Otherwise all supported compilers support COUNTER macro, 0296 // but user still might want to turn it off 0297 #if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L ) 0298 #define CATCH_INTERNAL_CONFIG_COUNTER 0299 #endif 0300 0301 //////////////////////////////////////////////////////////////////////////////// 0302 0303 // RTX is a special version of Windows that is real time. 0304 // This means that it is detected as Windows, but does not provide 0305 // the same set of capabilities as real Windows does. 0306 #if defined(UNDER_RTSS) || defined(RTX64_BUILD) 0307 #define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH 0308 #define CATCH_INTERNAL_CONFIG_NO_ASYNC 0309 #define CATCH_CONFIG_COLOUR_NONE 0310 #endif 0311 0312 #if !defined(_GLIBCXX_USE_C99_MATH_TR1) 0313 #define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER 0314 #endif 0315 0316 // Various stdlib support checks that require __has_include 0317 #if defined(__has_include) 0318 // Check if string_view is available and usable 0319 #if __has_include(<string_view>) && defined(CATCH_CPP17_OR_GREATER) 0320 # define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW 0321 #endif 0322 0323 // Check if optional is available and usable 0324 # if __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER) 0325 # define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL 0326 # endif // __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER) 0327 0328 // Check if byte is available and usable 0329 # if __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER) 0330 # include <cstddef> 0331 # if defined(__cpp_lib_byte) && (__cpp_lib_byte > 0) 0332 # define CATCH_INTERNAL_CONFIG_CPP17_BYTE 0333 # endif 0334 # endif // __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER) 0335 0336 // Check if variant is available and usable 0337 # if __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER) 0338 # if defined(__clang__) && (__clang_major__ < 8) 0339 // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852 0340 // fix should be in clang 8, workaround in libstdc++ 8.2 0341 # include <ciso646> 0342 # if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) 0343 # define CATCH_CONFIG_NO_CPP17_VARIANT 0344 # else 0345 # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT 0346 # endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) 0347 # else 0348 # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT 0349 # endif // defined(__clang__) && (__clang_major__ < 8) 0350 # endif // __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER) 0351 #endif // defined(__has_include) 0352 0353 #if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) 0354 # define CATCH_CONFIG_COUNTER 0355 #endif 0356 #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) 0357 # define CATCH_CONFIG_WINDOWS_SEH 0358 #endif 0359 // This is set by default, because we assume that unix compilers are posix-signal-compatible by default. 0360 #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) 0361 # define CATCH_CONFIG_POSIX_SIGNALS 0362 #endif 0363 // This is set by default, because we assume that compilers with no wchar_t support are just rare exceptions. 0364 #if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR) 0365 # define CATCH_CONFIG_WCHAR 0366 #endif 0367 0368 #if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING) 0369 # define CATCH_CONFIG_CPP11_TO_STRING 0370 #endif 0371 0372 #if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL) 0373 # define CATCH_CONFIG_CPP17_OPTIONAL 0374 #endif 0375 0376 #if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW) 0377 # define CATCH_CONFIG_CPP17_STRING_VIEW 0378 #endif 0379 0380 #if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT) 0381 # define CATCH_CONFIG_CPP17_VARIANT 0382 #endif 0383 0384 #if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && !defined(CATCH_CONFIG_NO_CPP17_BYTE) && !defined(CATCH_CONFIG_CPP17_BYTE) 0385 # define CATCH_CONFIG_CPP17_BYTE 0386 #endif 0387 0388 #if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) 0389 # define CATCH_INTERNAL_CONFIG_NEW_CAPTURE 0390 #endif 0391 0392 #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) 0393 # define CATCH_CONFIG_NEW_CAPTURE 0394 #endif 0395 0396 #if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 0397 # define CATCH_CONFIG_DISABLE_EXCEPTIONS 0398 #endif 0399 0400 #if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN) 0401 # define CATCH_CONFIG_POLYFILL_ISNAN 0402 #endif 0403 0404 #if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC) 0405 # define CATCH_CONFIG_USE_ASYNC 0406 #endif 0407 0408 #if defined(CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_NO_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_ANDROID_LOGWRITE) 0409 # define CATCH_CONFIG_ANDROID_LOGWRITE 0410 #endif 0411 0412 #if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER) 0413 # define CATCH_CONFIG_GLOBAL_NEXTAFTER 0414 #endif 0415 0416 // Even if we do not think the compiler has that warning, we still have 0417 // to provide a macro that can be used by the code. 0418 #if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION) 0419 # define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION 0420 #endif 0421 #if !defined(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION) 0422 # define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 0423 #endif 0424 #if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) 0425 # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS 0426 #endif 0427 #if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS) 0428 # define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS 0429 #endif 0430 #if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS) 0431 # define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS 0432 #endif 0433 #if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS) 0434 # define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS 0435 #endif 0436 0437 // The goal of this macro is to avoid evaluation of the arguments, but 0438 // still have the compiler warn on problems inside... 0439 #if !defined(CATCH_INTERNAL_IGNORE_BUT_WARN) 0440 # define CATCH_INTERNAL_IGNORE_BUT_WARN(...) 0441 #endif 0442 0443 #if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10) 0444 # undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS 0445 #elif defined(__clang__) && (__clang_major__ < 5) 0446 # undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS 0447 #endif 0448 0449 #if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS) 0450 # define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS 0451 #endif 0452 0453 #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 0454 #define CATCH_TRY if ((true)) 0455 #define CATCH_CATCH_ALL if ((false)) 0456 #define CATCH_CATCH_ANON(type) if ((false)) 0457 #else 0458 #define CATCH_TRY try 0459 #define CATCH_CATCH_ALL catch (...) 0460 #define CATCH_CATCH_ANON(type) catch (type) 0461 #endif 0462 0463 #if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) 0464 #define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 0465 #endif 0466 0467 // end catch_compiler_capabilities.h 0468 #define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line 0469 #define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) 0470 #ifdef CATCH_CONFIG_COUNTER 0471 # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) 0472 #else 0473 # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) 0474 #endif 0475 0476 #include <iosfwd> 0477 #include <string> 0478 #include <cstdint> 0479 0480 // We need a dummy global operator<< so we can bring it into Catch namespace later 0481 struct Catch_global_namespace_dummy {}; 0482 std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy); 0483 0484 namespace Catch { 0485 0486 struct CaseSensitive { enum Choice { 0487 Yes, 0488 No 0489 }; }; 0490 0491 class NonCopyable { 0492 NonCopyable( NonCopyable const& ) = delete; 0493 NonCopyable( NonCopyable && ) = delete; 0494 NonCopyable& operator = ( NonCopyable const& ) = delete; 0495 NonCopyable& operator = ( NonCopyable && ) = delete; 0496 0497 protected: 0498 NonCopyable(); 0499 virtual ~NonCopyable(); 0500 }; 0501 0502 struct SourceLineInfo { 0503 0504 SourceLineInfo() = delete; 0505 SourceLineInfo( char const* _file, std::size_t _line ) noexcept 0506 : file( _file ), 0507 line( _line ) 0508 {} 0509 0510 SourceLineInfo( SourceLineInfo const& other ) = default; 0511 SourceLineInfo& operator = ( SourceLineInfo const& ) = default; 0512 SourceLineInfo( SourceLineInfo&& ) noexcept = default; 0513 SourceLineInfo& operator = ( SourceLineInfo&& ) noexcept = default; 0514 0515 bool empty() const noexcept { return file[0] == '\0'; } 0516 bool operator == ( SourceLineInfo const& other ) const noexcept; 0517 bool operator < ( SourceLineInfo const& other ) const noexcept; 0518 0519 char const* file; 0520 std::size_t line; 0521 }; 0522 0523 std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); 0524 0525 // Bring in operator<< from global namespace into Catch namespace 0526 // This is necessary because the overload of operator<< above makes 0527 // lookup stop at namespace Catch 0528 using ::operator<<; 0529 0530 // Use this in variadic streaming macros to allow 0531 // >> +StreamEndStop 0532 // as well as 0533 // >> stuff +StreamEndStop 0534 struct StreamEndStop { 0535 std::string operator+() const; 0536 }; 0537 template<typename T> 0538 T const& operator + ( T const& value, StreamEndStop ) { 0539 return value; 0540 } 0541 } 0542 0543 #define CATCH_INTERNAL_LINEINFO \ 0544 ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) ) 0545 0546 // end catch_common.h 0547 namespace Catch { 0548 0549 struct RegistrarForTagAliases { 0550 RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); 0551 }; 0552 0553 } // end namespace Catch 0554 0555 #define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \ 0556 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 0557 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 0558 namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \ 0559 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 0560 0561 // end catch_tag_alias_autoregistrar.h 0562 // start catch_test_registry.h 0563 0564 // start catch_interfaces_testcase.h 0565 0566 #include <vector> 0567 0568 namespace Catch { 0569 0570 class TestSpec; 0571 0572 struct ITestInvoker { 0573 virtual void invoke () const = 0; 0574 virtual ~ITestInvoker(); 0575 }; 0576 0577 class TestCase; 0578 struct IConfig; 0579 0580 struct ITestCaseRegistry { 0581 virtual ~ITestCaseRegistry(); 0582 virtual std::vector<TestCase> const& getAllTests() const = 0; 0583 virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const = 0; 0584 }; 0585 0586 bool isThrowSafe( TestCase const& testCase, IConfig const& config ); 0587 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); 0588 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ); 0589 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ); 0590 0591 } 0592 0593 // end catch_interfaces_testcase.h 0594 // start catch_stringref.h 0595 0596 #include <cstddef> 0597 #include <string> 0598 #include <iosfwd> 0599 #include <cassert> 0600 0601 namespace Catch { 0602 0603 /// A non-owning string class (similar to the forthcoming std::string_view) 0604 /// Note that, because a StringRef may be a substring of another string, 0605 /// it may not be null terminated. 0606 class StringRef { 0607 public: 0608 using size_type = std::size_t; 0609 using const_iterator = const char*; 0610 0611 private: 0612 static constexpr char const* const s_empty = ""; 0613 0614 char const* m_start = s_empty; 0615 size_type m_size = 0; 0616 0617 public: // construction 0618 constexpr StringRef() noexcept = default; 0619 0620 StringRef( char const* rawChars ) noexcept; 0621 0622 constexpr StringRef( char const* rawChars, size_type size ) noexcept 0623 : m_start( rawChars ), 0624 m_size( size ) 0625 {} 0626 0627 StringRef( std::string const& stdString ) noexcept 0628 : m_start( stdString.c_str() ), 0629 m_size( stdString.size() ) 0630 {} 0631 0632 explicit operator std::string() const { 0633 return std::string(m_start, m_size); 0634 } 0635 0636 public: // operators 0637 auto operator == ( StringRef const& other ) const noexcept -> bool; 0638 auto operator != (StringRef const& other) const noexcept -> bool { 0639 return !(*this == other); 0640 } 0641 0642 auto operator[] ( size_type index ) const noexcept -> char { 0643 assert(index < m_size); 0644 return m_start[index]; 0645 } 0646 0647 public: // named queries 0648 constexpr auto empty() const noexcept -> bool { 0649 return m_size == 0; 0650 } 0651 constexpr auto size() const noexcept -> size_type { 0652 return m_size; 0653 } 0654 0655 // Returns the current start pointer. If the StringRef is not 0656 // null-terminated, throws std::domain_exception 0657 auto c_str() const -> char const*; 0658 0659 public: // substrings and searches 0660 // Returns a substring of [start, start + length). 0661 // If start + length > size(), then the substring is [start, size()). 0662 // If start > size(), then the substring is empty. 0663 auto substr( size_type start, size_type length ) const noexcept -> StringRef; 0664 0665 // Returns the current start pointer. May not be null-terminated. 0666 auto data() const noexcept -> char const*; 0667 0668 constexpr auto isNullTerminated() const noexcept -> bool { 0669 return m_start[m_size] == '\0'; 0670 } 0671 0672 public: // iterators 0673 constexpr const_iterator begin() const { return m_start; } 0674 constexpr const_iterator end() const { return m_start + m_size; } 0675 }; 0676 0677 auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&; 0678 auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&; 0679 0680 constexpr auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef { 0681 return StringRef( rawChars, size ); 0682 } 0683 } // namespace Catch 0684 0685 constexpr auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef { 0686 return Catch::StringRef( rawChars, size ); 0687 } 0688 0689 // end catch_stringref.h 0690 // start catch_preprocessor.hpp 0691 0692 0693 #define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__ 0694 #define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__))) 0695 #define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__))) 0696 #define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__))) 0697 #define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__))) 0698 #define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__))) 0699 0700 #ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 0701 #define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__ 0702 // MSVC needs more evaluations 0703 #define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__))) 0704 #define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__)) 0705 #else 0706 #define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL5(__VA_ARGS__) 0707 #endif 0708 0709 #define CATCH_REC_END(...) 0710 #define CATCH_REC_OUT 0711 0712 #define CATCH_EMPTY() 0713 #define CATCH_DEFER(id) id CATCH_EMPTY() 0714 0715 #define CATCH_REC_GET_END2() 0, CATCH_REC_END 0716 #define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2 0717 #define CATCH_REC_GET_END(...) CATCH_REC_GET_END1 0718 #define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT 0719 #define CATCH_REC_NEXT1(test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0) 0720 #define CATCH_REC_NEXT(test, next) CATCH_REC_NEXT1(CATCH_REC_GET_END test, next) 0721 0722 #define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) 0723 #define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ ) 0724 #define CATCH_REC_LIST2(f, x, peek, ...) f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) 0725 0726 #define CATCH_REC_LIST0_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) 0727 #define CATCH_REC_LIST1_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0_UD) ) ( f, userdata, peek, __VA_ARGS__ ) 0728 #define CATCH_REC_LIST2_UD(f, userdata, x, peek, ...) f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) 0729 0730 // Applies the function macro `f` to each of the remaining parameters, inserts commas between the results, 0731 // and passes userdata as the first parameter to each invocation, 0732 // e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c) 0733 #define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) 0734 0735 #define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) 0736 0737 #define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param) 0738 #define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__ 0739 #define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__ 0740 #define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF 0741 #define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__) 0742 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 0743 #define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__ 0744 #define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) 0745 #else 0746 // MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF 0747 #define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__) 0748 #define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__ 0749 #define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1) 0750 #endif 0751 0752 #define INTERNAL_CATCH_MAKE_NAMESPACE2(...) ns_##__VA_ARGS__ 0753 #define INTERNAL_CATCH_MAKE_NAMESPACE(name) INTERNAL_CATCH_MAKE_NAMESPACE2(name) 0754 0755 #define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__) 0756 0757 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 0758 #define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS_GEN(__VA_ARGS__)>()) 0759 #define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)) 0760 #else 0761 #define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) INTERNAL_CATCH_EXPAND_VARGS(decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS_GEN(__VA_ARGS__)>())) 0762 #define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))) 0763 #endif 0764 0765 #define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(...)\ 0766 CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,__VA_ARGS__) 0767 0768 #define INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_0) INTERNAL_CATCH_REMOVE_PARENS(_0) 0769 #define INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_0, _1) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_1) 0770 #define INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_0, _1, _2) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_1, _2) 0771 #define INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_0, _1, _2, _3) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_1, _2, _3) 0772 #define INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_0, _1, _2, _3, _4) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_1, _2, _3, _4) 0773 #define INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_0, _1, _2, _3, _4, _5) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_1, _2, _3, _4, _5) 0774 #define INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_0, _1, _2, _3, _4, _5, _6) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_1, _2, _3, _4, _5, _6) 0775 #define INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_0, _1, _2, _3, _4, _5, _6, _7) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_1, _2, _3, _4, _5, _6, _7) 0776 #define INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_1, _2, _3, _4, _5, _6, _7, _8) 0777 #define INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9) 0778 #define INTERNAL_CATCH_REMOVE_PARENS_11_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10) 0779 0780 #define INTERNAL_CATCH_VA_NARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N 0781 0782 #define INTERNAL_CATCH_TYPE_GEN\ 0783 template<typename...> struct TypeList {};\ 0784 template<typename...Ts>\ 0785 constexpr auto get_wrapper() noexcept -> TypeList<Ts...> { return {}; }\ 0786 template<template<typename...> class...> struct TemplateTypeList{};\ 0787 template<template<typename...> class...Cs>\ 0788 constexpr auto get_wrapper() noexcept -> TemplateTypeList<Cs...> { return {}; }\ 0789 template<typename...>\ 0790 struct append;\ 0791 template<typename...>\ 0792 struct rewrap;\ 0793 template<template<typename...> class, typename...>\ 0794 struct create;\ 0795 template<template<typename...> class, typename>\ 0796 struct convert;\ 0797 \ 0798 template<typename T> \ 0799 struct append<T> { using type = T; };\ 0800 template< template<typename...> class L1, typename...E1, template<typename...> class L2, typename...E2, typename...Rest>\ 0801 struct append<L1<E1...>, L2<E2...>, Rest...> { using type = typename append<L1<E1...,E2...>, Rest...>::type; };\ 0802 template< template<typename...> class L1, typename...E1, typename...Rest>\ 0803 struct append<L1<E1...>, TypeList<mpl_::na>, Rest...> { using type = L1<E1...>; };\ 0804 \ 0805 template< template<typename...> class Container, template<typename...> class List, typename...elems>\ 0806 struct rewrap<TemplateTypeList<Container>, List<elems...>> { using type = TypeList<Container<elems...>>; };\ 0807 template< template<typename...> class Container, template<typename...> class List, class...Elems, typename...Elements>\ 0808 struct rewrap<TemplateTypeList<Container>, List<Elems...>, Elements...> { using type = typename append<TypeList<Container<Elems...>>, typename rewrap<TemplateTypeList<Container>, Elements...>::type>::type; };\ 0809 \ 0810 template<template <typename...> class Final, template< typename...> class...Containers, typename...Types>\ 0811 struct create<Final, TemplateTypeList<Containers...>, TypeList<Types...>> { using type = typename append<Final<>, typename rewrap<TemplateTypeList<Containers>, Types...>::type...>::type; };\ 0812 template<template <typename...> class Final, template <typename...> class List, typename...Ts>\ 0813 struct convert<Final, List<Ts...>> { using type = typename append<Final<>,TypeList<Ts>...>::type; }; 0814 0815 #define INTERNAL_CATCH_NTTP_1(signature, ...)\ 0816 template<INTERNAL_CATCH_REMOVE_PARENS(signature)> struct Nttp{};\ 0817 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 0818 constexpr auto get_wrapper() noexcept -> Nttp<__VA_ARGS__> { return {}; } \ 0819 template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...> struct NttpTemplateTypeList{};\ 0820 template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...Cs>\ 0821 constexpr auto get_wrapper() noexcept -> NttpTemplateTypeList<Cs...> { return {}; } \ 0822 \ 0823 template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 0824 struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>> { using type = TypeList<Container<__VA_ARGS__>>; };\ 0825 template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature), typename...Elements>\ 0826 struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>, Elements...> { using type = typename append<TypeList<Container<__VA_ARGS__>>, typename rewrap<NttpTemplateTypeList<Container>, Elements...>::type>::type; };\ 0827 template<template <typename...> class Final, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...Containers, typename...Types>\ 0828 struct create<Final, NttpTemplateTypeList<Containers...>, TypeList<Types...>> { using type = typename append<Final<>, typename rewrap<NttpTemplateTypeList<Containers>, Types...>::type...>::type; }; 0829 0830 #define INTERNAL_CATCH_DECLARE_SIG_TEST0(TestName) 0831 #define INTERNAL_CATCH_DECLARE_SIG_TEST1(TestName, signature)\ 0832 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 0833 static void TestName() 0834 #define INTERNAL_CATCH_DECLARE_SIG_TEST_X(TestName, signature, ...)\ 0835 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 0836 static void TestName() 0837 0838 #define INTERNAL_CATCH_DEFINE_SIG_TEST0(TestName) 0839 #define INTERNAL_CATCH_DEFINE_SIG_TEST1(TestName, signature)\ 0840 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 0841 static void TestName() 0842 #define INTERNAL_CATCH_DEFINE_SIG_TEST_X(TestName, signature,...)\ 0843 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 0844 static void TestName() 0845 0846 #define INTERNAL_CATCH_NTTP_REGISTER0(TestFunc, signature)\ 0847 template<typename Type>\ 0848 void reg_test(TypeList<Type>, Catch::NameAndTags nameAndTags)\ 0849 {\ 0850 Catch::AutoReg( Catch::makeTestInvoker(&TestFunc<Type>), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), nameAndTags);\ 0851 } 0852 0853 #define INTERNAL_CATCH_NTTP_REGISTER(TestFunc, signature, ...)\ 0854 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 0855 void reg_test(Nttp<__VA_ARGS__>, Catch::NameAndTags nameAndTags)\ 0856 {\ 0857 Catch::AutoReg( Catch::makeTestInvoker(&TestFunc<__VA_ARGS__>), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), nameAndTags);\ 0858 } 0859 0860 #define INTERNAL_CATCH_NTTP_REGISTER_METHOD0(TestName, signature, ...)\ 0861 template<typename Type>\ 0862 void reg_test(TypeList<Type>, Catch::StringRef className, Catch::NameAndTags nameAndTags)\ 0863 {\ 0864 Catch::AutoReg( Catch::makeTestInvoker(&TestName<Type>::test), CATCH_INTERNAL_LINEINFO, className, nameAndTags);\ 0865 } 0866 0867 #define INTERNAL_CATCH_NTTP_REGISTER_METHOD(TestName, signature, ...)\ 0868 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 0869 void reg_test(Nttp<__VA_ARGS__>, Catch::StringRef className, Catch::NameAndTags nameAndTags)\ 0870 {\ 0871 Catch::AutoReg( Catch::makeTestInvoker(&TestName<__VA_ARGS__>::test), CATCH_INTERNAL_LINEINFO, className, nameAndTags);\ 0872 } 0873 0874 #define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0(TestName, ClassName) 0875 #define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1(TestName, ClassName, signature)\ 0876 template<typename TestType> \ 0877 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName)<TestType> { \ 0878 void test();\ 0879 } 0880 0881 #define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X(TestName, ClassName, signature, ...)\ 0882 template<INTERNAL_CATCH_REMOVE_PARENS(signature)> \ 0883 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName)<__VA_ARGS__> { \ 0884 void test();\ 0885 } 0886 0887 #define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0(TestName) 0888 #define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1(TestName, signature)\ 0889 template<typename TestType> \ 0890 void INTERNAL_CATCH_MAKE_NAMESPACE(TestName)::TestName<TestType>::test() 0891 #define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X(TestName, signature, ...)\ 0892 template<INTERNAL_CATCH_REMOVE_PARENS(signature)> \ 0893 void INTERNAL_CATCH_MAKE_NAMESPACE(TestName)::TestName<__VA_ARGS__>::test() 0894 0895 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 0896 #define INTERNAL_CATCH_NTTP_0 0897 #define INTERNAL_CATCH_NTTP_GEN(...) INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1( __VA_ARGS__), INTERNAL_CATCH_NTTP_1( __VA_ARGS__), INTERNAL_CATCH_NTTP_1( __VA_ARGS__), INTERNAL_CATCH_NTTP_1( __VA_ARGS__),INTERNAL_CATCH_NTTP_1( __VA_ARGS__), INTERNAL_CATCH_NTTP_0) 0898 #define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0)(TestName, __VA_ARGS__) 0899 #define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0)(TestName, ClassName, __VA_ARGS__) 0900 #define INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD0, INTERNAL_CATCH_NTTP_REGISTER_METHOD0)(TestName, __VA_ARGS__) 0901 #define INTERNAL_CATCH_NTTP_REG_GEN(TestFunc, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER0, INTERNAL_CATCH_NTTP_REGISTER0)(TestFunc, __VA_ARGS__) 0902 #define INTERNAL_CATCH_DEFINE_SIG_TEST(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST1, INTERNAL_CATCH_DEFINE_SIG_TEST0)(TestName, __VA_ARGS__) 0903 #define INTERNAL_CATCH_DECLARE_SIG_TEST(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST1, INTERNAL_CATCH_DECLARE_SIG_TEST0)(TestName, __VA_ARGS__) 0904 #define INTERNAL_CATCH_REMOVE_PARENS_GEN(...) INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_REMOVE_PARENS_11_ARG,INTERNAL_CATCH_REMOVE_PARENS_10_ARG,INTERNAL_CATCH_REMOVE_PARENS_9_ARG,INTERNAL_CATCH_REMOVE_PARENS_8_ARG,INTERNAL_CATCH_REMOVE_PARENS_7_ARG,INTERNAL_CATCH_REMOVE_PARENS_6_ARG,INTERNAL_CATCH_REMOVE_PARENS_5_ARG,INTERNAL_CATCH_REMOVE_PARENS_4_ARG,INTERNAL_CATCH_REMOVE_PARENS_3_ARG,INTERNAL_CATCH_REMOVE_PARENS_2_ARG,INTERNAL_CATCH_REMOVE_PARENS_1_ARG)(__VA_ARGS__) 0905 #else 0906 #define INTERNAL_CATCH_NTTP_0(signature) 0907 #define INTERNAL_CATCH_NTTP_GEN(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1,INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_0)( __VA_ARGS__)) 0908 #define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0)(TestName, __VA_ARGS__)) 0909 #define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0)(TestName, ClassName, __VA_ARGS__)) 0910 #define INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD0, INTERNAL_CATCH_NTTP_REGISTER_METHOD0)(TestName, __VA_ARGS__)) 0911 #define INTERNAL_CATCH_NTTP_REG_GEN(TestFunc, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER0, INTERNAL_CATCH_NTTP_REGISTER0)(TestFunc, __VA_ARGS__)) 0912 #define INTERNAL_CATCH_DEFINE_SIG_TEST(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST1, INTERNAL_CATCH_DEFINE_SIG_TEST0)(TestName, __VA_ARGS__)) 0913 #define INTERNAL_CATCH_DECLARE_SIG_TEST(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST1, INTERNAL_CATCH_DECLARE_SIG_TEST0)(TestName, __VA_ARGS__)) 0914 #define INTERNAL_CATCH_REMOVE_PARENS_GEN(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_REMOVE_PARENS_11_ARG,INTERNAL_CATCH_REMOVE_PARENS_10_ARG,INTERNAL_CATCH_REMOVE_PARENS_9_ARG,INTERNAL_CATCH_REMOVE_PARENS_8_ARG,INTERNAL_CATCH_REMOVE_PARENS_7_ARG,INTERNAL_CATCH_REMOVE_PARENS_6_ARG,INTERNAL_CATCH_REMOVE_PARENS_5_ARG,INTERNAL_CATCH_REMOVE_PARENS_4_ARG,INTERNAL_CATCH_REMOVE_PARENS_3_ARG,INTERNAL_CATCH_REMOVE_PARENS_2_ARG,INTERNAL_CATCH_REMOVE_PARENS_1_ARG)(__VA_ARGS__)) 0915 #endif 0916 0917 // end catch_preprocessor.hpp 0918 // start catch_meta.hpp 0919 0920 0921 #include <type_traits> 0922 0923 namespace Catch { 0924 template<typename T> 0925 struct always_false : std::false_type {}; 0926 0927 template <typename> struct true_given : std::true_type {}; 0928 struct is_callable_tester { 0929 template <typename Fun, typename... Args> 0930 true_given<decltype(std::declval<Fun>()(std::declval<Args>()...))> static test(int); 0931 template <typename...> 0932 std::false_type static test(...); 0933 }; 0934 0935 template <typename T> 0936 struct is_callable; 0937 0938 template <typename Fun, typename... Args> 0939 struct is_callable<Fun(Args...)> : decltype(is_callable_tester::test<Fun, Args...>(0)) {}; 0940 0941 #if defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703 0942 // std::result_of is deprecated in C++17 and removed in C++20. Hence, it is 0943 // replaced with std::invoke_result here. 0944 template <typename Func, typename... U> 0945 using FunctionReturnType = std::remove_reference_t<std::remove_cv_t<std::invoke_result_t<Func, U...>>>; 0946 #else 0947 // Keep ::type here because we still support C++11 0948 template <typename Func, typename... U> 0949 using FunctionReturnType = typename std::remove_reference<typename std::remove_cv<typename std::result_of<Func(U...)>::type>::type>::type; 0950 #endif 0951 0952 } // namespace Catch 0953 0954 namespace mpl_{ 0955 struct na; 0956 } 0957 0958 // end catch_meta.hpp 0959 namespace Catch { 0960 0961 template<typename C> 0962 class TestInvokerAsMethod : public ITestInvoker { 0963 void (C::*m_testAsMethod)(); 0964 public: 0965 TestInvokerAsMethod( void (C::*testAsMethod)() ) noexcept : m_testAsMethod( testAsMethod ) {} 0966 0967 void invoke() const override { 0968 C obj; 0969 (obj.*m_testAsMethod)(); 0970 } 0971 }; 0972 0973 auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker*; 0974 0975 template<typename C> 0976 auto makeTestInvoker( void (C::*testAsMethod)() ) noexcept -> ITestInvoker* { 0977 return new(std::nothrow) TestInvokerAsMethod<C>( testAsMethod ); 0978 } 0979 0980 struct NameAndTags { 0981 NameAndTags( StringRef const& name_ = StringRef(), StringRef const& tags_ = StringRef() ) noexcept; 0982 StringRef name; 0983 StringRef tags; 0984 }; 0985 0986 struct AutoReg : NonCopyable { 0987 AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept; 0988 ~AutoReg(); 0989 }; 0990 0991 } // end namespace Catch 0992 0993 #if defined(CATCH_CONFIG_DISABLE) 0994 #define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \ 0995 static void TestName() 0996 #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \ 0997 namespace{ \ 0998 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \ 0999 void test(); \ 1000 }; \ 1001 } \ 1002 void TestName::test() 1003 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( TestName, TestFunc, Name, Tags, Signature, ... ) \ 1004 INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature)) 1005 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \ 1006 namespace{ \ 1007 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) { \ 1008 INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, INTERNAL_CATCH_REMOVE_PARENS(Signature));\ 1009 } \ 1010 } \ 1011 INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature)) 1012 1013 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1014 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \ 1015 INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename TestType, __VA_ARGS__ ) 1016 #else 1017 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \ 1018 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename TestType, __VA_ARGS__ ) ) 1019 #endif 1020 1021 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1022 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \ 1023 INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ ) 1024 #else 1025 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \ 1026 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ ) ) 1027 #endif 1028 1029 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1030 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \ 1031 INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) 1032 #else 1033 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \ 1034 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) ) 1035 #endif 1036 1037 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1038 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \ 1039 INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) 1040 #else 1041 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \ 1042 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) ) 1043 #endif 1044 #endif 1045 1046 /////////////////////////////////////////////////////////////////////////////// 1047 #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ 1048 static void TestName(); \ 1049 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1050 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1051 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \ 1052 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1053 static void TestName() 1054 #define INTERNAL_CATCH_TESTCASE( ... ) \ 1055 INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ), __VA_ARGS__ ) 1056 1057 /////////////////////////////////////////////////////////////////////////////// 1058 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ 1059 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1060 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1061 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &QualifiedMethod ), CATCH_INTERNAL_LINEINFO, "&" #QualifiedMethod, Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \ 1062 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 1063 1064 /////////////////////////////////////////////////////////////////////////////// 1065 #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ 1066 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1067 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1068 namespace{ \ 1069 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \ 1070 void test(); \ 1071 }; \ 1072 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ 1073 } \ 1074 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1075 void TestName::test() 1076 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \ 1077 INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ), ClassName, __VA_ARGS__ ) 1078 1079 /////////////////////////////////////////////////////////////////////////////// 1080 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ 1081 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1082 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1083 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ 1084 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 1085 1086 /////////////////////////////////////////////////////////////////////////////// 1087 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_2(TestName, TestFunc, Name, Tags, Signature, ... )\ 1088 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1089 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1090 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ 1091 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 1092 INTERNAL_CATCH_DECLARE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature));\ 1093 namespace {\ 1094 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\ 1095 INTERNAL_CATCH_TYPE_GEN\ 1096 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\ 1097 INTERNAL_CATCH_NTTP_REG_GEN(TestFunc,INTERNAL_CATCH_REMOVE_PARENS(Signature))\ 1098 template<typename...Types> \ 1099 struct TestName{\ 1100 TestName(){\ 1101 int index = 0; \ 1102 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\ 1103 using expander = int[];\ 1104 (void)expander{(reg_test(Types{}, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };/* NOLINT */ \ 1105 }\ 1106 };\ 1107 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ 1108 TestName<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(__VA_ARGS__)>();\ 1109 return 0;\ 1110 }();\ 1111 }\ 1112 }\ 1113 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1114 INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc,INTERNAL_CATCH_REMOVE_PARENS(Signature)) 1115 1116 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1117 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \ 1118 INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename TestType, __VA_ARGS__ ) 1119 #else 1120 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \ 1121 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename TestType, __VA_ARGS__ ) ) 1122 #endif 1123 1124 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1125 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \ 1126 INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ ) 1127 #else 1128 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \ 1129 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ ) ) 1130 #endif 1131 1132 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(TestName, TestFuncName, Name, Tags, Signature, TmplTypes, TypesList) \ 1133 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1134 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1135 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ 1136 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 1137 template<typename TestType> static void TestFuncName(); \ 1138 namespace {\ 1139 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) { \ 1140 INTERNAL_CATCH_TYPE_GEN \ 1141 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature)) \ 1142 template<typename... Types> \ 1143 struct TestName { \ 1144 void reg_tests() { \ 1145 int index = 0; \ 1146 using expander = int[]; \ 1147 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\ 1148 constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\ 1149 constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\ 1150 (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFuncName<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++)... };/* NOLINT */\ 1151 } \ 1152 }; \ 1153 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \ 1154 using TestInit = typename create<TestName, decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>()), TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(INTERNAL_CATCH_REMOVE_PARENS(TypesList))>>::type; \ 1155 TestInit t; \ 1156 t.reg_tests(); \ 1157 return 0; \ 1158 }(); \ 1159 } \ 1160 } \ 1161 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1162 template<typename TestType> \ 1163 static void TestFuncName() 1164 1165 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1166 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\ 1167 INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename T,__VA_ARGS__) 1168 #else 1169 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\ 1170 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename T, __VA_ARGS__ ) ) 1171 #endif 1172 1173 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1174 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\ 1175 INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__) 1176 #else 1177 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\ 1178 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ ) ) 1179 #endif 1180 1181 #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2(TestName, TestFunc, Name, Tags, TmplList)\ 1182 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1183 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1184 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 1185 template<typename TestType> static void TestFunc(); \ 1186 namespace {\ 1187 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\ 1188 INTERNAL_CATCH_TYPE_GEN\ 1189 template<typename... Types> \ 1190 struct TestName { \ 1191 void reg_tests() { \ 1192 int index = 0; \ 1193 using expander = int[]; \ 1194 (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFunc<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */\ 1195 } \ 1196 };\ 1197 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \ 1198 using TestInit = typename convert<TestName, TmplList>::type; \ 1199 TestInit t; \ 1200 t.reg_tests(); \ 1201 return 0; \ 1202 }(); \ 1203 }}\ 1204 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1205 template<typename TestType> \ 1206 static void TestFunc() 1207 1208 #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(Name, Tags, TmplList) \ 1209 INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, TmplList ) 1210 1211 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \ 1212 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1213 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1214 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ 1215 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 1216 namespace {\ 1217 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \ 1218 INTERNAL_CATCH_TYPE_GEN\ 1219 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\ 1220 INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, INTERNAL_CATCH_REMOVE_PARENS(Signature));\ 1221 INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))\ 1222 template<typename...Types> \ 1223 struct TestNameClass{\ 1224 TestNameClass(){\ 1225 int index = 0; \ 1226 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\ 1227 using expander = int[];\ 1228 (void)expander{(reg_test(Types{}, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };/* NOLINT */ \ 1229 }\ 1230 };\ 1231 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ 1232 TestNameClass<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(__VA_ARGS__)>();\ 1233 return 0;\ 1234 }();\ 1235 }\ 1236 }\ 1237 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1238 INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature)) 1239 1240 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1241 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \ 1242 INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) 1243 #else 1244 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \ 1245 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) ) 1246 #endif 1247 1248 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1249 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \ 1250 INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) 1251 #else 1252 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \ 1253 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) ) 1254 #endif 1255 1256 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2(TestNameClass, TestName, ClassName, Name, Tags, Signature, TmplTypes, TypesList)\ 1257 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1258 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1259 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ 1260 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 1261 template<typename TestType> \ 1262 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \ 1263 void test();\ 1264 };\ 1265 namespace {\ 1266 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestNameClass) {\ 1267 INTERNAL_CATCH_TYPE_GEN \ 1268 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\ 1269 template<typename...Types>\ 1270 struct TestNameClass{\ 1271 void reg_tests(){\ 1272 int index = 0;\ 1273 using expander = int[];\ 1274 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\ 1275 constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\ 1276 constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\ 1277 (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++)... };/* NOLINT */ \ 1278 }\ 1279 };\ 1280 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ 1281 using TestInit = typename create<TestNameClass, decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>()), TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(INTERNAL_CATCH_REMOVE_PARENS(TypesList))>>::type;\ 1282 TestInit t;\ 1283 t.reg_tests();\ 1284 return 0;\ 1285 }(); \ 1286 }\ 1287 }\ 1288 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1289 template<typename TestType> \ 1290 void TestName<TestType>::test() 1291 1292 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1293 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\ 1294 INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, typename T, __VA_ARGS__ ) 1295 #else 1296 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\ 1297 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, typename T,__VA_ARGS__ ) ) 1298 #endif 1299 1300 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1301 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\ 1302 INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, Signature, __VA_ARGS__ ) 1303 #else 1304 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\ 1305 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, Signature,__VA_ARGS__ ) ) 1306 #endif 1307 1308 #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, TmplList) \ 1309 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1310 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1311 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 1312 template<typename TestType> \ 1313 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \ 1314 void test();\ 1315 };\ 1316 namespace {\ 1317 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \ 1318 INTERNAL_CATCH_TYPE_GEN\ 1319 template<typename...Types>\ 1320 struct TestNameClass{\ 1321 void reg_tests(){\ 1322 int index = 0;\ 1323 using expander = int[];\ 1324 (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */ \ 1325 }\ 1326 };\ 1327 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ 1328 using TestInit = typename convert<TestNameClass, TmplList>::type;\ 1329 TestInit t;\ 1330 t.reg_tests();\ 1331 return 0;\ 1332 }(); \ 1333 }}\ 1334 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1335 template<typename TestType> \ 1336 void TestName<TestType>::test() 1337 1338 #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD(ClassName, Name, Tags, TmplList) \ 1339 INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, TmplList ) 1340 1341 // end catch_test_registry.h 1342 // start catch_capture.hpp 1343 1344 // start catch_assertionhandler.h 1345 1346 // start catch_assertioninfo.h 1347 1348 // start catch_result_type.h 1349 1350 namespace Catch { 1351 1352 // ResultWas::OfType enum 1353 struct ResultWas { enum OfType { 1354 Unknown = -1, 1355 Ok = 0, 1356 Info = 1, 1357 Warning = 2, 1358 1359 FailureBit = 0x10, 1360 1361 ExpressionFailed = FailureBit | 1, 1362 ExplicitFailure = FailureBit | 2, 1363 1364 Exception = 0x100 | FailureBit, 1365 1366 ThrewException = Exception | 1, 1367 DidntThrowException = Exception | 2, 1368 1369 FatalErrorCondition = 0x200 | FailureBit 1370 1371 }; }; 1372 1373 bool isOk( ResultWas::OfType resultType ); 1374 bool isJustInfo( int flags ); 1375 1376 // ResultDisposition::Flags enum 1377 struct ResultDisposition { enum Flags { 1378 Normal = 0x01, 1379 1380 ContinueOnFailure = 0x02, // Failures fail test, but execution continues 1381 FalseTest = 0x04, // Prefix expression with ! 1382 SuppressFail = 0x08 // Failures are reported but do not fail the test 1383 }; }; 1384 1385 ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ); 1386 1387 bool shouldContinueOnFailure( int flags ); 1388 inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; } 1389 bool shouldSuppressFailure( int flags ); 1390 1391 } // end namespace Catch 1392 1393 // end catch_result_type.h 1394 namespace Catch { 1395 1396 struct AssertionInfo 1397 { 1398 StringRef macroName; 1399 SourceLineInfo lineInfo; 1400 StringRef capturedExpression; 1401 ResultDisposition::Flags resultDisposition; 1402 1403 // We want to delete this constructor but a compiler bug in 4.8 means 1404 // the struct is then treated as non-aggregate 1405 //AssertionInfo() = delete; 1406 }; 1407 1408 } // end namespace Catch 1409 1410 // end catch_assertioninfo.h 1411 // start catch_decomposer.h 1412 1413 // start catch_tostring.h 1414 1415 #include <vector> 1416 #include <cstddef> 1417 #include <type_traits> 1418 #include <string> 1419 // start catch_stream.h 1420 1421 #include <iosfwd> 1422 #include <cstddef> 1423 #include <ostream> 1424 1425 namespace Catch { 1426 1427 std::ostream& cout(); 1428 std::ostream& cerr(); 1429 std::ostream& clog(); 1430 1431 class StringRef; 1432 1433 struct IStream { 1434 virtual ~IStream(); 1435 virtual std::ostream& stream() const = 0; 1436 }; 1437 1438 auto makeStream( StringRef const &filename ) -> IStream const*; 1439 1440 class ReusableStringStream : NonCopyable { 1441 std::size_t m_index; 1442 std::ostream* m_oss; 1443 public: 1444 ReusableStringStream(); 1445 ~ReusableStringStream(); 1446 1447 auto str() const -> std::string; 1448 1449 template<typename T> 1450 auto operator << ( T const& value ) -> ReusableStringStream& { 1451 *m_oss << value; 1452 return *this; 1453 } 1454 auto get() -> std::ostream& { return *m_oss; } 1455 }; 1456 } 1457 1458 // end catch_stream.h 1459 // start catch_interfaces_enum_values_registry.h 1460 1461 #include <vector> 1462 1463 namespace Catch { 1464 1465 namespace Detail { 1466 struct EnumInfo { 1467 StringRef m_name; 1468 std::vector<std::pair<int, StringRef>> m_values; 1469 1470 ~EnumInfo(); 1471 1472 StringRef lookup( int value ) const; 1473 }; 1474 } // namespace Detail 1475 1476 struct IMutableEnumValuesRegistry { 1477 virtual ~IMutableEnumValuesRegistry(); 1478 1479 virtual Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::vector<int> const& values ) = 0; 1480 1481 template<typename E> 1482 Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::initializer_list<E> values ) { 1483 static_assert(sizeof(int) >= sizeof(E), "Cannot serialize enum to int"); 1484 std::vector<int> intValues; 1485 intValues.reserve( values.size() ); 1486 for( auto enumValue : values ) 1487 intValues.push_back( static_cast<int>( enumValue ) ); 1488 return registerEnum( enumName, allEnums, intValues ); 1489 } 1490 }; 1491 1492 } // Catch 1493 1494 // end catch_interfaces_enum_values_registry.h 1495 1496 #ifdef CATCH_CONFIG_CPP17_STRING_VIEW 1497 #include <string_view> 1498 #endif 1499 1500 #ifdef __OBJC__ 1501 // start catch_objc_arc.hpp 1502 1503 #import <Foundation/Foundation.h> 1504 1505 #ifdef __has_feature 1506 #define CATCH_ARC_ENABLED __has_feature(objc_arc) 1507 #else 1508 #define CATCH_ARC_ENABLED 0 1509 #endif 1510 1511 void arcSafeRelease( NSObject* obj ); 1512 id performOptionalSelector( id obj, SEL sel ); 1513 1514 #if !CATCH_ARC_ENABLED 1515 inline void arcSafeRelease( NSObject* obj ) { 1516 [obj release]; 1517 } 1518 inline id performOptionalSelector( id obj, SEL sel ) { 1519 if( [obj respondsToSelector: sel] ) 1520 return [obj performSelector: sel]; 1521 return nil; 1522 } 1523 #define CATCH_UNSAFE_UNRETAINED 1524 #define CATCH_ARC_STRONG 1525 #else 1526 inline void arcSafeRelease( NSObject* ){} 1527 inline id performOptionalSelector( id obj, SEL sel ) { 1528 #ifdef __clang__ 1529 #pragma clang diagnostic push 1530 #pragma clang diagnostic ignored "-Warc-performSelector-leaks" 1531 #endif 1532 if( [obj respondsToSelector: sel] ) 1533 return [obj performSelector: sel]; 1534 #ifdef __clang__ 1535 #pragma clang diagnostic pop 1536 #endif 1537 return nil; 1538 } 1539 #define CATCH_UNSAFE_UNRETAINED __unsafe_unretained 1540 #define CATCH_ARC_STRONG __strong 1541 #endif 1542 1543 // end catch_objc_arc.hpp 1544 #endif 1545 1546 #ifdef _MSC_VER 1547 #pragma warning(push) 1548 #pragma warning(disable:4180) // We attempt to stream a function (address) by const&, which MSVC complains about but is harmless 1549 #endif 1550 1551 namespace Catch { 1552 namespace Detail { 1553 1554 extern const std::string unprintableString; 1555 1556 std::string rawMemoryToString( const void *object, std::size_t size ); 1557 1558 template<typename T> 1559 std::string rawMemoryToString( const T& object ) { 1560 return rawMemoryToString( &object, sizeof(object) ); 1561 } 1562 1563 template<typename T> 1564 class IsStreamInsertable { 1565 template<typename Stream, typename U> 1566 static auto test(int) 1567 -> decltype(std::declval<Stream&>() << std::declval<U>(), std::true_type()); 1568 1569 template<typename, typename> 1570 static auto test(...)->std::false_type; 1571 1572 public: 1573 static const bool value = decltype(test<std::ostream, const T&>(0))::value; 1574 }; 1575 1576 template<typename E> 1577 std::string convertUnknownEnumToString( E e ); 1578 1579 template<typename T> 1580 typename std::enable_if< 1581 !std::is_enum<T>::value && !std::is_base_of<std::exception, T>::value, 1582 std::string>::type convertUnstreamable( T const& ) { 1583 return Detail::unprintableString; 1584 } 1585 template<typename T> 1586 typename std::enable_if< 1587 !std::is_enum<T>::value && std::is_base_of<std::exception, T>::value, 1588 std::string>::type convertUnstreamable(T const& ex) { 1589 return ex.what(); 1590 } 1591 1592 template<typename T> 1593 typename std::enable_if< 1594 std::is_enum<T>::value 1595 , std::string>::type convertUnstreamable( T const& value ) { 1596 return convertUnknownEnumToString( value ); 1597 } 1598 1599 #if defined(_MANAGED) 1600 //! Convert a CLR string to a utf8 std::string 1601 template<typename T> 1602 std::string clrReferenceToString( T^ ref ) { 1603 if (ref == nullptr) 1604 return std::string("null"); 1605 auto bytes = System::Text::Encoding::UTF8->GetBytes(ref->ToString()); 1606 cli::pin_ptr<System::Byte> p = &bytes[0]; 1607 return std::string(reinterpret_cast<char const *>(p), bytes->Length); 1608 } 1609 #endif 1610 1611 } // namespace Detail 1612 1613 // If we decide for C++14, change these to enable_if_ts 1614 template <typename T, typename = void> 1615 struct StringMaker { 1616 template <typename Fake = T> 1617 static 1618 typename std::enable_if<::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type 1619 convert(const Fake& value) { 1620 ReusableStringStream rss; 1621 // NB: call using the function-like syntax to avoid ambiguity with 1622 // user-defined templated operator<< under clang. 1623 rss.operator<<(value); 1624 return rss.str(); 1625 } 1626 1627 template <typename Fake = T> 1628 static 1629 typename std::enable_if<!::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type 1630 convert( const Fake& value ) { 1631 #if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER) 1632 return Detail::convertUnstreamable(value); 1633 #else 1634 return CATCH_CONFIG_FALLBACK_STRINGIFIER(value); 1635 #endif 1636 } 1637 }; 1638 1639 namespace Detail { 1640 1641 // This function dispatches all stringification requests inside of Catch. 1642 // Should be preferably called fully qualified, like ::Catch::Detail::stringify 1643 template <typename T> 1644 std::string stringify(const T& e) { 1645 return ::Catch::StringMaker<typename std::remove_cv<typename std::remove_reference<T>::type>::type>::convert(e); 1646 } 1647 1648 template<typename E> 1649 std::string convertUnknownEnumToString( E e ) { 1650 return ::Catch::Detail::stringify(static_cast<typename std::underlying_type<E>::type>(e)); 1651 } 1652 1653 #if defined(_MANAGED) 1654 template <typename T> 1655 std::string stringify( T^ e ) { 1656 return ::Catch::StringMaker<T^>::convert(e); 1657 } 1658 #endif 1659 1660 } // namespace Detail 1661 1662 // Some predefined specializations 1663 1664 template<> 1665 struct StringMaker<std::string> { 1666 static std::string convert(const std::string& str); 1667 }; 1668 1669 #ifdef CATCH_CONFIG_CPP17_STRING_VIEW 1670 template<> 1671 struct StringMaker<std::string_view> { 1672 static std::string convert(std::string_view str); 1673 }; 1674 #endif 1675 1676 template<> 1677 struct StringMaker<char const *> { 1678 static std::string convert(char const * str); 1679 }; 1680 template<> 1681 struct StringMaker<char *> { 1682 static std::string convert(char * str); 1683 }; 1684 1685 #ifdef CATCH_CONFIG_WCHAR 1686 template<> 1687 struct StringMaker<std::wstring> { 1688 static std::string convert(const std::wstring& wstr); 1689 }; 1690 1691 # ifdef CATCH_CONFIG_CPP17_STRING_VIEW 1692 template<> 1693 struct StringMaker<std::wstring_view> { 1694 static std::string convert(std::wstring_view str); 1695 }; 1696 # endif 1697 1698 template<> 1699 struct StringMaker<wchar_t const *> { 1700 static std::string convert(wchar_t const * str); 1701 }; 1702 template<> 1703 struct StringMaker<wchar_t *> { 1704 static std::string convert(wchar_t * str); 1705 }; 1706 #endif 1707 1708 // TBD: Should we use `strnlen` to ensure that we don't go out of the buffer, 1709 // while keeping string semantics? 1710 template<int SZ> 1711 struct StringMaker<char[SZ]> { 1712 static std::string convert(char const* str) { 1713 return ::Catch::Detail::stringify(std::string{ str }); 1714 } 1715 }; 1716 template<int SZ> 1717 struct StringMaker<signed char[SZ]> { 1718 static std::string convert(signed char const* str) { 1719 return ::Catch::Detail::stringify(std::string{ reinterpret_cast<char const *>(str) }); 1720 } 1721 }; 1722 template<int SZ> 1723 struct StringMaker<unsigned char[SZ]> { 1724 static std::string convert(unsigned char const* str) { 1725 return ::Catch::Detail::stringify(std::string{ reinterpret_cast<char const *>(str) }); 1726 } 1727 }; 1728 1729 #if defined(CATCH_CONFIG_CPP17_BYTE) 1730 template<> 1731 struct StringMaker<std::byte> { 1732 static std::string convert(std::byte value); 1733 }; 1734 #endif // defined(CATCH_CONFIG_CPP17_BYTE) 1735 template<> 1736 struct StringMaker<int> { 1737 static std::string convert(int value); 1738 }; 1739 template<> 1740 struct StringMaker<long> { 1741 static std::string convert(long value); 1742 }; 1743 template<> 1744 struct StringMaker<long long> { 1745 static std::string convert(long long value); 1746 }; 1747 template<> 1748 struct StringMaker<unsigned int> { 1749 static std::string convert(unsigned int value); 1750 }; 1751 template<> 1752 struct StringMaker<unsigned long> { 1753 static std::string convert(unsigned long value); 1754 }; 1755 template<> 1756 struct StringMaker<unsigned long long> { 1757 static std::string convert(unsigned long long value); 1758 }; 1759 1760 template<> 1761 struct StringMaker<bool> { 1762 static std::string convert(bool b); 1763 }; 1764 1765 template<> 1766 struct StringMaker<char> { 1767 static std::string convert(char c); 1768 }; 1769 template<> 1770 struct StringMaker<signed char> { 1771 static std::string convert(signed char c); 1772 }; 1773 template<> 1774 struct StringMaker<unsigned char> { 1775 static std::string convert(unsigned char c); 1776 }; 1777 1778 template<> 1779 struct StringMaker<std::nullptr_t> { 1780 static std::string convert(std::nullptr_t); 1781 }; 1782 1783 template<> 1784 struct StringMaker<float> { 1785 static std::string convert(float value); 1786 static int precision; 1787 }; 1788 1789 template<> 1790 struct StringMaker<double> { 1791 static std::string convert(double value); 1792 static int precision; 1793 }; 1794 1795 template <typename T> 1796 struct StringMaker<T*> { 1797 template <typename U> 1798 static std::string convert(U* p) { 1799 if (p) { 1800 return ::Catch::Detail::rawMemoryToString(p); 1801 } else { 1802 return "nullptr"; 1803 } 1804 } 1805 }; 1806 1807 template <typename R, typename C> 1808 struct StringMaker<R C::*> { 1809 static std::string convert(R C::* p) { 1810 if (p) { 1811 return ::Catch::Detail::rawMemoryToString(p); 1812 } else { 1813 return "nullptr"; 1814 } 1815 } 1816 }; 1817 1818 #if defined(_MANAGED) 1819 template <typename T> 1820 struct StringMaker<T^> { 1821 static std::string convert( T^ ref ) { 1822 return ::Catch::Detail::clrReferenceToString(ref); 1823 } 1824 }; 1825 #endif 1826 1827 namespace Detail { 1828 template<typename InputIterator, typename Sentinel = InputIterator> 1829 std::string rangeToString(InputIterator first, Sentinel last) { 1830 ReusableStringStream rss; 1831 rss << "{ "; 1832 if (first != last) { 1833 rss << ::Catch::Detail::stringify(*first); 1834 for (++first; first != last; ++first) 1835 rss << ", " << ::Catch::Detail::stringify(*first); 1836 } 1837 rss << " }"; 1838 return rss.str(); 1839 } 1840 } 1841 1842 #ifdef __OBJC__ 1843 template<> 1844 struct StringMaker<NSString*> { 1845 static std::string convert(NSString * nsstring) { 1846 if (!nsstring) 1847 return "nil"; 1848 return std::string("@") + [nsstring UTF8String]; 1849 } 1850 }; 1851 template<> 1852 struct StringMaker<NSObject*> { 1853 static std::string convert(NSObject* nsObject) { 1854 return ::Catch::Detail::stringify([nsObject description]); 1855 } 1856 1857 }; 1858 namespace Detail { 1859 inline std::string stringify( NSString* nsstring ) { 1860 return StringMaker<NSString*>::convert( nsstring ); 1861 } 1862 1863 } // namespace Detail 1864 #endif // __OBJC__ 1865 1866 } // namespace Catch 1867 1868 ////////////////////////////////////////////////////// 1869 // Separate std-lib types stringification, so it can be selectively enabled 1870 // This means that we do not bring in 1871 1872 #if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS) 1873 # define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER 1874 # define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER 1875 # define CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER 1876 # define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER 1877 # define CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER 1878 #endif 1879 1880 // Separate std::pair specialization 1881 #if defined(CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER) 1882 #include <utility> 1883 namespace Catch { 1884 template<typename T1, typename T2> 1885 struct StringMaker<std::pair<T1, T2> > { 1886 static std::string convert(const std::pair<T1, T2>& pair) { 1887 ReusableStringStream rss; 1888 rss << "{ " 1889 << ::Catch::Detail::stringify(pair.first) 1890 << ", " 1891 << ::Catch::Detail::stringify(pair.second) 1892 << " }"; 1893 return rss.str(); 1894 } 1895 }; 1896 } 1897 #endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER 1898 1899 #if defined(CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_OPTIONAL) 1900 #include <optional> 1901 namespace Catch { 1902 template<typename T> 1903 struct StringMaker<std::optional<T> > { 1904 static std::string convert(const std::optional<T>& optional) { 1905 ReusableStringStream rss; 1906 if (optional.has_value()) { 1907 rss << ::Catch::Detail::stringify(*optional); 1908 } else { 1909 rss << "{ }"; 1910 } 1911 return rss.str(); 1912 } 1913 }; 1914 } 1915 #endif // CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER 1916 1917 // Separate std::tuple specialization 1918 #if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER) 1919 #include <tuple> 1920 namespace Catch { 1921 namespace Detail { 1922 template< 1923 typename Tuple, 1924 std::size_t N = 0, 1925 bool = (N < std::tuple_size<Tuple>::value) 1926 > 1927 struct TupleElementPrinter { 1928 static void print(const Tuple& tuple, std::ostream& os) { 1929 os << (N ? ", " : " ") 1930 << ::Catch::Detail::stringify(std::get<N>(tuple)); 1931 TupleElementPrinter<Tuple, N + 1>::print(tuple, os); 1932 } 1933 }; 1934 1935 template< 1936 typename Tuple, 1937 std::size_t N 1938 > 1939 struct TupleElementPrinter<Tuple, N, false> { 1940 static void print(const Tuple&, std::ostream&) {} 1941 }; 1942 1943 } 1944 1945 template<typename ...Types> 1946 struct StringMaker<std::tuple<Types...>> { 1947 static std::string convert(const std::tuple<Types...>& tuple) { 1948 ReusableStringStream rss; 1949 rss << '{'; 1950 Detail::TupleElementPrinter<std::tuple<Types...>>::print(tuple, rss.get()); 1951 rss << " }"; 1952 return rss.str(); 1953 } 1954 }; 1955 } 1956 #endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER 1957 1958 #if defined(CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_VARIANT) 1959 #include <variant> 1960 namespace Catch { 1961 template<> 1962 struct StringMaker<std::monostate> { 1963 static std::string convert(const std::monostate&) { 1964 return "{ }"; 1965 } 1966 }; 1967 1968 template<typename... Elements> 1969 struct StringMaker<std::variant<Elements...>> { 1970 static std::string convert(const std::variant<Elements...>& variant) { 1971 if (variant.valueless_by_exception()) { 1972 return "{valueless variant}"; 1973 } else { 1974 return std::visit( 1975 [](const auto& value) { 1976 return ::Catch::Detail::stringify(value); 1977 }, 1978 variant 1979 ); 1980 } 1981 } 1982 }; 1983 } 1984 #endif // CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER 1985 1986 namespace Catch { 1987 // Import begin/ end from std here 1988 using std::begin; 1989 using std::end; 1990 1991 namespace detail { 1992 template <typename...> 1993 struct void_type { 1994 using type = void; 1995 }; 1996 1997 template <typename T, typename = void> 1998 struct is_range_impl : std::false_type { 1999 }; 2000 2001 template <typename T> 2002 struct is_range_impl<T, typename void_type<decltype(begin(std::declval<T>()))>::type> : std::true_type { 2003 }; 2004 } // namespace detail 2005 2006 template <typename T> 2007 struct is_range : detail::is_range_impl<T> { 2008 }; 2009 2010 #if defined(_MANAGED) // Managed types are never ranges 2011 template <typename T> 2012 struct is_range<T^> { 2013 static const bool value = false; 2014 }; 2015 #endif 2016 2017 template<typename Range> 2018 std::string rangeToString( Range const& range ) { 2019 return ::Catch::Detail::rangeToString( begin( range ), end( range ) ); 2020 } 2021 2022 // Handle vector<bool> specially 2023 template<typename Allocator> 2024 std::string rangeToString( std::vector<bool, Allocator> const& v ) { 2025 ReusableStringStream rss; 2026 rss << "{ "; 2027 bool first = true; 2028 for( bool b : v ) { 2029 if( first ) 2030 first = false; 2031 else 2032 rss << ", "; 2033 rss << ::Catch::Detail::stringify( b ); 2034 } 2035 rss << " }"; 2036 return rss.str(); 2037 } 2038 2039 template<typename R> 2040 struct StringMaker<R, typename std::enable_if<is_range<R>::value && !::Catch::Detail::IsStreamInsertable<R>::value>::type> { 2041 static std::string convert( R const& range ) { 2042 return rangeToString( range ); 2043 } 2044 }; 2045 2046 template <typename T, int SZ> 2047 struct StringMaker<T[SZ]> { 2048 static std::string convert(T const(&arr)[SZ]) { 2049 return rangeToString(arr); 2050 } 2051 }; 2052 2053 } // namespace Catch 2054 2055 // Separate std::chrono::duration specialization 2056 #if defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) 2057 #include <ctime> 2058 #include <ratio> 2059 #include <chrono> 2060 2061 namespace Catch { 2062 2063 template <class Ratio> 2064 struct ratio_string { 2065 static std::string symbol(); 2066 }; 2067 2068 template <class Ratio> 2069 std::string ratio_string<Ratio>::symbol() { 2070 Catch::ReusableStringStream rss; 2071 rss << '[' << Ratio::num << '/' 2072 << Ratio::den << ']'; 2073 return rss.str(); 2074 } 2075 template <> 2076 struct ratio_string<std::atto> { 2077 static std::string symbol(); 2078 }; 2079 template <> 2080 struct ratio_string<std::femto> { 2081 static std::string symbol(); 2082 }; 2083 template <> 2084 struct ratio_string<std::pico> { 2085 static std::string symbol(); 2086 }; 2087 template <> 2088 struct ratio_string<std::nano> { 2089 static std::string symbol(); 2090 }; 2091 template <> 2092 struct ratio_string<std::micro> { 2093 static std::string symbol(); 2094 }; 2095 template <> 2096 struct ratio_string<std::milli> { 2097 static std::string symbol(); 2098 }; 2099 2100 //////////// 2101 // std::chrono::duration specializations 2102 template<typename Value, typename Ratio> 2103 struct StringMaker<std::chrono::duration<Value, Ratio>> { 2104 static std::string convert(std::chrono::duration<Value, Ratio> const& duration) { 2105 ReusableStringStream rss; 2106 rss << duration.count() << ' ' << ratio_string<Ratio>::symbol() << 's'; 2107 return rss.str(); 2108 } 2109 }; 2110 template<typename Value> 2111 struct StringMaker<std::chrono::duration<Value, std::ratio<1>>> { 2112 static std::string convert(std::chrono::duration<Value, std::ratio<1>> const& duration) { 2113 ReusableStringStream rss; 2114 rss << duration.count() << " s"; 2115 return rss.str(); 2116 } 2117 }; 2118 template<typename Value> 2119 struct StringMaker<std::chrono::duration<Value, std::ratio<60>>> { 2120 static std::string convert(std::chrono::duration<Value, std::ratio<60>> const& duration) { 2121 ReusableStringStream rss; 2122 rss << duration.count() << " m"; 2123 return rss.str(); 2124 } 2125 }; 2126 template<typename Value> 2127 struct StringMaker<std::chrono::duration<Value, std::ratio<3600>>> { 2128 static std::string convert(std::chrono::duration<Value, std::ratio<3600>> const& duration) { 2129 ReusableStringStream rss; 2130 rss << duration.count() << " h"; 2131 return rss.str(); 2132 } 2133 }; 2134 2135 //////////// 2136 // std::chrono::time_point specialization 2137 // Generic time_point cannot be specialized, only std::chrono::time_point<system_clock> 2138 template<typename Clock, typename Duration> 2139 struct StringMaker<std::chrono::time_point<Clock, Duration>> { 2140 static std::string convert(std::chrono::time_point<Clock, Duration> const& time_point) { 2141 return ::Catch::Detail::stringify(time_point.time_since_epoch()) + " since epoch"; 2142 } 2143 }; 2144 // std::chrono::time_point<system_clock> specialization 2145 template<typename Duration> 2146 struct StringMaker<std::chrono::time_point<std::chrono::system_clock, Duration>> { 2147 static std::string convert(std::chrono::time_point<std::chrono::system_clock, Duration> const& time_point) { 2148 auto converted = std::chrono::system_clock::to_time_t(time_point); 2149 2150 #ifdef _MSC_VER 2151 std::tm timeInfo = {}; 2152 gmtime_s(&timeInfo, &converted); 2153 #else 2154 std::tm* timeInfo = std::gmtime(&converted); 2155 #endif 2156 2157 auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); 2158 char timeStamp[timeStampSize]; 2159 const char * const fmt = "%Y-%m-%dT%H:%M:%SZ"; 2160 2161 #ifdef _MSC_VER 2162 std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); 2163 #else 2164 std::strftime(timeStamp, timeStampSize, fmt, timeInfo); 2165 #endif 2166 return std::string(timeStamp); 2167 } 2168 }; 2169 } 2170 #endif // CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER 2171 2172 #define INTERNAL_CATCH_REGISTER_ENUM( enumName, ... ) \ 2173 namespace Catch { \ 2174 template<> struct StringMaker<enumName> { \ 2175 static std::string convert( enumName value ) { \ 2176 static const auto& enumInfo = ::Catch::getMutableRegistryHub().getMutableEnumValuesRegistry().registerEnum( #enumName, #__VA_ARGS__, { __VA_ARGS__ } ); \ 2177 return static_cast<std::string>(enumInfo.lookup( static_cast<int>( value ) )); \ 2178 } \ 2179 }; \ 2180 } 2181 2182 #define CATCH_REGISTER_ENUM( enumName, ... ) INTERNAL_CATCH_REGISTER_ENUM( enumName, __VA_ARGS__ ) 2183 2184 #ifdef _MSC_VER 2185 #pragma warning(pop) 2186 #endif 2187 2188 // end catch_tostring.h 2189 #include <iosfwd> 2190 2191 #ifdef _MSC_VER 2192 #pragma warning(push) 2193 #pragma warning(disable:4389) // '==' : signed/unsigned mismatch 2194 #pragma warning(disable:4018) // more "signed/unsigned mismatch" 2195 #pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform) 2196 #pragma warning(disable:4180) // qualifier applied to function type has no meaning 2197 #pragma warning(disable:4800) // Forcing result to true or false 2198 #endif 2199 2200 namespace Catch { 2201 2202 struct ITransientExpression { 2203 auto isBinaryExpression() const -> bool { return m_isBinaryExpression; } 2204 auto getResult() const -> bool { return m_result; } 2205 virtual void streamReconstructedExpression( std::ostream &os ) const = 0; 2206 2207 ITransientExpression( bool isBinaryExpression, bool result ) 2208 : m_isBinaryExpression( isBinaryExpression ), 2209 m_result( result ) 2210 {} 2211 2212 // We don't actually need a virtual destructor, but many static analysers 2213 // complain if it's not here :-( 2214 virtual ~ITransientExpression(); 2215 2216 bool m_isBinaryExpression; 2217 bool m_result; 2218 2219 }; 2220 2221 void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ); 2222 2223 template<typename LhsT, typename RhsT> 2224 class BinaryExpr : public ITransientExpression { 2225 LhsT m_lhs; 2226 StringRef m_op; 2227 RhsT m_rhs; 2228 2229 void streamReconstructedExpression( std::ostream &os ) const override { 2230 formatReconstructedExpression 2231 ( os, Catch::Detail::stringify( m_lhs ), m_op, Catch::Detail::stringify( m_rhs ) ); 2232 } 2233 2234 public: 2235 BinaryExpr( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs ) 2236 : ITransientExpression{ true, comparisonResult }, 2237 m_lhs( lhs ), 2238 m_op( op ), 2239 m_rhs( rhs ) 2240 {} 2241 2242 template<typename T> 2243 auto operator && ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 2244 static_assert(always_false<T>::value, 2245 "chained comparisons are not supported inside assertions, " 2246 "wrap the expression inside parentheses, or decompose it"); 2247 } 2248 2249 template<typename T> 2250 auto operator || ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 2251 static_assert(always_false<T>::value, 2252 "chained comparisons are not supported inside assertions, " 2253 "wrap the expression inside parentheses, or decompose it"); 2254 } 2255 2256 template<typename T> 2257 auto operator == ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 2258 static_assert(always_false<T>::value, 2259 "chained comparisons are not supported inside assertions, " 2260 "wrap the expression inside parentheses, or decompose it"); 2261 } 2262 2263 template<typename T> 2264 auto operator != ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 2265 static_assert(always_false<T>::value, 2266 "chained comparisons are not supported inside assertions, " 2267 "wrap the expression inside parentheses, or decompose it"); 2268 } 2269 2270 template<typename T> 2271 auto operator > ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 2272 static_assert(always_false<T>::value, 2273 "chained comparisons are not supported inside assertions, " 2274 "wrap the expression inside parentheses, or decompose it"); 2275 } 2276 2277 template<typename T> 2278 auto operator < ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 2279 static_assert(always_false<T>::value, 2280 "chained comparisons are not supported inside assertions, " 2281 "wrap the expression inside parentheses, or decompose it"); 2282 } 2283 2284 template<typename T> 2285 auto operator >= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 2286 static_assert(always_false<T>::value, 2287 "chained comparisons are not supported inside assertions, " 2288 "wrap the expression inside parentheses, or decompose it"); 2289 } 2290 2291 template<typename T> 2292 auto operator <= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 2293 static_assert(always_false<T>::value, 2294 "chained comparisons are not supported inside assertions, " 2295 "wrap the expression inside parentheses, or decompose it"); 2296 } 2297 }; 2298 2299 template<typename LhsT> 2300 class UnaryExpr : public ITransientExpression { 2301 LhsT m_lhs; 2302 2303 void streamReconstructedExpression( std::ostream &os ) const override { 2304 os << Catch::Detail::stringify( m_lhs ); 2305 } 2306 2307 public: 2308 explicit UnaryExpr( LhsT lhs ) 2309 : ITransientExpression{ false, static_cast<bool>(lhs) }, 2310 m_lhs( lhs ) 2311 {} 2312 }; 2313 2314 // Specialised comparison functions to handle equality comparisons between ints and pointers (NULL deduces as an int) 2315 template<typename LhsT, typename RhsT> 2316 auto compareEqual( LhsT const& lhs, RhsT const& rhs ) -> bool { return static_cast<bool>(lhs == rhs); } 2317 template<typename T> 2318 auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); } 2319 template<typename T> 2320 auto compareEqual( T* const& lhs, long rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); } 2321 template<typename T> 2322 auto compareEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; } 2323 template<typename T> 2324 auto compareEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; } 2325 2326 template<typename LhsT, typename RhsT> 2327 auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return static_cast<bool>(lhs != rhs); } 2328 template<typename T> 2329 auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); } 2330 template<typename T> 2331 auto compareNotEqual( T* const& lhs, long rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); } 2332 template<typename T> 2333 auto compareNotEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) != rhs; } 2334 template<typename T> 2335 auto compareNotEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) != rhs; } 2336 2337 template<typename LhsT> 2338 class ExprLhs { 2339 LhsT m_lhs; 2340 public: 2341 explicit ExprLhs( LhsT lhs ) : m_lhs( lhs ) {} 2342 2343 template<typename RhsT> 2344 auto operator == ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const { 2345 return { compareEqual( m_lhs, rhs ), m_lhs, "==", rhs }; 2346 } 2347 auto operator == ( bool rhs ) -> BinaryExpr<LhsT, bool> const { 2348 return { m_lhs == rhs, m_lhs, "==", rhs }; 2349 } 2350 2351 template<typename RhsT> 2352 auto operator != ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const { 2353 return { compareNotEqual( m_lhs, rhs ), m_lhs, "!=", rhs }; 2354 } 2355 auto operator != ( bool rhs ) -> BinaryExpr<LhsT, bool> const { 2356 return { m_lhs != rhs, m_lhs, "!=", rhs }; 2357 } 2358 2359 template<typename RhsT> 2360 auto operator > ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const { 2361 return { static_cast<bool>(m_lhs > rhs), m_lhs, ">", rhs }; 2362 } 2363 template<typename RhsT> 2364 auto operator < ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const { 2365 return { static_cast<bool>(m_lhs < rhs), m_lhs, "<", rhs }; 2366 } 2367 template<typename RhsT> 2368 auto operator >= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const { 2369 return { static_cast<bool>(m_lhs >= rhs), m_lhs, ">=", rhs }; 2370 } 2371 template<typename RhsT> 2372 auto operator <= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const { 2373 return { static_cast<bool>(m_lhs <= rhs), m_lhs, "<=", rhs }; 2374 } 2375 template <typename RhsT> 2376 auto operator | (RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const { 2377 return { static_cast<bool>(m_lhs | rhs), m_lhs, "|", rhs }; 2378 } 2379 template <typename RhsT> 2380 auto operator & (RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const { 2381 return { static_cast<bool>(m_lhs & rhs), m_lhs, "&", rhs }; 2382 } 2383 template <typename RhsT> 2384 auto operator ^ (RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const { 2385 return { static_cast<bool>(m_lhs ^ rhs), m_lhs, "^", rhs }; 2386 } 2387 2388 template<typename RhsT> 2389 auto operator && ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const { 2390 static_assert(always_false<RhsT>::value, 2391 "operator&& is not supported inside assertions, " 2392 "wrap the expression inside parentheses, or decompose it"); 2393 } 2394 2395 template<typename RhsT> 2396 auto operator || ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const { 2397 static_assert(always_false<RhsT>::value, 2398 "operator|| is not supported inside assertions, " 2399 "wrap the expression inside parentheses, or decompose it"); 2400 } 2401 2402 auto makeUnaryExpr() const -> UnaryExpr<LhsT> { 2403 return UnaryExpr<LhsT>{ m_lhs }; 2404 } 2405 }; 2406 2407 void handleExpression( ITransientExpression const& expr ); 2408 2409 template<typename T> 2410 void handleExpression( ExprLhs<T> const& expr ) { 2411 handleExpression( expr.makeUnaryExpr() ); 2412 } 2413 2414 struct Decomposer { 2415 template<typename T> 2416 auto operator <= ( T const& lhs ) -> ExprLhs<T const&> { 2417 return ExprLhs<T const&>{ lhs }; 2418 } 2419 2420 auto operator <=( bool value ) -> ExprLhs<bool> { 2421 return ExprLhs<bool>{ value }; 2422 } 2423 }; 2424 2425 } // end namespace Catch 2426 2427 #ifdef _MSC_VER 2428 #pragma warning(pop) 2429 #endif 2430 2431 // end catch_decomposer.h 2432 // start catch_interfaces_capture.h 2433 2434 #include <string> 2435 #include <chrono> 2436 2437 namespace Catch { 2438 2439 class AssertionResult; 2440 struct AssertionInfo; 2441 struct SectionInfo; 2442 struct SectionEndInfo; 2443 struct MessageInfo; 2444 struct MessageBuilder; 2445 struct Counts; 2446 struct AssertionReaction; 2447 struct SourceLineInfo; 2448 2449 struct ITransientExpression; 2450 struct IGeneratorTracker; 2451 2452 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 2453 struct BenchmarkInfo; 2454 template <typename Duration = std::chrono::duration<double, std::nano>> 2455 struct BenchmarkStats; 2456 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 2457 2458 struct IResultCapture { 2459 2460 virtual ~IResultCapture(); 2461 2462 virtual bool sectionStarted( SectionInfo const& sectionInfo, 2463 Counts& assertions ) = 0; 2464 virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; 2465 virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; 2466 2467 virtual auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& = 0; 2468 2469 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 2470 virtual void benchmarkPreparing( std::string const& name ) = 0; 2471 virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0; 2472 virtual void benchmarkEnded( BenchmarkStats<> const& stats ) = 0; 2473 virtual void benchmarkFailed( std::string const& error ) = 0; 2474 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 2475 2476 virtual void pushScopedMessage( MessageInfo const& message ) = 0; 2477 virtual void popScopedMessage( MessageInfo const& message ) = 0; 2478 2479 virtual void emplaceUnscopedMessage( MessageBuilder const& builder ) = 0; 2480 2481 virtual void handleFatalErrorCondition( StringRef message ) = 0; 2482 2483 virtual void handleExpr 2484 ( AssertionInfo const& info, 2485 ITransientExpression const& expr, 2486 AssertionReaction& reaction ) = 0; 2487 virtual void handleMessage 2488 ( AssertionInfo const& info, 2489 ResultWas::OfType resultType, 2490 StringRef const& message, 2491 AssertionReaction& reaction ) = 0; 2492 virtual void handleUnexpectedExceptionNotThrown 2493 ( AssertionInfo const& info, 2494 AssertionReaction& reaction ) = 0; 2495 virtual void handleUnexpectedInflightException 2496 ( AssertionInfo const& info, 2497 std::string const& message, 2498 AssertionReaction& reaction ) = 0; 2499 virtual void handleIncomplete 2500 ( AssertionInfo const& info ) = 0; 2501 virtual void handleNonExpr 2502 ( AssertionInfo const &info, 2503 ResultWas::OfType resultType, 2504 AssertionReaction &reaction ) = 0; 2505 2506 virtual bool lastAssertionPassed() = 0; 2507 virtual void assertionPassed() = 0; 2508 2509 // Deprecated, do not use: 2510 virtual std::string getCurrentTestName() const = 0; 2511 virtual const AssertionResult* getLastResult() const = 0; 2512 virtual void exceptionEarlyReported() = 0; 2513 }; 2514 2515 IResultCapture& getResultCapture(); 2516 } 2517 2518 // end catch_interfaces_capture.h 2519 namespace Catch { 2520 2521 struct TestFailureException{}; 2522 struct AssertionResultData; 2523 struct IResultCapture; 2524 class RunContext; 2525 2526 class LazyExpression { 2527 friend class AssertionHandler; 2528 friend struct AssertionStats; 2529 friend class RunContext; 2530 2531 ITransientExpression const* m_transientExpression = nullptr; 2532 bool m_isNegated; 2533 public: 2534 LazyExpression( bool isNegated ); 2535 LazyExpression( LazyExpression const& other ); 2536 LazyExpression& operator = ( LazyExpression const& ) = delete; 2537 2538 explicit operator bool() const; 2539 2540 friend auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream&; 2541 }; 2542 2543 struct AssertionReaction { 2544 bool shouldDebugBreak = false; 2545 bool shouldThrow = false; 2546 }; 2547 2548 class AssertionHandler { 2549 AssertionInfo m_assertionInfo; 2550 AssertionReaction m_reaction; 2551 bool m_completed = false; 2552 IResultCapture& m_resultCapture; 2553 2554 public: 2555 AssertionHandler 2556 ( StringRef const& macroName, 2557 SourceLineInfo const& lineInfo, 2558 StringRef capturedExpression, 2559 ResultDisposition::Flags resultDisposition ); 2560 ~AssertionHandler() { 2561 if ( !m_completed ) { 2562 m_resultCapture.handleIncomplete( m_assertionInfo ); 2563 } 2564 } 2565 2566 template<typename T> 2567 void handleExpr( ExprLhs<T> const& expr ) { 2568 handleExpr( expr.makeUnaryExpr() ); 2569 } 2570 void handleExpr( ITransientExpression const& expr ); 2571 2572 void handleMessage(ResultWas::OfType resultType, StringRef const& message); 2573 2574 void handleExceptionThrownAsExpected(); 2575 void handleUnexpectedExceptionNotThrown(); 2576 void handleExceptionNotThrownAsExpected(); 2577 void handleThrowingCallSkipped(); 2578 void handleUnexpectedInflightException(); 2579 2580 void complete(); 2581 void setCompleted(); 2582 2583 // query 2584 auto allowThrows() const -> bool; 2585 }; 2586 2587 void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef const& matcherString ); 2588 2589 } // namespace Catch 2590 2591 // end catch_assertionhandler.h 2592 // start catch_message.h 2593 2594 #include <string> 2595 #include <vector> 2596 2597 namespace Catch { 2598 2599 struct MessageInfo { 2600 MessageInfo( StringRef const& _macroName, 2601 SourceLineInfo const& _lineInfo, 2602 ResultWas::OfType _type ); 2603 2604 StringRef macroName; 2605 std::string message; 2606 SourceLineInfo lineInfo; 2607 ResultWas::OfType type; 2608 unsigned int sequence; 2609 2610 bool operator == ( MessageInfo const& other ) const; 2611 bool operator < ( MessageInfo const& other ) const; 2612 private: 2613 static unsigned int globalCount; 2614 }; 2615 2616 struct MessageStream { 2617 2618 template<typename T> 2619 MessageStream& operator << ( T const& value ) { 2620 m_stream << value; 2621 return *this; 2622 } 2623 2624 ReusableStringStream m_stream; 2625 }; 2626 2627 struct MessageBuilder : MessageStream { 2628 MessageBuilder( StringRef const& macroName, 2629 SourceLineInfo const& lineInfo, 2630 ResultWas::OfType type ); 2631 2632 template<typename T> 2633 MessageBuilder& operator << ( T const& value ) { 2634 m_stream << value; 2635 return *this; 2636 } 2637 2638 MessageInfo m_info; 2639 }; 2640 2641 class ScopedMessage { 2642 public: 2643 explicit ScopedMessage( MessageBuilder const& builder ); 2644 ScopedMessage( ScopedMessage& duplicate ) = delete; 2645 ScopedMessage( ScopedMessage&& old ); 2646 ~ScopedMessage(); 2647 2648 MessageInfo m_info; 2649 bool m_moved; 2650 }; 2651 2652 class Capturer { 2653 std::vector<MessageInfo> m_messages; 2654 IResultCapture& m_resultCapture = getResultCapture(); 2655 size_t m_captured = 0; 2656 public: 2657 Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names ); 2658 ~Capturer(); 2659 2660 void captureValue( size_t index, std::string const& value ); 2661 2662 template<typename T> 2663 void captureValues( size_t index, T const& value ) { 2664 captureValue( index, Catch::Detail::stringify( value ) ); 2665 } 2666 2667 template<typename T, typename... Ts> 2668 void captureValues( size_t index, T const& value, Ts const&... values ) { 2669 captureValue( index, Catch::Detail::stringify(value) ); 2670 captureValues( index+1, values... ); 2671 } 2672 }; 2673 2674 } // end namespace Catch 2675 2676 // end catch_message.h 2677 #if !defined(CATCH_CONFIG_DISABLE) 2678 2679 #if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION) 2680 #define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__ 2681 #else 2682 #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION" 2683 #endif 2684 2685 #if defined(CATCH_CONFIG_FAST_COMPILE) || defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 2686 2687 /////////////////////////////////////////////////////////////////////////////// 2688 // Another way to speed-up compilation is to omit local try-catch for REQUIRE* 2689 // macros. 2690 #define INTERNAL_CATCH_TRY 2691 #define INTERNAL_CATCH_CATCH( capturer ) 2692 2693 #else // CATCH_CONFIG_FAST_COMPILE 2694 2695 #define INTERNAL_CATCH_TRY try 2696 #define INTERNAL_CATCH_CATCH( handler ) catch(...) { handler.handleUnexpectedInflightException(); } 2697 2698 #endif 2699 2700 #define INTERNAL_CATCH_REACT( handler ) handler.complete(); 2701 2702 /////////////////////////////////////////////////////////////////////////////// 2703 #define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \ 2704 do { \ 2705 CATCH_INTERNAL_IGNORE_BUT_WARN(__VA_ARGS__); \ 2706 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ 2707 INTERNAL_CATCH_TRY { \ 2708 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 2709 CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ 2710 catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); \ 2711 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 2712 } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ 2713 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2714 } while( (void)0, (false) && static_cast<bool>( !!(__VA_ARGS__) ) ) 2715 2716 /////////////////////////////////////////////////////////////////////////////// 2717 #define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \ 2718 INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \ 2719 if( Catch::getResultCapture().lastAssertionPassed() ) 2720 2721 /////////////////////////////////////////////////////////////////////////////// 2722 #define INTERNAL_CATCH_ELSE( macroName, resultDisposition, ... ) \ 2723 INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \ 2724 if( !Catch::getResultCapture().lastAssertionPassed() ) 2725 2726 /////////////////////////////////////////////////////////////////////////////// 2727 #define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \ 2728 do { \ 2729 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ 2730 try { \ 2731 static_cast<void>(__VA_ARGS__); \ 2732 catchAssertionHandler.handleExceptionNotThrownAsExpected(); \ 2733 } \ 2734 catch( ... ) { \ 2735 catchAssertionHandler.handleUnexpectedInflightException(); \ 2736 } \ 2737 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2738 } while( false ) 2739 2740 /////////////////////////////////////////////////////////////////////////////// 2741 #define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \ 2742 do { \ 2743 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \ 2744 if( catchAssertionHandler.allowThrows() ) \ 2745 try { \ 2746 static_cast<void>(__VA_ARGS__); \ 2747 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 2748 } \ 2749 catch( ... ) { \ 2750 catchAssertionHandler.handleExceptionThrownAsExpected(); \ 2751 } \ 2752 else \ 2753 catchAssertionHandler.handleThrowingCallSkipped(); \ 2754 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2755 } while( false ) 2756 2757 /////////////////////////////////////////////////////////////////////////////// 2758 #define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \ 2759 do { \ 2760 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \ 2761 if( catchAssertionHandler.allowThrows() ) \ 2762 try { \ 2763 static_cast<void>(expr); \ 2764 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 2765 } \ 2766 catch( exceptionType const& ) { \ 2767 catchAssertionHandler.handleExceptionThrownAsExpected(); \ 2768 } \ 2769 catch( ... ) { \ 2770 catchAssertionHandler.handleUnexpectedInflightException(); \ 2771 } \ 2772 else \ 2773 catchAssertionHandler.handleThrowingCallSkipped(); \ 2774 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2775 } while( false ) 2776 2777 /////////////////////////////////////////////////////////////////////////////// 2778 #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \ 2779 do { \ 2780 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::StringRef(), resultDisposition ); \ 2781 catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \ 2782 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2783 } while( false ) 2784 2785 /////////////////////////////////////////////////////////////////////////////// 2786 #define INTERNAL_CATCH_CAPTURE( varName, macroName, ... ) \ 2787 auto varName = Catch::Capturer( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info, #__VA_ARGS__ ); \ 2788 varName.captureValues( 0, __VA_ARGS__ ) 2789 2790 /////////////////////////////////////////////////////////////////////////////// 2791 #define INTERNAL_CATCH_INFO( macroName, log ) \ 2792 Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log ); 2793 2794 /////////////////////////////////////////////////////////////////////////////// 2795 #define INTERNAL_CATCH_UNSCOPED_INFO( macroName, log ) \ 2796 Catch::getResultCapture().emplaceUnscopedMessage( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log ) 2797 2798 /////////////////////////////////////////////////////////////////////////////// 2799 // Although this is matcher-based, it can be used with just a string 2800 #define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \ 2801 do { \ 2802 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ 2803 if( catchAssertionHandler.allowThrows() ) \ 2804 try { \ 2805 static_cast<void>(__VA_ARGS__); \ 2806 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 2807 } \ 2808 catch( ... ) { \ 2809 Catch::handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher##_catch_sr ); \ 2810 } \ 2811 else \ 2812 catchAssertionHandler.handleThrowingCallSkipped(); \ 2813 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2814 } while( false ) 2815 2816 #endif // CATCH_CONFIG_DISABLE 2817 2818 // end catch_capture.hpp 2819 // start catch_section.h 2820 2821 // start catch_section_info.h 2822 2823 // start catch_totals.h 2824 2825 #include <cstddef> 2826 2827 namespace Catch { 2828 2829 struct Counts { 2830 Counts operator - ( Counts const& other ) const; 2831 Counts& operator += ( Counts const& other ); 2832 2833 std::size_t total() const; 2834 bool allPassed() const; 2835 bool allOk() const; 2836 2837 std::size_t passed = 0; 2838 std::size_t failed = 0; 2839 std::size_t failedButOk = 0; 2840 }; 2841 2842 struct Totals { 2843 2844 Totals operator - ( Totals const& other ) const; 2845 Totals& operator += ( Totals const& other ); 2846 2847 Totals delta( Totals const& prevTotals ) const; 2848 2849 int error = 0; 2850 Counts assertions; 2851 Counts testCases; 2852 }; 2853 } 2854 2855 // end catch_totals.h 2856 #include <string> 2857 2858 namespace Catch { 2859 2860 struct SectionInfo { 2861 SectionInfo 2862 ( SourceLineInfo const& _lineInfo, 2863 std::string const& _name ); 2864 2865 // Deprecated 2866 SectionInfo 2867 ( SourceLineInfo const& _lineInfo, 2868 std::string const& _name, 2869 std::string const& ) : SectionInfo( _lineInfo, _name ) {} 2870 2871 std::string name; 2872 std::string description; // !Deprecated: this will always be empty 2873 SourceLineInfo lineInfo; 2874 }; 2875 2876 struct SectionEndInfo { 2877 SectionInfo sectionInfo; 2878 Counts prevAssertions; 2879 double durationInSeconds; 2880 }; 2881 2882 } // end namespace Catch 2883 2884 // end catch_section_info.h 2885 // start catch_timer.h 2886 2887 #include <cstdint> 2888 2889 namespace Catch { 2890 2891 auto getCurrentNanosecondsSinceEpoch() -> uint64_t; 2892 auto getEstimatedClockResolution() -> uint64_t; 2893 2894 class Timer { 2895 uint64_t m_nanoseconds = 0; 2896 public: 2897 void start(); 2898 auto getElapsedNanoseconds() const -> uint64_t; 2899 auto getElapsedMicroseconds() const -> uint64_t; 2900 auto getElapsedMilliseconds() const -> unsigned int; 2901 auto getElapsedSeconds() const -> double; 2902 }; 2903 2904 } // namespace Catch 2905 2906 // end catch_timer.h 2907 #include <string> 2908 2909 namespace Catch { 2910 2911 class Section : NonCopyable { 2912 public: 2913 Section( SectionInfo const& info ); 2914 ~Section(); 2915 2916 // This indicates whether the section should be executed or not 2917 explicit operator bool() const; 2918 2919 private: 2920 SectionInfo m_info; 2921 2922 std::string m_name; 2923 Counts m_assertions; 2924 bool m_sectionIncluded; 2925 Timer m_timer; 2926 }; 2927 2928 } // end namespace Catch 2929 2930 #define INTERNAL_CATCH_SECTION( ... ) \ 2931 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 2932 CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ 2933 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \ 2934 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 2935 2936 #define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \ 2937 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 2938 CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ 2939 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, (Catch::ReusableStringStream() << __VA_ARGS__).str() ) ) \ 2940 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 2941 2942 // end catch_section.h 2943 // start catch_interfaces_exception.h 2944 2945 // start catch_interfaces_registry_hub.h 2946 2947 #include <string> 2948 #include <memory> 2949 2950 namespace Catch { 2951 2952 class TestCase; 2953 struct ITestCaseRegistry; 2954 struct IExceptionTranslatorRegistry; 2955 struct IExceptionTranslator; 2956 struct IReporterRegistry; 2957 struct IReporterFactory; 2958 struct ITagAliasRegistry; 2959 struct IMutableEnumValuesRegistry; 2960 2961 class StartupExceptionRegistry; 2962 2963 using IReporterFactoryPtr = std::shared_ptr<IReporterFactory>; 2964 2965 struct IRegistryHub { 2966 virtual ~IRegistryHub(); 2967 2968 virtual IReporterRegistry const& getReporterRegistry() const = 0; 2969 virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; 2970 virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0; 2971 virtual IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const = 0; 2972 2973 virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0; 2974 }; 2975 2976 struct IMutableRegistryHub { 2977 virtual ~IMutableRegistryHub(); 2978 virtual void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) = 0; 2979 virtual void registerListener( IReporterFactoryPtr const& factory ) = 0; 2980 virtual void registerTest( TestCase const& testInfo ) = 0; 2981 virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; 2982 virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0; 2983 virtual void registerStartupException() noexcept = 0; 2984 virtual IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() = 0; 2985 }; 2986 2987 IRegistryHub const& getRegistryHub(); 2988 IMutableRegistryHub& getMutableRegistryHub(); 2989 void cleanUp(); 2990 std::string translateActiveException(); 2991 2992 } 2993 2994 // end catch_interfaces_registry_hub.h 2995 #if defined(CATCH_CONFIG_DISABLE) 2996 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( translatorName, signature) \ 2997 static std::string translatorName( signature ) 2998 #endif 2999 3000 #include <exception> 3001 #include <string> 3002 #include <vector> 3003 3004 namespace Catch { 3005 using exceptionTranslateFunction = std::string(*)(); 3006 3007 struct IExceptionTranslator; 3008 using ExceptionTranslators = std::vector<std::unique_ptr<IExceptionTranslator const>>; 3009 3010 struct IExceptionTranslator { 3011 virtual ~IExceptionTranslator(); 3012 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0; 3013 }; 3014 3015 struct IExceptionTranslatorRegistry { 3016 virtual ~IExceptionTranslatorRegistry(); 3017 3018 virtual std::string translateActiveException() const = 0; 3019 }; 3020 3021 class ExceptionTranslatorRegistrar { 3022 template<typename T> 3023 class ExceptionTranslator : public IExceptionTranslator { 3024 public: 3025 3026 ExceptionTranslator( std::string(*translateFunction)( T& ) ) 3027 : m_translateFunction( translateFunction ) 3028 {} 3029 3030 std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override { 3031 #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 3032 return ""; 3033 #else 3034 try { 3035 if( it == itEnd ) 3036 std::rethrow_exception(std::current_exception()); 3037 else 3038 return (*it)->translate( it+1, itEnd ); 3039 } 3040 catch( T& ex ) { 3041 return m_translateFunction( ex ); 3042 } 3043 #endif 3044 } 3045 3046 protected: 3047 std::string(*m_translateFunction)( T& ); 3048 }; 3049 3050 public: 3051 template<typename T> 3052 ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) { 3053 getMutableRegistryHub().registerTranslator 3054 ( new ExceptionTranslator<T>( translateFunction ) ); 3055 } 3056 }; 3057 } 3058 3059 /////////////////////////////////////////////////////////////////////////////// 3060 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \ 3061 static std::string translatorName( signature ); \ 3062 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 3063 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 3064 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); } \ 3065 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 3066 static std::string translatorName( signature ) 3067 3068 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) 3069 3070 // end catch_interfaces_exception.h 3071 // start catch_approx.h 3072 3073 #include <type_traits> 3074 3075 namespace Catch { 3076 namespace Detail { 3077 3078 class Approx { 3079 private: 3080 bool equalityComparisonImpl(double other) const; 3081 // Validates the new margin (margin >= 0) 3082 // out-of-line to avoid including stdexcept in the header 3083 void setMargin(double margin); 3084 // Validates the new epsilon (0 < epsilon < 1) 3085 // out-of-line to avoid including stdexcept in the header 3086 void setEpsilon(double epsilon); 3087 3088 public: 3089 explicit Approx ( double value ); 3090 3091 static Approx custom(); 3092 3093 Approx operator-() const; 3094 3095 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3096 Approx operator()( T const& value ) const { 3097 Approx approx( static_cast<double>(value) ); 3098 approx.m_epsilon = m_epsilon; 3099 approx.m_margin = m_margin; 3100 approx.m_scale = m_scale; 3101 return approx; 3102 } 3103 3104 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3105 explicit Approx( T const& value ): Approx(static_cast<double>(value)) 3106 {} 3107 3108 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3109 friend bool operator == ( const T& lhs, Approx const& rhs ) { 3110 auto lhs_v = static_cast<double>(lhs); 3111 return rhs.equalityComparisonImpl(lhs_v); 3112 } 3113 3114 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3115 friend bool operator == ( Approx const& lhs, const T& rhs ) { 3116 return operator==( rhs, lhs ); 3117 } 3118 3119 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3120 friend bool operator != ( T const& lhs, Approx const& rhs ) { 3121 return !operator==( lhs, rhs ); 3122 } 3123 3124 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3125 friend bool operator != ( Approx const& lhs, T const& rhs ) { 3126 return !operator==( rhs, lhs ); 3127 } 3128 3129 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3130 friend bool operator <= ( T const& lhs, Approx const& rhs ) { 3131 return static_cast<double>(lhs) < rhs.m_value || lhs == rhs; 3132 } 3133 3134 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3135 friend bool operator <= ( Approx const& lhs, T const& rhs ) { 3136 return lhs.m_value < static_cast<double>(rhs) || lhs == rhs; 3137 } 3138 3139 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3140 friend bool operator >= ( T const& lhs, Approx const& rhs ) { 3141 return static_cast<double>(lhs) > rhs.m_value || lhs == rhs; 3142 } 3143 3144 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3145 friend bool operator >= ( Approx const& lhs, T const& rhs ) { 3146 return lhs.m_value > static_cast<double>(rhs) || lhs == rhs; 3147 } 3148 3149 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3150 Approx& epsilon( T const& newEpsilon ) { 3151 double epsilonAsDouble = static_cast<double>(newEpsilon); 3152 setEpsilon(epsilonAsDouble); 3153 return *this; 3154 } 3155 3156 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3157 Approx& margin( T const& newMargin ) { 3158 double marginAsDouble = static_cast<double>(newMargin); 3159 setMargin(marginAsDouble); 3160 return *this; 3161 } 3162 3163 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3164 Approx& scale( T const& newScale ) { 3165 m_scale = static_cast<double>(newScale); 3166 return *this; 3167 } 3168 3169 std::string toString() const; 3170 3171 private: 3172 double m_epsilon; 3173 double m_margin; 3174 double m_scale; 3175 double m_value; 3176 }; 3177 } // end namespace Detail 3178 3179 namespace literals { 3180 Detail::Approx operator "" _a(long double val); 3181 Detail::Approx operator "" _a(unsigned long long val); 3182 } // end namespace literals 3183 3184 template<> 3185 struct StringMaker<Catch::Detail::Approx> { 3186 static std::string convert(Catch::Detail::Approx const& value); 3187 }; 3188 3189 } // end namespace Catch 3190 3191 // end catch_approx.h 3192 // start catch_string_manip.h 3193 3194 #include <string> 3195 #include <iosfwd> 3196 #include <vector> 3197 3198 namespace Catch { 3199 3200 bool startsWith( std::string const& s, std::string const& prefix ); 3201 bool startsWith( std::string const& s, char prefix ); 3202 bool endsWith( std::string const& s, std::string const& suffix ); 3203 bool endsWith( std::string const& s, char suffix ); 3204 bool contains( std::string const& s, std::string const& infix ); 3205 void toLowerInPlace( std::string& s ); 3206 std::string toLower( std::string const& s ); 3207 //! Returns a new string without whitespace at the start/end 3208 std::string trim( std::string const& str ); 3209 //! Returns a substring of the original ref without whitespace. Beware lifetimes! 3210 StringRef trim(StringRef ref); 3211 3212 // !!! Be aware, returns refs into original string - make sure original string outlives them 3213 std::vector<StringRef> splitStringRef( StringRef str, char delimiter ); 3214 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ); 3215 3216 struct pluralise { 3217 pluralise( std::size_t count, std::string const& label ); 3218 3219 friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); 3220 3221 std::size_t m_count; 3222 std::string m_label; 3223 }; 3224 } 3225 3226 // end catch_string_manip.h 3227 #ifndef CATCH_CONFIG_DISABLE_MATCHERS 3228 // start catch_capture_matchers.h 3229 3230 // start catch_matchers.h 3231 3232 #include <string> 3233 #include <vector> 3234 3235 namespace Catch { 3236 namespace Matchers { 3237 namespace Impl { 3238 3239 template<typename ArgT> struct MatchAllOf; 3240 template<typename ArgT> struct MatchAnyOf; 3241 template<typename ArgT> struct MatchNotOf; 3242 3243 class MatcherUntypedBase { 3244 public: 3245 MatcherUntypedBase() = default; 3246 MatcherUntypedBase ( MatcherUntypedBase const& ) = default; 3247 MatcherUntypedBase& operator = ( MatcherUntypedBase const& ) = delete; 3248 std::string toString() const; 3249 3250 protected: 3251 virtual ~MatcherUntypedBase(); 3252 virtual std::string describe() const = 0; 3253 mutable std::string m_cachedToString; 3254 }; 3255 3256 #ifdef __clang__ 3257 # pragma clang diagnostic push 3258 # pragma clang diagnostic ignored "-Wnon-virtual-dtor" 3259 #endif 3260 3261 template<typename ObjectT> 3262 struct MatcherMethod { 3263 virtual bool match( ObjectT const& arg ) const = 0; 3264 }; 3265 3266 #if defined(__OBJC__) 3267 // Hack to fix Catch GH issue #1661. Could use id for generic Object support. 3268 // use of const for Object pointers is very uncommon and under ARC it causes some kind of signature mismatch that breaks compilation 3269 template<> 3270 struct MatcherMethod<NSString*> { 3271 virtual bool match( NSString* arg ) const = 0; 3272 }; 3273 #endif 3274 3275 #ifdef __clang__ 3276 # pragma clang diagnostic pop 3277 #endif 3278 3279 template<typename T> 3280 struct MatcherBase : MatcherUntypedBase, MatcherMethod<T> { 3281 3282 MatchAllOf<T> operator && ( MatcherBase const& other ) const; 3283 MatchAnyOf<T> operator || ( MatcherBase const& other ) const; 3284 MatchNotOf<T> operator ! () const; 3285 }; 3286 3287 template<typename ArgT> 3288 struct MatchAllOf : MatcherBase<ArgT> { 3289 bool match( ArgT const& arg ) const override { 3290 for( auto matcher : m_matchers ) { 3291 if (!matcher->match(arg)) 3292 return false; 3293 } 3294 return true; 3295 } 3296 std::string describe() const override { 3297 std::string description; 3298 description.reserve( 4 + m_matchers.size()*32 ); 3299 description += "( "; 3300 bool first = true; 3301 for( auto matcher : m_matchers ) { 3302 if( first ) 3303 first = false; 3304 else 3305 description += " and "; 3306 description += matcher->toString(); 3307 } 3308 description += " )"; 3309 return description; 3310 } 3311 3312 MatchAllOf<ArgT> operator && ( MatcherBase<ArgT> const& other ) { 3313 auto copy(*this); 3314 copy.m_matchers.push_back( &other ); 3315 return copy; 3316 } 3317 3318 std::vector<MatcherBase<ArgT> const*> m_matchers; 3319 }; 3320 template<typename ArgT> 3321 struct MatchAnyOf : MatcherBase<ArgT> { 3322 3323 bool match( ArgT const& arg ) const override { 3324 for( auto matcher : m_matchers ) { 3325 if (matcher->match(arg)) 3326 return true; 3327 } 3328 return false; 3329 } 3330 std::string describe() const override { 3331 std::string description; 3332 description.reserve( 4 + m_matchers.size()*32 ); 3333 description += "( "; 3334 bool first = true; 3335 for( auto matcher : m_matchers ) { 3336 if( first ) 3337 first = false; 3338 else 3339 description += " or "; 3340 description += matcher->toString(); 3341 } 3342 description += " )"; 3343 return description; 3344 } 3345 3346 MatchAnyOf<ArgT> operator || ( MatcherBase<ArgT> const& other ) { 3347 auto copy(*this); 3348 copy.m_matchers.push_back( &other ); 3349 return copy; 3350 } 3351 3352 std::vector<MatcherBase<ArgT> const*> m_matchers; 3353 }; 3354 3355 template<typename ArgT> 3356 struct MatchNotOf : MatcherBase<ArgT> { 3357 3358 MatchNotOf( MatcherBase<ArgT> const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {} 3359 3360 bool match( ArgT const& arg ) const override { 3361 return !m_underlyingMatcher.match( arg ); 3362 } 3363 3364 std::string describe() const override { 3365 return "not " + m_underlyingMatcher.toString(); 3366 } 3367 MatcherBase<ArgT> const& m_underlyingMatcher; 3368 }; 3369 3370 template<typename T> 3371 MatchAllOf<T> MatcherBase<T>::operator && ( MatcherBase const& other ) const { 3372 return MatchAllOf<T>() && *this && other; 3373 } 3374 template<typename T> 3375 MatchAnyOf<T> MatcherBase<T>::operator || ( MatcherBase const& other ) const { 3376 return MatchAnyOf<T>() || *this || other; 3377 } 3378 template<typename T> 3379 MatchNotOf<T> MatcherBase<T>::operator ! () const { 3380 return MatchNotOf<T>( *this ); 3381 } 3382 3383 } // namespace Impl 3384 3385 } // namespace Matchers 3386 3387 using namespace Matchers; 3388 using Matchers::Impl::MatcherBase; 3389 3390 } // namespace Catch 3391 3392 // end catch_matchers.h 3393 // start catch_matchers_exception.hpp 3394 3395 namespace Catch { 3396 namespace Matchers { 3397 namespace Exception { 3398 3399 class ExceptionMessageMatcher : public MatcherBase<std::exception> { 3400 std::string m_message; 3401 public: 3402 3403 ExceptionMessageMatcher(std::string const& message): 3404 m_message(message) 3405 {} 3406 3407 bool match(std::exception const& ex) const override; 3408 3409 std::string describe() const override; 3410 }; 3411 3412 } // namespace Exception 3413 3414 Exception::ExceptionMessageMatcher Message(std::string const& message); 3415 3416 } // namespace Matchers 3417 } // namespace Catch 3418 3419 // end catch_matchers_exception.hpp 3420 // start catch_matchers_floating.h 3421 3422 namespace Catch { 3423 namespace Matchers { 3424 3425 namespace Floating { 3426 3427 enum class FloatingPointKind : uint8_t; 3428 3429 struct WithinAbsMatcher : MatcherBase<double> { 3430 WithinAbsMatcher(double target, double margin); 3431 bool match(double const& matchee) const override; 3432 std::string describe() const override; 3433 private: 3434 double m_target; 3435 double m_margin; 3436 }; 3437 3438 struct WithinUlpsMatcher : MatcherBase<double> { 3439 WithinUlpsMatcher(double target, uint64_t ulps, FloatingPointKind baseType); 3440 bool match(double const& matchee) const override; 3441 std::string describe() const override; 3442 private: 3443 double m_target; 3444 uint64_t m_ulps; 3445 FloatingPointKind m_type; 3446 }; 3447 3448 // Given IEEE-754 format for floats and doubles, we can assume 3449 // that float -> double promotion is lossless. Given this, we can 3450 // assume that if we do the standard relative comparison of 3451 // |lhs - rhs| <= epsilon * max(fabs(lhs), fabs(rhs)), then we get 3452 // the same result if we do this for floats, as if we do this for 3453 // doubles that were promoted from floats. 3454 struct WithinRelMatcher : MatcherBase<double> { 3455 WithinRelMatcher(double target, double epsilon); 3456 bool match(double const& matchee) const override; 3457 std::string describe() const override; 3458 private: 3459 double m_target; 3460 double m_epsilon; 3461 }; 3462 3463 } // namespace Floating 3464 3465 // The following functions create the actual matcher objects. 3466 // This allows the types to be inferred 3467 Floating::WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff); 3468 Floating::WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff); 3469 Floating::WithinAbsMatcher WithinAbs(double target, double margin); 3470 Floating::WithinRelMatcher WithinRel(double target, double eps); 3471 // defaults epsilon to 100*numeric_limits<double>::epsilon() 3472 Floating::WithinRelMatcher WithinRel(double target); 3473 Floating::WithinRelMatcher WithinRel(float target, float eps); 3474 // defaults epsilon to 100*numeric_limits<float>::epsilon() 3475 Floating::WithinRelMatcher WithinRel(float target); 3476 3477 } // namespace Matchers 3478 } // namespace Catch 3479 3480 // end catch_matchers_floating.h 3481 // start catch_matchers_generic.hpp 3482 3483 #include <functional> 3484 #include <string> 3485 3486 namespace Catch { 3487 namespace Matchers { 3488 namespace Generic { 3489 3490 namespace Detail { 3491 std::string finalizeDescription(const std::string& desc); 3492 } 3493 3494 template <typename T> 3495 class PredicateMatcher : public MatcherBase<T> { 3496 std::function<bool(T const&)> m_predicate; 3497 std::string m_description; 3498 public: 3499 3500 PredicateMatcher(std::function<bool(T const&)> const& elem, std::string const& descr) 3501 :m_predicate(std::move(elem)), 3502 m_description(Detail::finalizeDescription(descr)) 3503 {} 3504 3505 bool match( T const& item ) const override { 3506 return m_predicate(item); 3507 } 3508 3509 std::string describe() const override { 3510 return m_description; 3511 } 3512 }; 3513 3514 } // namespace Generic 3515 3516 // The following functions create the actual matcher objects. 3517 // The user has to explicitly specify type to the function, because 3518 // inferring std::function<bool(T const&)> is hard (but possible) and 3519 // requires a lot of TMP. 3520 template<typename T> 3521 Generic::PredicateMatcher<T> Predicate(std::function<bool(T const&)> const& predicate, std::string const& description = "") { 3522 return Generic::PredicateMatcher<T>(predicate, description); 3523 } 3524 3525 } // namespace Matchers 3526 } // namespace Catch 3527 3528 // end catch_matchers_generic.hpp 3529 // start catch_matchers_string.h 3530 3531 #include <string> 3532 3533 namespace Catch { 3534 namespace Matchers { 3535 3536 namespace StdString { 3537 3538 struct CasedString 3539 { 3540 CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ); 3541 std::string adjustString( std::string const& str ) const; 3542 std::string caseSensitivitySuffix() const; 3543 3544 CaseSensitive::Choice m_caseSensitivity; 3545 std::string m_str; 3546 }; 3547 3548 struct StringMatcherBase : MatcherBase<std::string> { 3549 StringMatcherBase( std::string const& operation, CasedString const& comparator ); 3550 std::string describe() const override; 3551 3552 CasedString m_comparator; 3553 std::string m_operation; 3554 }; 3555 3556 struct EqualsMatcher : StringMatcherBase { 3557 EqualsMatcher( CasedString const& comparator ); 3558 bool match( std::string const& source ) const override; 3559 }; 3560 struct ContainsMatcher : StringMatcherBase { 3561 ContainsMatcher( CasedString const& comparator ); 3562 bool match( std::string const& source ) const override; 3563 }; 3564 struct StartsWithMatcher : StringMatcherBase { 3565 StartsWithMatcher( CasedString const& comparator ); 3566 bool match( std::string const& source ) const override; 3567 }; 3568 struct EndsWithMatcher : StringMatcherBase { 3569 EndsWithMatcher( CasedString const& comparator ); 3570 bool match( std::string const& source ) const override; 3571 }; 3572 3573 struct RegexMatcher : MatcherBase<std::string> { 3574 RegexMatcher( std::string regex, CaseSensitive::Choice caseSensitivity ); 3575 bool match( std::string const& matchee ) const override; 3576 std::string describe() const override; 3577 3578 private: 3579 std::string m_regex; 3580 CaseSensitive::Choice m_caseSensitivity; 3581 }; 3582 3583 } // namespace StdString 3584 3585 // The following functions create the actual matcher objects. 3586 // This allows the types to be inferred 3587 3588 StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); 3589 StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); 3590 StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); 3591 StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); 3592 StdString::RegexMatcher Matches( std::string const& regex, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); 3593 3594 } // namespace Matchers 3595 } // namespace Catch 3596 3597 // end catch_matchers_string.h 3598 // start catch_matchers_vector.h 3599 3600 #include <algorithm> 3601 3602 namespace Catch { 3603 namespace Matchers { 3604 3605 namespace Vector { 3606 template<typename T, typename Alloc> 3607 struct ContainsElementMatcher : MatcherBase<std::vector<T, Alloc>> { 3608 3609 ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {} 3610 3611 bool match(std::vector<T, Alloc> const &v) const override { 3612 for (auto const& el : v) { 3613 if (el == m_comparator) { 3614 return true; 3615 } 3616 } 3617 return false; 3618 } 3619 3620 std::string describe() const override { 3621 return "Contains: " + ::Catch::Detail::stringify( m_comparator ); 3622 } 3623 3624 T const& m_comparator; 3625 }; 3626 3627 template<typename T, typename AllocComp, typename AllocMatch> 3628 struct ContainsMatcher : MatcherBase<std::vector<T, AllocMatch>> { 3629 3630 ContainsMatcher(std::vector<T, AllocComp> const &comparator) : m_comparator( comparator ) {} 3631 3632 bool match(std::vector<T, AllocMatch> const &v) const override { 3633 // !TBD: see note in EqualsMatcher 3634 if (m_comparator.size() > v.size()) 3635 return false; 3636 for (auto const& comparator : m_comparator) { 3637 auto present = false; 3638 for (const auto& el : v) { 3639 if (el == comparator) { 3640 present = true; 3641 break; 3642 } 3643 } 3644 if (!present) { 3645 return false; 3646 } 3647 } 3648 return true; 3649 } 3650 std::string describe() const override { 3651 return "Contains: " + ::Catch::Detail::stringify( m_comparator ); 3652 } 3653 3654 std::vector<T, AllocComp> const& m_comparator; 3655 }; 3656 3657 template<typename T, typename AllocComp, typename AllocMatch> 3658 struct EqualsMatcher : MatcherBase<std::vector<T, AllocMatch>> { 3659 3660 EqualsMatcher(std::vector<T, AllocComp> const &comparator) : m_comparator( comparator ) {} 3661 3662 bool match(std::vector<T, AllocMatch> const &v) const override { 3663 // !TBD: This currently works if all elements can be compared using != 3664 // - a more general approach would be via a compare template that defaults 3665 // to using !=. but could be specialised for, e.g. std::vector<T, Alloc> etc 3666 // - then just call that directly 3667 if (m_comparator.size() != v.size()) 3668 return false; 3669 for (std::size_t i = 0; i < v.size(); ++i) 3670 if (m_comparator[i] != v[i]) 3671 return false; 3672 return true; 3673 } 3674 std::string describe() const override { 3675 return "Equals: " + ::Catch::Detail::stringify( m_comparator ); 3676 } 3677 std::vector<T, AllocComp> const& m_comparator; 3678 }; 3679 3680 template<typename T, typename AllocComp, typename AllocMatch> 3681 struct ApproxMatcher : MatcherBase<std::vector<T, AllocMatch>> { 3682 3683 ApproxMatcher(std::vector<T, AllocComp> const& comparator) : m_comparator( comparator ) {} 3684 3685 bool match(std::vector<T, AllocMatch> const &v) const override { 3686 if (m_comparator.size() != v.size()) 3687 return false; 3688 for (std::size_t i = 0; i < v.size(); ++i) 3689 if (m_comparator[i] != approx(v[i])) 3690 return false; 3691 return true; 3692 } 3693 std::string describe() const override { 3694 return "is approx: " + ::Catch::Detail::stringify( m_comparator ); 3695 } 3696 template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3697 ApproxMatcher& epsilon( T const& newEpsilon ) { 3698 approx.epsilon(newEpsilon); 3699 return *this; 3700 } 3701 template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3702 ApproxMatcher& margin( T const& newMargin ) { 3703 approx.margin(newMargin); 3704 return *this; 3705 } 3706 template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3707 ApproxMatcher& scale( T const& newScale ) { 3708 approx.scale(newScale); 3709 return *this; 3710 } 3711 3712 std::vector<T, AllocComp> const& m_comparator; 3713 mutable Catch::Detail::Approx approx = Catch::Detail::Approx::custom(); 3714 }; 3715 3716 template<typename T, typename AllocComp, typename AllocMatch> 3717 struct UnorderedEqualsMatcher : MatcherBase<std::vector<T, AllocMatch>> { 3718 UnorderedEqualsMatcher(std::vector<T, AllocComp> const& target) : m_target(target) {} 3719 bool match(std::vector<T, AllocMatch> const& vec) const override { 3720 if (m_target.size() != vec.size()) { 3721 return false; 3722 } 3723 return std::is_permutation(m_target.begin(), m_target.end(), vec.begin()); 3724 } 3725 3726 std::string describe() const override { 3727 return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target); 3728 } 3729 private: 3730 std::vector<T, AllocComp> const& m_target; 3731 }; 3732 3733 } // namespace Vector 3734 3735 // The following functions create the actual matcher objects. 3736 // This allows the types to be inferred 3737 3738 template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp> 3739 Vector::ContainsMatcher<T, AllocComp, AllocMatch> Contains( std::vector<T, AllocComp> const& comparator ) { 3740 return Vector::ContainsMatcher<T, AllocComp, AllocMatch>( comparator ); 3741 } 3742 3743 template<typename T, typename Alloc = std::allocator<T>> 3744 Vector::ContainsElementMatcher<T, Alloc> VectorContains( T const& comparator ) { 3745 return Vector::ContainsElementMatcher<T, Alloc>( comparator ); 3746 } 3747 3748 template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp> 3749 Vector::EqualsMatcher<T, AllocComp, AllocMatch> Equals( std::vector<T, AllocComp> const& comparator ) { 3750 return Vector::EqualsMatcher<T, AllocComp, AllocMatch>( comparator ); 3751 } 3752 3753 template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp> 3754 Vector::ApproxMatcher<T, AllocComp, AllocMatch> Approx( std::vector<T, AllocComp> const& comparator ) { 3755 return Vector::ApproxMatcher<T, AllocComp, AllocMatch>( comparator ); 3756 } 3757 3758 template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp> 3759 Vector::UnorderedEqualsMatcher<T, AllocComp, AllocMatch> UnorderedEquals(std::vector<T, AllocComp> const& target) { 3760 return Vector::UnorderedEqualsMatcher<T, AllocComp, AllocMatch>( target ); 3761 } 3762 3763 } // namespace Matchers 3764 } // namespace Catch 3765 3766 // end catch_matchers_vector.h 3767 namespace Catch { 3768 3769 template<typename ArgT, typename MatcherT> 3770 class MatchExpr : public ITransientExpression { 3771 ArgT const& m_arg; 3772 MatcherT m_matcher; 3773 StringRef m_matcherString; 3774 public: 3775 MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString ) 3776 : ITransientExpression{ true, matcher.match( arg ) }, 3777 m_arg( arg ), 3778 m_matcher( matcher ), 3779 m_matcherString( matcherString ) 3780 {} 3781 3782 void streamReconstructedExpression( std::ostream &os ) const override { 3783 auto matcherAsString = m_matcher.toString(); 3784 os << Catch::Detail::stringify( m_arg ) << ' '; 3785 if( matcherAsString == Detail::unprintableString ) 3786 os << m_matcherString; 3787 else 3788 os << matcherAsString; 3789 } 3790 }; 3791 3792 using StringMatcher = Matchers::Impl::MatcherBase<std::string>; 3793 3794 void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString ); 3795 3796 template<typename ArgT, typename MatcherT> 3797 auto makeMatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString ) -> MatchExpr<ArgT, MatcherT> { 3798 return MatchExpr<ArgT, MatcherT>( arg, matcher, matcherString ); 3799 } 3800 3801 } // namespace Catch 3802 3803 /////////////////////////////////////////////////////////////////////////////// 3804 #define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ 3805 do { \ 3806 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ 3807 INTERNAL_CATCH_TRY { \ 3808 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher, #matcher##_catch_sr ) ); \ 3809 } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ 3810 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 3811 } while( false ) 3812 3813 /////////////////////////////////////////////////////////////////////////////// 3814 #define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \ 3815 do { \ 3816 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ 3817 if( catchAssertionHandler.allowThrows() ) \ 3818 try { \ 3819 static_cast<void>(__VA_ARGS__ ); \ 3820 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 3821 } \ 3822 catch( exceptionType const& ex ) { \ 3823 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( ex, matcher, #matcher##_catch_sr ) ); \ 3824 } \ 3825 catch( ... ) { \ 3826 catchAssertionHandler.handleUnexpectedInflightException(); \ 3827 } \ 3828 else \ 3829 catchAssertionHandler.handleThrowingCallSkipped(); \ 3830 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 3831 } while( false ) 3832 3833 // end catch_capture_matchers.h 3834 #endif 3835 // start catch_generators.hpp 3836 3837 // start catch_interfaces_generatortracker.h 3838 3839 3840 #include <memory> 3841 3842 namespace Catch { 3843 3844 namespace Generators { 3845 class GeneratorUntypedBase { 3846 public: 3847 GeneratorUntypedBase() = default; 3848 virtual ~GeneratorUntypedBase(); 3849 // Attempts to move the generator to the next element 3850 // 3851 // Returns true iff the move succeeded (and a valid element 3852 // can be retrieved). 3853 virtual bool next() = 0; 3854 }; 3855 using GeneratorBasePtr = std::unique_ptr<GeneratorUntypedBase>; 3856 3857 } // namespace Generators 3858 3859 struct IGeneratorTracker { 3860 virtual ~IGeneratorTracker(); 3861 virtual auto hasGenerator() const -> bool = 0; 3862 virtual auto getGenerator() const -> Generators::GeneratorBasePtr const& = 0; 3863 virtual void setGenerator( Generators::GeneratorBasePtr&& generator ) = 0; 3864 }; 3865 3866 } // namespace Catch 3867 3868 // end catch_interfaces_generatortracker.h 3869 // start catch_enforce.h 3870 3871 #include <exception> 3872 3873 namespace Catch { 3874 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 3875 template <typename Ex> 3876 [[noreturn]] 3877 void throw_exception(Ex const& e) { 3878 throw e; 3879 } 3880 #else // ^^ Exceptions are enabled // Exceptions are disabled vv 3881 [[noreturn]] 3882 void throw_exception(std::exception const& e); 3883 #endif 3884 3885 [[noreturn]] 3886 void throw_logic_error(std::string const& msg); 3887 [[noreturn]] 3888 void throw_domain_error(std::string const& msg); 3889 [[noreturn]] 3890 void throw_runtime_error(std::string const& msg); 3891 3892 } // namespace Catch; 3893 3894 #define CATCH_MAKE_MSG(...) \ 3895 (Catch::ReusableStringStream() << __VA_ARGS__).str() 3896 3897 #define CATCH_INTERNAL_ERROR(...) \ 3898 Catch::throw_logic_error(CATCH_MAKE_MSG( CATCH_INTERNAL_LINEINFO << ": Internal Catch2 error: " << __VA_ARGS__)) 3899 3900 #define CATCH_ERROR(...) \ 3901 Catch::throw_domain_error(CATCH_MAKE_MSG( __VA_ARGS__ )) 3902 3903 #define CATCH_RUNTIME_ERROR(...) \ 3904 Catch::throw_runtime_error(CATCH_MAKE_MSG( __VA_ARGS__ )) 3905 3906 #define CATCH_ENFORCE( condition, ... ) \ 3907 do{ if( !(condition) ) CATCH_ERROR( __VA_ARGS__ ); } while(false) 3908 3909 // end catch_enforce.h 3910 #include <memory> 3911 #include <vector> 3912 #include <cassert> 3913 3914 #include <utility> 3915 #include <exception> 3916 3917 namespace Catch { 3918 3919 class GeneratorException : public std::exception { 3920 const char* const m_msg = ""; 3921 3922 public: 3923 GeneratorException(const char* msg): 3924 m_msg(msg) 3925 {} 3926 3927 const char* what() const noexcept override final; 3928 }; 3929 3930 namespace Generators { 3931 3932 // !TBD move this into its own location? 3933 namespace pf{ 3934 template<typename T, typename... Args> 3935 std::unique_ptr<T> make_unique( Args&&... args ) { 3936 return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); 3937 } 3938 } 3939 3940 template<typename T> 3941 struct IGenerator : GeneratorUntypedBase { 3942 virtual ~IGenerator() = default; 3943 3944 // Returns the current element of the generator 3945 // 3946 // \Precondition The generator is either freshly constructed, 3947 // or the last call to `next()` returned true 3948 virtual T const& get() const = 0; 3949 using type = T; 3950 }; 3951 3952 template<typename T> 3953 class SingleValueGenerator final : public IGenerator<T> { 3954 T m_value; 3955 public: 3956 SingleValueGenerator(T&& value) : m_value(std::move(value)) {} 3957 3958 T const& get() const override { 3959 return m_value; 3960 } 3961 bool next() override { 3962 return false; 3963 } 3964 }; 3965 3966 template<typename T> 3967 class FixedValuesGenerator final : public IGenerator<T> { 3968 static_assert(!std::is_same<T, bool>::value, 3969 "FixedValuesGenerator does not support bools because of std::vector<bool>" 3970 "specialization, use SingleValue Generator instead."); 3971 std::vector<T> m_values; 3972 size_t m_idx = 0; 3973 public: 3974 FixedValuesGenerator( std::initializer_list<T> values ) : m_values( values ) {} 3975 3976 T const& get() const override { 3977 return m_values[m_idx]; 3978 } 3979 bool next() override { 3980 ++m_idx; 3981 return m_idx < m_values.size(); 3982 } 3983 }; 3984 3985 template <typename T> 3986 class GeneratorWrapper final { 3987 std::unique_ptr<IGenerator<T>> m_generator; 3988 public: 3989 GeneratorWrapper(std::unique_ptr<IGenerator<T>> generator): 3990 m_generator(std::move(generator)) 3991 {} 3992 T const& get() const { 3993 return m_generator->get(); 3994 } 3995 bool next() { 3996 return m_generator->next(); 3997 } 3998 }; 3999 4000 template <typename T> 4001 GeneratorWrapper<T> value(T&& value) { 4002 return GeneratorWrapper<T>(pf::make_unique<SingleValueGenerator<T>>(std::forward<T>(value))); 4003 } 4004 template <typename T> 4005 GeneratorWrapper<T> values(std::initializer_list<T> values) { 4006 return GeneratorWrapper<T>(pf::make_unique<FixedValuesGenerator<T>>(values)); 4007 } 4008 4009 template<typename T> 4010 class Generators : public IGenerator<T> { 4011 std::vector<GeneratorWrapper<T>> m_generators; 4012 size_t m_current = 0; 4013 4014 void populate(GeneratorWrapper<T>&& generator) { 4015 m_generators.emplace_back(std::move(generator)); 4016 } 4017 void populate(T&& val) { 4018 m_generators.emplace_back(value(std::forward<T>(val))); 4019 } 4020 template<typename U> 4021 void populate(U&& val) { 4022 populate(T(std::forward<U>(val))); 4023 } 4024 template<typename U, typename... Gs> 4025 void populate(U&& valueOrGenerator, Gs &&... moreGenerators) { 4026 populate(std::forward<U>(valueOrGenerator)); 4027 populate(std::forward<Gs>(moreGenerators)...); 4028 } 4029 4030 public: 4031 template <typename... Gs> 4032 Generators(Gs &&... moreGenerators) { 4033 m_generators.reserve(sizeof...(Gs)); 4034 populate(std::forward<Gs>(moreGenerators)...); 4035 } 4036 4037 T const& get() const override { 4038 return m_generators[m_current].get(); 4039 } 4040 4041 bool next() override { 4042 if (m_current >= m_generators.size()) { 4043 return false; 4044 } 4045 const bool current_status = m_generators[m_current].next(); 4046 if (!current_status) { 4047 ++m_current; 4048 } 4049 return m_current < m_generators.size(); 4050 } 4051 }; 4052 4053 template<typename... Ts> 4054 GeneratorWrapper<std::tuple<Ts...>> table( std::initializer_list<std::tuple<typename std::decay<Ts>::type...>> tuples ) { 4055 return values<std::tuple<Ts...>>( tuples ); 4056 } 4057 4058 // Tag type to signal that a generator sequence should convert arguments to a specific type 4059 template <typename T> 4060 struct as {}; 4061 4062 template<typename T, typename... Gs> 4063 auto makeGenerators( GeneratorWrapper<T>&& generator, Gs &&... moreGenerators ) -> Generators<T> { 4064 return Generators<T>(std::move(generator), std::forward<Gs>(moreGenerators)...); 4065 } 4066 template<typename T> 4067 auto makeGenerators( GeneratorWrapper<T>&& generator ) -> Generators<T> { 4068 return Generators<T>(std::move(generator)); 4069 } 4070 template<typename T, typename... Gs> 4071 auto makeGenerators( T&& val, Gs &&... moreGenerators ) -> Generators<T> { 4072 return makeGenerators( value( std::forward<T>( val ) ), std::forward<Gs>( moreGenerators )... ); 4073 } 4074 template<typename T, typename U, typename... Gs> 4075 auto makeGenerators( as<T>, U&& val, Gs &&... moreGenerators ) -> Generators<T> { 4076 return makeGenerators( value( T( std::forward<U>( val ) ) ), std::forward<Gs>( moreGenerators )... ); 4077 } 4078 4079 auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker&; 4080 4081 template<typename L> 4082 // Note: The type after -> is weird, because VS2015 cannot parse 4083 // the expression used in the typedef inside, when it is in 4084 // return type. Yeah. 4085 auto generate( StringRef generatorName, SourceLineInfo const& lineInfo, L const& generatorExpression ) -> decltype(std::declval<decltype(generatorExpression())>().get()) { 4086 using UnderlyingType = typename decltype(generatorExpression())::type; 4087 4088 IGeneratorTracker& tracker = acquireGeneratorTracker( generatorName, lineInfo ); 4089 if (!tracker.hasGenerator()) { 4090 tracker.setGenerator(pf::make_unique<Generators<UnderlyingType>>(generatorExpression())); 4091 } 4092 4093 auto const& generator = static_cast<IGenerator<UnderlyingType> const&>( *tracker.getGenerator() ); 4094 return generator.get(); 4095 } 4096 4097 } // namespace Generators 4098 } // namespace Catch 4099 4100 #define GENERATE( ... ) \ 4101 Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \ 4102 CATCH_INTERNAL_LINEINFO, \ 4103 [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace) 4104 #define GENERATE_COPY( ... ) \ 4105 Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \ 4106 CATCH_INTERNAL_LINEINFO, \ 4107 [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace) 4108 #define GENERATE_REF( ... ) \ 4109 Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \ 4110 CATCH_INTERNAL_LINEINFO, \ 4111 [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace) 4112 4113 // end catch_generators.hpp 4114 // start catch_generators_generic.hpp 4115 4116 namespace Catch { 4117 namespace Generators { 4118 4119 template <typename T> 4120 class TakeGenerator : public IGenerator<T> { 4121 GeneratorWrapper<T> m_generator; 4122 size_t m_returned = 0; 4123 size_t m_target; 4124 public: 4125 TakeGenerator(size_t target, GeneratorWrapper<T>&& generator): 4126 m_generator(std::move(generator)), 4127 m_target(target) 4128 { 4129 assert(target != 0 && "Empty generators are not allowed"); 4130 } 4131 T const& get() const override { 4132 return m_generator.get(); 4133 } 4134 bool next() override { 4135 ++m_returned; 4136 if (m_returned >= m_target) { 4137 return false; 4138 } 4139 4140 const auto success = m_generator.next(); 4141 // If the underlying generator does not contain enough values 4142 // then we cut short as well 4143 if (!success) { 4144 m_returned = m_target; 4145 } 4146 return success; 4147 } 4148 }; 4149 4150 template <typename T> 4151 GeneratorWrapper<T> take(size_t target, GeneratorWrapper<T>&& generator) { 4152 return GeneratorWrapper<T>(pf::make_unique<TakeGenerator<T>>(target, std::move(generator))); 4153 } 4154 4155 template <typename T, typename Predicate> 4156 class FilterGenerator : public IGenerator<T> { 4157 GeneratorWrapper<T> m_generator; 4158 Predicate m_predicate; 4159 public: 4160 template <typename P = Predicate> 4161 FilterGenerator(P&& pred, GeneratorWrapper<T>&& generator): 4162 m_generator(std::move(generator)), 4163 m_predicate(std::forward<P>(pred)) 4164 { 4165 if (!m_predicate(m_generator.get())) { 4166 // It might happen that there are no values that pass the 4167 // filter. In that case we throw an exception. 4168 auto has_initial_value = nextImpl(); 4169 if (!has_initial_value) { 4170 Catch::throw_exception(GeneratorException("No valid value found in filtered generator")); 4171 } 4172 } 4173 } 4174 4175 T const& get() const override { 4176 return m_generator.get(); 4177 } 4178 4179 bool next() override { 4180 return nextImpl(); 4181 } 4182 4183 private: 4184 bool nextImpl() { 4185 bool success = m_generator.next(); 4186 if (!success) { 4187 return false; 4188 } 4189 while (!m_predicate(m_generator.get()) && (success = m_generator.next()) == true); 4190 return success; 4191 } 4192 }; 4193 4194 template <typename T, typename Predicate> 4195 GeneratorWrapper<T> filter(Predicate&& pred, GeneratorWrapper<T>&& generator) { 4196 return GeneratorWrapper<T>(std::unique_ptr<IGenerator<T>>(pf::make_unique<FilterGenerator<T, Predicate>>(std::forward<Predicate>(pred), std::move(generator)))); 4197 } 4198 4199 template <typename T> 4200 class RepeatGenerator : public IGenerator<T> { 4201 static_assert(!std::is_same<T, bool>::value, 4202 "RepeatGenerator currently does not support bools" 4203 "because of std::vector<bool> specialization"); 4204 GeneratorWrapper<T> m_generator; 4205 mutable std::vector<T> m_returned; 4206 size_t m_target_repeats; 4207 size_t m_current_repeat = 0; 4208 size_t m_repeat_index = 0; 4209 public: 4210 RepeatGenerator(size_t repeats, GeneratorWrapper<T>&& generator): 4211 m_generator(std::move(generator)), 4212 m_target_repeats(repeats) 4213 { 4214 assert(m_target_repeats > 0 && "Repeat generator must repeat at least once"); 4215 } 4216 4217 T const& get() const override { 4218 if (m_current_repeat == 0) { 4219 m_returned.push_back(m_generator.get()); 4220 return m_returned.back(); 4221 } 4222 return m_returned[m_repeat_index]; 4223 } 4224 4225 bool next() override { 4226 // There are 2 basic cases: 4227 // 1) We are still reading the generator 4228 // 2) We are reading our own cache 4229 4230 // In the first case, we need to poke the underlying generator. 4231 // If it happily moves, we are left in that state, otherwise it is time to start reading from our cache 4232 if (m_current_repeat == 0) { 4233 const auto success = m_generator.next(); 4234 if (!success) { 4235 ++m_current_repeat; 4236 } 4237 return m_current_repeat < m_target_repeats; 4238 } 4239 4240 // In the second case, we need to move indices forward and check that we haven't run up against the end 4241 ++m_repeat_index; 4242 if (m_repeat_index == m_returned.size()) { 4243 m_repeat_index = 0; 4244 ++m_current_repeat; 4245 } 4246 return m_current_repeat < m_target_repeats; 4247 } 4248 }; 4249 4250 template <typename T> 4251 GeneratorWrapper<T> repeat(size_t repeats, GeneratorWrapper<T>&& generator) { 4252 return GeneratorWrapper<T>(pf::make_unique<RepeatGenerator<T>>(repeats, std::move(generator))); 4253 } 4254 4255 template <typename T, typename U, typename Func> 4256 class MapGenerator : public IGenerator<T> { 4257 // TBD: provide static assert for mapping function, for friendly error message 4258 GeneratorWrapper<U> m_generator; 4259 Func m_function; 4260 // To avoid returning dangling reference, we have to save the values 4261 T m_cache; 4262 public: 4263 template <typename F2 = Func> 4264 MapGenerator(F2&& function, GeneratorWrapper<U>&& generator) : 4265 m_generator(std::move(generator)), 4266 m_function(std::forward<F2>(function)), 4267 m_cache(m_function(m_generator.get())) 4268 {} 4269 4270 T const& get() const override { 4271 return m_cache; 4272 } 4273 bool next() override { 4274 const auto success = m_generator.next(); 4275 if (success) { 4276 m_cache = m_function(m_generator.get()); 4277 } 4278 return success; 4279 } 4280 }; 4281 4282 template <typename Func, typename U, typename T = FunctionReturnType<Func, U>> 4283 GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) { 4284 return GeneratorWrapper<T>( 4285 pf::make_unique<MapGenerator<T, U, Func>>(std::forward<Func>(function), std::move(generator)) 4286 ); 4287 } 4288 4289 template <typename T, typename U, typename Func> 4290 GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) { 4291 return GeneratorWrapper<T>( 4292 pf::make_unique<MapGenerator<T, U, Func>>(std::forward<Func>(function), std::move(generator)) 4293 ); 4294 } 4295 4296 template <typename T> 4297 class ChunkGenerator final : public IGenerator<std::vector<T>> { 4298 std::vector<T> m_chunk; 4299 size_t m_chunk_size; 4300 GeneratorWrapper<T> m_generator; 4301 bool m_used_up = false; 4302 public: 4303 ChunkGenerator(size_t size, GeneratorWrapper<T> generator) : 4304 m_chunk_size(size), m_generator(std::move(generator)) 4305 { 4306 m_chunk.reserve(m_chunk_size); 4307 if (m_chunk_size != 0) { 4308 m_chunk.push_back(m_generator.get()); 4309 for (size_t i = 1; i < m_chunk_size; ++i) { 4310 if (!m_generator.next()) { 4311 Catch::throw_exception(GeneratorException("Not enough values to initialize the first chunk")); 4312 } 4313 m_chunk.push_back(m_generator.get()); 4314 } 4315 } 4316 } 4317 std::vector<T> const& get() const override { 4318 return m_chunk; 4319 } 4320 bool next() override { 4321 m_chunk.clear(); 4322 for (size_t idx = 0; idx < m_chunk_size; ++idx) { 4323 if (!m_generator.next()) { 4324 return false; 4325 } 4326 m_chunk.push_back(m_generator.get()); 4327 } 4328 return true; 4329 } 4330 }; 4331 4332 template <typename T> 4333 GeneratorWrapper<std::vector<T>> chunk(size_t size, GeneratorWrapper<T>&& generator) { 4334 return GeneratorWrapper<std::vector<T>>( 4335 pf::make_unique<ChunkGenerator<T>>(size, std::move(generator)) 4336 ); 4337 } 4338 4339 } // namespace Generators 4340 } // namespace Catch 4341 4342 // end catch_generators_generic.hpp 4343 // start catch_generators_specific.hpp 4344 4345 // start catch_context.h 4346 4347 #include <memory> 4348 4349 namespace Catch { 4350 4351 struct IResultCapture; 4352 struct IRunner; 4353 struct IConfig; 4354 struct IMutableContext; 4355 4356 using IConfigPtr = std::shared_ptr<IConfig const>; 4357 4358 struct IContext 4359 { 4360 virtual ~IContext(); 4361 4362 virtual IResultCapture* getResultCapture() = 0; 4363 virtual IRunner* getRunner() = 0; 4364 virtual IConfigPtr const& getConfig() const = 0; 4365 }; 4366 4367 struct IMutableContext : IContext 4368 { 4369 virtual ~IMutableContext(); 4370 virtual void setResultCapture( IResultCapture* resultCapture ) = 0; 4371 virtual void setRunner( IRunner* runner ) = 0; 4372 virtual void setConfig( IConfigPtr const& config ) = 0; 4373 4374 private: 4375 static IMutableContext *currentContext; 4376 friend IMutableContext& getCurrentMutableContext(); 4377 friend void cleanUpContext(); 4378 static void createContext(); 4379 }; 4380 4381 inline IMutableContext& getCurrentMutableContext() 4382 { 4383 if( !IMutableContext::currentContext ) 4384 IMutableContext::createContext(); 4385 // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn) 4386 return *IMutableContext::currentContext; 4387 } 4388 4389 inline IContext& getCurrentContext() 4390 { 4391 return getCurrentMutableContext(); 4392 } 4393 4394 void cleanUpContext(); 4395 4396 class SimplePcg32; 4397 SimplePcg32& rng(); 4398 } 4399 4400 // end catch_context.h 4401 // start catch_interfaces_config.h 4402 4403 // start catch_option.hpp 4404 4405 namespace Catch { 4406 4407 // An optional type 4408 template<typename T> 4409 class Option { 4410 public: 4411 Option() : nullableValue( nullptr ) {} 4412 Option( T const& _value ) 4413 : nullableValue( new( storage ) T( _value ) ) 4414 {} 4415 Option( Option const& _other ) 4416 : nullableValue( _other ? new( storage ) T( *_other ) : nullptr ) 4417 {} 4418 4419 ~Option() { 4420 reset(); 4421 } 4422 4423 Option& operator= ( Option const& _other ) { 4424 if( &_other != this ) { 4425 reset(); 4426 if( _other ) 4427 nullableValue = new( storage ) T( *_other ); 4428 } 4429 return *this; 4430 } 4431 Option& operator = ( T const& _value ) { 4432 reset(); 4433 nullableValue = new( storage ) T( _value ); 4434 return *this; 4435 } 4436 4437 void reset() { 4438 if( nullableValue ) 4439 nullableValue->~T(); 4440 nullableValue = nullptr; 4441 } 4442 4443 T& operator*() { return *nullableValue; } 4444 T const& operator*() const { return *nullableValue; } 4445 T* operator->() { return nullableValue; } 4446 const T* operator->() const { return nullableValue; } 4447 4448 T valueOr( T const& defaultValue ) const { 4449 return nullableValue ? *nullableValue : defaultValue; 4450 } 4451 4452 bool some() const { return nullableValue != nullptr; } 4453 bool none() const { return nullableValue == nullptr; } 4454 4455 bool operator !() const { return nullableValue == nullptr; } 4456 explicit operator bool() const { 4457 return some(); 4458 } 4459 4460 private: 4461 T *nullableValue; 4462 alignas(alignof(T)) char storage[sizeof(T)]; 4463 }; 4464 4465 } // end namespace Catch 4466 4467 // end catch_option.hpp 4468 #include <chrono> 4469 #include <iosfwd> 4470 #include <string> 4471 #include <vector> 4472 #include <memory> 4473 4474 namespace Catch { 4475 4476 enum class Verbosity { 4477 Quiet = 0, 4478 Normal, 4479 High 4480 }; 4481 4482 struct WarnAbout { enum What { 4483 Nothing = 0x00, 4484 NoAssertions = 0x01, 4485 NoTests = 0x02 4486 }; }; 4487 4488 struct ShowDurations { enum OrNot { 4489 DefaultForReporter, 4490 Always, 4491 Never 4492 }; }; 4493 struct RunTests { enum InWhatOrder { 4494 InDeclarationOrder, 4495 InLexicographicalOrder, 4496 InRandomOrder 4497 }; }; 4498 struct UseColour { enum YesOrNo { 4499 Auto, 4500 Yes, 4501 No 4502 }; }; 4503 struct WaitForKeypress { enum When { 4504 Never, 4505 BeforeStart = 1, 4506 BeforeExit = 2, 4507 BeforeStartAndExit = BeforeStart | BeforeExit 4508 }; }; 4509 4510 class TestSpec; 4511 4512 struct IConfig : NonCopyable { 4513 4514 virtual ~IConfig(); 4515 4516 virtual bool allowThrows() const = 0; 4517 virtual std::ostream& stream() const = 0; 4518 virtual std::string name() const = 0; 4519 virtual bool includeSuccessfulResults() const = 0; 4520 virtual bool shouldDebugBreak() const = 0; 4521 virtual bool warnAboutMissingAssertions() const = 0; 4522 virtual bool warnAboutNoTests() const = 0; 4523 virtual int abortAfter() const = 0; 4524 virtual bool showInvisibles() const = 0; 4525 virtual ShowDurations::OrNot showDurations() const = 0; 4526 virtual double minDuration() const = 0; 4527 virtual TestSpec const& testSpec() const = 0; 4528 virtual bool hasTestFilters() const = 0; 4529 virtual std::vector<std::string> const& getTestsOrTags() const = 0; 4530 virtual RunTests::InWhatOrder runOrder() const = 0; 4531 virtual unsigned int rngSeed() const = 0; 4532 virtual UseColour::YesOrNo useColour() const = 0; 4533 virtual std::vector<std::string> const& getSectionsToRun() const = 0; 4534 virtual Verbosity verbosity() const = 0; 4535 4536 virtual bool benchmarkNoAnalysis() const = 0; 4537 virtual int benchmarkSamples() const = 0; 4538 virtual double benchmarkConfidenceInterval() const = 0; 4539 virtual unsigned int benchmarkResamples() const = 0; 4540 virtual std::chrono::milliseconds benchmarkWarmupTime() const = 0; 4541 }; 4542 4543 using IConfigPtr = std::shared_ptr<IConfig const>; 4544 } 4545 4546 // end catch_interfaces_config.h 4547 // start catch_random_number_generator.h 4548 4549 #include <cstdint> 4550 4551 namespace Catch { 4552 4553 // This is a simple implementation of C++11 Uniform Random Number 4554 // Generator. It does not provide all operators, because Catch2 4555 // does not use it, but it should behave as expected inside stdlib's 4556 // distributions. 4557 // The implementation is based on the PCG family (http://pcg-random.org) 4558 class SimplePcg32 { 4559 using state_type = std::uint64_t; 4560 public: 4561 using result_type = std::uint32_t; 4562 static constexpr result_type (min)() { 4563 return 0; 4564 } 4565 static constexpr result_type (max)() { 4566 return static_cast<result_type>(-1); 4567 } 4568 4569 // Provide some default initial state for the default constructor 4570 SimplePcg32():SimplePcg32(0xed743cc4U) {} 4571 4572 explicit SimplePcg32(result_type seed_); 4573 4574 void seed(result_type seed_); 4575 void discard(uint64_t skip); 4576 4577 result_type operator()(); 4578 4579 private: 4580 friend bool operator==(SimplePcg32 const& lhs, SimplePcg32 const& rhs); 4581 friend bool operator!=(SimplePcg32 const& lhs, SimplePcg32 const& rhs); 4582 4583 // In theory we also need operator<< and operator>> 4584 // In practice we do not use them, so we will skip them for now 4585 4586 std::uint64_t m_state; 4587 // This part of the state determines which "stream" of the numbers 4588 // is chosen -- we take it as a constant for Catch2, so we only 4589 // need to deal with seeding the main state. 4590 // Picked by reading 8 bytes from `/dev/random` :-) 4591 static const std::uint64_t s_inc = (0x13ed0cc53f939476ULL << 1ULL) | 1ULL; 4592 }; 4593 4594 } // end namespace Catch 4595 4596 // end catch_random_number_generator.h 4597 #include <random> 4598 4599 namespace Catch { 4600 namespace Generators { 4601 4602 template <typename Float> 4603 class RandomFloatingGenerator final : public IGenerator<Float> { 4604 Catch::SimplePcg32& m_rng; 4605 std::uniform_real_distribution<Float> m_dist; 4606 Float m_current_number; 4607 public: 4608 4609 RandomFloatingGenerator(Float a, Float b): 4610 m_rng(rng()), 4611 m_dist(a, b) { 4612 static_cast<void>(next()); 4613 } 4614 4615 Float const& get() const override { 4616 return m_current_number; 4617 } 4618 bool next() override { 4619 m_current_number = m_dist(m_rng); 4620 return true; 4621 } 4622 }; 4623 4624 template <typename Integer> 4625 class RandomIntegerGenerator final : public IGenerator<Integer> { 4626 Catch::SimplePcg32& m_rng; 4627 std::uniform_int_distribution<Integer> m_dist; 4628 Integer m_current_number; 4629 public: 4630 4631 RandomIntegerGenerator(Integer a, Integer b): 4632 m_rng(rng()), 4633 m_dist(a, b) { 4634 static_cast<void>(next()); 4635 } 4636 4637 Integer const& get() const override { 4638 return m_current_number; 4639 } 4640 bool next() override { 4641 m_current_number = m_dist(m_rng); 4642 return true; 4643 } 4644 }; 4645 4646 // TODO: Ideally this would be also constrained against the various char types, 4647 // but I don't expect users to run into that in practice. 4648 template <typename T> 4649 typename std::enable_if<std::is_integral<T>::value && !std::is_same<T, bool>::value, 4650 GeneratorWrapper<T>>::type 4651 random(T a, T b) { 4652 return GeneratorWrapper<T>( 4653 pf::make_unique<RandomIntegerGenerator<T>>(a, b) 4654 ); 4655 } 4656 4657 template <typename T> 4658 typename std::enable_if<std::is_floating_point<T>::value, 4659 GeneratorWrapper<T>>::type 4660 random(T a, T b) { 4661 return GeneratorWrapper<T>( 4662 pf::make_unique<RandomFloatingGenerator<T>>(a, b) 4663 ); 4664 } 4665 4666 template <typename T> 4667 class RangeGenerator final : public IGenerator<T> { 4668 T m_current; 4669 T m_end; 4670 T m_step; 4671 bool m_positive; 4672 4673 public: 4674 RangeGenerator(T const& start, T const& end, T const& step): 4675 m_current(start), 4676 m_end(end), 4677 m_step(step), 4678 m_positive(m_step > T(0)) 4679 { 4680 assert(m_current != m_end && "Range start and end cannot be equal"); 4681 assert(m_step != T(0) && "Step size cannot be zero"); 4682 assert(((m_positive && m_current <= m_end) || (!m_positive && m_current >= m_end)) && "Step moves away from end"); 4683 } 4684 4685 RangeGenerator(T const& start, T const& end): 4686 RangeGenerator(start, end, (start < end) ? T(1) : T(-1)) 4687 {} 4688 4689 T const& get() const override { 4690 return m_current; 4691 } 4692 4693 bool next() override { 4694 m_current += m_step; 4695 return (m_positive) ? (m_current < m_end) : (m_current > m_end); 4696 } 4697 }; 4698 4699 template <typename T> 4700 GeneratorWrapper<T> range(T const& start, T const& end, T const& step) { 4701 static_assert(std::is_arithmetic<T>::value && !std::is_same<T, bool>::value, "Type must be numeric"); 4702 return GeneratorWrapper<T>(pf::make_unique<RangeGenerator<T>>(start, end, step)); 4703 } 4704 4705 template <typename T> 4706 GeneratorWrapper<T> range(T const& start, T const& end) { 4707 static_assert(std::is_integral<T>::value && !std::is_same<T, bool>::value, "Type must be an integer"); 4708 return GeneratorWrapper<T>(pf::make_unique<RangeGenerator<T>>(start, end)); 4709 } 4710 4711 template <typename T> 4712 class IteratorGenerator final : public IGenerator<T> { 4713 static_assert(!std::is_same<T, bool>::value, 4714 "IteratorGenerator currently does not support bools" 4715 "because of std::vector<bool> specialization"); 4716 4717 std::vector<T> m_elems; 4718 size_t m_current = 0; 4719 public: 4720 template <typename InputIterator, typename InputSentinel> 4721 IteratorGenerator(InputIterator first, InputSentinel last):m_elems(first, last) { 4722 if (m_elems.empty()) { 4723 Catch::throw_exception(GeneratorException("IteratorGenerator received no valid values")); 4724 } 4725 } 4726 4727 T const& get() const override { 4728 return m_elems[m_current]; 4729 } 4730 4731 bool next() override { 4732 ++m_current; 4733 return m_current != m_elems.size(); 4734 } 4735 }; 4736 4737 template <typename InputIterator, 4738 typename InputSentinel, 4739 typename ResultType = typename std::iterator_traits<InputIterator>::value_type> 4740 GeneratorWrapper<ResultType> from_range(InputIterator from, InputSentinel to) { 4741 return GeneratorWrapper<ResultType>(pf::make_unique<IteratorGenerator<ResultType>>(from, to)); 4742 } 4743 4744 template <typename Container, 4745 typename ResultType = typename Container::value_type> 4746 GeneratorWrapper<ResultType> from_range(Container const& cnt) { 4747 return GeneratorWrapper<ResultType>(pf::make_unique<IteratorGenerator<ResultType>>(cnt.begin(), cnt.end())); 4748 } 4749 4750 } // namespace Generators 4751 } // namespace Catch 4752 4753 // end catch_generators_specific.hpp 4754 4755 // These files are included here so the single_include script doesn't put them 4756 // in the conditionally compiled sections 4757 // start catch_test_case_info.h 4758 4759 #include <string> 4760 #include <vector> 4761 #include <memory> 4762 4763 #ifdef __clang__ 4764 #pragma clang diagnostic push 4765 #pragma clang diagnostic ignored "-Wpadded" 4766 #endif 4767 4768 namespace Catch { 4769 4770 struct ITestInvoker; 4771 4772 struct TestCaseInfo { 4773 enum SpecialProperties{ 4774 None = 0, 4775 IsHidden = 1 << 1, 4776 ShouldFail = 1 << 2, 4777 MayFail = 1 << 3, 4778 Throws = 1 << 4, 4779 NonPortable = 1 << 5, 4780 Benchmark = 1 << 6 4781 }; 4782 4783 TestCaseInfo( std::string const& _name, 4784 std::string const& _className, 4785 std::string const& _description, 4786 std::vector<std::string> const& _tags, 4787 SourceLineInfo const& _lineInfo ); 4788 4789 friend void setTags( TestCaseInfo& testCaseInfo, std::vector<std::string> tags ); 4790 4791 bool isHidden() const; 4792 bool throws() const; 4793 bool okToFail() const; 4794 bool expectedToFail() const; 4795 4796 std::string tagsAsString() const; 4797 4798 std::string name; 4799 std::string className; 4800 std::string description; 4801 std::vector<std::string> tags; 4802 std::vector<std::string> lcaseTags; 4803 SourceLineInfo lineInfo; 4804 SpecialProperties properties; 4805 }; 4806 4807 class TestCase : public TestCaseInfo { 4808 public: 4809 4810 TestCase( ITestInvoker* testCase, TestCaseInfo&& info ); 4811 4812 TestCase withName( std::string const& _newName ) const; 4813 4814 void invoke() const; 4815 4816 TestCaseInfo const& getTestCaseInfo() const; 4817 4818 bool operator == ( TestCase const& other ) const; 4819 bool operator < ( TestCase const& other ) const; 4820 4821 private: 4822 std::shared_ptr<ITestInvoker> test; 4823 }; 4824 4825 TestCase makeTestCase( ITestInvoker* testCase, 4826 std::string const& className, 4827 NameAndTags const& nameAndTags, 4828 SourceLineInfo const& lineInfo ); 4829 } 4830 4831 #ifdef __clang__ 4832 #pragma clang diagnostic pop 4833 #endif 4834 4835 // end catch_test_case_info.h 4836 // start catch_interfaces_runner.h 4837 4838 namespace Catch { 4839 4840 struct IRunner { 4841 virtual ~IRunner(); 4842 virtual bool aborting() const = 0; 4843 }; 4844 } 4845 4846 // end catch_interfaces_runner.h 4847 4848 #ifdef __OBJC__ 4849 // start catch_objc.hpp 4850 4851 #import <objc/runtime.h> 4852 4853 #include <string> 4854 4855 // NB. Any general catch headers included here must be included 4856 // in catch.hpp first to make sure they are included by the single 4857 // header for non obj-usage 4858 4859 /////////////////////////////////////////////////////////////////////////////// 4860 // This protocol is really only here for (self) documenting purposes, since 4861 // all its methods are optional. 4862 @protocol OcFixture 4863 4864 @optional 4865 4866 -(void) setUp; 4867 -(void) tearDown; 4868 4869 @end 4870 4871 namespace Catch { 4872 4873 class OcMethod : public ITestInvoker { 4874 4875 public: 4876 OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} 4877 4878 virtual void invoke() const { 4879 id obj = [[m_cls alloc] init]; 4880 4881 performOptionalSelector( obj, @selector(setUp) ); 4882 performOptionalSelector( obj, m_sel ); 4883 performOptionalSelector( obj, @selector(tearDown) ); 4884 4885 arcSafeRelease( obj ); 4886 } 4887 private: 4888 virtual ~OcMethod() {} 4889 4890 Class m_cls; 4891 SEL m_sel; 4892 }; 4893 4894 namespace Detail{ 4895 4896 inline std::string getAnnotation( Class cls, 4897 std::string const& annotationName, 4898 std::string const& testCaseName ) { 4899 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()]; 4900 SEL sel = NSSelectorFromString( selStr ); 4901 arcSafeRelease( selStr ); 4902 id value = performOptionalSelector( cls, sel ); 4903 if( value ) 4904 return [(NSString*)value UTF8String]; 4905 return ""; 4906 } 4907 } 4908 4909 inline std::size_t registerTestMethods() { 4910 std::size_t noTestMethods = 0; 4911 int noClasses = objc_getClassList( nullptr, 0 ); 4912 4913 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); 4914 objc_getClassList( classes, noClasses ); 4915 4916 for( int c = 0; c < noClasses; c++ ) { 4917 Class cls = classes[c]; 4918 { 4919 u_int count; 4920 Method* methods = class_copyMethodList( cls, &count ); 4921 for( u_int m = 0; m < count ; m++ ) { 4922 SEL selector = method_getName(methods[m]); 4923 std::string methodName = sel_getName(selector); 4924 if( startsWith( methodName, "Catch_TestCase_" ) ) { 4925 std::string testCaseName = methodName.substr( 15 ); 4926 std::string name = Detail::getAnnotation( cls, "Name", testCaseName ); 4927 std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); 4928 const char* className = class_getName( cls ); 4929 4930 getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, NameAndTags( name.c_str(), desc.c_str() ), SourceLineInfo("",0) ) ); 4931 noTestMethods++; 4932 } 4933 } 4934 free(methods); 4935 } 4936 } 4937 return noTestMethods; 4938 } 4939 4940 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 4941 4942 namespace Matchers { 4943 namespace Impl { 4944 namespace NSStringMatchers { 4945 4946 struct StringHolder : MatcherBase<NSString*>{ 4947 StringHolder( NSString* substr ) : m_substr( [substr copy] ){} 4948 StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){} 4949 StringHolder() { 4950 arcSafeRelease( m_substr ); 4951 } 4952 4953 bool match( NSString* str ) const override { 4954 return false; 4955 } 4956 4957 NSString* CATCH_ARC_STRONG m_substr; 4958 }; 4959 4960 struct Equals : StringHolder { 4961 Equals( NSString* substr ) : StringHolder( substr ){} 4962 4963 bool match( NSString* str ) const override { 4964 return (str != nil || m_substr == nil ) && 4965 [str isEqualToString:m_substr]; 4966 } 4967 4968 std::string describe() const override { 4969 return "equals string: " + Catch::Detail::stringify( m_substr ); 4970 } 4971 }; 4972 4973 struct Contains : StringHolder { 4974 Contains( NSString* substr ) : StringHolder( substr ){} 4975 4976 bool match( NSString* str ) const override { 4977 return (str != nil || m_substr == nil ) && 4978 [str rangeOfString:m_substr].location != NSNotFound; 4979 } 4980 4981 std::string describe() const override { 4982 return "contains string: " + Catch::Detail::stringify( m_substr ); 4983 } 4984 }; 4985 4986 struct StartsWith : StringHolder { 4987 StartsWith( NSString* substr ) : StringHolder( substr ){} 4988 4989 bool match( NSString* str ) const override { 4990 return (str != nil || m_substr == nil ) && 4991 [str rangeOfString:m_substr].location == 0; 4992 } 4993 4994 std::string describe() const override { 4995 return "starts with: " + Catch::Detail::stringify( m_substr ); 4996 } 4997 }; 4998 struct EndsWith : StringHolder { 4999 EndsWith( NSString* substr ) : StringHolder( substr ){} 5000 5001 bool match( NSString* str ) const override { 5002 return (str != nil || m_substr == nil ) && 5003 [str rangeOfString:m_substr].location == [str length] - [m_substr length]; 5004 } 5005 5006 std::string describe() const override { 5007 return "ends with: " + Catch::Detail::stringify( m_substr ); 5008 } 5009 }; 5010 5011 } // namespace NSStringMatchers 5012 } // namespace Impl 5013 5014 inline Impl::NSStringMatchers::Equals 5015 Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); } 5016 5017 inline Impl::NSStringMatchers::Contains 5018 Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); } 5019 5020 inline Impl::NSStringMatchers::StartsWith 5021 StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); } 5022 5023 inline Impl::NSStringMatchers::EndsWith 5024 EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); } 5025 5026 } // namespace Matchers 5027 5028 using namespace Matchers; 5029 5030 #endif // CATCH_CONFIG_DISABLE_MATCHERS 5031 5032 } // namespace Catch 5033 5034 /////////////////////////////////////////////////////////////////////////////// 5035 #define OC_MAKE_UNIQUE_NAME( root, uniqueSuffix ) root##uniqueSuffix 5036 #define OC_TEST_CASE2( name, desc, uniqueSuffix ) \ 5037 +(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Name_test_, uniqueSuffix ) \ 5038 { \ 5039 return @ name; \ 5040 } \ 5041 +(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Description_test_, uniqueSuffix ) \ 5042 { \ 5043 return @ desc; \ 5044 } \ 5045 -(void) OC_MAKE_UNIQUE_NAME( Catch_TestCase_test_, uniqueSuffix ) 5046 5047 #define OC_TEST_CASE( name, desc ) OC_TEST_CASE2( name, desc, __LINE__ ) 5048 5049 // end catch_objc.hpp 5050 #endif 5051 5052 // Benchmarking needs the externally-facing parts of reporters to work 5053 #if defined(CATCH_CONFIG_EXTERNAL_INTERFACES) || defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 5054 // start catch_external_interfaces.h 5055 5056 // start catch_reporter_bases.hpp 5057 5058 // start catch_interfaces_reporter.h 5059 5060 // start catch_config.hpp 5061 5062 // start catch_test_spec_parser.h 5063 5064 #ifdef __clang__ 5065 #pragma clang diagnostic push 5066 #pragma clang diagnostic ignored "-Wpadded" 5067 #endif 5068 5069 // start catch_test_spec.h 5070 5071 #ifdef __clang__ 5072 #pragma clang diagnostic push 5073 #pragma clang diagnostic ignored "-Wpadded" 5074 #endif 5075 5076 // start catch_wildcard_pattern.h 5077 5078 namespace Catch 5079 { 5080 class WildcardPattern { 5081 enum WildcardPosition { 5082 NoWildcard = 0, 5083 WildcardAtStart = 1, 5084 WildcardAtEnd = 2, 5085 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd 5086 }; 5087 5088 public: 5089 5090 WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity ); 5091 virtual ~WildcardPattern() = default; 5092 virtual bool matches( std::string const& str ) const; 5093 5094 private: 5095 std::string normaliseString( std::string const& str ) const; 5096 CaseSensitive::Choice m_caseSensitivity; 5097 WildcardPosition m_wildcard = NoWildcard; 5098 std::string m_pattern; 5099 }; 5100 } 5101 5102 // end catch_wildcard_pattern.h 5103 #include <string> 5104 #include <vector> 5105 #include <memory> 5106 5107 namespace Catch { 5108 5109 struct IConfig; 5110 5111 class TestSpec { 5112 class Pattern { 5113 public: 5114 explicit Pattern( std::string const& name ); 5115 virtual ~Pattern(); 5116 virtual bool matches( TestCaseInfo const& testCase ) const = 0; 5117 std::string const& name() const; 5118 private: 5119 std::string const m_name; 5120 }; 5121 using PatternPtr = std::shared_ptr<Pattern>; 5122 5123 class NamePattern : public Pattern { 5124 public: 5125 explicit NamePattern( std::string const& name, std::string const& filterString ); 5126 bool matches( TestCaseInfo const& testCase ) const override; 5127 private: 5128 WildcardPattern m_wildcardPattern; 5129 }; 5130 5131 class TagPattern : public Pattern { 5132 public: 5133 explicit TagPattern( std::string const& tag, std::string const& filterString ); 5134 bool matches( TestCaseInfo const& testCase ) const override; 5135 private: 5136 std::string m_tag; 5137 }; 5138 5139 class ExcludedPattern : public Pattern { 5140 public: 5141 explicit ExcludedPattern( PatternPtr const& underlyingPattern ); 5142 bool matches( TestCaseInfo const& testCase ) const override; 5143 private: 5144 PatternPtr m_underlyingPattern; 5145 }; 5146 5147 struct Filter { 5148 std::vector<PatternPtr> m_patterns; 5149 5150 bool matches( TestCaseInfo const& testCase ) const; 5151 std::string name() const; 5152 }; 5153 5154 public: 5155 struct FilterMatch { 5156 std::string name; 5157 std::vector<TestCase const*> tests; 5158 }; 5159 using Matches = std::vector<FilterMatch>; 5160 using vectorStrings = std::vector<std::string>; 5161 5162 bool hasFilters() const; 5163 bool matches( TestCaseInfo const& testCase ) const; 5164 Matches matchesByFilter( std::vector<TestCase> const& testCases, IConfig const& config ) const; 5165 const vectorStrings & getInvalidArgs() const; 5166 5167 private: 5168 std::vector<Filter> m_filters; 5169 std::vector<std::string> m_invalidArgs; 5170 friend class TestSpecParser; 5171 }; 5172 } 5173 5174 #ifdef __clang__ 5175 #pragma clang diagnostic pop 5176 #endif 5177 5178 // end catch_test_spec.h 5179 // start catch_interfaces_tag_alias_registry.h 5180 5181 #include <string> 5182 5183 namespace Catch { 5184 5185 struct TagAlias; 5186 5187 struct ITagAliasRegistry { 5188 virtual ~ITagAliasRegistry(); 5189 // Nullptr if not present 5190 virtual TagAlias const* find( std::string const& alias ) const = 0; 5191 virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; 5192 5193 static ITagAliasRegistry const& get(); 5194 }; 5195 5196 } // end namespace Catch 5197 5198 // end catch_interfaces_tag_alias_registry.h 5199 namespace Catch { 5200 5201 class TestSpecParser { 5202 enum Mode{ None, Name, QuotedName, Tag, EscapedName }; 5203 Mode m_mode = None; 5204 Mode lastMode = None; 5205 bool m_exclusion = false; 5206 std::size_t m_pos = 0; 5207 std::size_t m_realPatternPos = 0; 5208 std::string m_arg; 5209 std::string m_substring; 5210 std::string m_patternName; 5211 std::vector<std::size_t> m_escapeChars; 5212 TestSpec::Filter m_currentFilter; 5213 TestSpec m_testSpec; 5214 ITagAliasRegistry const* m_tagAliases = nullptr; 5215 5216 public: 5217 TestSpecParser( ITagAliasRegistry const& tagAliases ); 5218 5219 TestSpecParser& parse( std::string const& arg ); 5220 TestSpec testSpec(); 5221 5222 private: 5223 bool visitChar( char c ); 5224 void startNewMode( Mode mode ); 5225 bool processNoneChar( char c ); 5226 void processNameChar( char c ); 5227 bool processOtherChar( char c ); 5228 void endMode(); 5229 void escape(); 5230 bool isControlChar( char c ) const; 5231 void saveLastMode(); 5232 void revertBackToLastMode(); 5233 void addFilter(); 5234 bool separate(); 5235 5236 // Handles common preprocessing of the pattern for name/tag patterns 5237 std::string preprocessPattern(); 5238 // Adds the current pattern as a test name 5239 void addNamePattern(); 5240 // Adds the current pattern as a tag 5241 void addTagPattern(); 5242 5243 inline void addCharToPattern(char c) { 5244 m_substring += c; 5245 m_patternName += c; 5246 m_realPatternPos++; 5247 } 5248 5249 }; 5250 TestSpec parseTestSpec( std::string const& arg ); 5251 5252 } // namespace Catch 5253 5254 #ifdef __clang__ 5255 #pragma clang diagnostic pop 5256 #endif 5257 5258 // end catch_test_spec_parser.h 5259 // Libstdc++ doesn't like incomplete classes for unique_ptr 5260 5261 #include <memory> 5262 #include <vector> 5263 #include <string> 5264 5265 #ifndef CATCH_CONFIG_CONSOLE_WIDTH 5266 #define CATCH_CONFIG_CONSOLE_WIDTH 80 5267 #endif 5268 5269 namespace Catch { 5270 5271 struct IStream; 5272 5273 struct ConfigData { 5274 bool listTests = false; 5275 bool listTags = false; 5276 bool listReporters = false; 5277 bool listTestNamesOnly = false; 5278 5279 bool showSuccessfulTests = false; 5280 bool shouldDebugBreak = false; 5281 bool noThrow = false; 5282 bool showHelp = false; 5283 bool showInvisibles = false; 5284 bool filenamesAsTags = false; 5285 bool libIdentify = false; 5286 5287 int abortAfter = -1; 5288 unsigned int rngSeed = 0; 5289 5290 bool benchmarkNoAnalysis = false; 5291 unsigned int benchmarkSamples = 100; 5292 double benchmarkConfidenceInterval = 0.95; 5293 unsigned int benchmarkResamples = 100000; 5294 std::chrono::milliseconds::rep benchmarkWarmupTime = 100; 5295 5296 Verbosity verbosity = Verbosity::Normal; 5297 WarnAbout::What warnings = WarnAbout::Nothing; 5298 ShowDurations::OrNot showDurations = ShowDurations::DefaultForReporter; 5299 double minDuration = -1; 5300 RunTests::InWhatOrder runOrder = RunTests::InDeclarationOrder; 5301 UseColour::YesOrNo useColour = UseColour::Auto; 5302 WaitForKeypress::When waitForKeypress = WaitForKeypress::Never; 5303 5304 std::string outputFilename; 5305 std::string name; 5306 std::string processName; 5307 #ifndef CATCH_CONFIG_DEFAULT_REPORTER 5308 #define CATCH_CONFIG_DEFAULT_REPORTER "console" 5309 #endif 5310 std::string reporterName = CATCH_CONFIG_DEFAULT_REPORTER; 5311 #undef CATCH_CONFIG_DEFAULT_REPORTER 5312 5313 std::vector<std::string> testsOrTags; 5314 std::vector<std::string> sectionsToRun; 5315 }; 5316 5317 class Config : public IConfig { 5318 public: 5319 5320 Config() = default; 5321 Config( ConfigData const& data ); 5322 virtual ~Config() = default; 5323 5324 std::string const& getFilename() const; 5325 5326 bool listTests() const; 5327 bool listTestNamesOnly() const; 5328 bool listTags() const; 5329 bool listReporters() const; 5330 5331 std::string getProcessName() const; 5332 std::string const& getReporterName() const; 5333 5334 std::vector<std::string> const& getTestsOrTags() const override; 5335 std::vector<std::string> const& getSectionsToRun() const override; 5336 5337 TestSpec const& testSpec() const override; 5338 bool hasTestFilters() const override; 5339 5340 bool showHelp() const; 5341 5342 // IConfig interface 5343 bool allowThrows() const override; 5344 std::ostream& stream() const override; 5345 std::string name() const override; 5346 bool includeSuccessfulResults() const override; 5347 bool warnAboutMissingAssertions() const override; 5348 bool warnAboutNoTests() const override; 5349 ShowDurations::OrNot showDurations() const override; 5350 double minDuration() const override; 5351 RunTests::InWhatOrder runOrder() const override; 5352 unsigned int rngSeed() const override; 5353 UseColour::YesOrNo useColour() const override; 5354 bool shouldDebugBreak() const override; 5355 int abortAfter() const override; 5356 bool showInvisibles() const override; 5357 Verbosity verbosity() const override; 5358 bool benchmarkNoAnalysis() const override; 5359 int benchmarkSamples() const override; 5360 double benchmarkConfidenceInterval() const override; 5361 unsigned int benchmarkResamples() const override; 5362 std::chrono::milliseconds benchmarkWarmupTime() const override; 5363 5364 private: 5365 5366 IStream const* openStream(); 5367 ConfigData m_data; 5368 5369 std::unique_ptr<IStream const> m_stream; 5370 TestSpec m_testSpec; 5371 bool m_hasTestFilters = false; 5372 }; 5373 5374 } // end namespace Catch 5375 5376 // end catch_config.hpp 5377 // start catch_assertionresult.h 5378 5379 #include <string> 5380 5381 namespace Catch { 5382 5383 struct AssertionResultData 5384 { 5385 AssertionResultData() = delete; 5386 5387 AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression ); 5388 5389 std::string message; 5390 mutable std::string reconstructedExpression; 5391 LazyExpression lazyExpression; 5392 ResultWas::OfType resultType; 5393 5394 std::string reconstructExpression() const; 5395 }; 5396 5397 class AssertionResult { 5398 public: 5399 AssertionResult() = delete; 5400 AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); 5401 5402 bool isOk() const; 5403 bool succeeded() const; 5404 ResultWas::OfType getResultType() const; 5405 bool hasExpression() const; 5406 bool hasMessage() const; 5407 std::string getExpression() const; 5408 std::string getExpressionInMacro() const; 5409 bool hasExpandedExpression() const; 5410 std::string getExpandedExpression() const; 5411 std::string getMessage() const; 5412 SourceLineInfo getSourceInfo() const; 5413 StringRef getTestMacroName() const; 5414 5415 //protected: 5416 AssertionInfo m_info; 5417 AssertionResultData m_resultData; 5418 }; 5419 5420 } // end namespace Catch 5421 5422 // end catch_assertionresult.h 5423 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 5424 // start catch_estimate.hpp 5425 5426 // Statistics estimates 5427 5428 5429 namespace Catch { 5430 namespace Benchmark { 5431 template <typename Duration> 5432 struct Estimate { 5433 Duration point; 5434 Duration lower_bound; 5435 Duration upper_bound; 5436 double confidence_interval; 5437 5438 template <typename Duration2> 5439 operator Estimate<Duration2>() const { 5440 return { point, lower_bound, upper_bound, confidence_interval }; 5441 } 5442 }; 5443 } // namespace Benchmark 5444 } // namespace Catch 5445 5446 // end catch_estimate.hpp 5447 // start catch_outlier_classification.hpp 5448 5449 // Outlier information 5450 5451 namespace Catch { 5452 namespace Benchmark { 5453 struct OutlierClassification { 5454 int samples_seen = 0; 5455 int low_severe = 0; // more than 3 times IQR below Q1 5456 int low_mild = 0; // 1.5 to 3 times IQR below Q1 5457 int high_mild = 0; // 1.5 to 3 times IQR above Q3 5458 int high_severe = 0; // more than 3 times IQR above Q3 5459 5460 int total() const { 5461 return low_severe + low_mild + high_mild + high_severe; 5462 } 5463 }; 5464 } // namespace Benchmark 5465 } // namespace Catch 5466 5467 // end catch_outlier_classification.hpp 5468 5469 #include <iterator> 5470 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 5471 5472 #include <string> 5473 #include <iosfwd> 5474 #include <map> 5475 #include <set> 5476 #include <memory> 5477 #include <algorithm> 5478 5479 namespace Catch { 5480 5481 struct ReporterConfig { 5482 explicit ReporterConfig( IConfigPtr const& _fullConfig ); 5483 5484 ReporterConfig( IConfigPtr const& _fullConfig, std::ostream& _stream ); 5485 5486 std::ostream& stream() const; 5487 IConfigPtr fullConfig() const; 5488 5489 private: 5490 std::ostream* m_stream; 5491 IConfigPtr m_fullConfig; 5492 }; 5493 5494 struct ReporterPreferences { 5495 bool shouldRedirectStdOut = false; 5496 bool shouldReportAllAssertions = false; 5497 }; 5498 5499 template<typename T> 5500 struct LazyStat : Option<T> { 5501 LazyStat& operator=( T const& _value ) { 5502 Option<T>::operator=( _value ); 5503 used = false; 5504 return *this; 5505 } 5506 void reset() { 5507 Option<T>::reset(); 5508 used = false; 5509 } 5510 bool used = false; 5511 }; 5512 5513 struct TestRunInfo { 5514 TestRunInfo( std::string const& _name ); 5515 std::string name; 5516 }; 5517 struct GroupInfo { 5518 GroupInfo( std::string const& _name, 5519 std::size_t _groupIndex, 5520 std::size_t _groupsCount ); 5521 5522 std::string name; 5523 std::size_t groupIndex; 5524 std::size_t groupsCounts; 5525 }; 5526 5527 struct AssertionStats { 5528 AssertionStats( AssertionResult const& _assertionResult, 5529 std::vector<MessageInfo> const& _infoMessages, 5530 Totals const& _totals ); 5531 5532 AssertionStats( AssertionStats const& ) = default; 5533 AssertionStats( AssertionStats && ) = default; 5534 AssertionStats& operator = ( AssertionStats const& ) = delete; 5535 AssertionStats& operator = ( AssertionStats && ) = delete; 5536 virtual ~AssertionStats(); 5537 5538 AssertionResult assertionResult; 5539 std::vector<MessageInfo> infoMessages; 5540 Totals totals; 5541 }; 5542 5543 struct SectionStats { 5544 SectionStats( SectionInfo const& _sectionInfo, 5545 Counts const& _assertions, 5546 double _durationInSeconds, 5547 bool _missingAssertions ); 5548 SectionStats( SectionStats const& ) = default; 5549 SectionStats( SectionStats && ) = default; 5550 SectionStats& operator = ( SectionStats const& ) = default; 5551 SectionStats& operator = ( SectionStats && ) = default; 5552 virtual ~SectionStats(); 5553 5554 SectionInfo sectionInfo; 5555 Counts assertions; 5556 double durationInSeconds; 5557 bool missingAssertions; 5558 }; 5559 5560 struct TestCaseStats { 5561 TestCaseStats( TestCaseInfo const& _testInfo, 5562 Totals const& _totals, 5563 std::string const& _stdOut, 5564 std::string const& _stdErr, 5565 bool _aborting ); 5566 5567 TestCaseStats( TestCaseStats const& ) = default; 5568 TestCaseStats( TestCaseStats && ) = default; 5569 TestCaseStats& operator = ( TestCaseStats const& ) = default; 5570 TestCaseStats& operator = ( TestCaseStats && ) = default; 5571 virtual ~TestCaseStats(); 5572 5573 TestCaseInfo testInfo; 5574 Totals totals; 5575 std::string stdOut; 5576 std::string stdErr; 5577 bool aborting; 5578 }; 5579 5580 struct TestGroupStats { 5581 TestGroupStats( GroupInfo const& _groupInfo, 5582 Totals const& _totals, 5583 bool _aborting ); 5584 TestGroupStats( GroupInfo const& _groupInfo ); 5585 5586 TestGroupStats( TestGroupStats const& ) = default; 5587 TestGroupStats( TestGroupStats && ) = default; 5588 TestGroupStats& operator = ( TestGroupStats const& ) = default; 5589 TestGroupStats& operator = ( TestGroupStats && ) = default; 5590 virtual ~TestGroupStats(); 5591 5592 GroupInfo groupInfo; 5593 Totals totals; 5594 bool aborting; 5595 }; 5596 5597 struct TestRunStats { 5598 TestRunStats( TestRunInfo const& _runInfo, 5599 Totals const& _totals, 5600 bool _aborting ); 5601 5602 TestRunStats( TestRunStats const& ) = default; 5603 TestRunStats( TestRunStats && ) = default; 5604 TestRunStats& operator = ( TestRunStats const& ) = default; 5605 TestRunStats& operator = ( TestRunStats && ) = default; 5606 virtual ~TestRunStats(); 5607 5608 TestRunInfo runInfo; 5609 Totals totals; 5610 bool aborting; 5611 }; 5612 5613 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 5614 struct BenchmarkInfo { 5615 std::string name; 5616 double estimatedDuration; 5617 int iterations; 5618 int samples; 5619 unsigned int resamples; 5620 double clockResolution; 5621 double clockCost; 5622 }; 5623 5624 template <class Duration> 5625 struct BenchmarkStats { 5626 BenchmarkInfo info; 5627 5628 std::vector<Duration> samples; 5629 Benchmark::Estimate<Duration> mean; 5630 Benchmark::Estimate<Duration> standardDeviation; 5631 Benchmark::OutlierClassification outliers; 5632 double outlierVariance; 5633 5634 template <typename Duration2> 5635 operator BenchmarkStats<Duration2>() const { 5636 std::vector<Duration2> samples2; 5637 samples2.reserve(samples.size()); 5638 std::transform(samples.begin(), samples.end(), std::back_inserter(samples2), [](Duration d) { return Duration2(d); }); 5639 return { 5640 info, 5641 std::move(samples2), 5642 mean, 5643 standardDeviation, 5644 outliers, 5645 outlierVariance, 5646 }; 5647 } 5648 }; 5649 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 5650 5651 struct IStreamingReporter { 5652 virtual ~IStreamingReporter() = default; 5653 5654 // Implementing class must also provide the following static methods: 5655 // static std::string getDescription(); 5656 // static std::set<Verbosity> getSupportedVerbosities() 5657 5658 virtual ReporterPreferences getPreferences() const = 0; 5659 5660 virtual void noMatchingTestCases( std::string const& spec ) = 0; 5661 5662 virtual void reportInvalidArguments(std::string const&) {} 5663 5664 virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; 5665 virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0; 5666 5667 virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; 5668 virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; 5669 5670 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 5671 virtual void benchmarkPreparing( std::string const& ) {} 5672 virtual void benchmarkStarting( BenchmarkInfo const& ) {} 5673 virtual void benchmarkEnded( BenchmarkStats<> const& ) {} 5674 virtual void benchmarkFailed( std::string const& ) {} 5675 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 5676 5677 virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; 5678 5679 // The return value indicates if the messages buffer should be cleared: 5680 virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; 5681 5682 virtual void sectionEnded( SectionStats const& sectionStats ) = 0; 5683 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; 5684 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; 5685 virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; 5686 5687 virtual void skipTest( TestCaseInfo const& testInfo ) = 0; 5688 5689 // Default empty implementation provided 5690 virtual void fatalErrorEncountered( StringRef name ); 5691 5692 virtual bool isMulti() const; 5693 }; 5694 using IStreamingReporterPtr = std::unique_ptr<IStreamingReporter>; 5695 5696 struct IReporterFactory { 5697 virtual ~IReporterFactory(); 5698 virtual IStreamingReporterPtr create( ReporterConfig const& config ) const = 0; 5699 virtual std::string getDescription() const = 0; 5700 }; 5701 using IReporterFactoryPtr = std::shared_ptr<IReporterFactory>; 5702 5703 struct IReporterRegistry { 5704 using FactoryMap = std::map<std::string, IReporterFactoryPtr>; 5705 using Listeners = std::vector<IReporterFactoryPtr>; 5706 5707 virtual ~IReporterRegistry(); 5708 virtual IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const = 0; 5709 virtual FactoryMap const& getFactories() const = 0; 5710 virtual Listeners const& getListeners() const = 0; 5711 }; 5712 5713 } // end namespace Catch 5714 5715 // end catch_interfaces_reporter.h 5716 #include <algorithm> 5717 #include <cstring> 5718 #include <cfloat> 5719 #include <cstdio> 5720 #include <cassert> 5721 #include <memory> 5722 #include <ostream> 5723 5724 namespace Catch { 5725 void prepareExpandedExpression(AssertionResult& result); 5726 5727 // Returns double formatted as %.3f (format expected on output) 5728 std::string getFormattedDuration( double duration ); 5729 5730 //! Should the reporter show 5731 bool shouldShowDuration( IConfig const& config, double duration ); 5732 5733 std::string serializeFilters( std::vector<std::string> const& container ); 5734 5735 template<typename DerivedT> 5736 struct StreamingReporterBase : IStreamingReporter { 5737 5738 StreamingReporterBase( ReporterConfig const& _config ) 5739 : m_config( _config.fullConfig() ), 5740 stream( _config.stream() ) 5741 { 5742 m_reporterPrefs.shouldRedirectStdOut = false; 5743 if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) ) 5744 CATCH_ERROR( "Verbosity level not supported by this reporter" ); 5745 } 5746 5747 ReporterPreferences getPreferences() const override { 5748 return m_reporterPrefs; 5749 } 5750 5751 static std::set<Verbosity> getSupportedVerbosities() { 5752 return { Verbosity::Normal }; 5753 } 5754 5755 ~StreamingReporterBase() override = default; 5756 5757 void noMatchingTestCases(std::string const&) override {} 5758 5759 void reportInvalidArguments(std::string const&) override {} 5760 5761 void testRunStarting(TestRunInfo const& _testRunInfo) override { 5762 currentTestRunInfo = _testRunInfo; 5763 } 5764 5765 void testGroupStarting(GroupInfo const& _groupInfo) override { 5766 currentGroupInfo = _groupInfo; 5767 } 5768 5769 void testCaseStarting(TestCaseInfo const& _testInfo) override { 5770 currentTestCaseInfo = _testInfo; 5771 } 5772 void sectionStarting(SectionInfo const& _sectionInfo) override { 5773 m_sectionStack.push_back(_sectionInfo); 5774 } 5775 5776 void sectionEnded(SectionStats const& /* _sectionStats */) override { 5777 m_sectionStack.pop_back(); 5778 } 5779 void testCaseEnded(TestCaseStats const& /* _testCaseStats */) override { 5780 currentTestCaseInfo.reset(); 5781 } 5782 void testGroupEnded(TestGroupStats const& /* _testGroupStats */) override { 5783 currentGroupInfo.reset(); 5784 } 5785 void testRunEnded(TestRunStats const& /* _testRunStats */) override { 5786 currentTestCaseInfo.reset(); 5787 currentGroupInfo.reset(); 5788 currentTestRunInfo.reset(); 5789 } 5790 5791 void skipTest(TestCaseInfo const&) override { 5792 // Don't do anything with this by default. 5793 // It can optionally be overridden in the derived class. 5794 } 5795 5796 IConfigPtr m_config; 5797 std::ostream& stream; 5798 5799 LazyStat<TestRunInfo> currentTestRunInfo; 5800 LazyStat<GroupInfo> currentGroupInfo; 5801 LazyStat<TestCaseInfo> currentTestCaseInfo; 5802 5803 std::vector<SectionInfo> m_sectionStack; 5804 ReporterPreferences m_reporterPrefs; 5805 }; 5806 5807 template<typename DerivedT> 5808 struct CumulativeReporterBase : IStreamingReporter { 5809 template<typename T, typename ChildNodeT> 5810 struct Node { 5811 explicit Node( T const& _value ) : value( _value ) {} 5812 virtual ~Node() {} 5813 5814 using ChildNodes = std::vector<std::shared_ptr<ChildNodeT>>; 5815 T value; 5816 ChildNodes children; 5817 }; 5818 struct SectionNode { 5819 explicit SectionNode(SectionStats const& _stats) : stats(_stats) {} 5820 virtual ~SectionNode() = default; 5821 5822 bool operator == (SectionNode const& other) const { 5823 return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; 5824 } 5825 bool operator == (std::shared_ptr<SectionNode> const& other) const { 5826 return operator==(*other); 5827 } 5828 5829 SectionStats stats; 5830 using ChildSections = std::vector<std::shared_ptr<SectionNode>>; 5831 using Assertions = std::vector<AssertionStats>; 5832 ChildSections childSections; 5833 Assertions assertions; 5834 std::string stdOut; 5835 std::string stdErr; 5836 }; 5837 5838 struct BySectionInfo { 5839 BySectionInfo( SectionInfo const& other ) : m_other( other ) {} 5840 BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {} 5841 bool operator() (std::shared_ptr<SectionNode> const& node) const { 5842 return ((node->stats.sectionInfo.name == m_other.name) && 5843 (node->stats.sectionInfo.lineInfo == m_other.lineInfo)); 5844 } 5845 void operator=(BySectionInfo const&) = delete; 5846 5847 private: 5848 SectionInfo const& m_other; 5849 }; 5850 5851 using TestCaseNode = Node<TestCaseStats, SectionNode>; 5852 using TestGroupNode = Node<TestGroupStats, TestCaseNode>; 5853 using TestRunNode = Node<TestRunStats, TestGroupNode>; 5854 5855 CumulativeReporterBase( ReporterConfig const& _config ) 5856 : m_config( _config.fullConfig() ), 5857 stream( _config.stream() ) 5858 { 5859 m_reporterPrefs.shouldRedirectStdOut = false; 5860 if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) ) 5861 CATCH_ERROR( "Verbosity level not supported by this reporter" ); 5862 } 5863 ~CumulativeReporterBase() override = default; 5864 5865 ReporterPreferences getPreferences() const override { 5866 return m_reporterPrefs; 5867 } 5868 5869 static std::set<Verbosity> getSupportedVerbosities() { 5870 return { Verbosity::Normal }; 5871 } 5872 5873 void testRunStarting( TestRunInfo const& ) override {} 5874 void testGroupStarting( GroupInfo const& ) override {} 5875 5876 void testCaseStarting( TestCaseInfo const& ) override {} 5877 5878 void sectionStarting( SectionInfo const& sectionInfo ) override { 5879 SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); 5880 std::shared_ptr<SectionNode> node; 5881 if( m_sectionStack.empty() ) { 5882 if( !m_rootSection ) 5883 m_rootSection = std::make_shared<SectionNode>( incompleteStats ); 5884 node = m_rootSection; 5885 } 5886 else { 5887 SectionNode& parentNode = *m_sectionStack.back(); 5888 auto it = 5889 std::find_if( parentNode.childSections.begin(), 5890 parentNode.childSections.end(), 5891 BySectionInfo( sectionInfo ) ); 5892 if( it == parentNode.childSections.end() ) { 5893 node = std::make_shared<SectionNode>( incompleteStats ); 5894 parentNode.childSections.push_back( node ); 5895 } 5896 else 5897 node = *it; 5898 } 5899 m_sectionStack.push_back( node ); 5900 m_deepestSection = std::move(node); 5901 } 5902 5903 void assertionStarting(AssertionInfo const&) override {} 5904 5905 bool assertionEnded(AssertionStats const& assertionStats) override { 5906 assert(!m_sectionStack.empty()); 5907 // AssertionResult holds a pointer to a temporary DecomposedExpression, 5908 // which getExpandedExpression() calls to build the expression string. 5909 // Our section stack copy of the assertionResult will likely outlive the 5910 // temporary, so it must be expanded or discarded now to avoid calling 5911 // a destroyed object later. 5912 prepareExpandedExpression(const_cast<AssertionResult&>( assertionStats.assertionResult ) ); 5913 SectionNode& sectionNode = *m_sectionStack.back(); 5914 sectionNode.assertions.push_back(assertionStats); 5915 return true; 5916 } 5917 void sectionEnded(SectionStats const& sectionStats) override { 5918 assert(!m_sectionStack.empty()); 5919 SectionNode& node = *m_sectionStack.back(); 5920 node.stats = sectionStats; 5921 m_sectionStack.pop_back(); 5922 } 5923 void testCaseEnded(TestCaseStats const& testCaseStats) override { 5924 auto node = std::make_shared<TestCaseNode>(testCaseStats); 5925 assert(m_sectionStack.size() == 0); 5926 node->children.push_back(m_rootSection); 5927 m_testCases.push_back(node); 5928 m_rootSection.reset(); 5929 5930 assert(m_deepestSection); 5931 m_deepestSection->stdOut = testCaseStats.stdOut; 5932 m_deepestSection->stdErr = testCaseStats.stdErr; 5933 } 5934 void testGroupEnded(TestGroupStats const& testGroupStats) override { 5935 auto node = std::make_shared<TestGroupNode>(testGroupStats); 5936 node->children.swap(m_testCases); 5937 m_testGroups.push_back(node); 5938 } 5939 void testRunEnded(TestRunStats const& testRunStats) override { 5940 auto node = std::make_shared<TestRunNode>(testRunStats); 5941 node->children.swap(m_testGroups); 5942 m_testRuns.push_back(node); 5943 testRunEndedCumulative(); 5944 } 5945 virtual void testRunEndedCumulative() = 0; 5946 5947 void skipTest(TestCaseInfo const&) override {} 5948 5949 IConfigPtr m_config; 5950 std::ostream& stream; 5951 std::vector<AssertionStats> m_assertions; 5952 std::vector<std::vector<std::shared_ptr<SectionNode>>> m_sections; 5953 std::vector<std::shared_ptr<TestCaseNode>> m_testCases; 5954 std::vector<std::shared_ptr<TestGroupNode>> m_testGroups; 5955 5956 std::vector<std::shared_ptr<TestRunNode>> m_testRuns; 5957 5958 std::shared_ptr<SectionNode> m_rootSection; 5959 std::shared_ptr<SectionNode> m_deepestSection; 5960 std::vector<std::shared_ptr<SectionNode>> m_sectionStack; 5961 ReporterPreferences m_reporterPrefs; 5962 }; 5963 5964 template<char C> 5965 char const* getLineOfChars() { 5966 static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0}; 5967 if( !*line ) { 5968 std::memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 ); 5969 line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0; 5970 } 5971 return line; 5972 } 5973 5974 struct TestEventListenerBase : StreamingReporterBase<TestEventListenerBase> { 5975 TestEventListenerBase( ReporterConfig const& _config ); 5976 5977 static std::set<Verbosity> getSupportedVerbosities(); 5978 5979 void assertionStarting(AssertionInfo const&) override; 5980 bool assertionEnded(AssertionStats const&) override; 5981 }; 5982 5983 } // end namespace Catch 5984 5985 // end catch_reporter_bases.hpp 5986 // start catch_console_colour.h 5987 5988 namespace Catch { 5989 5990 struct Colour { 5991 enum Code { 5992 None = 0, 5993 5994 White, 5995 Red, 5996 Green, 5997 Blue, 5998 Cyan, 5999 Yellow, 6000 Grey, 6001 6002 Bright = 0x10, 6003 6004 BrightRed = Bright | Red, 6005 BrightGreen = Bright | Green, 6006 LightGrey = Bright | Grey, 6007 BrightWhite = Bright | White, 6008 BrightYellow = Bright | Yellow, 6009 6010 // By intention 6011 FileName = LightGrey, 6012 Warning = BrightYellow, 6013 ResultError = BrightRed, 6014 ResultSuccess = BrightGreen, 6015 ResultExpectedFailure = Warning, 6016 6017 Error = BrightRed, 6018 Success = Green, 6019 6020 OriginalExpression = Cyan, 6021 ReconstructedExpression = BrightYellow, 6022 6023 SecondaryText = LightGrey, 6024 Headers = White 6025 }; 6026 6027 // Use constructed object for RAII guard 6028 Colour( Code _colourCode ); 6029 Colour( Colour&& other ) noexcept; 6030 Colour& operator=( Colour&& other ) noexcept; 6031 ~Colour(); 6032 6033 // Use static method for one-shot changes 6034 static void use( Code _colourCode ); 6035 6036 private: 6037 bool m_moved = false; 6038 }; 6039 6040 std::ostream& operator << ( std::ostream& os, Colour const& ); 6041 6042 } // end namespace Catch 6043 6044 // end catch_console_colour.h 6045 // start catch_reporter_registrars.hpp 6046 6047 6048 namespace Catch { 6049 6050 template<typename T> 6051 class ReporterRegistrar { 6052 6053 class ReporterFactory : public IReporterFactory { 6054 6055 IStreamingReporterPtr create( ReporterConfig const& config ) const override { 6056 return std::unique_ptr<T>( new T( config ) ); 6057 } 6058 6059 std::string getDescription() const override { 6060 return T::getDescription(); 6061 } 6062 }; 6063 6064 public: 6065 6066 explicit ReporterRegistrar( std::string const& name ) { 6067 getMutableRegistryHub().registerReporter( name, std::make_shared<ReporterFactory>() ); 6068 } 6069 }; 6070 6071 template<typename T> 6072 class ListenerRegistrar { 6073 6074 class ListenerFactory : public IReporterFactory { 6075 6076 IStreamingReporterPtr create( ReporterConfig const& config ) const override { 6077 return std::unique_ptr<T>( new T( config ) ); 6078 } 6079 std::string getDescription() const override { 6080 return std::string(); 6081 } 6082 }; 6083 6084 public: 6085 6086 ListenerRegistrar() { 6087 getMutableRegistryHub().registerListener( std::make_shared<ListenerFactory>() ); 6088 } 6089 }; 6090 } 6091 6092 #if !defined(CATCH_CONFIG_DISABLE) 6093 6094 #define CATCH_REGISTER_REPORTER( name, reporterType ) \ 6095 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 6096 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 6097 namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); } \ 6098 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 6099 6100 #define CATCH_REGISTER_LISTENER( listenerType ) \ 6101 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 6102 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 6103 namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; } \ 6104 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 6105 #else // CATCH_CONFIG_DISABLE 6106 6107 #define CATCH_REGISTER_REPORTER(name, reporterType) 6108 #define CATCH_REGISTER_LISTENER(listenerType) 6109 6110 #endif // CATCH_CONFIG_DISABLE 6111 6112 // end catch_reporter_registrars.hpp 6113 // Allow users to base their work off existing reporters 6114 // start catch_reporter_compact.h 6115 6116 namespace Catch { 6117 6118 struct CompactReporter : StreamingReporterBase<CompactReporter> { 6119 6120 using StreamingReporterBase::StreamingReporterBase; 6121 6122 ~CompactReporter() override; 6123 6124 static std::string getDescription(); 6125 6126 void noMatchingTestCases(std::string const& spec) override; 6127 6128 void assertionStarting(AssertionInfo const&) override; 6129 6130 bool assertionEnded(AssertionStats const& _assertionStats) override; 6131 6132 void sectionEnded(SectionStats const& _sectionStats) override; 6133 6134 void testRunEnded(TestRunStats const& _testRunStats) override; 6135 6136 }; 6137 6138 } // end namespace Catch 6139 6140 // end catch_reporter_compact.h 6141 // start catch_reporter_console.h 6142 6143 #if defined(_MSC_VER) 6144 #pragma warning(push) 6145 #pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch 6146 // Note that 4062 (not all labels are handled 6147 // and default is missing) is enabled 6148 #endif 6149 6150 namespace Catch { 6151 // Fwd decls 6152 struct SummaryColumn; 6153 class TablePrinter; 6154 6155 struct ConsoleReporter : StreamingReporterBase<ConsoleReporter> { 6156 std::unique_ptr<TablePrinter> m_tablePrinter; 6157 6158 ConsoleReporter(ReporterConfig const& config); 6159 ~ConsoleReporter() override; 6160 static std::string getDescription(); 6161 6162 void noMatchingTestCases(std::string const& spec) override; 6163 6164 void reportInvalidArguments(std::string const&arg) override; 6165 6166 void assertionStarting(AssertionInfo const&) override; 6167 6168 bool assertionEnded(AssertionStats const& _assertionStats) override; 6169 6170 void sectionStarting(SectionInfo const& _sectionInfo) override; 6171 void sectionEnded(SectionStats const& _sectionStats) override; 6172 6173 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 6174 void benchmarkPreparing(std::string const& name) override; 6175 void benchmarkStarting(BenchmarkInfo const& info) override; 6176 void benchmarkEnded(BenchmarkStats<> const& stats) override; 6177 void benchmarkFailed(std::string const& error) override; 6178 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 6179 6180 void testCaseEnded(TestCaseStats const& _testCaseStats) override; 6181 void testGroupEnded(TestGroupStats const& _testGroupStats) override; 6182 void testRunEnded(TestRunStats const& _testRunStats) override; 6183 void testRunStarting(TestRunInfo const& _testRunInfo) override; 6184 private: 6185 6186 void lazyPrint(); 6187 6188 void lazyPrintWithoutClosingBenchmarkTable(); 6189 void lazyPrintRunInfo(); 6190 void lazyPrintGroupInfo(); 6191 void printTestCaseAndSectionHeader(); 6192 6193 void printClosedHeader(std::string const& _name); 6194 void printOpenHeader(std::string const& _name); 6195 6196 // if string has a : in first line will set indent to follow it on 6197 // subsequent lines 6198 void printHeaderString(std::string const& _string, std::size_t indent = 0); 6199 6200 void printTotals(Totals const& totals); 6201 void printSummaryRow(std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row); 6202 6203 void printTotalsDivider(Totals const& totals); 6204 void printSummaryDivider(); 6205 void printTestFilters(); 6206 6207 private: 6208 bool m_headerPrinted = false; 6209 }; 6210 6211 } // end namespace Catch 6212 6213 #if defined(_MSC_VER) 6214 #pragma warning(pop) 6215 #endif 6216 6217 // end catch_reporter_console.h 6218 // start catch_reporter_junit.h 6219 6220 // start catch_xmlwriter.h 6221 6222 #include <vector> 6223 6224 namespace Catch { 6225 enum class XmlFormatting { 6226 None = 0x00, 6227 Indent = 0x01, 6228 Newline = 0x02, 6229 }; 6230 6231 XmlFormatting operator | (XmlFormatting lhs, XmlFormatting rhs); 6232 XmlFormatting operator & (XmlFormatting lhs, XmlFormatting rhs); 6233 6234 class XmlEncode { 6235 public: 6236 enum ForWhat { ForTextNodes, ForAttributes }; 6237 6238 XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes ); 6239 6240 void encodeTo( std::ostream& os ) const; 6241 6242 friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ); 6243 6244 private: 6245 std::string m_str; 6246 ForWhat m_forWhat; 6247 }; 6248 6249 class XmlWriter { 6250 public: 6251 6252 class ScopedElement { 6253 public: 6254 ScopedElement( XmlWriter* writer, XmlFormatting fmt ); 6255 6256 ScopedElement( ScopedElement&& other ) noexcept; 6257 ScopedElement& operator=( ScopedElement&& other ) noexcept; 6258 6259 ~ScopedElement(); 6260 6261 ScopedElement& writeText( std::string const& text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent ); 6262 6263 template<typename T> 6264 ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { 6265 m_writer->writeAttribute( name, attribute ); 6266 return *this; 6267 } 6268 6269 private: 6270 mutable XmlWriter* m_writer = nullptr; 6271 XmlFormatting m_fmt; 6272 }; 6273 6274 XmlWriter( std::ostream& os = Catch::cout() ); 6275 ~XmlWriter(); 6276 6277 XmlWriter( XmlWriter const& ) = delete; 6278 XmlWriter& operator=( XmlWriter const& ) = delete; 6279 6280 XmlWriter& startElement( std::string const& name, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); 6281 6282 ScopedElement scopedElement( std::string const& name, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); 6283 6284 XmlWriter& endElement(XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); 6285 6286 XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ); 6287 6288 XmlWriter& writeAttribute( std::string const& name, bool attribute ); 6289 6290 template<typename T> 6291 XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { 6292 ReusableStringStream rss; 6293 rss << attribute; 6294 return writeAttribute( name, rss.str() ); 6295 } 6296 6297 XmlWriter& writeText( std::string const& text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); 6298 6299 XmlWriter& writeComment(std::string const& text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); 6300 6301 void writeStylesheetRef( std::string const& url ); 6302 6303 XmlWriter& writeBlankLine(); 6304 6305 void ensureTagClosed(); 6306 6307 private: 6308 6309 void applyFormatting(XmlFormatting fmt); 6310 6311 void writeDeclaration(); 6312 6313 void newlineIfNecessary(); 6314 6315 bool m_tagIsOpen = false; 6316 bool m_needsNewline = false; 6317 std::vector<std::string> m_tags; 6318 std::string m_indent; 6319 std::ostream& m_os; 6320 }; 6321 6322 } 6323 6324 // end catch_xmlwriter.h 6325 namespace Catch { 6326 6327 class JunitReporter : public CumulativeReporterBase<JunitReporter> { 6328 public: 6329 JunitReporter(ReporterConfig const& _config); 6330 6331 ~JunitReporter() override; 6332 6333 static std::string getDescription(); 6334 6335 void noMatchingTestCases(std::string const& /*spec*/) override; 6336 6337 void testRunStarting(TestRunInfo const& runInfo) override; 6338 6339 void testGroupStarting(GroupInfo const& groupInfo) override; 6340 6341 void testCaseStarting(TestCaseInfo const& testCaseInfo) override; 6342 bool assertionEnded(AssertionStats const& assertionStats) override; 6343 6344 void testCaseEnded(TestCaseStats const& testCaseStats) override; 6345 6346 void testGroupEnded(TestGroupStats const& testGroupStats) override; 6347 6348 void testRunEndedCumulative() override; 6349 6350 void writeGroup(TestGroupNode const& groupNode, double suiteTime); 6351 6352 void writeTestCase(TestCaseNode const& testCaseNode); 6353 6354 void writeSection( std::string const& className, 6355 std::string const& rootName, 6356 SectionNode const& sectionNode, 6357 bool testOkToFail ); 6358 6359 void writeAssertions(SectionNode const& sectionNode); 6360 void writeAssertion(AssertionStats const& stats); 6361 6362 XmlWriter xml; 6363 Timer suiteTimer; 6364 std::string stdOutForSuite; 6365 std::string stdErrForSuite; 6366 unsigned int unexpectedExceptions = 0; 6367 bool m_okToFail = false; 6368 }; 6369 6370 } // end namespace Catch 6371 6372 // end catch_reporter_junit.h 6373 // start catch_reporter_xml.h 6374 6375 namespace Catch { 6376 class XmlReporter : public StreamingReporterBase<XmlReporter> { 6377 public: 6378 XmlReporter(ReporterConfig const& _config); 6379 6380 ~XmlReporter() override; 6381 6382 static std::string getDescription(); 6383 6384 virtual std::string getStylesheetRef() const; 6385 6386 void writeSourceInfo(SourceLineInfo const& sourceInfo); 6387 6388 public: // StreamingReporterBase 6389 6390 void noMatchingTestCases(std::string const& s) override; 6391 6392 void testRunStarting(TestRunInfo const& testInfo) override; 6393 6394 void testGroupStarting(GroupInfo const& groupInfo) override; 6395 6396 void testCaseStarting(TestCaseInfo const& testInfo) override; 6397 6398 void sectionStarting(SectionInfo const& sectionInfo) override; 6399 6400 void assertionStarting(AssertionInfo const&) override; 6401 6402 bool assertionEnded(AssertionStats const& assertionStats) override; 6403 6404 void sectionEnded(SectionStats const& sectionStats) override; 6405 6406 void testCaseEnded(TestCaseStats const& testCaseStats) override; 6407 6408 void testGroupEnded(TestGroupStats const& testGroupStats) override; 6409 6410 void testRunEnded(TestRunStats const& testRunStats) override; 6411 6412 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 6413 void benchmarkPreparing(std::string const& name) override; 6414 void benchmarkStarting(BenchmarkInfo const&) override; 6415 void benchmarkEnded(BenchmarkStats<> const&) override; 6416 void benchmarkFailed(std::string const&) override; 6417 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 6418 6419 private: 6420 Timer m_testCaseTimer; 6421 XmlWriter m_xml; 6422 int m_sectionDepth = 0; 6423 }; 6424 6425 } // end namespace Catch 6426 6427 // end catch_reporter_xml.h 6428 6429 // end catch_external_interfaces.h 6430 #endif 6431 6432 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 6433 // start catch_benchmarking_all.hpp 6434 6435 // A proxy header that includes all of the benchmarking headers to allow 6436 // concise include of the benchmarking features. You should prefer the 6437 // individual includes in standard use. 6438 6439 // start catch_benchmark.hpp 6440 6441 // Benchmark 6442 6443 // start catch_chronometer.hpp 6444 6445 // User-facing chronometer 6446 6447 6448 // start catch_clock.hpp 6449 6450 // Clocks 6451 6452 6453 #include <chrono> 6454 #include <ratio> 6455 6456 namespace Catch { 6457 namespace Benchmark { 6458 template <typename Clock> 6459 using ClockDuration = typename Clock::duration; 6460 template <typename Clock> 6461 using FloatDuration = std::chrono::duration<double, typename Clock::period>; 6462 6463 template <typename Clock> 6464 using TimePoint = typename Clock::time_point; 6465 6466 using default_clock = std::chrono::steady_clock; 6467 6468 template <typename Clock> 6469 struct now { 6470 TimePoint<Clock> operator()() const { 6471 return Clock::now(); 6472 } 6473 }; 6474 6475 using fp_seconds = std::chrono::duration<double, std::ratio<1>>; 6476 } // namespace Benchmark 6477 } // namespace Catch 6478 6479 // end catch_clock.hpp 6480 // start catch_optimizer.hpp 6481 6482 // Hinting the optimizer 6483 6484 6485 #if defined(_MSC_VER) 6486 # include <atomic> // atomic_thread_fence 6487 #endif 6488 6489 namespace Catch { 6490 namespace Benchmark { 6491 #if defined(__GNUC__) || defined(__clang__) 6492 template <typename T> 6493 inline void keep_memory(T* p) { 6494 asm volatile("" : : "g"(p) : "memory"); 6495 } 6496 inline void keep_memory() { 6497 asm volatile("" : : : "memory"); 6498 } 6499 6500 namespace Detail { 6501 inline void optimizer_barrier() { keep_memory(); } 6502 } // namespace Detail 6503 #elif defined(_MSC_VER) 6504 6505 #pragma optimize("", off) 6506 template <typename T> 6507 inline void keep_memory(T* p) { 6508 // thanks @milleniumbug 6509 *reinterpret_cast<char volatile*>(p) = *reinterpret_cast<char const volatile*>(p); 6510 } 6511 // TODO equivalent keep_memory() 6512 #pragma optimize("", on) 6513 6514 namespace Detail { 6515 inline void optimizer_barrier() { 6516 std::atomic_thread_fence(std::memory_order_seq_cst); 6517 } 6518 } // namespace Detail 6519 6520 #endif 6521 6522 template <typename T> 6523 inline void deoptimize_value(T&& x) { 6524 keep_memory(&x); 6525 } 6526 6527 template <typename Fn, typename... Args> 6528 inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> typename std::enable_if<!std::is_same<void, decltype(fn(args...))>::value>::type { 6529 deoptimize_value(std::forward<Fn>(fn) (std::forward<Args...>(args...))); 6530 } 6531 6532 template <typename Fn, typename... Args> 6533 inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> typename std::enable_if<std::is_same<void, decltype(fn(args...))>::value>::type { 6534 std::forward<Fn>(fn) (std::forward<Args...>(args...)); 6535 } 6536 } // namespace Benchmark 6537 } // namespace Catch 6538 6539 // end catch_optimizer.hpp 6540 // start catch_complete_invoke.hpp 6541 6542 // Invoke with a special case for void 6543 6544 6545 #include <type_traits> 6546 #include <utility> 6547 6548 namespace Catch { 6549 namespace Benchmark { 6550 namespace Detail { 6551 template <typename T> 6552 struct CompleteType { using type = T; }; 6553 template <> 6554 struct CompleteType<void> { struct type {}; }; 6555 6556 template <typename T> 6557 using CompleteType_t = typename CompleteType<T>::type; 6558 6559 template <typename Result> 6560 struct CompleteInvoker { 6561 template <typename Fun, typename... Args> 6562 static Result invoke(Fun&& fun, Args&&... args) { 6563 return std::forward<Fun>(fun)(std::forward<Args>(args)...); 6564 } 6565 }; 6566 template <> 6567 struct CompleteInvoker<void> { 6568 template <typename Fun, typename... Args> 6569 static CompleteType_t<void> invoke(Fun&& fun, Args&&... args) { 6570 std::forward<Fun>(fun)(std::forward<Args>(args)...); 6571 return {}; 6572 } 6573 }; 6574 6575 // invoke and not return void :( 6576 template <typename Fun, typename... Args> 6577 CompleteType_t<FunctionReturnType<Fun, Args...>> complete_invoke(Fun&& fun, Args&&... args) { 6578 return CompleteInvoker<FunctionReturnType<Fun, Args...>>::invoke(std::forward<Fun>(fun), std::forward<Args>(args)...); 6579 } 6580 6581 const std::string benchmarkErrorMsg = "a benchmark failed to run successfully"; 6582 } // namespace Detail 6583 6584 template <typename Fun> 6585 Detail::CompleteType_t<FunctionReturnType<Fun>> user_code(Fun&& fun) { 6586 CATCH_TRY{ 6587 return Detail::complete_invoke(std::forward<Fun>(fun)); 6588 } CATCH_CATCH_ALL{ 6589 getResultCapture().benchmarkFailed(translateActiveException()); 6590 CATCH_RUNTIME_ERROR(Detail::benchmarkErrorMsg); 6591 } 6592 } 6593 } // namespace Benchmark 6594 } // namespace Catch 6595 6596 // end catch_complete_invoke.hpp 6597 namespace Catch { 6598 namespace Benchmark { 6599 namespace Detail { 6600 struct ChronometerConcept { 6601 virtual void start() = 0; 6602 virtual void finish() = 0; 6603 virtual ~ChronometerConcept() = default; 6604 }; 6605 template <typename Clock> 6606 struct ChronometerModel final : public ChronometerConcept { 6607 void start() override { started = Clock::now(); } 6608 void finish() override { finished = Clock::now(); } 6609 6610 ClockDuration<Clock> elapsed() const { return finished - started; } 6611 6612 TimePoint<Clock> started; 6613 TimePoint<Clock> finished; 6614 }; 6615 } // namespace Detail 6616 6617 struct Chronometer { 6618 public: 6619 template <typename Fun> 6620 void measure(Fun&& fun) { measure(std::forward<Fun>(fun), is_callable<Fun(int)>()); } 6621 6622 int runs() const { return k; } 6623 6624 Chronometer(Detail::ChronometerConcept& meter, int k) 6625 : impl(&meter) 6626 , k(k) {} 6627 6628 private: 6629 template <typename Fun> 6630 void measure(Fun&& fun, std::false_type) { 6631 measure([&fun](int) { return fun(); }, std::true_type()); 6632 } 6633 6634 template <typename Fun> 6635 void measure(Fun&& fun, std::true_type) { 6636 Detail::optimizer_barrier(); 6637 impl->start(); 6638 for (int i = 0; i < k; ++i) invoke_deoptimized(fun, i); 6639 impl->finish(); 6640 Detail::optimizer_barrier(); 6641 } 6642 6643 Detail::ChronometerConcept* impl; 6644 int k; 6645 }; 6646 } // namespace Benchmark 6647 } // namespace Catch 6648 6649 // end catch_chronometer.hpp 6650 // start catch_environment.hpp 6651 6652 // Environment information 6653 6654 6655 namespace Catch { 6656 namespace Benchmark { 6657 template <typename Duration> 6658 struct EnvironmentEstimate { 6659 Duration mean; 6660 OutlierClassification outliers; 6661 6662 template <typename Duration2> 6663 operator EnvironmentEstimate<Duration2>() const { 6664 return { mean, outliers }; 6665 } 6666 }; 6667 template <typename Clock> 6668 struct Environment { 6669 using clock_type = Clock; 6670 EnvironmentEstimate<FloatDuration<Clock>> clock_resolution; 6671 EnvironmentEstimate<FloatDuration<Clock>> clock_cost; 6672 }; 6673 } // namespace Benchmark 6674 } // namespace Catch 6675 6676 // end catch_environment.hpp 6677 // start catch_execution_plan.hpp 6678 6679 // Execution plan 6680 6681 6682 // start catch_benchmark_function.hpp 6683 6684 // Dumb std::function implementation for consistent call overhead 6685 6686 6687 #include <cassert> 6688 #include <type_traits> 6689 #include <utility> 6690 #include <memory> 6691 6692 namespace Catch { 6693 namespace Benchmark { 6694 namespace Detail { 6695 template <typename T> 6696 using Decay = typename std::decay<T>::type; 6697 template <typename T, typename U> 6698 struct is_related 6699 : std::is_same<Decay<T>, Decay<U>> {}; 6700 6701 /// We need to reinvent std::function because every piece of code that might add overhead 6702 /// in a measurement context needs to have consistent performance characteristics so that we 6703 /// can account for it in the measurement. 6704 /// Implementations of std::function with optimizations that aren't always applicable, like 6705 /// small buffer optimizations, are not uncommon. 6706 /// This is effectively an implementation of std::function without any such optimizations; 6707 /// it may be slow, but it is consistently slow. 6708 struct BenchmarkFunction { 6709 private: 6710 struct callable { 6711 virtual void call(Chronometer meter) const = 0; 6712 virtual callable* clone() const = 0; 6713 virtual ~callable() = default; 6714 }; 6715 template <typename Fun> 6716 struct model : public callable { 6717 model(Fun&& fun) : fun(std::move(fun)) {} 6718 model(Fun const& fun) : fun(fun) {} 6719 6720 model<Fun>* clone() const override { return new model<Fun>(*this); } 6721 6722 void call(Chronometer meter) const override { 6723 call(meter, is_callable<Fun(Chronometer)>()); 6724 } 6725 void call(Chronometer meter, std::true_type) const { 6726 fun(meter); 6727 } 6728 void call(Chronometer meter, std::false_type) const { 6729 meter.measure(fun); 6730 } 6731 6732 Fun fun; 6733 }; 6734 6735 struct do_nothing { void operator()() const {} }; 6736 6737 template <typename T> 6738 BenchmarkFunction(model<T>* c) : f(c) {} 6739 6740 public: 6741 BenchmarkFunction() 6742 : f(new model<do_nothing>{ {} }) {} 6743 6744 template <typename Fun, 6745 typename std::enable_if<!is_related<Fun, BenchmarkFunction>::value, int>::type = 0> 6746 BenchmarkFunction(Fun&& fun) 6747 : f(new model<typename std::decay<Fun>::type>(std::forward<Fun>(fun))) {} 6748 6749 BenchmarkFunction(BenchmarkFunction&& that) 6750 : f(std::move(that.f)) {} 6751 6752 BenchmarkFunction(BenchmarkFunction const& that) 6753 : f(that.f->clone()) {} 6754 6755 BenchmarkFunction& operator=(BenchmarkFunction&& that) { 6756 f = std::move(that.f); 6757 return *this; 6758 } 6759 6760 BenchmarkFunction& operator=(BenchmarkFunction const& that) { 6761 f.reset(that.f->clone()); 6762 return *this; 6763 } 6764 6765 void operator()(Chronometer meter) const { f->call(meter); } 6766 6767 private: 6768 std::unique_ptr<callable> f; 6769 }; 6770 } // namespace Detail 6771 } // namespace Benchmark 6772 } // namespace Catch 6773 6774 // end catch_benchmark_function.hpp 6775 // start catch_repeat.hpp 6776 6777 // repeat algorithm 6778 6779 6780 #include <type_traits> 6781 #include <utility> 6782 6783 namespace Catch { 6784 namespace Benchmark { 6785 namespace Detail { 6786 template <typename Fun> 6787 struct repeater { 6788 void operator()(int k) const { 6789 for (int i = 0; i < k; ++i) { 6790 fun(); 6791 } 6792 } 6793 Fun fun; 6794 }; 6795 template <typename Fun> 6796 repeater<typename std::decay<Fun>::type> repeat(Fun&& fun) { 6797 return { std::forward<Fun>(fun) }; 6798 } 6799 } // namespace Detail 6800 } // namespace Benchmark 6801 } // namespace Catch 6802 6803 // end catch_repeat.hpp 6804 // start catch_run_for_at_least.hpp 6805 6806 // Run a function for a minimum amount of time 6807 6808 6809 // start catch_measure.hpp 6810 6811 // Measure 6812 6813 6814 // start catch_timing.hpp 6815 6816 // Timing 6817 6818 6819 #include <tuple> 6820 #include <type_traits> 6821 6822 namespace Catch { 6823 namespace Benchmark { 6824 template <typename Duration, typename Result> 6825 struct Timing { 6826 Duration elapsed; 6827 Result result; 6828 int iterations; 6829 }; 6830 template <typename Clock, typename Func, typename... Args> 6831 using TimingOf = Timing<ClockDuration<Clock>, Detail::CompleteType_t<FunctionReturnType<Func, Args...>>>; 6832 } // namespace Benchmark 6833 } // namespace Catch 6834 6835 // end catch_timing.hpp 6836 #include <utility> 6837 6838 namespace Catch { 6839 namespace Benchmark { 6840 namespace Detail { 6841 template <typename Clock, typename Fun, typename... Args> 6842 TimingOf<Clock, Fun, Args...> measure(Fun&& fun, Args&&... args) { 6843 auto start = Clock::now(); 6844 auto&& r = Detail::complete_invoke(fun, std::forward<Args>(args)...); 6845 auto end = Clock::now(); 6846 auto delta = end - start; 6847 return { delta, std::forward<decltype(r)>(r), 1 }; 6848 } 6849 } // namespace Detail 6850 } // namespace Benchmark 6851 } // namespace Catch 6852 6853 // end catch_measure.hpp 6854 #include <utility> 6855 #include <type_traits> 6856 6857 namespace Catch { 6858 namespace Benchmark { 6859 namespace Detail { 6860 template <typename Clock, typename Fun> 6861 TimingOf<Clock, Fun, int> measure_one(Fun&& fun, int iters, std::false_type) { 6862 return Detail::measure<Clock>(fun, iters); 6863 } 6864 template <typename Clock, typename Fun> 6865 TimingOf<Clock, Fun, Chronometer> measure_one(Fun&& fun, int iters, std::true_type) { 6866 Detail::ChronometerModel<Clock> meter; 6867 auto&& result = Detail::complete_invoke(fun, Chronometer(meter, iters)); 6868 6869 return { meter.elapsed(), std::move(result), iters }; 6870 } 6871 6872 template <typename Clock, typename Fun> 6873 using run_for_at_least_argument_t = typename std::conditional<is_callable<Fun(Chronometer)>::value, Chronometer, int>::type; 6874 6875 struct optimized_away_error : std::exception { 6876 const char* what() const noexcept override { 6877 return "could not measure benchmark, maybe it was optimized away"; 6878 } 6879 }; 6880 6881 template <typename Clock, typename Fun> 6882 TimingOf<Clock, Fun, run_for_at_least_argument_t<Clock, Fun>> run_for_at_least(ClockDuration<Clock> how_long, int seed, Fun&& fun) { 6883 auto iters = seed; 6884 while (iters < (1 << 30)) { 6885 auto&& Timing = measure_one<Clock>(fun, iters, is_callable<Fun(Chronometer)>()); 6886 6887 if (Timing.elapsed >= how_long) { 6888 return { Timing.elapsed, std::move(Timing.result), iters }; 6889 } 6890 iters *= 2; 6891 } 6892 Catch::throw_exception(optimized_away_error{}); 6893 } 6894 } // namespace Detail 6895 } // namespace Benchmark 6896 } // namespace Catch 6897 6898 // end catch_run_for_at_least.hpp 6899 #include <algorithm> 6900 #include <iterator> 6901 6902 namespace Catch { 6903 namespace Benchmark { 6904 template <typename Duration> 6905 struct ExecutionPlan { 6906 int iterations_per_sample; 6907 Duration estimated_duration; 6908 Detail::BenchmarkFunction benchmark; 6909 Duration warmup_time; 6910 int warmup_iterations; 6911 6912 template <typename Duration2> 6913 operator ExecutionPlan<Duration2>() const { 6914 return { iterations_per_sample, estimated_duration, benchmark, warmup_time, warmup_iterations }; 6915 } 6916 6917 template <typename Clock> 6918 std::vector<FloatDuration<Clock>> run(const IConfig &cfg, Environment<FloatDuration<Clock>> env) const { 6919 // warmup a bit 6920 Detail::run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(warmup_time), warmup_iterations, Detail::repeat(now<Clock>{})); 6921 6922 std::vector<FloatDuration<Clock>> times; 6923 times.reserve(cfg.benchmarkSamples()); 6924 std::generate_n(std::back_inserter(times), cfg.benchmarkSamples(), [this, env] { 6925 Detail::ChronometerModel<Clock> model; 6926 this->benchmark(Chronometer(model, iterations_per_sample)); 6927 auto sample_time = model.elapsed() - env.clock_cost.mean; 6928 if (sample_time < FloatDuration<Clock>::zero()) sample_time = FloatDuration<Clock>::zero(); 6929 return sample_time / iterations_per_sample; 6930 }); 6931 return times; 6932 } 6933 }; 6934 } // namespace Benchmark 6935 } // namespace Catch 6936 6937 // end catch_execution_plan.hpp 6938 // start catch_estimate_clock.hpp 6939 6940 // Environment measurement 6941 6942 6943 // start catch_stats.hpp 6944 6945 // Statistical analysis tools 6946 6947 6948 #include <algorithm> 6949 #include <functional> 6950 #include <vector> 6951 #include <iterator> 6952 #include <numeric> 6953 #include <tuple> 6954 #include <cmath> 6955 #include <utility> 6956 #include <cstddef> 6957 #include <random> 6958 6959 namespace Catch { 6960 namespace Benchmark { 6961 namespace Detail { 6962 using sample = std::vector<double>; 6963 6964 double weighted_average_quantile(int k, int q, std::vector<double>::iterator first, std::vector<double>::iterator last); 6965 6966 template <typename Iterator> 6967 OutlierClassification classify_outliers(Iterator first, Iterator last) { 6968 std::vector<double> copy(first, last); 6969 6970 auto q1 = weighted_average_quantile(1, 4, copy.begin(), copy.end()); 6971 auto q3 = weighted_average_quantile(3, 4, copy.begin(), copy.end()); 6972 auto iqr = q3 - q1; 6973 auto los = q1 - (iqr * 3.); 6974 auto lom = q1 - (iqr * 1.5); 6975 auto him = q3 + (iqr * 1.5); 6976 auto his = q3 + (iqr * 3.); 6977 6978 OutlierClassification o; 6979 for (; first != last; ++first) { 6980 auto&& t = *first; 6981 if (t < los) ++o.low_severe; 6982 else if (t < lom) ++o.low_mild; 6983 else if (t > his) ++o.high_severe; 6984 else if (t > him) ++o.high_mild; 6985 ++o.samples_seen; 6986 } 6987 return o; 6988 } 6989 6990 template <typename Iterator> 6991 double mean(Iterator first, Iterator last) { 6992 auto count = last - first; 6993 double sum = std::accumulate(first, last, 0.); 6994 return sum / count; 6995 } 6996 6997 template <typename URng, typename Iterator, typename Estimator> 6998 sample resample(URng& rng, int resamples, Iterator first, Iterator last, Estimator& estimator) { 6999 auto n = last - first; 7000 std::uniform_int_distribution<decltype(n)> dist(0, n - 1); 7001 7002 sample out; 7003 out.reserve(resamples); 7004 std::generate_n(std::back_inserter(out), resamples, [n, first, &estimator, &dist, &rng] { 7005 std::vector<double> resampled; 7006 resampled.reserve(n); 7007 std::generate_n(std::back_inserter(resampled), n, [first, &dist, &rng] { return first[dist(rng)]; }); 7008 return estimator(resampled.begin(), resampled.end()); 7009 }); 7010 std::sort(out.begin(), out.end()); 7011 return out; 7012 } 7013 7014 template <typename Estimator, typename Iterator> 7015 sample jackknife(Estimator&& estimator, Iterator first, Iterator last) { 7016 auto n = last - first; 7017 auto second = std::next(first); 7018 sample results; 7019 results.reserve(n); 7020 7021 for (auto it = first; it != last; ++it) { 7022 std::iter_swap(it, first); 7023 results.push_back(estimator(second, last)); 7024 } 7025 7026 return results; 7027 } 7028 7029 inline double normal_cdf(double x) { 7030 return std::erfc(-x / std::sqrt(2.0)) / 2.0; 7031 } 7032 7033 double erfc_inv(double x); 7034 7035 double normal_quantile(double p); 7036 7037 template <typename Iterator, typename Estimator> 7038 Estimate<double> bootstrap(double confidence_level, Iterator first, Iterator last, sample const& resample, Estimator&& estimator) { 7039 auto n_samples = last - first; 7040 7041 double point = estimator(first, last); 7042 // Degenerate case with a single sample 7043 if (n_samples == 1) return { point, point, point, confidence_level }; 7044 7045 sample jack = jackknife(estimator, first, last); 7046 double jack_mean = mean(jack.begin(), jack.end()); 7047 double sum_squares, sum_cubes; 7048 std::tie(sum_squares, sum_cubes) = std::accumulate(jack.begin(), jack.end(), std::make_pair(0., 0.), [jack_mean](std::pair<double, double> sqcb, double x) -> std::pair<double, double> { 7049 auto d = jack_mean - x; 7050 auto d2 = d * d; 7051 auto d3 = d2 * d; 7052 return { sqcb.first + d2, sqcb.second + d3 }; 7053 }); 7054 7055 double accel = sum_cubes / (6 * std::pow(sum_squares, 1.5)); 7056 int n = static_cast<int>(resample.size()); 7057 double prob_n = std::count_if(resample.begin(), resample.end(), [point](double x) { return x < point; }) / (double)n; 7058 // degenerate case with uniform samples 7059 if (prob_n == 0) return { point, point, point, confidence_level }; 7060 7061 double bias = normal_quantile(prob_n); 7062 double z1 = normal_quantile((1. - confidence_level) / 2.); 7063 7064 auto cumn = [n](double x) -> int { 7065 return std::lround(normal_cdf(x) * n); }; 7066 auto a = [bias, accel](double b) { return bias + b / (1. - accel * b); }; 7067 double b1 = bias + z1; 7068 double b2 = bias - z1; 7069 double a1 = a(b1); 7070 double a2 = a(b2); 7071 auto lo = (std::max)(cumn(a1), 0); 7072 auto hi = (std::min)(cumn(a2), n - 1); 7073 7074 return { point, resample[lo], resample[hi], confidence_level }; 7075 } 7076 7077 double outlier_variance(Estimate<double> mean, Estimate<double> stddev, int n); 7078 7079 struct bootstrap_analysis { 7080 Estimate<double> mean; 7081 Estimate<double> standard_deviation; 7082 double outlier_variance; 7083 }; 7084 7085 bootstrap_analysis analyse_samples(double confidence_level, int n_resamples, std::vector<double>::iterator first, std::vector<double>::iterator last); 7086 } // namespace Detail 7087 } // namespace Benchmark 7088 } // namespace Catch 7089 7090 // end catch_stats.hpp 7091 #include <algorithm> 7092 #include <iterator> 7093 #include <tuple> 7094 #include <vector> 7095 #include <cmath> 7096 7097 namespace Catch { 7098 namespace Benchmark { 7099 namespace Detail { 7100 template <typename Clock> 7101 std::vector<double> resolution(int k) { 7102 std::vector<TimePoint<Clock>> times; 7103 times.reserve(k + 1); 7104 std::generate_n(std::back_inserter(times), k + 1, now<Clock>{}); 7105 7106 std::vector<double> deltas; 7107 deltas.reserve(k); 7108 std::transform(std::next(times.begin()), times.end(), times.begin(), 7109 std::back_inserter(deltas), 7110 [](TimePoint<Clock> a, TimePoint<Clock> b) { return static_cast<double>((a - b).count()); }); 7111 7112 return deltas; 7113 } 7114 7115 const auto warmup_iterations = 10000; 7116 const auto warmup_time = std::chrono::milliseconds(100); 7117 const auto minimum_ticks = 1000; 7118 const auto warmup_seed = 10000; 7119 const auto clock_resolution_estimation_time = std::chrono::milliseconds(500); 7120 const auto clock_cost_estimation_time_limit = std::chrono::seconds(1); 7121 const auto clock_cost_estimation_tick_limit = 100000; 7122 const auto clock_cost_estimation_time = std::chrono::milliseconds(10); 7123 const auto clock_cost_estimation_iterations = 10000; 7124 7125 template <typename Clock> 7126 int warmup() { 7127 return run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(warmup_time), warmup_seed, &resolution<Clock>) 7128 .iterations; 7129 } 7130 template <typename Clock> 7131 EnvironmentEstimate<FloatDuration<Clock>> estimate_clock_resolution(int iterations) { 7132 auto r = run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(clock_resolution_estimation_time), iterations, &resolution<Clock>) 7133 .result; 7134 return { 7135 FloatDuration<Clock>(mean(r.begin(), r.end())), 7136 classify_outliers(r.begin(), r.end()), 7137 }; 7138 } 7139 template <typename Clock> 7140 EnvironmentEstimate<FloatDuration<Clock>> estimate_clock_cost(FloatDuration<Clock> resolution) { 7141 auto time_limit = (std::min)( 7142 resolution * clock_cost_estimation_tick_limit, 7143 FloatDuration<Clock>(clock_cost_estimation_time_limit)); 7144 auto time_clock = [](int k) { 7145 return Detail::measure<Clock>([k] { 7146 for (int i = 0; i < k; ++i) { 7147 volatile auto ignored = Clock::now(); 7148 (void)ignored; 7149 } 7150 }).elapsed; 7151 }; 7152 time_clock(1); 7153 int iters = clock_cost_estimation_iterations; 7154 auto&& r = run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(clock_cost_estimation_time), iters, time_clock); 7155 std::vector<double> times; 7156 int nsamples = static_cast<int>(std::ceil(time_limit / r.elapsed)); 7157 times.reserve(nsamples); 7158 std::generate_n(std::back_inserter(times), nsamples, [time_clock, &r] { 7159 return static_cast<double>((time_clock(r.iterations) / r.iterations).count()); 7160 }); 7161 return { 7162 FloatDuration<Clock>(mean(times.begin(), times.end())), 7163 classify_outliers(times.begin(), times.end()), 7164 }; 7165 } 7166 7167 template <typename Clock> 7168 Environment<FloatDuration<Clock>> measure_environment() { 7169 static Environment<FloatDuration<Clock>>* env = nullptr; 7170 if (env) { 7171 return *env; 7172 } 7173 7174 auto iters = Detail::warmup<Clock>(); 7175 auto resolution = Detail::estimate_clock_resolution<Clock>(iters); 7176 auto cost = Detail::estimate_clock_cost<Clock>(resolution.mean); 7177 7178 env = new Environment<FloatDuration<Clock>>{ resolution, cost }; 7179 return *env; 7180 } 7181 } // namespace Detail 7182 } // namespace Benchmark 7183 } // namespace Catch 7184 7185 // end catch_estimate_clock.hpp 7186 // start catch_analyse.hpp 7187 7188 // Run and analyse one benchmark 7189 7190 7191 // start catch_sample_analysis.hpp 7192 7193 // Benchmark results 7194 7195 7196 #include <algorithm> 7197 #include <vector> 7198 #include <string> 7199 #include <iterator> 7200 7201 namespace Catch { 7202 namespace Benchmark { 7203 template <typename Duration> 7204 struct SampleAnalysis { 7205 std::vector<Duration> samples; 7206 Estimate<Duration> mean; 7207 Estimate<Duration> standard_deviation; 7208 OutlierClassification outliers; 7209 double outlier_variance; 7210 7211 template <typename Duration2> 7212 operator SampleAnalysis<Duration2>() const { 7213 std::vector<Duration2> samples2; 7214 samples2.reserve(samples.size()); 7215 std::transform(samples.begin(), samples.end(), std::back_inserter(samples2), [](Duration d) { return Duration2(d); }); 7216 return { 7217 std::move(samples2), 7218 mean, 7219 standard_deviation, 7220 outliers, 7221 outlier_variance, 7222 }; 7223 } 7224 }; 7225 } // namespace Benchmark 7226 } // namespace Catch 7227 7228 // end catch_sample_analysis.hpp 7229 #include <algorithm> 7230 #include <iterator> 7231 #include <vector> 7232 7233 namespace Catch { 7234 namespace Benchmark { 7235 namespace Detail { 7236 template <typename Duration, typename Iterator> 7237 SampleAnalysis<Duration> analyse(const IConfig &cfg, Environment<Duration>, Iterator first, Iterator last) { 7238 if (!cfg.benchmarkNoAnalysis()) { 7239 std::vector<double> samples; 7240 samples.reserve(last - first); 7241 std::transform(first, last, std::back_inserter(samples), [](Duration d) { return d.count(); }); 7242 7243 auto analysis = Catch::Benchmark::Detail::analyse_samples(cfg.benchmarkConfidenceInterval(), cfg.benchmarkResamples(), samples.begin(), samples.end()); 7244 auto outliers = Catch::Benchmark::Detail::classify_outliers(samples.begin(), samples.end()); 7245 7246 auto wrap_estimate = [](Estimate<double> e) { 7247 return Estimate<Duration> { 7248 Duration(e.point), 7249 Duration(e.lower_bound), 7250 Duration(e.upper_bound), 7251 e.confidence_interval, 7252 }; 7253 }; 7254 std::vector<Duration> samples2; 7255 samples2.reserve(samples.size()); 7256 std::transform(samples.begin(), samples.end(), std::back_inserter(samples2), [](double d) { return Duration(d); }); 7257 return { 7258 std::move(samples2), 7259 wrap_estimate(analysis.mean), 7260 wrap_estimate(analysis.standard_deviation), 7261 outliers, 7262 analysis.outlier_variance, 7263 }; 7264 } else { 7265 std::vector<Duration> samples; 7266 samples.reserve(last - first); 7267 7268 Duration mean = Duration(0); 7269 int i = 0; 7270 for (auto it = first; it < last; ++it, ++i) { 7271 samples.push_back(Duration(*it)); 7272 mean += Duration(*it); 7273 } 7274 mean /= i; 7275 7276 return { 7277 std::move(samples), 7278 Estimate<Duration>{mean, mean, mean, 0.0}, 7279 Estimate<Duration>{Duration(0), Duration(0), Duration(0), 0.0}, 7280 OutlierClassification{}, 7281 0.0 7282 }; 7283 } 7284 } 7285 } // namespace Detail 7286 } // namespace Benchmark 7287 } // namespace Catch 7288 7289 // end catch_analyse.hpp 7290 #include <algorithm> 7291 #include <functional> 7292 #include <string> 7293 #include <vector> 7294 #include <cmath> 7295 7296 namespace Catch { 7297 namespace Benchmark { 7298 struct Benchmark { 7299 Benchmark(std::string &&name) 7300 : name(std::move(name)) {} 7301 7302 template <class FUN> 7303 Benchmark(std::string &&name, FUN &&func) 7304 : fun(std::move(func)), name(std::move(name)) {} 7305 7306 template <typename Clock> 7307 ExecutionPlan<FloatDuration<Clock>> prepare(const IConfig &cfg, Environment<FloatDuration<Clock>> env) const { 7308 auto min_time = env.clock_resolution.mean * Detail::minimum_ticks; 7309 auto run_time = std::max(min_time, std::chrono::duration_cast<decltype(min_time)>(cfg.benchmarkWarmupTime())); 7310 auto&& test = Detail::run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(run_time), 1, fun); 7311 int new_iters = static_cast<int>(std::ceil(min_time * test.iterations / test.elapsed)); 7312 return { new_iters, test.elapsed / test.iterations * new_iters * cfg.benchmarkSamples(), fun, std::chrono::duration_cast<FloatDuration<Clock>>(cfg.benchmarkWarmupTime()), Detail::warmup_iterations }; 7313 } 7314 7315 template <typename Clock = default_clock> 7316 void run() { 7317 IConfigPtr cfg = getCurrentContext().getConfig(); 7318 7319 auto env = Detail::measure_environment<Clock>(); 7320 7321 getResultCapture().benchmarkPreparing(name); 7322 CATCH_TRY{ 7323 auto plan = user_code([&] { 7324 return prepare<Clock>(*cfg, env); 7325 }); 7326 7327 BenchmarkInfo info { 7328 name, 7329 plan.estimated_duration.count(), 7330 plan.iterations_per_sample, 7331 cfg->benchmarkSamples(), 7332 cfg->benchmarkResamples(), 7333 env.clock_resolution.mean.count(), 7334 env.clock_cost.mean.count() 7335 }; 7336 7337 getResultCapture().benchmarkStarting(info); 7338 7339 auto samples = user_code([&] { 7340 return plan.template run<Clock>(*cfg, env); 7341 }); 7342 7343 auto analysis = Detail::analyse(*cfg, env, samples.begin(), samples.end()); 7344 BenchmarkStats<FloatDuration<Clock>> stats{ info, analysis.samples, analysis.mean, analysis.standard_deviation, analysis.outliers, analysis.outlier_variance }; 7345 getResultCapture().benchmarkEnded(stats); 7346 7347 } CATCH_CATCH_ALL{ 7348 if (translateActiveException() != Detail::benchmarkErrorMsg) // benchmark errors have been reported, otherwise rethrow. 7349 std::rethrow_exception(std::current_exception()); 7350 } 7351 } 7352 7353 // sets lambda to be used in fun *and* executes benchmark! 7354 template <typename Fun, 7355 typename std::enable_if<!Detail::is_related<Fun, Benchmark>::value, int>::type = 0> 7356 Benchmark & operator=(Fun func) { 7357 fun = Detail::BenchmarkFunction(func); 7358 run(); 7359 return *this; 7360 } 7361 7362 explicit operator bool() { 7363 return true; 7364 } 7365 7366 private: 7367 Detail::BenchmarkFunction fun; 7368 std::string name; 7369 }; 7370 } 7371 } // namespace Catch 7372 7373 #define INTERNAL_CATCH_GET_1_ARG(arg1, arg2, ...) arg1 7374 #define INTERNAL_CATCH_GET_2_ARG(arg1, arg2, ...) arg2 7375 7376 #define INTERNAL_CATCH_BENCHMARK(BenchmarkName, name, benchmarkIndex)\ 7377 if( Catch::Benchmark::Benchmark BenchmarkName{name} ) \ 7378 BenchmarkName = [&](int benchmarkIndex) 7379 7380 #define INTERNAL_CATCH_BENCHMARK_ADVANCED(BenchmarkName, name)\ 7381 if( Catch::Benchmark::Benchmark BenchmarkName{name} ) \ 7382 BenchmarkName = [&] 7383 7384 // end catch_benchmark.hpp 7385 // start catch_constructor.hpp 7386 7387 // Constructor and destructor helpers 7388 7389 7390 #include <type_traits> 7391 7392 namespace Catch { 7393 namespace Benchmark { 7394 namespace Detail { 7395 template <typename T, bool Destruct> 7396 struct ObjectStorage 7397 { 7398 ObjectStorage() : data() {} 7399 7400 ObjectStorage(const ObjectStorage& other) 7401 { 7402 new(&data) T(other.stored_object()); 7403 } 7404 7405 ObjectStorage(ObjectStorage&& other) 7406 { 7407 new(&data) T(std::move(other.stored_object())); 7408 } 7409 7410 ~ObjectStorage() { destruct_on_exit<T>(); } 7411 7412 template <typename... Args> 7413 void construct(Args&&... args) 7414 { 7415 new (&data) T(std::forward<Args>(args)...); 7416 } 7417 7418 template <bool AllowManualDestruction = !Destruct> 7419 typename std::enable_if<AllowManualDestruction>::type destruct() 7420 { 7421 stored_object().~T(); 7422 } 7423 7424 private: 7425 // If this is a constructor benchmark, destruct the underlying object 7426 template <typename U> 7427 void destruct_on_exit(typename std::enable_if<Destruct, U>::type* = 0) { destruct<true>(); } 7428 // Otherwise, don't 7429 template <typename U> 7430 void destruct_on_exit(typename std::enable_if<!Destruct, U>::type* = 0) { } 7431 7432 T& stored_object() { 7433 return *static_cast<T*>(static_cast<void*>(&data)); 7434 } 7435 7436 T const& stored_object() const { 7437 return *static_cast<T*>(static_cast<void*>(&data)); 7438 } 7439 7440 struct { alignas(T) unsigned char data[sizeof(T)]; } data; 7441 }; 7442 } 7443 7444 template <typename T> 7445 using storage_for = Detail::ObjectStorage<T, true>; 7446 7447 template <typename T> 7448 using destructable_object = Detail::ObjectStorage<T, false>; 7449 } 7450 } 7451 7452 // end catch_constructor.hpp 7453 // end catch_benchmarking_all.hpp 7454 #endif 7455 7456 #endif // ! CATCH_CONFIG_IMPL_ONLY 7457 7458 #ifdef CATCH_IMPL 7459 // start catch_impl.hpp 7460 7461 #ifdef __clang__ 7462 #pragma clang diagnostic push 7463 #pragma clang diagnostic ignored "-Wweak-vtables" 7464 #endif 7465 7466 // Keep these here for external reporters 7467 // start catch_test_case_tracker.h 7468 7469 #include <string> 7470 #include <vector> 7471 #include <memory> 7472 7473 namespace Catch { 7474 namespace TestCaseTracking { 7475 7476 struct NameAndLocation { 7477 std::string name; 7478 SourceLineInfo location; 7479 7480 NameAndLocation( std::string const& _name, SourceLineInfo const& _location ); 7481 friend bool operator==(NameAndLocation const& lhs, NameAndLocation const& rhs) { 7482 return lhs.name == rhs.name 7483 && lhs.location == rhs.location; 7484 } 7485 }; 7486 7487 class ITracker; 7488 7489 using ITrackerPtr = std::shared_ptr<ITracker>; 7490 7491 class ITracker { 7492 NameAndLocation m_nameAndLocation; 7493 7494 public: 7495 ITracker(NameAndLocation const& nameAndLoc) : 7496 m_nameAndLocation(nameAndLoc) 7497 {} 7498 7499 // static queries 7500 NameAndLocation const& nameAndLocation() const { 7501 return m_nameAndLocation; 7502 } 7503 7504 virtual ~ITracker(); 7505 7506 // dynamic queries 7507 virtual bool isComplete() const = 0; // Successfully completed or failed 7508 virtual bool isSuccessfullyCompleted() const = 0; 7509 virtual bool isOpen() const = 0; // Started but not complete 7510 virtual bool hasChildren() const = 0; 7511 virtual bool hasStarted() const = 0; 7512 7513 virtual ITracker& parent() = 0; 7514 7515 // actions 7516 virtual void close() = 0; // Successfully complete 7517 virtual void fail() = 0; 7518 virtual void markAsNeedingAnotherRun() = 0; 7519 7520 virtual void addChild( ITrackerPtr const& child ) = 0; 7521 virtual ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) = 0; 7522 virtual void openChild() = 0; 7523 7524 // Debug/ checking 7525 virtual bool isSectionTracker() const = 0; 7526 virtual bool isGeneratorTracker() const = 0; 7527 }; 7528 7529 class TrackerContext { 7530 7531 enum RunState { 7532 NotStarted, 7533 Executing, 7534 CompletedCycle 7535 }; 7536 7537 ITrackerPtr m_rootTracker; 7538 ITracker* m_currentTracker = nullptr; 7539 RunState m_runState = NotStarted; 7540 7541 public: 7542 7543 ITracker& startRun(); 7544 void endRun(); 7545 7546 void startCycle(); 7547 void completeCycle(); 7548 7549 bool completedCycle() const; 7550 ITracker& currentTracker(); 7551 void setCurrentTracker( ITracker* tracker ); 7552 }; 7553 7554 class TrackerBase : public ITracker { 7555 protected: 7556 enum CycleState { 7557 NotStarted, 7558 Executing, 7559 ExecutingChildren, 7560 NeedsAnotherRun, 7561 CompletedSuccessfully, 7562 Failed 7563 }; 7564 7565 using Children = std::vector<ITrackerPtr>; 7566 TrackerContext& m_ctx; 7567 ITracker* m_parent; 7568 Children m_children; 7569 CycleState m_runState = NotStarted; 7570 7571 public: 7572 TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ); 7573 7574 bool isComplete() const override; 7575 bool isSuccessfullyCompleted() const override; 7576 bool isOpen() const override; 7577 bool hasChildren() const override; 7578 bool hasStarted() const override { 7579 return m_runState != NotStarted; 7580 } 7581 7582 void addChild( ITrackerPtr const& child ) override; 7583 7584 ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) override; 7585 ITracker& parent() override; 7586 7587 void openChild() override; 7588 7589 bool isSectionTracker() const override; 7590 bool isGeneratorTracker() const override; 7591 7592 void open(); 7593 7594 void close() override; 7595 void fail() override; 7596 void markAsNeedingAnotherRun() override; 7597 7598 private: 7599 void moveToParent(); 7600 void moveToThis(); 7601 }; 7602 7603 class SectionTracker : public TrackerBase { 7604 std::vector<std::string> m_filters; 7605 std::string m_trimmed_name; 7606 public: 7607 SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ); 7608 7609 bool isSectionTracker() const override; 7610 7611 bool isComplete() const override; 7612 7613 static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ); 7614 7615 void tryOpen(); 7616 7617 void addInitialFilters( std::vector<std::string> const& filters ); 7618 void addNextFilters( std::vector<std::string> const& filters ); 7619 //! Returns filters active in this tracker 7620 std::vector<std::string> const& getFilters() const; 7621 //! Returns whitespace-trimmed name of the tracked section 7622 std::string const& trimmedName() const; 7623 }; 7624 7625 } // namespace TestCaseTracking 7626 7627 using TestCaseTracking::ITracker; 7628 using TestCaseTracking::TrackerContext; 7629 using TestCaseTracking::SectionTracker; 7630 7631 } // namespace Catch 7632 7633 // end catch_test_case_tracker.h 7634 7635 // start catch_leak_detector.h 7636 7637 namespace Catch { 7638 7639 struct LeakDetector { 7640 LeakDetector(); 7641 ~LeakDetector(); 7642 }; 7643 7644 } 7645 // end catch_leak_detector.h 7646 // Cpp files will be included in the single-header file here 7647 // start catch_stats.cpp 7648 7649 // Statistical analysis tools 7650 7651 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 7652 7653 #include <cassert> 7654 #include <random> 7655 7656 #if defined(CATCH_CONFIG_USE_ASYNC) 7657 #include <future> 7658 #endif 7659 7660 namespace { 7661 double erf_inv(double x) { 7662 // Code accompanying the article "Approximating the erfinv function" in GPU Computing Gems, Volume 2 7663 double w, p; 7664 7665 w = -log((1.0 - x) * (1.0 + x)); 7666 7667 if (w < 6.250000) { 7668 w = w - 3.125000; 7669 p = -3.6444120640178196996e-21; 7670 p = -1.685059138182016589e-19 + p * w; 7671 p = 1.2858480715256400167e-18 + p * w; 7672 p = 1.115787767802518096e-17 + p * w; 7673 p = -1.333171662854620906e-16 + p * w; 7674 p = 2.0972767875968561637e-17 + p * w; 7675 p = 6.6376381343583238325e-15 + p * w; 7676 p = -4.0545662729752068639e-14 + p * w; 7677 p = -8.1519341976054721522e-14 + p * w; 7678 p = 2.6335093153082322977e-12 + p * w; 7679 p = -1.2975133253453532498e-11 + p * w; 7680 p = -5.4154120542946279317e-11 + p * w; 7681 p = 1.051212273321532285e-09 + p * w; 7682 p = -4.1126339803469836976e-09 + p * w; 7683 p = -2.9070369957882005086e-08 + p * w; 7684 p = 4.2347877827932403518e-07 + p * w; 7685 p = -1.3654692000834678645e-06 + p * w; 7686 p = -1.3882523362786468719e-05 + p * w; 7687 p = 0.0001867342080340571352 + p * w; 7688 p = -0.00074070253416626697512 + p * w; 7689 p = -0.0060336708714301490533 + p * w; 7690 p = 0.24015818242558961693 + p * w; 7691 p = 1.6536545626831027356 + p * w; 7692 } else if (w < 16.000000) { 7693 w = sqrt(w) - 3.250000; 7694 p = 2.2137376921775787049e-09; 7695 p = 9.0756561938885390979e-08 + p * w; 7696 p = -2.7517406297064545428e-07 + p * w; 7697 p = 1.8239629214389227755e-08 + p * w; 7698 p = 1.5027403968909827627e-06 + p * w; 7699 p = -4.013867526981545969e-06 + p * w; 7700 p = 2.9234449089955446044e-06 + p * w; 7701 p = 1.2475304481671778723e-05 + p * w; 7702 p = -4.7318229009055733981e-05 + p * w; 7703 p = 6.8284851459573175448e-05 + p * w; 7704 p = 2.4031110387097893999e-05 + p * w; 7705 p = -0.0003550375203628474796 + p * w; 7706 p = 0.00095328937973738049703 + p * w; 7707 p = -0.0016882755560235047313 + p * w; 7708 p = 0.0024914420961078508066 + p * w; 7709 p = -0.0037512085075692412107 + p * w; 7710 p = 0.005370914553590063617 + p * w; 7711 p = 1.0052589676941592334 + p * w; 7712 p = 3.0838856104922207635 + p * w; 7713 } else { 7714 w = sqrt(w) - 5.000000; 7715 p = -2.7109920616438573243e-11; 7716 p = -2.5556418169965252055e-10 + p * w; 7717 p = 1.5076572693500548083e-09 + p * w; 7718 p = -3.7894654401267369937e-09 + p * w; 7719 p = 7.6157012080783393804e-09 + p * w; 7720 p = -1.4960026627149240478e-08 + p * w; 7721 p = 2.9147953450901080826e-08 + p * w; 7722 p = -6.7711997758452339498e-08 + p * w; 7723 p = 2.2900482228026654717e-07 + p * w; 7724 p = -9.9298272942317002539e-07 + p * w; 7725 p = 4.5260625972231537039e-06 + p * w; 7726 p = -1.9681778105531670567e-05 + p * w; 7727 p = 7.5995277030017761139e-05 + p * w; 7728 p = -0.00021503011930044477347 + p * w; 7729 p = -0.00013871931833623122026 + p * w; 7730 p = 1.0103004648645343977 + p * w; 7731 p = 4.8499064014085844221 + p * w; 7732 } 7733 return p * x; 7734 } 7735 7736 double standard_deviation(std::vector<double>::iterator first, std::vector<double>::iterator last) { 7737 auto m = Catch::Benchmark::Detail::mean(first, last); 7738 double variance = std::accumulate(first, last, 0., [m](double a, double b) { 7739 double diff = b - m; 7740 return a + diff * diff; 7741 }) / (last - first); 7742 return std::sqrt(variance); 7743 } 7744 7745 } 7746 7747 namespace Catch { 7748 namespace Benchmark { 7749 namespace Detail { 7750 7751 double weighted_average_quantile(int k, int q, std::vector<double>::iterator first, std::vector<double>::iterator last) { 7752 auto count = last - first; 7753 double idx = (count - 1) * k / static_cast<double>(q); 7754 int j = static_cast<int>(idx); 7755 double g = idx - j; 7756 std::nth_element(first, first + j, last); 7757 auto xj = first[j]; 7758 if (g == 0) return xj; 7759 7760 auto xj1 = *std::min_element(first + (j + 1), last); 7761 return xj + g * (xj1 - xj); 7762 } 7763 7764 double erfc_inv(double x) { 7765 return erf_inv(1.0 - x); 7766 } 7767 7768 double normal_quantile(double p) { 7769 static const double ROOT_TWO = std::sqrt(2.0); 7770 7771 double result = 0.0; 7772 assert(p >= 0 && p <= 1); 7773 if (p < 0 || p > 1) { 7774 return result; 7775 } 7776 7777 result = -erfc_inv(2.0 * p); 7778 // result *= normal distribution standard deviation (1.0) * sqrt(2) 7779 result *= /*sd * */ ROOT_TWO; 7780 // result += normal disttribution mean (0) 7781 return result; 7782 } 7783 7784 double outlier_variance(Estimate<double> mean, Estimate<double> stddev, int n) { 7785 double sb = stddev.point; 7786 double mn = mean.point / n; 7787 double mg_min = mn / 2.; 7788 double sg = (std::min)(mg_min / 4., sb / std::sqrt(n)); 7789 double sg2 = sg * sg; 7790 double sb2 = sb * sb; 7791 7792 auto c_max = [n, mn, sb2, sg2](double x) -> double { 7793 double k = mn - x; 7794 double d = k * k; 7795 double nd = n * d; 7796 double k0 = -n * nd; 7797 double k1 = sb2 - n * sg2 + nd; 7798 double det = k1 * k1 - 4 * sg2 * k0; 7799 return (int)(-2. * k0 / (k1 + std::sqrt(det))); 7800 }; 7801 7802 auto var_out = [n, sb2, sg2](double c) { 7803 double nc = n - c; 7804 return (nc / n) * (sb2 - nc * sg2); 7805 }; 7806 7807 return (std::min)(var_out(1), var_out((std::min)(c_max(0.), c_max(mg_min)))) / sb2; 7808 } 7809 7810 bootstrap_analysis analyse_samples(double confidence_level, int n_resamples, std::vector<double>::iterator first, std::vector<double>::iterator last) { 7811 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION 7812 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS 7813 static std::random_device entropy; 7814 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 7815 7816 auto n = static_cast<int>(last - first); // seriously, one can't use integral types without hell in C++ 7817 7818 auto mean = &Detail::mean<std::vector<double>::iterator>; 7819 auto stddev = &standard_deviation; 7820 7821 #if defined(CATCH_CONFIG_USE_ASYNC) 7822 auto Estimate = [=](double(*f)(std::vector<double>::iterator, std::vector<double>::iterator)) { 7823 auto seed = entropy(); 7824 return std::async(std::launch::async, [=] { 7825 std::mt19937 rng(seed); 7826 auto resampled = resample(rng, n_resamples, first, last, f); 7827 return bootstrap(confidence_level, first, last, resampled, f); 7828 }); 7829 }; 7830 7831 auto mean_future = Estimate(mean); 7832 auto stddev_future = Estimate(stddev); 7833 7834 auto mean_estimate = mean_future.get(); 7835 auto stddev_estimate = stddev_future.get(); 7836 #else 7837 auto Estimate = [=](double(*f)(std::vector<double>::iterator, std::vector<double>::iterator)) { 7838 auto seed = entropy(); 7839 std::mt19937 rng(seed); 7840 auto resampled = resample(rng, n_resamples, first, last, f); 7841 return bootstrap(confidence_level, first, last, resampled, f); 7842 }; 7843 7844 auto mean_estimate = Estimate(mean); 7845 auto stddev_estimate = Estimate(stddev); 7846 #endif // CATCH_USE_ASYNC 7847 7848 double outlier_variance = Detail::outlier_variance(mean_estimate, stddev_estimate, n); 7849 7850 return { mean_estimate, stddev_estimate, outlier_variance }; 7851 } 7852 } // namespace Detail 7853 } // namespace Benchmark 7854 } // namespace Catch 7855 7856 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 7857 // end catch_stats.cpp 7858 // start catch_approx.cpp 7859 7860 #include <cmath> 7861 #include <limits> 7862 7863 namespace { 7864 7865 // Performs equivalent check of std::fabs(lhs - rhs) <= margin 7866 // But without the subtraction to allow for INFINITY in comparison 7867 bool marginComparison(double lhs, double rhs, double margin) { 7868 return (lhs + margin >= rhs) && (rhs + margin >= lhs); 7869 } 7870 7871 } 7872 7873 namespace Catch { 7874 namespace Detail { 7875 7876 Approx::Approx ( double value ) 7877 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ), 7878 m_margin( 0.0 ), 7879 m_scale( 0.0 ), 7880 m_value( value ) 7881 {} 7882 7883 Approx Approx::custom() { 7884 return Approx( 0 ); 7885 } 7886 7887 Approx Approx::operator-() const { 7888 auto temp(*this); 7889 temp.m_value = -temp.m_value; 7890 return temp; 7891 } 7892 7893 std::string Approx::toString() const { 7894 ReusableStringStream rss; 7895 rss << "Approx( " << ::Catch::Detail::stringify( m_value ) << " )"; 7896 return rss.str(); 7897 } 7898 7899 bool Approx::equalityComparisonImpl(const double other) const { 7900 // First try with fixed margin, then compute margin based on epsilon, scale and Approx's value 7901 // Thanks to Richard Harris for his help refining the scaled margin value 7902 return marginComparison(m_value, other, m_margin) 7903 || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(std::isinf(m_value)? 0 : m_value))); 7904 } 7905 7906 void Approx::setMargin(double newMargin) { 7907 CATCH_ENFORCE(newMargin >= 0, 7908 "Invalid Approx::margin: " << newMargin << '.' 7909 << " Approx::Margin has to be non-negative."); 7910 m_margin = newMargin; 7911 } 7912 7913 void Approx::setEpsilon(double newEpsilon) { 7914 CATCH_ENFORCE(newEpsilon >= 0 && newEpsilon <= 1.0, 7915 "Invalid Approx::epsilon: " << newEpsilon << '.' 7916 << " Approx::epsilon has to be in [0, 1]"); 7917 m_epsilon = newEpsilon; 7918 } 7919 7920 } // end namespace Detail 7921 7922 namespace literals { 7923 Detail::Approx operator "" _a(long double val) { 7924 return Detail::Approx(val); 7925 } 7926 Detail::Approx operator "" _a(unsigned long long val) { 7927 return Detail::Approx(val); 7928 } 7929 } // end namespace literals 7930 7931 std::string StringMaker<Catch::Detail::Approx>::convert(Catch::Detail::Approx const& value) { 7932 return value.toString(); 7933 } 7934 7935 } // end namespace Catch 7936 // end catch_approx.cpp 7937 // start catch_assertionhandler.cpp 7938 7939 // start catch_debugger.h 7940 7941 namespace Catch { 7942 bool isDebuggerActive(); 7943 } 7944 7945 #ifdef CATCH_PLATFORM_MAC 7946 7947 #if defined(__i386__) || defined(__x86_64__) 7948 #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */ 7949 #elif defined(__aarch64__) 7950 #define CATCH_TRAP() __asm__(".inst 0xd43e0000") 7951 #endif 7952 7953 #elif defined(CATCH_PLATFORM_IPHONE) 7954 7955 // use inline assembler 7956 #if defined(__i386__) || defined(__x86_64__) 7957 #define CATCH_TRAP() __asm__("int $3") 7958 #elif defined(__aarch64__) 7959 #define CATCH_TRAP() __asm__(".inst 0xd4200000") 7960 #elif defined(__arm__) && !defined(__thumb__) 7961 #define CATCH_TRAP() __asm__(".inst 0xe7f001f0") 7962 #elif defined(__arm__) && defined(__thumb__) 7963 #define CATCH_TRAP() __asm__(".inst 0xde01") 7964 #endif 7965 7966 #elif defined(CATCH_PLATFORM_LINUX) 7967 // If we can use inline assembler, do it because this allows us to break 7968 // directly at the location of the failing check instead of breaking inside 7969 // raise() called from it, i.e. one stack frame below. 7970 #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64)) 7971 #define CATCH_TRAP() asm volatile ("int $3") /* NOLINT */ 7972 #else // Fall back to the generic way. 7973 #include <signal.h> 7974 7975 #define CATCH_TRAP() raise(SIGTRAP) 7976 #endif 7977 #elif defined(_MSC_VER) 7978 #define CATCH_TRAP() __debugbreak() 7979 #elif defined(__MINGW32__) 7980 extern "C" __declspec(dllimport) void __stdcall DebugBreak(); 7981 #define CATCH_TRAP() DebugBreak() 7982 #endif 7983 7984 #ifndef CATCH_BREAK_INTO_DEBUGGER 7985 #ifdef CATCH_TRAP 7986 #define CATCH_BREAK_INTO_DEBUGGER() []{ if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } }() 7987 #else 7988 #define CATCH_BREAK_INTO_DEBUGGER() []{}() 7989 #endif 7990 #endif 7991 7992 // end catch_debugger.h 7993 // start catch_run_context.h 7994 7995 // start catch_fatal_condition.h 7996 7997 #include <cassert> 7998 7999 namespace Catch { 8000 8001 // Wrapper for platform-specific fatal error (signals/SEH) handlers 8002 // 8003 // Tries to be cooperative with other handlers, and not step over 8004 // other handlers. This means that unknown structured exceptions 8005 // are passed on, previous signal handlers are called, and so on. 8006 // 8007 // Can only be instantiated once, and assumes that once a signal 8008 // is caught, the binary will end up terminating. Thus, there 8009 class FatalConditionHandler { 8010 bool m_started = false; 8011 8012 // Install/disengage implementation for specific platform. 8013 // Should be if-defed to work on current platform, can assume 8014 // engage-disengage 1:1 pairing. 8015 void engage_platform(); 8016 void disengage_platform(); 8017 public: 8018 // Should also have platform-specific implementations as needed 8019 FatalConditionHandler(); 8020 ~FatalConditionHandler(); 8021 8022 void engage() { 8023 assert(!m_started && "Handler cannot be installed twice."); 8024 m_started = true; 8025 engage_platform(); 8026 } 8027 8028 void disengage() { 8029 assert(m_started && "Handler cannot be uninstalled without being installed first"); 8030 m_started = false; 8031 disengage_platform(); 8032 } 8033 }; 8034 8035 //! Simple RAII guard for (dis)engaging the FatalConditionHandler 8036 class FatalConditionHandlerGuard { 8037 FatalConditionHandler* m_handler; 8038 public: 8039 FatalConditionHandlerGuard(FatalConditionHandler* handler): 8040 m_handler(handler) { 8041 m_handler->engage(); 8042 } 8043 ~FatalConditionHandlerGuard() { 8044 m_handler->disengage(); 8045 } 8046 }; 8047 8048 } // end namespace Catch 8049 8050 // end catch_fatal_condition.h 8051 #include <string> 8052 8053 namespace Catch { 8054 8055 struct IMutableContext; 8056 8057 /////////////////////////////////////////////////////////////////////////// 8058 8059 class RunContext : public IResultCapture, public IRunner { 8060 8061 public: 8062 RunContext( RunContext const& ) = delete; 8063 RunContext& operator =( RunContext const& ) = delete; 8064 8065 explicit RunContext( IConfigPtr const& _config, IStreamingReporterPtr&& reporter ); 8066 8067 ~RunContext() override; 8068 8069 void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ); 8070 void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ); 8071 8072 Totals runTest(TestCase const& testCase); 8073 8074 IConfigPtr config() const; 8075 IStreamingReporter& reporter() const; 8076 8077 public: // IResultCapture 8078 8079 // Assertion handlers 8080 void handleExpr 8081 ( AssertionInfo const& info, 8082 ITransientExpression const& expr, 8083 AssertionReaction& reaction ) override; 8084 void handleMessage 8085 ( AssertionInfo const& info, 8086 ResultWas::OfType resultType, 8087 StringRef const& message, 8088 AssertionReaction& reaction ) override; 8089 void handleUnexpectedExceptionNotThrown 8090 ( AssertionInfo const& info, 8091 AssertionReaction& reaction ) override; 8092 void handleUnexpectedInflightException 8093 ( AssertionInfo const& info, 8094 std::string const& message, 8095 AssertionReaction& reaction ) override; 8096 void handleIncomplete 8097 ( AssertionInfo const& info ) override; 8098 void handleNonExpr 8099 ( AssertionInfo const &info, 8100 ResultWas::OfType resultType, 8101 AssertionReaction &reaction ) override; 8102 8103 bool sectionStarted( SectionInfo const& sectionInfo, Counts& assertions ) override; 8104 8105 void sectionEnded( SectionEndInfo const& endInfo ) override; 8106 void sectionEndedEarly( SectionEndInfo const& endInfo ) override; 8107 8108 auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& override; 8109 8110 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 8111 void benchmarkPreparing( std::string const& name ) override; 8112 void benchmarkStarting( BenchmarkInfo const& info ) override; 8113 void benchmarkEnded( BenchmarkStats<> const& stats ) override; 8114 void benchmarkFailed( std::string const& error ) override; 8115 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 8116 8117 void pushScopedMessage( MessageInfo const& message ) override; 8118 void popScopedMessage( MessageInfo const& message ) override; 8119 8120 void emplaceUnscopedMessage( MessageBuilder const& builder ) override; 8121 8122 std::string getCurrentTestName() const override; 8123 8124 const AssertionResult* getLastResult() const override; 8125 8126 void exceptionEarlyReported() override; 8127 8128 void handleFatalErrorCondition( StringRef message ) override; 8129 8130 bool lastAssertionPassed() override; 8131 8132 void assertionPassed() override; 8133 8134 public: 8135 // !TBD We need to do this another way! 8136 bool aborting() const final; 8137 8138 private: 8139 8140 void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ); 8141 void invokeActiveTestCase(); 8142 8143 void resetAssertionInfo(); 8144 bool testForMissingAssertions( Counts& assertions ); 8145 8146 void assertionEnded( AssertionResult const& result ); 8147 void reportExpr 8148 ( AssertionInfo const &info, 8149 ResultWas::OfType resultType, 8150 ITransientExpression const *expr, 8151 bool negated ); 8152 8153 void populateReaction( AssertionReaction& reaction ); 8154 8155 private: 8156 8157 void handleUnfinishedSections(); 8158 8159 TestRunInfo m_runInfo; 8160 IMutableContext& m_context; 8161 TestCase const* m_activeTestCase = nullptr; 8162 ITracker* m_testCaseTracker = nullptr; 8163 Option<AssertionResult> m_lastResult; 8164 8165 IConfigPtr m_config; 8166 Totals m_totals; 8167 IStreamingReporterPtr m_reporter; 8168 std::vector<MessageInfo> m_messages; 8169 std::vector<ScopedMessage> m_messageScopes; /* Keeps owners of so-called unscoped messages. */ 8170 AssertionInfo m_lastAssertionInfo; 8171 std::vector<SectionEndInfo> m_unfinishedSections; 8172 std::vector<ITracker*> m_activeSections; 8173 TrackerContext m_trackerContext; 8174 FatalConditionHandler m_fatalConditionhandler; 8175 bool m_lastAssertionPassed = false; 8176 bool m_shouldReportUnexpected = true; 8177 bool m_includeSuccessfulResults; 8178 }; 8179 8180 void seedRng(IConfig const& config); 8181 unsigned int rngSeed(); 8182 } // end namespace Catch 8183 8184 // end catch_run_context.h 8185 namespace Catch { 8186 8187 namespace { 8188 auto operator <<( std::ostream& os, ITransientExpression const& expr ) -> std::ostream& { 8189 expr.streamReconstructedExpression( os ); 8190 return os; 8191 } 8192 } 8193 8194 LazyExpression::LazyExpression( bool isNegated ) 8195 : m_isNegated( isNegated ) 8196 {} 8197 8198 LazyExpression::LazyExpression( LazyExpression const& other ) : m_isNegated( other.m_isNegated ) {} 8199 8200 LazyExpression::operator bool() const { 8201 return m_transientExpression != nullptr; 8202 } 8203 8204 auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream& { 8205 if( lazyExpr.m_isNegated ) 8206 os << "!"; 8207 8208 if( lazyExpr ) { 8209 if( lazyExpr.m_isNegated && lazyExpr.m_transientExpression->isBinaryExpression() ) 8210 os << "(" << *lazyExpr.m_transientExpression << ")"; 8211 else 8212 os << *lazyExpr.m_transientExpression; 8213 } 8214 else { 8215 os << "{** error - unchecked empty expression requested **}"; 8216 } 8217 return os; 8218 } 8219 8220 AssertionHandler::AssertionHandler 8221 ( StringRef const& macroName, 8222 SourceLineInfo const& lineInfo, 8223 StringRef capturedExpression, 8224 ResultDisposition::Flags resultDisposition ) 8225 : m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition }, 8226 m_resultCapture( getResultCapture() ) 8227 {} 8228 8229 void AssertionHandler::handleExpr( ITransientExpression const& expr ) { 8230 m_resultCapture.handleExpr( m_assertionInfo, expr, m_reaction ); 8231 } 8232 void AssertionHandler::handleMessage(ResultWas::OfType resultType, StringRef const& message) { 8233 m_resultCapture.handleMessage( m_assertionInfo, resultType, message, m_reaction ); 8234 } 8235 8236 auto AssertionHandler::allowThrows() const -> bool { 8237 return getCurrentContext().getConfig()->allowThrows(); 8238 } 8239 8240 void AssertionHandler::complete() { 8241 setCompleted(); 8242 if( m_reaction.shouldDebugBreak ) { 8243 8244 // If you find your debugger stopping you here then go one level up on the 8245 // call-stack for the code that caused it (typically a failed assertion) 8246 8247 // (To go back to the test and change execution, jump over the throw, next) 8248 CATCH_BREAK_INTO_DEBUGGER(); 8249 } 8250 if (m_reaction.shouldThrow) { 8251 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 8252 throw Catch::TestFailureException(); 8253 #else 8254 CATCH_ERROR( "Test failure requires aborting test!" ); 8255 #endif 8256 } 8257 } 8258 void AssertionHandler::setCompleted() { 8259 m_completed = true; 8260 } 8261 8262 void AssertionHandler::handleUnexpectedInflightException() { 8263 m_resultCapture.handleUnexpectedInflightException( m_assertionInfo, Catch::translateActiveException(), m_reaction ); 8264 } 8265 8266 void AssertionHandler::handleExceptionThrownAsExpected() { 8267 m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction); 8268 } 8269 void AssertionHandler::handleExceptionNotThrownAsExpected() { 8270 m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction); 8271 } 8272 8273 void AssertionHandler::handleUnexpectedExceptionNotThrown() { 8274 m_resultCapture.handleUnexpectedExceptionNotThrown( m_assertionInfo, m_reaction ); 8275 } 8276 8277 void AssertionHandler::handleThrowingCallSkipped() { 8278 m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction); 8279 } 8280 8281 // This is the overload that takes a string and infers the Equals matcher from it 8282 // The more general overload, that takes any string matcher, is in catch_capture_matchers.cpp 8283 void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef const& matcherString ) { 8284 handleExceptionMatchExpr( handler, Matchers::Equals( str ), matcherString ); 8285 } 8286 8287 } // namespace Catch 8288 // end catch_assertionhandler.cpp 8289 // start catch_assertionresult.cpp 8290 8291 namespace Catch { 8292 AssertionResultData::AssertionResultData(ResultWas::OfType _resultType, LazyExpression const & _lazyExpression): 8293 lazyExpression(_lazyExpression), 8294 resultType(_resultType) {} 8295 8296 std::string AssertionResultData::reconstructExpression() const { 8297 8298 if( reconstructedExpression.empty() ) { 8299 if( lazyExpression ) { 8300 ReusableStringStream rss; 8301 rss << lazyExpression; 8302 reconstructedExpression = rss.str(); 8303 } 8304 } 8305 return reconstructedExpression; 8306 } 8307 8308 AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) 8309 : m_info( info ), 8310 m_resultData( data ) 8311 {} 8312 8313 // Result was a success 8314 bool AssertionResult::succeeded() const { 8315 return Catch::isOk( m_resultData.resultType ); 8316 } 8317 8318 // Result was a success, or failure is suppressed 8319 bool AssertionResult::isOk() const { 8320 return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition ); 8321 } 8322 8323 ResultWas::OfType AssertionResult::getResultType() const { 8324 return m_resultData.resultType; 8325 } 8326 8327 bool AssertionResult::hasExpression() const { 8328 return !m_info.capturedExpression.empty(); 8329 } 8330 8331 bool AssertionResult::hasMessage() const { 8332 return !m_resultData.message.empty(); 8333 } 8334 8335 std::string AssertionResult::getExpression() const { 8336 // Possibly overallocating by 3 characters should be basically free 8337 std::string expr; expr.reserve(m_info.capturedExpression.size() + 3); 8338 if (isFalseTest(m_info.resultDisposition)) { 8339 expr += "!("; 8340 } 8341 expr += m_info.capturedExpression; 8342 if (isFalseTest(m_info.resultDisposition)) { 8343 expr += ')'; 8344 } 8345 return expr; 8346 } 8347 8348 std::string AssertionResult::getExpressionInMacro() const { 8349 std::string expr; 8350 if( m_info.macroName.empty() ) 8351 expr = static_cast<std::string>(m_info.capturedExpression); 8352 else { 8353 expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 ); 8354 expr += m_info.macroName; 8355 expr += "( "; 8356 expr += m_info.capturedExpression; 8357 expr += " )"; 8358 } 8359 return expr; 8360 } 8361 8362 bool AssertionResult::hasExpandedExpression() const { 8363 return hasExpression() && getExpandedExpression() != getExpression(); 8364 } 8365 8366 std::string AssertionResult::getExpandedExpression() const { 8367 std::string expr = m_resultData.reconstructExpression(); 8368 return expr.empty() 8369 ? getExpression() 8370 : expr; 8371 } 8372 8373 std::string AssertionResult::getMessage() const { 8374 return m_resultData.message; 8375 } 8376 SourceLineInfo AssertionResult::getSourceInfo() const { 8377 return m_info.lineInfo; 8378 } 8379 8380 StringRef AssertionResult::getTestMacroName() const { 8381 return m_info.macroName; 8382 } 8383 8384 } // end namespace Catch 8385 // end catch_assertionresult.cpp 8386 // start catch_capture_matchers.cpp 8387 8388 namespace Catch { 8389 8390 using StringMatcher = Matchers::Impl::MatcherBase<std::string>; 8391 8392 // This is the general overload that takes a any string matcher 8393 // There is another overload, in catch_assertionhandler.h/.cpp, that only takes a string and infers 8394 // the Equals matcher (so the header does not mention matchers) 8395 void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString ) { 8396 std::string exceptionMessage = Catch::translateActiveException(); 8397 MatchExpr<std::string, StringMatcher const&> expr( exceptionMessage, matcher, matcherString ); 8398 handler.handleExpr( expr ); 8399 } 8400 8401 } // namespace Catch 8402 // end catch_capture_matchers.cpp 8403 // start catch_commandline.cpp 8404 8405 // start catch_commandline.h 8406 8407 // start catch_clara.h 8408 8409 // Use Catch's value for console width (store Clara's off to the side, if present) 8410 #ifdef CLARA_CONFIG_CONSOLE_WIDTH 8411 #define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 8412 #undef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 8413 #endif 8414 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH-1 8415 8416 #ifdef __clang__ 8417 #pragma clang diagnostic push 8418 #pragma clang diagnostic ignored "-Wweak-vtables" 8419 #pragma clang diagnostic ignored "-Wexit-time-destructors" 8420 #pragma clang diagnostic ignored "-Wshadow" 8421 #endif 8422 8423 // start clara.hpp 8424 // Copyright 2017 Two Blue Cubes Ltd. All rights reserved. 8425 // 8426 // Distributed under the Boost Software License, Version 1.0. (See accompanying 8427 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8428 // 8429 // See https://github.com/philsquared/Clara for more details 8430 8431 // Clara v1.1.5 8432 8433 8434 #ifndef CATCH_CLARA_CONFIG_CONSOLE_WIDTH 8435 #define CATCH_CLARA_CONFIG_CONSOLE_WIDTH 80 8436 #endif 8437 8438 #ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 8439 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CLARA_CONFIG_CONSOLE_WIDTH 8440 #endif 8441 8442 #ifndef CLARA_CONFIG_OPTIONAL_TYPE 8443 #ifdef __has_include 8444 #if __has_include(<optional>) && __cplusplus >= 201703L 8445 #include <optional> 8446 #define CLARA_CONFIG_OPTIONAL_TYPE std::optional 8447 #endif 8448 #endif 8449 #endif 8450 8451 // ----------- #included from clara_textflow.hpp ----------- 8452 8453 // TextFlowCpp 8454 // 8455 // A single-header library for wrapping and laying out basic text, by Phil Nash 8456 // 8457 // Distributed under the Boost Software License, Version 1.0. (See accompanying 8458 // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8459 // 8460 // This project is hosted at https://github.com/philsquared/textflowcpp 8461 8462 8463 #include <cassert> 8464 #include <ostream> 8465 #include <sstream> 8466 #include <vector> 8467 8468 #ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 8469 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 80 8470 #endif 8471 8472 namespace Catch { 8473 namespace clara { 8474 namespace TextFlow { 8475 8476 inline auto isWhitespace(char c) -> bool { 8477 static std::string chars = " \t\n\r"; 8478 return chars.find(c) != std::string::npos; 8479 } 8480 inline auto isBreakableBefore(char c) -> bool { 8481 static std::string chars = "[({<|"; 8482 return chars.find(c) != std::string::npos; 8483 } 8484 inline auto isBreakableAfter(char c) -> bool { 8485 static std::string chars = "])}>.,:;*+-=&/\\"; 8486 return chars.find(c) != std::string::npos; 8487 } 8488 8489 class Columns; 8490 8491 class Column { 8492 std::vector<std::string> m_strings; 8493 size_t m_width = CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH; 8494 size_t m_indent = 0; 8495 size_t m_initialIndent = std::string::npos; 8496 8497 public: 8498 class iterator { 8499 friend Column; 8500 8501 Column const& m_column; 8502 size_t m_stringIndex = 0; 8503 size_t m_pos = 0; 8504 8505 size_t m_len = 0; 8506 size_t m_end = 0; 8507 bool m_suffix = false; 8508 8509 iterator(Column const& column, size_t stringIndex) 8510 : m_column(column), 8511 m_stringIndex(stringIndex) {} 8512 8513 auto line() const -> std::string const& { return m_column.m_strings[m_stringIndex]; } 8514 8515 auto isBoundary(size_t at) const -> bool { 8516 assert(at > 0); 8517 assert(at <= line().size()); 8518 8519 return at == line().size() || 8520 (isWhitespace(line()[at]) && !isWhitespace(line()[at - 1])) || 8521 isBreakableBefore(line()[at]) || 8522 isBreakableAfter(line()[at - 1]); 8523 } 8524 8525 void calcLength() { 8526 assert(m_stringIndex < m_column.m_strings.size()); 8527 8528 m_suffix = false; 8529 auto width = m_column.m_width - indent(); 8530 m_end = m_pos; 8531 if (line()[m_pos] == '\n') { 8532 ++m_end; 8533 } 8534 while (m_end < line().size() && line()[m_end] != '\n') 8535 ++m_end; 8536 8537 if (m_end < m_pos + width) { 8538 m_len = m_end - m_pos; 8539 } else { 8540 size_t len = width; 8541 while (len > 0 && !isBoundary(m_pos + len)) 8542 --len; 8543 while (len > 0 && isWhitespace(line()[m_pos + len - 1])) 8544 --len; 8545 8546 if (len > 0) { 8547 m_len = len; 8548 } else { 8549 m_suffix = true; 8550 m_len = width - 1; 8551 } 8552 } 8553 } 8554 8555 auto indent() const -> size_t { 8556 auto initial = m_pos == 0 && m_stringIndex == 0 ? m_column.m_initialIndent : std::string::npos; 8557 return initial == std::string::npos ? m_column.m_indent : initial; 8558 } 8559 8560 auto addIndentAndSuffix(std::string const &plain) const -> std::string { 8561 return std::string(indent(), ' ') + (m_suffix ? plain + "-" : plain); 8562 } 8563 8564 public: 8565 using difference_type = std::ptrdiff_t; 8566 using value_type = std::string; 8567 using pointer = value_type * ; 8568 using reference = value_type & ; 8569 using iterator_category = std::forward_iterator_tag; 8570 8571 explicit iterator(Column const& column) : m_column(column) { 8572 assert(m_column.m_width > m_column.m_indent); 8573 assert(m_column.m_initialIndent == std::string::npos || m_column.m_width > m_column.m_initialIndent); 8574 calcLength(); 8575 if (m_len == 0) 8576 m_stringIndex++; // Empty string 8577 } 8578 8579 auto operator *() const -> std::string { 8580 assert(m_stringIndex < m_column.m_strings.size()); 8581 assert(m_pos <= m_end); 8582 return addIndentAndSuffix(line().substr(m_pos, m_len)); 8583 } 8584 8585 auto operator ++() -> iterator& { 8586 m_pos += m_len; 8587 if (m_pos < line().size() && line()[m_pos] == '\n') 8588 m_pos += 1; 8589 else 8590 while (m_pos < line().size() && isWhitespace(line()[m_pos])) 8591 ++m_pos; 8592 8593 if (m_pos == line().size()) { 8594 m_pos = 0; 8595 ++m_stringIndex; 8596 } 8597 if (m_stringIndex < m_column.m_strings.size()) 8598 calcLength(); 8599 return *this; 8600 } 8601 auto operator ++(int) -> iterator { 8602 iterator prev(*this); 8603 operator++(); 8604 return prev; 8605 } 8606 8607 auto operator ==(iterator const& other) const -> bool { 8608 return 8609 m_pos == other.m_pos && 8610 m_stringIndex == other.m_stringIndex && 8611 &m_column == &other.m_column; 8612 } 8613 auto operator !=(iterator const& other) const -> bool { 8614 return !operator==(other); 8615 } 8616 }; 8617 using const_iterator = iterator; 8618 8619 explicit Column(std::string const& text) { m_strings.push_back(text); } 8620 8621 auto width(size_t newWidth) -> Column& { 8622 assert(newWidth > 0); 8623 m_width = newWidth; 8624 return *this; 8625 } 8626 auto indent(size_t newIndent) -> Column& { 8627 m_indent = newIndent; 8628 return *this; 8629 } 8630 auto initialIndent(size_t newIndent) -> Column& { 8631 m_initialIndent = newIndent; 8632 return *this; 8633 } 8634 8635 auto width() const -> size_t { return m_width; } 8636 auto begin() const -> iterator { return iterator(*this); } 8637 auto end() const -> iterator { return { *this, m_strings.size() }; } 8638 8639 inline friend std::ostream& operator << (std::ostream& os, Column const& col) { 8640 bool first = true; 8641 for (auto line : col) { 8642 if (first) 8643 first = false; 8644 else 8645 os << "\n"; 8646 os << line; 8647 } 8648 return os; 8649 } 8650 8651 auto operator + (Column const& other)->Columns; 8652 8653 auto toString() const -> std::string { 8654 std::ostringstream oss; 8655 oss << *this; 8656 return oss.str(); 8657 } 8658 }; 8659 8660 class Spacer : public Column { 8661 8662 public: 8663 explicit Spacer(size_t spaceWidth) : Column("") { 8664 width(spaceWidth); 8665 } 8666 }; 8667 8668 class Columns { 8669 std::vector<Column> m_columns; 8670 8671 public: 8672 8673 class iterator { 8674 friend Columns; 8675 struct EndTag {}; 8676 8677 std::vector<Column> const& m_columns; 8678 std::vector<Column::iterator> m_iterators; 8679 size_t m_activeIterators; 8680 8681 iterator(Columns const& columns, EndTag) 8682 : m_columns(columns.m_columns), 8683 m_activeIterators(0) { 8684 m_iterators.reserve(m_columns.size()); 8685 8686 for (auto const& col : m_columns) 8687 m_iterators.push_back(col.end()); 8688 } 8689 8690 public: 8691 using difference_type = std::ptrdiff_t; 8692 using value_type = std::string; 8693 using pointer = value_type * ; 8694 using reference = value_type & ; 8695 using iterator_category = std::forward_iterator_tag; 8696 8697 explicit iterator(Columns const& columns) 8698 : m_columns(columns.m_columns), 8699 m_activeIterators(m_columns.size()) { 8700 m_iterators.reserve(m_columns.size()); 8701 8702 for (auto const& col : m_columns) 8703 m_iterators.push_back(col.begin()); 8704 } 8705 8706 auto operator ==(iterator const& other) const -> bool { 8707 return m_iterators == other.m_iterators; 8708 } 8709 auto operator !=(iterator const& other) const -> bool { 8710 return m_iterators != other.m_iterators; 8711 } 8712 auto operator *() const -> std::string { 8713 std::string row, padding; 8714 8715 for (size_t i = 0; i < m_columns.size(); ++i) { 8716 auto width = m_columns[i].width(); 8717 if (m_iterators[i] != m_columns[i].end()) { 8718 std::string col = *m_iterators[i]; 8719 row += padding + col; 8720 if (col.size() < width) 8721 padding = std::string(width - col.size(), ' '); 8722 else 8723 padding = ""; 8724 } else { 8725 padding += std::string(width, ' '); 8726 } 8727 } 8728 return row; 8729 } 8730 auto operator ++() -> iterator& { 8731 for (size_t i = 0; i < m_columns.size(); ++i) { 8732 if (m_iterators[i] != m_columns[i].end()) 8733 ++m_iterators[i]; 8734 } 8735 return *this; 8736 } 8737 auto operator ++(int) -> iterator { 8738 iterator prev(*this); 8739 operator++(); 8740 return prev; 8741 } 8742 }; 8743 using const_iterator = iterator; 8744 8745 auto begin() const -> iterator { return iterator(*this); } 8746 auto end() const -> iterator { return { *this, iterator::EndTag() }; } 8747 8748 auto operator += (Column const& col) -> Columns& { 8749 m_columns.push_back(col); 8750 return *this; 8751 } 8752 auto operator + (Column const& col) -> Columns { 8753 Columns combined = *this; 8754 combined += col; 8755 return combined; 8756 } 8757 8758 inline friend std::ostream& operator << (std::ostream& os, Columns const& cols) { 8759 8760 bool first = true; 8761 for (auto line : cols) { 8762 if (first) 8763 first = false; 8764 else 8765 os << "\n"; 8766 os << line; 8767 } 8768 return os; 8769 } 8770 8771 auto toString() const -> std::string { 8772 std::ostringstream oss; 8773 oss << *this; 8774 return oss.str(); 8775 } 8776 }; 8777 8778 inline auto Column::operator + (Column const& other) -> Columns { 8779 Columns cols; 8780 cols += *this; 8781 cols += other; 8782 return cols; 8783 } 8784 } 8785 8786 } 8787 } 8788 8789 // ----------- end of #include from clara_textflow.hpp ----------- 8790 // ........... back in clara.hpp 8791 8792 #include <cctype> 8793 #include <string> 8794 #include <memory> 8795 #include <set> 8796 #include <algorithm> 8797 8798 #if !defined(CATCH_PLATFORM_WINDOWS) && ( defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) ) 8799 #define CATCH_PLATFORM_WINDOWS 8800 #endif 8801 8802 namespace Catch { namespace clara { 8803 namespace detail { 8804 8805 // Traits for extracting arg and return type of lambdas (for single argument lambdas) 8806 template<typename L> 8807 struct UnaryLambdaTraits : UnaryLambdaTraits<decltype( &L::operator() )> {}; 8808 8809 template<typename ClassT, typename ReturnT, typename... Args> 8810 struct UnaryLambdaTraits<ReturnT( ClassT::* )( Args... ) const> { 8811 static const bool isValid = false; 8812 }; 8813 8814 template<typename ClassT, typename ReturnT, typename ArgT> 8815 struct UnaryLambdaTraits<ReturnT( ClassT::* )( ArgT ) const> { 8816 static const bool isValid = true; 8817 using ArgType = typename std::remove_const<typename std::remove_reference<ArgT>::type>::type; 8818 using ReturnType = ReturnT; 8819 }; 8820 8821 class TokenStream; 8822 8823 // Transport for raw args (copied from main args, or supplied via init list for testing) 8824 class Args { 8825 friend TokenStream; 8826 std::string m_exeName; 8827 std::vector<std::string> m_args; 8828 8829 public: 8830 Args( int argc, char const* const* argv ) 8831 : m_exeName(argv[0]), 8832 m_args(argv + 1, argv + argc) {} 8833 8834 Args( std::initializer_list<std::string> args ) 8835 : m_exeName( *args.begin() ), 8836 m_args( args.begin()+1, args.end() ) 8837 {} 8838 8839 auto exeName() const -> std::string { 8840 return m_exeName; 8841 } 8842 }; 8843 8844 // Wraps a token coming from a token stream. These may not directly correspond to strings as a single string 8845 // may encode an option + its argument if the : or = form is used 8846 enum class TokenType { 8847 Option, Argument 8848 }; 8849 struct Token { 8850 TokenType type; 8851 std::string token; 8852 }; 8853 8854 inline auto isOptPrefix( char c ) -> bool { 8855 return c == '-' 8856 #ifdef CATCH_PLATFORM_WINDOWS 8857 || c == '/' 8858 #endif 8859 ; 8860 } 8861 8862 // Abstracts iterators into args as a stream of tokens, with option arguments uniformly handled 8863 class TokenStream { 8864 using Iterator = std::vector<std::string>::const_iterator; 8865 Iterator it; 8866 Iterator itEnd; 8867 std::vector<Token> m_tokenBuffer; 8868 8869 void loadBuffer() { 8870 m_tokenBuffer.resize( 0 ); 8871 8872 // Skip any empty strings 8873 while( it != itEnd && it->empty() ) 8874 ++it; 8875 8876 if( it != itEnd ) { 8877 auto const &next = *it; 8878 if( isOptPrefix( next[0] ) ) { 8879 auto delimiterPos = next.find_first_of( " :=" ); 8880 if( delimiterPos != std::string::npos ) { 8881 m_tokenBuffer.push_back( { TokenType::Option, next.substr( 0, delimiterPos ) } ); 8882 m_tokenBuffer.push_back( { TokenType::Argument, next.substr( delimiterPos + 1 ) } ); 8883 } else { 8884 if( next[1] != '-' && next.size() > 2 ) { 8885 std::string opt = "- "; 8886 for( size_t i = 1; i < next.size(); ++i ) { 8887 opt[1] = next[i]; 8888 m_tokenBuffer.push_back( { TokenType::Option, opt } ); 8889 } 8890 } else { 8891 m_tokenBuffer.push_back( { TokenType::Option, next } ); 8892 } 8893 } 8894 } else { 8895 m_tokenBuffer.push_back( { TokenType::Argument, next } ); 8896 } 8897 } 8898 } 8899 8900 public: 8901 explicit TokenStream( Args const &args ) : TokenStream( args.m_args.begin(), args.m_args.end() ) {} 8902 8903 TokenStream( Iterator it, Iterator itEnd ) : it( it ), itEnd( itEnd ) { 8904 loadBuffer(); 8905 } 8906 8907 explicit operator bool() const { 8908 return !m_tokenBuffer.empty() || it != itEnd; 8909 } 8910 8911 auto count() const -> size_t { return m_tokenBuffer.size() + (itEnd - it); } 8912 8913 auto operator*() const -> Token { 8914 assert( !m_tokenBuffer.empty() ); 8915 return m_tokenBuffer.front(); 8916 } 8917 8918 auto operator->() const -> Token const * { 8919 assert( !m_tokenBuffer.empty() ); 8920 return &m_tokenBuffer.front(); 8921 } 8922 8923 auto operator++() -> TokenStream & { 8924 if( m_tokenBuffer.size() >= 2 ) { 8925 m_tokenBuffer.erase( m_tokenBuffer.begin() ); 8926 } else { 8927 if( it != itEnd ) 8928 ++it; 8929 loadBuffer(); 8930 } 8931 return *this; 8932 } 8933 }; 8934 8935 class ResultBase { 8936 public: 8937 enum Type { 8938 Ok, LogicError, RuntimeError 8939 }; 8940 8941 protected: 8942 ResultBase( Type type ) : m_type( type ) {} 8943 virtual ~ResultBase() = default; 8944 8945 virtual void enforceOk() const = 0; 8946 8947 Type m_type; 8948 }; 8949 8950 template<typename T> 8951 class ResultValueBase : public ResultBase { 8952 public: 8953 auto value() const -> T const & { 8954 enforceOk(); 8955 return m_value; 8956 } 8957 8958 protected: 8959 ResultValueBase( Type type ) : ResultBase( type ) {} 8960 8961 ResultValueBase( ResultValueBase const &other ) : ResultBase( other ) { 8962 if( m_type == ResultBase::Ok ) 8963 new( &m_value ) T( other.m_value ); 8964 } 8965 8966 ResultValueBase( Type, T const &value ) : ResultBase( Ok ) { 8967 new( &m_value ) T( value ); 8968 } 8969 8970 auto operator=( ResultValueBase const &other ) -> ResultValueBase & { 8971 if( m_type == ResultBase::Ok ) 8972 m_value.~T(); 8973 ResultBase::operator=(other); 8974 if( m_type == ResultBase::Ok ) 8975 new( &m_value ) T( other.m_value ); 8976 return *this; 8977 } 8978 8979 ~ResultValueBase() override { 8980 if( m_type == Ok ) 8981 m_value.~T(); 8982 } 8983 8984 union { 8985 T m_value; 8986 }; 8987 }; 8988 8989 template<> 8990 class ResultValueBase<void> : public ResultBase { 8991 protected: 8992 using ResultBase::ResultBase; 8993 }; 8994 8995 template<typename T = void> 8996 class BasicResult : public ResultValueBase<T> { 8997 public: 8998 template<typename U> 8999 explicit BasicResult( BasicResult<U> const &other ) 9000 : ResultValueBase<T>( other.type() ), 9001 m_errorMessage( other.errorMessage() ) 9002 { 9003 assert( type() != ResultBase::Ok ); 9004 } 9005 9006 template<typename U> 9007 static auto ok( U const &value ) -> BasicResult { return { ResultBase::Ok, value }; } 9008 static auto ok() -> BasicResult { return { ResultBase::Ok }; } 9009 static auto logicError( std::string const &message ) -> BasicResult { return { ResultBase::LogicError, message }; } 9010 static auto runtimeError( std::string const &message ) -> BasicResult { return { ResultBase::RuntimeError, message }; } 9011 9012 explicit operator bool() const { return m_type == ResultBase::Ok; } 9013 auto type() const -> ResultBase::Type { return m_type; } 9014 auto errorMessage() const -> std::string { return m_errorMessage; } 9015 9016 protected: 9017 void enforceOk() const override { 9018 9019 // Errors shouldn't reach this point, but if they do 9020 // the actual error message will be in m_errorMessage 9021 assert( m_type != ResultBase::LogicError ); 9022 assert( m_type != ResultBase::RuntimeError ); 9023 if( m_type != ResultBase::Ok ) 9024 std::abort(); 9025 } 9026 9027 std::string m_errorMessage; // Only populated if resultType is an error 9028 9029 BasicResult( ResultBase::Type type, std::string const &message ) 9030 : ResultValueBase<T>(type), 9031 m_errorMessage(message) 9032 { 9033 assert( m_type != ResultBase::Ok ); 9034 } 9035 9036 using ResultValueBase<T>::ResultValueBase; 9037 using ResultBase::m_type; 9038 }; 9039 9040 enum class ParseResultType { 9041 Matched, NoMatch, ShortCircuitAll, ShortCircuitSame 9042 }; 9043 9044 class ParseState { 9045 public: 9046 9047 ParseState( ParseResultType type, TokenStream const &remainingTokens ) 9048 : m_type(type), 9049 m_remainingTokens( remainingTokens ) 9050 {} 9051 9052 auto type() const -> ParseResultType { return m_type; } 9053 auto remainingTokens() const -> TokenStream { return m_remainingTokens; } 9054 9055 private: 9056 ParseResultType m_type; 9057 TokenStream m_remainingTokens; 9058 }; 9059 9060 using Result = BasicResult<void>; 9061 using ParserResult = BasicResult<ParseResultType>; 9062 using InternalParseResult = BasicResult<ParseState>; 9063 9064 struct HelpColumns { 9065 std::string left; 9066 std::string right; 9067 }; 9068 9069 template<typename T> 9070 inline auto convertInto( std::string const &source, T& target ) -> ParserResult { 9071 std::stringstream ss; 9072 ss << source; 9073 ss >> target; 9074 if( ss.fail() ) 9075 return ParserResult::runtimeError( "Unable to convert '" + source + "' to destination type" ); 9076 else 9077 return ParserResult::ok( ParseResultType::Matched ); 9078 } 9079 inline auto convertInto( std::string const &source, std::string& target ) -> ParserResult { 9080 target = source; 9081 return ParserResult::ok( ParseResultType::Matched ); 9082 } 9083 inline auto convertInto( std::string const &source, bool &target ) -> ParserResult { 9084 std::string srcLC = source; 9085 std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( unsigned char c ) { return static_cast<char>( std::tolower(c) ); } ); 9086 if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on") 9087 target = true; 9088 else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off") 9089 target = false; 9090 else 9091 return ParserResult::runtimeError( "Expected a boolean value but did not recognise: '" + source + "'" ); 9092 return ParserResult::ok( ParseResultType::Matched ); 9093 } 9094 #ifdef CLARA_CONFIG_OPTIONAL_TYPE 9095 template<typename T> 9096 inline auto convertInto( std::string const &source, CLARA_CONFIG_OPTIONAL_TYPE<T>& target ) -> ParserResult { 9097 T temp; 9098 auto result = convertInto( source, temp ); 9099 if( result ) 9100 target = std::move(temp); 9101 return result; 9102 } 9103 #endif // CLARA_CONFIG_OPTIONAL_TYPE 9104 9105 struct NonCopyable { 9106 NonCopyable() = default; 9107 NonCopyable( NonCopyable const & ) = delete; 9108 NonCopyable( NonCopyable && ) = delete; 9109 NonCopyable &operator=( NonCopyable const & ) = delete; 9110 NonCopyable &operator=( NonCopyable && ) = delete; 9111 }; 9112 9113 struct BoundRef : NonCopyable { 9114 virtual ~BoundRef() = default; 9115 virtual auto isContainer() const -> bool { return false; } 9116 virtual auto isFlag() const -> bool { return false; } 9117 }; 9118 struct BoundValueRefBase : BoundRef { 9119 virtual auto setValue( std::string const &arg ) -> ParserResult = 0; 9120 }; 9121 struct BoundFlagRefBase : BoundRef { 9122 virtual auto setFlag( bool flag ) -> ParserResult = 0; 9123 virtual auto isFlag() const -> bool { return true; } 9124 }; 9125 9126 template<typename T> 9127 struct BoundValueRef : BoundValueRefBase { 9128 T &m_ref; 9129 9130 explicit BoundValueRef( T &ref ) : m_ref( ref ) {} 9131 9132 auto setValue( std::string const &arg ) -> ParserResult override { 9133 return convertInto( arg, m_ref ); 9134 } 9135 }; 9136 9137 template<typename T> 9138 struct BoundValueRef<std::vector<T>> : BoundValueRefBase { 9139 std::vector<T> &m_ref; 9140 9141 explicit BoundValueRef( std::vector<T> &ref ) : m_ref( ref ) {} 9142 9143 auto isContainer() const -> bool override { return true; } 9144 9145 auto setValue( std::string const &arg ) -> ParserResult override { 9146 T temp; 9147 auto result = convertInto( arg, temp ); 9148 if( result ) 9149 m_ref.push_back( temp ); 9150 return result; 9151 } 9152 }; 9153 9154 struct BoundFlagRef : BoundFlagRefBase { 9155 bool &m_ref; 9156 9157 explicit BoundFlagRef( bool &ref ) : m_ref( ref ) {} 9158 9159 auto setFlag( bool flag ) -> ParserResult override { 9160 m_ref = flag; 9161 return ParserResult::ok( ParseResultType::Matched ); 9162 } 9163 }; 9164 9165 template<typename ReturnType> 9166 struct LambdaInvoker { 9167 static_assert( std::is_same<ReturnType, ParserResult>::value, "Lambda must return void or clara::ParserResult" ); 9168 9169 template<typename L, typename ArgType> 9170 static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult { 9171 return lambda( arg ); 9172 } 9173 }; 9174 9175 template<> 9176 struct LambdaInvoker<void> { 9177 template<typename L, typename ArgType> 9178 static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult { 9179 lambda( arg ); 9180 return ParserResult::ok( ParseResultType::Matched ); 9181 } 9182 }; 9183 9184 template<typename ArgType, typename L> 9185 inline auto invokeLambda( L const &lambda, std::string const &arg ) -> ParserResult { 9186 ArgType temp{}; 9187 auto result = convertInto( arg, temp ); 9188 return !result 9189 ? result 9190 : LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( lambda, temp ); 9191 } 9192 9193 template<typename L> 9194 struct BoundLambda : BoundValueRefBase { 9195 L m_lambda; 9196 9197 static_assert( UnaryLambdaTraits<L>::isValid, "Supplied lambda must take exactly one argument" ); 9198 explicit BoundLambda( L const &lambda ) : m_lambda( lambda ) {} 9199 9200 auto setValue( std::string const &arg ) -> ParserResult override { 9201 return invokeLambda<typename UnaryLambdaTraits<L>::ArgType>( m_lambda, arg ); 9202 } 9203 }; 9204 9205 template<typename L> 9206 struct BoundFlagLambda : BoundFlagRefBase { 9207 L m_lambda; 9208 9209 static_assert( UnaryLambdaTraits<L>::isValid, "Supplied lambda must take exactly one argument" ); 9210 static_assert( std::is_same<typename UnaryLambdaTraits<L>::ArgType, bool>::value, "flags must be boolean" ); 9211 9212 explicit BoundFlagLambda( L const &lambda ) : m_lambda( lambda ) {} 9213 9214 auto setFlag( bool flag ) -> ParserResult override { 9215 return LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( m_lambda, flag ); 9216 } 9217 }; 9218 9219 enum class Optionality { Optional, Required }; 9220 9221 struct Parser; 9222 9223 class ParserBase { 9224 public: 9225 virtual ~ParserBase() = default; 9226 virtual auto validate() const -> Result { return Result::ok(); } 9227 virtual auto parse( std::string const& exeName, TokenStream const &tokens) const -> InternalParseResult = 0; 9228 virtual auto cardinality() const -> size_t { return 1; } 9229 9230 auto parse( Args const &args ) const -> InternalParseResult { 9231 return parse( args.exeName(), TokenStream( args ) ); 9232 } 9233 }; 9234 9235 template<typename DerivedT> 9236 class ComposableParserImpl : public ParserBase { 9237 public: 9238 template<typename T> 9239 auto operator|( T const &other ) const -> Parser; 9240 9241 template<typename T> 9242 auto operator+( T const &other ) const -> Parser; 9243 }; 9244 9245 // Common code and state for Args and Opts 9246 template<typename DerivedT> 9247 class ParserRefImpl : public ComposableParserImpl<DerivedT> { 9248 protected: 9249 Optionality m_optionality = Optionality::Optional; 9250 std::shared_ptr<BoundRef> m_ref; 9251 std::string m_hint; 9252 std::string m_description; 9253 9254 explicit ParserRefImpl( std::shared_ptr<BoundRef> const &ref ) : m_ref( ref ) {} 9255 9256 public: 9257 template<typename T> 9258 ParserRefImpl( T &ref, std::string const &hint ) 9259 : m_ref( std::make_shared<BoundValueRef<T>>( ref ) ), 9260 m_hint( hint ) 9261 {} 9262 9263 template<typename LambdaT> 9264 ParserRefImpl( LambdaT const &ref, std::string const &hint ) 9265 : m_ref( std::make_shared<BoundLambda<LambdaT>>( ref ) ), 9266 m_hint(hint) 9267 {} 9268 9269 auto operator()( std::string const &description ) -> DerivedT & { 9270 m_description = description; 9271 return static_cast<DerivedT &>( *this ); 9272 } 9273 9274 auto optional() -> DerivedT & { 9275 m_optionality = Optionality::Optional; 9276 return static_cast<DerivedT &>( *this ); 9277 }; 9278 9279 auto required() -> DerivedT & { 9280 m_optionality = Optionality::Required; 9281 return static_cast<DerivedT &>( *this ); 9282 }; 9283 9284 auto isOptional() const -> bool { 9285 return m_optionality == Optionality::Optional; 9286 } 9287 9288 auto cardinality() const -> size_t override { 9289 if( m_ref->isContainer() ) 9290 return 0; 9291 else 9292 return 1; 9293 } 9294 9295 auto hint() const -> std::string { return m_hint; } 9296 }; 9297 9298 class ExeName : public ComposableParserImpl<ExeName> { 9299 std::shared_ptr<std::string> m_name; 9300 std::shared_ptr<BoundValueRefBase> m_ref; 9301 9302 template<typename LambdaT> 9303 static auto makeRef(LambdaT const &lambda) -> std::shared_ptr<BoundValueRefBase> { 9304 return std::make_shared<BoundLambda<LambdaT>>( lambda) ; 9305 } 9306 9307 public: 9308 ExeName() : m_name( std::make_shared<std::string>( "<executable>" ) ) {} 9309 9310 explicit ExeName( std::string &ref ) : ExeName() { 9311 m_ref = std::make_shared<BoundValueRef<std::string>>( ref ); 9312 } 9313 9314 template<typename LambdaT> 9315 explicit ExeName( LambdaT const& lambda ) : ExeName() { 9316 m_ref = std::make_shared<BoundLambda<LambdaT>>( lambda ); 9317 } 9318 9319 // The exe name is not parsed out of the normal tokens, but is handled specially 9320 auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override { 9321 return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) ); 9322 } 9323 9324 auto name() const -> std::string { return *m_name; } 9325 auto set( std::string const& newName ) -> ParserResult { 9326 9327 auto lastSlash = newName.find_last_of( "\\/" ); 9328 auto filename = ( lastSlash == std::string::npos ) 9329 ? newName 9330 : newName.substr( lastSlash+1 ); 9331 9332 *m_name = filename; 9333 if( m_ref ) 9334 return m_ref->setValue( filename ); 9335 else 9336 return ParserResult::ok( ParseResultType::Matched ); 9337 } 9338 }; 9339 9340 class Arg : public ParserRefImpl<Arg> { 9341 public: 9342 using ParserRefImpl::ParserRefImpl; 9343 9344 auto parse( std::string const &, TokenStream const &tokens ) const -> InternalParseResult override { 9345 auto validationResult = validate(); 9346 if( !validationResult ) 9347 return InternalParseResult( validationResult ); 9348 9349 auto remainingTokens = tokens; 9350 auto const &token = *remainingTokens; 9351 if( token.type != TokenType::Argument ) 9352 return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) ); 9353 9354 assert( !m_ref->isFlag() ); 9355 auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() ); 9356 9357 auto result = valueRef->setValue( remainingTokens->token ); 9358 if( !result ) 9359 return InternalParseResult( result ); 9360 else 9361 return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) ); 9362 } 9363 }; 9364 9365 inline auto normaliseOpt( std::string const &optName ) -> std::string { 9366 #ifdef CATCH_PLATFORM_WINDOWS 9367 if( optName[0] == '/' ) 9368 return "-" + optName.substr( 1 ); 9369 else 9370 #endif 9371 return optName; 9372 } 9373 9374 class Opt : public ParserRefImpl<Opt> { 9375 protected: 9376 std::vector<std::string> m_optNames; 9377 9378 public: 9379 template<typename LambdaT> 9380 explicit Opt( LambdaT const &ref ) : ParserRefImpl( std::make_shared<BoundFlagLambda<LambdaT>>( ref ) ) {} 9381 9382 explicit Opt( bool &ref ) : ParserRefImpl( std::make_shared<BoundFlagRef>( ref ) ) {} 9383 9384 template<typename LambdaT> 9385 Opt( LambdaT const &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {} 9386 9387 template<typename T> 9388 Opt( T &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {} 9389 9390 auto operator[]( std::string const &optName ) -> Opt & { 9391 m_optNames.push_back( optName ); 9392 return *this; 9393 } 9394 9395 auto getHelpColumns() const -> std::vector<HelpColumns> { 9396 std::ostringstream oss; 9397 bool first = true; 9398 for( auto const &opt : m_optNames ) { 9399 if (first) 9400 first = false; 9401 else 9402 oss << ", "; 9403 oss << opt; 9404 } 9405 if( !m_hint.empty() ) 9406 oss << " <" << m_hint << ">"; 9407 return { { oss.str(), m_description } }; 9408 } 9409 9410 auto isMatch( std::string const &optToken ) const -> bool { 9411 auto normalisedToken = normaliseOpt( optToken ); 9412 for( auto const &name : m_optNames ) { 9413 if( normaliseOpt( name ) == normalisedToken ) 9414 return true; 9415 } 9416 return false; 9417 } 9418 9419 using ParserBase::parse; 9420 9421 auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override { 9422 auto validationResult = validate(); 9423 if( !validationResult ) 9424 return InternalParseResult( validationResult ); 9425 9426 auto remainingTokens = tokens; 9427 if( remainingTokens && remainingTokens->type == TokenType::Option ) { 9428 auto const &token = *remainingTokens; 9429 if( isMatch(token.token ) ) { 9430 if( m_ref->isFlag() ) { 9431 auto flagRef = static_cast<detail::BoundFlagRefBase*>( m_ref.get() ); 9432 auto result = flagRef->setFlag( true ); 9433 if( !result ) 9434 return InternalParseResult( result ); 9435 if( result.value() == ParseResultType::ShortCircuitAll ) 9436 return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) ); 9437 } else { 9438 auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() ); 9439 ++remainingTokens; 9440 if( !remainingTokens ) 9441 return InternalParseResult::runtimeError( "Expected argument following " + token.token ); 9442 auto const &argToken = *remainingTokens; 9443 if( argToken.type != TokenType::Argument ) 9444 return InternalParseResult::runtimeError( "Expected argument following " + token.token ); 9445 auto result = valueRef->setValue( argToken.token ); 9446 if( !result ) 9447 return InternalParseResult( result ); 9448 if( result.value() == ParseResultType::ShortCircuitAll ) 9449 return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) ); 9450 } 9451 return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) ); 9452 } 9453 } 9454 return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) ); 9455 } 9456 9457 auto validate() const -> Result override { 9458 if( m_optNames.empty() ) 9459 return Result::logicError( "No options supplied to Opt" ); 9460 for( auto const &name : m_optNames ) { 9461 if( name.empty() ) 9462 return Result::logicError( "Option name cannot be empty" ); 9463 #ifdef CATCH_PLATFORM_WINDOWS 9464 if( name[0] != '-' && name[0] != '/' ) 9465 return Result::logicError( "Option name must begin with '-' or '/'" ); 9466 #else 9467 if( name[0] != '-' ) 9468 return Result::logicError( "Option name must begin with '-'" ); 9469 #endif 9470 } 9471 return ParserRefImpl::validate(); 9472 } 9473 }; 9474 9475 struct Help : Opt { 9476 Help( bool &showHelpFlag ) 9477 : Opt([&]( bool flag ) { 9478 showHelpFlag = flag; 9479 return ParserResult::ok( ParseResultType::ShortCircuitAll ); 9480 }) 9481 { 9482 static_cast<Opt &>( *this ) 9483 ("display usage information") 9484 ["-?"]["-h"]["--help"] 9485 .optional(); 9486 } 9487 }; 9488 9489 struct Parser : ParserBase { 9490 9491 mutable ExeName m_exeName; 9492 std::vector<Opt> m_options; 9493 std::vector<Arg> m_args; 9494 9495 auto operator|=( ExeName const &exeName ) -> Parser & { 9496 m_exeName = exeName; 9497 return *this; 9498 } 9499 9500 auto operator|=( Arg const &arg ) -> Parser & { 9501 m_args.push_back(arg); 9502 return *this; 9503 } 9504 9505 auto operator|=( Opt const &opt ) -> Parser & { 9506 m_options.push_back(opt); 9507 return *this; 9508 } 9509 9510 auto operator|=( Parser const &other ) -> Parser & { 9511 m_options.insert(m_options.end(), other.m_options.begin(), other.m_options.end()); 9512 m_args.insert(m_args.end(), other.m_args.begin(), other.m_args.end()); 9513 return *this; 9514 } 9515 9516 template<typename T> 9517 auto operator|( T const &other ) const -> Parser { 9518 return Parser( *this ) |= other; 9519 } 9520 9521 // Forward deprecated interface with '+' instead of '|' 9522 template<typename T> 9523 auto operator+=( T const &other ) -> Parser & { return operator|=( other ); } 9524 template<typename T> 9525 auto operator+( T const &other ) const -> Parser { return operator|( other ); } 9526 9527 auto getHelpColumns() const -> std::vector<HelpColumns> { 9528 std::vector<HelpColumns> cols; 9529 for (auto const &o : m_options) { 9530 auto childCols = o.getHelpColumns(); 9531 cols.insert( cols.end(), childCols.begin(), childCols.end() ); 9532 } 9533 return cols; 9534 } 9535 9536 void writeToStream( std::ostream &os ) const { 9537 if (!m_exeName.name().empty()) { 9538 os << "usage:\n" << " " << m_exeName.name() << " "; 9539 bool required = true, first = true; 9540 for( auto const &arg : m_args ) { 9541 if (first) 9542 first = false; 9543 else 9544 os << " "; 9545 if( arg.isOptional() && required ) { 9546 os << "["; 9547 required = false; 9548 } 9549 os << "<" << arg.hint() << ">"; 9550 if( arg.cardinality() == 0 ) 9551 os << " ... "; 9552 } 9553 if( !required ) 9554 os << "]"; 9555 if( !m_options.empty() ) 9556 os << " options"; 9557 os << "\n\nwhere options are:" << std::endl; 9558 } 9559 9560 auto rows = getHelpColumns(); 9561 size_t consoleWidth = CATCH_CLARA_CONFIG_CONSOLE_WIDTH; 9562 size_t optWidth = 0; 9563 for( auto const &cols : rows ) 9564 optWidth = (std::max)(optWidth, cols.left.size() + 2); 9565 9566 optWidth = (std::min)(optWidth, consoleWidth/2); 9567 9568 for( auto const &cols : rows ) { 9569 auto row = 9570 TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) + 9571 TextFlow::Spacer(4) + 9572 TextFlow::Column( cols.right ).width( consoleWidth - 7 - optWidth ); 9573 os << row << std::endl; 9574 } 9575 } 9576 9577 friend auto operator<<( std::ostream &os, Parser const &parser ) -> std::ostream& { 9578 parser.writeToStream( os ); 9579 return os; 9580 } 9581 9582 auto validate() const -> Result override { 9583 for( auto const &opt : m_options ) { 9584 auto result = opt.validate(); 9585 if( !result ) 9586 return result; 9587 } 9588 for( auto const &arg : m_args ) { 9589 auto result = arg.validate(); 9590 if( !result ) 9591 return result; 9592 } 9593 return Result::ok(); 9594 } 9595 9596 using ParserBase::parse; 9597 9598 auto parse( std::string const& exeName, TokenStream const &tokens ) const -> InternalParseResult override { 9599 9600 struct ParserInfo { 9601 ParserBase const* parser = nullptr; 9602 size_t count = 0; 9603 }; 9604 const size_t totalParsers = m_options.size() + m_args.size(); 9605 assert( totalParsers < 512 ); 9606 // ParserInfo parseInfos[totalParsers]; // <-- this is what we really want to do 9607 ParserInfo parseInfos[512]; 9608 9609 { 9610 size_t i = 0; 9611 for (auto const &opt : m_options) parseInfos[i++].parser = &opt; 9612 for (auto const &arg : m_args) parseInfos[i++].parser = &arg; 9613 } 9614 9615 m_exeName.set( exeName ); 9616 9617 auto result = InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) ); 9618 while( result.value().remainingTokens() ) { 9619 bool tokenParsed = false; 9620 9621 for( size_t i = 0; i < totalParsers; ++i ) { 9622 auto& parseInfo = parseInfos[i]; 9623 if( parseInfo.parser->cardinality() == 0 || parseInfo.count < parseInfo.parser->cardinality() ) { 9624 result = parseInfo.parser->parse(exeName, result.value().remainingTokens()); 9625 if (!result) 9626 return result; 9627 if (result.value().type() != ParseResultType::NoMatch) { 9628 tokenParsed = true; 9629 ++parseInfo.count; 9630 break; 9631 } 9632 } 9633 } 9634 9635 if( result.value().type() == ParseResultType::ShortCircuitAll ) 9636 return result; 9637 if( !tokenParsed ) 9638 return InternalParseResult::runtimeError( "Unrecognised token: " + result.value().remainingTokens()->token ); 9639 } 9640 // !TBD Check missing required options 9641 return result; 9642 } 9643 }; 9644 9645 template<typename DerivedT> 9646 template<typename T> 9647 auto ComposableParserImpl<DerivedT>::operator|( T const &other ) const -> Parser { 9648 return Parser() | static_cast<DerivedT const &>( *this ) | other; 9649 } 9650 } // namespace detail 9651 9652 // A Combined parser 9653 using detail::Parser; 9654 9655 // A parser for options 9656 using detail::Opt; 9657 9658 // A parser for arguments 9659 using detail::Arg; 9660 9661 // Wrapper for argc, argv from main() 9662 using detail::Args; 9663 9664 // Specifies the name of the executable 9665 using detail::ExeName; 9666 9667 // Convenience wrapper for option parser that specifies the help option 9668 using detail::Help; 9669 9670 // enum of result types from a parse 9671 using detail::ParseResultType; 9672 9673 // Result type for parser operation 9674 using detail::ParserResult; 9675 9676 }} // namespace Catch::clara 9677 9678 // end clara.hpp 9679 #ifdef __clang__ 9680 #pragma clang diagnostic pop 9681 #endif 9682 9683 // Restore Clara's value for console width, if present 9684 #ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH 9685 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH 9686 #undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH 9687 #endif 9688 9689 // end catch_clara.h 9690 namespace Catch { 9691 9692 clara::Parser makeCommandLineParser( ConfigData& config ); 9693 9694 } // end namespace Catch 9695 9696 // end catch_commandline.h 9697 #include <fstream> 9698 #include <ctime> 9699 9700 namespace Catch { 9701 9702 clara::Parser makeCommandLineParser( ConfigData& config ) { 9703 9704 using namespace clara; 9705 9706 auto const setWarning = [&]( std::string const& warning ) { 9707 auto warningSet = [&]() { 9708 if( warning == "NoAssertions" ) 9709 return WarnAbout::NoAssertions; 9710 9711 if ( warning == "NoTests" ) 9712 return WarnAbout::NoTests; 9713 9714 return WarnAbout::Nothing; 9715 }(); 9716 9717 if (warningSet == WarnAbout::Nothing) 9718 return ParserResult::runtimeError( "Unrecognised warning: '" + warning + "'" ); 9719 config.warnings = static_cast<WarnAbout::What>( config.warnings | warningSet ); 9720 return ParserResult::ok( ParseResultType::Matched ); 9721 }; 9722 auto const loadTestNamesFromFile = [&]( std::string const& filename ) { 9723 std::ifstream f( filename.c_str() ); 9724 if( !f.is_open() ) 9725 return ParserResult::runtimeError( "Unable to load input file: '" + filename + "'" ); 9726 9727 std::string line; 9728 while( std::getline( f, line ) ) { 9729 line = trim(line); 9730 if( !line.empty() && !startsWith( line, '#' ) ) { 9731 if( !startsWith( line, '"' ) ) 9732 line = '"' + line + '"'; 9733 config.testsOrTags.push_back( line ); 9734 config.testsOrTags.emplace_back( "," ); 9735 } 9736 } 9737 //Remove comma in the end 9738 if(!config.testsOrTags.empty()) 9739 config.testsOrTags.erase( config.testsOrTags.end()-1 ); 9740 9741 return ParserResult::ok( ParseResultType::Matched ); 9742 }; 9743 auto const setTestOrder = [&]( std::string const& order ) { 9744 if( startsWith( "declared", order ) ) 9745 config.runOrder = RunTests::InDeclarationOrder; 9746 else if( startsWith( "lexical", order ) ) 9747 config.runOrder = RunTests::InLexicographicalOrder; 9748 else if( startsWith( "random", order ) ) 9749 config.runOrder = RunTests::InRandomOrder; 9750 else 9751 return clara::ParserResult::runtimeError( "Unrecognised ordering: '" + order + "'" ); 9752 return ParserResult::ok( ParseResultType::Matched ); 9753 }; 9754 auto const setRngSeed = [&]( std::string const& seed ) { 9755 if( seed != "time" ) 9756 return clara::detail::convertInto( seed, config.rngSeed ); 9757 config.rngSeed = static_cast<unsigned int>( std::time(nullptr) ); 9758 return ParserResult::ok( ParseResultType::Matched ); 9759 }; 9760 auto const setColourUsage = [&]( std::string const& useColour ) { 9761 auto mode = toLower( useColour ); 9762 9763 if( mode == "yes" ) 9764 config.useColour = UseColour::Yes; 9765 else if( mode == "no" ) 9766 config.useColour = UseColour::No; 9767 else if( mode == "auto" ) 9768 config.useColour = UseColour::Auto; 9769 else 9770 return ParserResult::runtimeError( "colour mode must be one of: auto, yes or no. '" + useColour + "' not recognised" ); 9771 return ParserResult::ok( ParseResultType::Matched ); 9772 }; 9773 auto const setWaitForKeypress = [&]( std::string const& keypress ) { 9774 auto keypressLc = toLower( keypress ); 9775 if (keypressLc == "never") 9776 config.waitForKeypress = WaitForKeypress::Never; 9777 else if( keypressLc == "start" ) 9778 config.waitForKeypress = WaitForKeypress::BeforeStart; 9779 else if( keypressLc == "exit" ) 9780 config.waitForKeypress = WaitForKeypress::BeforeExit; 9781 else if( keypressLc == "both" ) 9782 config.waitForKeypress = WaitForKeypress::BeforeStartAndExit; 9783 else 9784 return ParserResult::runtimeError( "keypress argument must be one of: never, start, exit or both. '" + keypress + "' not recognised" ); 9785 return ParserResult::ok( ParseResultType::Matched ); 9786 }; 9787 auto const setVerbosity = [&]( std::string const& verbosity ) { 9788 auto lcVerbosity = toLower( verbosity ); 9789 if( lcVerbosity == "quiet" ) 9790 config.verbosity = Verbosity::Quiet; 9791 else if( lcVerbosity == "normal" ) 9792 config.verbosity = Verbosity::Normal; 9793 else if( lcVerbosity == "high" ) 9794 config.verbosity = Verbosity::High; 9795 else 9796 return ParserResult::runtimeError( "Unrecognised verbosity, '" + verbosity + "'" ); 9797 return ParserResult::ok( ParseResultType::Matched ); 9798 }; 9799 auto const setReporter = [&]( std::string const& reporter ) { 9800 IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); 9801 9802 auto lcReporter = toLower( reporter ); 9803 auto result = factories.find( lcReporter ); 9804 9805 if( factories.end() != result ) 9806 config.reporterName = lcReporter; 9807 else 9808 return ParserResult::runtimeError( "Unrecognized reporter, '" + reporter + "'. Check available with --list-reporters" ); 9809 return ParserResult::ok( ParseResultType::Matched ); 9810 }; 9811 9812 auto cli 9813 = ExeName( config.processName ) 9814 | Help( config.showHelp ) 9815 | Opt( config.listTests ) 9816 ["-l"]["--list-tests"] 9817 ( "list all/matching test cases" ) 9818 | Opt( config.listTags ) 9819 ["-t"]["--list-tags"] 9820 ( "list all/matching tags" ) 9821 | Opt( config.showSuccessfulTests ) 9822 ["-s"]["--success"] 9823 ( "include successful tests in output" ) 9824 | Opt( config.shouldDebugBreak ) 9825 ["-b"]["--break"] 9826 ( "break into debugger on failure" ) 9827 | Opt( config.noThrow ) 9828 ["-e"]["--nothrow"] 9829 ( "skip exception tests" ) 9830 | Opt( config.showInvisibles ) 9831 ["-i"]["--invisibles"] 9832 ( "show invisibles (tabs, newlines)" ) 9833 | Opt( config.outputFilename, "filename" ) 9834 ["-o"]["--out"] 9835 ( "output filename" ) 9836 | Opt( setReporter, "name" ) 9837 ["-r"]["--reporter"] 9838 ( "reporter to use (defaults to console)" ) 9839 | Opt( config.name, "name" ) 9840 ["-n"]["--name"] 9841 ( "suite name" ) 9842 | Opt( [&]( bool ){ config.abortAfter = 1; } ) 9843 ["-a"]["--abort"] 9844 ( "abort at first failure" ) 9845 | Opt( [&]( int x ){ config.abortAfter = x; }, "no. failures" ) 9846 ["-x"]["--abortx"] 9847 ( "abort after x failures" ) 9848 | Opt( setWarning, "warning name" ) 9849 ["-w"]["--warn"] 9850 ( "enable warnings" ) 9851 | Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" ) 9852 ["-d"]["--durations"] 9853 ( "show test durations" ) 9854 | Opt( config.minDuration, "seconds" ) 9855 ["-D"]["--min-duration"] 9856 ( "show test durations for tests taking at least the given number of seconds" ) 9857 | Opt( loadTestNamesFromFile, "filename" ) 9858 ["-f"]["--input-file"] 9859 ( "load test names to run from a file" ) 9860 | Opt( config.filenamesAsTags ) 9861 ["-#"]["--filenames-as-tags"] 9862 ( "adds a tag for the filename" ) 9863 | Opt( config.sectionsToRun, "section name" ) 9864 ["-c"]["--section"] 9865 ( "specify section to run" ) 9866 | Opt( setVerbosity, "quiet|normal|high" ) 9867 ["-v"]["--verbosity"] 9868 ( "set output verbosity" ) 9869 | Opt( config.listTestNamesOnly ) 9870 ["--list-test-names-only"] 9871 ( "list all/matching test cases names only" ) 9872 | Opt( config.listReporters ) 9873 ["--list-reporters"] 9874 ( "list all reporters" ) 9875 | Opt( setTestOrder, "decl|lex|rand" ) 9876 ["--order"] 9877 ( "test case order (defaults to decl)" ) 9878 | Opt( setRngSeed, "'time'|number" ) 9879 ["--rng-seed"] 9880 ( "set a specific seed for random numbers" ) 9881 | Opt( setColourUsage, "yes|no" ) 9882 ["--use-colour"] 9883 ( "should output be colourised" ) 9884 | Opt( config.libIdentify ) 9885 ["--libidentify"] 9886 ( "report name and version according to libidentify standard" ) 9887 | Opt( setWaitForKeypress, "never|start|exit|both" ) 9888 ["--wait-for-keypress"] 9889 ( "waits for a keypress before exiting" ) 9890 | Opt( config.benchmarkSamples, "samples" ) 9891 ["--benchmark-samples"] 9892 ( "number of samples to collect (default: 100)" ) 9893 | Opt( config.benchmarkResamples, "resamples" ) 9894 ["--benchmark-resamples"] 9895 ( "number of resamples for the bootstrap (default: 100000)" ) 9896 | Opt( config.benchmarkConfidenceInterval, "confidence interval" ) 9897 ["--benchmark-confidence-interval"] 9898 ( "confidence interval for the bootstrap (between 0 and 1, default: 0.95)" ) 9899 | Opt( config.benchmarkNoAnalysis ) 9900 ["--benchmark-no-analysis"] 9901 ( "perform only measurements; do not perform any analysis" ) 9902 | Opt( config.benchmarkWarmupTime, "benchmarkWarmupTime" ) 9903 ["--benchmark-warmup-time"] 9904 ( "amount of time in milliseconds spent on warming up each test (default: 100)" ) 9905 | Arg( config.testsOrTags, "test name|pattern|tags" ) 9906 ( "which test or tests to use" ); 9907 9908 return cli; 9909 } 9910 9911 } // end namespace Catch 9912 // end catch_commandline.cpp 9913 // start catch_common.cpp 9914 9915 #include <cstring> 9916 #include <ostream> 9917 9918 namespace Catch { 9919 9920 bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const noexcept { 9921 return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0); 9922 } 9923 bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const noexcept { 9924 // We can assume that the same file will usually have the same pointer. 9925 // Thus, if the pointers are the same, there is no point in calling the strcmp 9926 return line < other.line || ( line == other.line && file != other.file && (std::strcmp(file, other.file) < 0)); 9927 } 9928 9929 std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { 9930 #ifndef __GNUG__ 9931 os << info.file << '(' << info.line << ')'; 9932 #else 9933 os << info.file << ':' << info.line; 9934 #endif 9935 return os; 9936 } 9937 9938 std::string StreamEndStop::operator+() const { 9939 return std::string(); 9940 } 9941 9942 NonCopyable::NonCopyable() = default; 9943 NonCopyable::~NonCopyable() = default; 9944 9945 } 9946 // end catch_common.cpp 9947 // start catch_config.cpp 9948 9949 namespace Catch { 9950 9951 Config::Config( ConfigData const& data ) 9952 : m_data( data ), 9953 m_stream( openStream() ) 9954 { 9955 // We need to trim filter specs to avoid trouble with superfluous 9956 // whitespace (esp. important for bdd macros, as those are manually 9957 // aligned with whitespace). 9958 9959 for (auto& elem : m_data.testsOrTags) { 9960 elem = trim(elem); 9961 } 9962 for (auto& elem : m_data.sectionsToRun) { 9963 elem = trim(elem); 9964 } 9965 9966 TestSpecParser parser(ITagAliasRegistry::get()); 9967 if (!m_data.testsOrTags.empty()) { 9968 m_hasTestFilters = true; 9969 for (auto const& testOrTags : m_data.testsOrTags) { 9970 parser.parse(testOrTags); 9971 } 9972 } 9973 m_testSpec = parser.testSpec(); 9974 } 9975 9976 std::string const& Config::getFilename() const { 9977 return m_data.outputFilename ; 9978 } 9979 9980 bool Config::listTests() const { return m_data.listTests; } 9981 bool Config::listTestNamesOnly() const { return m_data.listTestNamesOnly; } 9982 bool Config::listTags() const { return m_data.listTags; } 9983 bool Config::listReporters() const { return m_data.listReporters; } 9984 9985 std::string Config::getProcessName() const { return m_data.processName; } 9986 std::string const& Config::getReporterName() const { return m_data.reporterName; } 9987 9988 std::vector<std::string> const& Config::getTestsOrTags() const { return m_data.testsOrTags; } 9989 std::vector<std::string> const& Config::getSectionsToRun() const { return m_data.sectionsToRun; } 9990 9991 TestSpec const& Config::testSpec() const { return m_testSpec; } 9992 bool Config::hasTestFilters() const { return m_hasTestFilters; } 9993 9994 bool Config::showHelp() const { return m_data.showHelp; } 9995 9996 // IConfig interface 9997 bool Config::allowThrows() const { return !m_data.noThrow; } 9998 std::ostream& Config::stream() const { return m_stream->stream(); } 9999 std::string Config::name() const { return m_data.name.empty() ? m_data.processName : m_data.name; } 10000 bool Config::includeSuccessfulResults() const { return m_data.showSuccessfulTests; } 10001 bool Config::warnAboutMissingAssertions() const { return !!(m_data.warnings & WarnAbout::NoAssertions); } 10002 bool Config::warnAboutNoTests() const { return !!(m_data.warnings & WarnAbout::NoTests); } 10003 ShowDurations::OrNot Config::showDurations() const { return m_data.showDurations; } 10004 double Config::minDuration() const { return m_data.minDuration; } 10005 RunTests::InWhatOrder Config::runOrder() const { return m_data.runOrder; } 10006 unsigned int Config::rngSeed() const { return m_data.rngSeed; } 10007 UseColour::YesOrNo Config::useColour() const { return m_data.useColour; } 10008 bool Config::shouldDebugBreak() const { return m_data.shouldDebugBreak; } 10009 int Config::abortAfter() const { return m_data.abortAfter; } 10010 bool Config::showInvisibles() const { return m_data.showInvisibles; } 10011 Verbosity Config::verbosity() const { return m_data.verbosity; } 10012 10013 bool Config::benchmarkNoAnalysis() const { return m_data.benchmarkNoAnalysis; } 10014 int Config::benchmarkSamples() const { return m_data.benchmarkSamples; } 10015 double Config::benchmarkConfidenceInterval() const { return m_data.benchmarkConfidenceInterval; } 10016 unsigned int Config::benchmarkResamples() const { return m_data.benchmarkResamples; } 10017 std::chrono::milliseconds Config::benchmarkWarmupTime() const { return std::chrono::milliseconds(m_data.benchmarkWarmupTime); } 10018 10019 IStream const* Config::openStream() { 10020 return Catch::makeStream(m_data.outputFilename); 10021 } 10022 10023 } // end namespace Catch 10024 // end catch_config.cpp 10025 // start catch_console_colour.cpp 10026 10027 #if defined(__clang__) 10028 # pragma clang diagnostic push 10029 # pragma clang diagnostic ignored "-Wexit-time-destructors" 10030 #endif 10031 10032 // start catch_errno_guard.h 10033 10034 namespace Catch { 10035 10036 class ErrnoGuard { 10037 public: 10038 ErrnoGuard(); 10039 ~ErrnoGuard(); 10040 private: 10041 int m_oldErrno; 10042 }; 10043 10044 } 10045 10046 // end catch_errno_guard.h 10047 // start catch_windows_h_proxy.h 10048 10049 10050 #if defined(CATCH_PLATFORM_WINDOWS) 10051 10052 #if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX) 10053 # define CATCH_DEFINED_NOMINMAX 10054 # define NOMINMAX 10055 #endif 10056 #if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN) 10057 # define CATCH_DEFINED_WIN32_LEAN_AND_MEAN 10058 # define WIN32_LEAN_AND_MEAN 10059 #endif 10060 10061 #ifdef __AFXDLL 10062 #include <AfxWin.h> 10063 #else 10064 #include <windows.h> 10065 #endif 10066 10067 #ifdef CATCH_DEFINED_NOMINMAX 10068 # undef NOMINMAX 10069 #endif 10070 #ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN 10071 # undef WIN32_LEAN_AND_MEAN 10072 #endif 10073 10074 #endif // defined(CATCH_PLATFORM_WINDOWS) 10075 10076 // end catch_windows_h_proxy.h 10077 #include <sstream> 10078 10079 namespace Catch { 10080 namespace { 10081 10082 struct IColourImpl { 10083 virtual ~IColourImpl() = default; 10084 virtual void use( Colour::Code _colourCode ) = 0; 10085 }; 10086 10087 struct NoColourImpl : IColourImpl { 10088 void use( Colour::Code ) override {} 10089 10090 static IColourImpl* instance() { 10091 static NoColourImpl s_instance; 10092 return &s_instance; 10093 } 10094 }; 10095 10096 } // anon namespace 10097 } // namespace Catch 10098 10099 #if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI ) 10100 # ifdef CATCH_PLATFORM_WINDOWS 10101 # define CATCH_CONFIG_COLOUR_WINDOWS 10102 # else 10103 # define CATCH_CONFIG_COLOUR_ANSI 10104 # endif 10105 #endif 10106 10107 #if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) ///////////////////////////////////////// 10108 10109 namespace Catch { 10110 namespace { 10111 10112 class Win32ColourImpl : public IColourImpl { 10113 public: 10114 Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) ) 10115 { 10116 CONSOLE_SCREEN_BUFFER_INFO csbiInfo; 10117 GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo ); 10118 originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY ); 10119 originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ); 10120 } 10121 10122 void use( Colour::Code _colourCode ) override { 10123 switch( _colourCode ) { 10124 case Colour::None: return setTextAttribute( originalForegroundAttributes ); 10125 case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); 10126 case Colour::Red: return setTextAttribute( FOREGROUND_RED ); 10127 case Colour::Green: return setTextAttribute( FOREGROUND_GREEN ); 10128 case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE ); 10129 case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN ); 10130 case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN ); 10131 case Colour::Grey: return setTextAttribute( 0 ); 10132 10133 case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY ); 10134 case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED ); 10135 case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN ); 10136 case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); 10137 case Colour::BrightYellow: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN ); 10138 10139 case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" ); 10140 10141 default: 10142 CATCH_ERROR( "Unknown colour requested" ); 10143 } 10144 } 10145 10146 private: 10147 void setTextAttribute( WORD _textAttribute ) { 10148 SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes ); 10149 } 10150 HANDLE stdoutHandle; 10151 WORD originalForegroundAttributes; 10152 WORD originalBackgroundAttributes; 10153 }; 10154 10155 IColourImpl* platformColourInstance() { 10156 static Win32ColourImpl s_instance; 10157 10158 IConfigPtr config = getCurrentContext().getConfig(); 10159 UseColour::YesOrNo colourMode = config 10160 ? config->useColour() 10161 : UseColour::Auto; 10162 if( colourMode == UseColour::Auto ) 10163 colourMode = UseColour::Yes; 10164 return colourMode == UseColour::Yes 10165 ? &s_instance 10166 : NoColourImpl::instance(); 10167 } 10168 10169 } // end anon namespace 10170 } // end namespace Catch 10171 10172 #elif defined( CATCH_CONFIG_COLOUR_ANSI ) ////////////////////////////////////// 10173 10174 #include <unistd.h> 10175 10176 namespace Catch { 10177 namespace { 10178 10179 // use POSIX/ ANSI console terminal codes 10180 // Thanks to Adam Strzelecki for original contribution 10181 // (http://github.com/nanoant) 10182 // https://github.com/philsquared/Catch/pull/131 10183 class PosixColourImpl : public IColourImpl { 10184 public: 10185 void use( Colour::Code _colourCode ) override { 10186 switch( _colourCode ) { 10187 case Colour::None: 10188 case Colour::White: return setColour( "[0m" ); 10189 case Colour::Red: return setColour( "[0;31m" ); 10190 case Colour::Green: return setColour( "[0;32m" ); 10191 case Colour::Blue: return setColour( "[0;34m" ); 10192 case Colour::Cyan: return setColour( "[0;36m" ); 10193 case Colour::Yellow: return setColour( "[0;33m" ); 10194 case Colour::Grey: return setColour( "[1;30m" ); 10195 10196 case Colour::LightGrey: return setColour( "[0;37m" ); 10197 case Colour::BrightRed: return setColour( "[1;31m" ); 10198 case Colour::BrightGreen: return setColour( "[1;32m" ); 10199 case Colour::BrightWhite: return setColour( "[1;37m" ); 10200 case Colour::BrightYellow: return setColour( "[1;33m" ); 10201 10202 case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" ); 10203 default: CATCH_INTERNAL_ERROR( "Unknown colour requested" ); 10204 } 10205 } 10206 static IColourImpl* instance() { 10207 static PosixColourImpl s_instance; 10208 return &s_instance; 10209 } 10210 10211 private: 10212 void setColour( const char* _escapeCode ) { 10213 getCurrentContext().getConfig()->stream() 10214 << '\033' << _escapeCode; 10215 } 10216 }; 10217 10218 bool useColourOnPlatform() { 10219 return 10220 #if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE) 10221 !isDebuggerActive() && 10222 #endif 10223 #if !(defined(__DJGPP__) && defined(__STRICT_ANSI__)) 10224 isatty(STDOUT_FILENO) 10225 #else 10226 false 10227 #endif 10228 ; 10229 } 10230 IColourImpl* platformColourInstance() { 10231 ErrnoGuard guard; 10232 IConfigPtr config = getCurrentContext().getConfig(); 10233 UseColour::YesOrNo colourMode = config 10234 ? config->useColour() 10235 : UseColour::Auto; 10236 if( colourMode == UseColour::Auto ) 10237 colourMode = useColourOnPlatform() 10238 ? UseColour::Yes 10239 : UseColour::No; 10240 return colourMode == UseColour::Yes 10241 ? PosixColourImpl::instance() 10242 : NoColourImpl::instance(); 10243 } 10244 10245 } // end anon namespace 10246 } // end namespace Catch 10247 10248 #else // not Windows or ANSI /////////////////////////////////////////////// 10249 10250 namespace Catch { 10251 10252 static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); } 10253 10254 } // end namespace Catch 10255 10256 #endif // Windows/ ANSI/ None 10257 10258 namespace Catch { 10259 10260 Colour::Colour( Code _colourCode ) { use( _colourCode ); } 10261 Colour::Colour( Colour&& other ) noexcept { 10262 m_moved = other.m_moved; 10263 other.m_moved = true; 10264 } 10265 Colour& Colour::operator=( Colour&& other ) noexcept { 10266 m_moved = other.m_moved; 10267 other.m_moved = true; 10268 return *this; 10269 } 10270 10271 Colour::~Colour(){ if( !m_moved ) use( None ); } 10272 10273 void Colour::use( Code _colourCode ) { 10274 static IColourImpl* impl = platformColourInstance(); 10275 // Strictly speaking, this cannot possibly happen. 10276 // However, under some conditions it does happen (see #1626), 10277 // and this change is small enough that we can let practicality 10278 // triumph over purity in this case. 10279 if (impl != nullptr) { 10280 impl->use( _colourCode ); 10281 } 10282 } 10283 10284 std::ostream& operator << ( std::ostream& os, Colour const& ) { 10285 return os; 10286 } 10287 10288 } // end namespace Catch 10289 10290 #if defined(__clang__) 10291 # pragma clang diagnostic pop 10292 #endif 10293 10294 // end catch_console_colour.cpp 10295 // start catch_context.cpp 10296 10297 namespace Catch { 10298 10299 class Context : public IMutableContext, NonCopyable { 10300 10301 public: // IContext 10302 IResultCapture* getResultCapture() override { 10303 return m_resultCapture; 10304 } 10305 IRunner* getRunner() override { 10306 return m_runner; 10307 } 10308 10309 IConfigPtr const& getConfig() const override { 10310 return m_config; 10311 } 10312 10313 ~Context() override; 10314 10315 public: // IMutableContext 10316 void setResultCapture( IResultCapture* resultCapture ) override { 10317 m_resultCapture = resultCapture; 10318 } 10319 void setRunner( IRunner* runner ) override { 10320 m_runner = runner; 10321 } 10322 void setConfig( IConfigPtr const& config ) override { 10323 m_config = config; 10324 } 10325 10326 friend IMutableContext& getCurrentMutableContext(); 10327 10328 private: 10329 IConfigPtr m_config; 10330 IRunner* m_runner = nullptr; 10331 IResultCapture* m_resultCapture = nullptr; 10332 }; 10333 10334 IMutableContext *IMutableContext::currentContext = nullptr; 10335 10336 void IMutableContext::createContext() 10337 { 10338 currentContext = new Context(); 10339 } 10340 10341 void cleanUpContext() { 10342 delete IMutableContext::currentContext; 10343 IMutableContext::currentContext = nullptr; 10344 } 10345 IContext::~IContext() = default; 10346 IMutableContext::~IMutableContext() = default; 10347 Context::~Context() = default; 10348 10349 SimplePcg32& rng() { 10350 static SimplePcg32 s_rng; 10351 return s_rng; 10352 } 10353 10354 } 10355 // end catch_context.cpp 10356 // start catch_debug_console.cpp 10357 10358 // start catch_debug_console.h 10359 10360 #include <string> 10361 10362 namespace Catch { 10363 void writeToDebugConsole( std::string const& text ); 10364 } 10365 10366 // end catch_debug_console.h 10367 #if defined(CATCH_CONFIG_ANDROID_LOGWRITE) 10368 #include <android/log.h> 10369 10370 namespace Catch { 10371 void writeToDebugConsole( std::string const& text ) { 10372 __android_log_write( ANDROID_LOG_DEBUG, "Catch", text.c_str() ); 10373 } 10374 } 10375 10376 #elif defined(CATCH_PLATFORM_WINDOWS) 10377 10378 namespace Catch { 10379 void writeToDebugConsole( std::string const& text ) { 10380 ::OutputDebugStringA( text.c_str() ); 10381 } 10382 } 10383 10384 #else 10385 10386 namespace Catch { 10387 void writeToDebugConsole( std::string const& text ) { 10388 // !TBD: Need a version for Mac/ XCode and other IDEs 10389 Catch::cout() << text; 10390 } 10391 } 10392 10393 #endif // Platform 10394 // end catch_debug_console.cpp 10395 // start catch_debugger.cpp 10396 10397 #if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE) 10398 10399 # include <cassert> 10400 # include <sys/types.h> 10401 # include <unistd.h> 10402 # include <cstddef> 10403 # include <ostream> 10404 10405 #ifdef __apple_build_version__ 10406 // These headers will only compile with AppleClang (XCode) 10407 // For other compilers (Clang, GCC, ... ) we need to exclude them 10408 # include <sys/sysctl.h> 10409 #endif 10410 10411 namespace Catch { 10412 #ifdef __apple_build_version__ 10413 // The following function is taken directly from the following technical note: 10414 // https://developer.apple.com/library/archive/qa/qa1361/_index.html 10415 10416 // Returns true if the current process is being debugged (either 10417 // running under the debugger or has a debugger attached post facto). 10418 bool isDebuggerActive(){ 10419 int mib[4]; 10420 struct kinfo_proc info; 10421 std::size_t size; 10422 10423 // Initialize the flags so that, if sysctl fails for some bizarre 10424 // reason, we get a predictable result. 10425 10426 info.kp_proc.p_flag = 0; 10427 10428 // Initialize mib, which tells sysctl the info we want, in this case 10429 // we're looking for information about a specific process ID. 10430 10431 mib[0] = CTL_KERN; 10432 mib[1] = KERN_PROC; 10433 mib[2] = KERN_PROC_PID; 10434 mib[3] = getpid(); 10435 10436 // Call sysctl. 10437 10438 size = sizeof(info); 10439 if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, nullptr, 0) != 0 ) { 10440 Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; 10441 return false; 10442 } 10443 10444 // We're being debugged if the P_TRACED flag is set. 10445 10446 return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); 10447 } 10448 #else 10449 bool isDebuggerActive() { 10450 // We need to find another way to determine this for non-appleclang compilers on macOS 10451 return false; 10452 } 10453 #endif 10454 } // namespace Catch 10455 10456 #elif defined(CATCH_PLATFORM_LINUX) 10457 #include <fstream> 10458 #include <string> 10459 10460 namespace Catch{ 10461 // The standard POSIX way of detecting a debugger is to attempt to 10462 // ptrace() the process, but this needs to be done from a child and not 10463 // this process itself to still allow attaching to this process later 10464 // if wanted, so is rather heavy. Under Linux we have the PID of the 10465 // "debugger" (which doesn't need to be gdb, of course, it could also 10466 // be strace, for example) in /proc/$PID/status, so just get it from 10467 // there instead. 10468 bool isDebuggerActive(){ 10469 // Libstdc++ has a bug, where std::ifstream sets errno to 0 10470 // This way our users can properly assert over errno values 10471 ErrnoGuard guard; 10472 std::ifstream in("/proc/self/status"); 10473 for( std::string line; std::getline(in, line); ) { 10474 static const int PREFIX_LEN = 11; 10475 if( line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0 ) { 10476 // We're traced if the PID is not 0 and no other PID starts 10477 // with 0 digit, so it's enough to check for just a single 10478 // character. 10479 return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0'; 10480 } 10481 } 10482 10483 return false; 10484 } 10485 } // namespace Catch 10486 #elif defined(_MSC_VER) 10487 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); 10488 namespace Catch { 10489 bool isDebuggerActive() { 10490 return IsDebuggerPresent() != 0; 10491 } 10492 } 10493 #elif defined(__MINGW32__) 10494 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); 10495 namespace Catch { 10496 bool isDebuggerActive() { 10497 return IsDebuggerPresent() != 0; 10498 } 10499 } 10500 #else 10501 namespace Catch { 10502 bool isDebuggerActive() { return false; } 10503 } 10504 #endif // Platform 10505 // end catch_debugger.cpp 10506 // start catch_decomposer.cpp 10507 10508 namespace Catch { 10509 10510 ITransientExpression::~ITransientExpression() = default; 10511 10512 void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ) { 10513 if( lhs.size() + rhs.size() < 40 && 10514 lhs.find('\n') == std::string::npos && 10515 rhs.find('\n') == std::string::npos ) 10516 os << lhs << " " << op << " " << rhs; 10517 else 10518 os << lhs << "\n" << op << "\n" << rhs; 10519 } 10520 } 10521 // end catch_decomposer.cpp 10522 // start catch_enforce.cpp 10523 10524 #include <stdexcept> 10525 10526 namespace Catch { 10527 #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER) 10528 [[noreturn]] 10529 void throw_exception(std::exception const& e) { 10530 Catch::cerr() << "Catch will terminate because it needed to throw an exception.\n" 10531 << "The message was: " << e.what() << '\n'; 10532 std::terminate(); 10533 } 10534 #endif 10535 10536 [[noreturn]] 10537 void throw_logic_error(std::string const& msg) { 10538 throw_exception(std::logic_error(msg)); 10539 } 10540 10541 [[noreturn]] 10542 void throw_domain_error(std::string const& msg) { 10543 throw_exception(std::domain_error(msg)); 10544 } 10545 10546 [[noreturn]] 10547 void throw_runtime_error(std::string const& msg) { 10548 throw_exception(std::runtime_error(msg)); 10549 } 10550 10551 } // namespace Catch; 10552 // end catch_enforce.cpp 10553 // start catch_enum_values_registry.cpp 10554 // start catch_enum_values_registry.h 10555 10556 #include <vector> 10557 #include <memory> 10558 10559 namespace Catch { 10560 10561 namespace Detail { 10562 10563 std::unique_ptr<EnumInfo> makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ); 10564 10565 class EnumValuesRegistry : public IMutableEnumValuesRegistry { 10566 10567 std::vector<std::unique_ptr<EnumInfo>> m_enumInfos; 10568 10569 EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::vector<int> const& values) override; 10570 }; 10571 10572 std::vector<StringRef> parseEnums( StringRef enums ); 10573 10574 } // Detail 10575 10576 } // Catch 10577 10578 // end catch_enum_values_registry.h 10579 10580 #include <map> 10581 #include <cassert> 10582 10583 namespace Catch { 10584 10585 IMutableEnumValuesRegistry::~IMutableEnumValuesRegistry() {} 10586 10587 namespace Detail { 10588 10589 namespace { 10590 // Extracts the actual name part of an enum instance 10591 // In other words, it returns the Blue part of Bikeshed::Colour::Blue 10592 StringRef extractInstanceName(StringRef enumInstance) { 10593 // Find last occurrence of ":" 10594 size_t name_start = enumInstance.size(); 10595 while (name_start > 0 && enumInstance[name_start - 1] != ':') { 10596 --name_start; 10597 } 10598 return enumInstance.substr(name_start, enumInstance.size() - name_start); 10599 } 10600 } 10601 10602 std::vector<StringRef> parseEnums( StringRef enums ) { 10603 auto enumValues = splitStringRef( enums, ',' ); 10604 std::vector<StringRef> parsed; 10605 parsed.reserve( enumValues.size() ); 10606 for( auto const& enumValue : enumValues ) { 10607 parsed.push_back(trim(extractInstanceName(enumValue))); 10608 } 10609 return parsed; 10610 } 10611 10612 EnumInfo::~EnumInfo() {} 10613 10614 StringRef EnumInfo::lookup( int value ) const { 10615 for( auto const& valueToName : m_values ) { 10616 if( valueToName.first == value ) 10617 return valueToName.second; 10618 } 10619 return "{** unexpected enum value **}"_sr; 10620 } 10621 10622 std::unique_ptr<EnumInfo> makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ) { 10623 std::unique_ptr<EnumInfo> enumInfo( new EnumInfo ); 10624 enumInfo->m_name = enumName; 10625 enumInfo->m_values.reserve( values.size() ); 10626 10627 const auto valueNames = Catch::Detail::parseEnums( allValueNames ); 10628 assert( valueNames.size() == values.size() ); 10629 std::size_t i = 0; 10630 for( auto value : values ) 10631 enumInfo->m_values.emplace_back(value, valueNames[i++]); 10632 10633 return enumInfo; 10634 } 10635 10636 EnumInfo const& EnumValuesRegistry::registerEnum( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ) { 10637 m_enumInfos.push_back(makeEnumInfo(enumName, allValueNames, values)); 10638 return *m_enumInfos.back(); 10639 } 10640 10641 } // Detail 10642 } // Catch 10643 10644 // end catch_enum_values_registry.cpp 10645 // start catch_errno_guard.cpp 10646 10647 #include <cerrno> 10648 10649 namespace Catch { 10650 ErrnoGuard::ErrnoGuard():m_oldErrno(errno){} 10651 ErrnoGuard::~ErrnoGuard() { errno = m_oldErrno; } 10652 } 10653 // end catch_errno_guard.cpp 10654 // start catch_exception_translator_registry.cpp 10655 10656 // start catch_exception_translator_registry.h 10657 10658 #include <vector> 10659 #include <string> 10660 #include <memory> 10661 10662 namespace Catch { 10663 10664 class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { 10665 public: 10666 ~ExceptionTranslatorRegistry(); 10667 virtual void registerTranslator( const IExceptionTranslator* translator ); 10668 std::string translateActiveException() const override; 10669 std::string tryTranslators() const; 10670 10671 private: 10672 std::vector<std::unique_ptr<IExceptionTranslator const>> m_translators; 10673 }; 10674 } 10675 10676 // end catch_exception_translator_registry.h 10677 #ifdef __OBJC__ 10678 #import "Foundation/Foundation.h" 10679 #endif 10680 10681 namespace Catch { 10682 10683 ExceptionTranslatorRegistry::~ExceptionTranslatorRegistry() { 10684 } 10685 10686 void ExceptionTranslatorRegistry::registerTranslator( const IExceptionTranslator* translator ) { 10687 m_translators.push_back( std::unique_ptr<const IExceptionTranslator>( translator ) ); 10688 } 10689 10690 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 10691 std::string ExceptionTranslatorRegistry::translateActiveException() const { 10692 try { 10693 #ifdef __OBJC__ 10694 // In Objective-C try objective-c exceptions first 10695 @try { 10696 return tryTranslators(); 10697 } 10698 @catch (NSException *exception) { 10699 return Catch::Detail::stringify( [exception description] ); 10700 } 10701 #else 10702 // Compiling a mixed mode project with MSVC means that CLR 10703 // exceptions will be caught in (...) as well. However, these 10704 // do not fill-in std::current_exception and thus lead to crash 10705 // when attempting rethrow. 10706 // /EHa switch also causes structured exceptions to be caught 10707 // here, but they fill-in current_exception properly, so 10708 // at worst the output should be a little weird, instead of 10709 // causing a crash. 10710 if (std::current_exception() == nullptr) { 10711 return "Non C++ exception. Possibly a CLR exception."; 10712 } 10713 return tryTranslators(); 10714 #endif 10715 } 10716 catch( TestFailureException& ) { 10717 std::rethrow_exception(std::current_exception()); 10718 } 10719 catch( std::exception& ex ) { 10720 return ex.what(); 10721 } 10722 catch( std::string& msg ) { 10723 return msg; 10724 } 10725 catch( const char* msg ) { 10726 return msg; 10727 } 10728 catch(...) { 10729 return "Unknown exception"; 10730 } 10731 } 10732 10733 std::string ExceptionTranslatorRegistry::tryTranslators() const { 10734 if (m_translators.empty()) { 10735 std::rethrow_exception(std::current_exception()); 10736 } else { 10737 return m_translators[0]->translate(m_translators.begin() + 1, m_translators.end()); 10738 } 10739 } 10740 10741 #else // ^^ Exceptions are enabled // Exceptions are disabled vv 10742 std::string ExceptionTranslatorRegistry::translateActiveException() const { 10743 CATCH_INTERNAL_ERROR("Attempted to translate active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!"); 10744 } 10745 10746 std::string ExceptionTranslatorRegistry::tryTranslators() const { 10747 CATCH_INTERNAL_ERROR("Attempted to use exception translators under CATCH_CONFIG_DISABLE_EXCEPTIONS!"); 10748 } 10749 #endif 10750 10751 } 10752 // end catch_exception_translator_registry.cpp 10753 // start catch_fatal_condition.cpp 10754 10755 #include <algorithm> 10756 10757 #if !defined( CATCH_CONFIG_WINDOWS_SEH ) && !defined( CATCH_CONFIG_POSIX_SIGNALS ) 10758 10759 namespace Catch { 10760 10761 // If neither SEH nor signal handling is required, the handler impls 10762 // do not have to do anything, and can be empty. 10763 void FatalConditionHandler::engage_platform() {} 10764 void FatalConditionHandler::disengage_platform() {} 10765 FatalConditionHandler::FatalConditionHandler() = default; 10766 FatalConditionHandler::~FatalConditionHandler() = default; 10767 10768 } // end namespace Catch 10769 10770 #endif // !CATCH_CONFIG_WINDOWS_SEH && !CATCH_CONFIG_POSIX_SIGNALS 10771 10772 #if defined( CATCH_CONFIG_WINDOWS_SEH ) && defined( CATCH_CONFIG_POSIX_SIGNALS ) 10773 #error "Inconsistent configuration: Windows' SEH handling and POSIX signals cannot be enabled at the same time" 10774 #endif // CATCH_CONFIG_WINDOWS_SEH && CATCH_CONFIG_POSIX_SIGNALS 10775 10776 #if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS ) 10777 10778 namespace { 10779 //! Signals fatal error message to the run context 10780 void reportFatal( char const * const message ) { 10781 Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message ); 10782 } 10783 10784 //! Minimal size Catch2 needs for its own fatal error handling. 10785 //! Picked anecdotally, so it might not be sufficient on all 10786 //! platforms, and for all configurations. 10787 constexpr std::size_t minStackSizeForErrors = 32 * 1024; 10788 } // end unnamed namespace 10789 10790 #endif // CATCH_CONFIG_WINDOWS_SEH || CATCH_CONFIG_POSIX_SIGNALS 10791 10792 #if defined( CATCH_CONFIG_WINDOWS_SEH ) 10793 10794 namespace Catch { 10795 10796 struct SignalDefs { DWORD id; const char* name; }; 10797 10798 // There is no 1-1 mapping between signals and windows exceptions. 10799 // Windows can easily distinguish between SO and SigSegV, 10800 // but SigInt, SigTerm, etc are handled differently. 10801 static SignalDefs signalDefs[] = { 10802 { static_cast<DWORD>(EXCEPTION_ILLEGAL_INSTRUCTION), "SIGILL - Illegal instruction signal" }, 10803 { static_cast<DWORD>(EXCEPTION_STACK_OVERFLOW), "SIGSEGV - Stack overflow" }, 10804 { static_cast<DWORD>(EXCEPTION_ACCESS_VIOLATION), "SIGSEGV - Segmentation violation signal" }, 10805 { static_cast<DWORD>(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error" }, 10806 }; 10807 10808 static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) { 10809 for (auto const& def : signalDefs) { 10810 if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) { 10811 reportFatal(def.name); 10812 } 10813 } 10814 // If its not an exception we care about, pass it along. 10815 // This stops us from eating debugger breaks etc. 10816 return EXCEPTION_CONTINUE_SEARCH; 10817 } 10818 10819 // Since we do not support multiple instantiations, we put these 10820 // into global variables and rely on cleaning them up in outlined 10821 // constructors/destructors 10822 static PVOID exceptionHandlerHandle = nullptr; 10823 10824 // For MSVC, we reserve part of the stack memory for handling 10825 // memory overflow structured exception. 10826 FatalConditionHandler::FatalConditionHandler() { 10827 ULONG guaranteeSize = static_cast<ULONG>(minStackSizeForErrors); 10828 if (!SetThreadStackGuarantee(&guaranteeSize)) { 10829 // We do not want to fully error out, because needing 10830 // the stack reserve should be rare enough anyway. 10831 Catch::cerr() 10832 << "Failed to reserve piece of stack." 10833 << " Stack overflows will not be reported successfully."; 10834 } 10835 } 10836 10837 // We do not attempt to unset the stack guarantee, because 10838 // Windows does not support lowering the stack size guarantee. 10839 FatalConditionHandler::~FatalConditionHandler() = default; 10840 10841 void FatalConditionHandler::engage_platform() { 10842 // Register as first handler in current chain 10843 exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException); 10844 if (!exceptionHandlerHandle) { 10845 CATCH_RUNTIME_ERROR("Could not register vectored exception handler"); 10846 } 10847 } 10848 10849 void FatalConditionHandler::disengage_platform() { 10850 if (!RemoveVectoredExceptionHandler(exceptionHandlerHandle)) { 10851 CATCH_RUNTIME_ERROR("Could not unregister vectored exception handler"); 10852 } 10853 exceptionHandlerHandle = nullptr; 10854 } 10855 10856 } // end namespace Catch 10857 10858 #endif // CATCH_CONFIG_WINDOWS_SEH 10859 10860 #if defined( CATCH_CONFIG_POSIX_SIGNALS ) 10861 10862 #include <signal.h> 10863 10864 namespace Catch { 10865 10866 struct SignalDefs { 10867 int id; 10868 const char* name; 10869 }; 10870 10871 static SignalDefs signalDefs[] = { 10872 { SIGINT, "SIGINT - Terminal interrupt signal" }, 10873 { SIGILL, "SIGILL - Illegal instruction signal" }, 10874 { SIGFPE, "SIGFPE - Floating point error signal" }, 10875 { SIGSEGV, "SIGSEGV - Segmentation violation signal" }, 10876 { SIGTERM, "SIGTERM - Termination request signal" }, 10877 { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" } 10878 }; 10879 10880 // Older GCCs trigger -Wmissing-field-initializers for T foo = {} 10881 // which is zero initialization, but not explicit. We want to avoid 10882 // that. 10883 #if defined(__GNUC__) 10884 # pragma GCC diagnostic push 10885 # pragma GCC diagnostic ignored "-Wmissing-field-initializers" 10886 #endif 10887 10888 static char* altStackMem = nullptr; 10889 static std::size_t altStackSize = 0; 10890 static stack_t oldSigStack{}; 10891 static struct sigaction oldSigActions[sizeof(signalDefs) / sizeof(SignalDefs)]{}; 10892 10893 static void restorePreviousSignalHandlers() { 10894 // We set signal handlers back to the previous ones. Hopefully 10895 // nobody overwrote them in the meantime, and doesn't expect 10896 // their signal handlers to live past ours given that they 10897 // installed them after ours.. 10898 for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { 10899 sigaction(signalDefs[i].id, &oldSigActions[i], nullptr); 10900 } 10901 // Return the old stack 10902 sigaltstack(&oldSigStack, nullptr); 10903 } 10904 10905 static void handleSignal( int sig ) { 10906 char const * name = "<unknown signal>"; 10907 for (auto const& def : signalDefs) { 10908 if (sig == def.id) { 10909 name = def.name; 10910 break; 10911 } 10912 } 10913 // We need to restore previous signal handlers and let them do 10914 // their thing, so that the users can have the debugger break 10915 // when a signal is raised, and so on. 10916 restorePreviousSignalHandlers(); 10917 reportFatal( name ); 10918 raise( sig ); 10919 } 10920 10921 FatalConditionHandler::FatalConditionHandler() { 10922 assert(!altStackMem && "Cannot initialize POSIX signal handler when one already exists"); 10923 if (altStackSize == 0) { 10924 altStackSize = std::max(static_cast<size_t>(SIGSTKSZ), minStackSizeForErrors); 10925 } 10926 altStackMem = new char[altStackSize](); 10927 } 10928 10929 FatalConditionHandler::~FatalConditionHandler() { 10930 delete[] altStackMem; 10931 // We signal that another instance can be constructed by zeroing 10932 // out the pointer. 10933 altStackMem = nullptr; 10934 } 10935 10936 void FatalConditionHandler::engage_platform() { 10937 stack_t sigStack; 10938 sigStack.ss_sp = altStackMem; 10939 sigStack.ss_size = altStackSize; 10940 sigStack.ss_flags = 0; 10941 sigaltstack(&sigStack, &oldSigStack); 10942 struct sigaction sa = { }; 10943 10944 sa.sa_handler = handleSignal; 10945 sa.sa_flags = SA_ONSTACK; 10946 for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) { 10947 sigaction(signalDefs[i].id, &sa, &oldSigActions[i]); 10948 } 10949 } 10950 10951 #if defined(__GNUC__) 10952 # pragma GCC diagnostic pop 10953 #endif 10954 10955 void FatalConditionHandler::disengage_platform() { 10956 restorePreviousSignalHandlers(); 10957 } 10958 10959 } // end namespace Catch 10960 10961 #endif // CATCH_CONFIG_POSIX_SIGNALS 10962 // end catch_fatal_condition.cpp 10963 // start catch_generators.cpp 10964 10965 #include <limits> 10966 #include <set> 10967 10968 namespace Catch { 10969 10970 IGeneratorTracker::~IGeneratorTracker() {} 10971 10972 const char* GeneratorException::what() const noexcept { 10973 return m_msg; 10974 } 10975 10976 namespace Generators { 10977 10978 GeneratorUntypedBase::~GeneratorUntypedBase() {} 10979 10980 auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& { 10981 return getResultCapture().acquireGeneratorTracker( generatorName, lineInfo ); 10982 } 10983 10984 } // namespace Generators 10985 } // namespace Catch 10986 // end catch_generators.cpp 10987 // start catch_interfaces_capture.cpp 10988 10989 namespace Catch { 10990 IResultCapture::~IResultCapture() = default; 10991 } 10992 // end catch_interfaces_capture.cpp 10993 // start catch_interfaces_config.cpp 10994 10995 namespace Catch { 10996 IConfig::~IConfig() = default; 10997 } 10998 // end catch_interfaces_config.cpp 10999 // start catch_interfaces_exception.cpp 11000 11001 namespace Catch { 11002 IExceptionTranslator::~IExceptionTranslator() = default; 11003 IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() = default; 11004 } 11005 // end catch_interfaces_exception.cpp 11006 // start catch_interfaces_registry_hub.cpp 11007 11008 namespace Catch { 11009 IRegistryHub::~IRegistryHub() = default; 11010 IMutableRegistryHub::~IMutableRegistryHub() = default; 11011 } 11012 // end catch_interfaces_registry_hub.cpp 11013 // start catch_interfaces_reporter.cpp 11014 11015 // start catch_reporter_listening.h 11016 11017 namespace Catch { 11018 11019 class ListeningReporter : public IStreamingReporter { 11020 using Reporters = std::vector<IStreamingReporterPtr>; 11021 Reporters m_listeners; 11022 IStreamingReporterPtr m_reporter = nullptr; 11023 ReporterPreferences m_preferences; 11024 11025 public: 11026 ListeningReporter(); 11027 11028 void addListener( IStreamingReporterPtr&& listener ); 11029 void addReporter( IStreamingReporterPtr&& reporter ); 11030 11031 public: // IStreamingReporter 11032 11033 ReporterPreferences getPreferences() const override; 11034 11035 void noMatchingTestCases( std::string const& spec ) override; 11036 11037 void reportInvalidArguments(std::string const&arg) override; 11038 11039 static std::set<Verbosity> getSupportedVerbosities(); 11040 11041 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 11042 void benchmarkPreparing(std::string const& name) override; 11043 void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) override; 11044 void benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) override; 11045 void benchmarkFailed(std::string const&) override; 11046 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 11047 11048 void testRunStarting( TestRunInfo const& testRunInfo ) override; 11049 void testGroupStarting( GroupInfo const& groupInfo ) override; 11050 void testCaseStarting( TestCaseInfo const& testInfo ) override; 11051 void sectionStarting( SectionInfo const& sectionInfo ) override; 11052 void assertionStarting( AssertionInfo const& assertionInfo ) override; 11053 11054 // The return value indicates if the messages buffer should be cleared: 11055 bool assertionEnded( AssertionStats const& assertionStats ) override; 11056 void sectionEnded( SectionStats const& sectionStats ) override; 11057 void testCaseEnded( TestCaseStats const& testCaseStats ) override; 11058 void testGroupEnded( TestGroupStats const& testGroupStats ) override; 11059 void testRunEnded( TestRunStats const& testRunStats ) override; 11060 11061 void skipTest( TestCaseInfo const& testInfo ) override; 11062 bool isMulti() const override; 11063 11064 }; 11065 11066 } // end namespace Catch 11067 11068 // end catch_reporter_listening.h 11069 namespace Catch { 11070 11071 ReporterConfig::ReporterConfig( IConfigPtr const& _fullConfig ) 11072 : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} 11073 11074 ReporterConfig::ReporterConfig( IConfigPtr const& _fullConfig, std::ostream& _stream ) 11075 : m_stream( &_stream ), m_fullConfig( _fullConfig ) {} 11076 11077 std::ostream& ReporterConfig::stream() const { return *m_stream; } 11078 IConfigPtr ReporterConfig::fullConfig() const { return m_fullConfig; } 11079 11080 TestRunInfo::TestRunInfo( std::string const& _name ) : name( _name ) {} 11081 11082 GroupInfo::GroupInfo( std::string const& _name, 11083 std::size_t _groupIndex, 11084 std::size_t _groupsCount ) 11085 : name( _name ), 11086 groupIndex( _groupIndex ), 11087 groupsCounts( _groupsCount ) 11088 {} 11089 11090 AssertionStats::AssertionStats( AssertionResult const& _assertionResult, 11091 std::vector<MessageInfo> const& _infoMessages, 11092 Totals const& _totals ) 11093 : assertionResult( _assertionResult ), 11094 infoMessages( _infoMessages ), 11095 totals( _totals ) 11096 { 11097 assertionResult.m_resultData.lazyExpression.m_transientExpression = _assertionResult.m_resultData.lazyExpression.m_transientExpression; 11098 11099 if( assertionResult.hasMessage() ) { 11100 // Copy message into messages list. 11101 // !TBD This should have been done earlier, somewhere 11102 MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); 11103 builder << assertionResult.getMessage(); 11104 builder.m_info.message = builder.m_stream.str(); 11105 11106 infoMessages.push_back( builder.m_info ); 11107 } 11108 } 11109 11110 AssertionStats::~AssertionStats() = default; 11111 11112 SectionStats::SectionStats( SectionInfo const& _sectionInfo, 11113 Counts const& _assertions, 11114 double _durationInSeconds, 11115 bool _missingAssertions ) 11116 : sectionInfo( _sectionInfo ), 11117 assertions( _assertions ), 11118 durationInSeconds( _durationInSeconds ), 11119 missingAssertions( _missingAssertions ) 11120 {} 11121 11122 SectionStats::~SectionStats() = default; 11123 11124 TestCaseStats::TestCaseStats( TestCaseInfo const& _testInfo, 11125 Totals const& _totals, 11126 std::string const& _stdOut, 11127 std::string const& _stdErr, 11128 bool _aborting ) 11129 : testInfo( _testInfo ), 11130 totals( _totals ), 11131 stdOut( _stdOut ), 11132 stdErr( _stdErr ), 11133 aborting( _aborting ) 11134 {} 11135 11136 TestCaseStats::~TestCaseStats() = default; 11137 11138 TestGroupStats::TestGroupStats( GroupInfo const& _groupInfo, 11139 Totals const& _totals, 11140 bool _aborting ) 11141 : groupInfo( _groupInfo ), 11142 totals( _totals ), 11143 aborting( _aborting ) 11144 {} 11145 11146 TestGroupStats::TestGroupStats( GroupInfo const& _groupInfo ) 11147 : groupInfo( _groupInfo ), 11148 aborting( false ) 11149 {} 11150 11151 TestGroupStats::~TestGroupStats() = default; 11152 11153 TestRunStats::TestRunStats( TestRunInfo const& _runInfo, 11154 Totals const& _totals, 11155 bool _aborting ) 11156 : runInfo( _runInfo ), 11157 totals( _totals ), 11158 aborting( _aborting ) 11159 {} 11160 11161 TestRunStats::~TestRunStats() = default; 11162 11163 void IStreamingReporter::fatalErrorEncountered( StringRef ) {} 11164 bool IStreamingReporter::isMulti() const { return false; } 11165 11166 IReporterFactory::~IReporterFactory() = default; 11167 IReporterRegistry::~IReporterRegistry() = default; 11168 11169 } // end namespace Catch 11170 // end catch_interfaces_reporter.cpp 11171 // start catch_interfaces_runner.cpp 11172 11173 namespace Catch { 11174 IRunner::~IRunner() = default; 11175 } 11176 // end catch_interfaces_runner.cpp 11177 // start catch_interfaces_testcase.cpp 11178 11179 namespace Catch { 11180 ITestInvoker::~ITestInvoker() = default; 11181 ITestCaseRegistry::~ITestCaseRegistry() = default; 11182 } 11183 // end catch_interfaces_testcase.cpp 11184 // start catch_leak_detector.cpp 11185 11186 #ifdef CATCH_CONFIG_WINDOWS_CRTDBG 11187 #include <crtdbg.h> 11188 11189 namespace Catch { 11190 11191 LeakDetector::LeakDetector() { 11192 int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); 11193 flag |= _CRTDBG_LEAK_CHECK_DF; 11194 flag |= _CRTDBG_ALLOC_MEM_DF; 11195 _CrtSetDbgFlag(flag); 11196 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); 11197 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); 11198 // Change this to leaking allocation's number to break there 11199 _CrtSetBreakAlloc(-1); 11200 } 11201 } 11202 11203 #else 11204 11205 Catch::LeakDetector::LeakDetector() {} 11206 11207 #endif 11208 11209 Catch::LeakDetector::~LeakDetector() { 11210 Catch::cleanUp(); 11211 } 11212 // end catch_leak_detector.cpp 11213 // start catch_list.cpp 11214 11215 // start catch_list.h 11216 11217 #include <set> 11218 11219 namespace Catch { 11220 11221 std::size_t listTests( Config const& config ); 11222 11223 std::size_t listTestsNamesOnly( Config const& config ); 11224 11225 struct TagInfo { 11226 void add( std::string const& spelling ); 11227 std::string all() const; 11228 11229 std::set<std::string> spellings; 11230 std::size_t count = 0; 11231 }; 11232 11233 std::size_t listTags( Config const& config ); 11234 11235 std::size_t listReporters(); 11236 11237 Option<std::size_t> list( std::shared_ptr<Config> const& config ); 11238 11239 } // end namespace Catch 11240 11241 // end catch_list.h 11242 // start catch_text.h 11243 11244 namespace Catch { 11245 using namespace clara::TextFlow; 11246 } 11247 11248 // end catch_text.h 11249 #include <limits> 11250 #include <algorithm> 11251 #include <iomanip> 11252 11253 namespace Catch { 11254 11255 std::size_t listTests( Config const& config ) { 11256 TestSpec const& testSpec = config.testSpec(); 11257 if( config.hasTestFilters() ) 11258 Catch::cout() << "Matching test cases:\n"; 11259 else { 11260 Catch::cout() << "All available test cases:\n"; 11261 } 11262 11263 auto matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); 11264 for( auto const& testCaseInfo : matchedTestCases ) { 11265 Colour::Code colour = testCaseInfo.isHidden() 11266 ? Colour::SecondaryText 11267 : Colour::None; 11268 Colour colourGuard( colour ); 11269 11270 Catch::cout() << Column( testCaseInfo.name ).initialIndent( 2 ).indent( 4 ) << "\n"; 11271 if( config.verbosity() >= Verbosity::High ) { 11272 Catch::cout() << Column( Catch::Detail::stringify( testCaseInfo.lineInfo ) ).indent(4) << std::endl; 11273 std::string description = testCaseInfo.description; 11274 if( description.empty() ) 11275 description = "(NO DESCRIPTION)"; 11276 Catch::cout() << Column( description ).indent(4) << std::endl; 11277 } 11278 if( !testCaseInfo.tags.empty() ) 11279 Catch::cout() << Column( testCaseInfo.tagsAsString() ).indent( 6 ) << "\n"; 11280 } 11281 11282 if( !config.hasTestFilters() ) 11283 Catch::cout() << pluralise( matchedTestCases.size(), "test case" ) << '\n' << std::endl; 11284 else 11285 Catch::cout() << pluralise( matchedTestCases.size(), "matching test case" ) << '\n' << std::endl; 11286 return matchedTestCases.size(); 11287 } 11288 11289 std::size_t listTestsNamesOnly( Config const& config ) { 11290 TestSpec const& testSpec = config.testSpec(); 11291 std::size_t matchedTests = 0; 11292 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); 11293 for( auto const& testCaseInfo : matchedTestCases ) { 11294 matchedTests++; 11295 if( startsWith( testCaseInfo.name, '#' ) ) 11296 Catch::cout() << '"' << testCaseInfo.name << '"'; 11297 else 11298 Catch::cout() << testCaseInfo.name; 11299 if ( config.verbosity() >= Verbosity::High ) 11300 Catch::cout() << "\t@" << testCaseInfo.lineInfo; 11301 Catch::cout() << std::endl; 11302 } 11303 return matchedTests; 11304 } 11305 11306 void TagInfo::add( std::string const& spelling ) { 11307 ++count; 11308 spellings.insert( spelling ); 11309 } 11310 11311 std::string TagInfo::all() const { 11312 size_t size = 0; 11313 for (auto const& spelling : spellings) { 11314 // Add 2 for the brackes 11315 size += spelling.size() + 2; 11316 } 11317 11318 std::string out; out.reserve(size); 11319 for (auto const& spelling : spellings) { 11320 out += '['; 11321 out += spelling; 11322 out += ']'; 11323 } 11324 return out; 11325 } 11326 11327 std::size_t listTags( Config const& config ) { 11328 TestSpec const& testSpec = config.testSpec(); 11329 if( config.hasTestFilters() ) 11330 Catch::cout() << "Tags for matching test cases:\n"; 11331 else { 11332 Catch::cout() << "All available tags:\n"; 11333 } 11334 11335 std::map<std::string, TagInfo> tagCounts; 11336 11337 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); 11338 for( auto const& testCase : matchedTestCases ) { 11339 for( auto const& tagName : testCase.getTestCaseInfo().tags ) { 11340 std::string lcaseTagName = toLower( tagName ); 11341 auto countIt = tagCounts.find( lcaseTagName ); 11342 if( countIt == tagCounts.end() ) 11343 countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first; 11344 countIt->second.add( tagName ); 11345 } 11346 } 11347 11348 for( auto const& tagCount : tagCounts ) { 11349 ReusableStringStream rss; 11350 rss << " " << std::setw(2) << tagCount.second.count << " "; 11351 auto str = rss.str(); 11352 auto wrapper = Column( tagCount.second.all() ) 11353 .initialIndent( 0 ) 11354 .indent( str.size() ) 11355 .width( CATCH_CONFIG_CONSOLE_WIDTH-10 ); 11356 Catch::cout() << str << wrapper << '\n'; 11357 } 11358 Catch::cout() << pluralise( tagCounts.size(), "tag" ) << '\n' << std::endl; 11359 return tagCounts.size(); 11360 } 11361 11362 std::size_t listReporters() { 11363 Catch::cout() << "Available reporters:\n"; 11364 IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); 11365 std::size_t maxNameLen = 0; 11366 for( auto const& factoryKvp : factories ) 11367 maxNameLen = (std::max)( maxNameLen, factoryKvp.first.size() ); 11368 11369 for( auto const& factoryKvp : factories ) { 11370 Catch::cout() 11371 << Column( factoryKvp.first + ":" ) 11372 .indent(2) 11373 .width( 5+maxNameLen ) 11374 + Column( factoryKvp.second->getDescription() ) 11375 .initialIndent(0) 11376 .indent(2) 11377 .width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) 11378 << "\n"; 11379 } 11380 Catch::cout() << std::endl; 11381 return factories.size(); 11382 } 11383 11384 Option<std::size_t> list( std::shared_ptr<Config> const& config ) { 11385 Option<std::size_t> listedCount; 11386 getCurrentMutableContext().setConfig( config ); 11387 if( config->listTests() ) 11388 listedCount = listedCount.valueOr(0) + listTests( *config ); 11389 if( config->listTestNamesOnly() ) 11390 listedCount = listedCount.valueOr(0) + listTestsNamesOnly( *config ); 11391 if( config->listTags() ) 11392 listedCount = listedCount.valueOr(0) + listTags( *config ); 11393 if( config->listReporters() ) 11394 listedCount = listedCount.valueOr(0) + listReporters(); 11395 return listedCount; 11396 } 11397 11398 } // end namespace Catch 11399 // end catch_list.cpp 11400 // start catch_matchers.cpp 11401 11402 namespace Catch { 11403 namespace Matchers { 11404 namespace Impl { 11405 11406 std::string MatcherUntypedBase::toString() const { 11407 if( m_cachedToString.empty() ) 11408 m_cachedToString = describe(); 11409 return m_cachedToString; 11410 } 11411 11412 MatcherUntypedBase::~MatcherUntypedBase() = default; 11413 11414 } // namespace Impl 11415 } // namespace Matchers 11416 11417 using namespace Matchers; 11418 using Matchers::Impl::MatcherBase; 11419 11420 } // namespace Catch 11421 // end catch_matchers.cpp 11422 // start catch_matchers_exception.cpp 11423 11424 namespace Catch { 11425 namespace Matchers { 11426 namespace Exception { 11427 11428 bool ExceptionMessageMatcher::match(std::exception const& ex) const { 11429 return ex.what() == m_message; 11430 } 11431 11432 std::string ExceptionMessageMatcher::describe() const { 11433 return "exception message matches \"" + m_message + "\""; 11434 } 11435 11436 } 11437 Exception::ExceptionMessageMatcher Message(std::string const& message) { 11438 return Exception::ExceptionMessageMatcher(message); 11439 } 11440 11441 // namespace Exception 11442 } // namespace Matchers 11443 } // namespace Catch 11444 // end catch_matchers_exception.cpp 11445 // start catch_matchers_floating.cpp 11446 11447 // start catch_polyfills.hpp 11448 11449 namespace Catch { 11450 bool isnan(float f); 11451 bool isnan(double d); 11452 } 11453 11454 // end catch_polyfills.hpp 11455 // start catch_to_string.hpp 11456 11457 #include <string> 11458 11459 namespace Catch { 11460 template <typename T> 11461 std::string to_string(T const& t) { 11462 #if defined(CATCH_CONFIG_CPP11_TO_STRING) 11463 return std::to_string(t); 11464 #else 11465 ReusableStringStream rss; 11466 rss << t; 11467 return rss.str(); 11468 #endif 11469 } 11470 } // end namespace Catch 11471 11472 // end catch_to_string.hpp 11473 #include <algorithm> 11474 #include <cmath> 11475 #include <cstdlib> 11476 #include <cstdint> 11477 #include <cstring> 11478 #include <sstream> 11479 #include <type_traits> 11480 #include <iomanip> 11481 #include <limits> 11482 11483 namespace Catch { 11484 namespace { 11485 11486 int32_t convert(float f) { 11487 static_assert(sizeof(float) == sizeof(int32_t), "Important ULP matcher assumption violated"); 11488 int32_t i; 11489 std::memcpy(&i, &f, sizeof(f)); 11490 return i; 11491 } 11492 11493 int64_t convert(double d) { 11494 static_assert(sizeof(double) == sizeof(int64_t), "Important ULP matcher assumption violated"); 11495 int64_t i; 11496 std::memcpy(&i, &d, sizeof(d)); 11497 return i; 11498 } 11499 11500 template <typename FP> 11501 bool almostEqualUlps(FP lhs, FP rhs, uint64_t maxUlpDiff) { 11502 // Comparison with NaN should always be false. 11503 // This way we can rule it out before getting into the ugly details 11504 if (Catch::isnan(lhs) || Catch::isnan(rhs)) { 11505 return false; 11506 } 11507 11508 auto lc = convert(lhs); 11509 auto rc = convert(rhs); 11510 11511 if ((lc < 0) != (rc < 0)) { 11512 // Potentially we can have +0 and -0 11513 return lhs == rhs; 11514 } 11515 11516 // static cast as a workaround for IBM XLC 11517 auto ulpDiff = std::abs(static_cast<FP>(lc - rc)); 11518 return static_cast<uint64_t>(ulpDiff) <= maxUlpDiff; 11519 } 11520 11521 #if defined(CATCH_CONFIG_GLOBAL_NEXTAFTER) 11522 11523 float nextafter(float x, float y) { 11524 return ::nextafterf(x, y); 11525 } 11526 11527 double nextafter(double x, double y) { 11528 return ::nextafter(x, y); 11529 } 11530 11531 #endif // ^^^ CATCH_CONFIG_GLOBAL_NEXTAFTER ^^^ 11532 11533 template <typename FP> 11534 FP step(FP start, FP direction, uint64_t steps) { 11535 for (uint64_t i = 0; i < steps; ++i) { 11536 #if defined(CATCH_CONFIG_GLOBAL_NEXTAFTER) 11537 start = Catch::nextafter(start, direction); 11538 #else 11539 start = std::nextafter(start, direction); 11540 #endif 11541 } 11542 return start; 11543 } 11544 11545 // Performs equivalent check of std::fabs(lhs - rhs) <= margin 11546 // But without the subtraction to allow for INFINITY in comparison 11547 bool marginComparison(double lhs, double rhs, double margin) { 11548 return (lhs + margin >= rhs) && (rhs + margin >= lhs); 11549 } 11550 11551 template <typename FloatingPoint> 11552 void write(std::ostream& out, FloatingPoint num) { 11553 out << std::scientific 11554 << std::setprecision(std::numeric_limits<FloatingPoint>::max_digits10 - 1) 11555 << num; 11556 } 11557 11558 } // end anonymous namespace 11559 11560 namespace Matchers { 11561 namespace Floating { 11562 11563 enum class FloatingPointKind : uint8_t { 11564 Float, 11565 Double 11566 }; 11567 11568 WithinAbsMatcher::WithinAbsMatcher(double target, double margin) 11569 :m_target{ target }, m_margin{ margin } { 11570 CATCH_ENFORCE(margin >= 0, "Invalid margin: " << margin << '.' 11571 << " Margin has to be non-negative."); 11572 } 11573 11574 // Performs equivalent check of std::fabs(lhs - rhs) <= margin 11575 // But without the subtraction to allow for INFINITY in comparison 11576 bool WithinAbsMatcher::match(double const& matchee) const { 11577 return (matchee + m_margin >= m_target) && (m_target + m_margin >= matchee); 11578 } 11579 11580 std::string WithinAbsMatcher::describe() const { 11581 return "is within " + ::Catch::Detail::stringify(m_margin) + " of " + ::Catch::Detail::stringify(m_target); 11582 } 11583 11584 WithinUlpsMatcher::WithinUlpsMatcher(double target, uint64_t ulps, FloatingPointKind baseType) 11585 :m_target{ target }, m_ulps{ ulps }, m_type{ baseType } { 11586 CATCH_ENFORCE(m_type == FloatingPointKind::Double 11587 || m_ulps < (std::numeric_limits<uint32_t>::max)(), 11588 "Provided ULP is impossibly large for a float comparison."); 11589 } 11590 11591 #if defined(__clang__) 11592 #pragma clang diagnostic push 11593 // Clang <3.5 reports on the default branch in the switch below 11594 #pragma clang diagnostic ignored "-Wunreachable-code" 11595 #endif 11596 11597 bool WithinUlpsMatcher::match(double const& matchee) const { 11598 switch (m_type) { 11599 case FloatingPointKind::Float: 11600 return almostEqualUlps<float>(static_cast<float>(matchee), static_cast<float>(m_target), m_ulps); 11601 case FloatingPointKind::Double: 11602 return almostEqualUlps<double>(matchee, m_target, m_ulps); 11603 default: 11604 CATCH_INTERNAL_ERROR( "Unknown FloatingPointKind value" ); 11605 } 11606 } 11607 11608 #if defined(__clang__) 11609 #pragma clang diagnostic pop 11610 #endif 11611 11612 std::string WithinUlpsMatcher::describe() const { 11613 std::stringstream ret; 11614 11615 ret << "is within " << m_ulps << " ULPs of "; 11616 11617 if (m_type == FloatingPointKind::Float) { 11618 write(ret, static_cast<float>(m_target)); 11619 ret << 'f'; 11620 } else { 11621 write(ret, m_target); 11622 } 11623 11624 ret << " (["; 11625 if (m_type == FloatingPointKind::Double) { 11626 write(ret, step(m_target, static_cast<double>(-INFINITY), m_ulps)); 11627 ret << ", "; 11628 write(ret, step(m_target, static_cast<double>( INFINITY), m_ulps)); 11629 } else { 11630 // We have to cast INFINITY to float because of MinGW, see #1782 11631 write(ret, step(static_cast<float>(m_target), static_cast<float>(-INFINITY), m_ulps)); 11632 ret << ", "; 11633 write(ret, step(static_cast<float>(m_target), static_cast<float>( INFINITY), m_ulps)); 11634 } 11635 ret << "])"; 11636 11637 return ret.str(); 11638 } 11639 11640 WithinRelMatcher::WithinRelMatcher(double target, double epsilon): 11641 m_target(target), 11642 m_epsilon(epsilon){ 11643 CATCH_ENFORCE(m_epsilon >= 0., "Relative comparison with epsilon < 0 does not make sense."); 11644 CATCH_ENFORCE(m_epsilon < 1., "Relative comparison with epsilon >= 1 does not make sense."); 11645 } 11646 11647 bool WithinRelMatcher::match(double const& matchee) const { 11648 const auto relMargin = m_epsilon * (std::max)(std::fabs(matchee), std::fabs(m_target)); 11649 return marginComparison(matchee, m_target, 11650 std::isinf(relMargin)? 0 : relMargin); 11651 } 11652 11653 std::string WithinRelMatcher::describe() const { 11654 Catch::ReusableStringStream sstr; 11655 sstr << "and " << m_target << " are within " << m_epsilon * 100. << "% of each other"; 11656 return sstr.str(); 11657 } 11658 11659 }// namespace Floating 11660 11661 Floating::WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff) { 11662 return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Double); 11663 } 11664 11665 Floating::WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff) { 11666 return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Float); 11667 } 11668 11669 Floating::WithinAbsMatcher WithinAbs(double target, double margin) { 11670 return Floating::WithinAbsMatcher(target, margin); 11671 } 11672 11673 Floating::WithinRelMatcher WithinRel(double target, double eps) { 11674 return Floating::WithinRelMatcher(target, eps); 11675 } 11676 11677 Floating::WithinRelMatcher WithinRel(double target) { 11678 return Floating::WithinRelMatcher(target, std::numeric_limits<double>::epsilon() * 100); 11679 } 11680 11681 Floating::WithinRelMatcher WithinRel(float target, float eps) { 11682 return Floating::WithinRelMatcher(target, eps); 11683 } 11684 11685 Floating::WithinRelMatcher WithinRel(float target) { 11686 return Floating::WithinRelMatcher(target, std::numeric_limits<float>::epsilon() * 100); 11687 } 11688 11689 } // namespace Matchers 11690 } // namespace Catch 11691 // end catch_matchers_floating.cpp 11692 // start catch_matchers_generic.cpp 11693 11694 std::string Catch::Matchers::Generic::Detail::finalizeDescription(const std::string& desc) { 11695 if (desc.empty()) { 11696 return "matches undescribed predicate"; 11697 } else { 11698 return "matches predicate: \"" + desc + '"'; 11699 } 11700 } 11701 // end catch_matchers_generic.cpp 11702 // start catch_matchers_string.cpp 11703 11704 #include <regex> 11705 11706 namespace Catch { 11707 namespace Matchers { 11708 11709 namespace StdString { 11710 11711 CasedString::CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ) 11712 : m_caseSensitivity( caseSensitivity ), 11713 m_str( adjustString( str ) ) 11714 {} 11715 std::string CasedString::adjustString( std::string const& str ) const { 11716 return m_caseSensitivity == CaseSensitive::No 11717 ? toLower( str ) 11718 : str; 11719 } 11720 std::string CasedString::caseSensitivitySuffix() const { 11721 return m_caseSensitivity == CaseSensitive::No 11722 ? " (case insensitive)" 11723 : std::string(); 11724 } 11725 11726 StringMatcherBase::StringMatcherBase( std::string const& operation, CasedString const& comparator ) 11727 : m_comparator( comparator ), 11728 m_operation( operation ) { 11729 } 11730 11731 std::string StringMatcherBase::describe() const { 11732 std::string description; 11733 description.reserve(5 + m_operation.size() + m_comparator.m_str.size() + 11734 m_comparator.caseSensitivitySuffix().size()); 11735 description += m_operation; 11736 description += ": \""; 11737 description += m_comparator.m_str; 11738 description += "\""; 11739 description += m_comparator.caseSensitivitySuffix(); 11740 return description; 11741 } 11742 11743 EqualsMatcher::EqualsMatcher( CasedString const& comparator ) : StringMatcherBase( "equals", comparator ) {} 11744 11745 bool EqualsMatcher::match( std::string const& source ) const { 11746 return m_comparator.adjustString( source ) == m_comparator.m_str; 11747 } 11748 11749 ContainsMatcher::ContainsMatcher( CasedString const& comparator ) : StringMatcherBase( "contains", comparator ) {} 11750 11751 bool ContainsMatcher::match( std::string const& source ) const { 11752 return contains( m_comparator.adjustString( source ), m_comparator.m_str ); 11753 } 11754 11755 StartsWithMatcher::StartsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "starts with", comparator ) {} 11756 11757 bool StartsWithMatcher::match( std::string const& source ) const { 11758 return startsWith( m_comparator.adjustString( source ), m_comparator.m_str ); 11759 } 11760 11761 EndsWithMatcher::EndsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "ends with", comparator ) {} 11762 11763 bool EndsWithMatcher::match( std::string const& source ) const { 11764 return endsWith( m_comparator.adjustString( source ), m_comparator.m_str ); 11765 } 11766 11767 RegexMatcher::RegexMatcher(std::string regex, CaseSensitive::Choice caseSensitivity): m_regex(std::move(regex)), m_caseSensitivity(caseSensitivity) {} 11768 11769 bool RegexMatcher::match(std::string const& matchee) const { 11770 auto flags = std::regex::ECMAScript; // ECMAScript is the default syntax option anyway 11771 if (m_caseSensitivity == CaseSensitive::Choice::No) { 11772 flags |= std::regex::icase; 11773 } 11774 auto reg = std::regex(m_regex, flags); 11775 return std::regex_match(matchee, reg); 11776 } 11777 11778 std::string RegexMatcher::describe() const { 11779 return "matches " + ::Catch::Detail::stringify(m_regex) + ((m_caseSensitivity == CaseSensitive::Choice::Yes)? " case sensitively" : " case insensitively"); 11780 } 11781 11782 } // namespace StdString 11783 11784 StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity ) { 11785 return StdString::EqualsMatcher( StdString::CasedString( str, caseSensitivity) ); 11786 } 11787 StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity ) { 11788 return StdString::ContainsMatcher( StdString::CasedString( str, caseSensitivity) ); 11789 } 11790 StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) { 11791 return StdString::EndsWithMatcher( StdString::CasedString( str, caseSensitivity) ); 11792 } 11793 StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) { 11794 return StdString::StartsWithMatcher( StdString::CasedString( str, caseSensitivity) ); 11795 } 11796 11797 StdString::RegexMatcher Matches(std::string const& regex, CaseSensitive::Choice caseSensitivity) { 11798 return StdString::RegexMatcher(regex, caseSensitivity); 11799 } 11800 11801 } // namespace Matchers 11802 } // namespace Catch 11803 // end catch_matchers_string.cpp 11804 // start catch_message.cpp 11805 11806 // start catch_uncaught_exceptions.h 11807 11808 namespace Catch { 11809 bool uncaught_exceptions(); 11810 } // end namespace Catch 11811 11812 // end catch_uncaught_exceptions.h 11813 #include <cassert> 11814 #include <stack> 11815 11816 namespace Catch { 11817 11818 MessageInfo::MessageInfo( StringRef const& _macroName, 11819 SourceLineInfo const& _lineInfo, 11820 ResultWas::OfType _type ) 11821 : macroName( _macroName ), 11822 lineInfo( _lineInfo ), 11823 type( _type ), 11824 sequence( ++globalCount ) 11825 {} 11826 11827 bool MessageInfo::operator==( MessageInfo const& other ) const { 11828 return sequence == other.sequence; 11829 } 11830 11831 bool MessageInfo::operator<( MessageInfo const& other ) const { 11832 return sequence < other.sequence; 11833 } 11834 11835 // This may need protecting if threading support is added 11836 unsigned int MessageInfo::globalCount = 0; 11837 11838 //////////////////////////////////////////////////////////////////////////// 11839 11840 Catch::MessageBuilder::MessageBuilder( StringRef const& macroName, 11841 SourceLineInfo const& lineInfo, 11842 ResultWas::OfType type ) 11843 :m_info(macroName, lineInfo, type) {} 11844 11845 //////////////////////////////////////////////////////////////////////////// 11846 11847 ScopedMessage::ScopedMessage( MessageBuilder const& builder ) 11848 : m_info( builder.m_info ), m_moved() 11849 { 11850 m_info.message = builder.m_stream.str(); 11851 getResultCapture().pushScopedMessage( m_info ); 11852 } 11853 11854 ScopedMessage::ScopedMessage( ScopedMessage&& old ) 11855 : m_info( old.m_info ), m_moved() 11856 { 11857 old.m_moved = true; 11858 } 11859 11860 ScopedMessage::~ScopedMessage() { 11861 if ( !uncaught_exceptions() && !m_moved ){ 11862 getResultCapture().popScopedMessage(m_info); 11863 } 11864 } 11865 11866 Capturer::Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names ) { 11867 auto trimmed = [&] (size_t start, size_t end) { 11868 while (names[start] == ',' || isspace(static_cast<unsigned char>(names[start]))) { 11869 ++start; 11870 } 11871 while (names[end] == ',' || isspace(static_cast<unsigned char>(names[end]))) { 11872 --end; 11873 } 11874 return names.substr(start, end - start + 1); 11875 }; 11876 auto skipq = [&] (size_t start, char quote) { 11877 for (auto i = start + 1; i < names.size() ; ++i) { 11878 if (names[i] == quote) 11879 return i; 11880 if (names[i] == '\\') 11881 ++i; 11882 } 11883 CATCH_INTERNAL_ERROR("CAPTURE parsing encountered unmatched quote"); 11884 }; 11885 11886 size_t start = 0; 11887 std::stack<char> openings; 11888 for (size_t pos = 0; pos < names.size(); ++pos) { 11889 char c = names[pos]; 11890 switch (c) { 11891 case '[': 11892 case '{': 11893 case '(': 11894 // It is basically impossible to disambiguate between 11895 // comparison and start of template args in this context 11896 // case '<': 11897 openings.push(c); 11898 break; 11899 case ']': 11900 case '}': 11901 case ')': 11902 // case '>': 11903 openings.pop(); 11904 break; 11905 case '"': 11906 case '\'': 11907 pos = skipq(pos, c); 11908 break; 11909 case ',': 11910 if (start != pos && openings.empty()) { 11911 m_messages.emplace_back(macroName, lineInfo, resultType); 11912 m_messages.back().message = static_cast<std::string>(trimmed(start, pos)); 11913 m_messages.back().message += " := "; 11914 start = pos; 11915 } 11916 } 11917 } 11918 assert(openings.empty() && "Mismatched openings"); 11919 m_messages.emplace_back(macroName, lineInfo, resultType); 11920 m_messages.back().message = static_cast<std::string>(trimmed(start, names.size() - 1)); 11921 m_messages.back().message += " := "; 11922 } 11923 Capturer::~Capturer() { 11924 if ( !uncaught_exceptions() ){ 11925 assert( m_captured == m_messages.size() ); 11926 for( size_t i = 0; i < m_captured; ++i ) 11927 m_resultCapture.popScopedMessage( m_messages[i] ); 11928 } 11929 } 11930 11931 void Capturer::captureValue( size_t index, std::string const& value ) { 11932 assert( index < m_messages.size() ); 11933 m_messages[index].message += value; 11934 m_resultCapture.pushScopedMessage( m_messages[index] ); 11935 m_captured++; 11936 } 11937 11938 } // end namespace Catch 11939 // end catch_message.cpp 11940 // start catch_output_redirect.cpp 11941 11942 // start catch_output_redirect.h 11943 #ifndef TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H 11944 #define TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H 11945 11946 #include <cstdio> 11947 #include <iosfwd> 11948 #include <string> 11949 11950 namespace Catch { 11951 11952 class RedirectedStream { 11953 std::ostream& m_originalStream; 11954 std::ostream& m_redirectionStream; 11955 std::streambuf* m_prevBuf; 11956 11957 public: 11958 RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream ); 11959 ~RedirectedStream(); 11960 }; 11961 11962 class RedirectedStdOut { 11963 ReusableStringStream m_rss; 11964 RedirectedStream m_cout; 11965 public: 11966 RedirectedStdOut(); 11967 auto str() const -> std::string; 11968 }; 11969 11970 // StdErr has two constituent streams in C++, std::cerr and std::clog 11971 // This means that we need to redirect 2 streams into 1 to keep proper 11972 // order of writes 11973 class RedirectedStdErr { 11974 ReusableStringStream m_rss; 11975 RedirectedStream m_cerr; 11976 RedirectedStream m_clog; 11977 public: 11978 RedirectedStdErr(); 11979 auto str() const -> std::string; 11980 }; 11981 11982 class RedirectedStreams { 11983 public: 11984 RedirectedStreams(RedirectedStreams const&) = delete; 11985 RedirectedStreams& operator=(RedirectedStreams const&) = delete; 11986 RedirectedStreams(RedirectedStreams&&) = delete; 11987 RedirectedStreams& operator=(RedirectedStreams&&) = delete; 11988 11989 RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr); 11990 ~RedirectedStreams(); 11991 private: 11992 std::string& m_redirectedCout; 11993 std::string& m_redirectedCerr; 11994 RedirectedStdOut m_redirectedStdOut; 11995 RedirectedStdErr m_redirectedStdErr; 11996 }; 11997 11998 #if defined(CATCH_CONFIG_NEW_CAPTURE) 11999 12000 // Windows's implementation of std::tmpfile is terrible (it tries 12001 // to create a file inside system folder, thus requiring elevated 12002 // privileges for the binary), so we have to use tmpnam(_s) and 12003 // create the file ourselves there. 12004 class TempFile { 12005 public: 12006 TempFile(TempFile const&) = delete; 12007 TempFile& operator=(TempFile const&) = delete; 12008 TempFile(TempFile&&) = delete; 12009 TempFile& operator=(TempFile&&) = delete; 12010 12011 TempFile(); 12012 ~TempFile(); 12013 12014 std::FILE* getFile(); 12015 std::string getContents(); 12016 12017 private: 12018 std::FILE* m_file = nullptr; 12019 #if defined(_MSC_VER) 12020 char m_buffer[L_tmpnam] = { 0 }; 12021 #endif 12022 }; 12023 12024 class OutputRedirect { 12025 public: 12026 OutputRedirect(OutputRedirect const&) = delete; 12027 OutputRedirect& operator=(OutputRedirect const&) = delete; 12028 OutputRedirect(OutputRedirect&&) = delete; 12029 OutputRedirect& operator=(OutputRedirect&&) = delete; 12030 12031 OutputRedirect(std::string& stdout_dest, std::string& stderr_dest); 12032 ~OutputRedirect(); 12033 12034 private: 12035 int m_originalStdout = -1; 12036 int m_originalStderr = -1; 12037 TempFile m_stdoutFile; 12038 TempFile m_stderrFile; 12039 std::string& m_stdoutDest; 12040 std::string& m_stderrDest; 12041 }; 12042 12043 #endif 12044 12045 } // end namespace Catch 12046 12047 #endif // TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H 12048 // end catch_output_redirect.h 12049 #include <cstdio> 12050 #include <cstring> 12051 #include <fstream> 12052 #include <sstream> 12053 #include <stdexcept> 12054 12055 #if defined(CATCH_CONFIG_NEW_CAPTURE) 12056 #if defined(_MSC_VER) 12057 #include <io.h> //_dup and _dup2 12058 #define dup _dup 12059 #define dup2 _dup2 12060 #define fileno _fileno 12061 #else 12062 #include <unistd.h> // dup and dup2 12063 #endif 12064 #endif 12065 12066 namespace Catch { 12067 12068 RedirectedStream::RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream ) 12069 : m_originalStream( originalStream ), 12070 m_redirectionStream( redirectionStream ), 12071 m_prevBuf( m_originalStream.rdbuf() ) 12072 { 12073 m_originalStream.rdbuf( m_redirectionStream.rdbuf() ); 12074 } 12075 12076 RedirectedStream::~RedirectedStream() { 12077 m_originalStream.rdbuf( m_prevBuf ); 12078 } 12079 12080 RedirectedStdOut::RedirectedStdOut() : m_cout( Catch::cout(), m_rss.get() ) {} 12081 auto RedirectedStdOut::str() const -> std::string { return m_rss.str(); } 12082 12083 RedirectedStdErr::RedirectedStdErr() 12084 : m_cerr( Catch::cerr(), m_rss.get() ), 12085 m_clog( Catch::clog(), m_rss.get() ) 12086 {} 12087 auto RedirectedStdErr::str() const -> std::string { return m_rss.str(); } 12088 12089 RedirectedStreams::RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr) 12090 : m_redirectedCout(redirectedCout), 12091 m_redirectedCerr(redirectedCerr) 12092 {} 12093 12094 RedirectedStreams::~RedirectedStreams() { 12095 m_redirectedCout += m_redirectedStdOut.str(); 12096 m_redirectedCerr += m_redirectedStdErr.str(); 12097 } 12098 12099 #if defined(CATCH_CONFIG_NEW_CAPTURE) 12100 12101 #if defined(_MSC_VER) 12102 TempFile::TempFile() { 12103 if (tmpnam_s(m_buffer)) { 12104 CATCH_RUNTIME_ERROR("Could not get a temp filename"); 12105 } 12106 if (fopen_s(&m_file, m_buffer, "w+")) { 12107 char buffer[100]; 12108 if (strerror_s(buffer, errno)) { 12109 CATCH_RUNTIME_ERROR("Could not translate errno to a string"); 12110 } 12111 CATCH_RUNTIME_ERROR("Could not open the temp file: '" << m_buffer << "' because: " << buffer); 12112 } 12113 } 12114 #else 12115 TempFile::TempFile() { 12116 m_file = std::tmpfile(); 12117 if (!m_file) { 12118 CATCH_RUNTIME_ERROR("Could not create a temp file."); 12119 } 12120 } 12121 12122 #endif 12123 12124 TempFile::~TempFile() { 12125 // TBD: What to do about errors here? 12126 std::fclose(m_file); 12127 // We manually create the file on Windows only, on Linux 12128 // it will be autodeleted 12129 #if defined(_MSC_VER) 12130 std::remove(m_buffer); 12131 #endif 12132 } 12133 12134 FILE* TempFile::getFile() { 12135 return m_file; 12136 } 12137 12138 std::string TempFile::getContents() { 12139 std::stringstream sstr; 12140 char buffer[100] = {}; 12141 std::rewind(m_file); 12142 while (std::fgets(buffer, sizeof(buffer), m_file)) { 12143 sstr << buffer; 12144 } 12145 return sstr.str(); 12146 } 12147 12148 OutputRedirect::OutputRedirect(std::string& stdout_dest, std::string& stderr_dest) : 12149 m_originalStdout(dup(1)), 12150 m_originalStderr(dup(2)), 12151 m_stdoutDest(stdout_dest), 12152 m_stderrDest(stderr_dest) { 12153 dup2(fileno(m_stdoutFile.getFile()), 1); 12154 dup2(fileno(m_stderrFile.getFile()), 2); 12155 } 12156 12157 OutputRedirect::~OutputRedirect() { 12158 Catch::cout() << std::flush; 12159 fflush(stdout); 12160 // Since we support overriding these streams, we flush cerr 12161 // even though std::cerr is unbuffered 12162 Catch::cerr() << std::flush; 12163 Catch::clog() << std::flush; 12164 fflush(stderr); 12165 12166 dup2(m_originalStdout, 1); 12167 dup2(m_originalStderr, 2); 12168 12169 m_stdoutDest += m_stdoutFile.getContents(); 12170 m_stderrDest += m_stderrFile.getContents(); 12171 } 12172 12173 #endif // CATCH_CONFIG_NEW_CAPTURE 12174 12175 } // namespace Catch 12176 12177 #if defined(CATCH_CONFIG_NEW_CAPTURE) 12178 #if defined(_MSC_VER) 12179 #undef dup 12180 #undef dup2 12181 #undef fileno 12182 #endif 12183 #endif 12184 // end catch_output_redirect.cpp 12185 // start catch_polyfills.cpp 12186 12187 #include <cmath> 12188 12189 namespace Catch { 12190 12191 #if !defined(CATCH_CONFIG_POLYFILL_ISNAN) 12192 bool isnan(float f) { 12193 return std::isnan(f); 12194 } 12195 bool isnan(double d) { 12196 return std::isnan(d); 12197 } 12198 #else 12199 // For now we only use this for embarcadero 12200 bool isnan(float f) { 12201 return std::_isnan(f); 12202 } 12203 bool isnan(double d) { 12204 return std::_isnan(d); 12205 } 12206 #endif 12207 12208 } // end namespace Catch 12209 // end catch_polyfills.cpp 12210 // start catch_random_number_generator.cpp 12211 12212 namespace Catch { 12213 12214 namespace { 12215 12216 #if defined(_MSC_VER) 12217 #pragma warning(push) 12218 #pragma warning(disable:4146) // we negate uint32 during the rotate 12219 #endif 12220 // Safe rotr implementation thanks to John Regehr 12221 uint32_t rotate_right(uint32_t val, uint32_t count) { 12222 const uint32_t mask = 31; 12223 count &= mask; 12224 return (val >> count) | (val << (-count & mask)); 12225 } 12226 12227 #if defined(_MSC_VER) 12228 #pragma warning(pop) 12229 #endif 12230 12231 } 12232 12233 SimplePcg32::SimplePcg32(result_type seed_) { 12234 seed(seed_); 12235 } 12236 12237 void SimplePcg32::seed(result_type seed_) { 12238 m_state = 0; 12239 (*this)(); 12240 m_state += seed_; 12241 (*this)(); 12242 } 12243 12244 void SimplePcg32::discard(uint64_t skip) { 12245 // We could implement this to run in O(log n) steps, but this 12246 // should suffice for our use case. 12247 for (uint64_t s = 0; s < skip; ++s) { 12248 static_cast<void>((*this)()); 12249 } 12250 } 12251 12252 SimplePcg32::result_type SimplePcg32::operator()() { 12253 // prepare the output value 12254 const uint32_t xorshifted = static_cast<uint32_t>(((m_state >> 18u) ^ m_state) >> 27u); 12255 const auto output = rotate_right(xorshifted, m_state >> 59u); 12256 12257 // advance state 12258 m_state = m_state * 6364136223846793005ULL + s_inc; 12259 12260 return output; 12261 } 12262 12263 bool operator==(SimplePcg32 const& lhs, SimplePcg32 const& rhs) { 12264 return lhs.m_state == rhs.m_state; 12265 } 12266 12267 bool operator!=(SimplePcg32 const& lhs, SimplePcg32 const& rhs) { 12268 return lhs.m_state != rhs.m_state; 12269 } 12270 } 12271 // end catch_random_number_generator.cpp 12272 // start catch_registry_hub.cpp 12273 12274 // start catch_test_case_registry_impl.h 12275 12276 #include <vector> 12277 #include <set> 12278 #include <algorithm> 12279 #include <ios> 12280 12281 namespace Catch { 12282 12283 class TestCase; 12284 struct IConfig; 12285 12286 std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ); 12287 12288 bool isThrowSafe( TestCase const& testCase, IConfig const& config ); 12289 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); 12290 12291 void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ); 12292 12293 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ); 12294 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ); 12295 12296 class TestRegistry : public ITestCaseRegistry { 12297 public: 12298 virtual ~TestRegistry() = default; 12299 12300 virtual void registerTest( TestCase const& testCase ); 12301 12302 std::vector<TestCase> const& getAllTests() const override; 12303 std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const override; 12304 12305 private: 12306 std::vector<TestCase> m_functions; 12307 mutable RunTests::InWhatOrder m_currentSortOrder = RunTests::InDeclarationOrder; 12308 mutable std::vector<TestCase> m_sortedFunctions; 12309 std::size_t m_unnamedCount = 0; 12310 std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised 12311 }; 12312 12313 /////////////////////////////////////////////////////////////////////////// 12314 12315 class TestInvokerAsFunction : public ITestInvoker { 12316 void(*m_testAsFunction)(); 12317 public: 12318 TestInvokerAsFunction( void(*testAsFunction)() ) noexcept; 12319 12320 void invoke() const override; 12321 }; 12322 12323 std::string extractClassName( StringRef const& classOrQualifiedMethodName ); 12324 12325 /////////////////////////////////////////////////////////////////////////// 12326 12327 } // end namespace Catch 12328 12329 // end catch_test_case_registry_impl.h 12330 // start catch_reporter_registry.h 12331 12332 #include <map> 12333 12334 namespace Catch { 12335 12336 class ReporterRegistry : public IReporterRegistry { 12337 12338 public: 12339 12340 ~ReporterRegistry() override; 12341 12342 IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const override; 12343 12344 void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ); 12345 void registerListener( IReporterFactoryPtr const& factory ); 12346 12347 FactoryMap const& getFactories() const override; 12348 Listeners const& getListeners() const override; 12349 12350 private: 12351 FactoryMap m_factories; 12352 Listeners m_listeners; 12353 }; 12354 } 12355 12356 // end catch_reporter_registry.h 12357 // start catch_tag_alias_registry.h 12358 12359 // start catch_tag_alias.h 12360 12361 #include <string> 12362 12363 namespace Catch { 12364 12365 struct TagAlias { 12366 TagAlias(std::string const& _tag, SourceLineInfo _lineInfo); 12367 12368 std::string tag; 12369 SourceLineInfo lineInfo; 12370 }; 12371 12372 } // end namespace Catch 12373 12374 // end catch_tag_alias.h 12375 #include <map> 12376 12377 namespace Catch { 12378 12379 class TagAliasRegistry : public ITagAliasRegistry { 12380 public: 12381 ~TagAliasRegistry() override; 12382 TagAlias const* find( std::string const& alias ) const override; 12383 std::string expandAliases( std::string const& unexpandedTestSpec ) const override; 12384 void add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ); 12385 12386 private: 12387 std::map<std::string, TagAlias> m_registry; 12388 }; 12389 12390 } // end namespace Catch 12391 12392 // end catch_tag_alias_registry.h 12393 // start catch_startup_exception_registry.h 12394 12395 #include <vector> 12396 #include <exception> 12397 12398 namespace Catch { 12399 12400 class StartupExceptionRegistry { 12401 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 12402 public: 12403 void add(std::exception_ptr const& exception) noexcept; 12404 std::vector<std::exception_ptr> const& getExceptions() const noexcept; 12405 private: 12406 std::vector<std::exception_ptr> m_exceptions; 12407 #endif 12408 }; 12409 12410 } // end namespace Catch 12411 12412 // end catch_startup_exception_registry.h 12413 // start catch_singletons.hpp 12414 12415 namespace Catch { 12416 12417 struct ISingleton { 12418 virtual ~ISingleton(); 12419 }; 12420 12421 void addSingleton( ISingleton* singleton ); 12422 void cleanupSingletons(); 12423 12424 template<typename SingletonImplT, typename InterfaceT = SingletonImplT, typename MutableInterfaceT = InterfaceT> 12425 class Singleton : SingletonImplT, public ISingleton { 12426 12427 static auto getInternal() -> Singleton* { 12428 static Singleton* s_instance = nullptr; 12429 if( !s_instance ) { 12430 s_instance = new Singleton; 12431 addSingleton( s_instance ); 12432 } 12433 return s_instance; 12434 } 12435 12436 public: 12437 static auto get() -> InterfaceT const& { 12438 return *getInternal(); 12439 } 12440 static auto getMutable() -> MutableInterfaceT& { 12441 return *getInternal(); 12442 } 12443 }; 12444 12445 } // namespace Catch 12446 12447 // end catch_singletons.hpp 12448 namespace Catch { 12449 12450 namespace { 12451 12452 class RegistryHub : public IRegistryHub, public IMutableRegistryHub, 12453 private NonCopyable { 12454 12455 public: // IRegistryHub 12456 RegistryHub() = default; 12457 IReporterRegistry const& getReporterRegistry() const override { 12458 return m_reporterRegistry; 12459 } 12460 ITestCaseRegistry const& getTestCaseRegistry() const override { 12461 return m_testCaseRegistry; 12462 } 12463 IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const override { 12464 return m_exceptionTranslatorRegistry; 12465 } 12466 ITagAliasRegistry const& getTagAliasRegistry() const override { 12467 return m_tagAliasRegistry; 12468 } 12469 StartupExceptionRegistry const& getStartupExceptionRegistry() const override { 12470 return m_exceptionRegistry; 12471 } 12472 12473 public: // IMutableRegistryHub 12474 void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) override { 12475 m_reporterRegistry.registerReporter( name, factory ); 12476 } 12477 void registerListener( IReporterFactoryPtr const& factory ) override { 12478 m_reporterRegistry.registerListener( factory ); 12479 } 12480 void registerTest( TestCase const& testInfo ) override { 12481 m_testCaseRegistry.registerTest( testInfo ); 12482 } 12483 void registerTranslator( const IExceptionTranslator* translator ) override { 12484 m_exceptionTranslatorRegistry.registerTranslator( translator ); 12485 } 12486 void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) override { 12487 m_tagAliasRegistry.add( alias, tag, lineInfo ); 12488 } 12489 void registerStartupException() noexcept override { 12490 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 12491 m_exceptionRegistry.add(std::current_exception()); 12492 #else 12493 CATCH_INTERNAL_ERROR("Attempted to register active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!"); 12494 #endif 12495 } 12496 IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() override { 12497 return m_enumValuesRegistry; 12498 } 12499 12500 private: 12501 TestRegistry m_testCaseRegistry; 12502 ReporterRegistry m_reporterRegistry; 12503 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; 12504 TagAliasRegistry m_tagAliasRegistry; 12505 StartupExceptionRegistry m_exceptionRegistry; 12506 Detail::EnumValuesRegistry m_enumValuesRegistry; 12507 }; 12508 } 12509 12510 using RegistryHubSingleton = Singleton<RegistryHub, IRegistryHub, IMutableRegistryHub>; 12511 12512 IRegistryHub const& getRegistryHub() { 12513 return RegistryHubSingleton::get(); 12514 } 12515 IMutableRegistryHub& getMutableRegistryHub() { 12516 return RegistryHubSingleton::getMutable(); 12517 } 12518 void cleanUp() { 12519 cleanupSingletons(); 12520 cleanUpContext(); 12521 } 12522 std::string translateActiveException() { 12523 return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); 12524 } 12525 12526 } // end namespace Catch 12527 // end catch_registry_hub.cpp 12528 // start catch_reporter_registry.cpp 12529 12530 namespace Catch { 12531 12532 ReporterRegistry::~ReporterRegistry() = default; 12533 12534 IStreamingReporterPtr ReporterRegistry::create( std::string const& name, IConfigPtr const& config ) const { 12535 auto it = m_factories.find( name ); 12536 if( it == m_factories.end() ) 12537 return nullptr; 12538 return it->second->create( ReporterConfig( config ) ); 12539 } 12540 12541 void ReporterRegistry::registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) { 12542 m_factories.emplace(name, factory); 12543 } 12544 void ReporterRegistry::registerListener( IReporterFactoryPtr const& factory ) { 12545 m_listeners.push_back( factory ); 12546 } 12547 12548 IReporterRegistry::FactoryMap const& ReporterRegistry::getFactories() const { 12549 return m_factories; 12550 } 12551 IReporterRegistry::Listeners const& ReporterRegistry::getListeners() const { 12552 return m_listeners; 12553 } 12554 12555 } 12556 // end catch_reporter_registry.cpp 12557 // start catch_result_type.cpp 12558 12559 namespace Catch { 12560 12561 bool isOk( ResultWas::OfType resultType ) { 12562 return ( resultType & ResultWas::FailureBit ) == 0; 12563 } 12564 bool isJustInfo( int flags ) { 12565 return flags == ResultWas::Info; 12566 } 12567 12568 ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { 12569 return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( rhs ) ); 12570 } 12571 12572 bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; } 12573 bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; } 12574 12575 } // end namespace Catch 12576 // end catch_result_type.cpp 12577 // start catch_run_context.cpp 12578 12579 #include <cassert> 12580 #include <algorithm> 12581 #include <sstream> 12582 12583 namespace Catch { 12584 12585 namespace Generators { 12586 struct GeneratorTracker : TestCaseTracking::TrackerBase, IGeneratorTracker { 12587 GeneratorBasePtr m_generator; 12588 12589 GeneratorTracker( TestCaseTracking::NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) 12590 : TrackerBase( nameAndLocation, ctx, parent ) 12591 {} 12592 ~GeneratorTracker(); 12593 12594 static GeneratorTracker& acquire( TrackerContext& ctx, TestCaseTracking::NameAndLocation const& nameAndLocation ) { 12595 std::shared_ptr<GeneratorTracker> tracker; 12596 12597 ITracker& currentTracker = ctx.currentTracker(); 12598 // Under specific circumstances, the generator we want 12599 // to acquire is also the current tracker. If this is 12600 // the case, we have to avoid looking through current 12601 // tracker's children, and instead return the current 12602 // tracker. 12603 // A case where this check is important is e.g. 12604 // for (int i = 0; i < 5; ++i) { 12605 // int n = GENERATE(1, 2); 12606 // } 12607 // 12608 // without it, the code above creates 5 nested generators. 12609 if (currentTracker.nameAndLocation() == nameAndLocation) { 12610 auto thisTracker = currentTracker.parent().findChild(nameAndLocation); 12611 assert(thisTracker); 12612 assert(thisTracker->isGeneratorTracker()); 12613 tracker = std::static_pointer_cast<GeneratorTracker>(thisTracker); 12614 } else if ( TestCaseTracking::ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) { 12615 assert( childTracker ); 12616 assert( childTracker->isGeneratorTracker() ); 12617 tracker = std::static_pointer_cast<GeneratorTracker>( childTracker ); 12618 } else { 12619 tracker = std::make_shared<GeneratorTracker>( nameAndLocation, ctx, ¤tTracker ); 12620 currentTracker.addChild( tracker ); 12621 } 12622 12623 if( !tracker->isComplete() ) { 12624 tracker->open(); 12625 } 12626 12627 return *tracker; 12628 } 12629 12630 // TrackerBase interface 12631 bool isGeneratorTracker() const override { return true; } 12632 auto hasGenerator() const -> bool override { 12633 return !!m_generator; 12634 } 12635 void close() override { 12636 TrackerBase::close(); 12637 // If a generator has a child (it is followed by a section) 12638 // and none of its children have started, then we must wait 12639 // until later to start consuming its values. 12640 // This catches cases where `GENERATE` is placed between two 12641 // `SECTION`s. 12642 // **The check for m_children.empty cannot be removed**. 12643 // doing so would break `GENERATE` _not_ followed by `SECTION`s. 12644 const bool should_wait_for_child = [&]() { 12645 // No children -> nobody to wait for 12646 if ( m_children.empty() ) { 12647 return false; 12648 } 12649 // If at least one child started executing, don't wait 12650 if ( std::find_if( 12651 m_children.begin(), 12652 m_children.end(), 12653 []( TestCaseTracking::ITrackerPtr tracker ) { 12654 return tracker->hasStarted(); 12655 } ) != m_children.end() ) { 12656 return false; 12657 } 12658 12659 // No children have started. We need to check if they _can_ 12660 // start, and thus we should wait for them, or they cannot 12661 // start (due to filters), and we shouldn't wait for them 12662 auto* parent = m_parent; 12663 // This is safe: there is always at least one section 12664 // tracker in a test case tracking tree 12665 while ( !parent->isSectionTracker() ) { 12666 parent = &( parent->parent() ); 12667 } 12668 assert( parent && 12669 "Missing root (test case) level section" ); 12670 12671 auto const& parentSection = 12672 static_cast<SectionTracker&>( *parent ); 12673 auto const& filters = parentSection.getFilters(); 12674 // No filters -> no restrictions on running sections 12675 if ( filters.empty() ) { 12676 return true; 12677 } 12678 12679 for ( auto const& child : m_children ) { 12680 if ( child->isSectionTracker() && 12681 std::find( filters.begin(), 12682 filters.end(), 12683 static_cast<SectionTracker&>( *child ) 12684 .trimmedName() ) != 12685 filters.end() ) { 12686 return true; 12687 } 12688 } 12689 return false; 12690 }(); 12691 12692 // This check is a bit tricky, because m_generator->next() 12693 // has a side-effect, where it consumes generator's current 12694 // value, but we do not want to invoke the side-effect if 12695 // this generator is still waiting for any child to start. 12696 if ( should_wait_for_child || 12697 ( m_runState == CompletedSuccessfully && 12698 m_generator->next() ) ) { 12699 m_children.clear(); 12700 m_runState = Executing; 12701 } 12702 } 12703 12704 // IGeneratorTracker interface 12705 auto getGenerator() const -> GeneratorBasePtr const& override { 12706 return m_generator; 12707 } 12708 void setGenerator( GeneratorBasePtr&& generator ) override { 12709 m_generator = std::move( generator ); 12710 } 12711 }; 12712 GeneratorTracker::~GeneratorTracker() {} 12713 } 12714 12715 RunContext::RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter) 12716 : m_runInfo(_config->name()), 12717 m_context(getCurrentMutableContext()), 12718 m_config(_config), 12719 m_reporter(std::move(reporter)), 12720 m_lastAssertionInfo{ StringRef(), SourceLineInfo("",0), StringRef(), ResultDisposition::Normal }, 12721 m_includeSuccessfulResults( m_config->includeSuccessfulResults() || m_reporter->getPreferences().shouldReportAllAssertions ) 12722 { 12723 m_context.setRunner(this); 12724 m_context.setConfig(m_config); 12725 m_context.setResultCapture(this); 12726 m_reporter->testRunStarting(m_runInfo); 12727 } 12728 12729 RunContext::~RunContext() { 12730 m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, aborting())); 12731 } 12732 12733 void RunContext::testGroupStarting(std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount) { 12734 m_reporter->testGroupStarting(GroupInfo(testSpec, groupIndex, groupsCount)); 12735 } 12736 12737 void RunContext::testGroupEnded(std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount) { 12738 m_reporter->testGroupEnded(TestGroupStats(GroupInfo(testSpec, groupIndex, groupsCount), totals, aborting())); 12739 } 12740 12741 Totals RunContext::runTest(TestCase const& testCase) { 12742 Totals prevTotals = m_totals; 12743 12744 std::string redirectedCout; 12745 std::string redirectedCerr; 12746 12747 auto const& testInfo = testCase.getTestCaseInfo(); 12748 12749 m_reporter->testCaseStarting(testInfo); 12750 12751 m_activeTestCase = &testCase; 12752 12753 ITracker& rootTracker = m_trackerContext.startRun(); 12754 assert(rootTracker.isSectionTracker()); 12755 static_cast<SectionTracker&>(rootTracker).addInitialFilters(m_config->getSectionsToRun()); 12756 do { 12757 m_trackerContext.startCycle(); 12758 m_testCaseTracker = &SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(testInfo.name, testInfo.lineInfo)); 12759 runCurrentTest(redirectedCout, redirectedCerr); 12760 } while (!m_testCaseTracker->isSuccessfullyCompleted() && !aborting()); 12761 12762 Totals deltaTotals = m_totals.delta(prevTotals); 12763 if (testInfo.expectedToFail() && deltaTotals.testCases.passed > 0) { 12764 deltaTotals.assertions.failed++; 12765 deltaTotals.testCases.passed--; 12766 deltaTotals.testCases.failed++; 12767 } 12768 m_totals.testCases += deltaTotals.testCases; 12769 m_reporter->testCaseEnded(TestCaseStats(testInfo, 12770 deltaTotals, 12771 redirectedCout, 12772 redirectedCerr, 12773 aborting())); 12774 12775 m_activeTestCase = nullptr; 12776 m_testCaseTracker = nullptr; 12777 12778 return deltaTotals; 12779 } 12780 12781 IConfigPtr RunContext::config() const { 12782 return m_config; 12783 } 12784 12785 IStreamingReporter& RunContext::reporter() const { 12786 return *m_reporter; 12787 } 12788 12789 void RunContext::assertionEnded(AssertionResult const & result) { 12790 if (result.getResultType() == ResultWas::Ok) { 12791 m_totals.assertions.passed++; 12792 m_lastAssertionPassed = true; 12793 } else if (!result.isOk()) { 12794 m_lastAssertionPassed = false; 12795 if( m_activeTestCase->getTestCaseInfo().okToFail() ) 12796 m_totals.assertions.failedButOk++; 12797 else 12798 m_totals.assertions.failed++; 12799 } 12800 else { 12801 m_lastAssertionPassed = true; 12802 } 12803 12804 // We have no use for the return value (whether messages should be cleared), because messages were made scoped 12805 // and should be let to clear themselves out. 12806 static_cast<void>(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals))); 12807 12808 if (result.getResultType() != ResultWas::Warning) 12809 m_messageScopes.clear(); 12810 12811 // Reset working state 12812 resetAssertionInfo(); 12813 m_lastResult = result; 12814 } 12815 void RunContext::resetAssertionInfo() { 12816 m_lastAssertionInfo.macroName = StringRef(); 12817 m_lastAssertionInfo.capturedExpression = "{Unknown expression after the reported line}"_sr; 12818 } 12819 12820 bool RunContext::sectionStarted(SectionInfo const & sectionInfo, Counts & assertions) { 12821 ITracker& sectionTracker = SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(sectionInfo.name, sectionInfo.lineInfo)); 12822 if (!sectionTracker.isOpen()) 12823 return false; 12824 m_activeSections.push_back(§ionTracker); 12825 12826 m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; 12827 12828 m_reporter->sectionStarting(sectionInfo); 12829 12830 assertions = m_totals.assertions; 12831 12832 return true; 12833 } 12834 auto RunContext::acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& { 12835 using namespace Generators; 12836 GeneratorTracker& tracker = GeneratorTracker::acquire(m_trackerContext, 12837 TestCaseTracking::NameAndLocation( static_cast<std::string>(generatorName), lineInfo ) ); 12838 m_lastAssertionInfo.lineInfo = lineInfo; 12839 return tracker; 12840 } 12841 12842 bool RunContext::testForMissingAssertions(Counts& assertions) { 12843 if (assertions.total() != 0) 12844 return false; 12845 if (!m_config->warnAboutMissingAssertions()) 12846 return false; 12847 if (m_trackerContext.currentTracker().hasChildren()) 12848 return false; 12849 m_totals.assertions.failed++; 12850 assertions.failed++; 12851 return true; 12852 } 12853 12854 void RunContext::sectionEnded(SectionEndInfo const & endInfo) { 12855 Counts assertions = m_totals.assertions - endInfo.prevAssertions; 12856 bool missingAssertions = testForMissingAssertions(assertions); 12857 12858 if (!m_activeSections.empty()) { 12859 m_activeSections.back()->close(); 12860 m_activeSections.pop_back(); 12861 } 12862 12863 m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions)); 12864 m_messages.clear(); 12865 m_messageScopes.clear(); 12866 } 12867 12868 void RunContext::sectionEndedEarly(SectionEndInfo const & endInfo) { 12869 if (m_unfinishedSections.empty()) 12870 m_activeSections.back()->fail(); 12871 else 12872 m_activeSections.back()->close(); 12873 m_activeSections.pop_back(); 12874 12875 m_unfinishedSections.push_back(endInfo); 12876 } 12877 12878 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 12879 void RunContext::benchmarkPreparing(std::string const& name) { 12880 m_reporter->benchmarkPreparing(name); 12881 } 12882 void RunContext::benchmarkStarting( BenchmarkInfo const& info ) { 12883 m_reporter->benchmarkStarting( info ); 12884 } 12885 void RunContext::benchmarkEnded( BenchmarkStats<> const& stats ) { 12886 m_reporter->benchmarkEnded( stats ); 12887 } 12888 void RunContext::benchmarkFailed(std::string const & error) { 12889 m_reporter->benchmarkFailed(error); 12890 } 12891 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 12892 12893 void RunContext::pushScopedMessage(MessageInfo const & message) { 12894 m_messages.push_back(message); 12895 } 12896 12897 void RunContext::popScopedMessage(MessageInfo const & message) { 12898 m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end()); 12899 } 12900 12901 void RunContext::emplaceUnscopedMessage( MessageBuilder const& builder ) { 12902 m_messageScopes.emplace_back( builder ); 12903 } 12904 12905 std::string RunContext::getCurrentTestName() const { 12906 return m_activeTestCase 12907 ? m_activeTestCase->getTestCaseInfo().name 12908 : std::string(); 12909 } 12910 12911 const AssertionResult * RunContext::getLastResult() const { 12912 return &(*m_lastResult); 12913 } 12914 12915 void RunContext::exceptionEarlyReported() { 12916 m_shouldReportUnexpected = false; 12917 } 12918 12919 void RunContext::handleFatalErrorCondition( StringRef message ) { 12920 // First notify reporter that bad things happened 12921 m_reporter->fatalErrorEncountered(message); 12922 12923 // Don't rebuild the result -- the stringification itself can cause more fatal errors 12924 // Instead, fake a result data. 12925 AssertionResultData tempResult( ResultWas::FatalErrorCondition, { false } ); 12926 tempResult.message = static_cast<std::string>(message); 12927 AssertionResult result(m_lastAssertionInfo, tempResult); 12928 12929 assertionEnded(result); 12930 12931 handleUnfinishedSections(); 12932 12933 // Recreate section for test case (as we will lose the one that was in scope) 12934 auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); 12935 SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name); 12936 12937 Counts assertions; 12938 assertions.failed = 1; 12939 SectionStats testCaseSectionStats(testCaseSection, assertions, 0, false); 12940 m_reporter->sectionEnded(testCaseSectionStats); 12941 12942 auto const& testInfo = m_activeTestCase->getTestCaseInfo(); 12943 12944 Totals deltaTotals; 12945 deltaTotals.testCases.failed = 1; 12946 deltaTotals.assertions.failed = 1; 12947 m_reporter->testCaseEnded(TestCaseStats(testInfo, 12948 deltaTotals, 12949 std::string(), 12950 std::string(), 12951 false)); 12952 m_totals.testCases.failed++; 12953 testGroupEnded(std::string(), m_totals, 1, 1); 12954 m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, false)); 12955 } 12956 12957 bool RunContext::lastAssertionPassed() { 12958 return m_lastAssertionPassed; 12959 } 12960 12961 void RunContext::assertionPassed() { 12962 m_lastAssertionPassed = true; 12963 ++m_totals.assertions.passed; 12964 resetAssertionInfo(); 12965 m_messageScopes.clear(); 12966 } 12967 12968 bool RunContext::aborting() const { 12969 return m_totals.assertions.failed >= static_cast<std::size_t>(m_config->abortAfter()); 12970 } 12971 12972 void RunContext::runCurrentTest(std::string & redirectedCout, std::string & redirectedCerr) { 12973 auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); 12974 SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name); 12975 m_reporter->sectionStarting(testCaseSection); 12976 Counts prevAssertions = m_totals.assertions; 12977 double duration = 0; 12978 m_shouldReportUnexpected = true; 12979 m_lastAssertionInfo = { "TEST_CASE"_sr, testCaseInfo.lineInfo, StringRef(), ResultDisposition::Normal }; 12980 12981 seedRng(*m_config); 12982 12983 Timer timer; 12984 CATCH_TRY { 12985 if (m_reporter->getPreferences().shouldRedirectStdOut) { 12986 #if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) 12987 RedirectedStreams redirectedStreams(redirectedCout, redirectedCerr); 12988 12989 timer.start(); 12990 invokeActiveTestCase(); 12991 #else 12992 OutputRedirect r(redirectedCout, redirectedCerr); 12993 timer.start(); 12994 invokeActiveTestCase(); 12995 #endif 12996 } else { 12997 timer.start(); 12998 invokeActiveTestCase(); 12999 } 13000 duration = timer.getElapsedSeconds(); 13001 } CATCH_CATCH_ANON (TestFailureException&) { 13002 // This just means the test was aborted due to failure 13003 } CATCH_CATCH_ALL { 13004 // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions 13005 // are reported without translation at the point of origin. 13006 if( m_shouldReportUnexpected ) { 13007 AssertionReaction dummyReaction; 13008 handleUnexpectedInflightException( m_lastAssertionInfo, translateActiveException(), dummyReaction ); 13009 } 13010 } 13011 Counts assertions = m_totals.assertions - prevAssertions; 13012 bool missingAssertions = testForMissingAssertions(assertions); 13013 13014 m_testCaseTracker->close(); 13015 handleUnfinishedSections(); 13016 m_messages.clear(); 13017 m_messageScopes.clear(); 13018 13019 SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions); 13020 m_reporter->sectionEnded(testCaseSectionStats); 13021 } 13022 13023 void RunContext::invokeActiveTestCase() { 13024 FatalConditionHandlerGuard _(&m_fatalConditionhandler); 13025 m_activeTestCase->invoke(); 13026 } 13027 13028 void RunContext::handleUnfinishedSections() { 13029 // If sections ended prematurely due to an exception we stored their 13030 // infos here so we can tear them down outside the unwind process. 13031 for (auto it = m_unfinishedSections.rbegin(), 13032 itEnd = m_unfinishedSections.rend(); 13033 it != itEnd; 13034 ++it) 13035 sectionEnded(*it); 13036 m_unfinishedSections.clear(); 13037 } 13038 13039 void RunContext::handleExpr( 13040 AssertionInfo const& info, 13041 ITransientExpression const& expr, 13042 AssertionReaction& reaction 13043 ) { 13044 m_reporter->assertionStarting( info ); 13045 13046 bool negated = isFalseTest( info.resultDisposition ); 13047 bool result = expr.getResult() != negated; 13048 13049 if( result ) { 13050 if (!m_includeSuccessfulResults) { 13051 assertionPassed(); 13052 } 13053 else { 13054 reportExpr(info, ResultWas::Ok, &expr, negated); 13055 } 13056 } 13057 else { 13058 reportExpr(info, ResultWas::ExpressionFailed, &expr, negated ); 13059 populateReaction( reaction ); 13060 } 13061 } 13062 void RunContext::reportExpr( 13063 AssertionInfo const &info, 13064 ResultWas::OfType resultType, 13065 ITransientExpression const *expr, 13066 bool negated ) { 13067 13068 m_lastAssertionInfo = info; 13069 AssertionResultData data( resultType, LazyExpression( negated ) ); 13070 13071 AssertionResult assertionResult{ info, data }; 13072 assertionResult.m_resultData.lazyExpression.m_transientExpression = expr; 13073 13074 assertionEnded( assertionResult ); 13075 } 13076 13077 void RunContext::handleMessage( 13078 AssertionInfo const& info, 13079 ResultWas::OfType resultType, 13080 StringRef const& message, 13081 AssertionReaction& reaction 13082 ) { 13083 m_reporter->assertionStarting( info ); 13084 13085 m_lastAssertionInfo = info; 13086 13087 AssertionResultData data( resultType, LazyExpression( false ) ); 13088 data.message = static_cast<std::string>(message); 13089 AssertionResult assertionResult{ m_lastAssertionInfo, data }; 13090 assertionEnded( assertionResult ); 13091 if( !assertionResult.isOk() ) 13092 populateReaction( reaction ); 13093 } 13094 void RunContext::handleUnexpectedExceptionNotThrown( 13095 AssertionInfo const& info, 13096 AssertionReaction& reaction 13097 ) { 13098 handleNonExpr(info, Catch::ResultWas::DidntThrowException, reaction); 13099 } 13100 13101 void RunContext::handleUnexpectedInflightException( 13102 AssertionInfo const& info, 13103 std::string const& message, 13104 AssertionReaction& reaction 13105 ) { 13106 m_lastAssertionInfo = info; 13107 13108 AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) ); 13109 data.message = message; 13110 AssertionResult assertionResult{ info, data }; 13111 assertionEnded( assertionResult ); 13112 populateReaction( reaction ); 13113 } 13114 13115 void RunContext::populateReaction( AssertionReaction& reaction ) { 13116 reaction.shouldDebugBreak = m_config->shouldDebugBreak(); 13117 reaction.shouldThrow = aborting() || (m_lastAssertionInfo.resultDisposition & ResultDisposition::Normal); 13118 } 13119 13120 void RunContext::handleIncomplete( 13121 AssertionInfo const& info 13122 ) { 13123 m_lastAssertionInfo = info; 13124 13125 AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) ); 13126 data.message = "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE"; 13127 AssertionResult assertionResult{ info, data }; 13128 assertionEnded( assertionResult ); 13129 } 13130 void RunContext::handleNonExpr( 13131 AssertionInfo const &info, 13132 ResultWas::OfType resultType, 13133 AssertionReaction &reaction 13134 ) { 13135 m_lastAssertionInfo = info; 13136 13137 AssertionResultData data( resultType, LazyExpression( false ) ); 13138 AssertionResult assertionResult{ info, data }; 13139 assertionEnded( assertionResult ); 13140 13141 if( !assertionResult.isOk() ) 13142 populateReaction( reaction ); 13143 } 13144 13145 IResultCapture& getResultCapture() { 13146 if (auto* capture = getCurrentContext().getResultCapture()) 13147 return *capture; 13148 else 13149 CATCH_INTERNAL_ERROR("No result capture instance"); 13150 } 13151 13152 void seedRng(IConfig const& config) { 13153 if (config.rngSeed() != 0) { 13154 std::srand(config.rngSeed()); 13155 rng().seed(config.rngSeed()); 13156 } 13157 } 13158 13159 unsigned int rngSeed() { 13160 return getCurrentContext().getConfig()->rngSeed(); 13161 } 13162 13163 } 13164 // end catch_run_context.cpp 13165 // start catch_section.cpp 13166 13167 namespace Catch { 13168 13169 Section::Section( SectionInfo const& info ) 13170 : m_info( info ), 13171 m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) ) 13172 { 13173 m_timer.start(); 13174 } 13175 13176 Section::~Section() { 13177 if( m_sectionIncluded ) { 13178 SectionEndInfo endInfo{ m_info, m_assertions, m_timer.getElapsedSeconds() }; 13179 if( uncaught_exceptions() ) 13180 getResultCapture().sectionEndedEarly( endInfo ); 13181 else 13182 getResultCapture().sectionEnded( endInfo ); 13183 } 13184 } 13185 13186 // This indicates whether the section should be executed or not 13187 Section::operator bool() const { 13188 return m_sectionIncluded; 13189 } 13190 13191 } // end namespace Catch 13192 // end catch_section.cpp 13193 // start catch_section_info.cpp 13194 13195 namespace Catch { 13196 13197 SectionInfo::SectionInfo 13198 ( SourceLineInfo const& _lineInfo, 13199 std::string const& _name ) 13200 : name( _name ), 13201 lineInfo( _lineInfo ) 13202 {} 13203 13204 } // end namespace Catch 13205 // end catch_section_info.cpp 13206 // start catch_session.cpp 13207 13208 // start catch_session.h 13209 13210 #include <memory> 13211 13212 namespace Catch { 13213 13214 class Session : NonCopyable { 13215 public: 13216 13217 Session(); 13218 ~Session() override; 13219 13220 void showHelp() const; 13221 void libIdentify(); 13222 13223 int applyCommandLine( int argc, char const * const * argv ); 13224 #if defined(CATCH_CONFIG_WCHAR) && defined(_WIN32) && defined(UNICODE) 13225 int applyCommandLine( int argc, wchar_t const * const * argv ); 13226 #endif 13227 13228 void useConfigData( ConfigData const& configData ); 13229 13230 template<typename CharT> 13231 int run(int argc, CharT const * const argv[]) { 13232 if (m_startupExceptions) 13233 return 1; 13234 int returnCode = applyCommandLine(argc, argv); 13235 if (returnCode == 0) 13236 returnCode = run(); 13237 return returnCode; 13238 } 13239 13240 int run(); 13241 13242 clara::Parser const& cli() const; 13243 void cli( clara::Parser const& newParser ); 13244 ConfigData& configData(); 13245 Config& config(); 13246 private: 13247 int runInternal(); 13248 13249 clara::Parser m_cli; 13250 ConfigData m_configData; 13251 std::shared_ptr<Config> m_config; 13252 bool m_startupExceptions = false; 13253 }; 13254 13255 } // end namespace Catch 13256 13257 // end catch_session.h 13258 // start catch_version.h 13259 13260 #include <iosfwd> 13261 13262 namespace Catch { 13263 13264 // Versioning information 13265 struct Version { 13266 Version( Version const& ) = delete; 13267 Version& operator=( Version const& ) = delete; 13268 Version( unsigned int _majorVersion, 13269 unsigned int _minorVersion, 13270 unsigned int _patchNumber, 13271 char const * const _branchName, 13272 unsigned int _buildNumber ); 13273 13274 unsigned int const majorVersion; 13275 unsigned int const minorVersion; 13276 unsigned int const patchNumber; 13277 13278 // buildNumber is only used if branchName is not null 13279 char const * const branchName; 13280 unsigned int const buildNumber; 13281 13282 friend std::ostream& operator << ( std::ostream& os, Version const& version ); 13283 }; 13284 13285 Version const& libraryVersion(); 13286 } 13287 13288 // end catch_version.h 13289 #include <cstdlib> 13290 #include <iomanip> 13291 #include <set> 13292 #include <iterator> 13293 13294 namespace Catch { 13295 13296 namespace { 13297 const int MaxExitCode = 255; 13298 13299 IStreamingReporterPtr createReporter(std::string const& reporterName, IConfigPtr const& config) { 13300 auto reporter = Catch::getRegistryHub().getReporterRegistry().create(reporterName, config); 13301 CATCH_ENFORCE(reporter, "No reporter registered with name: '" << reporterName << "'"); 13302 13303 return reporter; 13304 } 13305 13306 IStreamingReporterPtr makeReporter(std::shared_ptr<Config> const& config) { 13307 if (Catch::getRegistryHub().getReporterRegistry().getListeners().empty()) { 13308 return createReporter(config->getReporterName(), config); 13309 } 13310 13311 // On older platforms, returning std::unique_ptr<ListeningReporter> 13312 // when the return type is std::unique_ptr<IStreamingReporter> 13313 // doesn't compile without a std::move call. However, this causes 13314 // a warning on newer platforms. Thus, we have to work around 13315 // it a bit and downcast the pointer manually. 13316 auto ret = std::unique_ptr<IStreamingReporter>(new ListeningReporter); 13317 auto& multi = static_cast<ListeningReporter&>(*ret); 13318 auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners(); 13319 for (auto const& listener : listeners) { 13320 multi.addListener(listener->create(Catch::ReporterConfig(config))); 13321 } 13322 multi.addReporter(createReporter(config->getReporterName(), config)); 13323 return ret; 13324 } 13325 13326 class TestGroup { 13327 public: 13328 explicit TestGroup(std::shared_ptr<Config> const& config) 13329 : m_config{config} 13330 , m_context{config, makeReporter(config)} 13331 { 13332 auto const& allTestCases = getAllTestCasesSorted(*m_config); 13333 m_matches = m_config->testSpec().matchesByFilter(allTestCases, *m_config); 13334 auto const& invalidArgs = m_config->testSpec().getInvalidArgs(); 13335 13336 if (m_matches.empty() && invalidArgs.empty()) { 13337 for (auto const& test : allTestCases) 13338 if (!test.isHidden()) 13339 m_tests.emplace(&test); 13340 } else { 13341 for (auto const& match : m_matches) 13342 m_tests.insert(match.tests.begin(), match.tests.end()); 13343 } 13344 } 13345 13346 Totals execute() { 13347 auto const& invalidArgs = m_config->testSpec().getInvalidArgs(); 13348 Totals totals; 13349 m_context.testGroupStarting(m_config->name(), 1, 1); 13350 for (auto const& testCase : m_tests) { 13351 if (!m_context.aborting()) 13352 totals += m_context.runTest(*testCase); 13353 else 13354 m_context.reporter().skipTest(*testCase); 13355 } 13356 13357 for (auto const& match : m_matches) { 13358 if (match.tests.empty()) { 13359 m_context.reporter().noMatchingTestCases(match.name); 13360 totals.error = -1; 13361 } 13362 } 13363 13364 if (!invalidArgs.empty()) { 13365 for (auto const& invalidArg: invalidArgs) 13366 m_context.reporter().reportInvalidArguments(invalidArg); 13367 } 13368 13369 m_context.testGroupEnded(m_config->name(), totals, 1, 1); 13370 return totals; 13371 } 13372 13373 private: 13374 using Tests = std::set<TestCase const*>; 13375 13376 std::shared_ptr<Config> m_config; 13377 RunContext m_context; 13378 Tests m_tests; 13379 TestSpec::Matches m_matches; 13380 }; 13381 13382 void applyFilenamesAsTags(Catch::IConfig const& config) { 13383 auto& tests = const_cast<std::vector<TestCase>&>(getAllTestCasesSorted(config)); 13384 for (auto& testCase : tests) { 13385 auto tags = testCase.tags; 13386 13387 std::string filename = testCase.lineInfo.file; 13388 auto lastSlash = filename.find_last_of("\\/"); 13389 if (lastSlash != std::string::npos) { 13390 filename.erase(0, lastSlash); 13391 filename[0] = '#'; 13392 } 13393 else 13394 { 13395 filename.insert(0, "#"); 13396 } 13397 13398 auto lastDot = filename.find_last_of('.'); 13399 if (lastDot != std::string::npos) { 13400 filename.erase(lastDot); 13401 } 13402 13403 tags.push_back(std::move(filename)); 13404 setTags(testCase, tags); 13405 } 13406 } 13407 13408 } // anon namespace 13409 13410 Session::Session() { 13411 static bool alreadyInstantiated = false; 13412 if( alreadyInstantiated ) { 13413 CATCH_TRY { CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" ); } 13414 CATCH_CATCH_ALL { getMutableRegistryHub().registerStartupException(); } 13415 } 13416 13417 // There cannot be exceptions at startup in no-exception mode. 13418 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 13419 const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions(); 13420 if ( !exceptions.empty() ) { 13421 config(); 13422 getCurrentMutableContext().setConfig(m_config); 13423 13424 m_startupExceptions = true; 13425 Colour colourGuard( Colour::Red ); 13426 Catch::cerr() << "Errors occurred during startup!" << '\n'; 13427 // iterate over all exceptions and notify user 13428 for ( const auto& ex_ptr : exceptions ) { 13429 try { 13430 std::rethrow_exception(ex_ptr); 13431 } catch ( std::exception const& ex ) { 13432 Catch::cerr() << Column( ex.what() ).indent(2) << '\n'; 13433 } 13434 } 13435 } 13436 #endif 13437 13438 alreadyInstantiated = true; 13439 m_cli = makeCommandLineParser( m_configData ); 13440 } 13441 Session::~Session() { 13442 Catch::cleanUp(); 13443 } 13444 13445 void Session::showHelp() const { 13446 Catch::cout() 13447 << "\nCatch v" << libraryVersion() << "\n" 13448 << m_cli << std::endl 13449 << "For more detailed usage please see the project docs\n" << std::endl; 13450 } 13451 void Session::libIdentify() { 13452 Catch::cout() 13453 << std::left << std::setw(16) << "description: " << "A Catch2 test executable\n" 13454 << std::left << std::setw(16) << "category: " << "testframework\n" 13455 << std::left << std::setw(16) << "framework: " << "Catch Test\n" 13456 << std::left << std::setw(16) << "version: " << libraryVersion() << std::endl; 13457 } 13458 13459 int Session::applyCommandLine( int argc, char const * const * argv ) { 13460 if( m_startupExceptions ) 13461 return 1; 13462 13463 auto result = m_cli.parse( clara::Args( argc, argv ) ); 13464 if( !result ) { 13465 config(); 13466 getCurrentMutableContext().setConfig(m_config); 13467 Catch::cerr() 13468 << Colour( Colour::Red ) 13469 << "\nError(s) in input:\n" 13470 << Column( result.errorMessage() ).indent( 2 ) 13471 << "\n\n"; 13472 Catch::cerr() << "Run with -? for usage\n" << std::endl; 13473 return MaxExitCode; 13474 } 13475 13476 if( m_configData.showHelp ) 13477 showHelp(); 13478 if( m_configData.libIdentify ) 13479 libIdentify(); 13480 m_config.reset(); 13481 return 0; 13482 } 13483 13484 #if defined(CATCH_CONFIG_WCHAR) && defined(_WIN32) && defined(UNICODE) 13485 int Session::applyCommandLine( int argc, wchar_t const * const * argv ) { 13486 13487 char **utf8Argv = new char *[ argc ]; 13488 13489 for ( int i = 0; i < argc; ++i ) { 13490 int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, nullptr, 0, nullptr, nullptr ); 13491 13492 utf8Argv[ i ] = new char[ bufSize ]; 13493 13494 WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, nullptr, nullptr ); 13495 } 13496 13497 int returnCode = applyCommandLine( argc, utf8Argv ); 13498 13499 for ( int i = 0; i < argc; ++i ) 13500 delete [] utf8Argv[ i ]; 13501 13502 delete [] utf8Argv; 13503 13504 return returnCode; 13505 } 13506 #endif 13507 13508 void Session::useConfigData( ConfigData const& configData ) { 13509 m_configData = configData; 13510 m_config.reset(); 13511 } 13512 13513 int Session::run() { 13514 if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) { 13515 Catch::cout() << "...waiting for enter/ return before starting" << std::endl; 13516 static_cast<void>(std::getchar()); 13517 } 13518 int exitCode = runInternal(); 13519 if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) { 13520 Catch::cout() << "...waiting for enter/ return before exiting, with code: " << exitCode << std::endl; 13521 static_cast<void>(std::getchar()); 13522 } 13523 return exitCode; 13524 } 13525 13526 clara::Parser const& Session::cli() const { 13527 return m_cli; 13528 } 13529 void Session::cli( clara::Parser const& newParser ) { 13530 m_cli = newParser; 13531 } 13532 ConfigData& Session::configData() { 13533 return m_configData; 13534 } 13535 Config& Session::config() { 13536 if( !m_config ) 13537 m_config = std::make_shared<Config>( m_configData ); 13538 return *m_config; 13539 } 13540 13541 int Session::runInternal() { 13542 if( m_startupExceptions ) 13543 return 1; 13544 13545 if (m_configData.showHelp || m_configData.libIdentify) { 13546 return 0; 13547 } 13548 13549 CATCH_TRY { 13550 config(); // Force config to be constructed 13551 13552 seedRng( *m_config ); 13553 13554 if( m_configData.filenamesAsTags ) 13555 applyFilenamesAsTags( *m_config ); 13556 13557 // Handle list request 13558 if( Option<std::size_t> listed = list( m_config ) ) 13559 return (std::min) (MaxExitCode, static_cast<int>(*listed)); 13560 13561 TestGroup tests { m_config }; 13562 auto const totals = tests.execute(); 13563 13564 if( m_config->warnAboutNoTests() && totals.error == -1 ) 13565 return 2; 13566 13567 // Note that on unices only the lower 8 bits are usually used, clamping 13568 // the return value to 255 prevents false negative when some multiple 13569 // of 256 tests has failed 13570 return (std::min) (MaxExitCode, (std::max) (totals.error, static_cast<int>(totals.assertions.failed))); 13571 } 13572 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 13573 catch( std::exception& ex ) { 13574 Catch::cerr() << ex.what() << std::endl; 13575 return MaxExitCode; 13576 } 13577 #endif 13578 } 13579 13580 } // end namespace Catch 13581 // end catch_session.cpp 13582 // start catch_singletons.cpp 13583 13584 #include <vector> 13585 13586 namespace Catch { 13587 13588 namespace { 13589 static auto getSingletons() -> std::vector<ISingleton*>*& { 13590 static std::vector<ISingleton*>* g_singletons = nullptr; 13591 if( !g_singletons ) 13592 g_singletons = new std::vector<ISingleton*>(); 13593 return g_singletons; 13594 } 13595 } 13596 13597 ISingleton::~ISingleton() {} 13598 13599 void addSingleton(ISingleton* singleton ) { 13600 getSingletons()->push_back( singleton ); 13601 } 13602 void cleanupSingletons() { 13603 auto& singletons = getSingletons(); 13604 for( auto singleton : *singletons ) 13605 delete singleton; 13606 delete singletons; 13607 singletons = nullptr; 13608 } 13609 13610 } // namespace Catch 13611 // end catch_singletons.cpp 13612 // start catch_startup_exception_registry.cpp 13613 13614 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 13615 namespace Catch { 13616 void StartupExceptionRegistry::add( std::exception_ptr const& exception ) noexcept { 13617 CATCH_TRY { 13618 m_exceptions.push_back(exception); 13619 } CATCH_CATCH_ALL { 13620 // If we run out of memory during start-up there's really not a lot more we can do about it 13621 std::terminate(); 13622 } 13623 } 13624 13625 std::vector<std::exception_ptr> const& StartupExceptionRegistry::getExceptions() const noexcept { 13626 return m_exceptions; 13627 } 13628 13629 } // end namespace Catch 13630 #endif 13631 // end catch_startup_exception_registry.cpp 13632 // start catch_stream.cpp 13633 13634 #include <cstdio> 13635 #include <iostream> 13636 #include <fstream> 13637 #include <sstream> 13638 #include <vector> 13639 #include <memory> 13640 13641 namespace Catch { 13642 13643 Catch::IStream::~IStream() = default; 13644 13645 namespace Detail { namespace { 13646 template<typename WriterF, std::size_t bufferSize=256> 13647 class StreamBufImpl : public std::streambuf { 13648 char data[bufferSize]; 13649 WriterF m_writer; 13650 13651 public: 13652 StreamBufImpl() { 13653 setp( data, data + sizeof(data) ); 13654 } 13655 13656 ~StreamBufImpl() noexcept { 13657 StreamBufImpl::sync(); 13658 } 13659 13660 private: 13661 int overflow( int c ) override { 13662 sync(); 13663 13664 if( c != EOF ) { 13665 if( pbase() == epptr() ) 13666 m_writer( std::string( 1, static_cast<char>( c ) ) ); 13667 else 13668 sputc( static_cast<char>( c ) ); 13669 } 13670 return 0; 13671 } 13672 13673 int sync() override { 13674 if( pbase() != pptr() ) { 13675 m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) ); 13676 setp( pbase(), epptr() ); 13677 } 13678 return 0; 13679 } 13680 }; 13681 13682 /////////////////////////////////////////////////////////////////////////// 13683 13684 struct OutputDebugWriter { 13685 13686 void operator()( std::string const&str ) { 13687 writeToDebugConsole( str ); 13688 } 13689 }; 13690 13691 /////////////////////////////////////////////////////////////////////////// 13692 13693 class FileStream : public IStream { 13694 mutable std::ofstream m_ofs; 13695 public: 13696 FileStream( StringRef filename ) { 13697 m_ofs.open( filename.c_str() ); 13698 CATCH_ENFORCE( !m_ofs.fail(), "Unable to open file: '" << filename << "'" ); 13699 } 13700 ~FileStream() override = default; 13701 public: // IStream 13702 std::ostream& stream() const override { 13703 return m_ofs; 13704 } 13705 }; 13706 13707 /////////////////////////////////////////////////////////////////////////// 13708 13709 class CoutStream : public IStream { 13710 mutable std::ostream m_os; 13711 public: 13712 // Store the streambuf from cout up-front because 13713 // cout may get redirected when running tests 13714 CoutStream() : m_os( Catch::cout().rdbuf() ) {} 13715 ~CoutStream() override = default; 13716 13717 public: // IStream 13718 std::ostream& stream() const override { return m_os; } 13719 }; 13720 13721 /////////////////////////////////////////////////////////////////////////// 13722 13723 class DebugOutStream : public IStream { 13724 std::unique_ptr<StreamBufImpl<OutputDebugWriter>> m_streamBuf; 13725 mutable std::ostream m_os; 13726 public: 13727 DebugOutStream() 13728 : m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ), 13729 m_os( m_streamBuf.get() ) 13730 {} 13731 13732 ~DebugOutStream() override = default; 13733 13734 public: // IStream 13735 std::ostream& stream() const override { return m_os; } 13736 }; 13737 13738 }} // namespace anon::detail 13739 13740 /////////////////////////////////////////////////////////////////////////// 13741 13742 auto makeStream( StringRef const &filename ) -> IStream const* { 13743 if( filename.empty() ) 13744 return new Detail::CoutStream(); 13745 else if( filename[0] == '%' ) { 13746 if( filename == "%debug" ) 13747 return new Detail::DebugOutStream(); 13748 else 13749 CATCH_ERROR( "Unrecognised stream: '" << filename << "'" ); 13750 } 13751 else 13752 return new Detail::FileStream( filename ); 13753 } 13754 13755 // This class encapsulates the idea of a pool of ostringstreams that can be reused. 13756 struct StringStreams { 13757 std::vector<std::unique_ptr<std::ostringstream>> m_streams; 13758 std::vector<std::size_t> m_unused; 13759 std::ostringstream m_referenceStream; // Used for copy state/ flags from 13760 13761 auto add() -> std::size_t { 13762 if( m_unused.empty() ) { 13763 m_streams.push_back( std::unique_ptr<std::ostringstream>( new std::ostringstream ) ); 13764 return m_streams.size()-1; 13765 } 13766 else { 13767 auto index = m_unused.back(); 13768 m_unused.pop_back(); 13769 return index; 13770 } 13771 } 13772 13773 void release( std::size_t index ) { 13774 m_streams[index]->copyfmt( m_referenceStream ); // Restore initial flags and other state 13775 m_unused.push_back(index); 13776 } 13777 }; 13778 13779 ReusableStringStream::ReusableStringStream() 13780 : m_index( Singleton<StringStreams>::getMutable().add() ), 13781 m_oss( Singleton<StringStreams>::getMutable().m_streams[m_index].get() ) 13782 {} 13783 13784 ReusableStringStream::~ReusableStringStream() { 13785 static_cast<std::ostringstream*>( m_oss )->str(""); 13786 m_oss->clear(); 13787 Singleton<StringStreams>::getMutable().release( m_index ); 13788 } 13789 13790 auto ReusableStringStream::str() const -> std::string { 13791 return static_cast<std::ostringstream*>( m_oss )->str(); 13792 } 13793 13794 /////////////////////////////////////////////////////////////////////////// 13795 13796 #ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions 13797 std::ostream& cout() { return std::cout; } 13798 std::ostream& cerr() { return std::cerr; } 13799 std::ostream& clog() { return std::clog; } 13800 #endif 13801 } 13802 // end catch_stream.cpp 13803 // start catch_string_manip.cpp 13804 13805 #include <algorithm> 13806 #include <ostream> 13807 #include <cstring> 13808 #include <cctype> 13809 #include <vector> 13810 13811 namespace Catch { 13812 13813 namespace { 13814 char toLowerCh(char c) { 13815 return static_cast<char>( std::tolower( static_cast<unsigned char>(c) ) ); 13816 } 13817 } 13818 13819 bool startsWith( std::string const& s, std::string const& prefix ) { 13820 return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin()); 13821 } 13822 bool startsWith( std::string const& s, char prefix ) { 13823 return !s.empty() && s[0] == prefix; 13824 } 13825 bool endsWith( std::string const& s, std::string const& suffix ) { 13826 return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin()); 13827 } 13828 bool endsWith( std::string const& s, char suffix ) { 13829 return !s.empty() && s[s.size()-1] == suffix; 13830 } 13831 bool contains( std::string const& s, std::string const& infix ) { 13832 return s.find( infix ) != std::string::npos; 13833 } 13834 void toLowerInPlace( std::string& s ) { 13835 std::transform( s.begin(), s.end(), s.begin(), toLowerCh ); 13836 } 13837 std::string toLower( std::string const& s ) { 13838 std::string lc = s; 13839 toLowerInPlace( lc ); 13840 return lc; 13841 } 13842 std::string trim( std::string const& str ) { 13843 static char const* whitespaceChars = "\n\r\t "; 13844 std::string::size_type start = str.find_first_not_of( whitespaceChars ); 13845 std::string::size_type end = str.find_last_not_of( whitespaceChars ); 13846 13847 return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string(); 13848 } 13849 13850 StringRef trim(StringRef ref) { 13851 const auto is_ws = [](char c) { 13852 return c == ' ' || c == '\t' || c == '\n' || c == '\r'; 13853 }; 13854 size_t real_begin = 0; 13855 while (real_begin < ref.size() && is_ws(ref[real_begin])) { ++real_begin; } 13856 size_t real_end = ref.size(); 13857 while (real_end > real_begin && is_ws(ref[real_end - 1])) { --real_end; } 13858 13859 return ref.substr(real_begin, real_end - real_begin); 13860 } 13861 13862 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) { 13863 bool replaced = false; 13864 std::size_t i = str.find( replaceThis ); 13865 while( i != std::string::npos ) { 13866 replaced = true; 13867 str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() ); 13868 if( i < str.size()-withThis.size() ) 13869 i = str.find( replaceThis, i+withThis.size() ); 13870 else 13871 i = std::string::npos; 13872 } 13873 return replaced; 13874 } 13875 13876 std::vector<StringRef> splitStringRef( StringRef str, char delimiter ) { 13877 std::vector<StringRef> subStrings; 13878 std::size_t start = 0; 13879 for(std::size_t pos = 0; pos < str.size(); ++pos ) { 13880 if( str[pos] == delimiter ) { 13881 if( pos - start > 1 ) 13882 subStrings.push_back( str.substr( start, pos-start ) ); 13883 start = pos+1; 13884 } 13885 } 13886 if( start < str.size() ) 13887 subStrings.push_back( str.substr( start, str.size()-start ) ); 13888 return subStrings; 13889 } 13890 13891 pluralise::pluralise( std::size_t count, std::string const& label ) 13892 : m_count( count ), 13893 m_label( label ) 13894 {} 13895 13896 std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { 13897 os << pluraliser.m_count << ' ' << pluraliser.m_label; 13898 if( pluraliser.m_count != 1 ) 13899 os << 's'; 13900 return os; 13901 } 13902 13903 } 13904 // end catch_string_manip.cpp 13905 // start catch_stringref.cpp 13906 13907 #include <algorithm> 13908 #include <ostream> 13909 #include <cstring> 13910 #include <cstdint> 13911 13912 namespace Catch { 13913 StringRef::StringRef( char const* rawChars ) noexcept 13914 : StringRef( rawChars, static_cast<StringRef::size_type>(std::strlen(rawChars) ) ) 13915 {} 13916 13917 auto StringRef::c_str() const -> char const* { 13918 CATCH_ENFORCE(isNullTerminated(), "Called StringRef::c_str() on a non-null-terminated instance"); 13919 return m_start; 13920 } 13921 auto StringRef::data() const noexcept -> char const* { 13922 return m_start; 13923 } 13924 13925 auto StringRef::substr( size_type start, size_type size ) const noexcept -> StringRef { 13926 if (start < m_size) { 13927 return StringRef(m_start + start, (std::min)(m_size - start, size)); 13928 } else { 13929 return StringRef(); 13930 } 13931 } 13932 auto StringRef::operator == ( StringRef const& other ) const noexcept -> bool { 13933 return m_size == other.m_size 13934 && (std::memcmp( m_start, other.m_start, m_size ) == 0); 13935 } 13936 13937 auto operator << ( std::ostream& os, StringRef const& str ) -> std::ostream& { 13938 return os.write(str.data(), str.size()); 13939 } 13940 13941 auto operator+=( std::string& lhs, StringRef const& rhs ) -> std::string& { 13942 lhs.append(rhs.data(), rhs.size()); 13943 return lhs; 13944 } 13945 13946 } // namespace Catch 13947 // end catch_stringref.cpp 13948 // start catch_tag_alias.cpp 13949 13950 namespace Catch { 13951 TagAlias::TagAlias(std::string const & _tag, SourceLineInfo _lineInfo): tag(_tag), lineInfo(_lineInfo) {} 13952 } 13953 // end catch_tag_alias.cpp 13954 // start catch_tag_alias_autoregistrar.cpp 13955 13956 namespace Catch { 13957 13958 RegistrarForTagAliases::RegistrarForTagAliases(char const* alias, char const* tag, SourceLineInfo const& lineInfo) { 13959 CATCH_TRY { 13960 getMutableRegistryHub().registerTagAlias(alias, tag, lineInfo); 13961 } CATCH_CATCH_ALL { 13962 // Do not throw when constructing global objects, instead register the exception to be processed later 13963 getMutableRegistryHub().registerStartupException(); 13964 } 13965 } 13966 13967 } 13968 // end catch_tag_alias_autoregistrar.cpp 13969 // start catch_tag_alias_registry.cpp 13970 13971 #include <sstream> 13972 13973 namespace Catch { 13974 13975 TagAliasRegistry::~TagAliasRegistry() {} 13976 13977 TagAlias const* TagAliasRegistry::find( std::string const& alias ) const { 13978 auto it = m_registry.find( alias ); 13979 if( it != m_registry.end() ) 13980 return &(it->second); 13981 else 13982 return nullptr; 13983 } 13984 13985 std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const { 13986 std::string expandedTestSpec = unexpandedTestSpec; 13987 for( auto const& registryKvp : m_registry ) { 13988 std::size_t pos = expandedTestSpec.find( registryKvp.first ); 13989 if( pos != std::string::npos ) { 13990 expandedTestSpec = expandedTestSpec.substr( 0, pos ) + 13991 registryKvp.second.tag + 13992 expandedTestSpec.substr( pos + registryKvp.first.size() ); 13993 } 13994 } 13995 return expandedTestSpec; 13996 } 13997 13998 void TagAliasRegistry::add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) { 13999 CATCH_ENFORCE( startsWith(alias, "[@") && endsWith(alias, ']'), 14000 "error: tag alias, '" << alias << "' is not of the form [@alias name].\n" << lineInfo ); 14001 14002 CATCH_ENFORCE( m_registry.insert(std::make_pair(alias, TagAlias(tag, lineInfo))).second, 14003 "error: tag alias, '" << alias << "' already registered.\n" 14004 << "\tFirst seen at: " << find(alias)->lineInfo << "\n" 14005 << "\tRedefined at: " << lineInfo ); 14006 } 14007 14008 ITagAliasRegistry::~ITagAliasRegistry() {} 14009 14010 ITagAliasRegistry const& ITagAliasRegistry::get() { 14011 return getRegistryHub().getTagAliasRegistry(); 14012 } 14013 14014 } // end namespace Catch 14015 // end catch_tag_alias_registry.cpp 14016 // start catch_test_case_info.cpp 14017 14018 #include <cctype> 14019 #include <exception> 14020 #include <algorithm> 14021 #include <sstream> 14022 14023 namespace Catch { 14024 14025 namespace { 14026 TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) { 14027 if( startsWith( tag, '.' ) || 14028 tag == "!hide" ) 14029 return TestCaseInfo::IsHidden; 14030 else if( tag == "!throws" ) 14031 return TestCaseInfo::Throws; 14032 else if( tag == "!shouldfail" ) 14033 return TestCaseInfo::ShouldFail; 14034 else if( tag == "!mayfail" ) 14035 return TestCaseInfo::MayFail; 14036 else if( tag == "!nonportable" ) 14037 return TestCaseInfo::NonPortable; 14038 else if( tag == "!benchmark" ) 14039 return static_cast<TestCaseInfo::SpecialProperties>( TestCaseInfo::Benchmark | TestCaseInfo::IsHidden ); 14040 else 14041 return TestCaseInfo::None; 14042 } 14043 bool isReservedTag( std::string const& tag ) { 14044 return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( static_cast<unsigned char>(tag[0]) ); 14045 } 14046 void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { 14047 CATCH_ENFORCE( !isReservedTag(tag), 14048 "Tag name: [" << tag << "] is not allowed.\n" 14049 << "Tag names starting with non alphanumeric characters are reserved\n" 14050 << _lineInfo ); 14051 } 14052 } 14053 14054 TestCase makeTestCase( ITestInvoker* _testCase, 14055 std::string const& _className, 14056 NameAndTags const& nameAndTags, 14057 SourceLineInfo const& _lineInfo ) 14058 { 14059 bool isHidden = false; 14060 14061 // Parse out tags 14062 std::vector<std::string> tags; 14063 std::string desc, tag; 14064 bool inTag = false; 14065 for (char c : nameAndTags.tags) { 14066 if( !inTag ) { 14067 if( c == '[' ) 14068 inTag = true; 14069 else 14070 desc += c; 14071 } 14072 else { 14073 if( c == ']' ) { 14074 TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag ); 14075 if( ( prop & TestCaseInfo::IsHidden ) != 0 ) 14076 isHidden = true; 14077 else if( prop == TestCaseInfo::None ) 14078 enforceNotReservedTag( tag, _lineInfo ); 14079 14080 // Merged hide tags like `[.approvals]` should be added as 14081 // `[.][approvals]`. The `[.]` is added at later point, so 14082 // we only strip the prefix 14083 if (startsWith(tag, '.') && tag.size() > 1) { 14084 tag.erase(0, 1); 14085 } 14086 tags.push_back( tag ); 14087 tag.clear(); 14088 inTag = false; 14089 } 14090 else 14091 tag += c; 14092 } 14093 } 14094 if( isHidden ) { 14095 // Add all "hidden" tags to make them behave identically 14096 tags.insert( tags.end(), { ".", "!hide" } ); 14097 } 14098 14099 TestCaseInfo info( static_cast<std::string>(nameAndTags.name), _className, desc, tags, _lineInfo ); 14100 return TestCase( _testCase, std::move(info) ); 14101 } 14102 14103 void setTags( TestCaseInfo& testCaseInfo, std::vector<std::string> tags ) { 14104 std::sort(begin(tags), end(tags)); 14105 tags.erase(std::unique(begin(tags), end(tags)), end(tags)); 14106 testCaseInfo.lcaseTags.clear(); 14107 14108 for( auto const& tag : tags ) { 14109 std::string lcaseTag = toLower( tag ); 14110 testCaseInfo.properties = static_cast<TestCaseInfo::SpecialProperties>( testCaseInfo.properties | parseSpecialTag( lcaseTag ) ); 14111 testCaseInfo.lcaseTags.push_back( lcaseTag ); 14112 } 14113 testCaseInfo.tags = std::move(tags); 14114 } 14115 14116 TestCaseInfo::TestCaseInfo( std::string const& _name, 14117 std::string const& _className, 14118 std::string const& _description, 14119 std::vector<std::string> const& _tags, 14120 SourceLineInfo const& _lineInfo ) 14121 : name( _name ), 14122 className( _className ), 14123 description( _description ), 14124 lineInfo( _lineInfo ), 14125 properties( None ) 14126 { 14127 setTags( *this, _tags ); 14128 } 14129 14130 bool TestCaseInfo::isHidden() const { 14131 return ( properties & IsHidden ) != 0; 14132 } 14133 bool TestCaseInfo::throws() const { 14134 return ( properties & Throws ) != 0; 14135 } 14136 bool TestCaseInfo::okToFail() const { 14137 return ( properties & (ShouldFail | MayFail ) ) != 0; 14138 } 14139 bool TestCaseInfo::expectedToFail() const { 14140 return ( properties & (ShouldFail ) ) != 0; 14141 } 14142 14143 std::string TestCaseInfo::tagsAsString() const { 14144 std::string ret; 14145 // '[' and ']' per tag 14146 std::size_t full_size = 2 * tags.size(); 14147 for (const auto& tag : tags) { 14148 full_size += tag.size(); 14149 } 14150 ret.reserve(full_size); 14151 for (const auto& tag : tags) { 14152 ret.push_back('['); 14153 ret.append(tag); 14154 ret.push_back(']'); 14155 } 14156 14157 return ret; 14158 } 14159 14160 TestCase::TestCase( ITestInvoker* testCase, TestCaseInfo&& info ) : TestCaseInfo( std::move(info) ), test( testCase ) {} 14161 14162 TestCase TestCase::withName( std::string const& _newName ) const { 14163 TestCase other( *this ); 14164 other.name = _newName; 14165 return other; 14166 } 14167 14168 void TestCase::invoke() const { 14169 test->invoke(); 14170 } 14171 14172 bool TestCase::operator == ( TestCase const& other ) const { 14173 return test.get() == other.test.get() && 14174 name == other.name && 14175 className == other.className; 14176 } 14177 14178 bool TestCase::operator < ( TestCase const& other ) const { 14179 return name < other.name; 14180 } 14181 14182 TestCaseInfo const& TestCase::getTestCaseInfo() const 14183 { 14184 return *this; 14185 } 14186 14187 } // end namespace Catch 14188 // end catch_test_case_info.cpp 14189 // start catch_test_case_registry_impl.cpp 14190 14191 #include <algorithm> 14192 #include <sstream> 14193 14194 namespace Catch { 14195 14196 namespace { 14197 struct TestHasher { 14198 using hash_t = uint64_t; 14199 14200 explicit TestHasher( hash_t hashSuffix ): 14201 m_hashSuffix{ hashSuffix } {} 14202 14203 uint32_t operator()( TestCase const& t ) const { 14204 // FNV-1a hash with multiplication fold. 14205 const hash_t prime = 1099511628211u; 14206 hash_t hash = 14695981039346656037u; 14207 for ( const char c : t.name ) { 14208 hash ^= c; 14209 hash *= prime; 14210 } 14211 hash ^= m_hashSuffix; 14212 hash *= prime; 14213 const uint32_t low{ static_cast<uint32_t>( hash ) }; 14214 const uint32_t high{ static_cast<uint32_t>( hash >> 32 ) }; 14215 return low * high; 14216 } 14217 14218 private: 14219 hash_t m_hashSuffix; 14220 }; 14221 } // end unnamed namespace 14222 14223 std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) { 14224 switch( config.runOrder() ) { 14225 case RunTests::InDeclarationOrder: 14226 // already in declaration order 14227 break; 14228 14229 case RunTests::InLexicographicalOrder: { 14230 std::vector<TestCase> sorted = unsortedTestCases; 14231 std::sort( sorted.begin(), sorted.end() ); 14232 return sorted; 14233 } 14234 14235 case RunTests::InRandomOrder: { 14236 seedRng( config ); 14237 TestHasher h{ config.rngSeed() }; 14238 14239 using hashedTest = std::pair<TestHasher::hash_t, TestCase const*>; 14240 std::vector<hashedTest> indexed_tests; 14241 indexed_tests.reserve( unsortedTestCases.size() ); 14242 14243 for (auto const& testCase : unsortedTestCases) { 14244 indexed_tests.emplace_back(h(testCase), &testCase); 14245 } 14246 14247 std::sort(indexed_tests.begin(), indexed_tests.end(), 14248 [](hashedTest const& lhs, hashedTest const& rhs) { 14249 if (lhs.first == rhs.first) { 14250 return lhs.second->name < rhs.second->name; 14251 } 14252 return lhs.first < rhs.first; 14253 }); 14254 14255 std::vector<TestCase> sorted; 14256 sorted.reserve( indexed_tests.size() ); 14257 14258 for (auto const& hashed : indexed_tests) { 14259 sorted.emplace_back(*hashed.second); 14260 } 14261 14262 return sorted; 14263 } 14264 } 14265 return unsortedTestCases; 14266 } 14267 14268 bool isThrowSafe( TestCase const& testCase, IConfig const& config ) { 14269 return !testCase.throws() || config.allowThrows(); 14270 } 14271 14272 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) { 14273 return testSpec.matches( testCase ) && isThrowSafe( testCase, config ); 14274 } 14275 14276 void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) { 14277 std::set<TestCase> seenFunctions; 14278 for( auto const& function : functions ) { 14279 auto prev = seenFunctions.insert( function ); 14280 CATCH_ENFORCE( prev.second, 14281 "error: TEST_CASE( \"" << function.name << "\" ) already defined.\n" 14282 << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n" 14283 << "\tRedefined at " << function.getTestCaseInfo().lineInfo ); 14284 } 14285 } 14286 14287 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) { 14288 std::vector<TestCase> filtered; 14289 filtered.reserve( testCases.size() ); 14290 for (auto const& testCase : testCases) { 14291 if ((!testSpec.hasFilters() && !testCase.isHidden()) || 14292 (testSpec.hasFilters() && matchTest(testCase, testSpec, config))) { 14293 filtered.push_back(testCase); 14294 } 14295 } 14296 return filtered; 14297 } 14298 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) { 14299 return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config ); 14300 } 14301 14302 void TestRegistry::registerTest( TestCase const& testCase ) { 14303 std::string name = testCase.getTestCaseInfo().name; 14304 if( name.empty() ) { 14305 ReusableStringStream rss; 14306 rss << "Anonymous test case " << ++m_unnamedCount; 14307 return registerTest( testCase.withName( rss.str() ) ); 14308 } 14309 m_functions.push_back( testCase ); 14310 } 14311 14312 std::vector<TestCase> const& TestRegistry::getAllTests() const { 14313 return m_functions; 14314 } 14315 std::vector<TestCase> const& TestRegistry::getAllTestsSorted( IConfig const& config ) const { 14316 if( m_sortedFunctions.empty() ) 14317 enforceNoDuplicateTestCases( m_functions ); 14318 14319 if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) { 14320 m_sortedFunctions = sortTests( config, m_functions ); 14321 m_currentSortOrder = config.runOrder(); 14322 } 14323 return m_sortedFunctions; 14324 } 14325 14326 /////////////////////////////////////////////////////////////////////////// 14327 TestInvokerAsFunction::TestInvokerAsFunction( void(*testAsFunction)() ) noexcept : m_testAsFunction( testAsFunction ) {} 14328 14329 void TestInvokerAsFunction::invoke() const { 14330 m_testAsFunction(); 14331 } 14332 14333 std::string extractClassName( StringRef const& classOrQualifiedMethodName ) { 14334 std::string className(classOrQualifiedMethodName); 14335 if( startsWith( className, '&' ) ) 14336 { 14337 std::size_t lastColons = className.rfind( "::" ); 14338 std::size_t penultimateColons = className.rfind( "::", lastColons-1 ); 14339 if( penultimateColons == std::string::npos ) 14340 penultimateColons = 1; 14341 className = className.substr( penultimateColons, lastColons-penultimateColons ); 14342 } 14343 return className; 14344 } 14345 14346 } // end namespace Catch 14347 // end catch_test_case_registry_impl.cpp 14348 // start catch_test_case_tracker.cpp 14349 14350 #include <algorithm> 14351 #include <cassert> 14352 #include <stdexcept> 14353 #include <memory> 14354 #include <sstream> 14355 14356 #if defined(__clang__) 14357 # pragma clang diagnostic push 14358 # pragma clang diagnostic ignored "-Wexit-time-destructors" 14359 #endif 14360 14361 namespace Catch { 14362 namespace TestCaseTracking { 14363 14364 NameAndLocation::NameAndLocation( std::string const& _name, SourceLineInfo const& _location ) 14365 : name( _name ), 14366 location( _location ) 14367 {} 14368 14369 ITracker::~ITracker() = default; 14370 14371 ITracker& TrackerContext::startRun() { 14372 m_rootTracker = std::make_shared<SectionTracker>( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, nullptr ); 14373 m_currentTracker = nullptr; 14374 m_runState = Executing; 14375 return *m_rootTracker; 14376 } 14377 14378 void TrackerContext::endRun() { 14379 m_rootTracker.reset(); 14380 m_currentTracker = nullptr; 14381 m_runState = NotStarted; 14382 } 14383 14384 void TrackerContext::startCycle() { 14385 m_currentTracker = m_rootTracker.get(); 14386 m_runState = Executing; 14387 } 14388 void TrackerContext::completeCycle() { 14389 m_runState = CompletedCycle; 14390 } 14391 14392 bool TrackerContext::completedCycle() const { 14393 return m_runState == CompletedCycle; 14394 } 14395 ITracker& TrackerContext::currentTracker() { 14396 return *m_currentTracker; 14397 } 14398 void TrackerContext::setCurrentTracker( ITracker* tracker ) { 14399 m_currentTracker = tracker; 14400 } 14401 14402 TrackerBase::TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ): 14403 ITracker(nameAndLocation), 14404 m_ctx( ctx ), 14405 m_parent( parent ) 14406 {} 14407 14408 bool TrackerBase::isComplete() const { 14409 return m_runState == CompletedSuccessfully || m_runState == Failed; 14410 } 14411 bool TrackerBase::isSuccessfullyCompleted() const { 14412 return m_runState == CompletedSuccessfully; 14413 } 14414 bool TrackerBase::isOpen() const { 14415 return m_runState != NotStarted && !isComplete(); 14416 } 14417 bool TrackerBase::hasChildren() const { 14418 return !m_children.empty(); 14419 } 14420 14421 void TrackerBase::addChild( ITrackerPtr const& child ) { 14422 m_children.push_back( child ); 14423 } 14424 14425 ITrackerPtr TrackerBase::findChild( NameAndLocation const& nameAndLocation ) { 14426 auto it = std::find_if( m_children.begin(), m_children.end(), 14427 [&nameAndLocation]( ITrackerPtr const& tracker ){ 14428 return 14429 tracker->nameAndLocation().location == nameAndLocation.location && 14430 tracker->nameAndLocation().name == nameAndLocation.name; 14431 } ); 14432 return( it != m_children.end() ) 14433 ? *it 14434 : nullptr; 14435 } 14436 ITracker& TrackerBase::parent() { 14437 assert( m_parent ); // Should always be non-null except for root 14438 return *m_parent; 14439 } 14440 14441 void TrackerBase::openChild() { 14442 if( m_runState != ExecutingChildren ) { 14443 m_runState = ExecutingChildren; 14444 if( m_parent ) 14445 m_parent->openChild(); 14446 } 14447 } 14448 14449 bool TrackerBase::isSectionTracker() const { return false; } 14450 bool TrackerBase::isGeneratorTracker() const { return false; } 14451 14452 void TrackerBase::open() { 14453 m_runState = Executing; 14454 moveToThis(); 14455 if( m_parent ) 14456 m_parent->openChild(); 14457 } 14458 14459 void TrackerBase::close() { 14460 14461 // Close any still open children (e.g. generators) 14462 while( &m_ctx.currentTracker() != this ) 14463 m_ctx.currentTracker().close(); 14464 14465 switch( m_runState ) { 14466 case NeedsAnotherRun: 14467 break; 14468 14469 case Executing: 14470 m_runState = CompletedSuccessfully; 14471 break; 14472 case ExecutingChildren: 14473 if( std::all_of(m_children.begin(), m_children.end(), [](ITrackerPtr const& t){ return t->isComplete(); }) ) 14474 m_runState = CompletedSuccessfully; 14475 break; 14476 14477 case NotStarted: 14478 case CompletedSuccessfully: 14479 case Failed: 14480 CATCH_INTERNAL_ERROR( "Illogical state: " << m_runState ); 14481 14482 default: 14483 CATCH_INTERNAL_ERROR( "Unknown state: " << m_runState ); 14484 } 14485 moveToParent(); 14486 m_ctx.completeCycle(); 14487 } 14488 void TrackerBase::fail() { 14489 m_runState = Failed; 14490 if( m_parent ) 14491 m_parent->markAsNeedingAnotherRun(); 14492 moveToParent(); 14493 m_ctx.completeCycle(); 14494 } 14495 void TrackerBase::markAsNeedingAnotherRun() { 14496 m_runState = NeedsAnotherRun; 14497 } 14498 14499 void TrackerBase::moveToParent() { 14500 assert( m_parent ); 14501 m_ctx.setCurrentTracker( m_parent ); 14502 } 14503 void TrackerBase::moveToThis() { 14504 m_ctx.setCurrentTracker( this ); 14505 } 14506 14507 SectionTracker::SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) 14508 : TrackerBase( nameAndLocation, ctx, parent ), 14509 m_trimmed_name(trim(nameAndLocation.name)) 14510 { 14511 if( parent ) { 14512 while( !parent->isSectionTracker() ) 14513 parent = &parent->parent(); 14514 14515 SectionTracker& parentSection = static_cast<SectionTracker&>( *parent ); 14516 addNextFilters( parentSection.m_filters ); 14517 } 14518 } 14519 14520 bool SectionTracker::isComplete() const { 14521 bool complete = true; 14522 14523 if (m_filters.empty() 14524 || m_filters[0] == "" 14525 || std::find(m_filters.begin(), m_filters.end(), m_trimmed_name) != m_filters.end()) { 14526 complete = TrackerBase::isComplete(); 14527 } 14528 return complete; 14529 } 14530 14531 bool SectionTracker::isSectionTracker() const { return true; } 14532 14533 SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) { 14534 std::shared_ptr<SectionTracker> section; 14535 14536 ITracker& currentTracker = ctx.currentTracker(); 14537 if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) { 14538 assert( childTracker ); 14539 assert( childTracker->isSectionTracker() ); 14540 section = std::static_pointer_cast<SectionTracker>( childTracker ); 14541 } 14542 else { 14543 section = std::make_shared<SectionTracker>( nameAndLocation, ctx, ¤tTracker ); 14544 currentTracker.addChild( section ); 14545 } 14546 if( !ctx.completedCycle() ) 14547 section->tryOpen(); 14548 return *section; 14549 } 14550 14551 void SectionTracker::tryOpen() { 14552 if( !isComplete() ) 14553 open(); 14554 } 14555 14556 void SectionTracker::addInitialFilters( std::vector<std::string> const& filters ) { 14557 if( !filters.empty() ) { 14558 m_filters.reserve( m_filters.size() + filters.size() + 2 ); 14559 m_filters.emplace_back(""); // Root - should never be consulted 14560 m_filters.emplace_back(""); // Test Case - not a section filter 14561 m_filters.insert( m_filters.end(), filters.begin(), filters.end() ); 14562 } 14563 } 14564 void SectionTracker::addNextFilters( std::vector<std::string> const& filters ) { 14565 if( filters.size() > 1 ) 14566 m_filters.insert( m_filters.end(), filters.begin()+1, filters.end() ); 14567 } 14568 14569 std::vector<std::string> const& SectionTracker::getFilters() const { 14570 return m_filters; 14571 } 14572 14573 std::string const& SectionTracker::trimmedName() const { 14574 return m_trimmed_name; 14575 } 14576 14577 } // namespace TestCaseTracking 14578 14579 using TestCaseTracking::ITracker; 14580 using TestCaseTracking::TrackerContext; 14581 using TestCaseTracking::SectionTracker; 14582 14583 } // namespace Catch 14584 14585 #if defined(__clang__) 14586 # pragma clang diagnostic pop 14587 #endif 14588 // end catch_test_case_tracker.cpp 14589 // start catch_test_registry.cpp 14590 14591 namespace Catch { 14592 14593 auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker* { 14594 return new(std::nothrow) TestInvokerAsFunction( testAsFunction ); 14595 } 14596 14597 NameAndTags::NameAndTags( StringRef const& name_ , StringRef const& tags_ ) noexcept : name( name_ ), tags( tags_ ) {} 14598 14599 AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept { 14600 CATCH_TRY { 14601 getMutableRegistryHub() 14602 .registerTest( 14603 makeTestCase( 14604 invoker, 14605 extractClassName( classOrMethod ), 14606 nameAndTags, 14607 lineInfo)); 14608 } CATCH_CATCH_ALL { 14609 // Do not throw when constructing global objects, instead register the exception to be processed later 14610 getMutableRegistryHub().registerStartupException(); 14611 } 14612 } 14613 14614 AutoReg::~AutoReg() = default; 14615 } 14616 // end catch_test_registry.cpp 14617 // start catch_test_spec.cpp 14618 14619 #include <algorithm> 14620 #include <string> 14621 #include <vector> 14622 #include <memory> 14623 14624 namespace Catch { 14625 14626 TestSpec::Pattern::Pattern( std::string const& name ) 14627 : m_name( name ) 14628 {} 14629 14630 TestSpec::Pattern::~Pattern() = default; 14631 14632 std::string const& TestSpec::Pattern::name() const { 14633 return m_name; 14634 } 14635 14636 TestSpec::NamePattern::NamePattern( std::string const& name, std::string const& filterString ) 14637 : Pattern( filterString ) 14638 , m_wildcardPattern( toLower( name ), CaseSensitive::No ) 14639 {} 14640 14641 bool TestSpec::NamePattern::matches( TestCaseInfo const& testCase ) const { 14642 return m_wildcardPattern.matches( testCase.name ); 14643 } 14644 14645 TestSpec::TagPattern::TagPattern( std::string const& tag, std::string const& filterString ) 14646 : Pattern( filterString ) 14647 , m_tag( toLower( tag ) ) 14648 {} 14649 14650 bool TestSpec::TagPattern::matches( TestCaseInfo const& testCase ) const { 14651 return std::find(begin(testCase.lcaseTags), 14652 end(testCase.lcaseTags), 14653 m_tag) != end(testCase.lcaseTags); 14654 } 14655 14656 TestSpec::ExcludedPattern::ExcludedPattern( PatternPtr const& underlyingPattern ) 14657 : Pattern( underlyingPattern->name() ) 14658 , m_underlyingPattern( underlyingPattern ) 14659 {} 14660 14661 bool TestSpec::ExcludedPattern::matches( TestCaseInfo const& testCase ) const { 14662 return !m_underlyingPattern->matches( testCase ); 14663 } 14664 14665 bool TestSpec::Filter::matches( TestCaseInfo const& testCase ) const { 14666 return std::all_of( m_patterns.begin(), m_patterns.end(), [&]( PatternPtr const& p ){ return p->matches( testCase ); } ); 14667 } 14668 14669 std::string TestSpec::Filter::name() const { 14670 std::string name; 14671 for( auto const& p : m_patterns ) 14672 name += p->name(); 14673 return name; 14674 } 14675 14676 bool TestSpec::hasFilters() const { 14677 return !m_filters.empty(); 14678 } 14679 14680 bool TestSpec::matches( TestCaseInfo const& testCase ) const { 14681 return std::any_of( m_filters.begin(), m_filters.end(), [&]( Filter const& f ){ return f.matches( testCase ); } ); 14682 } 14683 14684 TestSpec::Matches TestSpec::matchesByFilter( std::vector<TestCase> const& testCases, IConfig const& config ) const 14685 { 14686 Matches matches( m_filters.size() ); 14687 std::transform( m_filters.begin(), m_filters.end(), matches.begin(), [&]( Filter const& filter ){ 14688 std::vector<TestCase const*> currentMatches; 14689 for( auto const& test : testCases ) 14690 if( isThrowSafe( test, config ) && filter.matches( test ) ) 14691 currentMatches.emplace_back( &test ); 14692 return FilterMatch{ filter.name(), currentMatches }; 14693 } ); 14694 return matches; 14695 } 14696 14697 const TestSpec::vectorStrings& TestSpec::getInvalidArgs() const{ 14698 return (m_invalidArgs); 14699 } 14700 14701 } 14702 // end catch_test_spec.cpp 14703 // start catch_test_spec_parser.cpp 14704 14705 namespace Catch { 14706 14707 TestSpecParser::TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {} 14708 14709 TestSpecParser& TestSpecParser::parse( std::string const& arg ) { 14710 m_mode = None; 14711 m_exclusion = false; 14712 m_arg = m_tagAliases->expandAliases( arg ); 14713 m_escapeChars.clear(); 14714 m_substring.reserve(m_arg.size()); 14715 m_patternName.reserve(m_arg.size()); 14716 m_realPatternPos = 0; 14717 14718 for( m_pos = 0; m_pos < m_arg.size(); ++m_pos ) 14719 //if visitChar fails 14720 if( !visitChar( m_arg[m_pos] ) ){ 14721 m_testSpec.m_invalidArgs.push_back(arg); 14722 break; 14723 } 14724 endMode(); 14725 return *this; 14726 } 14727 TestSpec TestSpecParser::testSpec() { 14728 addFilter(); 14729 return m_testSpec; 14730 } 14731 bool TestSpecParser::visitChar( char c ) { 14732 if( (m_mode != EscapedName) && (c == '\\') ) { 14733 escape(); 14734 addCharToPattern(c); 14735 return true; 14736 }else if((m_mode != EscapedName) && (c == ',') ) { 14737 return separate(); 14738 } 14739 14740 switch( m_mode ) { 14741 case None: 14742 if( processNoneChar( c ) ) 14743 return true; 14744 break; 14745 case Name: 14746 processNameChar( c ); 14747 break; 14748 case EscapedName: 14749 endMode(); 14750 addCharToPattern(c); 14751 return true; 14752 default: 14753 case Tag: 14754 case QuotedName: 14755 if( processOtherChar( c ) ) 14756 return true; 14757 break; 14758 } 14759 14760 m_substring += c; 14761 if( !isControlChar( c ) ) { 14762 m_patternName += c; 14763 m_realPatternPos++; 14764 } 14765 return true; 14766 } 14767 // Two of the processing methods return true to signal the caller to return 14768 // without adding the given character to the current pattern strings 14769 bool TestSpecParser::processNoneChar( char c ) { 14770 switch( c ) { 14771 case ' ': 14772 return true; 14773 case '~': 14774 m_exclusion = true; 14775 return false; 14776 case '[': 14777 startNewMode( Tag ); 14778 return false; 14779 case '"': 14780 startNewMode( QuotedName ); 14781 return false; 14782 default: 14783 startNewMode( Name ); 14784 return false; 14785 } 14786 } 14787 void TestSpecParser::processNameChar( char c ) { 14788 if( c == '[' ) { 14789 if( m_substring == "exclude:" ) 14790 m_exclusion = true; 14791 else 14792 endMode(); 14793 startNewMode( Tag ); 14794 } 14795 } 14796 bool TestSpecParser::processOtherChar( char c ) { 14797 if( !isControlChar( c ) ) 14798 return false; 14799 m_substring += c; 14800 endMode(); 14801 return true; 14802 } 14803 void TestSpecParser::startNewMode( Mode mode ) { 14804 m_mode = mode; 14805 } 14806 void TestSpecParser::endMode() { 14807 switch( m_mode ) { 14808 case Name: 14809 case QuotedName: 14810 return addNamePattern(); 14811 case Tag: 14812 return addTagPattern(); 14813 case EscapedName: 14814 revertBackToLastMode(); 14815 return; 14816 case None: 14817 default: 14818 return startNewMode( None ); 14819 } 14820 } 14821 void TestSpecParser::escape() { 14822 saveLastMode(); 14823 m_mode = EscapedName; 14824 m_escapeChars.push_back(m_realPatternPos); 14825 } 14826 bool TestSpecParser::isControlChar( char c ) const { 14827 switch( m_mode ) { 14828 default: 14829 return false; 14830 case None: 14831 return c == '~'; 14832 case Name: 14833 return c == '['; 14834 case EscapedName: 14835 return true; 14836 case QuotedName: 14837 return c == '"'; 14838 case Tag: 14839 return c == '[' || c == ']'; 14840 } 14841 } 14842 14843 void TestSpecParser::addFilter() { 14844 if( !m_currentFilter.m_patterns.empty() ) { 14845 m_testSpec.m_filters.push_back( m_currentFilter ); 14846 m_currentFilter = TestSpec::Filter(); 14847 } 14848 } 14849 14850 void TestSpecParser::saveLastMode() { 14851 lastMode = m_mode; 14852 } 14853 14854 void TestSpecParser::revertBackToLastMode() { 14855 m_mode = lastMode; 14856 } 14857 14858 bool TestSpecParser::separate() { 14859 if( (m_mode==QuotedName) || (m_mode==Tag) ){ 14860 //invalid argument, signal failure to previous scope. 14861 m_mode = None; 14862 m_pos = m_arg.size(); 14863 m_substring.clear(); 14864 m_patternName.clear(); 14865 m_realPatternPos = 0; 14866 return false; 14867 } 14868 endMode(); 14869 addFilter(); 14870 return true; //success 14871 } 14872 14873 std::string TestSpecParser::preprocessPattern() { 14874 std::string token = m_patternName; 14875 for (std::size_t i = 0; i < m_escapeChars.size(); ++i) 14876 token = token.substr(0, m_escapeChars[i] - i) + token.substr(m_escapeChars[i] - i + 1); 14877 m_escapeChars.clear(); 14878 if (startsWith(token, "exclude:")) { 14879 m_exclusion = true; 14880 token = token.substr(8); 14881 } 14882 14883 m_patternName.clear(); 14884 m_realPatternPos = 0; 14885 14886 return token; 14887 } 14888 14889 void TestSpecParser::addNamePattern() { 14890 auto token = preprocessPattern(); 14891 14892 if (!token.empty()) { 14893 TestSpec::PatternPtr pattern = std::make_shared<TestSpec::NamePattern>(token, m_substring); 14894 if (m_exclusion) 14895 pattern = std::make_shared<TestSpec::ExcludedPattern>(pattern); 14896 m_currentFilter.m_patterns.push_back(pattern); 14897 } 14898 m_substring.clear(); 14899 m_exclusion = false; 14900 m_mode = None; 14901 } 14902 14903 void TestSpecParser::addTagPattern() { 14904 auto token = preprocessPattern(); 14905 14906 if (!token.empty()) { 14907 // If the tag pattern is the "hide and tag" shorthand (e.g. [.foo]) 14908 // we have to create a separate hide tag and shorten the real one 14909 if (token.size() > 1 && token[0] == '.') { 14910 token.erase(token.begin()); 14911 TestSpec::PatternPtr pattern = std::make_shared<TestSpec::TagPattern>(".", m_substring); 14912 if (m_exclusion) { 14913 pattern = std::make_shared<TestSpec::ExcludedPattern>(pattern); 14914 } 14915 m_currentFilter.m_patterns.push_back(pattern); 14916 } 14917 14918 TestSpec::PatternPtr pattern = std::make_shared<TestSpec::TagPattern>(token, m_substring); 14919 14920 if (m_exclusion) { 14921 pattern = std::make_shared<TestSpec::ExcludedPattern>(pattern); 14922 } 14923 m_currentFilter.m_patterns.push_back(pattern); 14924 } 14925 m_substring.clear(); 14926 m_exclusion = false; 14927 m_mode = None; 14928 } 14929 14930 TestSpec parseTestSpec( std::string const& arg ) { 14931 return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec(); 14932 } 14933 14934 } // namespace Catch 14935 // end catch_test_spec_parser.cpp 14936 // start catch_timer.cpp 14937 14938 #include <chrono> 14939 14940 static const uint64_t nanosecondsInSecond = 1000000000; 14941 14942 namespace Catch { 14943 14944 auto getCurrentNanosecondsSinceEpoch() -> uint64_t { 14945 return std::chrono::duration_cast<std::chrono::nanoseconds>( std::chrono::high_resolution_clock::now().time_since_epoch() ).count(); 14946 } 14947 14948 namespace { 14949 auto estimateClockResolution() -> uint64_t { 14950 uint64_t sum = 0; 14951 static const uint64_t iterations = 1000000; 14952 14953 auto startTime = getCurrentNanosecondsSinceEpoch(); 14954 14955 for( std::size_t i = 0; i < iterations; ++i ) { 14956 14957 uint64_t ticks; 14958 uint64_t baseTicks = getCurrentNanosecondsSinceEpoch(); 14959 do { 14960 ticks = getCurrentNanosecondsSinceEpoch(); 14961 } while( ticks == baseTicks ); 14962 14963 auto delta = ticks - baseTicks; 14964 sum += delta; 14965 14966 // If we have been calibrating for over 3 seconds -- the clock 14967 // is terrible and we should move on. 14968 // TBD: How to signal that the measured resolution is probably wrong? 14969 if (ticks > startTime + 3 * nanosecondsInSecond) { 14970 return sum / ( i + 1u ); 14971 } 14972 } 14973 14974 // We're just taking the mean, here. To do better we could take the std. dev and exclude outliers 14975 // - and potentially do more iterations if there's a high variance. 14976 return sum/iterations; 14977 } 14978 } 14979 auto getEstimatedClockResolution() -> uint64_t { 14980 static auto s_resolution = estimateClockResolution(); 14981 return s_resolution; 14982 } 14983 14984 void Timer::start() { 14985 m_nanoseconds = getCurrentNanosecondsSinceEpoch(); 14986 } 14987 auto Timer::getElapsedNanoseconds() const -> uint64_t { 14988 return getCurrentNanosecondsSinceEpoch() - m_nanoseconds; 14989 } 14990 auto Timer::getElapsedMicroseconds() const -> uint64_t { 14991 return getElapsedNanoseconds()/1000; 14992 } 14993 auto Timer::getElapsedMilliseconds() const -> unsigned int { 14994 return static_cast<unsigned int>(getElapsedMicroseconds()/1000); 14995 } 14996 auto Timer::getElapsedSeconds() const -> double { 14997 return getElapsedMicroseconds()/1000000.0; 14998 } 14999 15000 } // namespace Catch 15001 // end catch_timer.cpp 15002 // start catch_tostring.cpp 15003 15004 #if defined(__clang__) 15005 # pragma clang diagnostic push 15006 # pragma clang diagnostic ignored "-Wexit-time-destructors" 15007 # pragma clang diagnostic ignored "-Wglobal-constructors" 15008 #endif 15009 15010 // Enable specific decls locally 15011 #if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) 15012 #define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER 15013 #endif 15014 15015 #include <cmath> 15016 #include <iomanip> 15017 15018 namespace Catch { 15019 15020 namespace Detail { 15021 15022 const std::string unprintableString = "{?}"; 15023 15024 namespace { 15025 const int hexThreshold = 255; 15026 15027 struct Endianness { 15028 enum Arch { Big, Little }; 15029 15030 static Arch which() { 15031 int one = 1; 15032 // If the lowest byte we read is non-zero, we can assume 15033 // that little endian format is used. 15034 auto value = *reinterpret_cast<char*>(&one); 15035 return value ? Little : Big; 15036 } 15037 }; 15038 } 15039 15040 std::string rawMemoryToString( const void *object, std::size_t size ) { 15041 // Reverse order for little endian architectures 15042 int i = 0, end = static_cast<int>( size ), inc = 1; 15043 if( Endianness::which() == Endianness::Little ) { 15044 i = end-1; 15045 end = inc = -1; 15046 } 15047 15048 unsigned char const *bytes = static_cast<unsigned char const *>(object); 15049 ReusableStringStream rss; 15050 rss << "0x" << std::setfill('0') << std::hex; 15051 for( ; i != end; i += inc ) 15052 rss << std::setw(2) << static_cast<unsigned>(bytes[i]); 15053 return rss.str(); 15054 } 15055 } 15056 15057 template<typename T> 15058 std::string fpToString( T value, int precision ) { 15059 if (Catch::isnan(value)) { 15060 return "nan"; 15061 } 15062 15063 ReusableStringStream rss; 15064 rss << std::setprecision( precision ) 15065 << std::fixed 15066 << value; 15067 std::string d = rss.str(); 15068 std::size_t i = d.find_last_not_of( '0' ); 15069 if( i != std::string::npos && i != d.size()-1 ) { 15070 if( d[i] == '.' ) 15071 i++; 15072 d = d.substr( 0, i+1 ); 15073 } 15074 return d; 15075 } 15076 15077 //// ======================================================= //// 15078 // 15079 // Out-of-line defs for full specialization of StringMaker 15080 // 15081 //// ======================================================= //// 15082 15083 std::string StringMaker<std::string>::convert(const std::string& str) { 15084 if (!getCurrentContext().getConfig()->showInvisibles()) { 15085 return '"' + str + '"'; 15086 } 15087 15088 std::string s("\""); 15089 for (char c : str) { 15090 switch (c) { 15091 case '\n': 15092 s.append("\\n"); 15093 break; 15094 case '\t': 15095 s.append("\\t"); 15096 break; 15097 default: 15098 s.push_back(c); 15099 break; 15100 } 15101 } 15102 s.append("\""); 15103 return s; 15104 } 15105 15106 #ifdef CATCH_CONFIG_CPP17_STRING_VIEW 15107 std::string StringMaker<std::string_view>::convert(std::string_view str) { 15108 return ::Catch::Detail::stringify(std::string{ str }); 15109 } 15110 #endif 15111 15112 std::string StringMaker<char const*>::convert(char const* str) { 15113 if (str) { 15114 return ::Catch::Detail::stringify(std::string{ str }); 15115 } else { 15116 return{ "{null string}" }; 15117 } 15118 } 15119 std::string StringMaker<char*>::convert(char* str) { 15120 if (str) { 15121 return ::Catch::Detail::stringify(std::string{ str }); 15122 } else { 15123 return{ "{null string}" }; 15124 } 15125 } 15126 15127 #ifdef CATCH_CONFIG_WCHAR 15128 std::string StringMaker<std::wstring>::convert(const std::wstring& wstr) { 15129 std::string s; 15130 s.reserve(wstr.size()); 15131 for (auto c : wstr) { 15132 s += (c <= 0xff) ? static_cast<char>(c) : '?'; 15133 } 15134 return ::Catch::Detail::stringify(s); 15135 } 15136 15137 # ifdef CATCH_CONFIG_CPP17_STRING_VIEW 15138 std::string StringMaker<std::wstring_view>::convert(std::wstring_view str) { 15139 return StringMaker<std::wstring>::convert(std::wstring(str)); 15140 } 15141 # endif 15142 15143 std::string StringMaker<wchar_t const*>::convert(wchar_t const * str) { 15144 if (str) { 15145 return ::Catch::Detail::stringify(std::wstring{ str }); 15146 } else { 15147 return{ "{null string}" }; 15148 } 15149 } 15150 std::string StringMaker<wchar_t *>::convert(wchar_t * str) { 15151 if (str) { 15152 return ::Catch::Detail::stringify(std::wstring{ str }); 15153 } else { 15154 return{ "{null string}" }; 15155 } 15156 } 15157 #endif 15158 15159 #if defined(CATCH_CONFIG_CPP17_BYTE) 15160 #include <cstddef> 15161 std::string StringMaker<std::byte>::convert(std::byte value) { 15162 return ::Catch::Detail::stringify(std::to_integer<unsigned long long>(value)); 15163 } 15164 #endif // defined(CATCH_CONFIG_CPP17_BYTE) 15165 15166 std::string StringMaker<int>::convert(int value) { 15167 return ::Catch::Detail::stringify(static_cast<long long>(value)); 15168 } 15169 std::string StringMaker<long>::convert(long value) { 15170 return ::Catch::Detail::stringify(static_cast<long long>(value)); 15171 } 15172 std::string StringMaker<long long>::convert(long long value) { 15173 ReusableStringStream rss; 15174 rss << value; 15175 if (value > Detail::hexThreshold) { 15176 rss << " (0x" << std::hex << value << ')'; 15177 } 15178 return rss.str(); 15179 } 15180 15181 std::string StringMaker<unsigned int>::convert(unsigned int value) { 15182 return ::Catch::Detail::stringify(static_cast<unsigned long long>(value)); 15183 } 15184 std::string StringMaker<unsigned long>::convert(unsigned long value) { 15185 return ::Catch::Detail::stringify(static_cast<unsigned long long>(value)); 15186 } 15187 std::string StringMaker<unsigned long long>::convert(unsigned long long value) { 15188 ReusableStringStream rss; 15189 rss << value; 15190 if (value > Detail::hexThreshold) { 15191 rss << " (0x" << std::hex << value << ')'; 15192 } 15193 return rss.str(); 15194 } 15195 15196 std::string StringMaker<bool>::convert(bool b) { 15197 return b ? "true" : "false"; 15198 } 15199 15200 std::string StringMaker<signed char>::convert(signed char value) { 15201 if (value == '\r') { 15202 return "'\\r'"; 15203 } else if (value == '\f') { 15204 return "'\\f'"; 15205 } else if (value == '\n') { 15206 return "'\\n'"; 15207 } else if (value == '\t') { 15208 return "'\\t'"; 15209 } else if ('\0' <= value && value < ' ') { 15210 return ::Catch::Detail::stringify(static_cast<unsigned int>(value)); 15211 } else { 15212 char chstr[] = "' '"; 15213 chstr[1] = value; 15214 return chstr; 15215 } 15216 } 15217 std::string StringMaker<char>::convert(char c) { 15218 return ::Catch::Detail::stringify(static_cast<signed char>(c)); 15219 } 15220 std::string StringMaker<unsigned char>::convert(unsigned char c) { 15221 return ::Catch::Detail::stringify(static_cast<char>(c)); 15222 } 15223 15224 std::string StringMaker<std::nullptr_t>::convert(std::nullptr_t) { 15225 return "nullptr"; 15226 } 15227 15228 int StringMaker<float>::precision = 5; 15229 15230 std::string StringMaker<float>::convert(float value) { 15231 return fpToString(value, precision) + 'f'; 15232 } 15233 15234 int StringMaker<double>::precision = 10; 15235 15236 std::string StringMaker<double>::convert(double value) { 15237 return fpToString(value, precision); 15238 } 15239 15240 std::string ratio_string<std::atto>::symbol() { return "a"; } 15241 std::string ratio_string<std::femto>::symbol() { return "f"; } 15242 std::string ratio_string<std::pico>::symbol() { return "p"; } 15243 std::string ratio_string<std::nano>::symbol() { return "n"; } 15244 std::string ratio_string<std::micro>::symbol() { return "u"; } 15245 std::string ratio_string<std::milli>::symbol() { return "m"; } 15246 15247 } // end namespace Catch 15248 15249 #if defined(__clang__) 15250 # pragma clang diagnostic pop 15251 #endif 15252 15253 // end catch_tostring.cpp 15254 // start catch_totals.cpp 15255 15256 namespace Catch { 15257 15258 Counts Counts::operator - ( Counts const& other ) const { 15259 Counts diff; 15260 diff.passed = passed - other.passed; 15261 diff.failed = failed - other.failed; 15262 diff.failedButOk = failedButOk - other.failedButOk; 15263 return diff; 15264 } 15265 15266 Counts& Counts::operator += ( Counts const& other ) { 15267 passed += other.passed; 15268 failed += other.failed; 15269 failedButOk += other.failedButOk; 15270 return *this; 15271 } 15272 15273 std::size_t Counts::total() const { 15274 return passed + failed + failedButOk; 15275 } 15276 bool Counts::allPassed() const { 15277 return failed == 0 && failedButOk == 0; 15278 } 15279 bool Counts::allOk() const { 15280 return failed == 0; 15281 } 15282 15283 Totals Totals::operator - ( Totals const& other ) const { 15284 Totals diff; 15285 diff.assertions = assertions - other.assertions; 15286 diff.testCases = testCases - other.testCases; 15287 return diff; 15288 } 15289 15290 Totals& Totals::operator += ( Totals const& other ) { 15291 assertions += other.assertions; 15292 testCases += other.testCases; 15293 return *this; 15294 } 15295 15296 Totals Totals::delta( Totals const& prevTotals ) const { 15297 Totals diff = *this - prevTotals; 15298 if( diff.assertions.failed > 0 ) 15299 ++diff.testCases.failed; 15300 else if( diff.assertions.failedButOk > 0 ) 15301 ++diff.testCases.failedButOk; 15302 else 15303 ++diff.testCases.passed; 15304 return diff; 15305 } 15306 15307 } 15308 // end catch_totals.cpp 15309 // start catch_uncaught_exceptions.cpp 15310 15311 // start catch_config_uncaught_exceptions.hpp 15312 15313 // Copyright Catch2 Authors 15314 // Distributed under the Boost Software License, Version 1.0. 15315 // (See accompanying file LICENSE_1_0.txt or copy at 15316 // https://www.boost.org/LICENSE_1_0.txt) 15317 15318 // SPDX-License-Identifier: BSL-1.0 15319 15320 #ifndef CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP 15321 #define CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP 15322 15323 #if defined(_MSC_VER) 15324 # if _MSC_VER >= 1900 // Visual Studio 2015 or newer 15325 # define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS 15326 # endif 15327 #endif 15328 15329 #include <exception> 15330 15331 #if defined(__cpp_lib_uncaught_exceptions) \ 15332 && !defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) 15333 15334 # define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS 15335 #endif // __cpp_lib_uncaught_exceptions 15336 15337 #if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) \ 15338 && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) \ 15339 && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) 15340 15341 # define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS 15342 #endif 15343 15344 #endif // CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP 15345 // end catch_config_uncaught_exceptions.hpp 15346 #include <exception> 15347 15348 namespace Catch { 15349 bool uncaught_exceptions() { 15350 #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 15351 return false; 15352 #elif defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) 15353 return std::uncaught_exceptions() > 0; 15354 #else 15355 return std::uncaught_exception(); 15356 #endif 15357 } 15358 } // end namespace Catch 15359 // end catch_uncaught_exceptions.cpp 15360 // start catch_version.cpp 15361 15362 #include <ostream> 15363 15364 namespace Catch { 15365 15366 Version::Version 15367 ( unsigned int _majorVersion, 15368 unsigned int _minorVersion, 15369 unsigned int _patchNumber, 15370 char const * const _branchName, 15371 unsigned int _buildNumber ) 15372 : majorVersion( _majorVersion ), 15373 minorVersion( _minorVersion ), 15374 patchNumber( _patchNumber ), 15375 branchName( _branchName ), 15376 buildNumber( _buildNumber ) 15377 {} 15378 15379 std::ostream& operator << ( std::ostream& os, Version const& version ) { 15380 os << version.majorVersion << '.' 15381 << version.minorVersion << '.' 15382 << version.patchNumber; 15383 // branchName is never null -> 0th char is \0 if it is empty 15384 if (version.branchName[0]) { 15385 os << '-' << version.branchName 15386 << '.' << version.buildNumber; 15387 } 15388 return os; 15389 } 15390 15391 Version const& libraryVersion() { 15392 static Version version( 2, 13, 10, "", 0 ); 15393 return version; 15394 } 15395 15396 } 15397 // end catch_version.cpp 15398 // start catch_wildcard_pattern.cpp 15399 15400 namespace Catch { 15401 15402 WildcardPattern::WildcardPattern( std::string const& pattern, 15403 CaseSensitive::Choice caseSensitivity ) 15404 : m_caseSensitivity( caseSensitivity ), 15405 m_pattern( normaliseString( pattern ) ) 15406 { 15407 if( startsWith( m_pattern, '*' ) ) { 15408 m_pattern = m_pattern.substr( 1 ); 15409 m_wildcard = WildcardAtStart; 15410 } 15411 if( endsWith( m_pattern, '*' ) ) { 15412 m_pattern = m_pattern.substr( 0, m_pattern.size()-1 ); 15413 m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd ); 15414 } 15415 } 15416 15417 bool WildcardPattern::matches( std::string const& str ) const { 15418 switch( m_wildcard ) { 15419 case NoWildcard: 15420 return m_pattern == normaliseString( str ); 15421 case WildcardAtStart: 15422 return endsWith( normaliseString( str ), m_pattern ); 15423 case WildcardAtEnd: 15424 return startsWith( normaliseString( str ), m_pattern ); 15425 case WildcardAtBothEnds: 15426 return contains( normaliseString( str ), m_pattern ); 15427 default: 15428 CATCH_INTERNAL_ERROR( "Unknown enum" ); 15429 } 15430 } 15431 15432 std::string WildcardPattern::normaliseString( std::string const& str ) const { 15433 return trim( m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str ); 15434 } 15435 } 15436 // end catch_wildcard_pattern.cpp 15437 // start catch_xmlwriter.cpp 15438 15439 #include <iomanip> 15440 #include <type_traits> 15441 15442 namespace Catch { 15443 15444 namespace { 15445 15446 size_t trailingBytes(unsigned char c) { 15447 if ((c & 0xE0) == 0xC0) { 15448 return 2; 15449 } 15450 if ((c & 0xF0) == 0xE0) { 15451 return 3; 15452 } 15453 if ((c & 0xF8) == 0xF0) { 15454 return 4; 15455 } 15456 CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered"); 15457 } 15458 15459 uint32_t headerValue(unsigned char c) { 15460 if ((c & 0xE0) == 0xC0) { 15461 return c & 0x1F; 15462 } 15463 if ((c & 0xF0) == 0xE0) { 15464 return c & 0x0F; 15465 } 15466 if ((c & 0xF8) == 0xF0) { 15467 return c & 0x07; 15468 } 15469 CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered"); 15470 } 15471 15472 void hexEscapeChar(std::ostream& os, unsigned char c) { 15473 std::ios_base::fmtflags f(os.flags()); 15474 os << "\\x" 15475 << std::uppercase << std::hex << std::setfill('0') << std::setw(2) 15476 << static_cast<int>(c); 15477 os.flags(f); 15478 } 15479 15480 bool shouldNewline(XmlFormatting fmt) { 15481 return !!(static_cast<std::underlying_type<XmlFormatting>::type>(fmt & XmlFormatting::Newline)); 15482 } 15483 15484 bool shouldIndent(XmlFormatting fmt) { 15485 return !!(static_cast<std::underlying_type<XmlFormatting>::type>(fmt & XmlFormatting::Indent)); 15486 } 15487 15488 } // anonymous namespace 15489 15490 XmlFormatting operator | (XmlFormatting lhs, XmlFormatting rhs) { 15491 return static_cast<XmlFormatting>( 15492 static_cast<std::underlying_type<XmlFormatting>::type>(lhs) | 15493 static_cast<std::underlying_type<XmlFormatting>::type>(rhs) 15494 ); 15495 } 15496 15497 XmlFormatting operator & (XmlFormatting lhs, XmlFormatting rhs) { 15498 return static_cast<XmlFormatting>( 15499 static_cast<std::underlying_type<XmlFormatting>::type>(lhs) & 15500 static_cast<std::underlying_type<XmlFormatting>::type>(rhs) 15501 ); 15502 } 15503 15504 XmlEncode::XmlEncode( std::string const& str, ForWhat forWhat ) 15505 : m_str( str ), 15506 m_forWhat( forWhat ) 15507 {} 15508 15509 void XmlEncode::encodeTo( std::ostream& os ) const { 15510 // Apostrophe escaping not necessary if we always use " to write attributes 15511 // (see: http://www.w3.org/TR/xml/#syntax) 15512 15513 for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) { 15514 unsigned char c = m_str[idx]; 15515 switch (c) { 15516 case '<': os << "<"; break; 15517 case '&': os << "&"; break; 15518 15519 case '>': 15520 // See: http://www.w3.org/TR/xml/#syntax 15521 if (idx > 2 && m_str[idx - 1] == ']' && m_str[idx - 2] == ']') 15522 os << ">"; 15523 else 15524 os << c; 15525 break; 15526 15527 case '\"': 15528 if (m_forWhat == ForAttributes) 15529 os << """; 15530 else 15531 os << c; 15532 break; 15533 15534 default: 15535 // Check for control characters and invalid utf-8 15536 15537 // Escape control characters in standard ascii 15538 // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0 15539 if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) { 15540 hexEscapeChar(os, c); 15541 break; 15542 } 15543 15544 // Plain ASCII: Write it to stream 15545 if (c < 0x7F) { 15546 os << c; 15547 break; 15548 } 15549 15550 // UTF-8 territory 15551 // Check if the encoding is valid and if it is not, hex escape bytes. 15552 // Important: We do not check the exact decoded values for validity, only the encoding format 15553 // First check that this bytes is a valid lead byte: 15554 // This means that it is not encoded as 1111 1XXX 15555 // Or as 10XX XXXX 15556 if (c < 0xC0 || 15557 c >= 0xF8) { 15558 hexEscapeChar(os, c); 15559 break; 15560 } 15561 15562 auto encBytes = trailingBytes(c); 15563 // Are there enough bytes left to avoid accessing out-of-bounds memory? 15564 if (idx + encBytes - 1 >= m_str.size()) { 15565 hexEscapeChar(os, c); 15566 break; 15567 } 15568 // The header is valid, check data 15569 // The next encBytes bytes must together be a valid utf-8 15570 // This means: bitpattern 10XX XXXX and the extracted value is sane (ish) 15571 bool valid = true; 15572 uint32_t value = headerValue(c); 15573 for (std::size_t n = 1; n < encBytes; ++n) { 15574 unsigned char nc = m_str[idx + n]; 15575 valid &= ((nc & 0xC0) == 0x80); 15576 value = (value << 6) | (nc & 0x3F); 15577 } 15578 15579 if ( 15580 // Wrong bit pattern of following bytes 15581 (!valid) || 15582 // Overlong encodings 15583 (value < 0x80) || 15584 (0x80 <= value && value < 0x800 && encBytes > 2) || 15585 (0x800 < value && value < 0x10000 && encBytes > 3) || 15586 // Encoded value out of range 15587 (value >= 0x110000) 15588 ) { 15589 hexEscapeChar(os, c); 15590 break; 15591 } 15592 15593 // If we got here, this is in fact a valid(ish) utf-8 sequence 15594 for (std::size_t n = 0; n < encBytes; ++n) { 15595 os << m_str[idx + n]; 15596 } 15597 idx += encBytes - 1; 15598 break; 15599 } 15600 } 15601 } 15602 15603 std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) { 15604 xmlEncode.encodeTo( os ); 15605 return os; 15606 } 15607 15608 XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer, XmlFormatting fmt ) 15609 : m_writer( writer ), 15610 m_fmt(fmt) 15611 {} 15612 15613 XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) noexcept 15614 : m_writer( other.m_writer ), 15615 m_fmt(other.m_fmt) 15616 { 15617 other.m_writer = nullptr; 15618 other.m_fmt = XmlFormatting::None; 15619 } 15620 XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) noexcept { 15621 if ( m_writer ) { 15622 m_writer->endElement(); 15623 } 15624 m_writer = other.m_writer; 15625 other.m_writer = nullptr; 15626 m_fmt = other.m_fmt; 15627 other.m_fmt = XmlFormatting::None; 15628 return *this; 15629 } 15630 15631 XmlWriter::ScopedElement::~ScopedElement() { 15632 if (m_writer) { 15633 m_writer->endElement(m_fmt); 15634 } 15635 } 15636 15637 XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText( std::string const& text, XmlFormatting fmt ) { 15638 m_writer->writeText( text, fmt ); 15639 return *this; 15640 } 15641 15642 XmlWriter::XmlWriter( std::ostream& os ) : m_os( os ) 15643 { 15644 writeDeclaration(); 15645 } 15646 15647 XmlWriter::~XmlWriter() { 15648 while (!m_tags.empty()) { 15649 endElement(); 15650 } 15651 newlineIfNecessary(); 15652 } 15653 15654 XmlWriter& XmlWriter::startElement( std::string const& name, XmlFormatting fmt ) { 15655 ensureTagClosed(); 15656 newlineIfNecessary(); 15657 if (shouldIndent(fmt)) { 15658 m_os << m_indent; 15659 m_indent += " "; 15660 } 15661 m_os << '<' << name; 15662 m_tags.push_back( name ); 15663 m_tagIsOpen = true; 15664 applyFormatting(fmt); 15665 return *this; 15666 } 15667 15668 XmlWriter::ScopedElement XmlWriter::scopedElement( std::string const& name, XmlFormatting fmt ) { 15669 ScopedElement scoped( this, fmt ); 15670 startElement( name, fmt ); 15671 return scoped; 15672 } 15673 15674 XmlWriter& XmlWriter::endElement(XmlFormatting fmt) { 15675 m_indent = m_indent.substr(0, m_indent.size() - 2); 15676 15677 if( m_tagIsOpen ) { 15678 m_os << "/>"; 15679 m_tagIsOpen = false; 15680 } else { 15681 newlineIfNecessary(); 15682 if (shouldIndent(fmt)) { 15683 m_os << m_indent; 15684 } 15685 m_os << "</" << m_tags.back() << ">"; 15686 } 15687 m_os << std::flush; 15688 applyFormatting(fmt); 15689 m_tags.pop_back(); 15690 return *this; 15691 } 15692 15693 XmlWriter& XmlWriter::writeAttribute( std::string const& name, std::string const& attribute ) { 15694 if( !name.empty() && !attribute.empty() ) 15695 m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"'; 15696 return *this; 15697 } 15698 15699 XmlWriter& XmlWriter::writeAttribute( std::string const& name, bool attribute ) { 15700 m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"'; 15701 return *this; 15702 } 15703 15704 XmlWriter& XmlWriter::writeText( std::string const& text, XmlFormatting fmt) { 15705 if( !text.empty() ){ 15706 bool tagWasOpen = m_tagIsOpen; 15707 ensureTagClosed(); 15708 if (tagWasOpen && shouldIndent(fmt)) { 15709 m_os << m_indent; 15710 } 15711 m_os << XmlEncode( text ); 15712 applyFormatting(fmt); 15713 } 15714 return *this; 15715 } 15716 15717 XmlWriter& XmlWriter::writeComment( std::string const& text, XmlFormatting fmt) { 15718 ensureTagClosed(); 15719 if (shouldIndent(fmt)) { 15720 m_os << m_indent; 15721 } 15722 m_os << "<!--" << text << "-->"; 15723 applyFormatting(fmt); 15724 return *this; 15725 } 15726 15727 void XmlWriter::writeStylesheetRef( std::string const& url ) { 15728 m_os << "<?xml-stylesheet type=\"text/xsl\" href=\"" << url << "\"?>\n"; 15729 } 15730 15731 XmlWriter& XmlWriter::writeBlankLine() { 15732 ensureTagClosed(); 15733 m_os << '\n'; 15734 return *this; 15735 } 15736 15737 void XmlWriter::ensureTagClosed() { 15738 if( m_tagIsOpen ) { 15739 m_os << '>' << std::flush; 15740 newlineIfNecessary(); 15741 m_tagIsOpen = false; 15742 } 15743 } 15744 15745 void XmlWriter::applyFormatting(XmlFormatting fmt) { 15746 m_needsNewline = shouldNewline(fmt); 15747 } 15748 15749 void XmlWriter::writeDeclaration() { 15750 m_os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; 15751 } 15752 15753 void XmlWriter::newlineIfNecessary() { 15754 if( m_needsNewline ) { 15755 m_os << std::endl; 15756 m_needsNewline = false; 15757 } 15758 } 15759 } 15760 // end catch_xmlwriter.cpp 15761 // start catch_reporter_bases.cpp 15762 15763 #include <cstring> 15764 #include <cfloat> 15765 #include <cstdio> 15766 #include <cassert> 15767 #include <memory> 15768 15769 namespace Catch { 15770 void prepareExpandedExpression(AssertionResult& result) { 15771 result.getExpandedExpression(); 15772 } 15773 15774 // Because formatting using c++ streams is stateful, drop down to C is required 15775 // Alternatively we could use stringstream, but its performance is... not good. 15776 std::string getFormattedDuration( double duration ) { 15777 // Max exponent + 1 is required to represent the whole part 15778 // + 1 for decimal point 15779 // + 3 for the 3 decimal places 15780 // + 1 for null terminator 15781 const std::size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1; 15782 char buffer[maxDoubleSize]; 15783 15784 // Save previous errno, to prevent sprintf from overwriting it 15785 ErrnoGuard guard; 15786 #ifdef _MSC_VER 15787 sprintf_s(buffer, "%.3f", duration); 15788 #else 15789 std::sprintf(buffer, "%.3f", duration); 15790 #endif 15791 return std::string(buffer); 15792 } 15793 15794 bool shouldShowDuration( IConfig const& config, double duration ) { 15795 if ( config.showDurations() == ShowDurations::Always ) { 15796 return true; 15797 } 15798 if ( config.showDurations() == ShowDurations::Never ) { 15799 return false; 15800 } 15801 const double min = config.minDuration(); 15802 return min >= 0 && duration >= min; 15803 } 15804 15805 std::string serializeFilters( std::vector<std::string> const& container ) { 15806 ReusableStringStream oss; 15807 bool first = true; 15808 for (auto&& filter : container) 15809 { 15810 if (!first) 15811 oss << ' '; 15812 else 15813 first = false; 15814 15815 oss << filter; 15816 } 15817 return oss.str(); 15818 } 15819 15820 TestEventListenerBase::TestEventListenerBase(ReporterConfig const & _config) 15821 :StreamingReporterBase(_config) {} 15822 15823 std::set<Verbosity> TestEventListenerBase::getSupportedVerbosities() { 15824 return { Verbosity::Quiet, Verbosity::Normal, Verbosity::High }; 15825 } 15826 15827 void TestEventListenerBase::assertionStarting(AssertionInfo const &) {} 15828 15829 bool TestEventListenerBase::assertionEnded(AssertionStats const &) { 15830 return false; 15831 } 15832 15833 } // end namespace Catch 15834 // end catch_reporter_bases.cpp 15835 // start catch_reporter_compact.cpp 15836 15837 namespace { 15838 15839 #ifdef CATCH_PLATFORM_MAC 15840 const char* failedString() { return "FAILED"; } 15841 const char* passedString() { return "PASSED"; } 15842 #else 15843 const char* failedString() { return "failed"; } 15844 const char* passedString() { return "passed"; } 15845 #endif 15846 15847 // Colour::LightGrey 15848 Catch::Colour::Code dimColour() { return Catch::Colour::FileName; } 15849 15850 std::string bothOrAll( std::size_t count ) { 15851 return count == 1 ? std::string() : 15852 count == 2 ? "both " : "all " ; 15853 } 15854 15855 } // anon namespace 15856 15857 namespace Catch { 15858 namespace { 15859 // Colour, message variants: 15860 // - white: No tests ran. 15861 // - red: Failed [both/all] N test cases, failed [both/all] M assertions. 15862 // - white: Passed [both/all] N test cases (no assertions). 15863 // - red: Failed N tests cases, failed M assertions. 15864 // - green: Passed [both/all] N tests cases with M assertions. 15865 void printTotals(std::ostream& out, const Totals& totals) { 15866 if (totals.testCases.total() == 0) { 15867 out << "No tests ran."; 15868 } else if (totals.testCases.failed == totals.testCases.total()) { 15869 Colour colour(Colour::ResultError); 15870 const std::string qualify_assertions_failed = 15871 totals.assertions.failed == totals.assertions.total() ? 15872 bothOrAll(totals.assertions.failed) : std::string(); 15873 out << 15874 "Failed " << bothOrAll(totals.testCases.failed) 15875 << pluralise(totals.testCases.failed, "test case") << ", " 15876 "failed " << qualify_assertions_failed << 15877 pluralise(totals.assertions.failed, "assertion") << '.'; 15878 } else if (totals.assertions.total() == 0) { 15879 out << 15880 "Passed " << bothOrAll(totals.testCases.total()) 15881 << pluralise(totals.testCases.total(), "test case") 15882 << " (no assertions)."; 15883 } else if (totals.assertions.failed) { 15884 Colour colour(Colour::ResultError); 15885 out << 15886 "Failed " << pluralise(totals.testCases.failed, "test case") << ", " 15887 "failed " << pluralise(totals.assertions.failed, "assertion") << '.'; 15888 } else { 15889 Colour colour(Colour::ResultSuccess); 15890 out << 15891 "Passed " << bothOrAll(totals.testCases.passed) 15892 << pluralise(totals.testCases.passed, "test case") << 15893 " with " << pluralise(totals.assertions.passed, "assertion") << '.'; 15894 } 15895 } 15896 15897 // Implementation of CompactReporter formatting 15898 class AssertionPrinter { 15899 public: 15900 AssertionPrinter& operator= (AssertionPrinter const&) = delete; 15901 AssertionPrinter(AssertionPrinter const&) = delete; 15902 AssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages) 15903 : stream(_stream) 15904 , result(_stats.assertionResult) 15905 , messages(_stats.infoMessages) 15906 , itMessage(_stats.infoMessages.begin()) 15907 , printInfoMessages(_printInfoMessages) {} 15908 15909 void print() { 15910 printSourceInfo(); 15911 15912 itMessage = messages.begin(); 15913 15914 switch (result.getResultType()) { 15915 case ResultWas::Ok: 15916 printResultType(Colour::ResultSuccess, passedString()); 15917 printOriginalExpression(); 15918 printReconstructedExpression(); 15919 if (!result.hasExpression()) 15920 printRemainingMessages(Colour::None); 15921 else 15922 printRemainingMessages(); 15923 break; 15924 case ResultWas::ExpressionFailed: 15925 if (result.isOk()) 15926 printResultType(Colour::ResultSuccess, failedString() + std::string(" - but was ok")); 15927 else 15928 printResultType(Colour::Error, failedString()); 15929 printOriginalExpression(); 15930 printReconstructedExpression(); 15931 printRemainingMessages(); 15932 break; 15933 case ResultWas::ThrewException: 15934 printResultType(Colour::Error, failedString()); 15935 printIssue("unexpected exception with message:"); 15936 printMessage(); 15937 printExpressionWas(); 15938 printRemainingMessages(); 15939 break; 15940 case ResultWas::FatalErrorCondition: 15941 printResultType(Colour::Error, failedString()); 15942 printIssue("fatal error condition with message:"); 15943 printMessage(); 15944 printExpressionWas(); 15945 printRemainingMessages(); 15946 break; 15947 case ResultWas::DidntThrowException: 15948 printResultType(Colour::Error, failedString()); 15949 printIssue("expected exception, got none"); 15950 printExpressionWas(); 15951 printRemainingMessages(); 15952 break; 15953 case ResultWas::Info: 15954 printResultType(Colour::None, "info"); 15955 printMessage(); 15956 printRemainingMessages(); 15957 break; 15958 case ResultWas::Warning: 15959 printResultType(Colour::None, "warning"); 15960 printMessage(); 15961 printRemainingMessages(); 15962 break; 15963 case ResultWas::ExplicitFailure: 15964 printResultType(Colour::Error, failedString()); 15965 printIssue("explicitly"); 15966 printRemainingMessages(Colour::None); 15967 break; 15968 // These cases are here to prevent compiler warnings 15969 case ResultWas::Unknown: 15970 case ResultWas::FailureBit: 15971 case ResultWas::Exception: 15972 printResultType(Colour::Error, "** internal error **"); 15973 break; 15974 } 15975 } 15976 15977 private: 15978 void printSourceInfo() const { 15979 Colour colourGuard(Colour::FileName); 15980 stream << result.getSourceInfo() << ':'; 15981 } 15982 15983 void printResultType(Colour::Code colour, std::string const& passOrFail) const { 15984 if (!passOrFail.empty()) { 15985 { 15986 Colour colourGuard(colour); 15987 stream << ' ' << passOrFail; 15988 } 15989 stream << ':'; 15990 } 15991 } 15992 15993 void printIssue(std::string const& issue) const { 15994 stream << ' ' << issue; 15995 } 15996 15997 void printExpressionWas() { 15998 if (result.hasExpression()) { 15999 stream << ';'; 16000 { 16001 Colour colour(dimColour()); 16002 stream << " expression was:"; 16003 } 16004 printOriginalExpression(); 16005 } 16006 } 16007 16008 void printOriginalExpression() const { 16009 if (result.hasExpression()) { 16010 stream << ' ' << result.getExpression(); 16011 } 16012 } 16013 16014 void printReconstructedExpression() const { 16015 if (result.hasExpandedExpression()) { 16016 { 16017 Colour colour(dimColour()); 16018 stream << " for: "; 16019 } 16020 stream << result.getExpandedExpression(); 16021 } 16022 } 16023 16024 void printMessage() { 16025 if (itMessage != messages.end()) { 16026 stream << " '" << itMessage->message << '\''; 16027 ++itMessage; 16028 } 16029 } 16030 16031 void printRemainingMessages(Colour::Code colour = dimColour()) { 16032 if (itMessage == messages.end()) 16033 return; 16034 16035 const auto itEnd = messages.cend(); 16036 const auto N = static_cast<std::size_t>(std::distance(itMessage, itEnd)); 16037 16038 { 16039 Colour colourGuard(colour); 16040 stream << " with " << pluralise(N, "message") << ':'; 16041 } 16042 16043 while (itMessage != itEnd) { 16044 // If this assertion is a warning ignore any INFO messages 16045 if (printInfoMessages || itMessage->type != ResultWas::Info) { 16046 printMessage(); 16047 if (itMessage != itEnd) { 16048 Colour colourGuard(dimColour()); 16049 stream << " and"; 16050 } 16051 continue; 16052 } 16053 ++itMessage; 16054 } 16055 } 16056 16057 private: 16058 std::ostream& stream; 16059 AssertionResult const& result; 16060 std::vector<MessageInfo> messages; 16061 std::vector<MessageInfo>::const_iterator itMessage; 16062 bool printInfoMessages; 16063 }; 16064 16065 } // anon namespace 16066 16067 std::string CompactReporter::getDescription() { 16068 return "Reports test results on a single line, suitable for IDEs"; 16069 } 16070 16071 void CompactReporter::noMatchingTestCases( std::string const& spec ) { 16072 stream << "No test cases matched '" << spec << '\'' << std::endl; 16073 } 16074 16075 void CompactReporter::assertionStarting( AssertionInfo const& ) {} 16076 16077 bool CompactReporter::assertionEnded( AssertionStats const& _assertionStats ) { 16078 AssertionResult const& result = _assertionStats.assertionResult; 16079 16080 bool printInfoMessages = true; 16081 16082 // Drop out if result was successful and we're not printing those 16083 if( !m_config->includeSuccessfulResults() && result.isOk() ) { 16084 if( result.getResultType() != ResultWas::Warning ) 16085 return false; 16086 printInfoMessages = false; 16087 } 16088 16089 AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); 16090 printer.print(); 16091 16092 stream << std::endl; 16093 return true; 16094 } 16095 16096 void CompactReporter::sectionEnded(SectionStats const& _sectionStats) { 16097 double dur = _sectionStats.durationInSeconds; 16098 if ( shouldShowDuration( *m_config, dur ) ) { 16099 stream << getFormattedDuration( dur ) << " s: " << _sectionStats.sectionInfo.name << std::endl; 16100 } 16101 } 16102 16103 void CompactReporter::testRunEnded( TestRunStats const& _testRunStats ) { 16104 printTotals( stream, _testRunStats.totals ); 16105 stream << '\n' << std::endl; 16106 StreamingReporterBase::testRunEnded( _testRunStats ); 16107 } 16108 16109 CompactReporter::~CompactReporter() {} 16110 16111 CATCH_REGISTER_REPORTER( "compact", CompactReporter ) 16112 16113 } // end namespace Catch 16114 // end catch_reporter_compact.cpp 16115 // start catch_reporter_console.cpp 16116 16117 #include <cfloat> 16118 #include <cstdio> 16119 16120 #if defined(_MSC_VER) 16121 #pragma warning(push) 16122 #pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch 16123 // Note that 4062 (not all labels are handled and default is missing) is enabled 16124 #endif 16125 16126 #if defined(__clang__) 16127 # pragma clang diagnostic push 16128 // For simplicity, benchmarking-only helpers are always enabled 16129 # pragma clang diagnostic ignored "-Wunused-function" 16130 #endif 16131 16132 namespace Catch { 16133 16134 namespace { 16135 16136 // Formatter impl for ConsoleReporter 16137 class ConsoleAssertionPrinter { 16138 public: 16139 ConsoleAssertionPrinter& operator= (ConsoleAssertionPrinter const&) = delete; 16140 ConsoleAssertionPrinter(ConsoleAssertionPrinter const&) = delete; 16141 ConsoleAssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages) 16142 : stream(_stream), 16143 stats(_stats), 16144 result(_stats.assertionResult), 16145 colour(Colour::None), 16146 message(result.getMessage()), 16147 messages(_stats.infoMessages), 16148 printInfoMessages(_printInfoMessages) { 16149 switch (result.getResultType()) { 16150 case ResultWas::Ok: 16151 colour = Colour::Success; 16152 passOrFail = "PASSED"; 16153 //if( result.hasMessage() ) 16154 if (_stats.infoMessages.size() == 1) 16155 messageLabel = "with message"; 16156 if (_stats.infoMessages.size() > 1) 16157 messageLabel = "with messages"; 16158 break; 16159 case ResultWas::ExpressionFailed: 16160 if (result.isOk()) { 16161 colour = Colour::Success; 16162 passOrFail = "FAILED - but was ok"; 16163 } else { 16164 colour = Colour::Error; 16165 passOrFail = "FAILED"; 16166 } 16167 if (_stats.infoMessages.size() == 1) 16168 messageLabel = "with message"; 16169 if (_stats.infoMessages.size() > 1) 16170 messageLabel = "with messages"; 16171 break; 16172 case ResultWas::ThrewException: 16173 colour = Colour::Error; 16174 passOrFail = "FAILED"; 16175 messageLabel = "due to unexpected exception with "; 16176 if (_stats.infoMessages.size() == 1) 16177 messageLabel += "message"; 16178 if (_stats.infoMessages.size() > 1) 16179 messageLabel += "messages"; 16180 break; 16181 case ResultWas::FatalErrorCondition: 16182 colour = Colour::Error; 16183 passOrFail = "FAILED"; 16184 messageLabel = "due to a fatal error condition"; 16185 break; 16186 case ResultWas::DidntThrowException: 16187 colour = Colour::Error; 16188 passOrFail = "FAILED"; 16189 messageLabel = "because no exception was thrown where one was expected"; 16190 break; 16191 case ResultWas::Info: 16192 messageLabel = "info"; 16193 break; 16194 case ResultWas::Warning: 16195 messageLabel = "warning"; 16196 break; 16197 case ResultWas::ExplicitFailure: 16198 passOrFail = "FAILED"; 16199 colour = Colour::Error; 16200 if (_stats.infoMessages.size() == 1) 16201 messageLabel = "explicitly with message"; 16202 if (_stats.infoMessages.size() > 1) 16203 messageLabel = "explicitly with messages"; 16204 break; 16205 // These cases are here to prevent compiler warnings 16206 case ResultWas::Unknown: 16207 case ResultWas::FailureBit: 16208 case ResultWas::Exception: 16209 passOrFail = "** internal error **"; 16210 colour = Colour::Error; 16211 break; 16212 } 16213 } 16214 16215 void print() const { 16216 printSourceInfo(); 16217 if (stats.totals.assertions.total() > 0) { 16218 printResultType(); 16219 printOriginalExpression(); 16220 printReconstructedExpression(); 16221 } else { 16222 stream << '\n'; 16223 } 16224 printMessage(); 16225 } 16226 16227 private: 16228 void printResultType() const { 16229 if (!passOrFail.empty()) { 16230 Colour colourGuard(colour); 16231 stream << passOrFail << ":\n"; 16232 } 16233 } 16234 void printOriginalExpression() const { 16235 if (result.hasExpression()) { 16236 Colour colourGuard(Colour::OriginalExpression); 16237 stream << " "; 16238 stream << result.getExpressionInMacro(); 16239 stream << '\n'; 16240 } 16241 } 16242 void printReconstructedExpression() const { 16243 if (result.hasExpandedExpression()) { 16244 stream << "with expansion:\n"; 16245 Colour colourGuard(Colour::ReconstructedExpression); 16246 stream << Column(result.getExpandedExpression()).indent(2) << '\n'; 16247 } 16248 } 16249 void printMessage() const { 16250 if (!messageLabel.empty()) 16251 stream << messageLabel << ':' << '\n'; 16252 for (auto const& msg : messages) { 16253 // If this assertion is a warning ignore any INFO messages 16254 if (printInfoMessages || msg.type != ResultWas::Info) 16255 stream << Column(msg.message).indent(2) << '\n'; 16256 } 16257 } 16258 void printSourceInfo() const { 16259 Colour colourGuard(Colour::FileName); 16260 stream << result.getSourceInfo() << ": "; 16261 } 16262 16263 std::ostream& stream; 16264 AssertionStats const& stats; 16265 AssertionResult const& result; 16266 Colour::Code colour; 16267 std::string passOrFail; 16268 std::string messageLabel; 16269 std::string message; 16270 std::vector<MessageInfo> messages; 16271 bool printInfoMessages; 16272 }; 16273 16274 std::size_t makeRatio(std::size_t number, std::size_t total) { 16275 std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number / total : 0; 16276 return (ratio == 0 && number > 0) ? 1 : ratio; 16277 } 16278 16279 std::size_t& findMax(std::size_t& i, std::size_t& j, std::size_t& k) { 16280 if (i > j && i > k) 16281 return i; 16282 else if (j > k) 16283 return j; 16284 else 16285 return k; 16286 } 16287 16288 struct ColumnInfo { 16289 enum Justification { Left, Right }; 16290 std::string name; 16291 int width; 16292 Justification justification; 16293 }; 16294 struct ColumnBreak {}; 16295 struct RowBreak {}; 16296 16297 class Duration { 16298 enum class Unit { 16299 Auto, 16300 Nanoseconds, 16301 Microseconds, 16302 Milliseconds, 16303 Seconds, 16304 Minutes 16305 }; 16306 static const uint64_t s_nanosecondsInAMicrosecond = 1000; 16307 static const uint64_t s_nanosecondsInAMillisecond = 1000 * s_nanosecondsInAMicrosecond; 16308 static const uint64_t s_nanosecondsInASecond = 1000 * s_nanosecondsInAMillisecond; 16309 static const uint64_t s_nanosecondsInAMinute = 60 * s_nanosecondsInASecond; 16310 16311 double m_inNanoseconds; 16312 Unit m_units; 16313 16314 public: 16315 explicit Duration(double inNanoseconds, Unit units = Unit::Auto) 16316 : m_inNanoseconds(inNanoseconds), 16317 m_units(units) { 16318 if (m_units == Unit::Auto) { 16319 if (m_inNanoseconds < s_nanosecondsInAMicrosecond) 16320 m_units = Unit::Nanoseconds; 16321 else if (m_inNanoseconds < s_nanosecondsInAMillisecond) 16322 m_units = Unit::Microseconds; 16323 else if (m_inNanoseconds < s_nanosecondsInASecond) 16324 m_units = Unit::Milliseconds; 16325 else if (m_inNanoseconds < s_nanosecondsInAMinute) 16326 m_units = Unit::Seconds; 16327 else 16328 m_units = Unit::Minutes; 16329 } 16330 16331 } 16332 16333 auto value() const -> double { 16334 switch (m_units) { 16335 case Unit::Microseconds: 16336 return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMicrosecond); 16337 case Unit::Milliseconds: 16338 return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMillisecond); 16339 case Unit::Seconds: 16340 return m_inNanoseconds / static_cast<double>(s_nanosecondsInASecond); 16341 case Unit::Minutes: 16342 return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMinute); 16343 default: 16344 return m_inNanoseconds; 16345 } 16346 } 16347 auto unitsAsString() const -> std::string { 16348 switch (m_units) { 16349 case Unit::Nanoseconds: 16350 return "ns"; 16351 case Unit::Microseconds: 16352 return "us"; 16353 case Unit::Milliseconds: 16354 return "ms"; 16355 case Unit::Seconds: 16356 return "s"; 16357 case Unit::Minutes: 16358 return "m"; 16359 default: 16360 return "** internal error **"; 16361 } 16362 16363 } 16364 friend auto operator << (std::ostream& os, Duration const& duration) -> std::ostream& { 16365 return os << duration.value() << ' ' << duration.unitsAsString(); 16366 } 16367 }; 16368 } // end anon namespace 16369 16370 class TablePrinter { 16371 std::ostream& m_os; 16372 std::vector<ColumnInfo> m_columnInfos; 16373 std::ostringstream m_oss; 16374 int m_currentColumn = -1; 16375 bool m_isOpen = false; 16376 16377 public: 16378 TablePrinter( std::ostream& os, std::vector<ColumnInfo> columnInfos ) 16379 : m_os( os ), 16380 m_columnInfos( std::move( columnInfos ) ) {} 16381 16382 auto columnInfos() const -> std::vector<ColumnInfo> const& { 16383 return m_columnInfos; 16384 } 16385 16386 void open() { 16387 if (!m_isOpen) { 16388 m_isOpen = true; 16389 *this << RowBreak(); 16390 16391 Columns headerCols; 16392 Spacer spacer(2); 16393 for (auto const& info : m_columnInfos) { 16394 headerCols += Column(info.name).width(static_cast<std::size_t>(info.width - 2)); 16395 headerCols += spacer; 16396 } 16397 m_os << headerCols << '\n'; 16398 16399 m_os << Catch::getLineOfChars<'-'>() << '\n'; 16400 } 16401 } 16402 void close() { 16403 if (m_isOpen) { 16404 *this << RowBreak(); 16405 m_os << std::endl; 16406 m_isOpen = false; 16407 } 16408 } 16409 16410 template<typename T> 16411 friend TablePrinter& operator << (TablePrinter& tp, T const& value) { 16412 tp.m_oss << value; 16413 return tp; 16414 } 16415 16416 friend TablePrinter& operator << (TablePrinter& tp, ColumnBreak) { 16417 auto colStr = tp.m_oss.str(); 16418 const auto strSize = colStr.size(); 16419 tp.m_oss.str(""); 16420 tp.open(); 16421 if (tp.m_currentColumn == static_cast<int>(tp.m_columnInfos.size() - 1)) { 16422 tp.m_currentColumn = -1; 16423 tp.m_os << '\n'; 16424 } 16425 tp.m_currentColumn++; 16426 16427 auto colInfo = tp.m_columnInfos[tp.m_currentColumn]; 16428 auto padding = (strSize + 1 < static_cast<std::size_t>(colInfo.width)) 16429 ? std::string(colInfo.width - (strSize + 1), ' ') 16430 : std::string(); 16431 if (colInfo.justification == ColumnInfo::Left) 16432 tp.m_os << colStr << padding << ' '; 16433 else 16434 tp.m_os << padding << colStr << ' '; 16435 return tp; 16436 } 16437 16438 friend TablePrinter& operator << (TablePrinter& tp, RowBreak) { 16439 if (tp.m_currentColumn > 0) { 16440 tp.m_os << '\n'; 16441 tp.m_currentColumn = -1; 16442 } 16443 return tp; 16444 } 16445 }; 16446 16447 ConsoleReporter::ConsoleReporter(ReporterConfig const& config) 16448 : StreamingReporterBase(config), 16449 m_tablePrinter(new TablePrinter(config.stream(), 16450 [&config]() -> std::vector<ColumnInfo> { 16451 if (config.fullConfig()->benchmarkNoAnalysis()) 16452 { 16453 return{ 16454 { "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 43, ColumnInfo::Left }, 16455 { " samples", 14, ColumnInfo::Right }, 16456 { " iterations", 14, ColumnInfo::Right }, 16457 { " mean", 14, ColumnInfo::Right } 16458 }; 16459 } 16460 else 16461 { 16462 return{ 16463 { "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 43, ColumnInfo::Left }, 16464 { "samples mean std dev", 14, ColumnInfo::Right }, 16465 { "iterations low mean low std dev", 14, ColumnInfo::Right }, 16466 { "estimated high mean high std dev", 14, ColumnInfo::Right } 16467 }; 16468 } 16469 }())) {} 16470 ConsoleReporter::~ConsoleReporter() = default; 16471 16472 std::string ConsoleReporter::getDescription() { 16473 return "Reports test results as plain lines of text"; 16474 } 16475 16476 void ConsoleReporter::noMatchingTestCases(std::string const& spec) { 16477 stream << "No test cases matched '" << spec << '\'' << std::endl; 16478 } 16479 16480 void ConsoleReporter::reportInvalidArguments(std::string const&arg){ 16481 stream << "Invalid Filter: " << arg << std::endl; 16482 } 16483 16484 void ConsoleReporter::assertionStarting(AssertionInfo const&) {} 16485 16486 bool ConsoleReporter::assertionEnded(AssertionStats const& _assertionStats) { 16487 AssertionResult const& result = _assertionStats.assertionResult; 16488 16489 bool includeResults = m_config->includeSuccessfulResults() || !result.isOk(); 16490 16491 // Drop out if result was successful but we're not printing them. 16492 if (!includeResults && result.getResultType() != ResultWas::Warning) 16493 return false; 16494 16495 lazyPrint(); 16496 16497 ConsoleAssertionPrinter printer(stream, _assertionStats, includeResults); 16498 printer.print(); 16499 stream << std::endl; 16500 return true; 16501 } 16502 16503 void ConsoleReporter::sectionStarting(SectionInfo const& _sectionInfo) { 16504 m_tablePrinter->close(); 16505 m_headerPrinted = false; 16506 StreamingReporterBase::sectionStarting(_sectionInfo); 16507 } 16508 void ConsoleReporter::sectionEnded(SectionStats const& _sectionStats) { 16509 m_tablePrinter->close(); 16510 if (_sectionStats.missingAssertions) { 16511 lazyPrint(); 16512 Colour colour(Colour::ResultError); 16513 if (m_sectionStack.size() > 1) 16514 stream << "\nNo assertions in section"; 16515 else 16516 stream << "\nNo assertions in test case"; 16517 stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; 16518 } 16519 double dur = _sectionStats.durationInSeconds; 16520 if (shouldShowDuration(*m_config, dur)) { 16521 stream << getFormattedDuration(dur) << " s: " << _sectionStats.sectionInfo.name << std::endl; 16522 } 16523 if (m_headerPrinted) { 16524 m_headerPrinted = false; 16525 } 16526 StreamingReporterBase::sectionEnded(_sectionStats); 16527 } 16528 16529 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 16530 void ConsoleReporter::benchmarkPreparing(std::string const& name) { 16531 lazyPrintWithoutClosingBenchmarkTable(); 16532 16533 auto nameCol = Column(name).width(static_cast<std::size_t>(m_tablePrinter->columnInfos()[0].width - 2)); 16534 16535 bool firstLine = true; 16536 for (auto line : nameCol) { 16537 if (!firstLine) 16538 (*m_tablePrinter) << ColumnBreak() << ColumnBreak() << ColumnBreak(); 16539 else 16540 firstLine = false; 16541 16542 (*m_tablePrinter) << line << ColumnBreak(); 16543 } 16544 } 16545 16546 void ConsoleReporter::benchmarkStarting(BenchmarkInfo const& info) { 16547 (*m_tablePrinter) << info.samples << ColumnBreak() 16548 << info.iterations << ColumnBreak(); 16549 if (!m_config->benchmarkNoAnalysis()) 16550 (*m_tablePrinter) << Duration(info.estimatedDuration) << ColumnBreak(); 16551 } 16552 void ConsoleReporter::benchmarkEnded(BenchmarkStats<> const& stats) { 16553 if (m_config->benchmarkNoAnalysis()) 16554 { 16555 (*m_tablePrinter) << Duration(stats.mean.point.count()) << ColumnBreak(); 16556 } 16557 else 16558 { 16559 (*m_tablePrinter) << ColumnBreak() 16560 << Duration(stats.mean.point.count()) << ColumnBreak() 16561 << Duration(stats.mean.lower_bound.count()) << ColumnBreak() 16562 << Duration(stats.mean.upper_bound.count()) << ColumnBreak() << ColumnBreak() 16563 << Duration(stats.standardDeviation.point.count()) << ColumnBreak() 16564 << Duration(stats.standardDeviation.lower_bound.count()) << ColumnBreak() 16565 << Duration(stats.standardDeviation.upper_bound.count()) << ColumnBreak() << ColumnBreak() << ColumnBreak() << ColumnBreak() << ColumnBreak(); 16566 } 16567 } 16568 16569 void ConsoleReporter::benchmarkFailed(std::string const& error) { 16570 Colour colour(Colour::Red); 16571 (*m_tablePrinter) 16572 << "Benchmark failed (" << error << ')' 16573 << ColumnBreak() << RowBreak(); 16574 } 16575 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 16576 16577 void ConsoleReporter::testCaseEnded(TestCaseStats const& _testCaseStats) { 16578 m_tablePrinter->close(); 16579 StreamingReporterBase::testCaseEnded(_testCaseStats); 16580 m_headerPrinted = false; 16581 } 16582 void ConsoleReporter::testGroupEnded(TestGroupStats const& _testGroupStats) { 16583 if (currentGroupInfo.used) { 16584 printSummaryDivider(); 16585 stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; 16586 printTotals(_testGroupStats.totals); 16587 stream << '\n' << std::endl; 16588 } 16589 StreamingReporterBase::testGroupEnded(_testGroupStats); 16590 } 16591 void ConsoleReporter::testRunEnded(TestRunStats const& _testRunStats) { 16592 printTotalsDivider(_testRunStats.totals); 16593 printTotals(_testRunStats.totals); 16594 stream << std::endl; 16595 StreamingReporterBase::testRunEnded(_testRunStats); 16596 } 16597 void ConsoleReporter::testRunStarting(TestRunInfo const& _testInfo) { 16598 StreamingReporterBase::testRunStarting(_testInfo); 16599 printTestFilters(); 16600 } 16601 16602 void ConsoleReporter::lazyPrint() { 16603 16604 m_tablePrinter->close(); 16605 lazyPrintWithoutClosingBenchmarkTable(); 16606 } 16607 16608 void ConsoleReporter::lazyPrintWithoutClosingBenchmarkTable() { 16609 16610 if (!currentTestRunInfo.used) 16611 lazyPrintRunInfo(); 16612 if (!currentGroupInfo.used) 16613 lazyPrintGroupInfo(); 16614 16615 if (!m_headerPrinted) { 16616 printTestCaseAndSectionHeader(); 16617 m_headerPrinted = true; 16618 } 16619 } 16620 void ConsoleReporter::lazyPrintRunInfo() { 16621 stream << '\n' << getLineOfChars<'~'>() << '\n'; 16622 Colour colour(Colour::SecondaryText); 16623 stream << currentTestRunInfo->name 16624 << " is a Catch v" << libraryVersion() << " host application.\n" 16625 << "Run with -? for options\n\n"; 16626 16627 if (m_config->rngSeed() != 0) 16628 stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n"; 16629 16630 currentTestRunInfo.used = true; 16631 } 16632 void ConsoleReporter::lazyPrintGroupInfo() { 16633 if (!currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1) { 16634 printClosedHeader("Group: " + currentGroupInfo->name); 16635 currentGroupInfo.used = true; 16636 } 16637 } 16638 void ConsoleReporter::printTestCaseAndSectionHeader() { 16639 assert(!m_sectionStack.empty()); 16640 printOpenHeader(currentTestCaseInfo->name); 16641 16642 if (m_sectionStack.size() > 1) { 16643 Colour colourGuard(Colour::Headers); 16644 16645 auto 16646 it = m_sectionStack.begin() + 1, // Skip first section (test case) 16647 itEnd = m_sectionStack.end(); 16648 for (; it != itEnd; ++it) 16649 printHeaderString(it->name, 2); 16650 } 16651 16652 SourceLineInfo lineInfo = m_sectionStack.back().lineInfo; 16653 16654 stream << getLineOfChars<'-'>() << '\n'; 16655 Colour colourGuard(Colour::FileName); 16656 stream << lineInfo << '\n'; 16657 stream << getLineOfChars<'.'>() << '\n' << std::endl; 16658 } 16659 16660 void ConsoleReporter::printClosedHeader(std::string const& _name) { 16661 printOpenHeader(_name); 16662 stream << getLineOfChars<'.'>() << '\n'; 16663 } 16664 void ConsoleReporter::printOpenHeader(std::string const& _name) { 16665 stream << getLineOfChars<'-'>() << '\n'; 16666 { 16667 Colour colourGuard(Colour::Headers); 16668 printHeaderString(_name); 16669 } 16670 } 16671 16672 // if string has a : in first line will set indent to follow it on 16673 // subsequent lines 16674 void ConsoleReporter::printHeaderString(std::string const& _string, std::size_t indent) { 16675 std::size_t i = _string.find(": "); 16676 if (i != std::string::npos) 16677 i += 2; 16678 else 16679 i = 0; 16680 stream << Column(_string).indent(indent + i).initialIndent(indent) << '\n'; 16681 } 16682 16683 struct SummaryColumn { 16684 16685 SummaryColumn( std::string _label, Colour::Code _colour ) 16686 : label( std::move( _label ) ), 16687 colour( _colour ) {} 16688 SummaryColumn addRow( std::size_t count ) { 16689 ReusableStringStream rss; 16690 rss << count; 16691 std::string row = rss.str(); 16692 for (auto& oldRow : rows) { 16693 while (oldRow.size() < row.size()) 16694 oldRow = ' ' + oldRow; 16695 while (oldRow.size() > row.size()) 16696 row = ' ' + row; 16697 } 16698 rows.push_back(row); 16699 return *this; 16700 } 16701 16702 std::string label; 16703 Colour::Code colour; 16704 std::vector<std::string> rows; 16705 16706 }; 16707 16708 void ConsoleReporter::printTotals( Totals const& totals ) { 16709 if (totals.testCases.total() == 0) { 16710 stream << Colour(Colour::Warning) << "No tests ran\n"; 16711 } else if (totals.assertions.total() > 0 && totals.testCases.allPassed()) { 16712 stream << Colour(Colour::ResultSuccess) << "All tests passed"; 16713 stream << " (" 16714 << pluralise(totals.assertions.passed, "assertion") << " in " 16715 << pluralise(totals.testCases.passed, "test case") << ')' 16716 << '\n'; 16717 } else { 16718 16719 std::vector<SummaryColumn> columns; 16720 columns.push_back(SummaryColumn("", Colour::None) 16721 .addRow(totals.testCases.total()) 16722 .addRow(totals.assertions.total())); 16723 columns.push_back(SummaryColumn("passed", Colour::Success) 16724 .addRow(totals.testCases.passed) 16725 .addRow(totals.assertions.passed)); 16726 columns.push_back(SummaryColumn("failed", Colour::ResultError) 16727 .addRow(totals.testCases.failed) 16728 .addRow(totals.assertions.failed)); 16729 columns.push_back(SummaryColumn("failed as expected", Colour::ResultExpectedFailure) 16730 .addRow(totals.testCases.failedButOk) 16731 .addRow(totals.assertions.failedButOk)); 16732 16733 printSummaryRow("test cases", columns, 0); 16734 printSummaryRow("assertions", columns, 1); 16735 } 16736 } 16737 void ConsoleReporter::printSummaryRow(std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row) { 16738 for (auto col : cols) { 16739 std::string value = col.rows[row]; 16740 if (col.label.empty()) { 16741 stream << label << ": "; 16742 if (value != "0") 16743 stream << value; 16744 else 16745 stream << Colour(Colour::Warning) << "- none -"; 16746 } else if (value != "0") { 16747 stream << Colour(Colour::LightGrey) << " | "; 16748 stream << Colour(col.colour) 16749 << value << ' ' << col.label; 16750 } 16751 } 16752 stream << '\n'; 16753 } 16754 16755 void ConsoleReporter::printTotalsDivider(Totals const& totals) { 16756 if (totals.testCases.total() > 0) { 16757 std::size_t failedRatio = makeRatio(totals.testCases.failed, totals.testCases.total()); 16758 std::size_t failedButOkRatio = makeRatio(totals.testCases.failedButOk, totals.testCases.total()); 16759 std::size_t passedRatio = makeRatio(totals.testCases.passed, totals.testCases.total()); 16760 while (failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH - 1) 16761 findMax(failedRatio, failedButOkRatio, passedRatio)++; 16762 while (failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH - 1) 16763 findMax(failedRatio, failedButOkRatio, passedRatio)--; 16764 16765 stream << Colour(Colour::Error) << std::string(failedRatio, '='); 16766 stream << Colour(Colour::ResultExpectedFailure) << std::string(failedButOkRatio, '='); 16767 if (totals.testCases.allPassed()) 16768 stream << Colour(Colour::ResultSuccess) << std::string(passedRatio, '='); 16769 else 16770 stream << Colour(Colour::Success) << std::string(passedRatio, '='); 16771 } else { 16772 stream << Colour(Colour::Warning) << std::string(CATCH_CONFIG_CONSOLE_WIDTH - 1, '='); 16773 } 16774 stream << '\n'; 16775 } 16776 void ConsoleReporter::printSummaryDivider() { 16777 stream << getLineOfChars<'-'>() << '\n'; 16778 } 16779 16780 void ConsoleReporter::printTestFilters() { 16781 if (m_config->testSpec().hasFilters()) { 16782 Colour guard(Colour::BrightYellow); 16783 stream << "Filters: " << serializeFilters(m_config->getTestsOrTags()) << '\n'; 16784 } 16785 } 16786 16787 CATCH_REGISTER_REPORTER("console", ConsoleReporter) 16788 16789 } // end namespace Catch 16790 16791 #if defined(_MSC_VER) 16792 #pragma warning(pop) 16793 #endif 16794 16795 #if defined(__clang__) 16796 # pragma clang diagnostic pop 16797 #endif 16798 // end catch_reporter_console.cpp 16799 // start catch_reporter_junit.cpp 16800 16801 #include <cassert> 16802 #include <sstream> 16803 #include <ctime> 16804 #include <algorithm> 16805 #include <iomanip> 16806 16807 namespace Catch { 16808 16809 namespace { 16810 std::string getCurrentTimestamp() { 16811 // Beware, this is not reentrant because of backward compatibility issues 16812 // Also, UTC only, again because of backward compatibility (%z is C++11) 16813 time_t rawtime; 16814 std::time(&rawtime); 16815 auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); 16816 16817 #ifdef _MSC_VER 16818 std::tm timeInfo = {}; 16819 gmtime_s(&timeInfo, &rawtime); 16820 #else 16821 std::tm* timeInfo; 16822 timeInfo = std::gmtime(&rawtime); 16823 #endif 16824 16825 char timeStamp[timeStampSize]; 16826 const char * const fmt = "%Y-%m-%dT%H:%M:%SZ"; 16827 16828 #ifdef _MSC_VER 16829 std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); 16830 #else 16831 std::strftime(timeStamp, timeStampSize, fmt, timeInfo); 16832 #endif 16833 return std::string(timeStamp, timeStampSize-1); 16834 } 16835 16836 std::string fileNameTag(const std::vector<std::string> &tags) { 16837 auto it = std::find_if(begin(tags), 16838 end(tags), 16839 [] (std::string const& tag) {return tag.front() == '#'; }); 16840 if (it != tags.end()) 16841 return it->substr(1); 16842 return std::string(); 16843 } 16844 16845 // Formats the duration in seconds to 3 decimal places. 16846 // This is done because some genius defined Maven Surefire schema 16847 // in a way that only accepts 3 decimal places, and tools like 16848 // Jenkins use that schema for validation JUnit reporter output. 16849 std::string formatDuration( double seconds ) { 16850 ReusableStringStream rss; 16851 rss << std::fixed << std::setprecision( 3 ) << seconds; 16852 return rss.str(); 16853 } 16854 16855 } // anonymous namespace 16856 16857 JunitReporter::JunitReporter( ReporterConfig const& _config ) 16858 : CumulativeReporterBase( _config ), 16859 xml( _config.stream() ) 16860 { 16861 m_reporterPrefs.shouldRedirectStdOut = true; 16862 m_reporterPrefs.shouldReportAllAssertions = true; 16863 } 16864 16865 JunitReporter::~JunitReporter() {} 16866 16867 std::string JunitReporter::getDescription() { 16868 return "Reports test results in an XML format that looks like Ant's junitreport target"; 16869 } 16870 16871 void JunitReporter::noMatchingTestCases( std::string const& /*spec*/ ) {} 16872 16873 void JunitReporter::testRunStarting( TestRunInfo const& runInfo ) { 16874 CumulativeReporterBase::testRunStarting( runInfo ); 16875 xml.startElement( "testsuites" ); 16876 } 16877 16878 void JunitReporter::testGroupStarting( GroupInfo const& groupInfo ) { 16879 suiteTimer.start(); 16880 stdOutForSuite.clear(); 16881 stdErrForSuite.clear(); 16882 unexpectedExceptions = 0; 16883 CumulativeReporterBase::testGroupStarting( groupInfo ); 16884 } 16885 16886 void JunitReporter::testCaseStarting( TestCaseInfo const& testCaseInfo ) { 16887 m_okToFail = testCaseInfo.okToFail(); 16888 } 16889 16890 bool JunitReporter::assertionEnded( AssertionStats const& assertionStats ) { 16891 if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException && !m_okToFail ) 16892 unexpectedExceptions++; 16893 return CumulativeReporterBase::assertionEnded( assertionStats ); 16894 } 16895 16896 void JunitReporter::testCaseEnded( TestCaseStats const& testCaseStats ) { 16897 stdOutForSuite += testCaseStats.stdOut; 16898 stdErrForSuite += testCaseStats.stdErr; 16899 CumulativeReporterBase::testCaseEnded( testCaseStats ); 16900 } 16901 16902 void JunitReporter::testGroupEnded( TestGroupStats const& testGroupStats ) { 16903 double suiteTime = suiteTimer.getElapsedSeconds(); 16904 CumulativeReporterBase::testGroupEnded( testGroupStats ); 16905 writeGroup( *m_testGroups.back(), suiteTime ); 16906 } 16907 16908 void JunitReporter::testRunEndedCumulative() { 16909 xml.endElement(); 16910 } 16911 16912 void JunitReporter::writeGroup( TestGroupNode const& groupNode, double suiteTime ) { 16913 XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); 16914 16915 TestGroupStats const& stats = groupNode.value; 16916 xml.writeAttribute( "name", stats.groupInfo.name ); 16917 xml.writeAttribute( "errors", unexpectedExceptions ); 16918 xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions ); 16919 xml.writeAttribute( "tests", stats.totals.assertions.total() ); 16920 xml.writeAttribute( "hostname", "tbd" ); // !TBD 16921 if( m_config->showDurations() == ShowDurations::Never ) 16922 xml.writeAttribute( "time", "" ); 16923 else 16924 xml.writeAttribute( "time", formatDuration( suiteTime ) ); 16925 xml.writeAttribute( "timestamp", getCurrentTimestamp() ); 16926 16927 // Write properties if there are any 16928 if (m_config->hasTestFilters() || m_config->rngSeed() != 0) { 16929 auto properties = xml.scopedElement("properties"); 16930 if (m_config->hasTestFilters()) { 16931 xml.scopedElement("property") 16932 .writeAttribute("name", "filters") 16933 .writeAttribute("value", serializeFilters(m_config->getTestsOrTags())); 16934 } 16935 if (m_config->rngSeed() != 0) { 16936 xml.scopedElement("property") 16937 .writeAttribute("name", "random-seed") 16938 .writeAttribute("value", m_config->rngSeed()); 16939 } 16940 } 16941 16942 // Write test cases 16943 for( auto const& child : groupNode.children ) 16944 writeTestCase( *child ); 16945 16946 xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite ), XmlFormatting::Newline ); 16947 xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite ), XmlFormatting::Newline ); 16948 } 16949 16950 void JunitReporter::writeTestCase( TestCaseNode const& testCaseNode ) { 16951 TestCaseStats const& stats = testCaseNode.value; 16952 16953 // All test cases have exactly one section - which represents the 16954 // test case itself. That section may have 0-n nested sections 16955 assert( testCaseNode.children.size() == 1 ); 16956 SectionNode const& rootSection = *testCaseNode.children.front(); 16957 16958 std::string className = stats.testInfo.className; 16959 16960 if( className.empty() ) { 16961 className = fileNameTag(stats.testInfo.tags); 16962 if ( className.empty() ) 16963 className = "global"; 16964 } 16965 16966 if ( !m_config->name().empty() ) 16967 className = m_config->name() + "." + className; 16968 16969 writeSection( className, "", rootSection, stats.testInfo.okToFail() ); 16970 } 16971 16972 void JunitReporter::writeSection( std::string const& className, 16973 std::string const& rootName, 16974 SectionNode const& sectionNode, 16975 bool testOkToFail) { 16976 std::string name = trim( sectionNode.stats.sectionInfo.name ); 16977 if( !rootName.empty() ) 16978 name = rootName + '/' + name; 16979 16980 if( !sectionNode.assertions.empty() || 16981 !sectionNode.stdOut.empty() || 16982 !sectionNode.stdErr.empty() ) { 16983 XmlWriter::ScopedElement e = xml.scopedElement( "testcase" ); 16984 if( className.empty() ) { 16985 xml.writeAttribute( "classname", name ); 16986 xml.writeAttribute( "name", "root" ); 16987 } 16988 else { 16989 xml.writeAttribute( "classname", className ); 16990 xml.writeAttribute( "name", name ); 16991 } 16992 xml.writeAttribute( "time", formatDuration( sectionNode.stats.durationInSeconds ) ); 16993 // This is not ideal, but it should be enough to mimic gtest's 16994 // junit output. 16995 // Ideally the JUnit reporter would also handle `skipTest` 16996 // events and write those out appropriately. 16997 xml.writeAttribute( "status", "run" ); 16998 16999 if (sectionNode.stats.assertions.failedButOk) { 17000 xml.scopedElement("skipped") 17001 .writeAttribute("message", "TEST_CASE tagged with !mayfail"); 17002 } 17003 17004 writeAssertions( sectionNode ); 17005 17006 if( !sectionNode.stdOut.empty() ) 17007 xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), XmlFormatting::Newline ); 17008 if( !sectionNode.stdErr.empty() ) 17009 xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), XmlFormatting::Newline ); 17010 } 17011 for( auto const& childNode : sectionNode.childSections ) 17012 if( className.empty() ) 17013 writeSection( name, "", *childNode, testOkToFail ); 17014 else 17015 writeSection( className, name, *childNode, testOkToFail ); 17016 } 17017 17018 void JunitReporter::writeAssertions( SectionNode const& sectionNode ) { 17019 for( auto const& assertion : sectionNode.assertions ) 17020 writeAssertion( assertion ); 17021 } 17022 17023 void JunitReporter::writeAssertion( AssertionStats const& stats ) { 17024 AssertionResult const& result = stats.assertionResult; 17025 if( !result.isOk() ) { 17026 std::string elementName; 17027 switch( result.getResultType() ) { 17028 case ResultWas::ThrewException: 17029 case ResultWas::FatalErrorCondition: 17030 elementName = "error"; 17031 break; 17032 case ResultWas::ExplicitFailure: 17033 case ResultWas::ExpressionFailed: 17034 case ResultWas::DidntThrowException: 17035 elementName = "failure"; 17036 break; 17037 17038 // We should never see these here: 17039 case ResultWas::Info: 17040 case ResultWas::Warning: 17041 case ResultWas::Ok: 17042 case ResultWas::Unknown: 17043 case ResultWas::FailureBit: 17044 case ResultWas::Exception: 17045 elementName = "internalError"; 17046 break; 17047 } 17048 17049 XmlWriter::ScopedElement e = xml.scopedElement( elementName ); 17050 17051 xml.writeAttribute( "message", result.getExpression() ); 17052 xml.writeAttribute( "type", result.getTestMacroName() ); 17053 17054 ReusableStringStream rss; 17055 if (stats.totals.assertions.total() > 0) { 17056 rss << "FAILED" << ":\n"; 17057 if (result.hasExpression()) { 17058 rss << " "; 17059 rss << result.getExpressionInMacro(); 17060 rss << '\n'; 17061 } 17062 if (result.hasExpandedExpression()) { 17063 rss << "with expansion:\n"; 17064 rss << Column(result.getExpandedExpression()).indent(2) << '\n'; 17065 } 17066 } else { 17067 rss << '\n'; 17068 } 17069 17070 if( !result.getMessage().empty() ) 17071 rss << result.getMessage() << '\n'; 17072 for( auto const& msg : stats.infoMessages ) 17073 if( msg.type == ResultWas::Info ) 17074 rss << msg.message << '\n'; 17075 17076 rss << "at " << result.getSourceInfo(); 17077 xml.writeText( rss.str(), XmlFormatting::Newline ); 17078 } 17079 } 17080 17081 CATCH_REGISTER_REPORTER( "junit", JunitReporter ) 17082 17083 } // end namespace Catch 17084 // end catch_reporter_junit.cpp 17085 // start catch_reporter_listening.cpp 17086 17087 #include <cassert> 17088 17089 namespace Catch { 17090 17091 ListeningReporter::ListeningReporter() { 17092 // We will assume that listeners will always want all assertions 17093 m_preferences.shouldReportAllAssertions = true; 17094 } 17095 17096 void ListeningReporter::addListener( IStreamingReporterPtr&& listener ) { 17097 m_listeners.push_back( std::move( listener ) ); 17098 } 17099 17100 void ListeningReporter::addReporter(IStreamingReporterPtr&& reporter) { 17101 assert(!m_reporter && "Listening reporter can wrap only 1 real reporter"); 17102 m_reporter = std::move( reporter ); 17103 m_preferences.shouldRedirectStdOut = m_reporter->getPreferences().shouldRedirectStdOut; 17104 } 17105 17106 ReporterPreferences ListeningReporter::getPreferences() const { 17107 return m_preferences; 17108 } 17109 17110 std::set<Verbosity> ListeningReporter::getSupportedVerbosities() { 17111 return std::set<Verbosity>{ }; 17112 } 17113 17114 void ListeningReporter::noMatchingTestCases( std::string const& spec ) { 17115 for ( auto const& listener : m_listeners ) { 17116 listener->noMatchingTestCases( spec ); 17117 } 17118 m_reporter->noMatchingTestCases( spec ); 17119 } 17120 17121 void ListeningReporter::reportInvalidArguments(std::string const&arg){ 17122 for ( auto const& listener : m_listeners ) { 17123 listener->reportInvalidArguments( arg ); 17124 } 17125 m_reporter->reportInvalidArguments( arg ); 17126 } 17127 17128 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 17129 void ListeningReporter::benchmarkPreparing( std::string const& name ) { 17130 for (auto const& listener : m_listeners) { 17131 listener->benchmarkPreparing(name); 17132 } 17133 m_reporter->benchmarkPreparing(name); 17134 } 17135 void ListeningReporter::benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) { 17136 for ( auto const& listener : m_listeners ) { 17137 listener->benchmarkStarting( benchmarkInfo ); 17138 } 17139 m_reporter->benchmarkStarting( benchmarkInfo ); 17140 } 17141 void ListeningReporter::benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) { 17142 for ( auto const& listener : m_listeners ) { 17143 listener->benchmarkEnded( benchmarkStats ); 17144 } 17145 m_reporter->benchmarkEnded( benchmarkStats ); 17146 } 17147 17148 void ListeningReporter::benchmarkFailed( std::string const& error ) { 17149 for (auto const& listener : m_listeners) { 17150 listener->benchmarkFailed(error); 17151 } 17152 m_reporter->benchmarkFailed(error); 17153 } 17154 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 17155 17156 void ListeningReporter::testRunStarting( TestRunInfo const& testRunInfo ) { 17157 for ( auto const& listener : m_listeners ) { 17158 listener->testRunStarting( testRunInfo ); 17159 } 17160 m_reporter->testRunStarting( testRunInfo ); 17161 } 17162 17163 void ListeningReporter::testGroupStarting( GroupInfo const& groupInfo ) { 17164 for ( auto const& listener : m_listeners ) { 17165 listener->testGroupStarting( groupInfo ); 17166 } 17167 m_reporter->testGroupStarting( groupInfo ); 17168 } 17169 17170 void ListeningReporter::testCaseStarting( TestCaseInfo const& testInfo ) { 17171 for ( auto const& listener : m_listeners ) { 17172 listener->testCaseStarting( testInfo ); 17173 } 17174 m_reporter->testCaseStarting( testInfo ); 17175 } 17176 17177 void ListeningReporter::sectionStarting( SectionInfo const& sectionInfo ) { 17178 for ( auto const& listener : m_listeners ) { 17179 listener->sectionStarting( sectionInfo ); 17180 } 17181 m_reporter->sectionStarting( sectionInfo ); 17182 } 17183 17184 void ListeningReporter::assertionStarting( AssertionInfo const& assertionInfo ) { 17185 for ( auto const& listener : m_listeners ) { 17186 listener->assertionStarting( assertionInfo ); 17187 } 17188 m_reporter->assertionStarting( assertionInfo ); 17189 } 17190 17191 // The return value indicates if the messages buffer should be cleared: 17192 bool ListeningReporter::assertionEnded( AssertionStats const& assertionStats ) { 17193 for( auto const& listener : m_listeners ) { 17194 static_cast<void>( listener->assertionEnded( assertionStats ) ); 17195 } 17196 return m_reporter->assertionEnded( assertionStats ); 17197 } 17198 17199 void ListeningReporter::sectionEnded( SectionStats const& sectionStats ) { 17200 for ( auto const& listener : m_listeners ) { 17201 listener->sectionEnded( sectionStats ); 17202 } 17203 m_reporter->sectionEnded( sectionStats ); 17204 } 17205 17206 void ListeningReporter::testCaseEnded( TestCaseStats const& testCaseStats ) { 17207 for ( auto const& listener : m_listeners ) { 17208 listener->testCaseEnded( testCaseStats ); 17209 } 17210 m_reporter->testCaseEnded( testCaseStats ); 17211 } 17212 17213 void ListeningReporter::testGroupEnded( TestGroupStats const& testGroupStats ) { 17214 for ( auto const& listener : m_listeners ) { 17215 listener->testGroupEnded( testGroupStats ); 17216 } 17217 m_reporter->testGroupEnded( testGroupStats ); 17218 } 17219 17220 void ListeningReporter::testRunEnded( TestRunStats const& testRunStats ) { 17221 for ( auto const& listener : m_listeners ) { 17222 listener->testRunEnded( testRunStats ); 17223 } 17224 m_reporter->testRunEnded( testRunStats ); 17225 } 17226 17227 void ListeningReporter::skipTest( TestCaseInfo const& testInfo ) { 17228 for ( auto const& listener : m_listeners ) { 17229 listener->skipTest( testInfo ); 17230 } 17231 m_reporter->skipTest( testInfo ); 17232 } 17233 17234 bool ListeningReporter::isMulti() const { 17235 return true; 17236 } 17237 17238 } // end namespace Catch 17239 // end catch_reporter_listening.cpp 17240 // start catch_reporter_xml.cpp 17241 17242 #if defined(_MSC_VER) 17243 #pragma warning(push) 17244 #pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch 17245 // Note that 4062 (not all labels are handled 17246 // and default is missing) is enabled 17247 #endif 17248 17249 namespace Catch { 17250 XmlReporter::XmlReporter( ReporterConfig const& _config ) 17251 : StreamingReporterBase( _config ), 17252 m_xml(_config.stream()) 17253 { 17254 m_reporterPrefs.shouldRedirectStdOut = true; 17255 m_reporterPrefs.shouldReportAllAssertions = true; 17256 } 17257 17258 XmlReporter::~XmlReporter() = default; 17259 17260 std::string XmlReporter::getDescription() { 17261 return "Reports test results as an XML document"; 17262 } 17263 17264 std::string XmlReporter::getStylesheetRef() const { 17265 return std::string(); 17266 } 17267 17268 void XmlReporter::writeSourceInfo( SourceLineInfo const& sourceInfo ) { 17269 m_xml 17270 .writeAttribute( "filename", sourceInfo.file ) 17271 .writeAttribute( "line", sourceInfo.line ); 17272 } 17273 17274 void XmlReporter::noMatchingTestCases( std::string const& s ) { 17275 StreamingReporterBase::noMatchingTestCases( s ); 17276 } 17277 17278 void XmlReporter::testRunStarting( TestRunInfo const& testInfo ) { 17279 StreamingReporterBase::testRunStarting( testInfo ); 17280 std::string stylesheetRef = getStylesheetRef(); 17281 if( !stylesheetRef.empty() ) 17282 m_xml.writeStylesheetRef( stylesheetRef ); 17283 m_xml.startElement( "Catch" ); 17284 if( !m_config->name().empty() ) 17285 m_xml.writeAttribute( "name", m_config->name() ); 17286 if (m_config->testSpec().hasFilters()) 17287 m_xml.writeAttribute( "filters", serializeFilters( m_config->getTestsOrTags() ) ); 17288 if( m_config->rngSeed() != 0 ) 17289 m_xml.scopedElement( "Randomness" ) 17290 .writeAttribute( "seed", m_config->rngSeed() ); 17291 } 17292 17293 void XmlReporter::testGroupStarting( GroupInfo const& groupInfo ) { 17294 StreamingReporterBase::testGroupStarting( groupInfo ); 17295 m_xml.startElement( "Group" ) 17296 .writeAttribute( "name", groupInfo.name ); 17297 } 17298 17299 void XmlReporter::testCaseStarting( TestCaseInfo const& testInfo ) { 17300 StreamingReporterBase::testCaseStarting(testInfo); 17301 m_xml.startElement( "TestCase" ) 17302 .writeAttribute( "name", trim( testInfo.name ) ) 17303 .writeAttribute( "description", testInfo.description ) 17304 .writeAttribute( "tags", testInfo.tagsAsString() ); 17305 17306 writeSourceInfo( testInfo.lineInfo ); 17307 17308 if ( m_config->showDurations() == ShowDurations::Always ) 17309 m_testCaseTimer.start(); 17310 m_xml.ensureTagClosed(); 17311 } 17312 17313 void XmlReporter::sectionStarting( SectionInfo const& sectionInfo ) { 17314 StreamingReporterBase::sectionStarting( sectionInfo ); 17315 if( m_sectionDepth++ > 0 ) { 17316 m_xml.startElement( "Section" ) 17317 .writeAttribute( "name", trim( sectionInfo.name ) ); 17318 writeSourceInfo( sectionInfo.lineInfo ); 17319 m_xml.ensureTagClosed(); 17320 } 17321 } 17322 17323 void XmlReporter::assertionStarting( AssertionInfo const& ) { } 17324 17325 bool XmlReporter::assertionEnded( AssertionStats const& assertionStats ) { 17326 17327 AssertionResult const& result = assertionStats.assertionResult; 17328 17329 bool includeResults = m_config->includeSuccessfulResults() || !result.isOk(); 17330 17331 if( includeResults || result.getResultType() == ResultWas::Warning ) { 17332 // Print any info messages in <Info> tags. 17333 for( auto const& msg : assertionStats.infoMessages ) { 17334 if( msg.type == ResultWas::Info && includeResults ) { 17335 m_xml.scopedElement( "Info" ) 17336 .writeText( msg.message ); 17337 } else if ( msg.type == ResultWas::Warning ) { 17338 m_xml.scopedElement( "Warning" ) 17339 .writeText( msg.message ); 17340 } 17341 } 17342 } 17343 17344 // Drop out if result was successful but we're not printing them. 17345 if( !includeResults && result.getResultType() != ResultWas::Warning ) 17346 return true; 17347 17348 // Print the expression if there is one. 17349 if( result.hasExpression() ) { 17350 m_xml.startElement( "Expression" ) 17351 .writeAttribute( "success", result.succeeded() ) 17352 .writeAttribute( "type", result.getTestMacroName() ); 17353 17354 writeSourceInfo( result.getSourceInfo() ); 17355 17356 m_xml.scopedElement( "Original" ) 17357 .writeText( result.getExpression() ); 17358 m_xml.scopedElement( "Expanded" ) 17359 .writeText( result.getExpandedExpression() ); 17360 } 17361 17362 // And... Print a result applicable to each result type. 17363 switch( result.getResultType() ) { 17364 case ResultWas::ThrewException: 17365 m_xml.startElement( "Exception" ); 17366 writeSourceInfo( result.getSourceInfo() ); 17367 m_xml.writeText( result.getMessage() ); 17368 m_xml.endElement(); 17369 break; 17370 case ResultWas::FatalErrorCondition: 17371 m_xml.startElement( "FatalErrorCondition" ); 17372 writeSourceInfo( result.getSourceInfo() ); 17373 m_xml.writeText( result.getMessage() ); 17374 m_xml.endElement(); 17375 break; 17376 case ResultWas::Info: 17377 m_xml.scopedElement( "Info" ) 17378 .writeText( result.getMessage() ); 17379 break; 17380 case ResultWas::Warning: 17381 // Warning will already have been written 17382 break; 17383 case ResultWas::ExplicitFailure: 17384 m_xml.startElement( "Failure" ); 17385 writeSourceInfo( result.getSourceInfo() ); 17386 m_xml.writeText( result.getMessage() ); 17387 m_xml.endElement(); 17388 break; 17389 default: 17390 break; 17391 } 17392 17393 if( result.hasExpression() ) 17394 m_xml.endElement(); 17395 17396 return true; 17397 } 17398 17399 void XmlReporter::sectionEnded( SectionStats const& sectionStats ) { 17400 StreamingReporterBase::sectionEnded( sectionStats ); 17401 if( --m_sectionDepth > 0 ) { 17402 XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" ); 17403 e.writeAttribute( "successes", sectionStats.assertions.passed ); 17404 e.writeAttribute( "failures", sectionStats.assertions.failed ); 17405 e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk ); 17406 17407 if ( m_config->showDurations() == ShowDurations::Always ) 17408 e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds ); 17409 17410 m_xml.endElement(); 17411 } 17412 } 17413 17414 void XmlReporter::testCaseEnded( TestCaseStats const& testCaseStats ) { 17415 StreamingReporterBase::testCaseEnded( testCaseStats ); 17416 XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" ); 17417 e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() ); 17418 17419 if ( m_config->showDurations() == ShowDurations::Always ) 17420 e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() ); 17421 17422 if( !testCaseStats.stdOut.empty() ) 17423 m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), XmlFormatting::Newline ); 17424 if( !testCaseStats.stdErr.empty() ) 17425 m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), XmlFormatting::Newline ); 17426 17427 m_xml.endElement(); 17428 } 17429 17430 void XmlReporter::testGroupEnded( TestGroupStats const& testGroupStats ) { 17431 StreamingReporterBase::testGroupEnded( testGroupStats ); 17432 // TODO: Check testGroupStats.aborting and act accordingly. 17433 m_xml.scopedElement( "OverallResults" ) 17434 .writeAttribute( "successes", testGroupStats.totals.assertions.passed ) 17435 .writeAttribute( "failures", testGroupStats.totals.assertions.failed ) 17436 .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk ); 17437 m_xml.scopedElement( "OverallResultsCases") 17438 .writeAttribute( "successes", testGroupStats.totals.testCases.passed ) 17439 .writeAttribute( "failures", testGroupStats.totals.testCases.failed ) 17440 .writeAttribute( "expectedFailures", testGroupStats.totals.testCases.failedButOk ); 17441 m_xml.endElement(); 17442 } 17443 17444 void XmlReporter::testRunEnded( TestRunStats const& testRunStats ) { 17445 StreamingReporterBase::testRunEnded( testRunStats ); 17446 m_xml.scopedElement( "OverallResults" ) 17447 .writeAttribute( "successes", testRunStats.totals.assertions.passed ) 17448 .writeAttribute( "failures", testRunStats.totals.assertions.failed ) 17449 .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk ); 17450 m_xml.scopedElement( "OverallResultsCases") 17451 .writeAttribute( "successes", testRunStats.totals.testCases.passed ) 17452 .writeAttribute( "failures", testRunStats.totals.testCases.failed ) 17453 .writeAttribute( "expectedFailures", testRunStats.totals.testCases.failedButOk ); 17454 m_xml.endElement(); 17455 } 17456 17457 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 17458 void XmlReporter::benchmarkPreparing(std::string const& name) { 17459 m_xml.startElement("BenchmarkResults") 17460 .writeAttribute("name", name); 17461 } 17462 17463 void XmlReporter::benchmarkStarting(BenchmarkInfo const &info) { 17464 m_xml.writeAttribute("samples", info.samples) 17465 .writeAttribute("resamples", info.resamples) 17466 .writeAttribute("iterations", info.iterations) 17467 .writeAttribute("clockResolution", info.clockResolution) 17468 .writeAttribute("estimatedDuration", info.estimatedDuration) 17469 .writeComment("All values in nano seconds"); 17470 } 17471 17472 void XmlReporter::benchmarkEnded(BenchmarkStats<> const& benchmarkStats) { 17473 m_xml.startElement("mean") 17474 .writeAttribute("value", benchmarkStats.mean.point.count()) 17475 .writeAttribute("lowerBound", benchmarkStats.mean.lower_bound.count()) 17476 .writeAttribute("upperBound", benchmarkStats.mean.upper_bound.count()) 17477 .writeAttribute("ci", benchmarkStats.mean.confidence_interval); 17478 m_xml.endElement(); 17479 m_xml.startElement("standardDeviation") 17480 .writeAttribute("value", benchmarkStats.standardDeviation.point.count()) 17481 .writeAttribute("lowerBound", benchmarkStats.standardDeviation.lower_bound.count()) 17482 .writeAttribute("upperBound", benchmarkStats.standardDeviation.upper_bound.count()) 17483 .writeAttribute("ci", benchmarkStats.standardDeviation.confidence_interval); 17484 m_xml.endElement(); 17485 m_xml.startElement("outliers") 17486 .writeAttribute("variance", benchmarkStats.outlierVariance) 17487 .writeAttribute("lowMild", benchmarkStats.outliers.low_mild) 17488 .writeAttribute("lowSevere", benchmarkStats.outliers.low_severe) 17489 .writeAttribute("highMild", benchmarkStats.outliers.high_mild) 17490 .writeAttribute("highSevere", benchmarkStats.outliers.high_severe); 17491 m_xml.endElement(); 17492 m_xml.endElement(); 17493 } 17494 17495 void XmlReporter::benchmarkFailed(std::string const &error) { 17496 m_xml.scopedElement("failed"). 17497 writeAttribute("message", error); 17498 m_xml.endElement(); 17499 } 17500 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 17501 17502 CATCH_REGISTER_REPORTER( "xml", XmlReporter ) 17503 17504 } // end namespace Catch 17505 17506 #if defined(_MSC_VER) 17507 #pragma warning(pop) 17508 #endif 17509 // end catch_reporter_xml.cpp 17510 17511 namespace Catch { 17512 LeakDetector leakDetector; 17513 } 17514 17515 #ifdef __clang__ 17516 #pragma clang diagnostic pop 17517 #endif 17518 17519 // end catch_impl.hpp 17520 #endif 17521 17522 #ifdef CATCH_CONFIG_MAIN 17523 // start catch_default_main.hpp 17524 17525 #ifndef __OBJC__ 17526 17527 #ifndef CATCH_INTERNAL_CDECL 17528 #ifdef _MSC_VER 17529 #define CATCH_INTERNAL_CDECL __cdecl 17530 #else 17531 #define CATCH_INTERNAL_CDECL 17532 #endif 17533 #endif 17534 17535 #if defined(CATCH_CONFIG_WCHAR) && defined(CATCH_PLATFORM_WINDOWS) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN) 17536 // Standard C/C++ Win32 Unicode wmain entry point 17537 extern "C" int CATCH_INTERNAL_CDECL wmain (int argc, wchar_t * argv[], wchar_t * []) { 17538 #else 17539 // Standard C/C++ main entry point 17540 int CATCH_INTERNAL_CDECL main (int argc, char * argv[]) { 17541 #endif 17542 17543 return Catch::Session().run( argc, argv ); 17544 } 17545 17546 #else // __OBJC__ 17547 17548 // Objective-C entry point 17549 int main (int argc, char * const argv[]) { 17550 #if !CATCH_ARC_ENABLED 17551 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 17552 #endif 17553 17554 Catch::registerTestMethods(); 17555 int result = Catch::Session().run( argc, (char**)argv ); 17556 17557 #if !CATCH_ARC_ENABLED 17558 [pool drain]; 17559 #endif 17560 17561 return result; 17562 } 17563 17564 #endif // __OBJC__ 17565 17566 // end catch_default_main.hpp 17567 #endif 17568 17569 #if !defined(CATCH_CONFIG_IMPL_ONLY) 17570 17571 #ifdef CLARA_CONFIG_MAIN_NOT_DEFINED 17572 # undef CLARA_CONFIG_MAIN 17573 #endif 17574 17575 #if !defined(CATCH_CONFIG_DISABLE) 17576 ////// 17577 // If this config identifier is defined then all CATCH macros are prefixed with CATCH_ 17578 #ifdef CATCH_CONFIG_PREFIX_ALL 17579 17580 #define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17581 #define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 17582 17583 #define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17584 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) 17585 #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) 17586 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17587 #define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) 17588 #endif// CATCH_CONFIG_DISABLE_MATCHERS 17589 #define CATCH_REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17590 17591 #define CATCH_CHECK( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17592 #define CATCH_CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 17593 #define CATCH_CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17594 #define CATCH_CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17595 #define CATCH_CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) 17596 17597 #define CATCH_CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17598 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) 17599 #define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 17600 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17601 #define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 17602 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17603 #define CATCH_CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17604 17605 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17606 #define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) 17607 17608 #define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) 17609 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17610 17611 #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) 17612 #define CATCH_UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "CATCH_UNSCOPED_INFO", msg ) 17613 #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) 17614 #define CATCH_CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CATCH_CAPTURE",__VA_ARGS__ ) 17615 17616 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) 17617 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17618 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) 17619 #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) 17620 #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) 17621 #define CATCH_DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ ) 17622 #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17623 #define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17624 #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17625 17626 #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE() 17627 17628 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 17629 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17630 #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) 17631 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17632 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) 17633 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) 17634 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) 17635 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17636 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) 17637 #else 17638 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) ) 17639 #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) ) 17640 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) 17641 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) ) 17642 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) ) 17643 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) ) 17644 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) 17645 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) ) 17646 #endif 17647 17648 #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE) 17649 #define CATCH_STATIC_REQUIRE( ... ) static_assert( __VA_ARGS__ , #__VA_ARGS__ ); CATCH_SUCCEED( #__VA_ARGS__ ) 17650 #define CATCH_STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); CATCH_SUCCEED( #__VA_ARGS__ ) 17651 #else 17652 #define CATCH_STATIC_REQUIRE( ... ) CATCH_REQUIRE( __VA_ARGS__ ) 17653 #define CATCH_STATIC_REQUIRE_FALSE( ... ) CATCH_REQUIRE_FALSE( __VA_ARGS__ ) 17654 #endif 17655 17656 // "BDD-style" convenience wrappers 17657 #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) 17658 #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) 17659 #define CATCH_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc ) 17660 #define CATCH_AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc ) 17661 #define CATCH_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc ) 17662 #define CATCH_AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc ) 17663 #define CATCH_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc ) 17664 #define CATCH_AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc ) 17665 17666 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 17667 #define CATCH_BENCHMARK(...) \ 17668 INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_B_E_N_C_H_), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,)) 17669 #define CATCH_BENCHMARK_ADVANCED(name) \ 17670 INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_B_E_N_C_H_), name) 17671 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 17672 17673 // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required 17674 #else 17675 17676 #define REQUIRE( ... ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17677 #define REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 17678 17679 #define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17680 #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) 17681 #define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) 17682 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17683 #define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) 17684 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17685 #define REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17686 17687 #define CHECK( ... ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17688 #define CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 17689 #define CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17690 #define CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17691 #define CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) 17692 17693 #define CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17694 #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) 17695 #define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 17696 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17697 #define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 17698 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17699 #define CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17700 17701 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17702 #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) 17703 17704 #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) 17705 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17706 17707 #define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) 17708 #define UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "UNSCOPED_INFO", msg ) 17709 #define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) 17710 #define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE",__VA_ARGS__ ) 17711 17712 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) 17713 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17714 #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) 17715 #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) 17716 #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) 17717 #define DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ ) 17718 #define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17719 #define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17720 #define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17721 #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE() 17722 17723 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 17724 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17725 #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) 17726 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17727 #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) 17728 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) 17729 #define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) 17730 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17731 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) 17732 #define TEMPLATE_LIST_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(__VA_ARGS__) 17733 #define TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17734 #else 17735 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) ) 17736 #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) ) 17737 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) 17738 #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) ) 17739 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) ) 17740 #define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) ) 17741 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) 17742 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) ) 17743 #define TEMPLATE_LIST_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE( __VA_ARGS__ ) ) 17744 #define TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) 17745 #endif 17746 17747 #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE) 17748 #define STATIC_REQUIRE( ... ) static_assert( __VA_ARGS__, #__VA_ARGS__ ); SUCCEED( #__VA_ARGS__ ) 17749 #define STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); SUCCEED( "!(" #__VA_ARGS__ ")" ) 17750 #else 17751 #define STATIC_REQUIRE( ... ) REQUIRE( __VA_ARGS__ ) 17752 #define STATIC_REQUIRE_FALSE( ... ) REQUIRE_FALSE( __VA_ARGS__ ) 17753 #endif 17754 17755 #endif 17756 17757 #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) 17758 17759 // "BDD-style" convenience wrappers 17760 #define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) 17761 #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) 17762 17763 #define GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc ) 17764 #define AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc ) 17765 #define WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc ) 17766 #define AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc ) 17767 #define THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc ) 17768 #define AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc ) 17769 17770 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 17771 #define BENCHMARK(...) \ 17772 INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_B_E_N_C_H_), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,)) 17773 #define BENCHMARK_ADVANCED(name) \ 17774 INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_B_E_N_C_H_), name) 17775 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 17776 17777 using Catch::Detail::Approx; 17778 17779 #else // CATCH_CONFIG_DISABLE 17780 17781 ////// 17782 // If this config identifier is defined then all CATCH macros are prefixed with CATCH_ 17783 #ifdef CATCH_CONFIG_PREFIX_ALL 17784 17785 #define CATCH_REQUIRE( ... ) (void)(0) 17786 #define CATCH_REQUIRE_FALSE( ... ) (void)(0) 17787 17788 #define CATCH_REQUIRE_THROWS( ... ) (void)(0) 17789 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0) 17790 #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) (void)(0) 17791 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17792 #define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) 17793 #endif// CATCH_CONFIG_DISABLE_MATCHERS 17794 #define CATCH_REQUIRE_NOTHROW( ... ) (void)(0) 17795 17796 #define CATCH_CHECK( ... ) (void)(0) 17797 #define CATCH_CHECK_FALSE( ... ) (void)(0) 17798 #define CATCH_CHECKED_IF( ... ) if (__VA_ARGS__) 17799 #define CATCH_CHECKED_ELSE( ... ) if (!(__VA_ARGS__)) 17800 #define CATCH_CHECK_NOFAIL( ... ) (void)(0) 17801 17802 #define CATCH_CHECK_THROWS( ... ) (void)(0) 17803 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) (void)(0) 17804 #define CATCH_CHECK_THROWS_WITH( expr, matcher ) (void)(0) 17805 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17806 #define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) 17807 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17808 #define CATCH_CHECK_NOTHROW( ... ) (void)(0) 17809 17810 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17811 #define CATCH_CHECK_THAT( arg, matcher ) (void)(0) 17812 17813 #define CATCH_REQUIRE_THAT( arg, matcher ) (void)(0) 17814 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17815 17816 #define CATCH_INFO( msg ) (void)(0) 17817 #define CATCH_UNSCOPED_INFO( msg ) (void)(0) 17818 #define CATCH_WARN( msg ) (void)(0) 17819 #define CATCH_CAPTURE( msg ) (void)(0) 17820 17821 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ )) 17822 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ )) 17823 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) 17824 #define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0) 17825 #define CATCH_SECTION( ... ) 17826 #define CATCH_DYNAMIC_SECTION( ... ) 17827 #define CATCH_FAIL( ... ) (void)(0) 17828 #define CATCH_FAIL_CHECK( ... ) (void)(0) 17829 #define CATCH_SUCCEED( ... ) (void)(0) 17830 17831 #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ )) 17832 17833 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 17834 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) 17835 #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) 17836 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__) 17837 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) 17838 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17839 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17840 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17841 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17842 #else 17843 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) ) 17844 #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) ) 17845 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__ ) ) 17846 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) ) 17847 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17848 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17849 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17850 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17851 #endif 17852 17853 // "BDD-style" convenience wrappers 17854 #define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ )) 17855 #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ), className ) 17856 #define CATCH_GIVEN( desc ) 17857 #define CATCH_AND_GIVEN( desc ) 17858 #define CATCH_WHEN( desc ) 17859 #define CATCH_AND_WHEN( desc ) 17860 #define CATCH_THEN( desc ) 17861 #define CATCH_AND_THEN( desc ) 17862 17863 #define CATCH_STATIC_REQUIRE( ... ) (void)(0) 17864 #define CATCH_STATIC_REQUIRE_FALSE( ... ) (void)(0) 17865 17866 // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required 17867 #else 17868 17869 #define REQUIRE( ... ) (void)(0) 17870 #define REQUIRE_FALSE( ... ) (void)(0) 17871 17872 #define REQUIRE_THROWS( ... ) (void)(0) 17873 #define REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0) 17874 #define REQUIRE_THROWS_WITH( expr, matcher ) (void)(0) 17875 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17876 #define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) 17877 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17878 #define REQUIRE_NOTHROW( ... ) (void)(0) 17879 17880 #define CHECK( ... ) (void)(0) 17881 #define CHECK_FALSE( ... ) (void)(0) 17882 #define CHECKED_IF( ... ) if (__VA_ARGS__) 17883 #define CHECKED_ELSE( ... ) if (!(__VA_ARGS__)) 17884 #define CHECK_NOFAIL( ... ) (void)(0) 17885 17886 #define CHECK_THROWS( ... ) (void)(0) 17887 #define CHECK_THROWS_AS( expr, exceptionType ) (void)(0) 17888 #define CHECK_THROWS_WITH( expr, matcher ) (void)(0) 17889 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17890 #define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) 17891 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17892 #define CHECK_NOTHROW( ... ) (void)(0) 17893 17894 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17895 #define CHECK_THAT( arg, matcher ) (void)(0) 17896 17897 #define REQUIRE_THAT( arg, matcher ) (void)(0) 17898 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17899 17900 #define INFO( msg ) (void)(0) 17901 #define UNSCOPED_INFO( msg ) (void)(0) 17902 #define WARN( msg ) (void)(0) 17903 #define CAPTURE( ... ) (void)(0) 17904 17905 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ )) 17906 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ )) 17907 #define METHOD_AS_TEST_CASE( method, ... ) 17908 #define REGISTER_TEST_CASE( Function, ... ) (void)(0) 17909 #define SECTION( ... ) 17910 #define DYNAMIC_SECTION( ... ) 17911 #define FAIL( ... ) (void)(0) 17912 #define FAIL_CHECK( ... ) (void)(0) 17913 #define SUCCEED( ... ) (void)(0) 17914 #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ )) 17915 17916 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 17917 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) 17918 #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) 17919 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__) 17920 #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) 17921 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17922 #define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17923 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17924 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17925 #else 17926 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) ) 17927 #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) ) 17928 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__ ) ) 17929 #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) ) 17930 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17931 #define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17932 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17933 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17934 #endif 17935 17936 #define STATIC_REQUIRE( ... ) (void)(0) 17937 #define STATIC_REQUIRE_FALSE( ... ) (void)(0) 17938 17939 #endif 17940 17941 #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) 17942 17943 // "BDD-style" convenience wrappers 17944 #define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ) ) 17945 #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ), className ) 17946 17947 #define GIVEN( desc ) 17948 #define AND_GIVEN( desc ) 17949 #define WHEN( desc ) 17950 #define AND_WHEN( desc ) 17951 #define THEN( desc ) 17952 #define AND_THEN( desc ) 17953 17954 using Catch::Detail::Approx; 17955 17956 #endif 17957 17958 #endif // ! CATCH_CONFIG_IMPL_ONLY 17959 17960 // start catch_reenable_warnings.h 17961 17962 17963 #ifdef __clang__ 17964 # ifdef __ICC // icpc defines the __clang__ macro 17965 # pragma warning(pop) 17966 # else 17967 # pragma clang diagnostic pop 17968 # endif 17969 #elif defined __GNUC__ 17970 # pragma GCC diagnostic pop 17971 #endif 17972 17973 // end catch_reenable_warnings.h 17974 // end catch.hpp 17975 #endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED 17976