File indexing completed on 2024-04-21 04:52:47
0001 /* 0002 * Catch v2.13.7 0003 * Generated: 2021-07-28 20:29:27.753164 0004 * ---------------------------------------------------------- 0005 * This file has been merged from multiple headers. Please don't edit it directly 0006 * Copyright (c) 2021 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 /* 0012 SPDX-FileCopyrightText: 2021 Two Blue Cubes Ltd. All rights reserved. 0013 SPDX-License-Identifier: BSL-1.0 0014 */ 0015 0016 #ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED 0017 #define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED 0018 // start catch.hpp 0019 0020 0021 #define CATCH_VERSION_MAJOR 2 0022 #define CATCH_VERSION_MINOR 13 0023 #define CATCH_VERSION_PATCH 7 0024 0025 #ifdef __clang__ 0026 # pragma clang system_header 0027 #elif defined __GNUC__ 0028 # pragma GCC system_header 0029 #endif 0030 0031 // start catch_suppress_warnings.h 0032 0033 #ifdef __clang__ 0034 # ifdef __ICC // icpc defines the __clang__ macro 0035 # pragma warning(push) 0036 # pragma warning(disable: 161 1682) 0037 # else // __ICC 0038 # pragma clang diagnostic push 0039 # pragma clang diagnostic ignored "-Wpadded" 0040 # pragma clang diagnostic ignored "-Wswitch-enum" 0041 # pragma clang diagnostic ignored "-Wcovered-switch-default" 0042 # endif 0043 #elif defined __GNUC__ 0044 // Because REQUIREs trigger GCC's -Wparentheses, and because still 0045 // supported version of g++ have only buggy support for _Pragmas, 0046 // Wparentheses have to be suppressed globally. 0047 # pragma GCC diagnostic ignored "-Wparentheses" // See #674 for details 0048 0049 # pragma GCC diagnostic push 0050 # pragma GCC diagnostic ignored "-Wunused-variable" 0051 # pragma GCC diagnostic ignored "-Wpadded" 0052 #endif 0053 // end catch_suppress_warnings.h 0054 #if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) 0055 # define CATCH_IMPL 0056 # define CATCH_CONFIG_ALL_PARTS 0057 #endif 0058 0059 // In the impl file, we want to have access to all parts of the headers 0060 // Can also be used to sanely support PCHs 0061 #if defined(CATCH_CONFIG_ALL_PARTS) 0062 # define CATCH_CONFIG_EXTERNAL_INTERFACES 0063 # if defined(CATCH_CONFIG_DISABLE_MATCHERS) 0064 # undef CATCH_CONFIG_DISABLE_MATCHERS 0065 # endif 0066 # if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) 0067 # define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER 0068 # endif 0069 #endif 0070 0071 #if !defined(CATCH_CONFIG_IMPL_ONLY) 0072 // start catch_platform.h 0073 0074 // See e.g.: 0075 // https://opensource.apple.com/source/CarbonHeaders/CarbonHeaders-18.1/TargetConditionals.h.auto.html 0076 #ifdef __APPLE__ 0077 # include <TargetConditionals.h> 0078 # if (defined(TARGET_OS_OSX) && TARGET_OS_OSX == 1) || \ 0079 (defined(TARGET_OS_MAC) && TARGET_OS_MAC == 1) 0080 # define CATCH_PLATFORM_MAC 0081 # elif (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1) 0082 # define CATCH_PLATFORM_IPHONE 0083 # endif 0084 0085 #elif defined(linux) || defined(__linux) || defined(__linux__) 0086 # define CATCH_PLATFORM_LINUX 0087 0088 #elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__) 0089 # define CATCH_PLATFORM_WINDOWS 0090 #endif 0091 0092 // end catch_platform.h 0093 0094 #ifdef CATCH_IMPL 0095 # ifndef CLARA_CONFIG_MAIN 0096 # define CLARA_CONFIG_MAIN_NOT_DEFINED 0097 # define CLARA_CONFIG_MAIN 0098 # endif 0099 #endif 0100 0101 // start catch_user_interfaces.h 0102 0103 namespace Catch { 0104 unsigned int rngSeed(); 0105 } 0106 0107 // end catch_user_interfaces.h 0108 // start catch_tag_alias_autoregistrar.h 0109 0110 // start catch_common.h 0111 0112 // start catch_compiler_capabilities.h 0113 0114 // Detect a number of compiler features - by compiler 0115 // The following features are defined: 0116 // 0117 // CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? 0118 // CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported? 0119 // CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported? 0120 // CATCH_CONFIG_DISABLE_EXCEPTIONS : Are exceptions enabled? 0121 // **************** 0122 // Note to maintainers: if new toggles are added please document them 0123 // in configuration.md, too 0124 // **************** 0125 0126 // In general each macro has a _NO_<feature name> form 0127 // (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature. 0128 // Many features, at point of detection, define an _INTERNAL_ macro, so they 0129 // can be combined, en-mass, with the _NO_ forms later. 0130 0131 #ifdef __cplusplus 0132 0133 # if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L) 0134 # define CATCH_CPP14_OR_GREATER 0135 # endif 0136 0137 # if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) 0138 # define CATCH_CPP17_OR_GREATER 0139 # endif 0140 0141 #endif 0142 0143 // Only GCC compiler should be used in this block, so other compilers trying to 0144 // mask themselves as GCC should be ignored. 0145 #if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__) && !defined(__LCC__) 0146 # define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" ) 0147 # define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" ) 0148 0149 # define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) 0150 0151 #endif 0152 0153 #if defined(__clang__) 0154 0155 # define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" ) 0156 # define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic pop" ) 0157 0158 // As of this writing, IBM XL's implementation of __builtin_constant_p has a bug 0159 // which results in calls to destructors being emitted for each temporary, 0160 // without a matching initialization. In practice, this can result in something 0161 // like `std::string::~string` being called on an uninitialized value. 0162 // 0163 // For example, this code will likely segfault under IBM XL: 0164 // ``` 0165 // REQUIRE(std::string("12") + "34" == "1234") 0166 // ``` 0167 // 0168 // Therefore, `CATCH_INTERNAL_IGNORE_BUT_WARN` is not implemented. 0169 # if !defined(__ibmxl__) && !defined(__CUDACC__) 0170 # define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) /* NOLINT(cppcoreguidelines-pro-type-vararg, hicpp-vararg) */ 0171 # endif 0172 0173 # define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 0174 _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ 0175 _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") 0176 0177 # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ 0178 _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) 0179 0180 # define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ 0181 _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" ) 0182 0183 # define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ 0184 _Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" ) 0185 0186 # define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 0187 _Pragma( "clang diagnostic ignored \"-Wunused-template\"" ) 0188 0189 #endif // __clang__ 0190 0191 //////////////////////////////////////////////////////////////////////////////// 0192 // Assume that non-Windows platforms support posix signals by default 0193 #if !defined(CATCH_PLATFORM_WINDOWS) 0194 #define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS 0195 #endif 0196 0197 //////////////////////////////////////////////////////////////////////////////// 0198 // We know some environments not to support full POSIX signals 0199 #if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__) 0200 #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS 0201 #endif 0202 0203 #ifdef __OS400__ 0204 # define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS 0205 # define CATCH_CONFIG_COLOUR_NONE 0206 #endif 0207 0208 //////////////////////////////////////////////////////////////////////////////// 0209 // Android somehow still does not support std::to_string 0210 #if defined(__ANDROID__) 0211 # define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING 0212 # define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE 0213 #endif 0214 0215 //////////////////////////////////////////////////////////////////////////////// 0216 // Not all Windows environments support SEH properly 0217 #if defined(__MINGW32__) 0218 # define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH 0219 #endif 0220 0221 //////////////////////////////////////////////////////////////////////////////// 0222 // PS4 0223 #if defined(__ORBIS__) 0224 # define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE 0225 #endif 0226 0227 //////////////////////////////////////////////////////////////////////////////// 0228 // Cygwin 0229 #ifdef __CYGWIN__ 0230 0231 // Required for some versions of Cygwin to declare gettimeofday 0232 // see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin 0233 # define _BSD_SOURCE 0234 // some versions of cygwin (most) do not support std::to_string. Use the libstd check. 0235 // https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813 0236 # if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \ 0237 && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF)) 0238 0239 # define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING 0240 0241 # endif 0242 #endif // __CYGWIN__ 0243 0244 //////////////////////////////////////////////////////////////////////////////// 0245 // Visual C++ 0246 #if defined(_MSC_VER) 0247 0248 # define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) ) 0249 # define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) ) 0250 0251 // Universal Windows platform does not support SEH 0252 // Or console colours (or console at all...) 0253 # if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) 0254 # define CATCH_CONFIG_COLOUR_NONE 0255 # else 0256 # define CATCH_INTERNAL_CONFIG_WINDOWS_SEH 0257 # endif 0258 0259 // MSVC traditional preprocessor needs some workaround for __VA_ARGS__ 0260 // _MSVC_TRADITIONAL == 0 means new conformant preprocessor 0261 // _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor 0262 # if !defined(__clang__) // Handle Clang masquerading for msvc 0263 # if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) 0264 # define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 0265 # endif // MSVC_TRADITIONAL 0266 # endif // __clang__ 0267 0268 #endif // _MSC_VER 0269 0270 #if defined(_REENTRANT) || defined(_MSC_VER) 0271 // Enable async processing, as -pthread is specified or no additional linking is required 0272 # define CATCH_INTERNAL_CONFIG_USE_ASYNC 0273 #endif // _MSC_VER 0274 0275 //////////////////////////////////////////////////////////////////////////////// 0276 // Check if we are compiled with -fno-exceptions or equivalent 0277 #if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND) 0278 # define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED 0279 #endif 0280 0281 //////////////////////////////////////////////////////////////////////////////// 0282 // DJGPP 0283 #ifdef __DJGPP__ 0284 # define CATCH_INTERNAL_CONFIG_NO_WCHAR 0285 #endif // __DJGPP__ 0286 0287 //////////////////////////////////////////////////////////////////////////////// 0288 // Embarcadero C++Build 0289 #if defined(__BORLANDC__) 0290 #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN 0291 #endif 0292 0293 //////////////////////////////////////////////////////////////////////////////// 0294 0295 // Use of __COUNTER__ is suppressed during code analysis in 0296 // CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly 0297 // handled by it. 0298 // Otherwise all supported compilers support COUNTER macro, 0299 // but user still might want to turn it off 0300 #if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L ) 0301 #define CATCH_INTERNAL_CONFIG_COUNTER 0302 #endif 0303 0304 //////////////////////////////////////////////////////////////////////////////// 0305 0306 // RTX is a special version of Windows that is real time. 0307 // This means that it is detected as Windows, but does not provide 0308 // the same set of capabilities as real Windows does. 0309 #if defined(UNDER_RTSS) || defined(RTX64_BUILD) 0310 #define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH 0311 #define CATCH_INTERNAL_CONFIG_NO_ASYNC 0312 #define CATCH_CONFIG_COLOUR_NONE 0313 #endif 0314 0315 #if !defined(_GLIBCXX_USE_C99_MATH_TR1) 0316 #define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER 0317 #endif 0318 0319 // Various stdlib support checks that require __has_include 0320 #if defined(__has_include) 0321 // Check if string_view is available and usable 0322 #if __has_include(<string_view>) && defined(CATCH_CPP17_OR_GREATER) 0323 # define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW 0324 #endif 0325 0326 // Check if optional is available and usable 0327 # if __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER) 0328 # define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL 0329 # endif // __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER) 0330 0331 // Check if byte is available and usable 0332 # if __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER) 0333 # include <cstddef> 0334 # if defined(__cpp_lib_byte) && (__cpp_lib_byte > 0) 0335 # define CATCH_INTERNAL_CONFIG_CPP17_BYTE 0336 # endif 0337 # endif // __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER) 0338 0339 // Check if variant is available and usable 0340 # if __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER) 0341 # if defined(__clang__) && (__clang_major__ < 8) 0342 // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852 0343 // fix should be in clang 8, workaround in libstdc++ 8.2 0344 # include <ciso646> 0345 # if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) 0346 # define CATCH_CONFIG_NO_CPP17_VARIANT 0347 # else 0348 # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT 0349 # endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) 0350 # else 0351 # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT 0352 # endif // defined(__clang__) && (__clang_major__ < 8) 0353 # endif // __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER) 0354 #endif // defined(__has_include) 0355 0356 #if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) 0357 # define CATCH_CONFIG_COUNTER 0358 #endif 0359 #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) 0360 # define CATCH_CONFIG_WINDOWS_SEH 0361 #endif 0362 // This is set by default, because we assume that unix compilers are posix-signal-compatible by default. 0363 #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) 0364 # define CATCH_CONFIG_POSIX_SIGNALS 0365 #endif 0366 // This is set by default, because we assume that compilers with no wchar_t support are just rare exceptions. 0367 #if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR) 0368 # define CATCH_CONFIG_WCHAR 0369 #endif 0370 0371 #if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING) 0372 # define CATCH_CONFIG_CPP11_TO_STRING 0373 #endif 0374 0375 #if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL) 0376 # define CATCH_CONFIG_CPP17_OPTIONAL 0377 #endif 0378 0379 #if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW) 0380 # define CATCH_CONFIG_CPP17_STRING_VIEW 0381 #endif 0382 0383 #if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT) 0384 # define CATCH_CONFIG_CPP17_VARIANT 0385 #endif 0386 0387 #if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && !defined(CATCH_CONFIG_NO_CPP17_BYTE) && !defined(CATCH_CONFIG_CPP17_BYTE) 0388 # define CATCH_CONFIG_CPP17_BYTE 0389 #endif 0390 0391 #if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) 0392 # define CATCH_INTERNAL_CONFIG_NEW_CAPTURE 0393 #endif 0394 0395 #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) 0396 # define CATCH_CONFIG_NEW_CAPTURE 0397 #endif 0398 0399 #if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 0400 # define CATCH_CONFIG_DISABLE_EXCEPTIONS 0401 #endif 0402 0403 #if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN) 0404 # define CATCH_CONFIG_POLYFILL_ISNAN 0405 #endif 0406 0407 #if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC) 0408 # define CATCH_CONFIG_USE_ASYNC 0409 #endif 0410 0411 #if defined(CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_NO_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_ANDROID_LOGWRITE) 0412 # define CATCH_CONFIG_ANDROID_LOGWRITE 0413 #endif 0414 0415 #if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER) 0416 # define CATCH_CONFIG_GLOBAL_NEXTAFTER 0417 #endif 0418 0419 // Even if we do not think the compiler has that warning, we still have 0420 // to provide a macro that can be used by the code. 0421 #if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION) 0422 # define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION 0423 #endif 0424 #if !defined(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION) 0425 # define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 0426 #endif 0427 #if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) 0428 # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS 0429 #endif 0430 #if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS) 0431 # define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS 0432 #endif 0433 #if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS) 0434 # define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS 0435 #endif 0436 #if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS) 0437 # define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS 0438 #endif 0439 0440 // The goal of this macro is to avoid evaluation of the arguments, but 0441 // still have the compiler warn on problems inside... 0442 #if !defined(CATCH_INTERNAL_IGNORE_BUT_WARN) 0443 # define CATCH_INTERNAL_IGNORE_BUT_WARN(...) 0444 #endif 0445 0446 #if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10) 0447 # undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS 0448 #elif defined(__clang__) && (__clang_major__ < 5) 0449 # undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS 0450 #endif 0451 0452 #if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS) 0453 # define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS 0454 #endif 0455 0456 #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 0457 #define CATCH_TRY if ((true)) 0458 #define CATCH_CATCH_ALL if ((false)) 0459 #define CATCH_CATCH_ANON(type) if ((false)) 0460 #else 0461 #define CATCH_TRY try 0462 #define CATCH_CATCH_ALL catch (...) 0463 #define CATCH_CATCH_ANON(type) catch (type) 0464 #endif 0465 0466 #if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) 0467 #define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 0468 #endif 0469 0470 // end catch_compiler_capabilities.h 0471 #define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line 0472 #define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) 0473 #ifdef CATCH_CONFIG_COUNTER 0474 # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) 0475 #else 0476 # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) 0477 #endif 0478 0479 #include <iosfwd> 0480 #include <string> 0481 #include <cstdint> 0482 0483 // We need a dummy global operator<< so we can bring it into Catch namespace later 0484 struct Catch_global_namespace_dummy {}; 0485 std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy); 0486 0487 namespace Catch { 0488 0489 struct CaseSensitive { enum Choice { 0490 Yes, 0491 No 0492 }; }; 0493 0494 class NonCopyable { 0495 NonCopyable( NonCopyable const& ) = delete; 0496 NonCopyable( NonCopyable && ) = delete; 0497 NonCopyable& operator = ( NonCopyable const& ) = delete; 0498 NonCopyable& operator = ( NonCopyable && ) = delete; 0499 0500 protected: 0501 NonCopyable(); 0502 virtual ~NonCopyable(); 0503 }; 0504 0505 struct SourceLineInfo { 0506 0507 SourceLineInfo() = delete; 0508 SourceLineInfo( char const* _file, std::size_t _line ) noexcept 0509 : file( _file ), 0510 line( _line ) 0511 {} 0512 0513 SourceLineInfo( SourceLineInfo const& other ) = default; 0514 SourceLineInfo& operator = ( SourceLineInfo const& ) = default; 0515 SourceLineInfo( SourceLineInfo&& ) noexcept = default; 0516 SourceLineInfo& operator = ( SourceLineInfo&& ) noexcept = default; 0517 0518 bool empty() const noexcept { return file[0] == '\0'; } 0519 bool operator == ( SourceLineInfo const& other ) const noexcept; 0520 bool operator < ( SourceLineInfo const& other ) const noexcept; 0521 0522 char const* file; 0523 std::size_t line; 0524 }; 0525 0526 std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); 0527 0528 // Bring in operator<< from global namespace into Catch namespace 0529 // This is necessary because the overload of operator<< above makes 0530 // lookup stop at namespace Catch 0531 using ::operator<<; 0532 0533 // Use this in variadic streaming macros to allow 0534 // >> +StreamEndStop 0535 // as well as 0536 // >> stuff +StreamEndStop 0537 struct StreamEndStop { 0538 std::string operator+() const; 0539 }; 0540 template<typename T> 0541 T const& operator + ( T const& value, StreamEndStop ) { 0542 return value; 0543 } 0544 } 0545 0546 #define CATCH_INTERNAL_LINEINFO \ 0547 ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) ) 0548 0549 // end catch_common.h 0550 namespace Catch { 0551 0552 struct RegistrarForTagAliases { 0553 RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); 0554 }; 0555 0556 } // end namespace Catch 0557 0558 #define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \ 0559 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 0560 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 0561 namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \ 0562 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 0563 0564 // end catch_tag_alias_autoregistrar.h 0565 // start catch_test_registry.h 0566 0567 // start catch_interfaces_testcase.h 0568 0569 #include <vector> 0570 0571 namespace Catch { 0572 0573 class TestSpec; 0574 0575 struct ITestInvoker { 0576 virtual void invoke () const = 0; 0577 virtual ~ITestInvoker(); 0578 }; 0579 0580 class TestCase; 0581 struct IConfig; 0582 0583 struct ITestCaseRegistry { 0584 virtual ~ITestCaseRegistry(); 0585 virtual std::vector<TestCase> const& getAllTests() const = 0; 0586 virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const = 0; 0587 }; 0588 0589 bool isThrowSafe( TestCase const& testCase, IConfig const& config ); 0590 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); 0591 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ); 0592 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ); 0593 0594 } 0595 0596 // end catch_interfaces_testcase.h 0597 // start catch_stringref.h 0598 0599 #include <cstddef> 0600 #include <string> 0601 #include <iosfwd> 0602 #include <cassert> 0603 0604 namespace Catch { 0605 0606 /// A non-owning string class (similar to the forthcoming std::string_view) 0607 /// Note that, because a StringRef may be a substring of another string, 0608 /// it may not be null terminated. 0609 class StringRef { 0610 public: 0611 using size_type = std::size_t; 0612 using const_iterator = const char*; 0613 0614 private: 0615 static constexpr char const* const s_empty = ""; 0616 0617 char const* m_start = s_empty; 0618 size_type m_size = 0; 0619 0620 public: // construction 0621 constexpr StringRef() noexcept = default; 0622 0623 StringRef( char const* rawChars ) noexcept; 0624 0625 constexpr StringRef( char const* rawChars, size_type size ) noexcept 0626 : m_start( rawChars ), 0627 m_size( size ) 0628 {} 0629 0630 StringRef( std::string const& stdString ) noexcept 0631 : m_start( stdString.c_str() ), 0632 m_size( stdString.size() ) 0633 {} 0634 0635 explicit operator std::string() const { 0636 return std::string(m_start, m_size); 0637 } 0638 0639 public: // operators 0640 auto operator == ( StringRef const& other ) const noexcept -> bool; 0641 auto operator != (StringRef const& other) const noexcept -> bool { 0642 return !(*this == other); 0643 } 0644 0645 auto operator[] ( size_type index ) const noexcept -> char { 0646 assert(index < m_size); 0647 return m_start[index]; 0648 } 0649 0650 public: // named queries 0651 constexpr auto empty() const noexcept -> bool { 0652 return m_size == 0; 0653 } 0654 constexpr auto size() const noexcept -> size_type { 0655 return m_size; 0656 } 0657 0658 // Returns the current start pointer. If the StringRef is not 0659 // null-terminated, throws std::domain_exception 0660 auto c_str() const -> char const*; 0661 0662 public: // substrings and searches 0663 // Returns a substring of [start, start + length). 0664 // If start + length > size(), then the substring is [start, size()). 0665 // If start > size(), then the substring is empty. 0666 auto substr( size_type start, size_type length ) const noexcept -> StringRef; 0667 0668 // Returns the current start pointer. May not be null-terminated. 0669 auto data() const noexcept -> char const*; 0670 0671 constexpr auto isNullTerminated() const noexcept -> bool { 0672 return m_start[m_size] == '\0'; 0673 } 0674 0675 public: // iterators 0676 constexpr const_iterator begin() const { return m_start; } 0677 constexpr const_iterator end() const { return m_start + m_size; } 0678 }; 0679 0680 auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&; 0681 auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&; 0682 0683 constexpr auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef { 0684 return StringRef( rawChars, size ); 0685 } 0686 } // namespace Catch 0687 0688 constexpr auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef { 0689 return Catch::StringRef( rawChars, size ); 0690 } 0691 0692 // end catch_stringref.h 0693 // start catch_preprocessor.hpp 0694 0695 0696 #define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__ 0697 #define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__))) 0698 #define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__))) 0699 #define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__))) 0700 #define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__))) 0701 #define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__))) 0702 0703 #ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 0704 #define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__ 0705 // MSVC needs more evaluations 0706 #define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__))) 0707 #define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__)) 0708 #else 0709 #define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL5(__VA_ARGS__) 0710 #endif 0711 0712 #define CATCH_REC_END(...) 0713 #define CATCH_REC_OUT 0714 0715 #define CATCH_EMPTY() 0716 #define CATCH_DEFER(id) id CATCH_EMPTY() 0717 0718 #define CATCH_REC_GET_END2() 0, CATCH_REC_END 0719 #define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2 0720 #define CATCH_REC_GET_END(...) CATCH_REC_GET_END1 0721 #define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT 0722 #define CATCH_REC_NEXT1(test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0) 0723 #define CATCH_REC_NEXT(test, next) CATCH_REC_NEXT1(CATCH_REC_GET_END test, next) 0724 0725 #define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) 0726 #define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ ) 0727 #define CATCH_REC_LIST2(f, x, peek, ...) f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) 0728 0729 #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__ ) 0730 #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__ ) 0731 #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__ ) 0732 0733 // Applies the function macro `f` to each of the remaining parameters, inserts commas between the results, 0734 // and passes userdata as the first parameter to each invocation, 0735 // e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c) 0736 #define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) 0737 0738 #define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) 0739 0740 #define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param) 0741 #define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__ 0742 #define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__ 0743 #define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF 0744 #define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__) 0745 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 0746 #define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__ 0747 #define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) 0748 #else 0749 // MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF 0750 #define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__) 0751 #define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__ 0752 #define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1) 0753 #endif 0754 0755 #define INTERNAL_CATCH_MAKE_NAMESPACE2(...) ns_##__VA_ARGS__ 0756 #define INTERNAL_CATCH_MAKE_NAMESPACE(name) INTERNAL_CATCH_MAKE_NAMESPACE2(name) 0757 0758 #define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__) 0759 0760 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 0761 #define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS_GEN(__VA_ARGS__)>()) 0762 #define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)) 0763 #else 0764 #define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) INTERNAL_CATCH_EXPAND_VARGS(decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS_GEN(__VA_ARGS__)>())) 0765 #define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))) 0766 #endif 0767 0768 #define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(...)\ 0769 CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,__VA_ARGS__) 0770 0771 #define INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_0) INTERNAL_CATCH_REMOVE_PARENS(_0) 0772 #define INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_0, _1) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_1) 0773 #define INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_0, _1, _2) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_1, _2) 0774 #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) 0775 #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) 0776 #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) 0777 #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) 0778 #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) 0779 #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) 0780 #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) 0781 #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) 0782 0783 #define INTERNAL_CATCH_VA_NARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N 0784 0785 #define INTERNAL_CATCH_TYPE_GEN\ 0786 template<typename...> struct TypeList {};\ 0787 template<typename...Ts>\ 0788 constexpr auto get_wrapper() noexcept -> TypeList<Ts...> { return {}; }\ 0789 template<template<typename...> class...> struct TemplateTypeList{};\ 0790 template<template<typename...> class...Cs>\ 0791 constexpr auto get_wrapper() noexcept -> TemplateTypeList<Cs...> { return {}; }\ 0792 template<typename...>\ 0793 struct append;\ 0794 template<typename...>\ 0795 struct rewrap;\ 0796 template<template<typename...> class, typename...>\ 0797 struct create;\ 0798 template<template<typename...> class, typename>\ 0799 struct convert;\ 0800 \ 0801 template<typename T> \ 0802 struct append<T> { using type = T; };\ 0803 template< template<typename...> class L1, typename...E1, template<typename...> class L2, typename...E2, typename...Rest>\ 0804 struct append<L1<E1...>, L2<E2...>, Rest...> { using type = typename append<L1<E1...,E2...>, Rest...>::type; };\ 0805 template< template<typename...> class L1, typename...E1, typename...Rest>\ 0806 struct append<L1<E1...>, TypeList<mpl_::na>, Rest...> { using type = L1<E1...>; };\ 0807 \ 0808 template< template<typename...> class Container, template<typename...> class List, typename...elems>\ 0809 struct rewrap<TemplateTypeList<Container>, List<elems...>> { using type = TypeList<Container<elems...>>; };\ 0810 template< template<typename...> class Container, template<typename...> class List, class...Elems, typename...Elements>\ 0811 struct rewrap<TemplateTypeList<Container>, List<Elems...>, Elements...> { using type = typename append<TypeList<Container<Elems...>>, typename rewrap<TemplateTypeList<Container>, Elements...>::type>::type; };\ 0812 \ 0813 template<template <typename...> class Final, template< typename...> class...Containers, typename...Types>\ 0814 struct create<Final, TemplateTypeList<Containers...>, TypeList<Types...>> { using type = typename append<Final<>, typename rewrap<TemplateTypeList<Containers>, Types...>::type...>::type; };\ 0815 template<template <typename...> class Final, template <typename...> class List, typename...Ts>\ 0816 struct convert<Final, List<Ts...>> { using type = typename append<Final<>,TypeList<Ts>...>::type; }; 0817 0818 #define INTERNAL_CATCH_NTTP_1(signature, ...)\ 0819 template<INTERNAL_CATCH_REMOVE_PARENS(signature)> struct Nttp{};\ 0820 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 0821 constexpr auto get_wrapper() noexcept -> Nttp<__VA_ARGS__> { return {}; } \ 0822 template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...> struct NttpTemplateTypeList{};\ 0823 template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...Cs>\ 0824 constexpr auto get_wrapper() noexcept -> NttpTemplateTypeList<Cs...> { return {}; } \ 0825 \ 0826 template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 0827 struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>> { using type = TypeList<Container<__VA_ARGS__>>; };\ 0828 template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature), typename...Elements>\ 0829 struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>, Elements...> { using type = typename append<TypeList<Container<__VA_ARGS__>>, typename rewrap<NttpTemplateTypeList<Container>, Elements...>::type>::type; };\ 0830 template<template <typename...> class Final, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...Containers, typename...Types>\ 0831 struct create<Final, NttpTemplateTypeList<Containers...>, TypeList<Types...>> { using type = typename append<Final<>, typename rewrap<NttpTemplateTypeList<Containers>, Types...>::type...>::type; }; 0832 0833 #define INTERNAL_CATCH_DECLARE_SIG_TEST0(TestName) 0834 #define INTERNAL_CATCH_DECLARE_SIG_TEST1(TestName, signature)\ 0835 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 0836 static void TestName() 0837 #define INTERNAL_CATCH_DECLARE_SIG_TEST_X(TestName, signature, ...)\ 0838 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 0839 static void TestName() 0840 0841 #define INTERNAL_CATCH_DEFINE_SIG_TEST0(TestName) 0842 #define INTERNAL_CATCH_DEFINE_SIG_TEST1(TestName, signature)\ 0843 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 0844 static void TestName() 0845 #define INTERNAL_CATCH_DEFINE_SIG_TEST_X(TestName, signature,...)\ 0846 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 0847 static void TestName() 0848 0849 #define INTERNAL_CATCH_NTTP_REGISTER0(TestFunc, signature)\ 0850 template<typename Type>\ 0851 void reg_test(TypeList<Type>, Catch::NameAndTags nameAndTags)\ 0852 {\ 0853 Catch::AutoReg( Catch::makeTestInvoker(&TestFunc<Type>), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), nameAndTags);\ 0854 } 0855 0856 #define INTERNAL_CATCH_NTTP_REGISTER(TestFunc, signature, ...)\ 0857 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 0858 void reg_test(Nttp<__VA_ARGS__>, Catch::NameAndTags nameAndTags)\ 0859 {\ 0860 Catch::AutoReg( Catch::makeTestInvoker(&TestFunc<__VA_ARGS__>), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), nameAndTags);\ 0861 } 0862 0863 #define INTERNAL_CATCH_NTTP_REGISTER_METHOD0(TestName, signature, ...)\ 0864 template<typename Type>\ 0865 void reg_test(TypeList<Type>, Catch::StringRef className, Catch::NameAndTags nameAndTags)\ 0866 {\ 0867 Catch::AutoReg( Catch::makeTestInvoker(&TestName<Type>::test), CATCH_INTERNAL_LINEINFO, className, nameAndTags);\ 0868 } 0869 0870 #define INTERNAL_CATCH_NTTP_REGISTER_METHOD(TestName, signature, ...)\ 0871 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 0872 void reg_test(Nttp<__VA_ARGS__>, Catch::StringRef className, Catch::NameAndTags nameAndTags)\ 0873 {\ 0874 Catch::AutoReg( Catch::makeTestInvoker(&TestName<__VA_ARGS__>::test), CATCH_INTERNAL_LINEINFO, className, nameAndTags);\ 0875 } 0876 0877 #define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0(TestName, ClassName) 0878 #define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1(TestName, ClassName, signature)\ 0879 template<typename TestType> \ 0880 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName)<TestType> { \ 0881 void test();\ 0882 } 0883 0884 #define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X(TestName, ClassName, signature, ...)\ 0885 template<INTERNAL_CATCH_REMOVE_PARENS(signature)> \ 0886 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName)<__VA_ARGS__> { \ 0887 void test();\ 0888 } 0889 0890 #define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0(TestName) 0891 #define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1(TestName, signature)\ 0892 template<typename TestType> \ 0893 void INTERNAL_CATCH_MAKE_NAMESPACE(TestName)::TestName<TestType>::test() 0894 #define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X(TestName, signature, ...)\ 0895 template<INTERNAL_CATCH_REMOVE_PARENS(signature)> \ 0896 void INTERNAL_CATCH_MAKE_NAMESPACE(TestName)::TestName<__VA_ARGS__>::test() 0897 0898 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 0899 #define INTERNAL_CATCH_NTTP_0 0900 #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) 0901 #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__) 0902 #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__) 0903 #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__) 0904 #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__) 0905 #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__) 0906 #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__) 0907 #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__) 0908 #else 0909 #define INTERNAL_CATCH_NTTP_0(signature) 0910 #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__)) 0911 #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__)) 0912 #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__)) 0913 #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__)) 0914 #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__)) 0915 #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__)) 0916 #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__)) 0917 #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__)) 0918 #endif 0919 0920 // end catch_preprocessor.hpp 0921 // start catch_meta.hpp 0922 0923 0924 #include <type_traits> 0925 0926 namespace Catch { 0927 template<typename T> 0928 struct always_false : std::false_type {}; 0929 0930 template <typename> struct true_given : std::true_type {}; 0931 struct is_callable_tester { 0932 template <typename Fun, typename... Args> 0933 true_given<decltype(std::declval<Fun>()(std::declval<Args>()...))> static test(int); 0934 template <typename...> 0935 std::false_type static test(...); 0936 }; 0937 0938 template <typename T> 0939 struct is_callable; 0940 0941 template <typename Fun, typename... Args> 0942 struct is_callable<Fun(Args...)> : decltype(is_callable_tester::test<Fun, Args...>(0)) {}; 0943 0944 #if defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703 0945 // std::result_of is deprecated in C++17 and removed in C++20. Hence, it is 0946 // replaced with std::invoke_result here. 0947 template <typename Func, typename... U> 0948 using FunctionReturnType = std::remove_reference_t<std::remove_cv_t<std::invoke_result_t<Func, U...>>>; 0949 #else 0950 // Keep ::type here because we still support C++11 0951 template <typename Func, typename... U> 0952 using FunctionReturnType = typename std::remove_reference<typename std::remove_cv<typename std::result_of<Func(U...)>::type>::type>::type; 0953 #endif 0954 0955 } // namespace Catch 0956 0957 namespace mpl_{ 0958 struct na; 0959 } 0960 0961 // end catch_meta.hpp 0962 namespace Catch { 0963 0964 template<typename C> 0965 class TestInvokerAsMethod : public ITestInvoker { 0966 void (C::*m_testAsMethod)(); 0967 public: 0968 TestInvokerAsMethod( void (C::*testAsMethod)() ) noexcept : m_testAsMethod( testAsMethod ) {} 0969 0970 void invoke() const override { 0971 C obj; 0972 (obj.*m_testAsMethod)(); 0973 } 0974 }; 0975 0976 auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker*; 0977 0978 template<typename C> 0979 auto makeTestInvoker( void (C::*testAsMethod)() ) noexcept -> ITestInvoker* { 0980 return new(std::nothrow) TestInvokerAsMethod<C>( testAsMethod ); 0981 } 0982 0983 struct NameAndTags { 0984 NameAndTags( StringRef const& name_ = StringRef(), StringRef const& tags_ = StringRef() ) noexcept; 0985 StringRef name; 0986 StringRef tags; 0987 }; 0988 0989 struct AutoReg : NonCopyable { 0990 AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept; 0991 ~AutoReg(); 0992 }; 0993 0994 } // end namespace Catch 0995 0996 #if defined(CATCH_CONFIG_DISABLE) 0997 #define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \ 0998 static void TestName() 0999 #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \ 1000 namespace{ \ 1001 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \ 1002 void test(); \ 1003 }; \ 1004 } \ 1005 void TestName::test() 1006 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( TestName, TestFunc, Name, Tags, Signature, ... ) \ 1007 INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature)) 1008 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \ 1009 namespace{ \ 1010 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) { \ 1011 INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, INTERNAL_CATCH_REMOVE_PARENS(Signature));\ 1012 } \ 1013 } \ 1014 INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature)) 1015 1016 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1017 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \ 1018 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 #else 1020 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \ 1021 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__ ) ) 1022 #endif 1023 1024 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1025 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \ 1026 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 #else 1028 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \ 1029 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__ ) ) 1030 #endif 1031 1032 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1033 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \ 1034 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 #else 1036 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \ 1037 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__ ) ) 1038 #endif 1039 1040 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1041 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \ 1042 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 #else 1044 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \ 1045 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__ ) ) 1046 #endif 1047 #endif 1048 1049 /////////////////////////////////////////////////////////////////////////////// 1050 #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ 1051 static void TestName(); \ 1052 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1053 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1054 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \ 1055 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1056 static void TestName() 1057 #define INTERNAL_CATCH_TESTCASE( ... ) \ 1058 INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ ) 1059 1060 /////////////////////////////////////////////////////////////////////////////// 1061 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ 1062 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1063 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1064 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &QualifiedMethod ), CATCH_INTERNAL_LINEINFO, "&" #QualifiedMethod, Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \ 1065 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 1066 1067 /////////////////////////////////////////////////////////////////////////////// 1068 #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ 1069 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1070 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1071 namespace{ \ 1072 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \ 1073 void test(); \ 1074 }; \ 1075 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ 1076 } \ 1077 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1078 void TestName::test() 1079 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \ 1080 INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ ) 1081 1082 /////////////////////////////////////////////////////////////////////////////// 1083 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ 1084 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1085 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1086 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ 1087 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 1088 1089 /////////////////////////////////////////////////////////////////////////////// 1090 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_2(TestName, TestFunc, Name, Tags, Signature, ... )\ 1091 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1092 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1093 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ 1094 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 1095 INTERNAL_CATCH_DECLARE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature));\ 1096 namespace {\ 1097 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\ 1098 INTERNAL_CATCH_TYPE_GEN\ 1099 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\ 1100 INTERNAL_CATCH_NTTP_REG_GEN(TestFunc,INTERNAL_CATCH_REMOVE_PARENS(Signature))\ 1101 template<typename...Types> \ 1102 struct TestName{\ 1103 TestName(){\ 1104 int index = 0; \ 1105 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\ 1106 using expander = int[];\ 1107 (void)expander{(reg_test(Types{}, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };/* NOLINT */ \ 1108 }\ 1109 };\ 1110 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ 1111 TestName<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(__VA_ARGS__)>();\ 1112 return 0;\ 1113 }();\ 1114 }\ 1115 }\ 1116 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1117 INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc,INTERNAL_CATCH_REMOVE_PARENS(Signature)) 1118 1119 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1120 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \ 1121 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 #else 1123 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \ 1124 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__ ) ) 1125 #endif 1126 1127 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1128 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \ 1129 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 #else 1131 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \ 1132 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__ ) ) 1133 #endif 1134 1135 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(TestName, TestFuncName, Name, Tags, Signature, TmplTypes, TypesList) \ 1136 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1137 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1138 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ 1139 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 1140 template<typename TestType> static void TestFuncName(); \ 1141 namespace {\ 1142 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) { \ 1143 INTERNAL_CATCH_TYPE_GEN \ 1144 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature)) \ 1145 template<typename... Types> \ 1146 struct TestName { \ 1147 void reg_tests() { \ 1148 int index = 0; \ 1149 using expander = int[]; \ 1150 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\ 1151 constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\ 1152 constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\ 1153 (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 */\ 1154 } \ 1155 }; \ 1156 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \ 1157 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; \ 1158 TestInit t; \ 1159 t.reg_tests(); \ 1160 return 0; \ 1161 }(); \ 1162 } \ 1163 } \ 1164 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1165 template<typename TestType> \ 1166 static void TestFuncName() 1167 1168 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1169 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\ 1170 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 #else 1172 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\ 1173 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__ ) ) 1174 #endif 1175 1176 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1177 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\ 1178 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 #else 1180 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\ 1181 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__ ) ) 1182 #endif 1183 1184 #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2(TestName, TestFunc, Name, Tags, TmplList)\ 1185 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1186 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1187 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 1188 template<typename TestType> static void TestFunc(); \ 1189 namespace {\ 1190 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\ 1191 INTERNAL_CATCH_TYPE_GEN\ 1192 template<typename... Types> \ 1193 struct TestName { \ 1194 void reg_tests() { \ 1195 int index = 0; \ 1196 using expander = int[]; \ 1197 (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 */\ 1198 } \ 1199 };\ 1200 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \ 1201 using TestInit = typename convert<TestName, TmplList>::type; \ 1202 TestInit t; \ 1203 t.reg_tests(); \ 1204 return 0; \ 1205 }(); \ 1206 }}\ 1207 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1208 template<typename TestType> \ 1209 static void TestFunc() 1210 1211 #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(Name, Tags, TmplList) \ 1212 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 ) 1213 1214 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \ 1215 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1216 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1217 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ 1218 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 1219 namespace {\ 1220 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \ 1221 INTERNAL_CATCH_TYPE_GEN\ 1222 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\ 1223 INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, INTERNAL_CATCH_REMOVE_PARENS(Signature));\ 1224 INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))\ 1225 template<typename...Types> \ 1226 struct TestNameClass{\ 1227 TestNameClass(){\ 1228 int index = 0; \ 1229 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\ 1230 using expander = int[];\ 1231 (void)expander{(reg_test(Types{}, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };/* NOLINT */ \ 1232 }\ 1233 };\ 1234 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ 1235 TestNameClass<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(__VA_ARGS__)>();\ 1236 return 0;\ 1237 }();\ 1238 }\ 1239 }\ 1240 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1241 INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature)) 1242 1243 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1244 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \ 1245 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 #else 1247 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \ 1248 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__ ) ) 1249 #endif 1250 1251 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1252 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \ 1253 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 #else 1255 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \ 1256 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__ ) ) 1257 #endif 1258 1259 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2(TestNameClass, TestName, ClassName, Name, Tags, Signature, TmplTypes, TypesList)\ 1260 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1261 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1262 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ 1263 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 1264 template<typename TestType> \ 1265 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \ 1266 void test();\ 1267 };\ 1268 namespace {\ 1269 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestNameClass) {\ 1270 INTERNAL_CATCH_TYPE_GEN \ 1271 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\ 1272 template<typename...Types>\ 1273 struct TestNameClass{\ 1274 void reg_tests(){\ 1275 int index = 0;\ 1276 using expander = int[];\ 1277 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\ 1278 constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\ 1279 constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\ 1280 (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 */ \ 1281 }\ 1282 };\ 1283 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ 1284 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;\ 1285 TestInit t;\ 1286 t.reg_tests();\ 1287 return 0;\ 1288 }(); \ 1289 }\ 1290 }\ 1291 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1292 template<typename TestType> \ 1293 void TestName<TestType>::test() 1294 1295 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1296 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\ 1297 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 #else 1299 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\ 1300 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__ ) ) 1301 #endif 1302 1303 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1304 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\ 1305 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 #else 1307 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\ 1308 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__ ) ) 1309 #endif 1310 1311 #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, TmplList) \ 1312 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1313 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1314 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 1315 template<typename TestType> \ 1316 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \ 1317 void test();\ 1318 };\ 1319 namespace {\ 1320 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \ 1321 INTERNAL_CATCH_TYPE_GEN\ 1322 template<typename...Types>\ 1323 struct TestNameClass{\ 1324 void reg_tests(){\ 1325 int index = 0;\ 1326 using expander = int[];\ 1327 (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 */ \ 1328 }\ 1329 };\ 1330 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ 1331 using TestInit = typename convert<TestNameClass, TmplList>::type;\ 1332 TestInit t;\ 1333 t.reg_tests();\ 1334 return 0;\ 1335 }(); \ 1336 }}\ 1337 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1338 template<typename TestType> \ 1339 void TestName<TestType>::test() 1340 1341 #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD(ClassName, Name, Tags, TmplList) \ 1342 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 ) 1343 1344 // end catch_test_registry.h 1345 // start catch_capture.hpp 1346 1347 // start catch_assertionhandler.h 1348 1349 // start catch_assertioninfo.h 1350 1351 // start catch_result_type.h 1352 1353 namespace Catch { 1354 1355 // ResultWas::OfType enum 1356 struct ResultWas { enum OfType { 1357 Unknown = -1, 1358 Ok = 0, 1359 Info = 1, 1360 Warning = 2, 1361 1362 FailureBit = 0x10, 1363 1364 ExpressionFailed = FailureBit | 1, 1365 ExplicitFailure = FailureBit | 2, 1366 1367 Exception = 0x100 | FailureBit, 1368 1369 ThrewException = Exception | 1, 1370 DidntThrowException = Exception | 2, 1371 1372 FatalErrorCondition = 0x200 | FailureBit 1373 1374 }; }; 1375 1376 bool isOk( ResultWas::OfType resultType ); 1377 bool isJustInfo( int flags ); 1378 1379 // ResultDisposition::Flags enum 1380 struct ResultDisposition { enum Flags { 1381 Normal = 0x01, 1382 1383 ContinueOnFailure = 0x02, // Failures fail test, but execution continues 1384 FalseTest = 0x04, // Prefix expression with ! 1385 SuppressFail = 0x08 // Failures are reported but do not fail the test 1386 }; }; 1387 1388 ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ); 1389 1390 bool shouldContinueOnFailure( int flags ); 1391 inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; } 1392 bool shouldSuppressFailure( int flags ); 1393 1394 } // end namespace Catch 1395 1396 // end catch_result_type.h 1397 namespace Catch { 1398 1399 struct AssertionInfo 1400 { 1401 StringRef macroName; 1402 SourceLineInfo lineInfo; 1403 StringRef capturedExpression; 1404 ResultDisposition::Flags resultDisposition; 1405 1406 // We want to delete this constructor but a compiler bug in 4.8 means 1407 // the struct is then treated as non-aggregate 1408 //AssertionInfo() = delete; 1409 }; 1410 1411 } // end namespace Catch 1412 1413 // end catch_assertioninfo.h 1414 // start catch_decomposer.h 1415 1416 // start catch_tostring.h 1417 1418 #include <vector> 1419 #include <cstddef> 1420 #include <type_traits> 1421 #include <string> 1422 // start catch_stream.h 1423 1424 #include <iosfwd> 1425 #include <cstddef> 1426 #include <ostream> 1427 1428 namespace Catch { 1429 1430 std::ostream& cout(); 1431 std::ostream& cerr(); 1432 std::ostream& clog(); 1433 1434 class StringRef; 1435 1436 struct IStream { 1437 virtual ~IStream(); 1438 virtual std::ostream& stream() const = 0; 1439 }; 1440 1441 auto makeStream( StringRef const &filename ) -> IStream const*; 1442 1443 class ReusableStringStream : NonCopyable { 1444 std::size_t m_index; 1445 std::ostream* m_oss; 1446 public: 1447 ReusableStringStream(); 1448 ~ReusableStringStream(); 1449 1450 auto str() const -> std::string; 1451 1452 template<typename T> 1453 auto operator << ( T const& value ) -> ReusableStringStream& { 1454 *m_oss << value; 1455 return *this; 1456 } 1457 auto get() -> std::ostream& { return *m_oss; } 1458 }; 1459 } 1460 1461 // end catch_stream.h 1462 // start catch_interfaces_enum_values_registry.h 1463 1464 #include <vector> 1465 1466 namespace Catch { 1467 1468 namespace Detail { 1469 struct EnumInfo { 1470 StringRef m_name; 1471 std::vector<std::pair<int, StringRef>> m_values; 1472 1473 ~EnumInfo(); 1474 1475 StringRef lookup( int value ) const; 1476 }; 1477 } // namespace Detail 1478 1479 struct IMutableEnumValuesRegistry { 1480 virtual ~IMutableEnumValuesRegistry(); 1481 1482 virtual Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::vector<int> const& values ) = 0; 1483 1484 template<typename E> 1485 Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::initializer_list<E> values ) { 1486 static_assert(sizeof(int) >= sizeof(E), "Cannot serialize enum to int"); 1487 std::vector<int> intValues; 1488 intValues.reserve( values.size() ); 1489 for( auto enumValue : values ) 1490 intValues.push_back( static_cast<int>( enumValue ) ); 1491 return registerEnum( enumName, allEnums, intValues ); 1492 } 1493 }; 1494 1495 } // Catch 1496 1497 // end catch_interfaces_enum_values_registry.h 1498 1499 #ifdef CATCH_CONFIG_CPP17_STRING_VIEW 1500 #include <string_view> 1501 #endif 1502 1503 #ifdef __OBJC__ 1504 // start catch_objc_arc.hpp 1505 1506 #import <Foundation/Foundation.h> 1507 1508 #ifdef __has_feature 1509 #define CATCH_ARC_ENABLED __has_feature(objc_arc) 1510 #else 1511 #define CATCH_ARC_ENABLED 0 1512 #endif 1513 1514 void arcSafeRelease( NSObject* obj ); 1515 id performOptionalSelector( id obj, SEL sel ); 1516 1517 #if !CATCH_ARC_ENABLED 1518 inline void arcSafeRelease( NSObject* obj ) { 1519 [obj release]; 1520 } 1521 inline id performOptionalSelector( id obj, SEL sel ) { 1522 if( [obj respondsToSelector: sel] ) 1523 return [obj performSelector: sel]; 1524 return nil; 1525 } 1526 #define CATCH_UNSAFE_UNRETAINED 1527 #define CATCH_ARC_STRONG 1528 #else 1529 inline void arcSafeRelease( NSObject* ){} 1530 inline id performOptionalSelector( id obj, SEL sel ) { 1531 #ifdef __clang__ 1532 #pragma clang diagnostic push 1533 #pragma clang diagnostic ignored "-Warc-performSelector-leaks" 1534 #endif 1535 if( [obj respondsToSelector: sel] ) 1536 return [obj performSelector: sel]; 1537 #ifdef __clang__ 1538 #pragma clang diagnostic pop 1539 #endif 1540 return nil; 1541 } 1542 #define CATCH_UNSAFE_UNRETAINED __unsafe_unretained 1543 #define CATCH_ARC_STRONG __strong 1544 #endif 1545 1546 // end catch_objc_arc.hpp 1547 #endif 1548 1549 #ifdef _MSC_VER 1550 #pragma warning(push) 1551 #pragma warning(disable:4180) // We attempt to stream a function (address) by const&, which MSVC complains about but is harmless 1552 #endif 1553 1554 namespace Catch { 1555 namespace Detail { 1556 1557 extern const std::string unprintableString; 1558 1559 std::string rawMemoryToString( const void *object, std::size_t size ); 1560 1561 template<typename T> 1562 std::string rawMemoryToString( const T& object ) { 1563 return rawMemoryToString( &object, sizeof(object) ); 1564 } 1565 1566 template<typename T> 1567 class IsStreamInsertable { 1568 template<typename Stream, typename U> 1569 static auto test(int) 1570 -> decltype(std::declval<Stream&>() << std::declval<U>(), std::true_type()); 1571 1572 template<typename, typename> 1573 static auto test(...)->std::false_type; 1574 1575 public: 1576 static const bool value = decltype(test<std::ostream, const T&>(0))::value; 1577 }; 1578 1579 template<typename E> 1580 std::string convertUnknownEnumToString( E e ); 1581 1582 template<typename T> 1583 typename std::enable_if< 1584 !std::is_enum<T>::value && !std::is_base_of<std::exception, T>::value, 1585 std::string>::type convertUnstreamable( T const& ) { 1586 return Detail::unprintableString; 1587 } 1588 template<typename T> 1589 typename std::enable_if< 1590 !std::is_enum<T>::value && std::is_base_of<std::exception, T>::value, 1591 std::string>::type convertUnstreamable(T const& ex) { 1592 return ex.what(); 1593 } 1594 1595 template<typename T> 1596 typename std::enable_if< 1597 std::is_enum<T>::value 1598 , std::string>::type convertUnstreamable( T const& value ) { 1599 return convertUnknownEnumToString( value ); 1600 } 1601 1602 #if defined(_MANAGED) 1603 //! Convert a CLR string to a utf8 std::string 1604 template<typename T> 1605 std::string clrReferenceToString( T^ ref ) { 1606 if (ref == nullptr) 1607 return std::string("null"); 1608 auto bytes = System::Text::Encoding::UTF8->GetBytes(ref->ToString()); 1609 cli::pin_ptr<System::Byte> p = &bytes[0]; 1610 return std::string(reinterpret_cast<char const *>(p), bytes->Length); 1611 } 1612 #endif 1613 1614 } // namespace Detail 1615 1616 // If we decide for C++14, change these to enable_if_ts 1617 template <typename T, typename = void> 1618 struct StringMaker { 1619 template <typename Fake = T> 1620 static 1621 typename std::enable_if<::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type 1622 convert(const Fake& value) { 1623 ReusableStringStream rss; 1624 // NB: call using the function-like syntax to avoid ambiguity with 1625 // user-defined templated operator<< under clang. 1626 rss.operator<<(value); 1627 return rss.str(); 1628 } 1629 1630 template <typename Fake = T> 1631 static 1632 typename std::enable_if<!::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type 1633 convert( const Fake& value ) { 1634 #if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER) 1635 return Detail::convertUnstreamable(value); 1636 #else 1637 return CATCH_CONFIG_FALLBACK_STRINGIFIER(value); 1638 #endif 1639 } 1640 }; 1641 1642 namespace Detail { 1643 1644 // This function dispatches all stringification requests inside of Catch. 1645 // Should be preferably called fully qualified, like ::Catch::Detail::stringify 1646 template <typename T> 1647 std::string stringify(const T& e) { 1648 return ::Catch::StringMaker<typename std::remove_cv<typename std::remove_reference<T>::type>::type>::convert(e); 1649 } 1650 1651 template<typename E> 1652 std::string convertUnknownEnumToString( E e ) { 1653 return ::Catch::Detail::stringify(static_cast<typename std::underlying_type<E>::type>(e)); 1654 } 1655 1656 #if defined(_MANAGED) 1657 template <typename T> 1658 std::string stringify( T^ e ) { 1659 return ::Catch::StringMaker<T^>::convert(e); 1660 } 1661 #endif 1662 1663 } // namespace Detail 1664 1665 // Some predefined specializations 1666 1667 template<> 1668 struct StringMaker<std::string> { 1669 static std::string convert(const std::string& str); 1670 }; 1671 1672 #ifdef CATCH_CONFIG_CPP17_STRING_VIEW 1673 template<> 1674 struct StringMaker<std::string_view> { 1675 static std::string convert(std::string_view str); 1676 }; 1677 #endif 1678 1679 template<> 1680 struct StringMaker<char const *> { 1681 static std::string convert(char const * str); 1682 }; 1683 template<> 1684 struct StringMaker<char *> { 1685 static std::string convert(char * str); 1686 }; 1687 1688 #ifdef CATCH_CONFIG_WCHAR 1689 template<> 1690 struct StringMaker<std::wstring> { 1691 static std::string convert(const std::wstring& wstr); 1692 }; 1693 1694 # ifdef CATCH_CONFIG_CPP17_STRING_VIEW 1695 template<> 1696 struct StringMaker<std::wstring_view> { 1697 static std::string convert(std::wstring_view str); 1698 }; 1699 # endif 1700 1701 template<> 1702 struct StringMaker<wchar_t const *> { 1703 static std::string convert(wchar_t const * str); 1704 }; 1705 template<> 1706 struct StringMaker<wchar_t *> { 1707 static std::string convert(wchar_t * str); 1708 }; 1709 #endif 1710 1711 // TBD: Should we use `strnlen` to ensure that we don't go out of the buffer, 1712 // while keeping string semantics? 1713 template<int SZ> 1714 struct StringMaker<char[SZ]> { 1715 static std::string convert(char const* str) { 1716 return ::Catch::Detail::stringify(std::string{ str }); 1717 } 1718 }; 1719 template<int SZ> 1720 struct StringMaker<signed char[SZ]> { 1721 static std::string convert(signed char const* str) { 1722 return ::Catch::Detail::stringify(std::string{ reinterpret_cast<char const *>(str) }); 1723 } 1724 }; 1725 template<int SZ> 1726 struct StringMaker<unsigned char[SZ]> { 1727 static std::string convert(unsigned char const* str) { 1728 return ::Catch::Detail::stringify(std::string{ reinterpret_cast<char const *>(str) }); 1729 } 1730 }; 1731 1732 #if defined(CATCH_CONFIG_CPP17_BYTE) 1733 template<> 1734 struct StringMaker<std::byte> { 1735 static std::string convert(std::byte value); 1736 }; 1737 #endif // defined(CATCH_CONFIG_CPP17_BYTE) 1738 template<> 1739 struct StringMaker<int> { 1740 static std::string convert(int value); 1741 }; 1742 template<> 1743 struct StringMaker<long> { 1744 static std::string convert(long value); 1745 }; 1746 template<> 1747 struct StringMaker<long long> { 1748 static std::string convert(long long value); 1749 }; 1750 template<> 1751 struct StringMaker<unsigned int> { 1752 static std::string convert(unsigned int value); 1753 }; 1754 template<> 1755 struct StringMaker<unsigned long> { 1756 static std::string convert(unsigned long value); 1757 }; 1758 template<> 1759 struct StringMaker<unsigned long long> { 1760 static std::string convert(unsigned long long value); 1761 }; 1762 1763 template<> 1764 struct StringMaker<bool> { 1765 static std::string convert(bool b); 1766 }; 1767 1768 template<> 1769 struct StringMaker<char> { 1770 static std::string convert(char c); 1771 }; 1772 template<> 1773 struct StringMaker<signed char> { 1774 static std::string convert(signed char c); 1775 }; 1776 template<> 1777 struct StringMaker<unsigned char> { 1778 static std::string convert(unsigned char c); 1779 }; 1780 1781 template<> 1782 struct StringMaker<std::nullptr_t> { 1783 static std::string convert(std::nullptr_t); 1784 }; 1785 1786 template<> 1787 struct StringMaker<float> { 1788 static std::string convert(float value); 1789 static int precision; 1790 }; 1791 1792 template<> 1793 struct StringMaker<double> { 1794 static std::string convert(double value); 1795 static int precision; 1796 }; 1797 1798 template <typename T> 1799 struct StringMaker<T*> { 1800 template <typename U> 1801 static std::string convert(U* p) { 1802 if (p) { 1803 return ::Catch::Detail::rawMemoryToString(p); 1804 } else { 1805 return "nullptr"; 1806 } 1807 } 1808 }; 1809 1810 template <typename R, typename C> 1811 struct StringMaker<R C::*> { 1812 static std::string convert(R C::* p) { 1813 if (p) { 1814 return ::Catch::Detail::rawMemoryToString(p); 1815 } else { 1816 return "nullptr"; 1817 } 1818 } 1819 }; 1820 1821 #if defined(_MANAGED) 1822 template <typename T> 1823 struct StringMaker<T^> { 1824 static std::string convert( T^ ref ) { 1825 return ::Catch::Detail::clrReferenceToString(ref); 1826 } 1827 }; 1828 #endif 1829 1830 namespace Detail { 1831 template<typename InputIterator, typename Sentinel = InputIterator> 1832 std::string rangeToString(InputIterator first, Sentinel last) { 1833 ReusableStringStream rss; 1834 rss << "{ "; 1835 if (first != last) { 1836 rss << ::Catch::Detail::stringify(*first); 1837 for (++first; first != last; ++first) 1838 rss << ", " << ::Catch::Detail::stringify(*first); 1839 } 1840 rss << " }"; 1841 return rss.str(); 1842 } 1843 } 1844 1845 #ifdef __OBJC__ 1846 template<> 1847 struct StringMaker<NSString*> { 1848 static std::string convert(NSString * nsstring) { 1849 if (!nsstring) 1850 return "nil"; 1851 return std::string("@") + [nsstring UTF8String]; 1852 } 1853 }; 1854 template<> 1855 struct StringMaker<NSObject*> { 1856 static std::string convert(NSObject* nsObject) { 1857 return ::Catch::Detail::stringify([nsObject description]); 1858 } 1859 1860 }; 1861 namespace Detail { 1862 inline std::string stringify( NSString* nsstring ) { 1863 return StringMaker<NSString*>::convert( nsstring ); 1864 } 1865 1866 } // namespace Detail 1867 #endif // __OBJC__ 1868 1869 } // namespace Catch 1870 1871 ////////////////////////////////////////////////////// 1872 // Separate std-lib types stringification, so it can be selectively enabled 1873 // This means that we do not bring in 1874 1875 #if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS) 1876 # define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER 1877 # define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER 1878 # define CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER 1879 # define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER 1880 # define CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER 1881 #endif 1882 1883 // Separate std::pair specialization 1884 #if defined(CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER) 1885 #include <utility> 1886 namespace Catch { 1887 template<typename T1, typename T2> 1888 struct StringMaker<std::pair<T1, T2> > { 1889 static std::string convert(const std::pair<T1, T2>& pair) { 1890 ReusableStringStream rss; 1891 rss << "{ " 1892 << ::Catch::Detail::stringify(pair.first) 1893 << ", " 1894 << ::Catch::Detail::stringify(pair.second) 1895 << " }"; 1896 return rss.str(); 1897 } 1898 }; 1899 } 1900 #endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER 1901 1902 #if defined(CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_OPTIONAL) 1903 #include <optional> 1904 namespace Catch { 1905 template<typename T> 1906 struct StringMaker<std::optional<T> > { 1907 static std::string convert(const std::optional<T>& optional) { 1908 ReusableStringStream rss; 1909 if (optional.has_value()) { 1910 rss << ::Catch::Detail::stringify(*optional); 1911 } else { 1912 rss << "{ }"; 1913 } 1914 return rss.str(); 1915 } 1916 }; 1917 } 1918 #endif // CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER 1919 1920 // Separate std::tuple specialization 1921 #if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER) 1922 #include <tuple> 1923 namespace Catch { 1924 namespace Detail { 1925 template< 1926 typename Tuple, 1927 std::size_t N = 0, 1928 bool = (N < std::tuple_size<Tuple>::value) 1929 > 1930 struct TupleElementPrinter { 1931 static void print(const Tuple& tuple, std::ostream& os) { 1932 os << (N ? ", " : " ") 1933 << ::Catch::Detail::stringify(std::get<N>(tuple)); 1934 TupleElementPrinter<Tuple, N + 1>::print(tuple, os); 1935 } 1936 }; 1937 1938 template< 1939 typename Tuple, 1940 std::size_t N 1941 > 1942 struct TupleElementPrinter<Tuple, N, false> { 1943 static void print(const Tuple&, std::ostream&) {} 1944 }; 1945 1946 } 1947 1948 template<typename ...Types> 1949 struct StringMaker<std::tuple<Types...>> { 1950 static std::string convert(const std::tuple<Types...>& tuple) { 1951 ReusableStringStream rss; 1952 rss << '{'; 1953 Detail::TupleElementPrinter<std::tuple<Types...>>::print(tuple, rss.get()); 1954 rss << " }"; 1955 return rss.str(); 1956 } 1957 }; 1958 } 1959 #endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER 1960 1961 #if defined(CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_VARIANT) 1962 #include <variant> 1963 namespace Catch { 1964 template<> 1965 struct StringMaker<std::monostate> { 1966 static std::string convert(const std::monostate&) { 1967 return "{ }"; 1968 } 1969 }; 1970 1971 template<typename... Elements> 1972 struct StringMaker<std::variant<Elements...>> { 1973 static std::string convert(const std::variant<Elements...>& variant) { 1974 if (variant.valueless_by_exception()) { 1975 return "{valueless variant}"; 1976 } else { 1977 return std::visit( 1978 [](const auto& value) { 1979 return ::Catch::Detail::stringify(value); 1980 }, 1981 variant 1982 ); 1983 } 1984 } 1985 }; 1986 } 1987 #endif // CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER 1988 1989 namespace Catch { 1990 // Import begin/ end from std here 1991 using std::begin; 1992 using std::end; 1993 1994 namespace detail { 1995 template <typename...> 1996 struct void_type { 1997 using type = void; 1998 }; 1999 2000 template <typename T, typename = void> 2001 struct is_range_impl : std::false_type { 2002 }; 2003 2004 template <typename T> 2005 struct is_range_impl<T, typename void_type<decltype(begin(std::declval<T>()))>::type> : std::true_type { 2006 }; 2007 } // namespace detail 2008 2009 template <typename T> 2010 struct is_range : detail::is_range_impl<T> { 2011 }; 2012 2013 #if defined(_MANAGED) // Managed types are never ranges 2014 template <typename T> 2015 struct is_range<T^> { 2016 static const bool value = false; 2017 }; 2018 #endif 2019 2020 template<typename Range> 2021 std::string rangeToString( Range const& range ) { 2022 return ::Catch::Detail::rangeToString( begin( range ), end( range ) ); 2023 } 2024 2025 // Handle vector<bool> specially 2026 template<typename Allocator> 2027 std::string rangeToString( std::vector<bool, Allocator> const& v ) { 2028 ReusableStringStream rss; 2029 rss << "{ "; 2030 bool first = true; 2031 for( bool b : v ) { 2032 if( first ) 2033 first = false; 2034 else 2035 rss << ", "; 2036 rss << ::Catch::Detail::stringify( b ); 2037 } 2038 rss << " }"; 2039 return rss.str(); 2040 } 2041 2042 template<typename R> 2043 struct StringMaker<R, typename std::enable_if<is_range<R>::value && !::Catch::Detail::IsStreamInsertable<R>::value>::type> { 2044 static std::string convert( R const& range ) { 2045 return rangeToString( range ); 2046 } 2047 }; 2048 2049 template <typename T, int SZ> 2050 struct StringMaker<T[SZ]> { 2051 static std::string convert(T const(&arr)[SZ]) { 2052 return rangeToString(arr); 2053 } 2054 }; 2055 2056 } // namespace Catch 2057 2058 // Separate std::chrono::duration specialization 2059 #if defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) 2060 #include <ctime> 2061 #include <ratio> 2062 #include <chrono> 2063 2064 namespace Catch { 2065 2066 template <class Ratio> 2067 struct ratio_string { 2068 static std::string symbol(); 2069 }; 2070 2071 template <class Ratio> 2072 std::string ratio_string<Ratio>::symbol() { 2073 Catch::ReusableStringStream rss; 2074 rss << '[' << Ratio::num << '/' 2075 << Ratio::den << ']'; 2076 return rss.str(); 2077 } 2078 template <> 2079 struct ratio_string<std::atto> { 2080 static std::string symbol(); 2081 }; 2082 template <> 2083 struct ratio_string<std::femto> { 2084 static std::string symbol(); 2085 }; 2086 template <> 2087 struct ratio_string<std::pico> { 2088 static std::string symbol(); 2089 }; 2090 template <> 2091 struct ratio_string<std::nano> { 2092 static std::string symbol(); 2093 }; 2094 template <> 2095 struct ratio_string<std::micro> { 2096 static std::string symbol(); 2097 }; 2098 template <> 2099 struct ratio_string<std::milli> { 2100 static std::string symbol(); 2101 }; 2102 2103 //////////// 2104 // std::chrono::duration specializations 2105 template<typename Value, typename Ratio> 2106 struct StringMaker<std::chrono::duration<Value, Ratio>> { 2107 static std::string convert(std::chrono::duration<Value, Ratio> const& duration) { 2108 ReusableStringStream rss; 2109 rss << duration.count() << ' ' << ratio_string<Ratio>::symbol() << 's'; 2110 return rss.str(); 2111 } 2112 }; 2113 template<typename Value> 2114 struct StringMaker<std::chrono::duration<Value, std::ratio<1>>> { 2115 static std::string convert(std::chrono::duration<Value, std::ratio<1>> const& duration) { 2116 ReusableStringStream rss; 2117 rss << duration.count() << " s"; 2118 return rss.str(); 2119 } 2120 }; 2121 template<typename Value> 2122 struct StringMaker<std::chrono::duration<Value, std::ratio<60>>> { 2123 static std::string convert(std::chrono::duration<Value, std::ratio<60>> const& duration) { 2124 ReusableStringStream rss; 2125 rss << duration.count() << " m"; 2126 return rss.str(); 2127 } 2128 }; 2129 template<typename Value> 2130 struct StringMaker<std::chrono::duration<Value, std::ratio<3600>>> { 2131 static std::string convert(std::chrono::duration<Value, std::ratio<3600>> const& duration) { 2132 ReusableStringStream rss; 2133 rss << duration.count() << " h"; 2134 return rss.str(); 2135 } 2136 }; 2137 2138 //////////// 2139 // std::chrono::time_point specialization 2140 // Generic time_point cannot be specialized, only std::chrono::time_point<system_clock> 2141 template<typename Clock, typename Duration> 2142 struct StringMaker<std::chrono::time_point<Clock, Duration>> { 2143 static std::string convert(std::chrono::time_point<Clock, Duration> const& time_point) { 2144 return ::Catch::Detail::stringify(time_point.time_since_epoch()) + " since epoch"; 2145 } 2146 }; 2147 // std::chrono::time_point<system_clock> specialization 2148 template<typename Duration> 2149 struct StringMaker<std::chrono::time_point<std::chrono::system_clock, Duration>> { 2150 static std::string convert(std::chrono::time_point<std::chrono::system_clock, Duration> const& time_point) { 2151 auto converted = std::chrono::system_clock::to_time_t(time_point); 2152 2153 #ifdef _MSC_VER 2154 std::tm timeInfo = {}; 2155 gmtime_s(&timeInfo, &converted); 2156 #else 2157 std::tm* timeInfo = std::gmtime(&converted); 2158 #endif 2159 2160 auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); 2161 char timeStamp[timeStampSize]; 2162 const char * const fmt = "%Y-%m-%dT%H:%M:%SZ"; 2163 2164 #ifdef _MSC_VER 2165 std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); 2166 #else 2167 std::strftime(timeStamp, timeStampSize, fmt, timeInfo); 2168 #endif 2169 return std::string(timeStamp); 2170 } 2171 }; 2172 } 2173 #endif // CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER 2174 2175 #define INTERNAL_CATCH_REGISTER_ENUM( enumName, ... ) \ 2176 namespace Catch { \ 2177 template<> struct StringMaker<enumName> { \ 2178 static std::string convert( enumName value ) { \ 2179 static const auto& enumInfo = ::Catch::getMutableRegistryHub().getMutableEnumValuesRegistry().registerEnum( #enumName, #__VA_ARGS__, { __VA_ARGS__ } ); \ 2180 return static_cast<std::string>(enumInfo.lookup( static_cast<int>( value ) )); \ 2181 } \ 2182 }; \ 2183 } 2184 2185 #define CATCH_REGISTER_ENUM( enumName, ... ) INTERNAL_CATCH_REGISTER_ENUM( enumName, __VA_ARGS__ ) 2186 2187 #ifdef _MSC_VER 2188 #pragma warning(pop) 2189 #endif 2190 2191 // end catch_tostring.h 2192 #include <iosfwd> 2193 2194 #ifdef _MSC_VER 2195 #pragma warning(push) 2196 #pragma warning(disable:4389) // '==' : signed/unsigned mismatch 2197 #pragma warning(disable:4018) // more "signed/unsigned mismatch" 2198 #pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform) 2199 #pragma warning(disable:4180) // qualifier applied to function type has no meaning 2200 #pragma warning(disable:4800) // Forcing result to true or false 2201 #endif 2202 2203 namespace Catch { 2204 2205 struct ITransientExpression { 2206 auto isBinaryExpression() const -> bool { return m_isBinaryExpression; } 2207 auto getResult() const -> bool { return m_result; } 2208 virtual void streamReconstructedExpression( std::ostream &os ) const = 0; 2209 2210 ITransientExpression( bool isBinaryExpression, bool result ) 2211 : m_isBinaryExpression( isBinaryExpression ), 2212 m_result( result ) 2213 {} 2214 2215 // We don't actually need a virtual destructor, but many static analysers 2216 // complain if it's not here :-( 2217 virtual ~ITransientExpression(); 2218 2219 bool m_isBinaryExpression; 2220 bool m_result; 2221 2222 }; 2223 2224 void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ); 2225 2226 template<typename LhsT, typename RhsT> 2227 class BinaryExpr : public ITransientExpression { 2228 LhsT m_lhs; 2229 StringRef m_op; 2230 RhsT m_rhs; 2231 2232 void streamReconstructedExpression( std::ostream &os ) const override { 2233 formatReconstructedExpression 2234 ( os, Catch::Detail::stringify( m_lhs ), m_op, Catch::Detail::stringify( m_rhs ) ); 2235 } 2236 2237 public: 2238 BinaryExpr( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs ) 2239 : ITransientExpression{ true, comparisonResult }, 2240 m_lhs( lhs ), 2241 m_op( op ), 2242 m_rhs( rhs ) 2243 {} 2244 2245 template<typename T> 2246 auto operator && ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 2247 static_assert(always_false<T>::value, 2248 "chained comparisons are not supported inside assertions, " 2249 "wrap the expression inside parentheses, or decompose it"); 2250 } 2251 2252 template<typename T> 2253 auto operator || ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 2254 static_assert(always_false<T>::value, 2255 "chained comparisons are not supported inside assertions, " 2256 "wrap the expression inside parentheses, or decompose it"); 2257 } 2258 2259 template<typename T> 2260 auto operator == ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 2261 static_assert(always_false<T>::value, 2262 "chained comparisons are not supported inside assertions, " 2263 "wrap the expression inside parentheses, or decompose it"); 2264 } 2265 2266 template<typename T> 2267 auto operator != ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 2268 static_assert(always_false<T>::value, 2269 "chained comparisons are not supported inside assertions, " 2270 "wrap the expression inside parentheses, or decompose it"); 2271 } 2272 2273 template<typename T> 2274 auto operator > ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 2275 static_assert(always_false<T>::value, 2276 "chained comparisons are not supported inside assertions, " 2277 "wrap the expression inside parentheses, or decompose it"); 2278 } 2279 2280 template<typename T> 2281 auto operator < ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 2282 static_assert(always_false<T>::value, 2283 "chained comparisons are not supported inside assertions, " 2284 "wrap the expression inside parentheses, or decompose it"); 2285 } 2286 2287 template<typename T> 2288 auto operator >= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 2289 static_assert(always_false<T>::value, 2290 "chained comparisons are not supported inside assertions, " 2291 "wrap the expression inside parentheses, or decompose it"); 2292 } 2293 2294 template<typename T> 2295 auto operator <= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 2296 static_assert(always_false<T>::value, 2297 "chained comparisons are not supported inside assertions, " 2298 "wrap the expression inside parentheses, or decompose it"); 2299 } 2300 }; 2301 2302 template<typename LhsT> 2303 class UnaryExpr : public ITransientExpression { 2304 LhsT m_lhs; 2305 2306 void streamReconstructedExpression( std::ostream &os ) const override { 2307 os << Catch::Detail::stringify( m_lhs ); 2308 } 2309 2310 public: 2311 explicit UnaryExpr( LhsT lhs ) 2312 : ITransientExpression{ false, static_cast<bool>(lhs) }, 2313 m_lhs( lhs ) 2314 {} 2315 }; 2316 2317 // Specialised comparison functions to handle equality comparisons between ints and pointers (NULL deduces as an int) 2318 template<typename LhsT, typename RhsT> 2319 auto compareEqual( LhsT const& lhs, RhsT const& rhs ) -> bool { return static_cast<bool>(lhs == rhs); } 2320 template<typename T> 2321 auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); } 2322 template<typename T> 2323 auto compareEqual( T* const& lhs, long rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); } 2324 template<typename T> 2325 auto compareEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; } 2326 template<typename T> 2327 auto compareEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; } 2328 2329 template<typename LhsT, typename RhsT> 2330 auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return static_cast<bool>(lhs != rhs); } 2331 template<typename T> 2332 auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); } 2333 template<typename T> 2334 auto compareNotEqual( T* const& lhs, long rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); } 2335 template<typename T> 2336 auto compareNotEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) != rhs; } 2337 template<typename T> 2338 auto compareNotEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) != rhs; } 2339 2340 template<typename LhsT> 2341 class ExprLhs { 2342 LhsT m_lhs; 2343 public: 2344 explicit ExprLhs( LhsT lhs ) : m_lhs( lhs ) {} 2345 2346 template<typename RhsT> 2347 auto operator == ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const { 2348 return { compareEqual( m_lhs, rhs ), m_lhs, "==", rhs }; 2349 } 2350 auto operator == ( bool rhs ) -> BinaryExpr<LhsT, bool> const { 2351 return { m_lhs == rhs, m_lhs, "==", rhs }; 2352 } 2353 2354 template<typename RhsT> 2355 auto operator != ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const { 2356 return { compareNotEqual( m_lhs, rhs ), m_lhs, "!=", rhs }; 2357 } 2358 auto operator != ( bool rhs ) -> BinaryExpr<LhsT, bool> const { 2359 return { m_lhs != rhs, m_lhs, "!=", rhs }; 2360 } 2361 2362 template<typename RhsT> 2363 auto operator > ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const { 2364 return { static_cast<bool>(m_lhs > rhs), m_lhs, ">", rhs }; 2365 } 2366 template<typename RhsT> 2367 auto operator < ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const { 2368 return { static_cast<bool>(m_lhs < rhs), m_lhs, "<", rhs }; 2369 } 2370 template<typename RhsT> 2371 auto operator >= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const { 2372 return { static_cast<bool>(m_lhs >= rhs), m_lhs, ">=", rhs }; 2373 } 2374 template<typename RhsT> 2375 auto operator <= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const { 2376 return { static_cast<bool>(m_lhs <= rhs), m_lhs, "<=", rhs }; 2377 } 2378 template <typename RhsT> 2379 auto operator | (RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const { 2380 return { static_cast<bool>(m_lhs | rhs), m_lhs, "|", rhs }; 2381 } 2382 template <typename RhsT> 2383 auto operator & (RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const { 2384 return { static_cast<bool>(m_lhs & rhs), m_lhs, "&", rhs }; 2385 } 2386 template <typename RhsT> 2387 auto operator ^ (RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const { 2388 return { static_cast<bool>(m_lhs ^ rhs), m_lhs, "^", rhs }; 2389 } 2390 2391 template<typename RhsT> 2392 auto operator && ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const { 2393 static_assert(always_false<RhsT>::value, 2394 "operator&& is not supported inside assertions, " 2395 "wrap the expression inside parentheses, or decompose it"); 2396 } 2397 2398 template<typename RhsT> 2399 auto operator || ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const { 2400 static_assert(always_false<RhsT>::value, 2401 "operator|| is not supported inside assertions, " 2402 "wrap the expression inside parentheses, or decompose it"); 2403 } 2404 2405 auto makeUnaryExpr() const -> UnaryExpr<LhsT> { 2406 return UnaryExpr<LhsT>{ m_lhs }; 2407 } 2408 }; 2409 2410 void handleExpression( ITransientExpression const& expr ); 2411 2412 template<typename T> 2413 void handleExpression( ExprLhs<T> const& expr ) { 2414 handleExpression( expr.makeUnaryExpr() ); 2415 } 2416 2417 struct Decomposer { 2418 template<typename T> 2419 auto operator <= ( T const& lhs ) -> ExprLhs<T const&> { 2420 return ExprLhs<T const&>{ lhs }; 2421 } 2422 2423 auto operator <=( bool value ) -> ExprLhs<bool> { 2424 return ExprLhs<bool>{ value }; 2425 } 2426 }; 2427 2428 } // end namespace Catch 2429 2430 #ifdef _MSC_VER 2431 #pragma warning(pop) 2432 #endif 2433 2434 // end catch_decomposer.h 2435 // start catch_interfaces_capture.h 2436 2437 #include <string> 2438 #include <chrono> 2439 2440 namespace Catch { 2441 2442 class AssertionResult; 2443 struct AssertionInfo; 2444 struct SectionInfo; 2445 struct SectionEndInfo; 2446 struct MessageInfo; 2447 struct MessageBuilder; 2448 struct Counts; 2449 struct AssertionReaction; 2450 struct SourceLineInfo; 2451 2452 struct ITransientExpression; 2453 struct IGeneratorTracker; 2454 2455 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 2456 struct BenchmarkInfo; 2457 template <typename Duration = std::chrono::duration<double, std::nano>> 2458 struct BenchmarkStats; 2459 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 2460 2461 struct IResultCapture { 2462 2463 virtual ~IResultCapture(); 2464 2465 virtual bool sectionStarted( SectionInfo const& sectionInfo, 2466 Counts& assertions ) = 0; 2467 virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; 2468 virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; 2469 2470 virtual auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& = 0; 2471 2472 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 2473 virtual void benchmarkPreparing( std::string const& name ) = 0; 2474 virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0; 2475 virtual void benchmarkEnded( BenchmarkStats<> const& stats ) = 0; 2476 virtual void benchmarkFailed( std::string const& error ) = 0; 2477 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 2478 2479 virtual void pushScopedMessage( MessageInfo const& message ) = 0; 2480 virtual void popScopedMessage( MessageInfo const& message ) = 0; 2481 2482 virtual void emplaceUnscopedMessage( MessageBuilder const& builder ) = 0; 2483 2484 virtual void handleFatalErrorCondition( StringRef message ) = 0; 2485 2486 virtual void handleExpr 2487 ( AssertionInfo const& info, 2488 ITransientExpression const& expr, 2489 AssertionReaction& reaction ) = 0; 2490 virtual void handleMessage 2491 ( AssertionInfo const& info, 2492 ResultWas::OfType resultType, 2493 StringRef const& message, 2494 AssertionReaction& reaction ) = 0; 2495 virtual void handleUnexpectedExceptionNotThrown 2496 ( AssertionInfo const& info, 2497 AssertionReaction& reaction ) = 0; 2498 virtual void handleUnexpectedInflightException 2499 ( AssertionInfo const& info, 2500 std::string const& message, 2501 AssertionReaction& reaction ) = 0; 2502 virtual void handleIncomplete 2503 ( AssertionInfo const& info ) = 0; 2504 virtual void handleNonExpr 2505 ( AssertionInfo const &info, 2506 ResultWas::OfType resultType, 2507 AssertionReaction &reaction ) = 0; 2508 2509 virtual bool lastAssertionPassed() = 0; 2510 virtual void assertionPassed() = 0; 2511 2512 // Deprecated, do not use: 2513 virtual std::string getCurrentTestName() const = 0; 2514 virtual const AssertionResult* getLastResult() const = 0; 2515 virtual void exceptionEarlyReported() = 0; 2516 }; 2517 2518 IResultCapture& getResultCapture(); 2519 } 2520 2521 // end catch_interfaces_capture.h 2522 namespace Catch { 2523 2524 struct TestFailureException{}; 2525 struct AssertionResultData; 2526 struct IResultCapture; 2527 class RunContext; 2528 2529 class LazyExpression { 2530 friend class AssertionHandler; 2531 friend struct AssertionStats; 2532 friend class RunContext; 2533 2534 ITransientExpression const* m_transientExpression = nullptr; 2535 bool m_isNegated; 2536 public: 2537 LazyExpression( bool isNegated ); 2538 LazyExpression( LazyExpression const& other ); 2539 LazyExpression& operator = ( LazyExpression const& ) = delete; 2540 2541 explicit operator bool() const; 2542 2543 friend auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream&; 2544 }; 2545 2546 struct AssertionReaction { 2547 bool shouldDebugBreak = false; 2548 bool shouldThrow = false; 2549 }; 2550 2551 class AssertionHandler { 2552 AssertionInfo m_assertionInfo; 2553 AssertionReaction m_reaction; 2554 bool m_completed = false; 2555 IResultCapture& m_resultCapture; 2556 2557 public: 2558 AssertionHandler 2559 ( StringRef const& macroName, 2560 SourceLineInfo const& lineInfo, 2561 StringRef capturedExpression, 2562 ResultDisposition::Flags resultDisposition ); 2563 ~AssertionHandler() { 2564 if ( !m_completed ) { 2565 m_resultCapture.handleIncomplete( m_assertionInfo ); 2566 } 2567 } 2568 2569 template<typename T> 2570 void handleExpr( ExprLhs<T> const& expr ) { 2571 handleExpr( expr.makeUnaryExpr() ); 2572 } 2573 void handleExpr( ITransientExpression const& expr ); 2574 2575 void handleMessage(ResultWas::OfType resultType, StringRef const& message); 2576 2577 void handleExceptionThrownAsExpected(); 2578 void handleUnexpectedExceptionNotThrown(); 2579 void handleExceptionNotThrownAsExpected(); 2580 void handleThrowingCallSkipped(); 2581 void handleUnexpectedInflightException(); 2582 2583 void complete(); 2584 void setCompleted(); 2585 2586 // query 2587 auto allowThrows() const -> bool; 2588 }; 2589 2590 void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef const& matcherString ); 2591 2592 } // namespace Catch 2593 2594 // end catch_assertionhandler.h 2595 // start catch_message.h 2596 2597 #include <string> 2598 #include <vector> 2599 2600 namespace Catch { 2601 2602 struct MessageInfo { 2603 MessageInfo( StringRef const& _macroName, 2604 SourceLineInfo const& _lineInfo, 2605 ResultWas::OfType _type ); 2606 2607 StringRef macroName; 2608 std::string message; 2609 SourceLineInfo lineInfo; 2610 ResultWas::OfType type; 2611 unsigned int sequence; 2612 2613 bool operator == ( MessageInfo const& other ) const; 2614 bool operator < ( MessageInfo const& other ) const; 2615 private: 2616 static unsigned int globalCount; 2617 }; 2618 2619 struct MessageStream { 2620 2621 template<typename T> 2622 MessageStream& operator << ( T const& value ) { 2623 m_stream << value; 2624 return *this; 2625 } 2626 2627 ReusableStringStream m_stream; 2628 }; 2629 2630 struct MessageBuilder : MessageStream { 2631 MessageBuilder( StringRef const& macroName, 2632 SourceLineInfo const& lineInfo, 2633 ResultWas::OfType type ); 2634 2635 template<typename T> 2636 MessageBuilder& operator << ( T const& value ) { 2637 m_stream << value; 2638 return *this; 2639 } 2640 2641 MessageInfo m_info; 2642 }; 2643 2644 class ScopedMessage { 2645 public: 2646 explicit ScopedMessage( MessageBuilder const& builder ); 2647 ScopedMessage( ScopedMessage& duplicate ) = delete; 2648 ScopedMessage( ScopedMessage&& old ); 2649 ~ScopedMessage(); 2650 2651 MessageInfo m_info; 2652 bool m_moved; 2653 }; 2654 2655 class Capturer { 2656 std::vector<MessageInfo> m_messages; 2657 IResultCapture& m_resultCapture = getResultCapture(); 2658 size_t m_captured = 0; 2659 public: 2660 Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names ); 2661 ~Capturer(); 2662 2663 void captureValue( size_t index, std::string const& value ); 2664 2665 template<typename T> 2666 void captureValues( size_t index, T const& value ) { 2667 captureValue( index, Catch::Detail::stringify( value ) ); 2668 } 2669 2670 template<typename T, typename... Ts> 2671 void captureValues( size_t index, T const& value, Ts const&... values ) { 2672 captureValue( index, Catch::Detail::stringify(value) ); 2673 captureValues( index+1, values... ); 2674 } 2675 }; 2676 2677 } // end namespace Catch 2678 2679 // end catch_message.h 2680 #if !defined(CATCH_CONFIG_DISABLE) 2681 2682 #if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION) 2683 #define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__ 2684 #else 2685 #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION" 2686 #endif 2687 2688 #if defined(CATCH_CONFIG_FAST_COMPILE) || defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 2689 2690 /////////////////////////////////////////////////////////////////////////////// 2691 // Another way to speed-up compilation is to omit local try-catch for REQUIRE* 2692 // macros. 2693 #define INTERNAL_CATCH_TRY 2694 #define INTERNAL_CATCH_CATCH( capturer ) 2695 2696 #else // CATCH_CONFIG_FAST_COMPILE 2697 2698 #define INTERNAL_CATCH_TRY try 2699 #define INTERNAL_CATCH_CATCH( handler ) catch(...) { handler.handleUnexpectedInflightException(); } 2700 2701 #endif 2702 2703 #define INTERNAL_CATCH_REACT( handler ) handler.complete(); 2704 2705 /////////////////////////////////////////////////////////////////////////////// 2706 #define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \ 2707 do { \ 2708 CATCH_INTERNAL_IGNORE_BUT_WARN(__VA_ARGS__); \ 2709 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ 2710 INTERNAL_CATCH_TRY { \ 2711 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 2712 CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ 2713 catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); \ 2714 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 2715 } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ 2716 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2717 } while( (void)0, (false) && static_cast<bool>( !!(__VA_ARGS__) ) ) 2718 2719 /////////////////////////////////////////////////////////////////////////////// 2720 #define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \ 2721 INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \ 2722 if( Catch::getResultCapture().lastAssertionPassed() ) 2723 2724 /////////////////////////////////////////////////////////////////////////////// 2725 #define INTERNAL_CATCH_ELSE( macroName, resultDisposition, ... ) \ 2726 INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \ 2727 if( !Catch::getResultCapture().lastAssertionPassed() ) 2728 2729 /////////////////////////////////////////////////////////////////////////////// 2730 #define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \ 2731 do { \ 2732 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ 2733 try { \ 2734 static_cast<void>(__VA_ARGS__); \ 2735 catchAssertionHandler.handleExceptionNotThrownAsExpected(); \ 2736 } \ 2737 catch( ... ) { \ 2738 catchAssertionHandler.handleUnexpectedInflightException(); \ 2739 } \ 2740 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2741 } while( false ) 2742 2743 /////////////////////////////////////////////////////////////////////////////// 2744 #define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \ 2745 do { \ 2746 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \ 2747 if( catchAssertionHandler.allowThrows() ) \ 2748 try { \ 2749 static_cast<void>(__VA_ARGS__); \ 2750 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 2751 } \ 2752 catch( ... ) { \ 2753 catchAssertionHandler.handleExceptionThrownAsExpected(); \ 2754 } \ 2755 else \ 2756 catchAssertionHandler.handleThrowingCallSkipped(); \ 2757 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2758 } while( false ) 2759 2760 /////////////////////////////////////////////////////////////////////////////// 2761 #define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \ 2762 do { \ 2763 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \ 2764 if( catchAssertionHandler.allowThrows() ) \ 2765 try { \ 2766 static_cast<void>(expr); \ 2767 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 2768 } \ 2769 catch( exceptionType const& ) { \ 2770 catchAssertionHandler.handleExceptionThrownAsExpected(); \ 2771 } \ 2772 catch( ... ) { \ 2773 catchAssertionHandler.handleUnexpectedInflightException(); \ 2774 } \ 2775 else \ 2776 catchAssertionHandler.handleThrowingCallSkipped(); \ 2777 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2778 } while( false ) 2779 2780 /////////////////////////////////////////////////////////////////////////////// 2781 #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \ 2782 do { \ 2783 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::StringRef(), resultDisposition ); \ 2784 catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \ 2785 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2786 } while( false ) 2787 2788 /////////////////////////////////////////////////////////////////////////////// 2789 #define INTERNAL_CATCH_CAPTURE( varName, macroName, ... ) \ 2790 auto varName = Catch::Capturer( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info, #__VA_ARGS__ ); \ 2791 varName.captureValues( 0, __VA_ARGS__ ) 2792 2793 /////////////////////////////////////////////////////////////////////////////// 2794 #define INTERNAL_CATCH_INFO( macroName, log ) \ 2795 Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log ); 2796 2797 /////////////////////////////////////////////////////////////////////////////// 2798 #define INTERNAL_CATCH_UNSCOPED_INFO( macroName, log ) \ 2799 Catch::getResultCapture().emplaceUnscopedMessage( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log ) 2800 2801 /////////////////////////////////////////////////////////////////////////////// 2802 // Although this is matcher-based, it can be used with just a string 2803 #define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \ 2804 do { \ 2805 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ 2806 if( catchAssertionHandler.allowThrows() ) \ 2807 try { \ 2808 static_cast<void>(__VA_ARGS__); \ 2809 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 2810 } \ 2811 catch( ... ) { \ 2812 Catch::handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher##_catch_sr ); \ 2813 } \ 2814 else \ 2815 catchAssertionHandler.handleThrowingCallSkipped(); \ 2816 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2817 } while( false ) 2818 2819 #endif // CATCH_CONFIG_DISABLE 2820 2821 // end catch_capture.hpp 2822 // start catch_section.h 2823 2824 // start catch_section_info.h 2825 2826 // start catch_totals.h 2827 2828 #include <cstddef> 2829 2830 namespace Catch { 2831 2832 struct Counts { 2833 Counts operator - ( Counts const& other ) const; 2834 Counts& operator += ( Counts const& other ); 2835 2836 std::size_t total() const; 2837 bool allPassed() const; 2838 bool allOk() const; 2839 2840 std::size_t passed = 0; 2841 std::size_t failed = 0; 2842 std::size_t failedButOk = 0; 2843 }; 2844 2845 struct Totals { 2846 2847 Totals operator - ( Totals const& other ) const; 2848 Totals& operator += ( Totals const& other ); 2849 2850 Totals delta( Totals const& prevTotals ) const; 2851 2852 int error = 0; 2853 Counts assertions; 2854 Counts testCases; 2855 }; 2856 } 2857 2858 // end catch_totals.h 2859 #include <string> 2860 2861 namespace Catch { 2862 2863 struct SectionInfo { 2864 SectionInfo 2865 ( SourceLineInfo const& _lineInfo, 2866 std::string const& _name ); 2867 2868 // Deprecated 2869 SectionInfo 2870 ( SourceLineInfo const& _lineInfo, 2871 std::string const& _name, 2872 std::string const& ) : SectionInfo( _lineInfo, _name ) {} 2873 2874 std::string name; 2875 std::string description; // !Deprecated: this will always be empty 2876 SourceLineInfo lineInfo; 2877 }; 2878 2879 struct SectionEndInfo { 2880 SectionInfo sectionInfo; 2881 Counts prevAssertions; 2882 double durationInSeconds; 2883 }; 2884 2885 } // end namespace Catch 2886 2887 // end catch_section_info.h 2888 // start catch_timer.h 2889 2890 #include <cstdint> 2891 2892 namespace Catch { 2893 2894 auto getCurrentNanosecondsSinceEpoch() -> uint64_t; 2895 auto getEstimatedClockResolution() -> uint64_t; 2896 2897 class Timer { 2898 uint64_t m_nanoseconds = 0; 2899 public: 2900 void start(); 2901 auto getElapsedNanoseconds() const -> uint64_t; 2902 auto getElapsedMicroseconds() const -> uint64_t; 2903 auto getElapsedMilliseconds() const -> unsigned int; 2904 auto getElapsedSeconds() const -> double; 2905 }; 2906 2907 } // namespace Catch 2908 2909 // end catch_timer.h 2910 #include <string> 2911 2912 namespace Catch { 2913 2914 class Section : NonCopyable { 2915 public: 2916 Section( SectionInfo const& info ); 2917 ~Section(); 2918 2919 // This indicates whether the section should be executed or not 2920 explicit operator bool() const; 2921 2922 private: 2923 SectionInfo m_info; 2924 2925 std::string m_name; 2926 Counts m_assertions; 2927 bool m_sectionIncluded; 2928 Timer m_timer; 2929 }; 2930 2931 } // end namespace Catch 2932 2933 #define INTERNAL_CATCH_SECTION( ... ) \ 2934 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 2935 CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ 2936 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \ 2937 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 2938 2939 #define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \ 2940 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 2941 CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ 2942 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, (Catch::ReusableStringStream() << __VA_ARGS__).str() ) ) \ 2943 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 2944 2945 // end catch_section.h 2946 // start catch_interfaces_exception.h 2947 2948 // start catch_interfaces_registry_hub.h 2949 2950 #include <string> 2951 #include <memory> 2952 2953 namespace Catch { 2954 2955 class TestCase; 2956 struct ITestCaseRegistry; 2957 struct IExceptionTranslatorRegistry; 2958 struct IExceptionTranslator; 2959 struct IReporterRegistry; 2960 struct IReporterFactory; 2961 struct ITagAliasRegistry; 2962 struct IMutableEnumValuesRegistry; 2963 2964 class StartupExceptionRegistry; 2965 2966 using IReporterFactoryPtr = std::shared_ptr<IReporterFactory>; 2967 2968 struct IRegistryHub { 2969 virtual ~IRegistryHub(); 2970 2971 virtual IReporterRegistry const& getReporterRegistry() const = 0; 2972 virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; 2973 virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0; 2974 virtual IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const = 0; 2975 2976 virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0; 2977 }; 2978 2979 struct IMutableRegistryHub { 2980 virtual ~IMutableRegistryHub(); 2981 virtual void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) = 0; 2982 virtual void registerListener( IReporterFactoryPtr const& factory ) = 0; 2983 virtual void registerTest( TestCase const& testInfo ) = 0; 2984 virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; 2985 virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0; 2986 virtual void registerStartupException() noexcept = 0; 2987 virtual IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() = 0; 2988 }; 2989 2990 IRegistryHub const& getRegistryHub(); 2991 IMutableRegistryHub& getMutableRegistryHub(); 2992 void cleanUp(); 2993 std::string translateActiveException(); 2994 2995 } 2996 2997 // end catch_interfaces_registry_hub.h 2998 #if defined(CATCH_CONFIG_DISABLE) 2999 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( translatorName, signature) \ 3000 static std::string translatorName( signature ) 3001 #endif 3002 3003 #include <exception> 3004 #include <string> 3005 #include <vector> 3006 3007 namespace Catch { 3008 using exceptionTranslateFunction = std::string(*)(); 3009 3010 struct IExceptionTranslator; 3011 using ExceptionTranslators = std::vector<std::unique_ptr<IExceptionTranslator const>>; 3012 3013 struct IExceptionTranslator { 3014 virtual ~IExceptionTranslator(); 3015 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0; 3016 }; 3017 3018 struct IExceptionTranslatorRegistry { 3019 virtual ~IExceptionTranslatorRegistry(); 3020 3021 virtual std::string translateActiveException() const = 0; 3022 }; 3023 3024 class ExceptionTranslatorRegistrar { 3025 template<typename T> 3026 class ExceptionTranslator : public IExceptionTranslator { 3027 public: 3028 3029 ExceptionTranslator( std::string(*translateFunction)( T& ) ) 3030 : m_translateFunction( translateFunction ) 3031 {} 3032 3033 std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override { 3034 #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 3035 return ""; 3036 #else 3037 try { 3038 if( it == itEnd ) 3039 std::rethrow_exception(std::current_exception()); 3040 else 3041 return (*it)->translate( it+1, itEnd ); 3042 } 3043 catch( T& ex ) { 3044 return m_translateFunction( ex ); 3045 } 3046 #endif 3047 } 3048 3049 protected: 3050 std::string(*m_translateFunction)( T& ); 3051 }; 3052 3053 public: 3054 template<typename T> 3055 ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) { 3056 getMutableRegistryHub().registerTranslator 3057 ( new ExceptionTranslator<T>( translateFunction ) ); 3058 } 3059 }; 3060 } 3061 3062 /////////////////////////////////////////////////////////////////////////////// 3063 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \ 3064 static std::string translatorName( signature ); \ 3065 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 3066 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 3067 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); } \ 3068 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 3069 static std::string translatorName( signature ) 3070 3071 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) 3072 3073 // end catch_interfaces_exception.h 3074 // start catch_approx.h 3075 3076 #include <type_traits> 3077 3078 namespace Catch { 3079 namespace Detail { 3080 3081 class Approx { 3082 private: 3083 bool equalityComparisonImpl(double other) const; 3084 // Validates the new margin (margin >= 0) 3085 // out-of-line to avoid including stdexcept in the header 3086 void setMargin(double margin); 3087 // Validates the new epsilon (0 < epsilon < 1) 3088 // out-of-line to avoid including stdexcept in the header 3089 void setEpsilon(double epsilon); 3090 3091 public: 3092 explicit Approx ( double value ); 3093 3094 static Approx custom(); 3095 3096 Approx operator-() const; 3097 3098 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3099 Approx operator()( T const& value ) { 3100 Approx approx( static_cast<double>(value) ); 3101 approx.m_epsilon = m_epsilon; 3102 approx.m_margin = m_margin; 3103 approx.m_scale = m_scale; 3104 return approx; 3105 } 3106 3107 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3108 explicit Approx( T const& value ): Approx(static_cast<double>(value)) 3109 {} 3110 3111 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3112 friend bool operator == ( const T& lhs, Approx const& rhs ) { 3113 auto lhs_v = static_cast<double>(lhs); 3114 return rhs.equalityComparisonImpl(lhs_v); 3115 } 3116 3117 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3118 friend bool operator == ( Approx const& lhs, const T& rhs ) { 3119 return operator==( rhs, lhs ); 3120 } 3121 3122 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3123 friend bool operator != ( T const& lhs, Approx const& rhs ) { 3124 return !operator==( lhs, rhs ); 3125 } 3126 3127 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3128 friend bool operator != ( Approx const& lhs, T const& rhs ) { 3129 return !operator==( rhs, lhs ); 3130 } 3131 3132 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3133 friend bool operator <= ( T const& lhs, Approx const& rhs ) { 3134 return static_cast<double>(lhs) < rhs.m_value || lhs == rhs; 3135 } 3136 3137 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3138 friend bool operator <= ( Approx const& lhs, T const& rhs ) { 3139 return lhs.m_value < static_cast<double>(rhs) || lhs == rhs; 3140 } 3141 3142 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3143 friend bool operator >= ( T const& lhs, Approx const& rhs ) { 3144 return static_cast<double>(lhs) > rhs.m_value || lhs == rhs; 3145 } 3146 3147 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3148 friend bool operator >= ( Approx const& lhs, T const& rhs ) { 3149 return lhs.m_value > static_cast<double>(rhs) || lhs == rhs; 3150 } 3151 3152 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3153 Approx& epsilon( T const& newEpsilon ) { 3154 double epsilonAsDouble = static_cast<double>(newEpsilon); 3155 setEpsilon(epsilonAsDouble); 3156 return *this; 3157 } 3158 3159 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3160 Approx& margin( T const& newMargin ) { 3161 double marginAsDouble = static_cast<double>(newMargin); 3162 setMargin(marginAsDouble); 3163 return *this; 3164 } 3165 3166 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3167 Approx& scale( T const& newScale ) { 3168 m_scale = static_cast<double>(newScale); 3169 return *this; 3170 } 3171 3172 std::string toString() const; 3173 3174 private: 3175 double m_epsilon; 3176 double m_margin; 3177 double m_scale; 3178 double m_value; 3179 }; 3180 } // end namespace Detail 3181 3182 namespace literals { 3183 Detail::Approx operator "" _a(long double val); 3184 Detail::Approx operator "" _a(unsigned long long val); 3185 } // end namespace literals 3186 3187 template<> 3188 struct StringMaker<Catch::Detail::Approx> { 3189 static std::string convert(Catch::Detail::Approx const& value); 3190 }; 3191 3192 } // end namespace Catch 3193 3194 // end catch_approx.h 3195 // start catch_string_manip.h 3196 3197 #include <string> 3198 #include <iosfwd> 3199 #include <vector> 3200 3201 namespace Catch { 3202 3203 bool startsWith( std::string const& s, std::string const& prefix ); 3204 bool startsWith( std::string const& s, char prefix ); 3205 bool endsWith( std::string const& s, std::string const& suffix ); 3206 bool endsWith( std::string const& s, char suffix ); 3207 bool contains( std::string const& s, std::string const& infix ); 3208 void toLowerInPlace( std::string& s ); 3209 std::string toLower( std::string const& s ); 3210 //! Returns a new string without whitespace at the start/end 3211 std::string trim( std::string const& str ); 3212 //! Returns a substring of the original ref without whitespace. Beware lifetimes! 3213 StringRef trim(StringRef ref); 3214 3215 // !!! Be aware, returns refs into original string - make sure original string outlives them 3216 std::vector<StringRef> splitStringRef( StringRef str, char delimiter ); 3217 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ); 3218 3219 struct pluralise { 3220 pluralise( std::size_t count, std::string const& label ); 3221 3222 friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); 3223 3224 std::size_t m_count; 3225 std::string m_label; 3226 }; 3227 } 3228 3229 // end catch_string_manip.h 3230 #ifndef CATCH_CONFIG_DISABLE_MATCHERS 3231 // start catch_capture_matchers.h 3232 3233 // start catch_matchers.h 3234 3235 #include <string> 3236 #include <vector> 3237 3238 namespace Catch { 3239 namespace Matchers { 3240 namespace Impl { 3241 3242 template<typename ArgT> struct MatchAllOf; 3243 template<typename ArgT> struct MatchAnyOf; 3244 template<typename ArgT> struct MatchNotOf; 3245 3246 class MatcherUntypedBase { 3247 public: 3248 MatcherUntypedBase() = default; 3249 MatcherUntypedBase ( MatcherUntypedBase const& ) = default; 3250 MatcherUntypedBase& operator = ( MatcherUntypedBase const& ) = delete; 3251 std::string toString() const; 3252 3253 protected: 3254 virtual ~MatcherUntypedBase(); 3255 virtual std::string describe() const = 0; 3256 mutable std::string m_cachedToString; 3257 }; 3258 3259 #ifdef __clang__ 3260 # pragma clang diagnostic push 3261 # pragma clang diagnostic ignored "-Wnon-virtual-dtor" 3262 #endif 3263 3264 template<typename ObjectT> 3265 struct MatcherMethod { 3266 virtual bool match( ObjectT const& arg ) const = 0; 3267 }; 3268 3269 #if defined(__OBJC__) 3270 // Hack to fix Catch GH issue #1661. Could use id for generic Object support. 3271 // use of const for Object pointers is very uncommon and under ARC it causes some kind of signature mismatch that breaks compilation 3272 template<> 3273 struct MatcherMethod<NSString*> { 3274 virtual bool match( NSString* arg ) const = 0; 3275 }; 3276 #endif 3277 3278 #ifdef __clang__ 3279 # pragma clang diagnostic pop 3280 #endif 3281 3282 template<typename T> 3283 struct MatcherBase : MatcherUntypedBase, MatcherMethod<T> { 3284 3285 MatchAllOf<T> operator && ( MatcherBase const& other ) const; 3286 MatchAnyOf<T> operator || ( MatcherBase const& other ) const; 3287 MatchNotOf<T> operator ! () const; 3288 }; 3289 3290 template<typename ArgT> 3291 struct MatchAllOf : MatcherBase<ArgT> { 3292 bool match( ArgT const& arg ) const override { 3293 for( auto matcher : m_matchers ) { 3294 if (!matcher->match(arg)) 3295 return false; 3296 } 3297 return true; 3298 } 3299 std::string describe() const override { 3300 std::string description; 3301 description.reserve( 4 + m_matchers.size()*32 ); 3302 description += "( "; 3303 bool first = true; 3304 for( auto matcher : m_matchers ) { 3305 if( first ) 3306 first = false; 3307 else 3308 description += " and "; 3309 description += matcher->toString(); 3310 } 3311 description += " )"; 3312 return description; 3313 } 3314 3315 MatchAllOf<ArgT> operator && ( MatcherBase<ArgT> const& other ) { 3316 auto copy(*this); 3317 copy.m_matchers.push_back( &other ); 3318 return copy; 3319 } 3320 3321 std::vector<MatcherBase<ArgT> const*> m_matchers; 3322 }; 3323 template<typename ArgT> 3324 struct MatchAnyOf : MatcherBase<ArgT> { 3325 3326 bool match( ArgT const& arg ) const override { 3327 for( auto matcher : m_matchers ) { 3328 if (matcher->match(arg)) 3329 return true; 3330 } 3331 return false; 3332 } 3333 std::string describe() const override { 3334 std::string description; 3335 description.reserve( 4 + m_matchers.size()*32 ); 3336 description += "( "; 3337 bool first = true; 3338 for( auto matcher : m_matchers ) { 3339 if( first ) 3340 first = false; 3341 else 3342 description += " or "; 3343 description += matcher->toString(); 3344 } 3345 description += " )"; 3346 return description; 3347 } 3348 3349 MatchAnyOf<ArgT> operator || ( MatcherBase<ArgT> const& other ) { 3350 auto copy(*this); 3351 copy.m_matchers.push_back( &other ); 3352 return copy; 3353 } 3354 3355 std::vector<MatcherBase<ArgT> const*> m_matchers; 3356 }; 3357 3358 template<typename ArgT> 3359 struct MatchNotOf : MatcherBase<ArgT> { 3360 3361 MatchNotOf( MatcherBase<ArgT> const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {} 3362 3363 bool match( ArgT const& arg ) const override { 3364 return !m_underlyingMatcher.match( arg ); 3365 } 3366 3367 std::string describe() const override { 3368 return "not " + m_underlyingMatcher.toString(); 3369 } 3370 MatcherBase<ArgT> const& m_underlyingMatcher; 3371 }; 3372 3373 template<typename T> 3374 MatchAllOf<T> MatcherBase<T>::operator && ( MatcherBase const& other ) const { 3375 return MatchAllOf<T>() && *this && other; 3376 } 3377 template<typename T> 3378 MatchAnyOf<T> MatcherBase<T>::operator || ( MatcherBase const& other ) const { 3379 return MatchAnyOf<T>() || *this || other; 3380 } 3381 template<typename T> 3382 MatchNotOf<T> MatcherBase<T>::operator ! () const { 3383 return MatchNotOf<T>( *this ); 3384 } 3385 3386 } // namespace Impl 3387 3388 } // namespace Matchers 3389 3390 using namespace Matchers; 3391 using Matchers::Impl::MatcherBase; 3392 3393 } // namespace Catch 3394 3395 // end catch_matchers.h 3396 // start catch_matchers_exception.hpp 3397 3398 namespace Catch { 3399 namespace Matchers { 3400 namespace Exception { 3401 3402 class ExceptionMessageMatcher : public MatcherBase<std::exception> { 3403 std::string m_message; 3404 public: 3405 3406 ExceptionMessageMatcher(std::string const& message): 3407 m_message(message) 3408 {} 3409 3410 bool match(std::exception const& ex) const override; 3411 3412 std::string describe() const override; 3413 }; 3414 3415 } // namespace Exception 3416 3417 Exception::ExceptionMessageMatcher Message(std::string const& message); 3418 3419 } // namespace Matchers 3420 } // namespace Catch 3421 3422 // end catch_matchers_exception.hpp 3423 // start catch_matchers_floating.h 3424 3425 namespace Catch { 3426 namespace Matchers { 3427 3428 namespace Floating { 3429 3430 enum class FloatingPointKind : uint8_t; 3431 3432 struct WithinAbsMatcher : MatcherBase<double> { 3433 WithinAbsMatcher(double target, double margin); 3434 bool match(double const& matchee) const override; 3435 std::string describe() const override; 3436 private: 3437 double m_target; 3438 double m_margin; 3439 }; 3440 3441 struct WithinUlpsMatcher : MatcherBase<double> { 3442 WithinUlpsMatcher(double target, uint64_t ulps, FloatingPointKind baseType); 3443 bool match(double const& matchee) const override; 3444 std::string describe() const override; 3445 private: 3446 double m_target; 3447 uint64_t m_ulps; 3448 FloatingPointKind m_type; 3449 }; 3450 3451 // Given IEEE-754 format for floats and doubles, we can assume 3452 // that float -> double promotion is lossless. Given this, we can 3453 // assume that if we do the standard relative comparison of 3454 // |lhs - rhs| <= epsilon * max(fabs(lhs), fabs(rhs)), then we get 3455 // the same result if we do this for floats, as if we do this for 3456 // doubles that were promoted from floats. 3457 struct WithinRelMatcher : MatcherBase<double> { 3458 WithinRelMatcher(double target, double epsilon); 3459 bool match(double const& matchee) const override; 3460 std::string describe() const override; 3461 private: 3462 double m_target; 3463 double m_epsilon; 3464 }; 3465 3466 } // namespace Floating 3467 3468 // The following functions create the actual matcher objects. 3469 // This allows the types to be inferred 3470 Floating::WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff); 3471 Floating::WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff); 3472 Floating::WithinAbsMatcher WithinAbs(double target, double margin); 3473 Floating::WithinRelMatcher WithinRel(double target, double eps); 3474 // defaults epsilon to 100*numeric_limits<double>::epsilon() 3475 Floating::WithinRelMatcher WithinRel(double target); 3476 Floating::WithinRelMatcher WithinRel(float target, float eps); 3477 // defaults epsilon to 100*numeric_limits<float>::epsilon() 3478 Floating::WithinRelMatcher WithinRel(float target); 3479 3480 } // namespace Matchers 3481 } // namespace Catch 3482 3483 // end catch_matchers_floating.h 3484 // start catch_matchers_generic.hpp 3485 3486 #include <functional> 3487 #include <string> 3488 3489 namespace Catch { 3490 namespace Matchers { 3491 namespace Generic { 3492 3493 namespace Detail { 3494 std::string finalizeDescription(const std::string& desc); 3495 } 3496 3497 template <typename T> 3498 class PredicateMatcher : public MatcherBase<T> { 3499 std::function<bool(T const&)> m_predicate; 3500 std::string m_description; 3501 public: 3502 3503 PredicateMatcher(std::function<bool(T const&)> const& elem, std::string const& descr) 3504 :m_predicate(std::move(elem)), 3505 m_description(Detail::finalizeDescription(descr)) 3506 {} 3507 3508 bool match( T const& item ) const override { 3509 return m_predicate(item); 3510 } 3511 3512 std::string describe() const override { 3513 return m_description; 3514 } 3515 }; 3516 3517 } // namespace Generic 3518 3519 // The following functions create the actual matcher objects. 3520 // The user has to explicitly specify type to the function, because 3521 // inferring std::function<bool(T const&)> is hard (but possible) and 3522 // requires a lot of TMP. 3523 template<typename T> 3524 Generic::PredicateMatcher<T> Predicate(std::function<bool(T const&)> const& predicate, std::string const& description = "") { 3525 return Generic::PredicateMatcher<T>(predicate, description); 3526 } 3527 3528 } // namespace Matchers 3529 } // namespace Catch 3530 3531 // end catch_matchers_generic.hpp 3532 // start catch_matchers_string.h 3533 3534 #include <string> 3535 3536 namespace Catch { 3537 namespace Matchers { 3538 3539 namespace StdString { 3540 3541 struct CasedString 3542 { 3543 CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ); 3544 std::string adjustString( std::string const& str ) const; 3545 std::string caseSensitivitySuffix() const; 3546 3547 CaseSensitive::Choice m_caseSensitivity; 3548 std::string m_str; 3549 }; 3550 3551 struct StringMatcherBase : MatcherBase<std::string> { 3552 StringMatcherBase( std::string const& operation, CasedString const& comparator ); 3553 std::string describe() const override; 3554 3555 CasedString m_comparator; 3556 std::string m_operation; 3557 }; 3558 3559 struct EqualsMatcher : StringMatcherBase { 3560 EqualsMatcher( CasedString const& comparator ); 3561 bool match( std::string const& source ) const override; 3562 }; 3563 struct ContainsMatcher : StringMatcherBase { 3564 ContainsMatcher( CasedString const& comparator ); 3565 bool match( std::string const& source ) const override; 3566 }; 3567 struct StartsWithMatcher : StringMatcherBase { 3568 StartsWithMatcher( CasedString const& comparator ); 3569 bool match( std::string const& source ) const override; 3570 }; 3571 struct EndsWithMatcher : StringMatcherBase { 3572 EndsWithMatcher( CasedString const& comparator ); 3573 bool match( std::string const& source ) const override; 3574 }; 3575 3576 struct RegexMatcher : MatcherBase<std::string> { 3577 RegexMatcher( std::string regex, CaseSensitive::Choice caseSensitivity ); 3578 bool match( std::string const& matchee ) const override; 3579 std::string describe() const override; 3580 3581 private: 3582 std::string m_regex; 3583 CaseSensitive::Choice m_caseSensitivity; 3584 }; 3585 3586 } // namespace StdString 3587 3588 // The following functions create the actual matcher objects. 3589 // This allows the types to be inferred 3590 3591 StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); 3592 StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); 3593 StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); 3594 StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); 3595 StdString::RegexMatcher Matches( std::string const& regex, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); 3596 3597 } // namespace Matchers 3598 } // namespace Catch 3599 3600 // end catch_matchers_string.h 3601 // start catch_matchers_vector.h 3602 3603 #include <algorithm> 3604 3605 namespace Catch { 3606 namespace Matchers { 3607 3608 namespace Vector { 3609 template<typename T, typename Alloc> 3610 struct ContainsElementMatcher : MatcherBase<std::vector<T, Alloc>> { 3611 3612 ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {} 3613 3614 bool match(std::vector<T, Alloc> const &v) const override { 3615 for (auto const& el : v) { 3616 if (el == m_comparator) { 3617 return true; 3618 } 3619 } 3620 return false; 3621 } 3622 3623 std::string describe() const override { 3624 return "Contains: " + ::Catch::Detail::stringify( m_comparator ); 3625 } 3626 3627 T const& m_comparator; 3628 }; 3629 3630 template<typename T, typename AllocComp, typename AllocMatch> 3631 struct ContainsMatcher : MatcherBase<std::vector<T, AllocMatch>> { 3632 3633 ContainsMatcher(std::vector<T, AllocComp> const &comparator) : m_comparator( comparator ) {} 3634 3635 bool match(std::vector<T, AllocMatch> const &v) const override { 3636 // !TBD: see note in EqualsMatcher 3637 if (m_comparator.size() > v.size()) 3638 return false; 3639 for (auto const& comparator : m_comparator) { 3640 auto present = false; 3641 for (const auto& el : v) { 3642 if (el == comparator) { 3643 present = true; 3644 break; 3645 } 3646 } 3647 if (!present) { 3648 return false; 3649 } 3650 } 3651 return true; 3652 } 3653 std::string describe() const override { 3654 return "Contains: " + ::Catch::Detail::stringify( m_comparator ); 3655 } 3656 3657 std::vector<T, AllocComp> const& m_comparator; 3658 }; 3659 3660 template<typename T, typename AllocComp, typename AllocMatch> 3661 struct EqualsMatcher : MatcherBase<std::vector<T, AllocMatch>> { 3662 3663 EqualsMatcher(std::vector<T, AllocComp> const &comparator) : m_comparator( comparator ) {} 3664 3665 bool match(std::vector<T, AllocMatch> const &v) const override { 3666 // !TBD: This currently works if all elements can be compared using != 3667 // - a more general approach would be via a compare template that defaults 3668 // to using !=. but could be specialised for, e.g. std::vector<T, Alloc> etc 3669 // - then just call that directly 3670 if (m_comparator.size() != v.size()) 3671 return false; 3672 for (std::size_t i = 0; i < v.size(); ++i) 3673 if (m_comparator[i] != v[i]) 3674 return false; 3675 return true; 3676 } 3677 std::string describe() const override { 3678 return "Equals: " + ::Catch::Detail::stringify( m_comparator ); 3679 } 3680 std::vector<T, AllocComp> const& m_comparator; 3681 }; 3682 3683 template<typename T, typename AllocComp, typename AllocMatch> 3684 struct ApproxMatcher : MatcherBase<std::vector<T, AllocMatch>> { 3685 3686 ApproxMatcher(std::vector<T, AllocComp> const& comparator) : m_comparator( comparator ) {} 3687 3688 bool match(std::vector<T, AllocMatch> const &v) const override { 3689 if (m_comparator.size() != v.size()) 3690 return false; 3691 for (std::size_t i = 0; i < v.size(); ++i) 3692 if (m_comparator[i] != approx(v[i])) 3693 return false; 3694 return true; 3695 } 3696 std::string describe() const override { 3697 return "is approx: " + ::Catch::Detail::stringify( m_comparator ); 3698 } 3699 template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3700 ApproxMatcher& epsilon( T const& newEpsilon ) { 3701 approx.epsilon(newEpsilon); 3702 return *this; 3703 } 3704 template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3705 ApproxMatcher& margin( T const& newMargin ) { 3706 approx.margin(newMargin); 3707 return *this; 3708 } 3709 template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3710 ApproxMatcher& scale( T const& newScale ) { 3711 approx.scale(newScale); 3712 return *this; 3713 } 3714 3715 std::vector<T, AllocComp> const& m_comparator; 3716 mutable Catch::Detail::Approx approx = Catch::Detail::Approx::custom(); 3717 }; 3718 3719 template<typename T, typename AllocComp, typename AllocMatch> 3720 struct UnorderedEqualsMatcher : MatcherBase<std::vector<T, AllocMatch>> { 3721 UnorderedEqualsMatcher(std::vector<T, AllocComp> const& target) : m_target(target) {} 3722 bool match(std::vector<T, AllocMatch> const& vec) const override { 3723 if (m_target.size() != vec.size()) { 3724 return false; 3725 } 3726 return std::is_permutation(m_target.begin(), m_target.end(), vec.begin()); 3727 } 3728 3729 std::string describe() const override { 3730 return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target); 3731 } 3732 private: 3733 std::vector<T, AllocComp> const& m_target; 3734 }; 3735 3736 } // namespace Vector 3737 3738 // The following functions create the actual matcher objects. 3739 // This allows the types to be inferred 3740 3741 template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp> 3742 Vector::ContainsMatcher<T, AllocComp, AllocMatch> Contains( std::vector<T, AllocComp> const& comparator ) { 3743 return Vector::ContainsMatcher<T, AllocComp, AllocMatch>( comparator ); 3744 } 3745 3746 template<typename T, typename Alloc = std::allocator<T>> 3747 Vector::ContainsElementMatcher<T, Alloc> VectorContains( T const& comparator ) { 3748 return Vector::ContainsElementMatcher<T, Alloc>( comparator ); 3749 } 3750 3751 template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp> 3752 Vector::EqualsMatcher<T, AllocComp, AllocMatch> Equals( std::vector<T, AllocComp> const& comparator ) { 3753 return Vector::EqualsMatcher<T, AllocComp, AllocMatch>( comparator ); 3754 } 3755 3756 template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp> 3757 Vector::ApproxMatcher<T, AllocComp, AllocMatch> Approx( std::vector<T, AllocComp> const& comparator ) { 3758 return Vector::ApproxMatcher<T, AllocComp, AllocMatch>( comparator ); 3759 } 3760 3761 template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp> 3762 Vector::UnorderedEqualsMatcher<T, AllocComp, AllocMatch> UnorderedEquals(std::vector<T, AllocComp> const& target) { 3763 return Vector::UnorderedEqualsMatcher<T, AllocComp, AllocMatch>( target ); 3764 } 3765 3766 } // namespace Matchers 3767 } // namespace Catch 3768 3769 // end catch_matchers_vector.h 3770 namespace Catch { 3771 3772 template<typename ArgT, typename MatcherT> 3773 class MatchExpr : public ITransientExpression { 3774 ArgT const& m_arg; 3775 MatcherT m_matcher; 3776 StringRef m_matcherString; 3777 public: 3778 MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString ) 3779 : ITransientExpression{ true, matcher.match( arg ) }, 3780 m_arg( arg ), 3781 m_matcher( matcher ), 3782 m_matcherString( matcherString ) 3783 {} 3784 3785 void streamReconstructedExpression( std::ostream &os ) const override { 3786 auto matcherAsString = m_matcher.toString(); 3787 os << Catch::Detail::stringify( m_arg ) << ' '; 3788 if( matcherAsString == Detail::unprintableString ) 3789 os << m_matcherString; 3790 else 3791 os << matcherAsString; 3792 } 3793 }; 3794 3795 using StringMatcher = Matchers::Impl::MatcherBase<std::string>; 3796 3797 void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString ); 3798 3799 template<typename ArgT, typename MatcherT> 3800 auto makeMatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString ) -> MatchExpr<ArgT, MatcherT> { 3801 return MatchExpr<ArgT, MatcherT>( arg, matcher, matcherString ); 3802 } 3803 3804 } // namespace Catch 3805 3806 /////////////////////////////////////////////////////////////////////////////// 3807 #define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ 3808 do { \ 3809 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ 3810 INTERNAL_CATCH_TRY { \ 3811 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher, #matcher##_catch_sr ) ); \ 3812 } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ 3813 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 3814 } while( false ) 3815 3816 /////////////////////////////////////////////////////////////////////////////// 3817 #define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \ 3818 do { \ 3819 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ 3820 if( catchAssertionHandler.allowThrows() ) \ 3821 try { \ 3822 static_cast<void>(__VA_ARGS__ ); \ 3823 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 3824 } \ 3825 catch( exceptionType const& ex ) { \ 3826 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( ex, matcher, #matcher##_catch_sr ) ); \ 3827 } \ 3828 catch( ... ) { \ 3829 catchAssertionHandler.handleUnexpectedInflightException(); \ 3830 } \ 3831 else \ 3832 catchAssertionHandler.handleThrowingCallSkipped(); \ 3833 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 3834 } while( false ) 3835 3836 // end catch_capture_matchers.h 3837 #endif 3838 // start catch_generators.hpp 3839 3840 // start catch_interfaces_generatortracker.h 3841 3842 3843 #include <memory> 3844 3845 namespace Catch { 3846 3847 namespace Generators { 3848 class GeneratorUntypedBase { 3849 public: 3850 GeneratorUntypedBase() = default; 3851 virtual ~GeneratorUntypedBase(); 3852 // Attempts to move the generator to the next element 3853 // 3854 // Returns true iff the move succeeded (and a valid element 3855 // can be retrieved). 3856 virtual bool next() = 0; 3857 }; 3858 using GeneratorBasePtr = std::unique_ptr<GeneratorUntypedBase>; 3859 3860 } // namespace Generators 3861 3862 struct IGeneratorTracker { 3863 virtual ~IGeneratorTracker(); 3864 virtual auto hasGenerator() const -> bool = 0; 3865 virtual auto getGenerator() const -> Generators::GeneratorBasePtr const& = 0; 3866 virtual void setGenerator( Generators::GeneratorBasePtr&& generator ) = 0; 3867 }; 3868 3869 } // namespace Catch 3870 3871 // end catch_interfaces_generatortracker.h 3872 // start catch_enforce.h 3873 3874 #include <exception> 3875 3876 namespace Catch { 3877 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 3878 template <typename Ex> 3879 [[noreturn]] 3880 void throw_exception(Ex const& e) { 3881 throw e; 3882 } 3883 #else // ^^ Exceptions are enabled // Exceptions are disabled vv 3884 [[noreturn]] 3885 void throw_exception(std::exception const& e); 3886 #endif 3887 3888 [[noreturn]] 3889 void throw_logic_error(std::string const& msg); 3890 [[noreturn]] 3891 void throw_domain_error(std::string const& msg); 3892 [[noreturn]] 3893 void throw_runtime_error(std::string const& msg); 3894 3895 } // namespace Catch; 3896 3897 #define CATCH_MAKE_MSG(...) \ 3898 (Catch::ReusableStringStream() << __VA_ARGS__).str() 3899 3900 #define CATCH_INTERNAL_ERROR(...) \ 3901 Catch::throw_logic_error(CATCH_MAKE_MSG( CATCH_INTERNAL_LINEINFO << ": Internal Catch2 error: " << __VA_ARGS__)) 3902 3903 #define CATCH_ERROR(...) \ 3904 Catch::throw_domain_error(CATCH_MAKE_MSG( __VA_ARGS__ )) 3905 3906 #define CATCH_RUNTIME_ERROR(...) \ 3907 Catch::throw_runtime_error(CATCH_MAKE_MSG( __VA_ARGS__ )) 3908 3909 #define CATCH_ENFORCE( condition, ... ) \ 3910 do{ if( !(condition) ) CATCH_ERROR( __VA_ARGS__ ); } while(false) 3911 3912 // end catch_enforce.h 3913 #include <memory> 3914 #include <vector> 3915 #include <cassert> 3916 3917 #include <utility> 3918 #include <exception> 3919 3920 namespace Catch { 3921 3922 class GeneratorException : public std::exception { 3923 const char* const m_msg = ""; 3924 3925 public: 3926 GeneratorException(const char* msg): 3927 m_msg(msg) 3928 {} 3929 3930 const char* what() const noexcept override final; 3931 }; 3932 3933 namespace Generators { 3934 3935 // !TBD move this into its own location? 3936 namespace pf{ 3937 template<typename T, typename... Args> 3938 std::unique_ptr<T> make_unique( Args&&... args ) { 3939 return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); 3940 } 3941 } 3942 3943 template<typename T> 3944 struct IGenerator : GeneratorUntypedBase { 3945 virtual ~IGenerator() = default; 3946 3947 // Returns the current element of the generator 3948 // 3949 // \Precondition The generator is either freshly constructed, 3950 // or the last call to `next()` returned true 3951 virtual T const& get() const = 0; 3952 using type = T; 3953 }; 3954 3955 template<typename T> 3956 class SingleValueGenerator final : public IGenerator<T> { 3957 T m_value; 3958 public: 3959 SingleValueGenerator(T&& value) : m_value(std::move(value)) {} 3960 3961 T const& get() const override { 3962 return m_value; 3963 } 3964 bool next() override { 3965 return false; 3966 } 3967 }; 3968 3969 template<typename T> 3970 class FixedValuesGenerator final : public IGenerator<T> { 3971 static_assert(!std::is_same<T, bool>::value, 3972 "FixedValuesGenerator does not support bools because of std::vector<bool>" 3973 "specialization, use SingleValue Generator instead."); 3974 std::vector<T> m_values; 3975 size_t m_idx = 0; 3976 public: 3977 FixedValuesGenerator( std::initializer_list<T> values ) : m_values( values ) {} 3978 3979 T const& get() const override { 3980 return m_values[m_idx]; 3981 } 3982 bool next() override { 3983 ++m_idx; 3984 return m_idx < m_values.size(); 3985 } 3986 }; 3987 3988 template <typename T> 3989 class GeneratorWrapper final { 3990 std::unique_ptr<IGenerator<T>> m_generator; 3991 public: 3992 GeneratorWrapper(std::unique_ptr<IGenerator<T>> generator): 3993 m_generator(std::move(generator)) 3994 {} 3995 T const& get() const { 3996 return m_generator->get(); 3997 } 3998 bool next() { 3999 return m_generator->next(); 4000 } 4001 }; 4002 4003 template <typename T> 4004 GeneratorWrapper<T> value(T&& value) { 4005 return GeneratorWrapper<T>(pf::make_unique<SingleValueGenerator<T>>(std::forward<T>(value))); 4006 } 4007 template <typename T> 4008 GeneratorWrapper<T> values(std::initializer_list<T> values) { 4009 return GeneratorWrapper<T>(pf::make_unique<FixedValuesGenerator<T>>(values)); 4010 } 4011 4012 template<typename T> 4013 class Generators : public IGenerator<T> { 4014 std::vector<GeneratorWrapper<T>> m_generators; 4015 size_t m_current = 0; 4016 4017 void populate(GeneratorWrapper<T>&& generator) { 4018 m_generators.emplace_back(std::move(generator)); 4019 } 4020 void populate(T&& val) { 4021 m_generators.emplace_back(value(std::forward<T>(val))); 4022 } 4023 template<typename U> 4024 void populate(U&& val) { 4025 populate(T(std::forward<U>(val))); 4026 } 4027 template<typename U, typename... Gs> 4028 void populate(U&& valueOrGenerator, Gs &&... moreGenerators) { 4029 populate(std::forward<U>(valueOrGenerator)); 4030 populate(std::forward<Gs>(moreGenerators)...); 4031 } 4032 4033 public: 4034 template <typename... Gs> 4035 Generators(Gs &&... moreGenerators) { 4036 m_generators.reserve(sizeof...(Gs)); 4037 populate(std::forward<Gs>(moreGenerators)...); 4038 } 4039 4040 T const& get() const override { 4041 return m_generators[m_current].get(); 4042 } 4043 4044 bool next() override { 4045 if (m_current >= m_generators.size()) { 4046 return false; 4047 } 4048 const bool current_status = m_generators[m_current].next(); 4049 if (!current_status) { 4050 ++m_current; 4051 } 4052 return m_current < m_generators.size(); 4053 } 4054 }; 4055 4056 template<typename... Ts> 4057 GeneratorWrapper<std::tuple<Ts...>> table( std::initializer_list<std::tuple<typename std::decay<Ts>::type...>> tuples ) { 4058 return values<std::tuple<Ts...>>( tuples ); 4059 } 4060 4061 // Tag type to signal that a generator sequence should convert arguments to a specific type 4062 template <typename T> 4063 struct as {}; 4064 4065 template<typename T, typename... Gs> 4066 auto makeGenerators( GeneratorWrapper<T>&& generator, Gs &&... moreGenerators ) -> Generators<T> { 4067 return Generators<T>(std::move(generator), std::forward<Gs>(moreGenerators)...); 4068 } 4069 template<typename T> 4070 auto makeGenerators( GeneratorWrapper<T>&& generator ) -> Generators<T> { 4071 return Generators<T>(std::move(generator)); 4072 } 4073 template<typename T, typename... Gs> 4074 auto makeGenerators( T&& val, Gs &&... moreGenerators ) -> Generators<T> { 4075 return makeGenerators( value( std::forward<T>( val ) ), std::forward<Gs>( moreGenerators )... ); 4076 } 4077 template<typename T, typename U, typename... Gs> 4078 auto makeGenerators( as<T>, U&& val, Gs &&... moreGenerators ) -> Generators<T> { 4079 return makeGenerators( value( T( std::forward<U>( val ) ) ), std::forward<Gs>( moreGenerators )... ); 4080 } 4081 4082 auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker&; 4083 4084 template<typename L> 4085 // Note: The type after -> is weird, because VS2015 cannot parse 4086 // the expression used in the typedef inside, when it is in 4087 // return type. Yeah. 4088 auto generate( StringRef generatorName, SourceLineInfo const& lineInfo, L const& generatorExpression ) -> decltype(std::declval<decltype(generatorExpression())>().get()) { 4089 using UnderlyingType = typename decltype(generatorExpression())::type; 4090 4091 IGeneratorTracker& tracker = acquireGeneratorTracker( generatorName, lineInfo ); 4092 if (!tracker.hasGenerator()) { 4093 tracker.setGenerator(pf::make_unique<Generators<UnderlyingType>>(generatorExpression())); 4094 } 4095 4096 auto const& generator = static_cast<IGenerator<UnderlyingType> const&>( *tracker.getGenerator() ); 4097 return generator.get(); 4098 } 4099 4100 } // namespace Generators 4101 } // namespace Catch 4102 4103 #define GENERATE( ... ) \ 4104 Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \ 4105 CATCH_INTERNAL_LINEINFO, \ 4106 [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace) 4107 #define GENERATE_COPY( ... ) \ 4108 Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \ 4109 CATCH_INTERNAL_LINEINFO, \ 4110 [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace) 4111 #define GENERATE_REF( ... ) \ 4112 Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \ 4113 CATCH_INTERNAL_LINEINFO, \ 4114 [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace) 4115 4116 // end catch_generators.hpp 4117 // start catch_generators_generic.hpp 4118 4119 namespace Catch { 4120 namespace Generators { 4121 4122 template <typename T> 4123 class TakeGenerator : public IGenerator<T> { 4124 GeneratorWrapper<T> m_generator; 4125 size_t m_returned = 0; 4126 size_t m_target; 4127 public: 4128 TakeGenerator(size_t target, GeneratorWrapper<T>&& generator): 4129 m_generator(std::move(generator)), 4130 m_target(target) 4131 { 4132 assert(target != 0 && "Empty generators are not allowed"); 4133 } 4134 T const& get() const override { 4135 return m_generator.get(); 4136 } 4137 bool next() override { 4138 ++m_returned; 4139 if (m_returned >= m_target) { 4140 return false; 4141 } 4142 4143 const auto success = m_generator.next(); 4144 // If the underlying generator does not contain enough values 4145 // then we cut short as well 4146 if (!success) { 4147 m_returned = m_target; 4148 } 4149 return success; 4150 } 4151 }; 4152 4153 template <typename T> 4154 GeneratorWrapper<T> take(size_t target, GeneratorWrapper<T>&& generator) { 4155 return GeneratorWrapper<T>(pf::make_unique<TakeGenerator<T>>(target, std::move(generator))); 4156 } 4157 4158 template <typename T, typename Predicate> 4159 class FilterGenerator : public IGenerator<T> { 4160 GeneratorWrapper<T> m_generator; 4161 Predicate m_predicate; 4162 public: 4163 template <typename P = Predicate> 4164 FilterGenerator(P&& pred, GeneratorWrapper<T>&& generator): 4165 m_generator(std::move(generator)), 4166 m_predicate(std::forward<P>(pred)) 4167 { 4168 if (!m_predicate(m_generator.get())) { 4169 // It might happen that there are no values that pass the 4170 // filter. In that case we throw an exception. 4171 auto has_initial_value = next(); 4172 if (!has_initial_value) { 4173 Catch::throw_exception(GeneratorException("No valid value found in filtered generator")); 4174 } 4175 } 4176 } 4177 4178 T const& get() const override { 4179 return m_generator.get(); 4180 } 4181 4182 bool next() override { 4183 bool success = m_generator.next(); 4184 if (!success) { 4185 return false; 4186 } 4187 while (!m_predicate(m_generator.get()) && (success = m_generator.next()) == true); 4188 return success; 4189 } 4190 }; 4191 4192 template <typename T, typename Predicate> 4193 GeneratorWrapper<T> filter(Predicate&& pred, GeneratorWrapper<T>&& generator) { 4194 return GeneratorWrapper<T>(std::unique_ptr<IGenerator<T>>(pf::make_unique<FilterGenerator<T, Predicate>>(std::forward<Predicate>(pred), std::move(generator)))); 4195 } 4196 4197 template <typename T> 4198 class RepeatGenerator : public IGenerator<T> { 4199 static_assert(!std::is_same<T, bool>::value, 4200 "RepeatGenerator currently does not support bools" 4201 "because of std::vector<bool> specialization"); 4202 GeneratorWrapper<T> m_generator; 4203 mutable std::vector<T> m_returned; 4204 size_t m_target_repeats; 4205 size_t m_current_repeat = 0; 4206 size_t m_repeat_index = 0; 4207 public: 4208 RepeatGenerator(size_t repeats, GeneratorWrapper<T>&& generator): 4209 m_generator(std::move(generator)), 4210 m_target_repeats(repeats) 4211 { 4212 assert(m_target_repeats > 0 && "Repeat generator must repeat at least once"); 4213 } 4214 4215 T const& get() const override { 4216 if (m_current_repeat == 0) { 4217 m_returned.push_back(m_generator.get()); 4218 return m_returned.back(); 4219 } 4220 return m_returned[m_repeat_index]; 4221 } 4222 4223 bool next() override { 4224 // There are 2 basic cases: 4225 // 1) We are still reading the generator 4226 // 2) We are reading our own cache 4227 4228 // In the first case, we need to poke the underlying generator. 4229 // If it happily moves, we are left in that state, otherwise it is time to start reading from our cache 4230 if (m_current_repeat == 0) { 4231 const auto success = m_generator.next(); 4232 if (!success) { 4233 ++m_current_repeat; 4234 } 4235 return m_current_repeat < m_target_repeats; 4236 } 4237 4238 // In the second case, we need to move indices forward and check that we haven't run up against the end 4239 ++m_repeat_index; 4240 if (m_repeat_index == m_returned.size()) { 4241 m_repeat_index = 0; 4242 ++m_current_repeat; 4243 } 4244 return m_current_repeat < m_target_repeats; 4245 } 4246 }; 4247 4248 template <typename T> 4249 GeneratorWrapper<T> repeat(size_t repeats, GeneratorWrapper<T>&& generator) { 4250 return GeneratorWrapper<T>(pf::make_unique<RepeatGenerator<T>>(repeats, std::move(generator))); 4251 } 4252 4253 template <typename T, typename U, typename Func> 4254 class MapGenerator : public IGenerator<T> { 4255 // TBD: provide static assert for mapping function, for friendly error message 4256 GeneratorWrapper<U> m_generator; 4257 Func m_function; 4258 // To avoid returning dangling reference, we have to save the values 4259 T m_cache; 4260 public: 4261 template <typename F2 = Func> 4262 MapGenerator(F2&& function, GeneratorWrapper<U>&& generator) : 4263 m_generator(std::move(generator)), 4264 m_function(std::forward<F2>(function)), 4265 m_cache(m_function(m_generator.get())) 4266 {} 4267 4268 T const& get() const override { 4269 return m_cache; 4270 } 4271 bool next() override { 4272 const auto success = m_generator.next(); 4273 if (success) { 4274 m_cache = m_function(m_generator.get()); 4275 } 4276 return success; 4277 } 4278 }; 4279 4280 template <typename Func, typename U, typename T = FunctionReturnType<Func, U>> 4281 GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) { 4282 return GeneratorWrapper<T>( 4283 pf::make_unique<MapGenerator<T, U, Func>>(std::forward<Func>(function), std::move(generator)) 4284 ); 4285 } 4286 4287 template <typename T, typename U, typename Func> 4288 GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) { 4289 return GeneratorWrapper<T>( 4290 pf::make_unique<MapGenerator<T, U, Func>>(std::forward<Func>(function), std::move(generator)) 4291 ); 4292 } 4293 4294 template <typename T> 4295 class ChunkGenerator final : public IGenerator<std::vector<T>> { 4296 std::vector<T> m_chunk; 4297 size_t m_chunk_size; 4298 GeneratorWrapper<T> m_generator; 4299 bool m_used_up = false; 4300 public: 4301 ChunkGenerator(size_t size, GeneratorWrapper<T> generator) : 4302 m_chunk_size(size), m_generator(std::move(generator)) 4303 { 4304 m_chunk.reserve(m_chunk_size); 4305 if (m_chunk_size != 0) { 4306 m_chunk.push_back(m_generator.get()); 4307 for (size_t i = 1; i < m_chunk_size; ++i) { 4308 if (!m_generator.next()) { 4309 Catch::throw_exception(GeneratorException("Not enough values to initialize the first chunk")); 4310 } 4311 m_chunk.push_back(m_generator.get()); 4312 } 4313 } 4314 } 4315 std::vector<T> const& get() const override { 4316 return m_chunk; 4317 } 4318 bool next() override { 4319 m_chunk.clear(); 4320 for (size_t idx = 0; idx < m_chunk_size; ++idx) { 4321 if (!m_generator.next()) { 4322 return false; 4323 } 4324 m_chunk.push_back(m_generator.get()); 4325 } 4326 return true; 4327 } 4328 }; 4329 4330 template <typename T> 4331 GeneratorWrapper<std::vector<T>> chunk(size_t size, GeneratorWrapper<T>&& generator) { 4332 return GeneratorWrapper<std::vector<T>>( 4333 pf::make_unique<ChunkGenerator<T>>(size, std::move(generator)) 4334 ); 4335 } 4336 4337 } // namespace Generators 4338 } // namespace Catch 4339 4340 // end catch_generators_generic.hpp 4341 // start catch_generators_specific.hpp 4342 4343 // start catch_context.h 4344 4345 #include <memory> 4346 4347 namespace Catch { 4348 4349 struct IResultCapture; 4350 struct IRunner; 4351 struct IConfig; 4352 struct IMutableContext; 4353 4354 using IConfigPtr = std::shared_ptr<IConfig const>; 4355 4356 struct IContext 4357 { 4358 virtual ~IContext(); 4359 4360 virtual IResultCapture* getResultCapture() = 0; 4361 virtual IRunner* getRunner() = 0; 4362 virtual IConfigPtr const& getConfig() const = 0; 4363 }; 4364 4365 struct IMutableContext : IContext 4366 { 4367 virtual ~IMutableContext(); 4368 virtual void setResultCapture( IResultCapture* resultCapture ) = 0; 4369 virtual void setRunner( IRunner* runner ) = 0; 4370 virtual void setConfig( IConfigPtr const& config ) = 0; 4371 4372 private: 4373 static IMutableContext *currentContext; 4374 friend IMutableContext& getCurrentMutableContext(); 4375 friend void cleanUpContext(); 4376 static void createContext(); 4377 }; 4378 4379 inline IMutableContext& getCurrentMutableContext() 4380 { 4381 if( !IMutableContext::currentContext ) 4382 IMutableContext::createContext(); 4383 // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn) 4384 return *IMutableContext::currentContext; 4385 } 4386 4387 inline IContext& getCurrentContext() 4388 { 4389 return getCurrentMutableContext(); 4390 } 4391 4392 void cleanUpContext(); 4393 4394 class SimplePcg32; 4395 SimplePcg32& rng(); 4396 } 4397 4398 // end catch_context.h 4399 // start catch_interfaces_config.h 4400 4401 // start catch_option.hpp 4402 4403 namespace Catch { 4404 4405 // An optional type 4406 template<typename T> 4407 class Option { 4408 public: 4409 Option() : nullableValue( nullptr ) {} 4410 Option( T const& _value ) 4411 : nullableValue( new( storage ) T( _value ) ) 4412 {} 4413 Option( Option const& _other ) 4414 : nullableValue( _other ? new( storage ) T( *_other ) : nullptr ) 4415 {} 4416 4417 ~Option() { 4418 reset(); 4419 } 4420 4421 Option& operator= ( Option const& _other ) { 4422 if( &_other != this ) { 4423 reset(); 4424 if( _other ) 4425 nullableValue = new( storage ) T( *_other ); 4426 } 4427 return *this; 4428 } 4429 Option& operator = ( T const& _value ) { 4430 reset(); 4431 nullableValue = new( storage ) T( _value ); 4432 return *this; 4433 } 4434 4435 void reset() { 4436 if( nullableValue ) 4437 nullableValue->~T(); 4438 nullableValue = nullptr; 4439 } 4440 4441 T& operator*() { return *nullableValue; } 4442 T const& operator*() const { return *nullableValue; } 4443 T* operator->() { return nullableValue; } 4444 const T* operator->() const { return nullableValue; } 4445 4446 T valueOr( T const& defaultValue ) const { 4447 return nullableValue ? *nullableValue : defaultValue; 4448 } 4449 4450 bool some() const { return nullableValue != nullptr; } 4451 bool none() const { return nullableValue == nullptr; } 4452 4453 bool operator !() const { return nullableValue == nullptr; } 4454 explicit operator bool() const { 4455 return some(); 4456 } 4457 4458 private: 4459 T *nullableValue; 4460 alignas(alignof(T)) char storage[sizeof(T)]; 4461 }; 4462 4463 } // end namespace Catch 4464 4465 // end catch_option.hpp 4466 #include <chrono> 4467 #include <iosfwd> 4468 #include <string> 4469 #include <vector> 4470 #include <memory> 4471 4472 namespace Catch { 4473 4474 enum class Verbosity { 4475 Quiet = 0, 4476 Normal, 4477 High 4478 }; 4479 4480 struct WarnAbout { enum What { 4481 Nothing = 0x00, 4482 NoAssertions = 0x01, 4483 NoTests = 0x02 4484 }; }; 4485 4486 struct ShowDurations { enum OrNot { 4487 DefaultForReporter, 4488 Always, 4489 Never 4490 }; }; 4491 struct RunTests { enum InWhatOrder { 4492 InDeclarationOrder, 4493 InLexicographicalOrder, 4494 InRandomOrder 4495 }; }; 4496 struct UseColour { enum YesOrNo { 4497 Auto, 4498 Yes, 4499 No 4500 }; }; 4501 struct WaitForKeypress { enum When { 4502 Never, 4503 BeforeStart = 1, 4504 BeforeExit = 2, 4505 BeforeStartAndExit = BeforeStart | BeforeExit 4506 }; }; 4507 4508 class TestSpec; 4509 4510 struct IConfig : NonCopyable { 4511 4512 virtual ~IConfig(); 4513 4514 virtual bool allowThrows() const = 0; 4515 virtual std::ostream& stream() const = 0; 4516 virtual std::string name() const = 0; 4517 virtual bool includeSuccessfulResults() const = 0; 4518 virtual bool shouldDebugBreak() const = 0; 4519 virtual bool warnAboutMissingAssertions() const = 0; 4520 virtual bool warnAboutNoTests() const = 0; 4521 virtual int abortAfter() const = 0; 4522 virtual bool showInvisibles() const = 0; 4523 virtual ShowDurations::OrNot showDurations() const = 0; 4524 virtual double minDuration() const = 0; 4525 virtual TestSpec const& testSpec() const = 0; 4526 virtual bool hasTestFilters() const = 0; 4527 virtual std::vector<std::string> const& getTestsOrTags() const = 0; 4528 virtual RunTests::InWhatOrder runOrder() const = 0; 4529 virtual unsigned int rngSeed() const = 0; 4530 virtual UseColour::YesOrNo useColour() const = 0; 4531 virtual std::vector<std::string> const& getSectionsToRun() const = 0; 4532 virtual Verbosity verbosity() const = 0; 4533 4534 virtual bool benchmarkNoAnalysis() const = 0; 4535 virtual int benchmarkSamples() const = 0; 4536 virtual double benchmarkConfidenceInterval() const = 0; 4537 virtual unsigned int benchmarkResamples() const = 0; 4538 virtual std::chrono::milliseconds benchmarkWarmupTime() const = 0; 4539 }; 4540 4541 using IConfigPtr = std::shared_ptr<IConfig const>; 4542 } 4543 4544 // end catch_interfaces_config.h 4545 // start catch_random_number_generator.h 4546 4547 #include <cstdint> 4548 4549 namespace Catch { 4550 4551 // This is a simple implementation of C++11 Uniform Random Number 4552 // Generator. It does not provide all operators, because Catch2 4553 // does not use it, but it should behave as expected inside stdlib's 4554 // distributions. 4555 // The implementation is based on the PCG family (http://pcg-random.org) 4556 class SimplePcg32 { 4557 using state_type = std::uint64_t; 4558 public: 4559 using result_type = std::uint32_t; 4560 static constexpr result_type (min)() { 4561 return 0; 4562 } 4563 static constexpr result_type (max)() { 4564 return static_cast<result_type>(-1); 4565 } 4566 4567 // Provide some default initial state for the default constructor 4568 SimplePcg32():SimplePcg32(0xed743cc4U) {} 4569 4570 explicit SimplePcg32(result_type seed_); 4571 4572 void seed(result_type seed_); 4573 void discard(uint64_t skip); 4574 4575 result_type operator()(); 4576 4577 private: 4578 friend bool operator==(SimplePcg32 const& lhs, SimplePcg32 const& rhs); 4579 friend bool operator!=(SimplePcg32 const& lhs, SimplePcg32 const& rhs); 4580 4581 // In theory we also need operator<< and operator>> 4582 // In practice we do not use them, so we will skip them for now 4583 4584 std::uint64_t m_state; 4585 // This part of the state determines which "stream" of the numbers 4586 // is chosen -- we take it as a constant for Catch2, so we only 4587 // need to deal with seeding the main state. 4588 // Picked by reading 8 bytes from `/dev/random` :-) 4589 static const std::uint64_t s_inc = (0x13ed0cc53f939476ULL << 1ULL) | 1ULL; 4590 }; 4591 4592 } // end namespace Catch 4593 4594 // end catch_random_number_generator.h 4595 #include <random> 4596 4597 namespace Catch { 4598 namespace Generators { 4599 4600 template <typename Float> 4601 class RandomFloatingGenerator final : public IGenerator<Float> { 4602 Catch::SimplePcg32& m_rng; 4603 std::uniform_real_distribution<Float> m_dist; 4604 Float m_current_number; 4605 public: 4606 4607 RandomFloatingGenerator(Float a, Float b): 4608 m_rng(rng()), 4609 m_dist(a, b) { 4610 static_cast<void>(next()); 4611 } 4612 4613 Float const& get() const override { 4614 return m_current_number; 4615 } 4616 bool next() override { 4617 m_current_number = m_dist(m_rng); 4618 return true; 4619 } 4620 }; 4621 4622 template <typename Integer> 4623 class RandomIntegerGenerator final : public IGenerator<Integer> { 4624 Catch::SimplePcg32& m_rng; 4625 std::uniform_int_distribution<Integer> m_dist; 4626 Integer m_current_number; 4627 public: 4628 4629 RandomIntegerGenerator(Integer a, Integer b): 4630 m_rng(rng()), 4631 m_dist(a, b) { 4632 static_cast<void>(next()); 4633 } 4634 4635 Integer const& get() const override { 4636 return m_current_number; 4637 } 4638 bool next() override { 4639 m_current_number = m_dist(m_rng); 4640 return true; 4641 } 4642 }; 4643 4644 // TODO: Ideally this would be also constrained against the various char types, 4645 // but I don't expect users to run into that in practice. 4646 template <typename T> 4647 typename std::enable_if<std::is_integral<T>::value && !std::is_same<T, bool>::value, 4648 GeneratorWrapper<T>>::type 4649 random(T a, T b) { 4650 return GeneratorWrapper<T>( 4651 pf::make_unique<RandomIntegerGenerator<T>>(a, b) 4652 ); 4653 } 4654 4655 template <typename T> 4656 typename std::enable_if<std::is_floating_point<T>::value, 4657 GeneratorWrapper<T>>::type 4658 random(T a, T b) { 4659 return GeneratorWrapper<T>( 4660 pf::make_unique<RandomFloatingGenerator<T>>(a, b) 4661 ); 4662 } 4663 4664 template <typename T> 4665 class RangeGenerator final : public IGenerator<T> { 4666 T m_current; 4667 T m_end; 4668 T m_step; 4669 bool m_positive; 4670 4671 public: 4672 RangeGenerator(T const& start, T const& end, T const& step): 4673 m_current(start), 4674 m_end(end), 4675 m_step(step), 4676 m_positive(m_step > T(0)) 4677 { 4678 assert(m_current != m_end && "Range start and end cannot be equal"); 4679 assert(m_step != T(0) && "Step size cannot be zero"); 4680 assert(((m_positive && m_current <= m_end) || (!m_positive && m_current >= m_end)) && "Step moves away from end"); 4681 } 4682 4683 RangeGenerator(T const& start, T const& end): 4684 RangeGenerator(start, end, (start < end) ? T(1) : T(-1)) 4685 {} 4686 4687 T const& get() const override { 4688 return m_current; 4689 } 4690 4691 bool next() override { 4692 m_current += m_step; 4693 return (m_positive) ? (m_current < m_end) : (m_current > m_end); 4694 } 4695 }; 4696 4697 template <typename T> 4698 GeneratorWrapper<T> range(T const& start, T const& end, T const& step) { 4699 static_assert(std::is_arithmetic<T>::value && !std::is_same<T, bool>::value, "Type must be numeric"); 4700 return GeneratorWrapper<T>(pf::make_unique<RangeGenerator<T>>(start, end, step)); 4701 } 4702 4703 template <typename T> 4704 GeneratorWrapper<T> range(T const& start, T const& end) { 4705 static_assert(std::is_integral<T>::value && !std::is_same<T, bool>::value, "Type must be an integer"); 4706 return GeneratorWrapper<T>(pf::make_unique<RangeGenerator<T>>(start, end)); 4707 } 4708 4709 template <typename T> 4710 class IteratorGenerator final : public IGenerator<T> { 4711 static_assert(!std::is_same<T, bool>::value, 4712 "IteratorGenerator currently does not support bools" 4713 "because of std::vector<bool> specialization"); 4714 4715 std::vector<T> m_elems; 4716 size_t m_current = 0; 4717 public: 4718 template <typename InputIterator, typename InputSentinel> 4719 IteratorGenerator(InputIterator first, InputSentinel last):m_elems(first, last) { 4720 if (m_elems.empty()) { 4721 Catch::throw_exception(GeneratorException("IteratorGenerator received no valid values")); 4722 } 4723 } 4724 4725 T const& get() const override { 4726 return m_elems[m_current]; 4727 } 4728 4729 bool next() override { 4730 ++m_current; 4731 return m_current != m_elems.size(); 4732 } 4733 }; 4734 4735 template <typename InputIterator, 4736 typename InputSentinel, 4737 typename ResultType = typename std::iterator_traits<InputIterator>::value_type> 4738 GeneratorWrapper<ResultType> from_range(InputIterator from, InputSentinel to) { 4739 return GeneratorWrapper<ResultType>(pf::make_unique<IteratorGenerator<ResultType>>(from, to)); 4740 } 4741 4742 template <typename Container, 4743 typename ResultType = typename Container::value_type> 4744 GeneratorWrapper<ResultType> from_range(Container const& cnt) { 4745 return GeneratorWrapper<ResultType>(pf::make_unique<IteratorGenerator<ResultType>>(cnt.begin(), cnt.end())); 4746 } 4747 4748 } // namespace Generators 4749 } // namespace Catch 4750 4751 // end catch_generators_specific.hpp 4752 4753 // These files are included here so the single_include script doesn't put them 4754 // in the conditionally compiled sections 4755 // start catch_test_case_info.h 4756 4757 #include <string> 4758 #include <vector> 4759 #include <memory> 4760 4761 #ifdef __clang__ 4762 #pragma clang diagnostic push 4763 #pragma clang diagnostic ignored "-Wpadded" 4764 #endif 4765 4766 namespace Catch { 4767 4768 struct ITestInvoker; 4769 4770 struct TestCaseInfo { 4771 enum SpecialProperties{ 4772 None = 0, 4773 IsHidden = 1 << 1, 4774 ShouldFail = 1 << 2, 4775 MayFail = 1 << 3, 4776 Throws = 1 << 4, 4777 NonPortable = 1 << 5, 4778 Benchmark = 1 << 6 4779 }; 4780 4781 TestCaseInfo( std::string const& _name, 4782 std::string const& _className, 4783 std::string const& _description, 4784 std::vector<std::string> const& _tags, 4785 SourceLineInfo const& _lineInfo ); 4786 4787 friend void setTags( TestCaseInfo& testCaseInfo, std::vector<std::string> tags ); 4788 4789 bool isHidden() const; 4790 bool throws() const; 4791 bool okToFail() const; 4792 bool expectedToFail() const; 4793 4794 std::string tagsAsString() const; 4795 4796 std::string name; 4797 std::string className; 4798 std::string description; 4799 std::vector<std::string> tags; 4800 std::vector<std::string> lcaseTags; 4801 SourceLineInfo lineInfo; 4802 SpecialProperties properties; 4803 }; 4804 4805 class TestCase : public TestCaseInfo { 4806 public: 4807 4808 TestCase( ITestInvoker* testCase, TestCaseInfo&& info ); 4809 4810 TestCase withName( std::string const& _newName ) const; 4811 4812 void invoke() const; 4813 4814 TestCaseInfo const& getTestCaseInfo() const; 4815 4816 bool operator == ( TestCase const& other ) const; 4817 bool operator < ( TestCase const& other ) const; 4818 4819 private: 4820 std::shared_ptr<ITestInvoker> test; 4821 }; 4822 4823 TestCase makeTestCase( ITestInvoker* testCase, 4824 std::string const& className, 4825 NameAndTags const& nameAndTags, 4826 SourceLineInfo const& lineInfo ); 4827 } 4828 4829 #ifdef __clang__ 4830 #pragma clang diagnostic pop 4831 #endif 4832 4833 // end catch_test_case_info.h 4834 // start catch_interfaces_runner.h 4835 4836 namespace Catch { 4837 4838 struct IRunner { 4839 virtual ~IRunner(); 4840 virtual bool aborting() const = 0; 4841 }; 4842 } 4843 4844 // end catch_interfaces_runner.h 4845 4846 #ifdef __OBJC__ 4847 // start catch_objc.hpp 4848 4849 #import <objc/runtime.h> 4850 4851 #include <string> 4852 4853 // NB. Any general catch headers included here must be included 4854 // in catch.hpp first to make sure they are included by the single 4855 // header for non obj-usage 4856 4857 /////////////////////////////////////////////////////////////////////////////// 4858 // This protocol is really only here for (self) documenting purposes, since 4859 // all its methods are optional. 4860 @protocol OcFixture 4861 4862 @optional 4863 4864 -(void) setUp; 4865 -(void) tearDown; 4866 4867 @end 4868 4869 namespace Catch { 4870 4871 class OcMethod : public ITestInvoker { 4872 4873 public: 4874 OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} 4875 4876 virtual void invoke() const { 4877 id obj = [[m_cls alloc] init]; 4878 4879 performOptionalSelector( obj, @selector(setUp) ); 4880 performOptionalSelector( obj, m_sel ); 4881 performOptionalSelector( obj, @selector(tearDown) ); 4882 4883 arcSafeRelease( obj ); 4884 } 4885 private: 4886 virtual ~OcMethod() {} 4887 4888 Class m_cls; 4889 SEL m_sel; 4890 }; 4891 4892 namespace Detail{ 4893 4894 inline std::string getAnnotation( Class cls, 4895 std::string const& annotationName, 4896 std::string const& testCaseName ) { 4897 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()]; 4898 SEL sel = NSSelectorFromString( selStr ); 4899 arcSafeRelease( selStr ); 4900 id value = performOptionalSelector( cls, sel ); 4901 if( value ) 4902 return [(NSString*)value UTF8String]; 4903 return ""; 4904 } 4905 } 4906 4907 inline std::size_t registerTestMethods() { 4908 std::size_t noTestMethods = 0; 4909 int noClasses = objc_getClassList( nullptr, 0 ); 4910 4911 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); 4912 objc_getClassList( classes, noClasses ); 4913 4914 for( int c = 0; c < noClasses; c++ ) { 4915 Class cls = classes[c]; 4916 { 4917 u_int count; 4918 Method* methods = class_copyMethodList( cls, &count ); 4919 for( u_int m = 0; m < count ; m++ ) { 4920 SEL selector = method_getName(methods[m]); 4921 std::string methodName = sel_getName(selector); 4922 if( startsWith( methodName, "Catch_TestCase_" ) ) { 4923 std::string testCaseName = methodName.substr( 15 ); 4924 std::string name = Detail::getAnnotation( cls, "Name", testCaseName ); 4925 std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); 4926 const char* className = class_getName( cls ); 4927 4928 getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, NameAndTags( name.c_str(), desc.c_str() ), SourceLineInfo("",0) ) ); 4929 noTestMethods++; 4930 } 4931 } 4932 free(methods); 4933 } 4934 } 4935 return noTestMethods; 4936 } 4937 4938 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 4939 4940 namespace Matchers { 4941 namespace Impl { 4942 namespace NSStringMatchers { 4943 4944 struct StringHolder : MatcherBase<NSString*>{ 4945 StringHolder( NSString* substr ) : m_substr( [substr copy] ){} 4946 StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){} 4947 StringHolder() { 4948 arcSafeRelease( m_substr ); 4949 } 4950 4951 bool match( NSString* str ) const override { 4952 return false; 4953 } 4954 4955 NSString* CATCH_ARC_STRONG m_substr; 4956 }; 4957 4958 struct Equals : StringHolder { 4959 Equals( NSString* substr ) : StringHolder( substr ){} 4960 4961 bool match( NSString* str ) const override { 4962 return (str != nil || m_substr == nil ) && 4963 [str isEqualToString:m_substr]; 4964 } 4965 4966 std::string describe() const override { 4967 return "equals string: " + Catch::Detail::stringify( m_substr ); 4968 } 4969 }; 4970 4971 struct Contains : StringHolder { 4972 Contains( NSString* substr ) : StringHolder( substr ){} 4973 4974 bool match( NSString* str ) const override { 4975 return (str != nil || m_substr == nil ) && 4976 [str rangeOfString:m_substr].location != NSNotFound; 4977 } 4978 4979 std::string describe() const override { 4980 return "contains string: " + Catch::Detail::stringify( m_substr ); 4981 } 4982 }; 4983 4984 struct StartsWith : StringHolder { 4985 StartsWith( NSString* substr ) : StringHolder( substr ){} 4986 4987 bool match( NSString* str ) const override { 4988 return (str != nil || m_substr == nil ) && 4989 [str rangeOfString:m_substr].location == 0; 4990 } 4991 4992 std::string describe() const override { 4993 return "starts with: " + Catch::Detail::stringify( m_substr ); 4994 } 4995 }; 4996 struct EndsWith : StringHolder { 4997 EndsWith( NSString* substr ) : StringHolder( substr ){} 4998 4999 bool match( NSString* str ) const override { 5000 return (str != nil || m_substr == nil ) && 5001 [str rangeOfString:m_substr].location == [str length] - [m_substr length]; 5002 } 5003 5004 std::string describe() const override { 5005 return "ends with: " + Catch::Detail::stringify( m_substr ); 5006 } 5007 }; 5008 5009 } // namespace NSStringMatchers 5010 } // namespace Impl 5011 5012 inline Impl::NSStringMatchers::Equals 5013 Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); } 5014 5015 inline Impl::NSStringMatchers::Contains 5016 Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); } 5017 5018 inline Impl::NSStringMatchers::StartsWith 5019 StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); } 5020 5021 inline Impl::NSStringMatchers::EndsWith 5022 EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); } 5023 5024 } // namespace Matchers 5025 5026 using namespace Matchers; 5027 5028 #endif // CATCH_CONFIG_DISABLE_MATCHERS 5029 5030 } // namespace Catch 5031 5032 /////////////////////////////////////////////////////////////////////////////// 5033 #define OC_MAKE_UNIQUE_NAME( root, uniqueSuffix ) root##uniqueSuffix 5034 #define OC_TEST_CASE2( name, desc, uniqueSuffix ) \ 5035 +(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Name_test_, uniqueSuffix ) \ 5036 { \ 5037 return @ name; \ 5038 } \ 5039 +(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Description_test_, uniqueSuffix ) \ 5040 { \ 5041 return @ desc; \ 5042 } \ 5043 -(void) OC_MAKE_UNIQUE_NAME( Catch_TestCase_test_, uniqueSuffix ) 5044 5045 #define OC_TEST_CASE( name, desc ) OC_TEST_CASE2( name, desc, __LINE__ ) 5046 5047 // end catch_objc.hpp 5048 #endif 5049 5050 // Benchmarking needs the externally-facing parts of reporters to work 5051 #if defined(CATCH_CONFIG_EXTERNAL_INTERFACES) || defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 5052 // start catch_external_interfaces.h 5053 5054 // start catch_reporter_bases.hpp 5055 5056 // start catch_interfaces_reporter.h 5057 5058 // start catch_config.hpp 5059 5060 // start catch_test_spec_parser.h 5061 5062 #ifdef __clang__ 5063 #pragma clang diagnostic push 5064 #pragma clang diagnostic ignored "-Wpadded" 5065 #endif 5066 5067 // start catch_test_spec.h 5068 5069 #ifdef __clang__ 5070 #pragma clang diagnostic push 5071 #pragma clang diagnostic ignored "-Wpadded" 5072 #endif 5073 5074 // start catch_wildcard_pattern.h 5075 5076 namespace Catch 5077 { 5078 class WildcardPattern { 5079 enum WildcardPosition { 5080 NoWildcard = 0, 5081 WildcardAtStart = 1, 5082 WildcardAtEnd = 2, 5083 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd 5084 }; 5085 5086 public: 5087 5088 WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity ); 5089 virtual ~WildcardPattern() = default; 5090 virtual bool matches( std::string const& str ) const; 5091 5092 private: 5093 std::string normaliseString( std::string const& str ) const; 5094 CaseSensitive::Choice m_caseSensitivity; 5095 WildcardPosition m_wildcard = NoWildcard; 5096 std::string m_pattern; 5097 }; 5098 } 5099 5100 // end catch_wildcard_pattern.h 5101 #include <string> 5102 #include <vector> 5103 #include <memory> 5104 5105 namespace Catch { 5106 5107 struct IConfig; 5108 5109 class TestSpec { 5110 class Pattern { 5111 public: 5112 explicit Pattern( std::string const& name ); 5113 virtual ~Pattern(); 5114 virtual bool matches( TestCaseInfo const& testCase ) const = 0; 5115 std::string const& name() const; 5116 private: 5117 std::string const m_name; 5118 }; 5119 using PatternPtr = std::shared_ptr<Pattern>; 5120 5121 class NamePattern : public Pattern { 5122 public: 5123 explicit NamePattern( std::string const& name, std::string const& filterString ); 5124 bool matches( TestCaseInfo const& testCase ) const override; 5125 private: 5126 WildcardPattern m_wildcardPattern; 5127 }; 5128 5129 class TagPattern : public Pattern { 5130 public: 5131 explicit TagPattern( std::string const& tag, std::string const& filterString ); 5132 bool matches( TestCaseInfo const& testCase ) const override; 5133 private: 5134 std::string m_tag; 5135 }; 5136 5137 class ExcludedPattern : public Pattern { 5138 public: 5139 explicit ExcludedPattern( PatternPtr const& underlyingPattern ); 5140 bool matches( TestCaseInfo const& testCase ) const override; 5141 private: 5142 PatternPtr m_underlyingPattern; 5143 }; 5144 5145 struct Filter { 5146 std::vector<PatternPtr> m_patterns; 5147 5148 bool matches( TestCaseInfo const& testCase ) const; 5149 std::string name() const; 5150 }; 5151 5152 public: 5153 struct FilterMatch { 5154 std::string name; 5155 std::vector<TestCase const*> tests; 5156 }; 5157 using Matches = std::vector<FilterMatch>; 5158 using vectorStrings = std::vector<std::string>; 5159 5160 bool hasFilters() const; 5161 bool matches( TestCaseInfo const& testCase ) const; 5162 Matches matchesByFilter( std::vector<TestCase> const& testCases, IConfig const& config ) const; 5163 const vectorStrings & getInvalidArgs() const; 5164 5165 private: 5166 std::vector<Filter> m_filters; 5167 std::vector<std::string> m_invalidArgs; 5168 friend class TestSpecParser; 5169 }; 5170 } 5171 5172 #ifdef __clang__ 5173 #pragma clang diagnostic pop 5174 #endif 5175 5176 // end catch_test_spec.h 5177 // start catch_interfaces_tag_alias_registry.h 5178 5179 #include <string> 5180 5181 namespace Catch { 5182 5183 struct TagAlias; 5184 5185 struct ITagAliasRegistry { 5186 virtual ~ITagAliasRegistry(); 5187 // Nullptr if not present 5188 virtual TagAlias const* find( std::string const& alias ) const = 0; 5189 virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; 5190 5191 static ITagAliasRegistry const& get(); 5192 }; 5193 5194 } // end namespace Catch 5195 5196 // end catch_interfaces_tag_alias_registry.h 5197 namespace Catch { 5198 5199 class TestSpecParser { 5200 enum Mode{ None, Name, QuotedName, Tag, EscapedName }; 5201 Mode m_mode = None; 5202 Mode lastMode = None; 5203 bool m_exclusion = false; 5204 std::size_t m_pos = 0; 5205 std::size_t m_realPatternPos = 0; 5206 std::string m_arg; 5207 std::string m_substring; 5208 std::string m_patternName; 5209 std::vector<std::size_t> m_escapeChars; 5210 TestSpec::Filter m_currentFilter; 5211 TestSpec m_testSpec; 5212 ITagAliasRegistry const* m_tagAliases = nullptr; 5213 5214 public: 5215 TestSpecParser( ITagAliasRegistry const& tagAliases ); 5216 5217 TestSpecParser& parse( std::string const& arg ); 5218 TestSpec testSpec(); 5219 5220 private: 5221 bool visitChar( char c ); 5222 void startNewMode( Mode mode ); 5223 bool processNoneChar( char c ); 5224 void processNameChar( char c ); 5225 bool processOtherChar( char c ); 5226 void endMode(); 5227 void escape(); 5228 bool isControlChar( char c ) const; 5229 void saveLastMode(); 5230 void revertBackToLastMode(); 5231 void addFilter(); 5232 bool separate(); 5233 5234 // Handles common preprocessing of the pattern for name/tag patterns 5235 std::string preprocessPattern(); 5236 // Adds the current pattern as a test name 5237 void addNamePattern(); 5238 // Adds the current pattern as a tag 5239 void addTagPattern(); 5240 5241 inline void addCharToPattern(char c) { 5242 m_substring += c; 5243 m_patternName += c; 5244 m_realPatternPos++; 5245 } 5246 5247 }; 5248 TestSpec parseTestSpec( std::string const& arg ); 5249 5250 } // namespace Catch 5251 5252 #ifdef __clang__ 5253 #pragma clang diagnostic pop 5254 #endif 5255 5256 // end catch_test_spec_parser.h 5257 // Libstdc++ doesn't like incomplete classes for unique_ptr 5258 5259 #include <memory> 5260 #include <vector> 5261 #include <string> 5262 5263 #ifndef CATCH_CONFIG_CONSOLE_WIDTH 5264 #define CATCH_CONFIG_CONSOLE_WIDTH 80 5265 #endif 5266 5267 namespace Catch { 5268 5269 struct IStream; 5270 5271 struct ConfigData { 5272 bool listTests = false; 5273 bool listTags = false; 5274 bool listReporters = false; 5275 bool listTestNamesOnly = false; 5276 5277 bool showSuccessfulTests = false; 5278 bool shouldDebugBreak = false; 5279 bool noThrow = false; 5280 bool showHelp = false; 5281 bool showInvisibles = false; 5282 bool filenamesAsTags = false; 5283 bool libIdentify = false; 5284 5285 int abortAfter = -1; 5286 unsigned int rngSeed = 0; 5287 5288 bool benchmarkNoAnalysis = false; 5289 unsigned int benchmarkSamples = 100; 5290 double benchmarkConfidenceInterval = 0.95; 5291 unsigned int benchmarkResamples = 100000; 5292 std::chrono::milliseconds::rep benchmarkWarmupTime = 100; 5293 5294 Verbosity verbosity = Verbosity::Normal; 5295 WarnAbout::What warnings = WarnAbout::Nothing; 5296 ShowDurations::OrNot showDurations = ShowDurations::DefaultForReporter; 5297 double minDuration = -1; 5298 RunTests::InWhatOrder runOrder = RunTests::InDeclarationOrder; 5299 UseColour::YesOrNo useColour = UseColour::Auto; 5300 WaitForKeypress::When waitForKeypress = WaitForKeypress::Never; 5301 5302 std::string outputFilename; 5303 std::string name; 5304 std::string processName; 5305 #ifndef CATCH_CONFIG_DEFAULT_REPORTER 5306 #define CATCH_CONFIG_DEFAULT_REPORTER "console" 5307 #endif 5308 std::string reporterName = CATCH_CONFIG_DEFAULT_REPORTER; 5309 #undef CATCH_CONFIG_DEFAULT_REPORTER 5310 5311 std::vector<std::string> testsOrTags; 5312 std::vector<std::string> sectionsToRun; 5313 }; 5314 5315 class Config : public IConfig { 5316 public: 5317 5318 Config() = default; 5319 Config( ConfigData const& data ); 5320 virtual ~Config() = default; 5321 5322 std::string const& getFilename() const; 5323 5324 bool listTests() const; 5325 bool listTestNamesOnly() const; 5326 bool listTags() const; 5327 bool listReporters() const; 5328 5329 std::string getProcessName() const; 5330 std::string const& getReporterName() const; 5331 5332 std::vector<std::string> const& getTestsOrTags() const override; 5333 std::vector<std::string> const& getSectionsToRun() const override; 5334 5335 TestSpec const& testSpec() const override; 5336 bool hasTestFilters() const override; 5337 5338 bool showHelp() const; 5339 5340 // IConfig interface 5341 bool allowThrows() const override; 5342 std::ostream& stream() const override; 5343 std::string name() const override; 5344 bool includeSuccessfulResults() const override; 5345 bool warnAboutMissingAssertions() const override; 5346 bool warnAboutNoTests() const override; 5347 ShowDurations::OrNot showDurations() const override; 5348 double minDuration() const override; 5349 RunTests::InWhatOrder runOrder() const override; 5350 unsigned int rngSeed() const override; 5351 UseColour::YesOrNo useColour() const override; 5352 bool shouldDebugBreak() const override; 5353 int abortAfter() const override; 5354 bool showInvisibles() const override; 5355 Verbosity verbosity() const override; 5356 bool benchmarkNoAnalysis() const override; 5357 int benchmarkSamples() const override; 5358 double benchmarkConfidenceInterval() const override; 5359 unsigned int benchmarkResamples() const override; 5360 std::chrono::milliseconds benchmarkWarmupTime() const override; 5361 5362 private: 5363 5364 IStream const* openStream(); 5365 ConfigData m_data; 5366 5367 std::unique_ptr<IStream const> m_stream; 5368 TestSpec m_testSpec; 5369 bool m_hasTestFilters = false; 5370 }; 5371 5372 } // end namespace Catch 5373 5374 // end catch_config.hpp 5375 // start catch_assertionresult.h 5376 5377 #include <string> 5378 5379 namespace Catch { 5380 5381 struct AssertionResultData 5382 { 5383 AssertionResultData() = delete; 5384 5385 AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression ); 5386 5387 std::string message; 5388 mutable std::string reconstructedExpression; 5389 LazyExpression lazyExpression; 5390 ResultWas::OfType resultType; 5391 5392 std::string reconstructExpression() const; 5393 }; 5394 5395 class AssertionResult { 5396 public: 5397 AssertionResult() = delete; 5398 AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); 5399 5400 bool isOk() const; 5401 bool succeeded() const; 5402 ResultWas::OfType getResultType() const; 5403 bool hasExpression() const; 5404 bool hasMessage() const; 5405 std::string getExpression() const; 5406 std::string getExpressionInMacro() const; 5407 bool hasExpandedExpression() const; 5408 std::string getExpandedExpression() const; 5409 std::string getMessage() const; 5410 SourceLineInfo getSourceInfo() const; 5411 StringRef getTestMacroName() const; 5412 5413 //protected: 5414 AssertionInfo m_info; 5415 AssertionResultData m_resultData; 5416 }; 5417 5418 } // end namespace Catch 5419 5420 // end catch_assertionresult.h 5421 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 5422 // start catch_estimate.hpp 5423 5424 // Statistics estimates 5425 5426 5427 namespace Catch { 5428 namespace Benchmark { 5429 template <typename Duration> 5430 struct Estimate { 5431 Duration point; 5432 Duration lower_bound; 5433 Duration upper_bound; 5434 double confidence_interval; 5435 5436 template <typename Duration2> 5437 operator Estimate<Duration2>() const { 5438 return { point, lower_bound, upper_bound, confidence_interval }; 5439 } 5440 }; 5441 } // namespace Benchmark 5442 } // namespace Catch 5443 5444 // end catch_estimate.hpp 5445 // start catch_outlier_classification.hpp 5446 5447 // Outlier information 5448 5449 namespace Catch { 5450 namespace Benchmark { 5451 struct OutlierClassification { 5452 int samples_seen = 0; 5453 int low_severe = 0; // more than 3 times IQR below Q1 5454 int low_mild = 0; // 1.5 to 3 times IQR below Q1 5455 int high_mild = 0; // 1.5 to 3 times IQR above Q3 5456 int high_severe = 0; // more than 3 times IQR above Q3 5457 5458 int total() const { 5459 return low_severe + low_mild + high_mild + high_severe; 5460 } 5461 }; 5462 } // namespace Benchmark 5463 } // namespace Catch 5464 5465 // end catch_outlier_classification.hpp 5466 5467 #include <iterator> 5468 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 5469 5470 #include <string> 5471 #include <iosfwd> 5472 #include <map> 5473 #include <set> 5474 #include <memory> 5475 #include <algorithm> 5476 5477 namespace Catch { 5478 5479 struct ReporterConfig { 5480 explicit ReporterConfig( IConfigPtr const& _fullConfig ); 5481 5482 ReporterConfig( IConfigPtr const& _fullConfig, std::ostream& _stream ); 5483 5484 std::ostream& stream() const; 5485 IConfigPtr fullConfig() const; 5486 5487 private: 5488 std::ostream* m_stream; 5489 IConfigPtr m_fullConfig; 5490 }; 5491 5492 struct ReporterPreferences { 5493 bool shouldRedirectStdOut = false; 5494 bool shouldReportAllAssertions = false; 5495 }; 5496 5497 template<typename T> 5498 struct LazyStat : Option<T> { 5499 LazyStat& operator=( T const& _value ) { 5500 Option<T>::operator=( _value ); 5501 used = false; 5502 return *this; 5503 } 5504 void reset() { 5505 Option<T>::reset(); 5506 used = false; 5507 } 5508 bool used = false; 5509 }; 5510 5511 struct TestRunInfo { 5512 TestRunInfo( std::string const& _name ); 5513 std::string name; 5514 }; 5515 struct GroupInfo { 5516 GroupInfo( std::string const& _name, 5517 std::size_t _groupIndex, 5518 std::size_t _groupsCount ); 5519 5520 std::string name; 5521 std::size_t groupIndex; 5522 std::size_t groupsCounts; 5523 }; 5524 5525 struct AssertionStats { 5526 AssertionStats( AssertionResult const& _assertionResult, 5527 std::vector<MessageInfo> const& _infoMessages, 5528 Totals const& _totals ); 5529 5530 AssertionStats( AssertionStats const& ) = default; 5531 AssertionStats( AssertionStats && ) = default; 5532 AssertionStats& operator = ( AssertionStats const& ) = delete; 5533 AssertionStats& operator = ( AssertionStats && ) = delete; 5534 virtual ~AssertionStats(); 5535 5536 AssertionResult assertionResult; 5537 std::vector<MessageInfo> infoMessages; 5538 Totals totals; 5539 }; 5540 5541 struct SectionStats { 5542 SectionStats( SectionInfo const& _sectionInfo, 5543 Counts const& _assertions, 5544 double _durationInSeconds, 5545 bool _missingAssertions ); 5546 SectionStats( SectionStats const& ) = default; 5547 SectionStats( SectionStats && ) = default; 5548 SectionStats& operator = ( SectionStats const& ) = default; 5549 SectionStats& operator = ( SectionStats && ) = default; 5550 virtual ~SectionStats(); 5551 5552 SectionInfo sectionInfo; 5553 Counts assertions; 5554 double durationInSeconds; 5555 bool missingAssertions; 5556 }; 5557 5558 struct TestCaseStats { 5559 TestCaseStats( TestCaseInfo const& _testInfo, 5560 Totals const& _totals, 5561 std::string const& _stdOut, 5562 std::string const& _stdErr, 5563 bool _aborting ); 5564 5565 TestCaseStats( TestCaseStats const& ) = default; 5566 TestCaseStats( TestCaseStats && ) = default; 5567 TestCaseStats& operator = ( TestCaseStats const& ) = default; 5568 TestCaseStats& operator = ( TestCaseStats && ) = default; 5569 virtual ~TestCaseStats(); 5570 5571 TestCaseInfo testInfo; 5572 Totals totals; 5573 std::string stdOut; 5574 std::string stdErr; 5575 bool aborting; 5576 }; 5577 5578 struct TestGroupStats { 5579 TestGroupStats( GroupInfo const& _groupInfo, 5580 Totals const& _totals, 5581 bool _aborting ); 5582 TestGroupStats( GroupInfo const& _groupInfo ); 5583 5584 TestGroupStats( TestGroupStats const& ) = default; 5585 TestGroupStats( TestGroupStats && ) = default; 5586 TestGroupStats& operator = ( TestGroupStats const& ) = default; 5587 TestGroupStats& operator = ( TestGroupStats && ) = default; 5588 virtual ~TestGroupStats(); 5589 5590 GroupInfo groupInfo; 5591 Totals totals; 5592 bool aborting; 5593 }; 5594 5595 struct TestRunStats { 5596 TestRunStats( TestRunInfo const& _runInfo, 5597 Totals const& _totals, 5598 bool _aborting ); 5599 5600 TestRunStats( TestRunStats const& ) = default; 5601 TestRunStats( TestRunStats && ) = default; 5602 TestRunStats& operator = ( TestRunStats const& ) = default; 5603 TestRunStats& operator = ( TestRunStats && ) = default; 5604 virtual ~TestRunStats(); 5605 5606 TestRunInfo runInfo; 5607 Totals totals; 5608 bool aborting; 5609 }; 5610 5611 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 5612 struct BenchmarkInfo { 5613 std::string name; 5614 double estimatedDuration; 5615 int iterations; 5616 int samples; 5617 unsigned int resamples; 5618 double clockResolution; 5619 double clockCost; 5620 }; 5621 5622 template <class Duration> 5623 struct BenchmarkStats { 5624 BenchmarkInfo info; 5625 5626 std::vector<Duration> samples; 5627 Benchmark::Estimate<Duration> mean; 5628 Benchmark::Estimate<Duration> standardDeviation; 5629 Benchmark::OutlierClassification outliers; 5630 double outlierVariance; 5631 5632 template <typename Duration2> 5633 operator BenchmarkStats<Duration2>() const { 5634 std::vector<Duration2> samples2; 5635 samples2.reserve(samples.size()); 5636 std::transform(samples.begin(), samples.end(), std::back_inserter(samples2), [](Duration d) { return Duration2(d); }); 5637 return { 5638 info, 5639 std::move(samples2), 5640 mean, 5641 standardDeviation, 5642 outliers, 5643 outlierVariance, 5644 }; 5645 } 5646 }; 5647 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 5648 5649 struct IStreamingReporter { 5650 virtual ~IStreamingReporter() = default; 5651 5652 // Implementing class must also provide the following static methods: 5653 // static std::string getDescription(); 5654 // static std::set<Verbosity> getSupportedVerbosities() 5655 5656 virtual ReporterPreferences getPreferences() const = 0; 5657 5658 virtual void noMatchingTestCases( std::string const& spec ) = 0; 5659 5660 virtual void reportInvalidArguments(std::string const&) {} 5661 5662 virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; 5663 virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0; 5664 5665 virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; 5666 virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; 5667 5668 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 5669 virtual void benchmarkPreparing( std::string const& ) {} 5670 virtual void benchmarkStarting( BenchmarkInfo const& ) {} 5671 virtual void benchmarkEnded( BenchmarkStats<> const& ) {} 5672 virtual void benchmarkFailed( std::string const& ) {} 5673 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 5674 5675 virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; 5676 5677 // The return value indicates if the messages buffer should be cleared: 5678 virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; 5679 5680 virtual void sectionEnded( SectionStats const& sectionStats ) = 0; 5681 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; 5682 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; 5683 virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; 5684 5685 virtual void skipTest( TestCaseInfo const& testInfo ) = 0; 5686 5687 // Default empty implementation provided 5688 virtual void fatalErrorEncountered( StringRef name ); 5689 5690 virtual bool isMulti() const; 5691 }; 5692 using IStreamingReporterPtr = std::unique_ptr<IStreamingReporter>; 5693 5694 struct IReporterFactory { 5695 virtual ~IReporterFactory(); 5696 virtual IStreamingReporterPtr create( ReporterConfig const& config ) const = 0; 5697 virtual std::string getDescription() const = 0; 5698 }; 5699 using IReporterFactoryPtr = std::shared_ptr<IReporterFactory>; 5700 5701 struct IReporterRegistry { 5702 using FactoryMap = std::map<std::string, IReporterFactoryPtr>; 5703 using Listeners = std::vector<IReporterFactoryPtr>; 5704 5705 virtual ~IReporterRegistry(); 5706 virtual IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const = 0; 5707 virtual FactoryMap const& getFactories() const = 0; 5708 virtual Listeners const& getListeners() const = 0; 5709 }; 5710 5711 } // end namespace Catch 5712 5713 // end catch_interfaces_reporter.h 5714 #include <algorithm> 5715 #include <cstring> 5716 #include <cfloat> 5717 #include <cstdio> 5718 #include <cassert> 5719 #include <memory> 5720 #include <ostream> 5721 5722 namespace Catch { 5723 void prepareExpandedExpression(AssertionResult& result); 5724 5725 // Returns double formatted as %.3f (format expected on output) 5726 std::string getFormattedDuration( double duration ); 5727 5728 //! Should the reporter show 5729 bool shouldShowDuration( IConfig const& config, double duration ); 5730 5731 std::string serializeFilters( std::vector<std::string> const& container ); 5732 5733 template<typename DerivedT> 5734 struct StreamingReporterBase : IStreamingReporter { 5735 5736 StreamingReporterBase( ReporterConfig const& _config ) 5737 : m_config( _config.fullConfig() ), 5738 stream( _config.stream() ) 5739 { 5740 m_reporterPrefs.shouldRedirectStdOut = false; 5741 if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) ) 5742 CATCH_ERROR( "Verbosity level not supported by this reporter" ); 5743 } 5744 5745 ReporterPreferences getPreferences() const override { 5746 return m_reporterPrefs; 5747 } 5748 5749 static std::set<Verbosity> getSupportedVerbosities() { 5750 return { Verbosity::Normal }; 5751 } 5752 5753 ~StreamingReporterBase() override = default; 5754 5755 void noMatchingTestCases(std::string const&) override {} 5756 5757 void reportInvalidArguments(std::string const&) override {} 5758 5759 void testRunStarting(TestRunInfo const& _testRunInfo) override { 5760 currentTestRunInfo = _testRunInfo; 5761 } 5762 5763 void testGroupStarting(GroupInfo const& _groupInfo) override { 5764 currentGroupInfo = _groupInfo; 5765 } 5766 5767 void testCaseStarting(TestCaseInfo const& _testInfo) override { 5768 currentTestCaseInfo = _testInfo; 5769 } 5770 void sectionStarting(SectionInfo const& _sectionInfo) override { 5771 m_sectionStack.push_back(_sectionInfo); 5772 } 5773 5774 void sectionEnded(SectionStats const& /* _sectionStats */) override { 5775 m_sectionStack.pop_back(); 5776 } 5777 void testCaseEnded(TestCaseStats const& /* _testCaseStats */) override { 5778 currentTestCaseInfo.reset(); 5779 } 5780 void testGroupEnded(TestGroupStats const& /* _testGroupStats */) override { 5781 currentGroupInfo.reset(); 5782 } 5783 void testRunEnded(TestRunStats const& /* _testRunStats */) override { 5784 currentTestCaseInfo.reset(); 5785 currentGroupInfo.reset(); 5786 currentTestRunInfo.reset(); 5787 } 5788 5789 void skipTest(TestCaseInfo const&) override { 5790 // Don't do anything with this by default. 5791 // It can optionally be overridden in the derived class. 5792 } 5793 5794 IConfigPtr m_config; 5795 std::ostream& stream; 5796 5797 LazyStat<TestRunInfo> currentTestRunInfo; 5798 LazyStat<GroupInfo> currentGroupInfo; 5799 LazyStat<TestCaseInfo> currentTestCaseInfo; 5800 5801 std::vector<SectionInfo> m_sectionStack; 5802 ReporterPreferences m_reporterPrefs; 5803 }; 5804 5805 template<typename DerivedT> 5806 struct CumulativeReporterBase : IStreamingReporter { 5807 template<typename T, typename ChildNodeT> 5808 struct Node { 5809 explicit Node( T const& _value ) : value( _value ) {} 5810 virtual ~Node() {} 5811 5812 using ChildNodes = std::vector<std::shared_ptr<ChildNodeT>>; 5813 T value; 5814 ChildNodes children; 5815 }; 5816 struct SectionNode { 5817 explicit SectionNode(SectionStats const& _stats) : stats(_stats) {} 5818 virtual ~SectionNode() = default; 5819 5820 bool operator == (SectionNode const& other) const { 5821 return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; 5822 } 5823 bool operator == (std::shared_ptr<SectionNode> const& other) const { 5824 return operator==(*other); 5825 } 5826 5827 SectionStats stats; 5828 using ChildSections = std::vector<std::shared_ptr<SectionNode>>; 5829 using Assertions = std::vector<AssertionStats>; 5830 ChildSections childSections; 5831 Assertions assertions; 5832 std::string stdOut; 5833 std::string stdErr; 5834 }; 5835 5836 struct BySectionInfo { 5837 BySectionInfo( SectionInfo const& other ) : m_other( other ) {} 5838 BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {} 5839 bool operator() (std::shared_ptr<SectionNode> const& node) const { 5840 return ((node->stats.sectionInfo.name == m_other.name) && 5841 (node->stats.sectionInfo.lineInfo == m_other.lineInfo)); 5842 } 5843 void operator=(BySectionInfo const&) = delete; 5844 5845 private: 5846 SectionInfo const& m_other; 5847 }; 5848 5849 using TestCaseNode = Node<TestCaseStats, SectionNode>; 5850 using TestGroupNode = Node<TestGroupStats, TestCaseNode>; 5851 using TestRunNode = Node<TestRunStats, TestGroupNode>; 5852 5853 CumulativeReporterBase( ReporterConfig const& _config ) 5854 : m_config( _config.fullConfig() ), 5855 stream( _config.stream() ) 5856 { 5857 m_reporterPrefs.shouldRedirectStdOut = false; 5858 if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) ) 5859 CATCH_ERROR( "Verbosity level not supported by this reporter" ); 5860 } 5861 ~CumulativeReporterBase() override = default; 5862 5863 ReporterPreferences getPreferences() const override { 5864 return m_reporterPrefs; 5865 } 5866 5867 static std::set<Verbosity> getSupportedVerbosities() { 5868 return { Verbosity::Normal }; 5869 } 5870 5871 void testRunStarting( TestRunInfo const& ) override {} 5872 void testGroupStarting( GroupInfo const& ) override {} 5873 5874 void testCaseStarting( TestCaseInfo const& ) override {} 5875 5876 void sectionStarting( SectionInfo const& sectionInfo ) override { 5877 SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); 5878 std::shared_ptr<SectionNode> node; 5879 if( m_sectionStack.empty() ) { 5880 if( !m_rootSection ) 5881 m_rootSection = std::make_shared<SectionNode>( incompleteStats ); 5882 node = m_rootSection; 5883 } 5884 else { 5885 SectionNode& parentNode = *m_sectionStack.back(); 5886 auto it = 5887 std::find_if( parentNode.childSections.begin(), 5888 parentNode.childSections.end(), 5889 BySectionInfo( sectionInfo ) ); 5890 if( it == parentNode.childSections.end() ) { 5891 node = std::make_shared<SectionNode>( incompleteStats ); 5892 parentNode.childSections.push_back( node ); 5893 } 5894 else 5895 node = *it; 5896 } 5897 m_sectionStack.push_back( node ); 5898 m_deepestSection = std::move(node); 5899 } 5900 5901 void assertionStarting(AssertionInfo const&) override {} 5902 5903 bool assertionEnded(AssertionStats const& assertionStats) override { 5904 assert(!m_sectionStack.empty()); 5905 // AssertionResult holds a pointer to a temporary DecomposedExpression, 5906 // which getExpandedExpression() calls to build the expression string. 5907 // Our section stack copy of the assertionResult will likely outlive the 5908 // temporary, so it must be expanded or discarded now to avoid calling 5909 // a destroyed object later. 5910 prepareExpandedExpression(const_cast<AssertionResult&>( assertionStats.assertionResult ) ); 5911 SectionNode& sectionNode = *m_sectionStack.back(); 5912 sectionNode.assertions.push_back(assertionStats); 5913 return true; 5914 } 5915 void sectionEnded(SectionStats const& sectionStats) override { 5916 assert(!m_sectionStack.empty()); 5917 SectionNode& node = *m_sectionStack.back(); 5918 node.stats = sectionStats; 5919 m_sectionStack.pop_back(); 5920 } 5921 void testCaseEnded(TestCaseStats const& testCaseStats) override { 5922 auto node = std::make_shared<TestCaseNode>(testCaseStats); 5923 assert(m_sectionStack.size() == 0); 5924 node->children.push_back(m_rootSection); 5925 m_testCases.push_back(node); 5926 m_rootSection.reset(); 5927 5928 assert(m_deepestSection); 5929 m_deepestSection->stdOut = testCaseStats.stdOut; 5930 m_deepestSection->stdErr = testCaseStats.stdErr; 5931 } 5932 void testGroupEnded(TestGroupStats const& testGroupStats) override { 5933 auto node = std::make_shared<TestGroupNode>(testGroupStats); 5934 node->children.swap(m_testCases); 5935 m_testGroups.push_back(node); 5936 } 5937 void testRunEnded(TestRunStats const& testRunStats) override { 5938 auto node = std::make_shared<TestRunNode>(testRunStats); 5939 node->children.swap(m_testGroups); 5940 m_testRuns.push_back(node); 5941 testRunEndedCumulative(); 5942 } 5943 virtual void testRunEndedCumulative() = 0; 5944 5945 void skipTest(TestCaseInfo const&) override {} 5946 5947 IConfigPtr m_config; 5948 std::ostream& stream; 5949 std::vector<AssertionStats> m_assertions; 5950 std::vector<std::vector<std::shared_ptr<SectionNode>>> m_sections; 5951 std::vector<std::shared_ptr<TestCaseNode>> m_testCases; 5952 std::vector<std::shared_ptr<TestGroupNode>> m_testGroups; 5953 5954 std::vector<std::shared_ptr<TestRunNode>> m_testRuns; 5955 5956 std::shared_ptr<SectionNode> m_rootSection; 5957 std::shared_ptr<SectionNode> m_deepestSection; 5958 std::vector<std::shared_ptr<SectionNode>> m_sectionStack; 5959 ReporterPreferences m_reporterPrefs; 5960 }; 5961 5962 template<char C> 5963 char const* getLineOfChars() { 5964 static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0}; 5965 if( !*line ) { 5966 std::memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 ); 5967 line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0; 5968 } 5969 return line; 5970 } 5971 5972 struct TestEventListenerBase : StreamingReporterBase<TestEventListenerBase> { 5973 TestEventListenerBase( ReporterConfig const& _config ); 5974 5975 static std::set<Verbosity> getSupportedVerbosities(); 5976 5977 void assertionStarting(AssertionInfo const&) override; 5978 bool assertionEnded(AssertionStats const&) override; 5979 }; 5980 5981 } // end namespace Catch 5982 5983 // end catch_reporter_bases.hpp 5984 // start catch_console_colour.h 5985 5986 namespace Catch { 5987 5988 struct Colour { 5989 enum Code { 5990 None = 0, 5991 5992 White, 5993 Red, 5994 Green, 5995 Blue, 5996 Cyan, 5997 Yellow, 5998 Grey, 5999 6000 Bright = 0x10, 6001 6002 BrightRed = Bright | Red, 6003 BrightGreen = Bright | Green, 6004 LightGrey = Bright | Grey, 6005 BrightWhite = Bright | White, 6006 BrightYellow = Bright | Yellow, 6007 6008 // By intention 6009 FileName = LightGrey, 6010 Warning = BrightYellow, 6011 ResultError = BrightRed, 6012 ResultSuccess = BrightGreen, 6013 ResultExpectedFailure = Warning, 6014 6015 Error = BrightRed, 6016 Success = Green, 6017 6018 OriginalExpression = Cyan, 6019 ReconstructedExpression = BrightYellow, 6020 6021 SecondaryText = LightGrey, 6022 Headers = White 6023 }; 6024 6025 // Use constructed object for RAII guard 6026 Colour( Code _colourCode ); 6027 Colour( Colour&& other ) noexcept; 6028 Colour& operator=( Colour&& other ) noexcept; 6029 ~Colour(); 6030 6031 // Use static method for one-shot changes 6032 static void use( Code _colourCode ); 6033 6034 private: 6035 bool m_moved = false; 6036 }; 6037 6038 std::ostream& operator << ( std::ostream& os, Colour const& ); 6039 6040 } // end namespace Catch 6041 6042 // end catch_console_colour.h 6043 // start catch_reporter_registrars.hpp 6044 6045 6046 namespace Catch { 6047 6048 template<typename T> 6049 class ReporterRegistrar { 6050 6051 class ReporterFactory : public IReporterFactory { 6052 6053 IStreamingReporterPtr create( ReporterConfig const& config ) const override { 6054 return std::unique_ptr<T>( new T( config ) ); 6055 } 6056 6057 std::string getDescription() const override { 6058 return T::getDescription(); 6059 } 6060 }; 6061 6062 public: 6063 6064 explicit ReporterRegistrar( std::string const& name ) { 6065 getMutableRegistryHub().registerReporter( name, std::make_shared<ReporterFactory>() ); 6066 } 6067 }; 6068 6069 template<typename T> 6070 class ListenerRegistrar { 6071 6072 class ListenerFactory : public IReporterFactory { 6073 6074 IStreamingReporterPtr create( ReporterConfig const& config ) const override { 6075 return std::unique_ptr<T>( new T( config ) ); 6076 } 6077 std::string getDescription() const override { 6078 return std::string(); 6079 } 6080 }; 6081 6082 public: 6083 6084 ListenerRegistrar() { 6085 getMutableRegistryHub().registerListener( std::make_shared<ListenerFactory>() ); 6086 } 6087 }; 6088 } 6089 6090 #if !defined(CATCH_CONFIG_DISABLE) 6091 6092 #define CATCH_REGISTER_REPORTER( name, reporterType ) \ 6093 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 6094 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 6095 namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); } \ 6096 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 6097 6098 #define CATCH_REGISTER_LISTENER( listenerType ) \ 6099 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 6100 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 6101 namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; } \ 6102 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 6103 #else // CATCH_CONFIG_DISABLE 6104 6105 #define CATCH_REGISTER_REPORTER(name, reporterType) 6106 #define CATCH_REGISTER_LISTENER(listenerType) 6107 6108 #endif // CATCH_CONFIG_DISABLE 6109 6110 // end catch_reporter_registrars.hpp 6111 // Allow users to base their work off existing reporters 6112 // start catch_reporter_compact.h 6113 6114 namespace Catch { 6115 6116 struct CompactReporter : StreamingReporterBase<CompactReporter> { 6117 6118 using StreamingReporterBase::StreamingReporterBase; 6119 6120 ~CompactReporter() override; 6121 6122 static std::string getDescription(); 6123 6124 void noMatchingTestCases(std::string const& spec) override; 6125 6126 void assertionStarting(AssertionInfo const&) override; 6127 6128 bool assertionEnded(AssertionStats const& _assertionStats) override; 6129 6130 void sectionEnded(SectionStats const& _sectionStats) override; 6131 6132 void testRunEnded(TestRunStats const& _testRunStats) override; 6133 6134 }; 6135 6136 } // end namespace Catch 6137 6138 // end catch_reporter_compact.h 6139 // start catch_reporter_console.h 6140 6141 #if defined(_MSC_VER) 6142 #pragma warning(push) 6143 #pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch 6144 // Note that 4062 (not all labels are handled 6145 // and default is missing) is enabled 6146 #endif 6147 6148 namespace Catch { 6149 // Fwd decls 6150 struct SummaryColumn; 6151 class TablePrinter; 6152 6153 struct ConsoleReporter : StreamingReporterBase<ConsoleReporter> { 6154 std::unique_ptr<TablePrinter> m_tablePrinter; 6155 6156 ConsoleReporter(ReporterConfig const& config); 6157 ~ConsoleReporter() override; 6158 static std::string getDescription(); 6159 6160 void noMatchingTestCases(std::string const& spec) override; 6161 6162 void reportInvalidArguments(std::string const&arg) override; 6163 6164 void assertionStarting(AssertionInfo const&) override; 6165 6166 bool assertionEnded(AssertionStats const& _assertionStats) override; 6167 6168 void sectionStarting(SectionInfo const& _sectionInfo) override; 6169 void sectionEnded(SectionStats const& _sectionStats) override; 6170 6171 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 6172 void benchmarkPreparing(std::string const& name) override; 6173 void benchmarkStarting(BenchmarkInfo const& info) override; 6174 void benchmarkEnded(BenchmarkStats<> const& stats) override; 6175 void benchmarkFailed(std::string const& error) override; 6176 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 6177 6178 void testCaseEnded(TestCaseStats const& _testCaseStats) override; 6179 void testGroupEnded(TestGroupStats const& _testGroupStats) override; 6180 void testRunEnded(TestRunStats const& _testRunStats) override; 6181 void testRunStarting(TestRunInfo const& _testRunInfo) override; 6182 private: 6183 6184 void lazyPrint(); 6185 6186 void lazyPrintWithoutClosingBenchmarkTable(); 6187 void lazyPrintRunInfo(); 6188 void lazyPrintGroupInfo(); 6189 void printTestCaseAndSectionHeader(); 6190 6191 void printClosedHeader(std::string const& _name); 6192 void printOpenHeader(std::string const& _name); 6193 6194 // if string has a : in first line will set indent to follow it on 6195 // subsequent lines 6196 void printHeaderString(std::string const& _string, std::size_t indent = 0); 6197 6198 void printTotals(Totals const& totals); 6199 void printSummaryRow(std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row); 6200 6201 void printTotalsDivider(Totals const& totals); 6202 void printSummaryDivider(); 6203 void printTestFilters(); 6204 6205 private: 6206 bool m_headerPrinted = false; 6207 }; 6208 6209 } // end namespace Catch 6210 6211 #if defined(_MSC_VER) 6212 #pragma warning(pop) 6213 #endif 6214 6215 // end catch_reporter_console.h 6216 // start catch_reporter_junit.h 6217 6218 // start catch_xmlwriter.h 6219 6220 #include <vector> 6221 6222 namespace Catch { 6223 enum class XmlFormatting { 6224 None = 0x00, 6225 Indent = 0x01, 6226 Newline = 0x02, 6227 }; 6228 6229 XmlFormatting operator | (XmlFormatting lhs, XmlFormatting rhs); 6230 XmlFormatting operator & (XmlFormatting lhs, XmlFormatting rhs); 6231 6232 class XmlEncode { 6233 public: 6234 enum ForWhat { ForTextNodes, ForAttributes }; 6235 6236 XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes ); 6237 6238 void encodeTo( std::ostream& os ) const; 6239 6240 friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ); 6241 6242 private: 6243 std::string m_str; 6244 ForWhat m_forWhat; 6245 }; 6246 6247 class XmlWriter { 6248 public: 6249 6250 class ScopedElement { 6251 public: 6252 ScopedElement( XmlWriter* writer, XmlFormatting fmt ); 6253 6254 ScopedElement( ScopedElement&& other ) noexcept; 6255 ScopedElement& operator=( ScopedElement&& other ) noexcept; 6256 6257 ~ScopedElement(); 6258 6259 ScopedElement& writeText( std::string const& text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent ); 6260 6261 template<typename T> 6262 ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { 6263 m_writer->writeAttribute( name, attribute ); 6264 return *this; 6265 } 6266 6267 private: 6268 mutable XmlWriter* m_writer = nullptr; 6269 XmlFormatting m_fmt; 6270 }; 6271 6272 XmlWriter( std::ostream& os = Catch::cout() ); 6273 ~XmlWriter(); 6274 6275 XmlWriter( XmlWriter const& ) = delete; 6276 XmlWriter& operator=( XmlWriter const& ) = delete; 6277 6278 XmlWriter& startElement( std::string const& name, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); 6279 6280 ScopedElement scopedElement( std::string const& name, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); 6281 6282 XmlWriter& endElement(XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); 6283 6284 XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ); 6285 6286 XmlWriter& writeAttribute( std::string const& name, bool attribute ); 6287 6288 template<typename T> 6289 XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { 6290 ReusableStringStream rss; 6291 rss << attribute; 6292 return writeAttribute( name, rss.str() ); 6293 } 6294 6295 XmlWriter& writeText( std::string const& text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); 6296 6297 XmlWriter& writeComment(std::string const& text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); 6298 6299 void writeStylesheetRef( std::string const& url ); 6300 6301 XmlWriter& writeBlankLine(); 6302 6303 void ensureTagClosed(); 6304 6305 private: 6306 6307 void applyFormatting(XmlFormatting fmt); 6308 6309 void writeDeclaration(); 6310 6311 void newlineIfNecessary(); 6312 6313 bool m_tagIsOpen = false; 6314 bool m_needsNewline = false; 6315 std::vector<std::string> m_tags; 6316 std::string m_indent; 6317 std::ostream& m_os; 6318 }; 6319 6320 } 6321 6322 // end catch_xmlwriter.h 6323 namespace Catch { 6324 6325 class JunitReporter : public CumulativeReporterBase<JunitReporter> { 6326 public: 6327 JunitReporter(ReporterConfig const& _config); 6328 6329 ~JunitReporter() override; 6330 6331 static std::string getDescription(); 6332 6333 void noMatchingTestCases(std::string const& /*spec*/) override; 6334 6335 void testRunStarting(TestRunInfo const& runInfo) override; 6336 6337 void testGroupStarting(GroupInfo const& groupInfo) override; 6338 6339 void testCaseStarting(TestCaseInfo const& testCaseInfo) override; 6340 bool assertionEnded(AssertionStats const& assertionStats) override; 6341 6342 void testCaseEnded(TestCaseStats const& testCaseStats) override; 6343 6344 void testGroupEnded(TestGroupStats const& testGroupStats) override; 6345 6346 void testRunEndedCumulative() override; 6347 6348 void writeGroup(TestGroupNode const& groupNode, double suiteTime); 6349 6350 void writeTestCase(TestCaseNode const& testCaseNode); 6351 6352 void writeSection( std::string const& className, 6353 std::string const& rootName, 6354 SectionNode const& sectionNode, 6355 bool testOkToFail ); 6356 6357 void writeAssertions(SectionNode const& sectionNode); 6358 void writeAssertion(AssertionStats const& stats); 6359 6360 XmlWriter xml; 6361 Timer suiteTimer; 6362 std::string stdOutForSuite; 6363 std::string stdErrForSuite; 6364 unsigned int unexpectedExceptions = 0; 6365 bool m_okToFail = false; 6366 }; 6367 6368 } // end namespace Catch 6369 6370 // end catch_reporter_junit.h 6371 // start catch_reporter_xml.h 6372 6373 namespace Catch { 6374 class XmlReporter : public StreamingReporterBase<XmlReporter> { 6375 public: 6376 XmlReporter(ReporterConfig const& _config); 6377 6378 ~XmlReporter() override; 6379 6380 static std::string getDescription(); 6381 6382 virtual std::string getStylesheetRef() const; 6383 6384 void writeSourceInfo(SourceLineInfo const& sourceInfo); 6385 6386 public: // StreamingReporterBase 6387 6388 void noMatchingTestCases(std::string const& s) override; 6389 6390 void testRunStarting(TestRunInfo const& testInfo) override; 6391 6392 void testGroupStarting(GroupInfo const& groupInfo) override; 6393 6394 void testCaseStarting(TestCaseInfo const& testInfo) override; 6395 6396 void sectionStarting(SectionInfo const& sectionInfo) override; 6397 6398 void assertionStarting(AssertionInfo const&) override; 6399 6400 bool assertionEnded(AssertionStats const& assertionStats) override; 6401 6402 void sectionEnded(SectionStats const& sectionStats) override; 6403 6404 void testCaseEnded(TestCaseStats const& testCaseStats) override; 6405 6406 void testGroupEnded(TestGroupStats const& testGroupStats) override; 6407 6408 void testRunEnded(TestRunStats const& testRunStats) override; 6409 6410 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 6411 void benchmarkPreparing(std::string const& name) override; 6412 void benchmarkStarting(BenchmarkInfo const&) override; 6413 void benchmarkEnded(BenchmarkStats<> const&) override; 6414 void benchmarkFailed(std::string const&) override; 6415 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 6416 6417 private: 6418 Timer m_testCaseTimer; 6419 XmlWriter m_xml; 6420 int m_sectionDepth = 0; 6421 }; 6422 6423 } // end namespace Catch 6424 6425 // end catch_reporter_xml.h 6426 6427 // end catch_external_interfaces.h 6428 #endif 6429 6430 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 6431 // start catch_benchmarking_all.hpp 6432 6433 // A proxy header that includes all of the benchmarking headers to allow 6434 // concise include of the benchmarking features. You should prefer the 6435 // individual includes in standard use. 6436 6437 // start catch_benchmark.hpp 6438 6439 // Benchmark 6440 6441 // start catch_chronometer.hpp 6442 6443 // User-facing chronometer 6444 6445 6446 // start catch_clock.hpp 6447 6448 // Clocks 6449 6450 6451 #include <chrono> 6452 #include <ratio> 6453 6454 namespace Catch { 6455 namespace Benchmark { 6456 template <typename Clock> 6457 using ClockDuration = typename Clock::duration; 6458 template <typename Clock> 6459 using FloatDuration = std::chrono::duration<double, typename Clock::period>; 6460 6461 template <typename Clock> 6462 using TimePoint = typename Clock::time_point; 6463 6464 using default_clock = std::chrono::steady_clock; 6465 6466 template <typename Clock> 6467 struct now { 6468 TimePoint<Clock> operator()() const { 6469 return Clock::now(); 6470 } 6471 }; 6472 6473 using fp_seconds = std::chrono::duration<double, std::ratio<1>>; 6474 } // namespace Benchmark 6475 } // namespace Catch 6476 6477 // end catch_clock.hpp 6478 // start catch_optimizer.hpp 6479 6480 // Hinting the optimizer 6481 6482 6483 #if defined(_MSC_VER) 6484 # include <atomic> // atomic_thread_fence 6485 #endif 6486 6487 namespace Catch { 6488 namespace Benchmark { 6489 #if defined(__GNUC__) || defined(__clang__) 6490 template <typename T> 6491 inline void keep_memory(T* p) { 6492 asm volatile("" : : "g"(p) : "memory"); 6493 } 6494 inline void keep_memory() { 6495 asm volatile("" : : : "memory"); 6496 } 6497 6498 namespace Detail { 6499 inline void optimizer_barrier() { keep_memory(); } 6500 } // namespace Detail 6501 #elif defined(_MSC_VER) 6502 6503 #pragma optimize("", off) 6504 template <typename T> 6505 inline void keep_memory(T* p) { 6506 // thanks @milleniumbug 6507 *reinterpret_cast<char volatile*>(p) = *reinterpret_cast<char const volatile*>(p); 6508 } 6509 // TODO equivalent keep_memory() 6510 #pragma optimize("", on) 6511 6512 namespace Detail { 6513 inline void optimizer_barrier() { 6514 std::atomic_thread_fence(std::memory_order_seq_cst); 6515 } 6516 } // namespace Detail 6517 6518 #endif 6519 6520 template <typename T> 6521 inline void deoptimize_value(T&& x) { 6522 keep_memory(&x); 6523 } 6524 6525 template <typename Fn, typename... Args> 6526 inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> typename std::enable_if<!std::is_same<void, decltype(fn(args...))>::value>::type { 6527 deoptimize_value(std::forward<Fn>(fn) (std::forward<Args...>(args...))); 6528 } 6529 6530 template <typename Fn, typename... Args> 6531 inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> typename std::enable_if<std::is_same<void, decltype(fn(args...))>::value>::type { 6532 std::forward<Fn>(fn) (std::forward<Args...>(args...)); 6533 } 6534 } // namespace Benchmark 6535 } // namespace Catch 6536 6537 // end catch_optimizer.hpp 6538 // start catch_complete_invoke.hpp 6539 6540 // Invoke with a special case for void 6541 6542 6543 #include <type_traits> 6544 #include <utility> 6545 6546 namespace Catch { 6547 namespace Benchmark { 6548 namespace Detail { 6549 template <typename T> 6550 struct CompleteType { using type = T; }; 6551 template <> 6552 struct CompleteType<void> { struct type {}; }; 6553 6554 template <typename T> 6555 using CompleteType_t = typename CompleteType<T>::type; 6556 6557 template <typename Result> 6558 struct CompleteInvoker { 6559 template <typename Fun, typename... Args> 6560 static Result invoke(Fun&& fun, Args&&... args) { 6561 return std::forward<Fun>(fun)(std::forward<Args>(args)...); 6562 } 6563 }; 6564 template <> 6565 struct CompleteInvoker<void> { 6566 template <typename Fun, typename... Args> 6567 static CompleteType_t<void> invoke(Fun&& fun, Args&&... args) { 6568 std::forward<Fun>(fun)(std::forward<Args>(args)...); 6569 return {}; 6570 } 6571 }; 6572 6573 // invoke and not return void :( 6574 template <typename Fun, typename... Args> 6575 CompleteType_t<FunctionReturnType<Fun, Args...>> complete_invoke(Fun&& fun, Args&&... args) { 6576 return CompleteInvoker<FunctionReturnType<Fun, Args...>>::invoke(std::forward<Fun>(fun), std::forward<Args>(args)...); 6577 } 6578 6579 const std::string benchmarkErrorMsg = "a benchmark failed to run successfully"; 6580 } // namespace Detail 6581 6582 template <typename Fun> 6583 Detail::CompleteType_t<FunctionReturnType<Fun>> user_code(Fun&& fun) { 6584 CATCH_TRY{ 6585 return Detail::complete_invoke(std::forward<Fun>(fun)); 6586 } CATCH_CATCH_ALL{ 6587 getResultCapture().benchmarkFailed(translateActiveException()); 6588 CATCH_RUNTIME_ERROR(Detail::benchmarkErrorMsg); 6589 } 6590 } 6591 } // namespace Benchmark 6592 } // namespace Catch 6593 6594 // end catch_complete_invoke.hpp 6595 namespace Catch { 6596 namespace Benchmark { 6597 namespace Detail { 6598 struct ChronometerConcept { 6599 virtual void start() = 0; 6600 virtual void finish() = 0; 6601 virtual ~ChronometerConcept() = default; 6602 }; 6603 template <typename Clock> 6604 struct ChronometerModel final : public ChronometerConcept { 6605 void start() override { started = Clock::now(); } 6606 void finish() override { finished = Clock::now(); } 6607 6608 ClockDuration<Clock> elapsed() const { return finished - started; } 6609 6610 TimePoint<Clock> started; 6611 TimePoint<Clock> finished; 6612 }; 6613 } // namespace Detail 6614 6615 struct Chronometer { 6616 public: 6617 template <typename Fun> 6618 void measure(Fun&& fun) { measure(std::forward<Fun>(fun), is_callable<Fun(int)>()); } 6619 6620 int runs() const { return k; } 6621 6622 Chronometer(Detail::ChronometerConcept& meter, int k) 6623 : impl(&meter) 6624 , k(k) {} 6625 6626 private: 6627 template <typename Fun> 6628 void measure(Fun&& fun, std::false_type) { 6629 measure([&fun](int) { return fun(); }, std::true_type()); 6630 } 6631 6632 template <typename Fun> 6633 void measure(Fun&& fun, std::true_type) { 6634 Detail::optimizer_barrier(); 6635 impl->start(); 6636 for (int i = 0; i < k; ++i) invoke_deoptimized(fun, i); 6637 impl->finish(); 6638 Detail::optimizer_barrier(); 6639 } 6640 6641 Detail::ChronometerConcept* impl; 6642 int k; 6643 }; 6644 } // namespace Benchmark 6645 } // namespace Catch 6646 6647 // end catch_chronometer.hpp 6648 // start catch_environment.hpp 6649 6650 // Environment information 6651 6652 6653 namespace Catch { 6654 namespace Benchmark { 6655 template <typename Duration> 6656 struct EnvironmentEstimate { 6657 Duration mean; 6658 OutlierClassification outliers; 6659 6660 template <typename Duration2> 6661 operator EnvironmentEstimate<Duration2>() const { 6662 return { mean, outliers }; 6663 } 6664 }; 6665 template <typename Clock> 6666 struct Environment { 6667 using clock_type = Clock; 6668 EnvironmentEstimate<FloatDuration<Clock>> clock_resolution; 6669 EnvironmentEstimate<FloatDuration<Clock>> clock_cost; 6670 }; 6671 } // namespace Benchmark 6672 } // namespace Catch 6673 6674 // end catch_environment.hpp 6675 // start catch_execution_plan.hpp 6676 6677 // Execution plan 6678 6679 6680 // start catch_benchmark_function.hpp 6681 6682 // Dumb std::function implementation for consistent call overhead 6683 6684 6685 #include <cassert> 6686 #include <type_traits> 6687 #include <utility> 6688 #include <memory> 6689 6690 namespace Catch { 6691 namespace Benchmark { 6692 namespace Detail { 6693 template <typename T> 6694 using Decay = typename std::decay<T>::type; 6695 template <typename T, typename U> 6696 struct is_related 6697 : std::is_same<Decay<T>, Decay<U>> {}; 6698 6699 /// We need to reinvent std::function because every piece of code that might add overhead 6700 /// in a measurement context needs to have consistent performance characteristics so that we 6701 /// can account for it in the measurement. 6702 /// Implementations of std::function with optimizations that aren't always applicable, like 6703 /// small buffer optimizations, are not uncommon. 6704 /// This is effectively an implementation of std::function without any such optimizations; 6705 /// it may be slow, but it is consistently slow. 6706 struct BenchmarkFunction { 6707 private: 6708 struct callable { 6709 virtual void call(Chronometer meter) const = 0; 6710 virtual callable* clone() const = 0; 6711 virtual ~callable() = default; 6712 }; 6713 template <typename Fun> 6714 struct model : public callable { 6715 model(Fun&& fun) : fun(std::move(fun)) {} 6716 model(Fun const& fun) : fun(fun) {} 6717 6718 model<Fun>* clone() const override { return new model<Fun>(*this); } 6719 6720 void call(Chronometer meter) const override { 6721 call(meter, is_callable<Fun(Chronometer)>()); 6722 } 6723 void call(Chronometer meter, std::true_type) const { 6724 fun(meter); 6725 } 6726 void call(Chronometer meter, std::false_type) const { 6727 meter.measure(fun); 6728 } 6729 6730 Fun fun; 6731 }; 6732 6733 struct do_nothing { void operator()() const {} }; 6734 6735 template <typename T> 6736 BenchmarkFunction(model<T>* c) : f(c) {} 6737 6738 public: 6739 BenchmarkFunction() 6740 : f(new model<do_nothing>{ {} }) {} 6741 6742 template <typename Fun, 6743 typename std::enable_if<!is_related<Fun, BenchmarkFunction>::value, int>::type = 0> 6744 BenchmarkFunction(Fun&& fun) 6745 : f(new model<typename std::decay<Fun>::type>(std::forward<Fun>(fun))) {} 6746 6747 BenchmarkFunction(BenchmarkFunction&& that) 6748 : f(std::move(that.f)) {} 6749 6750 BenchmarkFunction(BenchmarkFunction const& that) 6751 : f(that.f->clone()) {} 6752 6753 BenchmarkFunction& operator=(BenchmarkFunction&& that) { 6754 f = std::move(that.f); 6755 return *this; 6756 } 6757 6758 BenchmarkFunction& operator=(BenchmarkFunction const& that) { 6759 f.reset(that.f->clone()); 6760 return *this; 6761 } 6762 6763 void operator()(Chronometer meter) const { f->call(meter); } 6764 6765 private: 6766 std::unique_ptr<callable> f; 6767 }; 6768 } // namespace Detail 6769 } // namespace Benchmark 6770 } // namespace Catch 6771 6772 // end catch_benchmark_function.hpp 6773 // start catch_repeat.hpp 6774 6775 // repeat algorithm 6776 6777 6778 #include <type_traits> 6779 #include <utility> 6780 6781 namespace Catch { 6782 namespace Benchmark { 6783 namespace Detail { 6784 template <typename Fun> 6785 struct repeater { 6786 void operator()(int k) const { 6787 for (int i = 0; i < k; ++i) { 6788 fun(); 6789 } 6790 } 6791 Fun fun; 6792 }; 6793 template <typename Fun> 6794 repeater<typename std::decay<Fun>::type> repeat(Fun&& fun) { 6795 return { std::forward<Fun>(fun) }; 6796 } 6797 } // namespace Detail 6798 } // namespace Benchmark 6799 } // namespace Catch 6800 6801 // end catch_repeat.hpp 6802 // start catch_run_for_at_least.hpp 6803 6804 // Run a function for a minimum amount of time 6805 6806 6807 // start catch_measure.hpp 6808 6809 // Measure 6810 6811 6812 // start catch_timing.hpp 6813 6814 // Timing 6815 6816 6817 #include <tuple> 6818 #include <type_traits> 6819 6820 namespace Catch { 6821 namespace Benchmark { 6822 template <typename Duration, typename Result> 6823 struct Timing { 6824 Duration elapsed; 6825 Result result; 6826 int iterations; 6827 }; 6828 template <typename Clock, typename Func, typename... Args> 6829 using TimingOf = Timing<ClockDuration<Clock>, Detail::CompleteType_t<FunctionReturnType<Func, Args...>>>; 6830 } // namespace Benchmark 6831 } // namespace Catch 6832 6833 // end catch_timing.hpp 6834 #include <utility> 6835 6836 namespace Catch { 6837 namespace Benchmark { 6838 namespace Detail { 6839 template <typename Clock, typename Fun, typename... Args> 6840 TimingOf<Clock, Fun, Args...> measure(Fun&& fun, Args&&... args) { 6841 auto start = Clock::now(); 6842 auto&& r = Detail::complete_invoke(fun, std::forward<Args>(args)...); 6843 auto end = Clock::now(); 6844 auto delta = end - start; 6845 return { delta, std::forward<decltype(r)>(r), 1 }; 6846 } 6847 } // namespace Detail 6848 } // namespace Benchmark 6849 } // namespace Catch 6850 6851 // end catch_measure.hpp 6852 #include <utility> 6853 #include <type_traits> 6854 6855 namespace Catch { 6856 namespace Benchmark { 6857 namespace Detail { 6858 template <typename Clock, typename Fun> 6859 TimingOf<Clock, Fun, int> measure_one(Fun&& fun, int iters, std::false_type) { 6860 return Detail::measure<Clock>(fun, iters); 6861 } 6862 template <typename Clock, typename Fun> 6863 TimingOf<Clock, Fun, Chronometer> measure_one(Fun&& fun, int iters, std::true_type) { 6864 Detail::ChronometerModel<Clock> meter; 6865 auto&& result = Detail::complete_invoke(fun, Chronometer(meter, iters)); 6866 6867 return { meter.elapsed(), std::move(result), iters }; 6868 } 6869 6870 template <typename Clock, typename Fun> 6871 using run_for_at_least_argument_t = typename std::conditional<is_callable<Fun(Chronometer)>::value, Chronometer, int>::type; 6872 6873 struct optimized_away_error : std::exception { 6874 const char* what() const noexcept override { 6875 return "could not measure benchmark, maybe it was optimized away"; 6876 } 6877 }; 6878 6879 template <typename Clock, typename Fun> 6880 TimingOf<Clock, Fun, run_for_at_least_argument_t<Clock, Fun>> run_for_at_least(ClockDuration<Clock> how_long, int seed, Fun&& fun) { 6881 auto iters = seed; 6882 while (iters < (1 << 30)) { 6883 auto&& Timing = measure_one<Clock>(fun, iters, is_callable<Fun(Chronometer)>()); 6884 6885 if (Timing.elapsed >= how_long) { 6886 return { Timing.elapsed, std::move(Timing.result), iters }; 6887 } 6888 iters *= 2; 6889 } 6890 Catch::throw_exception(optimized_away_error{}); 6891 } 6892 } // namespace Detail 6893 } // namespace Benchmark 6894 } // namespace Catch 6895 6896 // end catch_run_for_at_least.hpp 6897 #include <algorithm> 6898 #include <iterator> 6899 6900 namespace Catch { 6901 namespace Benchmark { 6902 template <typename Duration> 6903 struct ExecutionPlan { 6904 int iterations_per_sample; 6905 Duration estimated_duration; 6906 Detail::BenchmarkFunction benchmark; 6907 Duration warmup_time; 6908 int warmup_iterations; 6909 6910 template <typename Duration2> 6911 operator ExecutionPlan<Duration2>() const { 6912 return { iterations_per_sample, estimated_duration, benchmark, warmup_time, warmup_iterations }; 6913 } 6914 6915 template <typename Clock> 6916 std::vector<FloatDuration<Clock>> run(const IConfig &cfg, Environment<FloatDuration<Clock>> env) const { 6917 // warmup a bit 6918 Detail::run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(warmup_time), warmup_iterations, Detail::repeat(now<Clock>{})); 6919 6920 std::vector<FloatDuration<Clock>> times; 6921 times.reserve(cfg.benchmarkSamples()); 6922 std::generate_n(std::back_inserter(times), cfg.benchmarkSamples(), [this, env] { 6923 Detail::ChronometerModel<Clock> model; 6924 this->benchmark(Chronometer(model, iterations_per_sample)); 6925 auto sample_time = model.elapsed() - env.clock_cost.mean; 6926 if (sample_time < FloatDuration<Clock>::zero()) sample_time = FloatDuration<Clock>::zero(); 6927 return sample_time / iterations_per_sample; 6928 }); 6929 return times; 6930 } 6931 }; 6932 } // namespace Benchmark 6933 } // namespace Catch 6934 6935 // end catch_execution_plan.hpp 6936 // start catch_estimate_clock.hpp 6937 6938 // Environment measurement 6939 6940 6941 // start catch_stats.hpp 6942 6943 // Statistical analysis tools 6944 6945 6946 #include <algorithm> 6947 #include <functional> 6948 #include <vector> 6949 #include <iterator> 6950 #include <numeric> 6951 #include <tuple> 6952 #include <cmath> 6953 #include <utility> 6954 #include <cstddef> 6955 #include <random> 6956 6957 namespace Catch { 6958 namespace Benchmark { 6959 namespace Detail { 6960 using sample = std::vector<double>; 6961 6962 double weighted_average_quantile(int k, int q, std::vector<double>::iterator first, std::vector<double>::iterator last); 6963 6964 template <typename Iterator> 6965 OutlierClassification classify_outliers(Iterator first, Iterator last) { 6966 std::vector<double> copy(first, last); 6967 6968 auto q1 = weighted_average_quantile(1, 4, copy.begin(), copy.end()); 6969 auto q3 = weighted_average_quantile(3, 4, copy.begin(), copy.end()); 6970 auto iqr = q3 - q1; 6971 auto los = q1 - (iqr * 3.); 6972 auto lom = q1 - (iqr * 1.5); 6973 auto him = q3 + (iqr * 1.5); 6974 auto his = q3 + (iqr * 3.); 6975 6976 OutlierClassification o; 6977 for (; first != last; ++first) { 6978 auto&& t = *first; 6979 if (t < los) ++o.low_severe; 6980 else if (t < lom) ++o.low_mild; 6981 else if (t > his) ++o.high_severe; 6982 else if (t > him) ++o.high_mild; 6983 ++o.samples_seen; 6984 } 6985 return o; 6986 } 6987 6988 template <typename Iterator> 6989 double mean(Iterator first, Iterator last) { 6990 auto count = last - first; 6991 double sum = std::accumulate(first, last, 0.); 6992 return sum / count; 6993 } 6994 6995 template <typename URng, typename Iterator, typename Estimator> 6996 sample resample(URng& rng, int resamples, Iterator first, Iterator last, Estimator& estimator) { 6997 auto n = last - first; 6998 std::uniform_int_distribution<decltype(n)> dist(0, n - 1); 6999 7000 sample out; 7001 out.reserve(resamples); 7002 std::generate_n(std::back_inserter(out), resamples, [n, first, &estimator, &dist, &rng] { 7003 std::vector<double> resampled; 7004 resampled.reserve(n); 7005 std::generate_n(std::back_inserter(resampled), n, [first, &dist, &rng] { return first[dist(rng)]; }); 7006 return estimator(resampled.begin(), resampled.end()); 7007 }); 7008 std::sort(out.begin(), out.end()); 7009 return out; 7010 } 7011 7012 template <typename Estimator, typename Iterator> 7013 sample jackknife(Estimator&& estimator, Iterator first, Iterator last) { 7014 auto n = last - first; 7015 auto second = std::next(first); 7016 sample results; 7017 results.reserve(n); 7018 7019 for (auto it = first; it != last; ++it) { 7020 std::iter_swap(it, first); 7021 results.push_back(estimator(second, last)); 7022 } 7023 7024 return results; 7025 } 7026 7027 inline double normal_cdf(double x) { 7028 return std::erfc(-x / std::sqrt(2.0)) / 2.0; 7029 } 7030 7031 double erfc_inv(double x); 7032 7033 double normal_quantile(double p); 7034 7035 template <typename Iterator, typename Estimator> 7036 Estimate<double> bootstrap(double confidence_level, Iterator first, Iterator last, sample const& resample, Estimator&& estimator) { 7037 auto n_samples = last - first; 7038 7039 double point = estimator(first, last); 7040 // Degenerate case with a single sample 7041 if (n_samples == 1) return { point, point, point, confidence_level }; 7042 7043 sample jack = jackknife(estimator, first, last); 7044 double jack_mean = mean(jack.begin(), jack.end()); 7045 double sum_squares, sum_cubes; 7046 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> { 7047 auto d = jack_mean - x; 7048 auto d2 = d * d; 7049 auto d3 = d2 * d; 7050 return { sqcb.first + d2, sqcb.second + d3 }; 7051 }); 7052 7053 double accel = sum_cubes / (6 * std::pow(sum_squares, 1.5)); 7054 int n = static_cast<int>(resample.size()); 7055 double prob_n = std::count_if(resample.begin(), resample.end(), [point](double x) { return x < point; }) / (double)n; 7056 // degenerate case with uniform samples 7057 if (prob_n == 0) return { point, point, point, confidence_level }; 7058 7059 double bias = normal_quantile(prob_n); 7060 double z1 = normal_quantile((1. - confidence_level) / 2.); 7061 7062 auto cumn = [n](double x) -> int { 7063 return std::lround(normal_cdf(x) * n); }; 7064 auto a = [bias, accel](double b) { return bias + b / (1. - accel * b); }; 7065 double b1 = bias + z1; 7066 double b2 = bias - z1; 7067 double a1 = a(b1); 7068 double a2 = a(b2); 7069 auto lo = (std::max)(cumn(a1), 0); 7070 auto hi = (std::min)(cumn(a2), n - 1); 7071 7072 return { point, resample[lo], resample[hi], confidence_level }; 7073 } 7074 7075 double outlier_variance(Estimate<double> mean, Estimate<double> stddev, int n); 7076 7077 struct bootstrap_analysis { 7078 Estimate<double> mean; 7079 Estimate<double> standard_deviation; 7080 double outlier_variance; 7081 }; 7082 7083 bootstrap_analysis analyse_samples(double confidence_level, int n_resamples, std::vector<double>::iterator first, std::vector<double>::iterator last); 7084 } // namespace Detail 7085 } // namespace Benchmark 7086 } // namespace Catch 7087 7088 // end catch_stats.hpp 7089 #include <algorithm> 7090 #include <iterator> 7091 #include <tuple> 7092 #include <vector> 7093 #include <cmath> 7094 7095 namespace Catch { 7096 namespace Benchmark { 7097 namespace Detail { 7098 template <typename Clock> 7099 std::vector<double> resolution(int k) { 7100 std::vector<TimePoint<Clock>> times; 7101 times.reserve(k + 1); 7102 std::generate_n(std::back_inserter(times), k + 1, now<Clock>{}); 7103 7104 std::vector<double> deltas; 7105 deltas.reserve(k); 7106 std::transform(std::next(times.begin()), times.end(), times.begin(), 7107 std::back_inserter(deltas), 7108 [](TimePoint<Clock> a, TimePoint<Clock> b) { return static_cast<double>((a - b).count()); }); 7109 7110 return deltas; 7111 } 7112 7113 const auto warmup_iterations = 10000; 7114 const auto warmup_time = std::chrono::milliseconds(100); 7115 const auto minimum_ticks = 1000; 7116 const auto warmup_seed = 10000; 7117 const auto clock_resolution_estimation_time = std::chrono::milliseconds(500); 7118 const auto clock_cost_estimation_time_limit = std::chrono::seconds(1); 7119 const auto clock_cost_estimation_tick_limit = 100000; 7120 const auto clock_cost_estimation_time = std::chrono::milliseconds(10); 7121 const auto clock_cost_estimation_iterations = 10000; 7122 7123 template <typename Clock> 7124 int warmup() { 7125 return run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(warmup_time), warmup_seed, &resolution<Clock>) 7126 .iterations; 7127 } 7128 template <typename Clock> 7129 EnvironmentEstimate<FloatDuration<Clock>> estimate_clock_resolution(int iterations) { 7130 auto r = run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(clock_resolution_estimation_time), iterations, &resolution<Clock>) 7131 .result; 7132 return { 7133 FloatDuration<Clock>(mean(r.begin(), r.end())), 7134 classify_outliers(r.begin(), r.end()), 7135 }; 7136 } 7137 template <typename Clock> 7138 EnvironmentEstimate<FloatDuration<Clock>> estimate_clock_cost(FloatDuration<Clock> resolution) { 7139 auto time_limit = (std::min)( 7140 resolution * clock_cost_estimation_tick_limit, 7141 FloatDuration<Clock>(clock_cost_estimation_time_limit)); 7142 auto time_clock = [](int k) { 7143 return Detail::measure<Clock>([k] { 7144 for (int i = 0; i < k; ++i) { 7145 volatile auto ignored = Clock::now(); 7146 (void)ignored; 7147 } 7148 }).elapsed; 7149 }; 7150 time_clock(1); 7151 int iters = clock_cost_estimation_iterations; 7152 auto&& r = run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(clock_cost_estimation_time), iters, time_clock); 7153 std::vector<double> times; 7154 int nsamples = static_cast<int>(std::ceil(time_limit / r.elapsed)); 7155 times.reserve(nsamples); 7156 std::generate_n(std::back_inserter(times), nsamples, [time_clock, &r] { 7157 return static_cast<double>((time_clock(r.iterations) / r.iterations).count()); 7158 }); 7159 return { 7160 FloatDuration<Clock>(mean(times.begin(), times.end())), 7161 classify_outliers(times.begin(), times.end()), 7162 }; 7163 } 7164 7165 template <typename Clock> 7166 Environment<FloatDuration<Clock>> measure_environment() { 7167 static Environment<FloatDuration<Clock>>* env = nullptr; 7168 if (env) { 7169 return *env; 7170 } 7171 7172 auto iters = Detail::warmup<Clock>(); 7173 auto resolution = Detail::estimate_clock_resolution<Clock>(iters); 7174 auto cost = Detail::estimate_clock_cost<Clock>(resolution.mean); 7175 7176 env = new Environment<FloatDuration<Clock>>{ resolution, cost }; 7177 return *env; 7178 } 7179 } // namespace Detail 7180 } // namespace Benchmark 7181 } // namespace Catch 7182 7183 // end catch_estimate_clock.hpp 7184 // start catch_analyse.hpp 7185 7186 // Run and analyse one benchmark 7187 7188 7189 // start catch_sample_analysis.hpp 7190 7191 // Benchmark results 7192 7193 7194 #include <algorithm> 7195 #include <vector> 7196 #include <string> 7197 #include <iterator> 7198 7199 namespace Catch { 7200 namespace Benchmark { 7201 template <typename Duration> 7202 struct SampleAnalysis { 7203 std::vector<Duration> samples; 7204 Estimate<Duration> mean; 7205 Estimate<Duration> standard_deviation; 7206 OutlierClassification outliers; 7207 double outlier_variance; 7208 7209 template <typename Duration2> 7210 operator SampleAnalysis<Duration2>() const { 7211 std::vector<Duration2> samples2; 7212 samples2.reserve(samples.size()); 7213 std::transform(samples.begin(), samples.end(), std::back_inserter(samples2), [](Duration d) { return Duration2(d); }); 7214 return { 7215 std::move(samples2), 7216 mean, 7217 standard_deviation, 7218 outliers, 7219 outlier_variance, 7220 }; 7221 } 7222 }; 7223 } // namespace Benchmark 7224 } // namespace Catch 7225 7226 // end catch_sample_analysis.hpp 7227 #include <algorithm> 7228 #include <iterator> 7229 #include <vector> 7230 7231 namespace Catch { 7232 namespace Benchmark { 7233 namespace Detail { 7234 template <typename Duration, typename Iterator> 7235 SampleAnalysis<Duration> analyse(const IConfig &cfg, Environment<Duration>, Iterator first, Iterator last) { 7236 if (!cfg.benchmarkNoAnalysis()) { 7237 std::vector<double> samples; 7238 samples.reserve(last - first); 7239 std::transform(first, last, std::back_inserter(samples), [](Duration d) { return d.count(); }); 7240 7241 auto analysis = Catch::Benchmark::Detail::analyse_samples(cfg.benchmarkConfidenceInterval(), cfg.benchmarkResamples(), samples.begin(), samples.end()); 7242 auto outliers = Catch::Benchmark::Detail::classify_outliers(samples.begin(), samples.end()); 7243 7244 auto wrap_estimate = [](Estimate<double> e) { 7245 return Estimate<Duration> { 7246 Duration(e.point), 7247 Duration(e.lower_bound), 7248 Duration(e.upper_bound), 7249 e.confidence_interval, 7250 }; 7251 }; 7252 std::vector<Duration> samples2; 7253 samples2.reserve(samples.size()); 7254 std::transform(samples.begin(), samples.end(), std::back_inserter(samples2), [](double d) { return Duration(d); }); 7255 return { 7256 std::move(samples2), 7257 wrap_estimate(analysis.mean), 7258 wrap_estimate(analysis.standard_deviation), 7259 outliers, 7260 analysis.outlier_variance, 7261 }; 7262 } else { 7263 std::vector<Duration> samples; 7264 samples.reserve(last - first); 7265 7266 Duration mean = Duration(0); 7267 int i = 0; 7268 for (auto it = first; it < last; ++it, ++i) { 7269 samples.push_back(Duration(*it)); 7270 mean += Duration(*it); 7271 } 7272 mean /= i; 7273 7274 return { 7275 std::move(samples), 7276 Estimate<Duration>{mean, mean, mean, 0.0}, 7277 Estimate<Duration>{Duration(0), Duration(0), Duration(0), 0.0}, 7278 OutlierClassification{}, 7279 0.0 7280 }; 7281 } 7282 } 7283 } // namespace Detail 7284 } // namespace Benchmark 7285 } // namespace Catch 7286 7287 // end catch_analyse.hpp 7288 #include <algorithm> 7289 #include <functional> 7290 #include <string> 7291 #include <vector> 7292 #include <cmath> 7293 7294 namespace Catch { 7295 namespace Benchmark { 7296 struct Benchmark { 7297 Benchmark(std::string &&name) 7298 : name(std::move(name)) {} 7299 7300 template <class FUN> 7301 Benchmark(std::string &&name, FUN &&func) 7302 : fun(std::move(func)), name(std::move(name)) {} 7303 7304 template <typename Clock> 7305 ExecutionPlan<FloatDuration<Clock>> prepare(const IConfig &cfg, Environment<FloatDuration<Clock>> env) const { 7306 auto min_time = env.clock_resolution.mean * Detail::minimum_ticks; 7307 auto run_time = std::max(min_time, std::chrono::duration_cast<decltype(min_time)>(cfg.benchmarkWarmupTime())); 7308 auto&& test = Detail::run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(run_time), 1, fun); 7309 int new_iters = static_cast<int>(std::ceil(min_time * test.iterations / test.elapsed)); 7310 return { new_iters, test.elapsed / test.iterations * new_iters * cfg.benchmarkSamples(), fun, std::chrono::duration_cast<FloatDuration<Clock>>(cfg.benchmarkWarmupTime()), Detail::warmup_iterations }; 7311 } 7312 7313 template <typename Clock = default_clock> 7314 void run() { 7315 IConfigPtr cfg = getCurrentContext().getConfig(); 7316 7317 auto env = Detail::measure_environment<Clock>(); 7318 7319 getResultCapture().benchmarkPreparing(name); 7320 CATCH_TRY{ 7321 auto plan = user_code([&] { 7322 return prepare<Clock>(*cfg, env); 7323 }); 7324 7325 BenchmarkInfo info { 7326 name, 7327 plan.estimated_duration.count(), 7328 plan.iterations_per_sample, 7329 cfg->benchmarkSamples(), 7330 cfg->benchmarkResamples(), 7331 env.clock_resolution.mean.count(), 7332 env.clock_cost.mean.count() 7333 }; 7334 7335 getResultCapture().benchmarkStarting(info); 7336 7337 auto samples = user_code([&] { 7338 return plan.template run<Clock>(*cfg, env); 7339 }); 7340 7341 auto analysis = Detail::analyse(*cfg, env, samples.begin(), samples.end()); 7342 BenchmarkStats<FloatDuration<Clock>> stats{ info, analysis.samples, analysis.mean, analysis.standard_deviation, analysis.outliers, analysis.outlier_variance }; 7343 getResultCapture().benchmarkEnded(stats); 7344 7345 } CATCH_CATCH_ALL{ 7346 if (translateActiveException() != Detail::benchmarkErrorMsg) // benchmark errors have been reported, otherwise rethrow. 7347 std::rethrow_exception(std::current_exception()); 7348 } 7349 } 7350 7351 // sets lambda to be used in fun *and* executes benchmark! 7352 template <typename Fun, 7353 typename std::enable_if<!Detail::is_related<Fun, Benchmark>::value, int>::type = 0> 7354 Benchmark & operator=(Fun func) { 7355 fun = Detail::BenchmarkFunction(func); 7356 run(); 7357 return *this; 7358 } 7359 7360 explicit operator bool() { 7361 return true; 7362 } 7363 7364 private: 7365 Detail::BenchmarkFunction fun; 7366 std::string name; 7367 }; 7368 } 7369 } // namespace Catch 7370 7371 #define INTERNAL_CATCH_GET_1_ARG(arg1, arg2, ...) arg1 7372 #define INTERNAL_CATCH_GET_2_ARG(arg1, arg2, ...) arg2 7373 7374 #define INTERNAL_CATCH_BENCHMARK(BenchmarkName, name, benchmarkIndex)\ 7375 if( Catch::Benchmark::Benchmark BenchmarkName{name} ) \ 7376 BenchmarkName = [&](int benchmarkIndex) 7377 7378 #define INTERNAL_CATCH_BENCHMARK_ADVANCED(BenchmarkName, name)\ 7379 if( Catch::Benchmark::Benchmark BenchmarkName{name} ) \ 7380 BenchmarkName = [&] 7381 7382 // end catch_benchmark.hpp 7383 // start catch_constructor.hpp 7384 7385 // Constructor and destructor helpers 7386 7387 7388 #include <type_traits> 7389 7390 namespace Catch { 7391 namespace Benchmark { 7392 namespace Detail { 7393 template <typename T, bool Destruct> 7394 struct ObjectStorage 7395 { 7396 using TStorage = typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type; 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 TStorage 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 0xd4200000") 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 13394 auto lastDot = filename.find_last_of('.'); 13395 if (lastDot != std::string::npos) { 13396 filename.erase(lastDot); 13397 } 13398 13399 tags.push_back(std::move(filename)); 13400 setTags(testCase, tags); 13401 } 13402 } 13403 13404 } // anon namespace 13405 13406 Session::Session() { 13407 static bool alreadyInstantiated = false; 13408 if( alreadyInstantiated ) { 13409 CATCH_TRY { CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" ); } 13410 CATCH_CATCH_ALL { getMutableRegistryHub().registerStartupException(); } 13411 } 13412 13413 // There cannot be exceptions at startup in no-exception mode. 13414 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 13415 const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions(); 13416 if ( !exceptions.empty() ) { 13417 config(); 13418 getCurrentMutableContext().setConfig(m_config); 13419 13420 m_startupExceptions = true; 13421 Colour colourGuard( Colour::Red ); 13422 Catch::cerr() << "Errors occurred during startup!" << '\n'; 13423 // iterate over all exceptions and notify user 13424 for ( const auto& ex_ptr : exceptions ) { 13425 try { 13426 std::rethrow_exception(ex_ptr); 13427 } catch ( std::exception const& ex ) { 13428 Catch::cerr() << Column( ex.what() ).indent(2) << '\n'; 13429 } 13430 } 13431 } 13432 #endif 13433 13434 alreadyInstantiated = true; 13435 m_cli = makeCommandLineParser( m_configData ); 13436 } 13437 Session::~Session() { 13438 Catch::cleanUp(); 13439 } 13440 13441 void Session::showHelp() const { 13442 Catch::cout() 13443 << "\nCatch v" << libraryVersion() << "\n" 13444 << m_cli << std::endl 13445 << "For more detailed usage please see the project docs\n" << std::endl; 13446 } 13447 void Session::libIdentify() { 13448 Catch::cout() 13449 << std::left << std::setw(16) << "description: " << "A Catch2 test executable\n" 13450 << std::left << std::setw(16) << "category: " << "testframework\n" 13451 << std::left << std::setw(16) << "framework: " << "Catch Test\n" 13452 << std::left << std::setw(16) << "version: " << libraryVersion() << std::endl; 13453 } 13454 13455 int Session::applyCommandLine( int argc, char const * const * argv ) { 13456 if( m_startupExceptions ) 13457 return 1; 13458 13459 auto result = m_cli.parse( clara::Args( argc, argv ) ); 13460 if( !result ) { 13461 config(); 13462 getCurrentMutableContext().setConfig(m_config); 13463 Catch::cerr() 13464 << Colour( Colour::Red ) 13465 << "\nError(s) in input:\n" 13466 << Column( result.errorMessage() ).indent( 2 ) 13467 << "\n\n"; 13468 Catch::cerr() << "Run with -? for usage\n" << std::endl; 13469 return MaxExitCode; 13470 } 13471 13472 if( m_configData.showHelp ) 13473 showHelp(); 13474 if( m_configData.libIdentify ) 13475 libIdentify(); 13476 m_config.reset(); 13477 return 0; 13478 } 13479 13480 #if defined(CATCH_CONFIG_WCHAR) && defined(_WIN32) && defined(UNICODE) 13481 int Session::applyCommandLine( int argc, wchar_t const * const * argv ) { 13482 13483 char **utf8Argv = new char *[ argc ]; 13484 13485 for ( int i = 0; i < argc; ++i ) { 13486 int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, nullptr, 0, nullptr, nullptr ); 13487 13488 utf8Argv[ i ] = new char[ bufSize ]; 13489 13490 WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, nullptr, nullptr ); 13491 } 13492 13493 int returnCode = applyCommandLine( argc, utf8Argv ); 13494 13495 for ( int i = 0; i < argc; ++i ) 13496 delete [] utf8Argv[ i ]; 13497 13498 delete [] utf8Argv; 13499 13500 return returnCode; 13501 } 13502 #endif 13503 13504 void Session::useConfigData( ConfigData const& configData ) { 13505 m_configData = configData; 13506 m_config.reset(); 13507 } 13508 13509 int Session::run() { 13510 if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) { 13511 Catch::cout() << "...waiting for enter/ return before starting" << std::endl; 13512 static_cast<void>(std::getchar()); 13513 } 13514 int exitCode = runInternal(); 13515 if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) { 13516 Catch::cout() << "...waiting for enter/ return before exiting, with code: " << exitCode << std::endl; 13517 static_cast<void>(std::getchar()); 13518 } 13519 return exitCode; 13520 } 13521 13522 clara::Parser const& Session::cli() const { 13523 return m_cli; 13524 } 13525 void Session::cli( clara::Parser const& newParser ) { 13526 m_cli = newParser; 13527 } 13528 ConfigData& Session::configData() { 13529 return m_configData; 13530 } 13531 Config& Session::config() { 13532 if( !m_config ) 13533 m_config = std::make_shared<Config>( m_configData ); 13534 return *m_config; 13535 } 13536 13537 int Session::runInternal() { 13538 if( m_startupExceptions ) 13539 return 1; 13540 13541 if (m_configData.showHelp || m_configData.libIdentify) { 13542 return 0; 13543 } 13544 13545 CATCH_TRY { 13546 config(); // Force config to be constructed 13547 13548 seedRng( *m_config ); 13549 13550 if( m_configData.filenamesAsTags ) 13551 applyFilenamesAsTags( *m_config ); 13552 13553 // Handle list request 13554 if( Option<std::size_t> listed = list( m_config ) ) 13555 return static_cast<int>( *listed ); 13556 13557 TestGroup tests { m_config }; 13558 auto const totals = tests.execute(); 13559 13560 if( m_config->warnAboutNoTests() && totals.error == -1 ) 13561 return 2; 13562 13563 // Note that on unices only the lower 8 bits are usually used, clamping 13564 // the return value to 255 prevents false negative when some multiple 13565 // of 256 tests has failed 13566 return (std::min) (MaxExitCode, (std::max) (totals.error, static_cast<int>(totals.assertions.failed))); 13567 } 13568 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 13569 catch( std::exception& ex ) { 13570 Catch::cerr() << ex.what() << std::endl; 13571 return MaxExitCode; 13572 } 13573 #endif 13574 } 13575 13576 } // end namespace Catch 13577 // end catch_session.cpp 13578 // start catch_singletons.cpp 13579 13580 #include <vector> 13581 13582 namespace Catch { 13583 13584 namespace { 13585 static auto getSingletons() -> std::vector<ISingleton*>*& { 13586 static std::vector<ISingleton*>* g_singletons = nullptr; 13587 if( !g_singletons ) 13588 g_singletons = new std::vector<ISingleton*>(); 13589 return g_singletons; 13590 } 13591 } 13592 13593 ISingleton::~ISingleton() {} 13594 13595 void addSingleton(ISingleton* singleton ) { 13596 getSingletons()->push_back( singleton ); 13597 } 13598 void cleanupSingletons() { 13599 auto& singletons = getSingletons(); 13600 for( auto singleton : *singletons ) 13601 delete singleton; 13602 delete singletons; 13603 singletons = nullptr; 13604 } 13605 13606 } // namespace Catch 13607 // end catch_singletons.cpp 13608 // start catch_startup_exception_registry.cpp 13609 13610 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 13611 namespace Catch { 13612 void StartupExceptionRegistry::add( std::exception_ptr const& exception ) noexcept { 13613 CATCH_TRY { 13614 m_exceptions.push_back(exception); 13615 } CATCH_CATCH_ALL { 13616 // If we run out of memory during start-up there's really not a lot more we can do about it 13617 std::terminate(); 13618 } 13619 } 13620 13621 std::vector<std::exception_ptr> const& StartupExceptionRegistry::getExceptions() const noexcept { 13622 return m_exceptions; 13623 } 13624 13625 } // end namespace Catch 13626 #endif 13627 // end catch_startup_exception_registry.cpp 13628 // start catch_stream.cpp 13629 13630 #include <cstdio> 13631 #include <iostream> 13632 #include <fstream> 13633 #include <sstream> 13634 #include <vector> 13635 #include <memory> 13636 13637 namespace Catch { 13638 13639 Catch::IStream::~IStream() = default; 13640 13641 namespace Detail { namespace { 13642 template<typename WriterF, std::size_t bufferSize=256> 13643 class StreamBufImpl : public std::streambuf { 13644 char data[bufferSize]; 13645 WriterF m_writer; 13646 13647 public: 13648 StreamBufImpl() { 13649 setp( data, data + sizeof(data) ); 13650 } 13651 13652 ~StreamBufImpl() noexcept { 13653 StreamBufImpl::sync(); 13654 } 13655 13656 private: 13657 int overflow( int c ) override { 13658 sync(); 13659 13660 if( c != EOF ) { 13661 if( pbase() == epptr() ) 13662 m_writer( std::string( 1, static_cast<char>( c ) ) ); 13663 else 13664 sputc( static_cast<char>( c ) ); 13665 } 13666 return 0; 13667 } 13668 13669 int sync() override { 13670 if( pbase() != pptr() ) { 13671 m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) ); 13672 setp( pbase(), epptr() ); 13673 } 13674 return 0; 13675 } 13676 }; 13677 13678 /////////////////////////////////////////////////////////////////////////// 13679 13680 struct OutputDebugWriter { 13681 13682 void operator()( std::string const&str ) { 13683 writeToDebugConsole( str ); 13684 } 13685 }; 13686 13687 /////////////////////////////////////////////////////////////////////////// 13688 13689 class FileStream : public IStream { 13690 mutable std::ofstream m_ofs; 13691 public: 13692 FileStream( StringRef filename ) { 13693 m_ofs.open( filename.c_str() ); 13694 CATCH_ENFORCE( !m_ofs.fail(), "Unable to open file: '" << filename << "'" ); 13695 } 13696 ~FileStream() override = default; 13697 public: // IStream 13698 std::ostream& stream() const override { 13699 return m_ofs; 13700 } 13701 }; 13702 13703 /////////////////////////////////////////////////////////////////////////// 13704 13705 class CoutStream : public IStream { 13706 mutable std::ostream m_os; 13707 public: 13708 // Store the streambuf from cout up-front because 13709 // cout may get redirected when running tests 13710 CoutStream() : m_os( Catch::cout().rdbuf() ) {} 13711 ~CoutStream() override = default; 13712 13713 public: // IStream 13714 std::ostream& stream() const override { return m_os; } 13715 }; 13716 13717 /////////////////////////////////////////////////////////////////////////// 13718 13719 class DebugOutStream : public IStream { 13720 std::unique_ptr<StreamBufImpl<OutputDebugWriter>> m_streamBuf; 13721 mutable std::ostream m_os; 13722 public: 13723 DebugOutStream() 13724 : m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ), 13725 m_os( m_streamBuf.get() ) 13726 {} 13727 13728 ~DebugOutStream() override = default; 13729 13730 public: // IStream 13731 std::ostream& stream() const override { return m_os; } 13732 }; 13733 13734 }} // namespace anon::detail 13735 13736 /////////////////////////////////////////////////////////////////////////// 13737 13738 auto makeStream( StringRef const &filename ) -> IStream const* { 13739 if( filename.empty() ) 13740 return new Detail::CoutStream(); 13741 else if( filename[0] == '%' ) { 13742 if( filename == "%debug" ) 13743 return new Detail::DebugOutStream(); 13744 else 13745 CATCH_ERROR( "Unrecognised stream: '" << filename << "'" ); 13746 } 13747 else 13748 return new Detail::FileStream( filename ); 13749 } 13750 13751 // This class encapsulates the idea of a pool of ostringstreams that can be reused. 13752 struct StringStreams { 13753 std::vector<std::unique_ptr<std::ostringstream>> m_streams; 13754 std::vector<std::size_t> m_unused; 13755 std::ostringstream m_referenceStream; // Used for copy state/ flags from 13756 13757 auto add() -> std::size_t { 13758 if( m_unused.empty() ) { 13759 m_streams.push_back( std::unique_ptr<std::ostringstream>( new std::ostringstream ) ); 13760 return m_streams.size()-1; 13761 } 13762 else { 13763 auto index = m_unused.back(); 13764 m_unused.pop_back(); 13765 return index; 13766 } 13767 } 13768 13769 void release( std::size_t index ) { 13770 m_streams[index]->copyfmt( m_referenceStream ); // Restore initial flags and other state 13771 m_unused.push_back(index); 13772 } 13773 }; 13774 13775 ReusableStringStream::ReusableStringStream() 13776 : m_index( Singleton<StringStreams>::getMutable().add() ), 13777 m_oss( Singleton<StringStreams>::getMutable().m_streams[m_index].get() ) 13778 {} 13779 13780 ReusableStringStream::~ReusableStringStream() { 13781 static_cast<std::ostringstream*>( m_oss )->str(""); 13782 m_oss->clear(); 13783 Singleton<StringStreams>::getMutable().release( m_index ); 13784 } 13785 13786 auto ReusableStringStream::str() const -> std::string { 13787 return static_cast<std::ostringstream*>( m_oss )->str(); 13788 } 13789 13790 /////////////////////////////////////////////////////////////////////////// 13791 13792 #ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions 13793 std::ostream& cout() { return std::cout; } 13794 std::ostream& cerr() { return std::cerr; } 13795 std::ostream& clog() { return std::clog; } 13796 #endif 13797 } 13798 // end catch_stream.cpp 13799 // start catch_string_manip.cpp 13800 13801 #include <algorithm> 13802 #include <ostream> 13803 #include <cstring> 13804 #include <cctype> 13805 #include <vector> 13806 13807 namespace Catch { 13808 13809 namespace { 13810 char toLowerCh(char c) { 13811 return static_cast<char>( std::tolower( static_cast<unsigned char>(c) ) ); 13812 } 13813 } 13814 13815 bool startsWith( std::string const& s, std::string const& prefix ) { 13816 return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin()); 13817 } 13818 bool startsWith( std::string const& s, char prefix ) { 13819 return !s.empty() && s[0] == prefix; 13820 } 13821 bool endsWith( std::string const& s, std::string const& suffix ) { 13822 return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin()); 13823 } 13824 bool endsWith( std::string const& s, char suffix ) { 13825 return !s.empty() && s[s.size()-1] == suffix; 13826 } 13827 bool contains( std::string const& s, std::string const& infix ) { 13828 return s.find( infix ) != std::string::npos; 13829 } 13830 void toLowerInPlace( std::string& s ) { 13831 std::transform( s.begin(), s.end(), s.begin(), toLowerCh ); 13832 } 13833 std::string toLower( std::string const& s ) { 13834 std::string lc = s; 13835 toLowerInPlace( lc ); 13836 return lc; 13837 } 13838 std::string trim( std::string const& str ) { 13839 static char const* whitespaceChars = "\n\r\t "; 13840 std::string::size_type start = str.find_first_not_of( whitespaceChars ); 13841 std::string::size_type end = str.find_last_not_of( whitespaceChars ); 13842 13843 return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string(); 13844 } 13845 13846 StringRef trim(StringRef ref) { 13847 const auto is_ws = [](char c) { 13848 return c == ' ' || c == '\t' || c == '\n' || c == '\r'; 13849 }; 13850 size_t real_begin = 0; 13851 while (real_begin < ref.size() && is_ws(ref[real_begin])) { ++real_begin; } 13852 size_t real_end = ref.size(); 13853 while (real_end > real_begin && is_ws(ref[real_end - 1])) { --real_end; } 13854 13855 return ref.substr(real_begin, real_end - real_begin); 13856 } 13857 13858 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) { 13859 bool replaced = false; 13860 std::size_t i = str.find( replaceThis ); 13861 while( i != std::string::npos ) { 13862 replaced = true; 13863 str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() ); 13864 if( i < str.size()-withThis.size() ) 13865 i = str.find( replaceThis, i+withThis.size() ); 13866 else 13867 i = std::string::npos; 13868 } 13869 return replaced; 13870 } 13871 13872 std::vector<StringRef> splitStringRef( StringRef str, char delimiter ) { 13873 std::vector<StringRef> subStrings; 13874 std::size_t start = 0; 13875 for(std::size_t pos = 0; pos < str.size(); ++pos ) { 13876 if( str[pos] == delimiter ) { 13877 if( pos - start > 1 ) 13878 subStrings.push_back( str.substr( start, pos-start ) ); 13879 start = pos+1; 13880 } 13881 } 13882 if( start < str.size() ) 13883 subStrings.push_back( str.substr( start, str.size()-start ) ); 13884 return subStrings; 13885 } 13886 13887 pluralise::pluralise( std::size_t count, std::string const& label ) 13888 : m_count( count ), 13889 m_label( label ) 13890 {} 13891 13892 std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { 13893 os << pluraliser.m_count << ' ' << pluraliser.m_label; 13894 if( pluraliser.m_count != 1 ) 13895 os << 's'; 13896 return os; 13897 } 13898 13899 } 13900 // end catch_string_manip.cpp 13901 // start catch_stringref.cpp 13902 13903 #include <algorithm> 13904 #include <ostream> 13905 #include <cstring> 13906 #include <cstdint> 13907 13908 namespace Catch { 13909 StringRef::StringRef( char const* rawChars ) noexcept 13910 : StringRef( rawChars, static_cast<StringRef::size_type>(std::strlen(rawChars) ) ) 13911 {} 13912 13913 auto StringRef::c_str() const -> char const* { 13914 CATCH_ENFORCE(isNullTerminated(), "Called StringRef::c_str() on a non-null-terminated instance"); 13915 return m_start; 13916 } 13917 auto StringRef::data() const noexcept -> char const* { 13918 return m_start; 13919 } 13920 13921 auto StringRef::substr( size_type start, size_type size ) const noexcept -> StringRef { 13922 if (start < m_size) { 13923 return StringRef(m_start + start, (std::min)(m_size - start, size)); 13924 } else { 13925 return StringRef(); 13926 } 13927 } 13928 auto StringRef::operator == ( StringRef const& other ) const noexcept -> bool { 13929 return m_size == other.m_size 13930 && (std::memcmp( m_start, other.m_start, m_size ) == 0); 13931 } 13932 13933 auto operator << ( std::ostream& os, StringRef const& str ) -> std::ostream& { 13934 return os.write(str.data(), str.size()); 13935 } 13936 13937 auto operator+=( std::string& lhs, StringRef const& rhs ) -> std::string& { 13938 lhs.append(rhs.data(), rhs.size()); 13939 return lhs; 13940 } 13941 13942 } // namespace Catch 13943 // end catch_stringref.cpp 13944 // start catch_tag_alias.cpp 13945 13946 namespace Catch { 13947 TagAlias::TagAlias(std::string const & _tag, SourceLineInfo _lineInfo): tag(_tag), lineInfo(_lineInfo) {} 13948 } 13949 // end catch_tag_alias.cpp 13950 // start catch_tag_alias_autoregistrar.cpp 13951 13952 namespace Catch { 13953 13954 RegistrarForTagAliases::RegistrarForTagAliases(char const* alias, char const* tag, SourceLineInfo const& lineInfo) { 13955 CATCH_TRY { 13956 getMutableRegistryHub().registerTagAlias(alias, tag, lineInfo); 13957 } CATCH_CATCH_ALL { 13958 // Do not throw when constructing global objects, instead register the exception to be processed later 13959 getMutableRegistryHub().registerStartupException(); 13960 } 13961 } 13962 13963 } 13964 // end catch_tag_alias_autoregistrar.cpp 13965 // start catch_tag_alias_registry.cpp 13966 13967 #include <sstream> 13968 13969 namespace Catch { 13970 13971 TagAliasRegistry::~TagAliasRegistry() {} 13972 13973 TagAlias const* TagAliasRegistry::find( std::string const& alias ) const { 13974 auto it = m_registry.find( alias ); 13975 if( it != m_registry.end() ) 13976 return &(it->second); 13977 else 13978 return nullptr; 13979 } 13980 13981 std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const { 13982 std::string expandedTestSpec = unexpandedTestSpec; 13983 for( auto const& registryKvp : m_registry ) { 13984 std::size_t pos = expandedTestSpec.find( registryKvp.first ); 13985 if( pos != std::string::npos ) { 13986 expandedTestSpec = expandedTestSpec.substr( 0, pos ) + 13987 registryKvp.second.tag + 13988 expandedTestSpec.substr( pos + registryKvp.first.size() ); 13989 } 13990 } 13991 return expandedTestSpec; 13992 } 13993 13994 void TagAliasRegistry::add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) { 13995 CATCH_ENFORCE( startsWith(alias, "[@") && endsWith(alias, ']'), 13996 "error: tag alias, '" << alias << "' is not of the form [@alias name].\n" << lineInfo ); 13997 13998 CATCH_ENFORCE( m_registry.insert(std::make_pair(alias, TagAlias(tag, lineInfo))).second, 13999 "error: tag alias, '" << alias << "' already registered.\n" 14000 << "\tFirst seen at: " << find(alias)->lineInfo << "\n" 14001 << "\tRedefined at: " << lineInfo ); 14002 } 14003 14004 ITagAliasRegistry::~ITagAliasRegistry() {} 14005 14006 ITagAliasRegistry const& ITagAliasRegistry::get() { 14007 return getRegistryHub().getTagAliasRegistry(); 14008 } 14009 14010 } // end namespace Catch 14011 // end catch_tag_alias_registry.cpp 14012 // start catch_test_case_info.cpp 14013 14014 #include <cctype> 14015 #include <exception> 14016 #include <algorithm> 14017 #include <sstream> 14018 14019 namespace Catch { 14020 14021 namespace { 14022 TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) { 14023 if( startsWith( tag, '.' ) || 14024 tag == "!hide" ) 14025 return TestCaseInfo::IsHidden; 14026 else if( tag == "!throws" ) 14027 return TestCaseInfo::Throws; 14028 else if( tag == "!shouldfail" ) 14029 return TestCaseInfo::ShouldFail; 14030 else if( tag == "!mayfail" ) 14031 return TestCaseInfo::MayFail; 14032 else if( tag == "!nonportable" ) 14033 return TestCaseInfo::NonPortable; 14034 else if( tag == "!benchmark" ) 14035 return static_cast<TestCaseInfo::SpecialProperties>( TestCaseInfo::Benchmark | TestCaseInfo::IsHidden ); 14036 else 14037 return TestCaseInfo::None; 14038 } 14039 bool isReservedTag( std::string const& tag ) { 14040 return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( static_cast<unsigned char>(tag[0]) ); 14041 } 14042 void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { 14043 CATCH_ENFORCE( !isReservedTag(tag), 14044 "Tag name: [" << tag << "] is not allowed.\n" 14045 << "Tag names starting with non alphanumeric characters are reserved\n" 14046 << _lineInfo ); 14047 } 14048 } 14049 14050 TestCase makeTestCase( ITestInvoker* _testCase, 14051 std::string const& _className, 14052 NameAndTags const& nameAndTags, 14053 SourceLineInfo const& _lineInfo ) 14054 { 14055 bool isHidden = false; 14056 14057 // Parse out tags 14058 std::vector<std::string> tags; 14059 std::string desc, tag; 14060 bool inTag = false; 14061 for (char c : nameAndTags.tags) { 14062 if( !inTag ) { 14063 if( c == '[' ) 14064 inTag = true; 14065 else 14066 desc += c; 14067 } 14068 else { 14069 if( c == ']' ) { 14070 TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag ); 14071 if( ( prop & TestCaseInfo::IsHidden ) != 0 ) 14072 isHidden = true; 14073 else if( prop == TestCaseInfo::None ) 14074 enforceNotReservedTag( tag, _lineInfo ); 14075 14076 // Merged hide tags like `[.approvals]` should be added as 14077 // `[.][approvals]`. The `[.]` is added at later point, so 14078 // we only strip the prefix 14079 if (startsWith(tag, '.') && tag.size() > 1) { 14080 tag.erase(0, 1); 14081 } 14082 tags.push_back( tag ); 14083 tag.clear(); 14084 inTag = false; 14085 } 14086 else 14087 tag += c; 14088 } 14089 } 14090 if( isHidden ) { 14091 // Add all "hidden" tags to make them behave identically 14092 tags.insert( tags.end(), { ".", "!hide" } ); 14093 } 14094 14095 TestCaseInfo info( static_cast<std::string>(nameAndTags.name), _className, desc, tags, _lineInfo ); 14096 return TestCase( _testCase, std::move(info) ); 14097 } 14098 14099 void setTags( TestCaseInfo& testCaseInfo, std::vector<std::string> tags ) { 14100 std::sort(begin(tags), end(tags)); 14101 tags.erase(std::unique(begin(tags), end(tags)), end(tags)); 14102 testCaseInfo.lcaseTags.clear(); 14103 14104 for( auto const& tag : tags ) { 14105 std::string lcaseTag = toLower( tag ); 14106 testCaseInfo.properties = static_cast<TestCaseInfo::SpecialProperties>( testCaseInfo.properties | parseSpecialTag( lcaseTag ) ); 14107 testCaseInfo.lcaseTags.push_back( lcaseTag ); 14108 } 14109 testCaseInfo.tags = std::move(tags); 14110 } 14111 14112 TestCaseInfo::TestCaseInfo( std::string const& _name, 14113 std::string const& _className, 14114 std::string const& _description, 14115 std::vector<std::string> const& _tags, 14116 SourceLineInfo const& _lineInfo ) 14117 : name( _name ), 14118 className( _className ), 14119 description( _description ), 14120 lineInfo( _lineInfo ), 14121 properties( None ) 14122 { 14123 setTags( *this, _tags ); 14124 } 14125 14126 bool TestCaseInfo::isHidden() const { 14127 return ( properties & IsHidden ) != 0; 14128 } 14129 bool TestCaseInfo::throws() const { 14130 return ( properties & Throws ) != 0; 14131 } 14132 bool TestCaseInfo::okToFail() const { 14133 return ( properties & (ShouldFail | MayFail ) ) != 0; 14134 } 14135 bool TestCaseInfo::expectedToFail() const { 14136 return ( properties & (ShouldFail ) ) != 0; 14137 } 14138 14139 std::string TestCaseInfo::tagsAsString() const { 14140 std::string ret; 14141 // '[' and ']' per tag 14142 std::size_t full_size = 2 * tags.size(); 14143 for (const auto& tag : tags) { 14144 full_size += tag.size(); 14145 } 14146 ret.reserve(full_size); 14147 for (const auto& tag : tags) { 14148 ret.push_back('['); 14149 ret.append(tag); 14150 ret.push_back(']'); 14151 } 14152 14153 return ret; 14154 } 14155 14156 TestCase::TestCase( ITestInvoker* testCase, TestCaseInfo&& info ) : TestCaseInfo( std::move(info) ), test( testCase ) {} 14157 14158 TestCase TestCase::withName( std::string const& _newName ) const { 14159 TestCase other( *this ); 14160 other.name = _newName; 14161 return other; 14162 } 14163 14164 void TestCase::invoke() const { 14165 test->invoke(); 14166 } 14167 14168 bool TestCase::operator == ( TestCase const& other ) const { 14169 return test.get() == other.test.get() && 14170 name == other.name && 14171 className == other.className; 14172 } 14173 14174 bool TestCase::operator < ( TestCase const& other ) const { 14175 return name < other.name; 14176 } 14177 14178 TestCaseInfo const& TestCase::getTestCaseInfo() const 14179 { 14180 return *this; 14181 } 14182 14183 } // end namespace Catch 14184 // end catch_test_case_info.cpp 14185 // start catch_test_case_registry_impl.cpp 14186 14187 #include <algorithm> 14188 #include <sstream> 14189 14190 namespace Catch { 14191 14192 namespace { 14193 struct TestHasher { 14194 using hash_t = uint64_t; 14195 14196 explicit TestHasher( hash_t hashSuffix ): 14197 m_hashSuffix{ hashSuffix } {} 14198 14199 uint32_t operator()( TestCase const& t ) const { 14200 // FNV-1a hash with multiplication fold. 14201 const hash_t prime = 1099511628211u; 14202 hash_t hash = 14695981039346656037u; 14203 for ( const char c : t.name ) { 14204 hash ^= c; 14205 hash *= prime; 14206 } 14207 hash ^= m_hashSuffix; 14208 hash *= prime; 14209 const uint32_t low{ static_cast<uint32_t>( hash ) }; 14210 const uint32_t high{ static_cast<uint32_t>( hash >> 32 ) }; 14211 return low * high; 14212 } 14213 14214 private: 14215 hash_t m_hashSuffix; 14216 }; 14217 } // end unnamed namespace 14218 14219 std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) { 14220 switch( config.runOrder() ) { 14221 case RunTests::InDeclarationOrder: 14222 // already in declaration order 14223 break; 14224 14225 case RunTests::InLexicographicalOrder: { 14226 std::vector<TestCase> sorted = unsortedTestCases; 14227 std::sort( sorted.begin(), sorted.end() ); 14228 return sorted; 14229 } 14230 14231 case RunTests::InRandomOrder: { 14232 seedRng( config ); 14233 TestHasher h{ config.rngSeed() }; 14234 14235 using hashedTest = std::pair<TestHasher::hash_t, TestCase const*>; 14236 std::vector<hashedTest> indexed_tests; 14237 indexed_tests.reserve( unsortedTestCases.size() ); 14238 14239 for (auto const& testCase : unsortedTestCases) { 14240 indexed_tests.emplace_back(h(testCase), &testCase); 14241 } 14242 14243 std::sort(indexed_tests.begin(), indexed_tests.end(), 14244 [](hashedTest const& lhs, hashedTest const& rhs) { 14245 if (lhs.first == rhs.first) { 14246 return lhs.second->name < rhs.second->name; 14247 } 14248 return lhs.first < rhs.first; 14249 }); 14250 14251 std::vector<TestCase> sorted; 14252 sorted.reserve( indexed_tests.size() ); 14253 14254 for (auto const& hashed : indexed_tests) { 14255 sorted.emplace_back(*hashed.second); 14256 } 14257 14258 return sorted; 14259 } 14260 } 14261 return unsortedTestCases; 14262 } 14263 14264 bool isThrowSafe( TestCase const& testCase, IConfig const& config ) { 14265 return !testCase.throws() || config.allowThrows(); 14266 } 14267 14268 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) { 14269 return testSpec.matches( testCase ) && isThrowSafe( testCase, config ); 14270 } 14271 14272 void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) { 14273 std::set<TestCase> seenFunctions; 14274 for( auto const& function : functions ) { 14275 auto prev = seenFunctions.insert( function ); 14276 CATCH_ENFORCE( prev.second, 14277 "error: TEST_CASE( \"" << function.name << "\" ) already defined.\n" 14278 << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n" 14279 << "\tRedefined at " << function.getTestCaseInfo().lineInfo ); 14280 } 14281 } 14282 14283 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) { 14284 std::vector<TestCase> filtered; 14285 filtered.reserve( testCases.size() ); 14286 for (auto const& testCase : testCases) { 14287 if ((!testSpec.hasFilters() && !testCase.isHidden()) || 14288 (testSpec.hasFilters() && matchTest(testCase, testSpec, config))) { 14289 filtered.push_back(testCase); 14290 } 14291 } 14292 return filtered; 14293 } 14294 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) { 14295 return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config ); 14296 } 14297 14298 void TestRegistry::registerTest( TestCase const& testCase ) { 14299 std::string name = testCase.getTestCaseInfo().name; 14300 if( name.empty() ) { 14301 ReusableStringStream rss; 14302 rss << "Anonymous test case " << ++m_unnamedCount; 14303 return registerTest( testCase.withName( rss.str() ) ); 14304 } 14305 m_functions.push_back( testCase ); 14306 } 14307 14308 std::vector<TestCase> const& TestRegistry::getAllTests() const { 14309 return m_functions; 14310 } 14311 std::vector<TestCase> const& TestRegistry::getAllTestsSorted( IConfig const& config ) const { 14312 if( m_sortedFunctions.empty() ) 14313 enforceNoDuplicateTestCases( m_functions ); 14314 14315 if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) { 14316 m_sortedFunctions = sortTests( config, m_functions ); 14317 m_currentSortOrder = config.runOrder(); 14318 } 14319 return m_sortedFunctions; 14320 } 14321 14322 /////////////////////////////////////////////////////////////////////////// 14323 TestInvokerAsFunction::TestInvokerAsFunction( void(*testAsFunction)() ) noexcept : m_testAsFunction( testAsFunction ) {} 14324 14325 void TestInvokerAsFunction::invoke() const { 14326 m_testAsFunction(); 14327 } 14328 14329 std::string extractClassName( StringRef const& classOrQualifiedMethodName ) { 14330 std::string className(classOrQualifiedMethodName); 14331 if( startsWith( className, '&' ) ) 14332 { 14333 std::size_t lastColons = className.rfind( "::" ); 14334 std::size_t penultimateColons = className.rfind( "::", lastColons-1 ); 14335 if( penultimateColons == std::string::npos ) 14336 penultimateColons = 1; 14337 className = className.substr( penultimateColons, lastColons-penultimateColons ); 14338 } 14339 return className; 14340 } 14341 14342 } // end namespace Catch 14343 // end catch_test_case_registry_impl.cpp 14344 // start catch_test_case_tracker.cpp 14345 14346 #include <algorithm> 14347 #include <cassert> 14348 #include <stdexcept> 14349 #include <memory> 14350 #include <sstream> 14351 14352 #if defined(__clang__) 14353 # pragma clang diagnostic push 14354 # pragma clang diagnostic ignored "-Wexit-time-destructors" 14355 #endif 14356 14357 namespace Catch { 14358 namespace TestCaseTracking { 14359 14360 NameAndLocation::NameAndLocation( std::string const& _name, SourceLineInfo const& _location ) 14361 : name( _name ), 14362 location( _location ) 14363 {} 14364 14365 ITracker::~ITracker() = default; 14366 14367 ITracker& TrackerContext::startRun() { 14368 m_rootTracker = std::make_shared<SectionTracker>( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, nullptr ); 14369 m_currentTracker = nullptr; 14370 m_runState = Executing; 14371 return *m_rootTracker; 14372 } 14373 14374 void TrackerContext::endRun() { 14375 m_rootTracker.reset(); 14376 m_currentTracker = nullptr; 14377 m_runState = NotStarted; 14378 } 14379 14380 void TrackerContext::startCycle() { 14381 m_currentTracker = m_rootTracker.get(); 14382 m_runState = Executing; 14383 } 14384 void TrackerContext::completeCycle() { 14385 m_runState = CompletedCycle; 14386 } 14387 14388 bool TrackerContext::completedCycle() const { 14389 return m_runState == CompletedCycle; 14390 } 14391 ITracker& TrackerContext::currentTracker() { 14392 return *m_currentTracker; 14393 } 14394 void TrackerContext::setCurrentTracker( ITracker* tracker ) { 14395 m_currentTracker = tracker; 14396 } 14397 14398 TrackerBase::TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ): 14399 ITracker(nameAndLocation), 14400 m_ctx( ctx ), 14401 m_parent( parent ) 14402 {} 14403 14404 bool TrackerBase::isComplete() const { 14405 return m_runState == CompletedSuccessfully || m_runState == Failed; 14406 } 14407 bool TrackerBase::isSuccessfullyCompleted() const { 14408 return m_runState == CompletedSuccessfully; 14409 } 14410 bool TrackerBase::isOpen() const { 14411 return m_runState != NotStarted && !isComplete(); 14412 } 14413 bool TrackerBase::hasChildren() const { 14414 return !m_children.empty(); 14415 } 14416 14417 void TrackerBase::addChild( ITrackerPtr const& child ) { 14418 m_children.push_back( child ); 14419 } 14420 14421 ITrackerPtr TrackerBase::findChild( NameAndLocation const& nameAndLocation ) { 14422 auto it = std::find_if( m_children.begin(), m_children.end(), 14423 [&nameAndLocation]( ITrackerPtr const& tracker ){ 14424 return 14425 tracker->nameAndLocation().location == nameAndLocation.location && 14426 tracker->nameAndLocation().name == nameAndLocation.name; 14427 } ); 14428 return( it != m_children.end() ) 14429 ? *it 14430 : nullptr; 14431 } 14432 ITracker& TrackerBase::parent() { 14433 assert( m_parent ); // Should always be non-null except for root 14434 return *m_parent; 14435 } 14436 14437 void TrackerBase::openChild() { 14438 if( m_runState != ExecutingChildren ) { 14439 m_runState = ExecutingChildren; 14440 if( m_parent ) 14441 m_parent->openChild(); 14442 } 14443 } 14444 14445 bool TrackerBase::isSectionTracker() const { return false; } 14446 bool TrackerBase::isGeneratorTracker() const { return false; } 14447 14448 void TrackerBase::open() { 14449 m_runState = Executing; 14450 moveToThis(); 14451 if( m_parent ) 14452 m_parent->openChild(); 14453 } 14454 14455 void TrackerBase::close() { 14456 14457 // Close any still open children (e.g. generators) 14458 while( &m_ctx.currentTracker() != this ) 14459 m_ctx.currentTracker().close(); 14460 14461 switch( m_runState ) { 14462 case NeedsAnotherRun: 14463 break; 14464 14465 case Executing: 14466 m_runState = CompletedSuccessfully; 14467 break; 14468 case ExecutingChildren: 14469 if( std::all_of(m_children.begin(), m_children.end(), [](ITrackerPtr const& t){ return t->isComplete(); }) ) 14470 m_runState = CompletedSuccessfully; 14471 break; 14472 14473 case NotStarted: 14474 case CompletedSuccessfully: 14475 case Failed: 14476 CATCH_INTERNAL_ERROR( "Illogical state: " << m_runState ); 14477 14478 default: 14479 CATCH_INTERNAL_ERROR( "Unknown state: " << m_runState ); 14480 } 14481 moveToParent(); 14482 m_ctx.completeCycle(); 14483 } 14484 void TrackerBase::fail() { 14485 m_runState = Failed; 14486 if( m_parent ) 14487 m_parent->markAsNeedingAnotherRun(); 14488 moveToParent(); 14489 m_ctx.completeCycle(); 14490 } 14491 void TrackerBase::markAsNeedingAnotherRun() { 14492 m_runState = NeedsAnotherRun; 14493 } 14494 14495 void TrackerBase::moveToParent() { 14496 assert( m_parent ); 14497 m_ctx.setCurrentTracker( m_parent ); 14498 } 14499 void TrackerBase::moveToThis() { 14500 m_ctx.setCurrentTracker( this ); 14501 } 14502 14503 SectionTracker::SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) 14504 : TrackerBase( nameAndLocation, ctx, parent ), 14505 m_trimmed_name(trim(nameAndLocation.name)) 14506 { 14507 if( parent ) { 14508 while( !parent->isSectionTracker() ) 14509 parent = &parent->parent(); 14510 14511 SectionTracker& parentSection = static_cast<SectionTracker&>( *parent ); 14512 addNextFilters( parentSection.m_filters ); 14513 } 14514 } 14515 14516 bool SectionTracker::isComplete() const { 14517 bool complete = true; 14518 14519 if (m_filters.empty() 14520 || m_filters[0] == "" 14521 || std::find(m_filters.begin(), m_filters.end(), m_trimmed_name) != m_filters.end()) { 14522 complete = TrackerBase::isComplete(); 14523 } 14524 return complete; 14525 } 14526 14527 bool SectionTracker::isSectionTracker() const { return true; } 14528 14529 SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) { 14530 std::shared_ptr<SectionTracker> section; 14531 14532 ITracker& currentTracker = ctx.currentTracker(); 14533 if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) { 14534 assert( childTracker ); 14535 assert( childTracker->isSectionTracker() ); 14536 section = std::static_pointer_cast<SectionTracker>( childTracker ); 14537 } 14538 else { 14539 section = std::make_shared<SectionTracker>( nameAndLocation, ctx, ¤tTracker ); 14540 currentTracker.addChild( section ); 14541 } 14542 if( !ctx.completedCycle() ) 14543 section->tryOpen(); 14544 return *section; 14545 } 14546 14547 void SectionTracker::tryOpen() { 14548 if( !isComplete() ) 14549 open(); 14550 } 14551 14552 void SectionTracker::addInitialFilters( std::vector<std::string> const& filters ) { 14553 if( !filters.empty() ) { 14554 m_filters.reserve( m_filters.size() + filters.size() + 2 ); 14555 m_filters.emplace_back(""); // Root - should never be consulted 14556 m_filters.emplace_back(""); // Test Case - not a section filter 14557 m_filters.insert( m_filters.end(), filters.begin(), filters.end() ); 14558 } 14559 } 14560 void SectionTracker::addNextFilters( std::vector<std::string> const& filters ) { 14561 if( filters.size() > 1 ) 14562 m_filters.insert( m_filters.end(), filters.begin()+1, filters.end() ); 14563 } 14564 14565 std::vector<std::string> const& SectionTracker::getFilters() const { 14566 return m_filters; 14567 } 14568 14569 std::string const& SectionTracker::trimmedName() const { 14570 return m_trimmed_name; 14571 } 14572 14573 } // namespace TestCaseTracking 14574 14575 using TestCaseTracking::ITracker; 14576 using TestCaseTracking::TrackerContext; 14577 using TestCaseTracking::SectionTracker; 14578 14579 } // namespace Catch 14580 14581 #if defined(__clang__) 14582 # pragma clang diagnostic pop 14583 #endif 14584 // end catch_test_case_tracker.cpp 14585 // start catch_test_registry.cpp 14586 14587 namespace Catch { 14588 14589 auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker* { 14590 return new(std::nothrow) TestInvokerAsFunction( testAsFunction ); 14591 } 14592 14593 NameAndTags::NameAndTags( StringRef const& name_ , StringRef const& tags_ ) noexcept : name( name_ ), tags( tags_ ) {} 14594 14595 AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept { 14596 CATCH_TRY { 14597 getMutableRegistryHub() 14598 .registerTest( 14599 makeTestCase( 14600 invoker, 14601 extractClassName( classOrMethod ), 14602 nameAndTags, 14603 lineInfo)); 14604 } CATCH_CATCH_ALL { 14605 // Do not throw when constructing global objects, instead register the exception to be processed later 14606 getMutableRegistryHub().registerStartupException(); 14607 } 14608 } 14609 14610 AutoReg::~AutoReg() = default; 14611 } 14612 // end catch_test_registry.cpp 14613 // start catch_test_spec.cpp 14614 14615 #include <algorithm> 14616 #include <string> 14617 #include <vector> 14618 #include <memory> 14619 14620 namespace Catch { 14621 14622 TestSpec::Pattern::Pattern( std::string const& name ) 14623 : m_name( name ) 14624 {} 14625 14626 TestSpec::Pattern::~Pattern() = default; 14627 14628 std::string const& TestSpec::Pattern::name() const { 14629 return m_name; 14630 } 14631 14632 TestSpec::NamePattern::NamePattern( std::string const& name, std::string const& filterString ) 14633 : Pattern( filterString ) 14634 , m_wildcardPattern( toLower( name ), CaseSensitive::No ) 14635 {} 14636 14637 bool TestSpec::NamePattern::matches( TestCaseInfo const& testCase ) const { 14638 return m_wildcardPattern.matches( testCase.name ); 14639 } 14640 14641 TestSpec::TagPattern::TagPattern( std::string const& tag, std::string const& filterString ) 14642 : Pattern( filterString ) 14643 , m_tag( toLower( tag ) ) 14644 {} 14645 14646 bool TestSpec::TagPattern::matches( TestCaseInfo const& testCase ) const { 14647 return std::find(begin(testCase.lcaseTags), 14648 end(testCase.lcaseTags), 14649 m_tag) != end(testCase.lcaseTags); 14650 } 14651 14652 TestSpec::ExcludedPattern::ExcludedPattern( PatternPtr const& underlyingPattern ) 14653 : Pattern( underlyingPattern->name() ) 14654 , m_underlyingPattern( underlyingPattern ) 14655 {} 14656 14657 bool TestSpec::ExcludedPattern::matches( TestCaseInfo const& testCase ) const { 14658 return !m_underlyingPattern->matches( testCase ); 14659 } 14660 14661 bool TestSpec::Filter::matches( TestCaseInfo const& testCase ) const { 14662 return std::all_of( m_patterns.begin(), m_patterns.end(), [&]( PatternPtr const& p ){ return p->matches( testCase ); } ); 14663 } 14664 14665 std::string TestSpec::Filter::name() const { 14666 std::string name; 14667 for( auto const& p : m_patterns ) 14668 name += p->name(); 14669 return name; 14670 } 14671 14672 bool TestSpec::hasFilters() const { 14673 return !m_filters.empty(); 14674 } 14675 14676 bool TestSpec::matches( TestCaseInfo const& testCase ) const { 14677 return std::any_of( m_filters.begin(), m_filters.end(), [&]( Filter const& f ){ return f.matches( testCase ); } ); 14678 } 14679 14680 TestSpec::Matches TestSpec::matchesByFilter( std::vector<TestCase> const& testCases, IConfig const& config ) const 14681 { 14682 Matches matches( m_filters.size() ); 14683 std::transform( m_filters.begin(), m_filters.end(), matches.begin(), [&]( Filter const& filter ){ 14684 std::vector<TestCase const*> currentMatches; 14685 for( auto const& test : testCases ) 14686 if( isThrowSafe( test, config ) && filter.matches( test ) ) 14687 currentMatches.emplace_back( &test ); 14688 return FilterMatch{ filter.name(), currentMatches }; 14689 } ); 14690 return matches; 14691 } 14692 14693 const TestSpec::vectorStrings& TestSpec::getInvalidArgs() const{ 14694 return (m_invalidArgs); 14695 } 14696 14697 } 14698 // end catch_test_spec.cpp 14699 // start catch_test_spec_parser.cpp 14700 14701 namespace Catch { 14702 14703 TestSpecParser::TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {} 14704 14705 TestSpecParser& TestSpecParser::parse( std::string const& arg ) { 14706 m_mode = None; 14707 m_exclusion = false; 14708 m_arg = m_tagAliases->expandAliases( arg ); 14709 m_escapeChars.clear(); 14710 m_substring.reserve(m_arg.size()); 14711 m_patternName.reserve(m_arg.size()); 14712 m_realPatternPos = 0; 14713 14714 for( m_pos = 0; m_pos < m_arg.size(); ++m_pos ) 14715 //if visitChar fails 14716 if( !visitChar( m_arg[m_pos] ) ){ 14717 m_testSpec.m_invalidArgs.push_back(arg); 14718 break; 14719 } 14720 endMode(); 14721 return *this; 14722 } 14723 TestSpec TestSpecParser::testSpec() { 14724 addFilter(); 14725 return m_testSpec; 14726 } 14727 bool TestSpecParser::visitChar( char c ) { 14728 if( (m_mode != EscapedName) && (c == '\\') ) { 14729 escape(); 14730 addCharToPattern(c); 14731 return true; 14732 }else if((m_mode != EscapedName) && (c == ',') ) { 14733 return separate(); 14734 } 14735 14736 switch( m_mode ) { 14737 case None: 14738 if( processNoneChar( c ) ) 14739 return true; 14740 break; 14741 case Name: 14742 processNameChar( c ); 14743 break; 14744 case EscapedName: 14745 endMode(); 14746 addCharToPattern(c); 14747 return true; 14748 default: 14749 case Tag: 14750 case QuotedName: 14751 if( processOtherChar( c ) ) 14752 return true; 14753 break; 14754 } 14755 14756 m_substring += c; 14757 if( !isControlChar( c ) ) { 14758 m_patternName += c; 14759 m_realPatternPos++; 14760 } 14761 return true; 14762 } 14763 // Two of the processing methods return true to signal the caller to return 14764 // without adding the given character to the current pattern strings 14765 bool TestSpecParser::processNoneChar( char c ) { 14766 switch( c ) { 14767 case ' ': 14768 return true; 14769 case '~': 14770 m_exclusion = true; 14771 return false; 14772 case '[': 14773 startNewMode( Tag ); 14774 return false; 14775 case '"': 14776 startNewMode( QuotedName ); 14777 return false; 14778 default: 14779 startNewMode( Name ); 14780 return false; 14781 } 14782 } 14783 void TestSpecParser::processNameChar( char c ) { 14784 if( c == '[' ) { 14785 if( m_substring == "exclude:" ) 14786 m_exclusion = true; 14787 else 14788 endMode(); 14789 startNewMode( Tag ); 14790 } 14791 } 14792 bool TestSpecParser::processOtherChar( char c ) { 14793 if( !isControlChar( c ) ) 14794 return false; 14795 m_substring += c; 14796 endMode(); 14797 return true; 14798 } 14799 void TestSpecParser::startNewMode( Mode mode ) { 14800 m_mode = mode; 14801 } 14802 void TestSpecParser::endMode() { 14803 switch( m_mode ) { 14804 case Name: 14805 case QuotedName: 14806 return addNamePattern(); 14807 case Tag: 14808 return addTagPattern(); 14809 case EscapedName: 14810 revertBackToLastMode(); 14811 return; 14812 case None: 14813 default: 14814 return startNewMode( None ); 14815 } 14816 } 14817 void TestSpecParser::escape() { 14818 saveLastMode(); 14819 m_mode = EscapedName; 14820 m_escapeChars.push_back(m_realPatternPos); 14821 } 14822 bool TestSpecParser::isControlChar( char c ) const { 14823 switch( m_mode ) { 14824 default: 14825 return false; 14826 case None: 14827 return c == '~'; 14828 case Name: 14829 return c == '['; 14830 case EscapedName: 14831 return true; 14832 case QuotedName: 14833 return c == '"'; 14834 case Tag: 14835 return c == '[' || c == ']'; 14836 } 14837 } 14838 14839 void TestSpecParser::addFilter() { 14840 if( !m_currentFilter.m_patterns.empty() ) { 14841 m_testSpec.m_filters.push_back( m_currentFilter ); 14842 m_currentFilter = TestSpec::Filter(); 14843 } 14844 } 14845 14846 void TestSpecParser::saveLastMode() { 14847 lastMode = m_mode; 14848 } 14849 14850 void TestSpecParser::revertBackToLastMode() { 14851 m_mode = lastMode; 14852 } 14853 14854 bool TestSpecParser::separate() { 14855 if( (m_mode==QuotedName) || (m_mode==Tag) ){ 14856 //invalid argument, signal failure to previous scope. 14857 m_mode = None; 14858 m_pos = m_arg.size(); 14859 m_substring.clear(); 14860 m_patternName.clear(); 14861 m_realPatternPos = 0; 14862 return false; 14863 } 14864 endMode(); 14865 addFilter(); 14866 return true; //success 14867 } 14868 14869 std::string TestSpecParser::preprocessPattern() { 14870 std::string token = m_patternName; 14871 for (std::size_t i = 0; i < m_escapeChars.size(); ++i) 14872 token = token.substr(0, m_escapeChars[i] - i) + token.substr(m_escapeChars[i] - i + 1); 14873 m_escapeChars.clear(); 14874 if (startsWith(token, "exclude:")) { 14875 m_exclusion = true; 14876 token = token.substr(8); 14877 } 14878 14879 m_patternName.clear(); 14880 m_realPatternPos = 0; 14881 14882 return token; 14883 } 14884 14885 void TestSpecParser::addNamePattern() { 14886 auto token = preprocessPattern(); 14887 14888 if (!token.empty()) { 14889 TestSpec::PatternPtr pattern = std::make_shared<TestSpec::NamePattern>(token, m_substring); 14890 if (m_exclusion) 14891 pattern = std::make_shared<TestSpec::ExcludedPattern>(pattern); 14892 m_currentFilter.m_patterns.push_back(pattern); 14893 } 14894 m_substring.clear(); 14895 m_exclusion = false; 14896 m_mode = None; 14897 } 14898 14899 void TestSpecParser::addTagPattern() { 14900 auto token = preprocessPattern(); 14901 14902 if (!token.empty()) { 14903 // If the tag pattern is the "hide and tag" shorthand (e.g. [.foo]) 14904 // we have to create a separate hide tag and shorten the real one 14905 if (token.size() > 1 && token[0] == '.') { 14906 token.erase(token.begin()); 14907 TestSpec::PatternPtr pattern = std::make_shared<TestSpec::TagPattern>(".", m_substring); 14908 if (m_exclusion) { 14909 pattern = std::make_shared<TestSpec::ExcludedPattern>(pattern); 14910 } 14911 m_currentFilter.m_patterns.push_back(pattern); 14912 } 14913 14914 TestSpec::PatternPtr pattern = std::make_shared<TestSpec::TagPattern>(token, m_substring); 14915 14916 if (m_exclusion) { 14917 pattern = std::make_shared<TestSpec::ExcludedPattern>(pattern); 14918 } 14919 m_currentFilter.m_patterns.push_back(pattern); 14920 } 14921 m_substring.clear(); 14922 m_exclusion = false; 14923 m_mode = None; 14924 } 14925 14926 TestSpec parseTestSpec( std::string const& arg ) { 14927 return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec(); 14928 } 14929 14930 } // namespace Catch 14931 // end catch_test_spec_parser.cpp 14932 // start catch_timer.cpp 14933 14934 #include <chrono> 14935 14936 static const uint64_t nanosecondsInSecond = 1000000000; 14937 14938 namespace Catch { 14939 14940 auto getCurrentNanosecondsSinceEpoch() -> uint64_t { 14941 return std::chrono::duration_cast<std::chrono::nanoseconds>( std::chrono::high_resolution_clock::now().time_since_epoch() ).count(); 14942 } 14943 14944 namespace { 14945 auto estimateClockResolution() -> uint64_t { 14946 uint64_t sum = 0; 14947 static const uint64_t iterations = 1000000; 14948 14949 auto startTime = getCurrentNanosecondsSinceEpoch(); 14950 14951 for( std::size_t i = 0; i < iterations; ++i ) { 14952 14953 uint64_t ticks; 14954 uint64_t baseTicks = getCurrentNanosecondsSinceEpoch(); 14955 do { 14956 ticks = getCurrentNanosecondsSinceEpoch(); 14957 } while( ticks == baseTicks ); 14958 14959 auto delta = ticks - baseTicks; 14960 sum += delta; 14961 14962 // If we have been calibrating for over 3 seconds -- the clock 14963 // is terrible and we should move on. 14964 // TBD: How to signal that the measured resolution is probably wrong? 14965 if (ticks > startTime + 3 * nanosecondsInSecond) { 14966 return sum / ( i + 1u ); 14967 } 14968 } 14969 14970 // We're just taking the mean, here. To do better we could take the std. dev and exclude outliers 14971 // - and potentially do more iterations if there's a high variance. 14972 return sum/iterations; 14973 } 14974 } 14975 auto getEstimatedClockResolution() -> uint64_t { 14976 static auto s_resolution = estimateClockResolution(); 14977 return s_resolution; 14978 } 14979 14980 void Timer::start() { 14981 m_nanoseconds = getCurrentNanosecondsSinceEpoch(); 14982 } 14983 auto Timer::getElapsedNanoseconds() const -> uint64_t { 14984 return getCurrentNanosecondsSinceEpoch() - m_nanoseconds; 14985 } 14986 auto Timer::getElapsedMicroseconds() const -> uint64_t { 14987 return getElapsedNanoseconds()/1000; 14988 } 14989 auto Timer::getElapsedMilliseconds() const -> unsigned int { 14990 return static_cast<unsigned int>(getElapsedMicroseconds()/1000); 14991 } 14992 auto Timer::getElapsedSeconds() const -> double { 14993 return getElapsedMicroseconds()/1000000.0; 14994 } 14995 14996 } // namespace Catch 14997 // end catch_timer.cpp 14998 // start catch_tostring.cpp 14999 15000 #if defined(__clang__) 15001 # pragma clang diagnostic push 15002 # pragma clang diagnostic ignored "-Wexit-time-destructors" 15003 # pragma clang diagnostic ignored "-Wglobal-constructors" 15004 #endif 15005 15006 // Enable specific decls locally 15007 #if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) 15008 #define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER 15009 #endif 15010 15011 #include <cmath> 15012 #include <iomanip> 15013 15014 namespace Catch { 15015 15016 namespace Detail { 15017 15018 const std::string unprintableString = "{?}"; 15019 15020 namespace { 15021 const int hexThreshold = 255; 15022 15023 struct Endianness { 15024 enum Arch { Big, Little }; 15025 15026 static Arch which() { 15027 int one = 1; 15028 // If the lowest byte we read is non-zero, we can assume 15029 // that little endian format is used. 15030 auto value = *reinterpret_cast<char*>(&one); 15031 return value ? Little : Big; 15032 } 15033 }; 15034 } 15035 15036 std::string rawMemoryToString( const void *object, std::size_t size ) { 15037 // Reverse order for little endian architectures 15038 int i = 0, end = static_cast<int>( size ), inc = 1; 15039 if( Endianness::which() == Endianness::Little ) { 15040 i = end-1; 15041 end = inc = -1; 15042 } 15043 15044 unsigned char const *bytes = static_cast<unsigned char const *>(object); 15045 ReusableStringStream rss; 15046 rss << "0x" << std::setfill('0') << std::hex; 15047 for( ; i != end; i += inc ) 15048 rss << std::setw(2) << static_cast<unsigned>(bytes[i]); 15049 return rss.str(); 15050 } 15051 } 15052 15053 template<typename T> 15054 std::string fpToString( T value, int precision ) { 15055 if (Catch::isnan(value)) { 15056 return "nan"; 15057 } 15058 15059 ReusableStringStream rss; 15060 rss << std::setprecision( precision ) 15061 << std::fixed 15062 << value; 15063 std::string d = rss.str(); 15064 std::size_t i = d.find_last_not_of( '0' ); 15065 if( i != std::string::npos && i != d.size()-1 ) { 15066 if( d[i] == '.' ) 15067 i++; 15068 d = d.substr( 0, i+1 ); 15069 } 15070 return d; 15071 } 15072 15073 //// ======================================================= //// 15074 // 15075 // Out-of-line defs for full specialization of StringMaker 15076 // 15077 //// ======================================================= //// 15078 15079 std::string StringMaker<std::string>::convert(const std::string& str) { 15080 if (!getCurrentContext().getConfig()->showInvisibles()) { 15081 return '"' + str + '"'; 15082 } 15083 15084 std::string s("\""); 15085 for (char c : str) { 15086 switch (c) { 15087 case '\n': 15088 s.append("\\n"); 15089 break; 15090 case '\t': 15091 s.append("\\t"); 15092 break; 15093 default: 15094 s.push_back(c); 15095 break; 15096 } 15097 } 15098 s.append("\""); 15099 return s; 15100 } 15101 15102 #ifdef CATCH_CONFIG_CPP17_STRING_VIEW 15103 std::string StringMaker<std::string_view>::convert(std::string_view str) { 15104 return ::Catch::Detail::stringify(std::string{ str }); 15105 } 15106 #endif 15107 15108 std::string StringMaker<char const*>::convert(char const* str) { 15109 if (str) { 15110 return ::Catch::Detail::stringify(std::string{ str }); 15111 } else { 15112 return{ "{null string}" }; 15113 } 15114 } 15115 std::string StringMaker<char*>::convert(char* str) { 15116 if (str) { 15117 return ::Catch::Detail::stringify(std::string{ str }); 15118 } else { 15119 return{ "{null string}" }; 15120 } 15121 } 15122 15123 #ifdef CATCH_CONFIG_WCHAR 15124 std::string StringMaker<std::wstring>::convert(const std::wstring& wstr) { 15125 std::string s; 15126 s.reserve(wstr.size()); 15127 for (auto c : wstr) { 15128 s += (c <= 0xff) ? static_cast<char>(c) : '?'; 15129 } 15130 return ::Catch::Detail::stringify(s); 15131 } 15132 15133 # ifdef CATCH_CONFIG_CPP17_STRING_VIEW 15134 std::string StringMaker<std::wstring_view>::convert(std::wstring_view str) { 15135 return StringMaker<std::wstring>::convert(std::wstring(str)); 15136 } 15137 # endif 15138 15139 std::string StringMaker<wchar_t const*>::convert(wchar_t const * str) { 15140 if (str) { 15141 return ::Catch::Detail::stringify(std::wstring{ str }); 15142 } else { 15143 return{ "{null string}" }; 15144 } 15145 } 15146 std::string StringMaker<wchar_t *>::convert(wchar_t * str) { 15147 if (str) { 15148 return ::Catch::Detail::stringify(std::wstring{ str }); 15149 } else { 15150 return{ "{null string}" }; 15151 } 15152 } 15153 #endif 15154 15155 #if defined(CATCH_CONFIG_CPP17_BYTE) 15156 #include <cstddef> 15157 std::string StringMaker<std::byte>::convert(std::byte value) { 15158 return ::Catch::Detail::stringify(std::to_integer<unsigned long long>(value)); 15159 } 15160 #endif // defined(CATCH_CONFIG_CPP17_BYTE) 15161 15162 std::string StringMaker<int>::convert(int value) { 15163 return ::Catch::Detail::stringify(static_cast<long long>(value)); 15164 } 15165 std::string StringMaker<long>::convert(long value) { 15166 return ::Catch::Detail::stringify(static_cast<long long>(value)); 15167 } 15168 std::string StringMaker<long long>::convert(long long value) { 15169 ReusableStringStream rss; 15170 rss << value; 15171 if (value > Detail::hexThreshold) { 15172 rss << " (0x" << std::hex << value << ')'; 15173 } 15174 return rss.str(); 15175 } 15176 15177 std::string StringMaker<unsigned int>::convert(unsigned int value) { 15178 return ::Catch::Detail::stringify(static_cast<unsigned long long>(value)); 15179 } 15180 std::string StringMaker<unsigned long>::convert(unsigned long value) { 15181 return ::Catch::Detail::stringify(static_cast<unsigned long long>(value)); 15182 } 15183 std::string StringMaker<unsigned long long>::convert(unsigned long long value) { 15184 ReusableStringStream rss; 15185 rss << value; 15186 if (value > Detail::hexThreshold) { 15187 rss << " (0x" << std::hex << value << ')'; 15188 } 15189 return rss.str(); 15190 } 15191 15192 std::string StringMaker<bool>::convert(bool b) { 15193 return b ? "true" : "false"; 15194 } 15195 15196 std::string StringMaker<signed char>::convert(signed char value) { 15197 if (value == '\r') { 15198 return "'\\r'"; 15199 } else if (value == '\f') { 15200 return "'\\f'"; 15201 } else if (value == '\n') { 15202 return "'\\n'"; 15203 } else if (value == '\t') { 15204 return "'\\t'"; 15205 } else if ('\0' <= value && value < ' ') { 15206 return ::Catch::Detail::stringify(static_cast<unsigned int>(value)); 15207 } else { 15208 char chstr[] = "' '"; 15209 chstr[1] = value; 15210 return chstr; 15211 } 15212 } 15213 std::string StringMaker<char>::convert(char c) { 15214 return ::Catch::Detail::stringify(static_cast<signed char>(c)); 15215 } 15216 std::string StringMaker<unsigned char>::convert(unsigned char c) { 15217 return ::Catch::Detail::stringify(static_cast<char>(c)); 15218 } 15219 15220 std::string StringMaker<std::nullptr_t>::convert(std::nullptr_t) { 15221 return "nullptr"; 15222 } 15223 15224 int StringMaker<float>::precision = 5; 15225 15226 std::string StringMaker<float>::convert(float value) { 15227 return fpToString(value, precision) + 'f'; 15228 } 15229 15230 int StringMaker<double>::precision = 10; 15231 15232 std::string StringMaker<double>::convert(double value) { 15233 return fpToString(value, precision); 15234 } 15235 15236 std::string ratio_string<std::atto>::symbol() { return "a"; } 15237 std::string ratio_string<std::femto>::symbol() { return "f"; } 15238 std::string ratio_string<std::pico>::symbol() { return "p"; } 15239 std::string ratio_string<std::nano>::symbol() { return "n"; } 15240 std::string ratio_string<std::micro>::symbol() { return "u"; } 15241 std::string ratio_string<std::milli>::symbol() { return "m"; } 15242 15243 } // end namespace Catch 15244 15245 #if defined(__clang__) 15246 # pragma clang diagnostic pop 15247 #endif 15248 15249 // end catch_tostring.cpp 15250 // start catch_totals.cpp 15251 15252 namespace Catch { 15253 15254 Counts Counts::operator - ( Counts const& other ) const { 15255 Counts diff; 15256 diff.passed = passed - other.passed; 15257 diff.failed = failed - other.failed; 15258 diff.failedButOk = failedButOk - other.failedButOk; 15259 return diff; 15260 } 15261 15262 Counts& Counts::operator += ( Counts const& other ) { 15263 passed += other.passed; 15264 failed += other.failed; 15265 failedButOk += other.failedButOk; 15266 return *this; 15267 } 15268 15269 std::size_t Counts::total() const { 15270 return passed + failed + failedButOk; 15271 } 15272 bool Counts::allPassed() const { 15273 return failed == 0 && failedButOk == 0; 15274 } 15275 bool Counts::allOk() const { 15276 return failed == 0; 15277 } 15278 15279 Totals Totals::operator - ( Totals const& other ) const { 15280 Totals diff; 15281 diff.assertions = assertions - other.assertions; 15282 diff.testCases = testCases - other.testCases; 15283 return diff; 15284 } 15285 15286 Totals& Totals::operator += ( Totals const& other ) { 15287 assertions += other.assertions; 15288 testCases += other.testCases; 15289 return *this; 15290 } 15291 15292 Totals Totals::delta( Totals const& prevTotals ) const { 15293 Totals diff = *this - prevTotals; 15294 if( diff.assertions.failed > 0 ) 15295 ++diff.testCases.failed; 15296 else if( diff.assertions.failedButOk > 0 ) 15297 ++diff.testCases.failedButOk; 15298 else 15299 ++diff.testCases.passed; 15300 return diff; 15301 } 15302 15303 } 15304 // end catch_totals.cpp 15305 // start catch_uncaught_exceptions.cpp 15306 15307 // start catch_config_uncaught_exceptions.hpp 15308 15309 // Copyright Catch2 Authors 15310 // Distributed under the Boost Software License, Version 1.0. 15311 // (See accompanying file LICENSE_1_0.txt or copy at 15312 // https://www.boost.org/LICENSE_1_0.txt) 15313 15314 // SPDX-License-Identifier: BSL-1.0 15315 15316 #ifndef CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP 15317 #define CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP 15318 15319 #if defined(_MSC_VER) 15320 # if _MSC_VER >= 1900 // Visual Studio 2015 or newer 15321 # define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS 15322 # endif 15323 #endif 15324 15325 #include <exception> 15326 15327 #if defined(__cpp_lib_uncaught_exceptions) \ 15328 && !defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) 15329 15330 # define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS 15331 #endif // __cpp_lib_uncaught_exceptions 15332 15333 #if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) \ 15334 && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) \ 15335 && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) 15336 15337 # define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS 15338 #endif 15339 15340 #endif // CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP 15341 // end catch_config_uncaught_exceptions.hpp 15342 #include <exception> 15343 15344 namespace Catch { 15345 bool uncaught_exceptions() { 15346 #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 15347 return false; 15348 #elif defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) 15349 return std::uncaught_exceptions() > 0; 15350 #else 15351 return std::uncaught_exception(); 15352 #endif 15353 } 15354 } // end namespace Catch 15355 // end catch_uncaught_exceptions.cpp 15356 // start catch_version.cpp 15357 15358 #include <ostream> 15359 15360 namespace Catch { 15361 15362 Version::Version 15363 ( unsigned int _majorVersion, 15364 unsigned int _minorVersion, 15365 unsigned int _patchNumber, 15366 char const * const _branchName, 15367 unsigned int _buildNumber ) 15368 : majorVersion( _majorVersion ), 15369 minorVersion( _minorVersion ), 15370 patchNumber( _patchNumber ), 15371 branchName( _branchName ), 15372 buildNumber( _buildNumber ) 15373 {} 15374 15375 std::ostream& operator << ( std::ostream& os, Version const& version ) { 15376 os << version.majorVersion << '.' 15377 << version.minorVersion << '.' 15378 << version.patchNumber; 15379 // branchName is never null -> 0th char is \0 if it is empty 15380 if (version.branchName[0]) { 15381 os << '-' << version.branchName 15382 << '.' << version.buildNumber; 15383 } 15384 return os; 15385 } 15386 15387 Version const& libraryVersion() { 15388 static Version version( 2, 13, 7, "", 0 ); 15389 return version; 15390 } 15391 15392 } 15393 // end catch_version.cpp 15394 // start catch_wildcard_pattern.cpp 15395 15396 namespace Catch { 15397 15398 WildcardPattern::WildcardPattern( std::string const& pattern, 15399 CaseSensitive::Choice caseSensitivity ) 15400 : m_caseSensitivity( caseSensitivity ), 15401 m_pattern( normaliseString( pattern ) ) 15402 { 15403 if( startsWith( m_pattern, '*' ) ) { 15404 m_pattern = m_pattern.substr( 1 ); 15405 m_wildcard = WildcardAtStart; 15406 } 15407 if( endsWith( m_pattern, '*' ) ) { 15408 m_pattern = m_pattern.substr( 0, m_pattern.size()-1 ); 15409 m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd ); 15410 } 15411 } 15412 15413 bool WildcardPattern::matches( std::string const& str ) const { 15414 switch( m_wildcard ) { 15415 case NoWildcard: 15416 return m_pattern == normaliseString( str ); 15417 case WildcardAtStart: 15418 return endsWith( normaliseString( str ), m_pattern ); 15419 case WildcardAtEnd: 15420 return startsWith( normaliseString( str ), m_pattern ); 15421 case WildcardAtBothEnds: 15422 return contains( normaliseString( str ), m_pattern ); 15423 default: 15424 CATCH_INTERNAL_ERROR( "Unknown enum" ); 15425 } 15426 } 15427 15428 std::string WildcardPattern::normaliseString( std::string const& str ) const { 15429 return trim( m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str ); 15430 } 15431 } 15432 // end catch_wildcard_pattern.cpp 15433 // start catch_xmlwriter.cpp 15434 15435 #include <iomanip> 15436 #include <type_traits> 15437 15438 namespace Catch { 15439 15440 namespace { 15441 15442 size_t trailingBytes(unsigned char c) { 15443 if ((c & 0xE0) == 0xC0) { 15444 return 2; 15445 } 15446 if ((c & 0xF0) == 0xE0) { 15447 return 3; 15448 } 15449 if ((c & 0xF8) == 0xF0) { 15450 return 4; 15451 } 15452 CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered"); 15453 } 15454 15455 uint32_t headerValue(unsigned char c) { 15456 if ((c & 0xE0) == 0xC0) { 15457 return c & 0x1F; 15458 } 15459 if ((c & 0xF0) == 0xE0) { 15460 return c & 0x0F; 15461 } 15462 if ((c & 0xF8) == 0xF0) { 15463 return c & 0x07; 15464 } 15465 CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered"); 15466 } 15467 15468 void hexEscapeChar(std::ostream& os, unsigned char c) { 15469 std::ios_base::fmtflags f(os.flags()); 15470 os << "\\x" 15471 << std::uppercase << std::hex << std::setfill('0') << std::setw(2) 15472 << static_cast<int>(c); 15473 os.flags(f); 15474 } 15475 15476 bool shouldNewline(XmlFormatting fmt) { 15477 return !!(static_cast<std::underlying_type<XmlFormatting>::type>(fmt & XmlFormatting::Newline)); 15478 } 15479 15480 bool shouldIndent(XmlFormatting fmt) { 15481 return !!(static_cast<std::underlying_type<XmlFormatting>::type>(fmt & XmlFormatting::Indent)); 15482 } 15483 15484 } // anonymous namespace 15485 15486 XmlFormatting operator | (XmlFormatting lhs, XmlFormatting rhs) { 15487 return static_cast<XmlFormatting>( 15488 static_cast<std::underlying_type<XmlFormatting>::type>(lhs) | 15489 static_cast<std::underlying_type<XmlFormatting>::type>(rhs) 15490 ); 15491 } 15492 15493 XmlFormatting operator & (XmlFormatting lhs, XmlFormatting rhs) { 15494 return static_cast<XmlFormatting>( 15495 static_cast<std::underlying_type<XmlFormatting>::type>(lhs) & 15496 static_cast<std::underlying_type<XmlFormatting>::type>(rhs) 15497 ); 15498 } 15499 15500 XmlEncode::XmlEncode( std::string const& str, ForWhat forWhat ) 15501 : m_str( str ), 15502 m_forWhat( forWhat ) 15503 {} 15504 15505 void XmlEncode::encodeTo( std::ostream& os ) const { 15506 // Apostrophe escaping not necessary if we always use " to write attributes 15507 // (see: http://www.w3.org/TR/xml/#syntax) 15508 15509 for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) { 15510 unsigned char c = m_str[idx]; 15511 switch (c) { 15512 case '<': os << "<"; break; 15513 case '&': os << "&"; break; 15514 15515 case '>': 15516 // See: http://www.w3.org/TR/xml/#syntax 15517 if (idx > 2 && m_str[idx - 1] == ']' && m_str[idx - 2] == ']') 15518 os << ">"; 15519 else 15520 os << c; 15521 break; 15522 15523 case '\"': 15524 if (m_forWhat == ForAttributes) 15525 os << """; 15526 else 15527 os << c; 15528 break; 15529 15530 default: 15531 // Check for control characters and invalid utf-8 15532 15533 // Escape control characters in standard ascii 15534 // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0 15535 if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) { 15536 hexEscapeChar(os, c); 15537 break; 15538 } 15539 15540 // Plain ASCII: Write it to stream 15541 if (c < 0x7F) { 15542 os << c; 15543 break; 15544 } 15545 15546 // UTF-8 territory 15547 // Check if the encoding is valid and if it is not, hex escape bytes. 15548 // Important: We do not check the exact decoded values for validity, only the encoding format 15549 // First check that this bytes is a valid lead byte: 15550 // This means that it is not encoded as 1111 1XXX 15551 // Or as 10XX XXXX 15552 if (c < 0xC0 || 15553 c >= 0xF8) { 15554 hexEscapeChar(os, c); 15555 break; 15556 } 15557 15558 auto encBytes = trailingBytes(c); 15559 // Are there enough bytes left to avoid accessing out-of-bounds memory? 15560 if (idx + encBytes - 1 >= m_str.size()) { 15561 hexEscapeChar(os, c); 15562 break; 15563 } 15564 // The header is valid, check data 15565 // The next encBytes bytes must together be a valid utf-8 15566 // This means: bitpattern 10XX XXXX and the extracted value is sane (ish) 15567 bool valid = true; 15568 uint32_t value = headerValue(c); 15569 for (std::size_t n = 1; n < encBytes; ++n) { 15570 unsigned char nc = m_str[idx + n]; 15571 valid &= ((nc & 0xC0) == 0x80); 15572 value = (value << 6) | (nc & 0x3F); 15573 } 15574 15575 if ( 15576 // Wrong bit pattern of following bytes 15577 (!valid) || 15578 // Overlong encodings 15579 (value < 0x80) || 15580 (0x80 <= value && value < 0x800 && encBytes > 2) || 15581 (0x800 < value && value < 0x10000 && encBytes > 3) || 15582 // Encoded value out of range 15583 (value >= 0x110000) 15584 ) { 15585 hexEscapeChar(os, c); 15586 break; 15587 } 15588 15589 // If we got here, this is in fact a valid(ish) utf-8 sequence 15590 for (std::size_t n = 0; n < encBytes; ++n) { 15591 os << m_str[idx + n]; 15592 } 15593 idx += encBytes - 1; 15594 break; 15595 } 15596 } 15597 } 15598 15599 std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) { 15600 xmlEncode.encodeTo( os ); 15601 return os; 15602 } 15603 15604 XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer, XmlFormatting fmt ) 15605 : m_writer( writer ), 15606 m_fmt(fmt) 15607 {} 15608 15609 XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) noexcept 15610 : m_writer( other.m_writer ), 15611 m_fmt(other.m_fmt) 15612 { 15613 other.m_writer = nullptr; 15614 other.m_fmt = XmlFormatting::None; 15615 } 15616 XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) noexcept { 15617 if ( m_writer ) { 15618 m_writer->endElement(); 15619 } 15620 m_writer = other.m_writer; 15621 other.m_writer = nullptr; 15622 m_fmt = other.m_fmt; 15623 other.m_fmt = XmlFormatting::None; 15624 return *this; 15625 } 15626 15627 XmlWriter::ScopedElement::~ScopedElement() { 15628 if (m_writer) { 15629 m_writer->endElement(m_fmt); 15630 } 15631 } 15632 15633 XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText( std::string const& text, XmlFormatting fmt ) { 15634 m_writer->writeText( text, fmt ); 15635 return *this; 15636 } 15637 15638 XmlWriter::XmlWriter( std::ostream& os ) : m_os( os ) 15639 { 15640 writeDeclaration(); 15641 } 15642 15643 XmlWriter::~XmlWriter() { 15644 while (!m_tags.empty()) { 15645 endElement(); 15646 } 15647 newlineIfNecessary(); 15648 } 15649 15650 XmlWriter& XmlWriter::startElement( std::string const& name, XmlFormatting fmt ) { 15651 ensureTagClosed(); 15652 newlineIfNecessary(); 15653 if (shouldIndent(fmt)) { 15654 m_os << m_indent; 15655 m_indent += " "; 15656 } 15657 m_os << '<' << name; 15658 m_tags.push_back( name ); 15659 m_tagIsOpen = true; 15660 applyFormatting(fmt); 15661 return *this; 15662 } 15663 15664 XmlWriter::ScopedElement XmlWriter::scopedElement( std::string const& name, XmlFormatting fmt ) { 15665 ScopedElement scoped( this, fmt ); 15666 startElement( name, fmt ); 15667 return scoped; 15668 } 15669 15670 XmlWriter& XmlWriter::endElement(XmlFormatting fmt) { 15671 m_indent = m_indent.substr(0, m_indent.size() - 2); 15672 15673 if( m_tagIsOpen ) { 15674 m_os << "/>"; 15675 m_tagIsOpen = false; 15676 } else { 15677 newlineIfNecessary(); 15678 if (shouldIndent(fmt)) { 15679 m_os << m_indent; 15680 } 15681 m_os << "</" << m_tags.back() << ">"; 15682 } 15683 m_os << std::flush; 15684 applyFormatting(fmt); 15685 m_tags.pop_back(); 15686 return *this; 15687 } 15688 15689 XmlWriter& XmlWriter::writeAttribute( std::string const& name, std::string const& attribute ) { 15690 if( !name.empty() && !attribute.empty() ) 15691 m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"'; 15692 return *this; 15693 } 15694 15695 XmlWriter& XmlWriter::writeAttribute( std::string const& name, bool attribute ) { 15696 m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"'; 15697 return *this; 15698 } 15699 15700 XmlWriter& XmlWriter::writeText( std::string const& text, XmlFormatting fmt) { 15701 if( !text.empty() ){ 15702 bool tagWasOpen = m_tagIsOpen; 15703 ensureTagClosed(); 15704 if (tagWasOpen && shouldIndent(fmt)) { 15705 m_os << m_indent; 15706 } 15707 m_os << XmlEncode( text ); 15708 applyFormatting(fmt); 15709 } 15710 return *this; 15711 } 15712 15713 XmlWriter& XmlWriter::writeComment( std::string const& text, XmlFormatting fmt) { 15714 ensureTagClosed(); 15715 if (shouldIndent(fmt)) { 15716 m_os << m_indent; 15717 } 15718 m_os << "<!--" << text << "-->"; 15719 applyFormatting(fmt); 15720 return *this; 15721 } 15722 15723 void XmlWriter::writeStylesheetRef( std::string const& url ) { 15724 m_os << "<?xml-stylesheet type=\"text/xsl\" href=\"" << url << "\"?>\n"; 15725 } 15726 15727 XmlWriter& XmlWriter::writeBlankLine() { 15728 ensureTagClosed(); 15729 m_os << '\n'; 15730 return *this; 15731 } 15732 15733 void XmlWriter::ensureTagClosed() { 15734 if( m_tagIsOpen ) { 15735 m_os << '>' << std::flush; 15736 newlineIfNecessary(); 15737 m_tagIsOpen = false; 15738 } 15739 } 15740 15741 void XmlWriter::applyFormatting(XmlFormatting fmt) { 15742 m_needsNewline = shouldNewline(fmt); 15743 } 15744 15745 void XmlWriter::writeDeclaration() { 15746 m_os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; 15747 } 15748 15749 void XmlWriter::newlineIfNecessary() { 15750 if( m_needsNewline ) { 15751 m_os << std::endl; 15752 m_needsNewline = false; 15753 } 15754 } 15755 } 15756 // end catch_xmlwriter.cpp 15757 // start catch_reporter_bases.cpp 15758 15759 #include <cstring> 15760 #include <cfloat> 15761 #include <cstdio> 15762 #include <cassert> 15763 #include <memory> 15764 15765 namespace Catch { 15766 void prepareExpandedExpression(AssertionResult& result) { 15767 result.getExpandedExpression(); 15768 } 15769 15770 // Because formatting using c++ streams is stateful, drop down to C is required 15771 // Alternatively we could use stringstream, but its performance is... not good. 15772 std::string getFormattedDuration( double duration ) { 15773 // Max exponent + 1 is required to represent the whole part 15774 // + 1 for decimal point 15775 // + 3 for the 3 decimal places 15776 // + 1 for null terminator 15777 const std::size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1; 15778 char buffer[maxDoubleSize]; 15779 15780 // Save previous errno, to prevent sprintf from overwriting it 15781 ErrnoGuard guard; 15782 #ifdef _MSC_VER 15783 sprintf_s(buffer, "%.3f", duration); 15784 #else 15785 std::sprintf(buffer, "%.3f", duration); 15786 #endif 15787 return std::string(buffer); 15788 } 15789 15790 bool shouldShowDuration( IConfig const& config, double duration ) { 15791 if ( config.showDurations() == ShowDurations::Always ) { 15792 return true; 15793 } 15794 if ( config.showDurations() == ShowDurations::Never ) { 15795 return false; 15796 } 15797 const double min = config.minDuration(); 15798 return min >= 0 && duration >= min; 15799 } 15800 15801 std::string serializeFilters( std::vector<std::string> const& container ) { 15802 ReusableStringStream oss; 15803 bool first = true; 15804 for (auto&& filter : container) 15805 { 15806 if (!first) 15807 oss << ' '; 15808 else 15809 first = false; 15810 15811 oss << filter; 15812 } 15813 return oss.str(); 15814 } 15815 15816 TestEventListenerBase::TestEventListenerBase(ReporterConfig const & _config) 15817 :StreamingReporterBase(_config) {} 15818 15819 std::set<Verbosity> TestEventListenerBase::getSupportedVerbosities() { 15820 return { Verbosity::Quiet, Verbosity::Normal, Verbosity::High }; 15821 } 15822 15823 void TestEventListenerBase::assertionStarting(AssertionInfo const &) {} 15824 15825 bool TestEventListenerBase::assertionEnded(AssertionStats const &) { 15826 return false; 15827 } 15828 15829 } // end namespace Catch 15830 // end catch_reporter_bases.cpp 15831 // start catch_reporter_compact.cpp 15832 15833 namespace { 15834 15835 #ifdef CATCH_PLATFORM_MAC 15836 const char* failedString() { return "FAILED"; } 15837 const char* passedString() { return "PASSED"; } 15838 #else 15839 const char* failedString() { return "failed"; } 15840 const char* passedString() { return "passed"; } 15841 #endif 15842 15843 // Colour::LightGrey 15844 Catch::Colour::Code dimColour() { return Catch::Colour::FileName; } 15845 15846 std::string bothOrAll( std::size_t count ) { 15847 return count == 1 ? std::string() : 15848 count == 2 ? "both " : "all " ; 15849 } 15850 15851 } // anon namespace 15852 15853 namespace Catch { 15854 namespace { 15855 // Colour, message variants: 15856 // - white: No tests ran. 15857 // - red: Failed [both/all] N test cases, failed [both/all] M assertions. 15858 // - white: Passed [both/all] N test cases (no assertions). 15859 // - red: Failed N tests cases, failed M assertions. 15860 // - green: Passed [both/all] N tests cases with M assertions. 15861 void printTotals(std::ostream& out, const Totals& totals) { 15862 if (totals.testCases.total() == 0) { 15863 out << "No tests ran."; 15864 } else if (totals.testCases.failed == totals.testCases.total()) { 15865 Colour colour(Colour::ResultError); 15866 const std::string qualify_assertions_failed = 15867 totals.assertions.failed == totals.assertions.total() ? 15868 bothOrAll(totals.assertions.failed) : std::string(); 15869 out << 15870 "Failed " << bothOrAll(totals.testCases.failed) 15871 << pluralise(totals.testCases.failed, "test case") << ", " 15872 "failed " << qualify_assertions_failed << 15873 pluralise(totals.assertions.failed, "assertion") << '.'; 15874 } else if (totals.assertions.total() == 0) { 15875 out << 15876 "Passed " << bothOrAll(totals.testCases.total()) 15877 << pluralise(totals.testCases.total(), "test case") 15878 << " (no assertions)."; 15879 } else if (totals.assertions.failed) { 15880 Colour colour(Colour::ResultError); 15881 out << 15882 "Failed " << pluralise(totals.testCases.failed, "test case") << ", " 15883 "failed " << pluralise(totals.assertions.failed, "assertion") << '.'; 15884 } else { 15885 Colour colour(Colour::ResultSuccess); 15886 out << 15887 "Passed " << bothOrAll(totals.testCases.passed) 15888 << pluralise(totals.testCases.passed, "test case") << 15889 " with " << pluralise(totals.assertions.passed, "assertion") << '.'; 15890 } 15891 } 15892 15893 // Implementation of CompactReporter formatting 15894 class AssertionPrinter { 15895 public: 15896 AssertionPrinter& operator= (AssertionPrinter const&) = delete; 15897 AssertionPrinter(AssertionPrinter const&) = delete; 15898 AssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages) 15899 : stream(_stream) 15900 , result(_stats.assertionResult) 15901 , messages(_stats.infoMessages) 15902 , itMessage(_stats.infoMessages.begin()) 15903 , printInfoMessages(_printInfoMessages) {} 15904 15905 void print() { 15906 printSourceInfo(); 15907 15908 itMessage = messages.begin(); 15909 15910 switch (result.getResultType()) { 15911 case ResultWas::Ok: 15912 printResultType(Colour::ResultSuccess, passedString()); 15913 printOriginalExpression(); 15914 printReconstructedExpression(); 15915 if (!result.hasExpression()) 15916 printRemainingMessages(Colour::None); 15917 else 15918 printRemainingMessages(); 15919 break; 15920 case ResultWas::ExpressionFailed: 15921 if (result.isOk()) 15922 printResultType(Colour::ResultSuccess, failedString() + std::string(" - but was ok")); 15923 else 15924 printResultType(Colour::Error, failedString()); 15925 printOriginalExpression(); 15926 printReconstructedExpression(); 15927 printRemainingMessages(); 15928 break; 15929 case ResultWas::ThrewException: 15930 printResultType(Colour::Error, failedString()); 15931 printIssue("unexpected exception with message:"); 15932 printMessage(); 15933 printExpressionWas(); 15934 printRemainingMessages(); 15935 break; 15936 case ResultWas::FatalErrorCondition: 15937 printResultType(Colour::Error, failedString()); 15938 printIssue("fatal error condition with message:"); 15939 printMessage(); 15940 printExpressionWas(); 15941 printRemainingMessages(); 15942 break; 15943 case ResultWas::DidntThrowException: 15944 printResultType(Colour::Error, failedString()); 15945 printIssue("expected exception, got none"); 15946 printExpressionWas(); 15947 printRemainingMessages(); 15948 break; 15949 case ResultWas::Info: 15950 printResultType(Colour::None, "info"); 15951 printMessage(); 15952 printRemainingMessages(); 15953 break; 15954 case ResultWas::Warning: 15955 printResultType(Colour::None, "warning"); 15956 printMessage(); 15957 printRemainingMessages(); 15958 break; 15959 case ResultWas::ExplicitFailure: 15960 printResultType(Colour::Error, failedString()); 15961 printIssue("explicitly"); 15962 printRemainingMessages(Colour::None); 15963 break; 15964 // These cases are here to prevent compiler warnings 15965 case ResultWas::Unknown: 15966 case ResultWas::FailureBit: 15967 case ResultWas::Exception: 15968 printResultType(Colour::Error, "** internal error **"); 15969 break; 15970 } 15971 } 15972 15973 private: 15974 void printSourceInfo() const { 15975 Colour colourGuard(Colour::FileName); 15976 stream << result.getSourceInfo() << ':'; 15977 } 15978 15979 void printResultType(Colour::Code colour, std::string const& passOrFail) const { 15980 if (!passOrFail.empty()) { 15981 { 15982 Colour colourGuard(colour); 15983 stream << ' ' << passOrFail; 15984 } 15985 stream << ':'; 15986 } 15987 } 15988 15989 void printIssue(std::string const& issue) const { 15990 stream << ' ' << issue; 15991 } 15992 15993 void printExpressionWas() { 15994 if (result.hasExpression()) { 15995 stream << ';'; 15996 { 15997 Colour colour(dimColour()); 15998 stream << " expression was:"; 15999 } 16000 printOriginalExpression(); 16001 } 16002 } 16003 16004 void printOriginalExpression() const { 16005 if (result.hasExpression()) { 16006 stream << ' ' << result.getExpression(); 16007 } 16008 } 16009 16010 void printReconstructedExpression() const { 16011 if (result.hasExpandedExpression()) { 16012 { 16013 Colour colour(dimColour()); 16014 stream << " for: "; 16015 } 16016 stream << result.getExpandedExpression(); 16017 } 16018 } 16019 16020 void printMessage() { 16021 if (itMessage != messages.end()) { 16022 stream << " '" << itMessage->message << '\''; 16023 ++itMessage; 16024 } 16025 } 16026 16027 void printRemainingMessages(Colour::Code colour = dimColour()) { 16028 if (itMessage == messages.end()) 16029 return; 16030 16031 const auto itEnd = messages.cend(); 16032 const auto N = static_cast<std::size_t>(std::distance(itMessage, itEnd)); 16033 16034 { 16035 Colour colourGuard(colour); 16036 stream << " with " << pluralise(N, "message") << ':'; 16037 } 16038 16039 while (itMessage != itEnd) { 16040 // If this assertion is a warning ignore any INFO messages 16041 if (printInfoMessages || itMessage->type != ResultWas::Info) { 16042 printMessage(); 16043 if (itMessage != itEnd) { 16044 Colour colourGuard(dimColour()); 16045 stream << " and"; 16046 } 16047 continue; 16048 } 16049 ++itMessage; 16050 } 16051 } 16052 16053 private: 16054 std::ostream& stream; 16055 AssertionResult const& result; 16056 std::vector<MessageInfo> messages; 16057 std::vector<MessageInfo>::const_iterator itMessage; 16058 bool printInfoMessages; 16059 }; 16060 16061 } // anon namespace 16062 16063 std::string CompactReporter::getDescription() { 16064 return "Reports test results on a single line, suitable for IDEs"; 16065 } 16066 16067 void CompactReporter::noMatchingTestCases( std::string const& spec ) { 16068 stream << "No test cases matched '" << spec << '\'' << std::endl; 16069 } 16070 16071 void CompactReporter::assertionStarting( AssertionInfo const& ) {} 16072 16073 bool CompactReporter::assertionEnded( AssertionStats const& _assertionStats ) { 16074 AssertionResult const& result = _assertionStats.assertionResult; 16075 16076 bool printInfoMessages = true; 16077 16078 // Drop out if result was successful and we're not printing those 16079 if( !m_config->includeSuccessfulResults() && result.isOk() ) { 16080 if( result.getResultType() != ResultWas::Warning ) 16081 return false; 16082 printInfoMessages = false; 16083 } 16084 16085 AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); 16086 printer.print(); 16087 16088 stream << std::endl; 16089 return true; 16090 } 16091 16092 void CompactReporter::sectionEnded(SectionStats const& _sectionStats) { 16093 double dur = _sectionStats.durationInSeconds; 16094 if ( shouldShowDuration( *m_config, dur ) ) { 16095 stream << getFormattedDuration( dur ) << " s: " << _sectionStats.sectionInfo.name << std::endl; 16096 } 16097 } 16098 16099 void CompactReporter::testRunEnded( TestRunStats const& _testRunStats ) { 16100 printTotals( stream, _testRunStats.totals ); 16101 stream << '\n' << std::endl; 16102 StreamingReporterBase::testRunEnded( _testRunStats ); 16103 } 16104 16105 CompactReporter::~CompactReporter() {} 16106 16107 CATCH_REGISTER_REPORTER( "compact", CompactReporter ) 16108 16109 } // end namespace Catch 16110 // end catch_reporter_compact.cpp 16111 // start catch_reporter_console.cpp 16112 16113 #include <cfloat> 16114 #include <cstdio> 16115 16116 #if defined(_MSC_VER) 16117 #pragma warning(push) 16118 #pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch 16119 // Note that 4062 (not all labels are handled and default is missing) is enabled 16120 #endif 16121 16122 #if defined(__clang__) 16123 # pragma clang diagnostic push 16124 // For simplicity, benchmarking-only helpers are always enabled 16125 # pragma clang diagnostic ignored "-Wunused-function" 16126 #endif 16127 16128 namespace Catch { 16129 16130 namespace { 16131 16132 // Formatter impl for ConsoleReporter 16133 class ConsoleAssertionPrinter { 16134 public: 16135 ConsoleAssertionPrinter& operator= (ConsoleAssertionPrinter const&) = delete; 16136 ConsoleAssertionPrinter(ConsoleAssertionPrinter const&) = delete; 16137 ConsoleAssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages) 16138 : stream(_stream), 16139 stats(_stats), 16140 result(_stats.assertionResult), 16141 colour(Colour::None), 16142 message(result.getMessage()), 16143 messages(_stats.infoMessages), 16144 printInfoMessages(_printInfoMessages) { 16145 switch (result.getResultType()) { 16146 case ResultWas::Ok: 16147 colour = Colour::Success; 16148 passOrFail = "PASSED"; 16149 //if( result.hasMessage() ) 16150 if (_stats.infoMessages.size() == 1) 16151 messageLabel = "with message"; 16152 if (_stats.infoMessages.size() > 1) 16153 messageLabel = "with messages"; 16154 break; 16155 case ResultWas::ExpressionFailed: 16156 if (result.isOk()) { 16157 colour = Colour::Success; 16158 passOrFail = "FAILED - but was ok"; 16159 } else { 16160 colour = Colour::Error; 16161 passOrFail = "FAILED"; 16162 } 16163 if (_stats.infoMessages.size() == 1) 16164 messageLabel = "with message"; 16165 if (_stats.infoMessages.size() > 1) 16166 messageLabel = "with messages"; 16167 break; 16168 case ResultWas::ThrewException: 16169 colour = Colour::Error; 16170 passOrFail = "FAILED"; 16171 messageLabel = "due to unexpected exception with "; 16172 if (_stats.infoMessages.size() == 1) 16173 messageLabel += "message"; 16174 if (_stats.infoMessages.size() > 1) 16175 messageLabel += "messages"; 16176 break; 16177 case ResultWas::FatalErrorCondition: 16178 colour = Colour::Error; 16179 passOrFail = "FAILED"; 16180 messageLabel = "due to a fatal error condition"; 16181 break; 16182 case ResultWas::DidntThrowException: 16183 colour = Colour::Error; 16184 passOrFail = "FAILED"; 16185 messageLabel = "because no exception was thrown where one was expected"; 16186 break; 16187 case ResultWas::Info: 16188 messageLabel = "info"; 16189 break; 16190 case ResultWas::Warning: 16191 messageLabel = "warning"; 16192 break; 16193 case ResultWas::ExplicitFailure: 16194 passOrFail = "FAILED"; 16195 colour = Colour::Error; 16196 if (_stats.infoMessages.size() == 1) 16197 messageLabel = "explicitly with message"; 16198 if (_stats.infoMessages.size() > 1) 16199 messageLabel = "explicitly with messages"; 16200 break; 16201 // These cases are here to prevent compiler warnings 16202 case ResultWas::Unknown: 16203 case ResultWas::FailureBit: 16204 case ResultWas::Exception: 16205 passOrFail = "** internal error **"; 16206 colour = Colour::Error; 16207 break; 16208 } 16209 } 16210 16211 void print() const { 16212 printSourceInfo(); 16213 if (stats.totals.assertions.total() > 0) { 16214 printResultType(); 16215 printOriginalExpression(); 16216 printReconstructedExpression(); 16217 } else { 16218 stream << '\n'; 16219 } 16220 printMessage(); 16221 } 16222 16223 private: 16224 void printResultType() const { 16225 if (!passOrFail.empty()) { 16226 Colour colourGuard(colour); 16227 stream << passOrFail << ":\n"; 16228 } 16229 } 16230 void printOriginalExpression() const { 16231 if (result.hasExpression()) { 16232 Colour colourGuard(Colour::OriginalExpression); 16233 stream << " "; 16234 stream << result.getExpressionInMacro(); 16235 stream << '\n'; 16236 } 16237 } 16238 void printReconstructedExpression() const { 16239 if (result.hasExpandedExpression()) { 16240 stream << "with expansion:\n"; 16241 Colour colourGuard(Colour::ReconstructedExpression); 16242 stream << Column(result.getExpandedExpression()).indent(2) << '\n'; 16243 } 16244 } 16245 void printMessage() const { 16246 if (!messageLabel.empty()) 16247 stream << messageLabel << ':' << '\n'; 16248 for (auto const& msg : messages) { 16249 // If this assertion is a warning ignore any INFO messages 16250 if (printInfoMessages || msg.type != ResultWas::Info) 16251 stream << Column(msg.message).indent(2) << '\n'; 16252 } 16253 } 16254 void printSourceInfo() const { 16255 Colour colourGuard(Colour::FileName); 16256 stream << result.getSourceInfo() << ": "; 16257 } 16258 16259 std::ostream& stream; 16260 AssertionStats const& stats; 16261 AssertionResult const& result; 16262 Colour::Code colour; 16263 std::string passOrFail; 16264 std::string messageLabel; 16265 std::string message; 16266 std::vector<MessageInfo> messages; 16267 bool printInfoMessages; 16268 }; 16269 16270 std::size_t makeRatio(std::size_t number, std::size_t total) { 16271 std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number / total : 0; 16272 return (ratio == 0 && number > 0) ? 1 : ratio; 16273 } 16274 16275 std::size_t& findMax(std::size_t& i, std::size_t& j, std::size_t& k) { 16276 if (i > j && i > k) 16277 return i; 16278 else if (j > k) 16279 return j; 16280 else 16281 return k; 16282 } 16283 16284 struct ColumnInfo { 16285 enum Justification { Left, Right }; 16286 std::string name; 16287 int width; 16288 Justification justification; 16289 }; 16290 struct ColumnBreak {}; 16291 struct RowBreak {}; 16292 16293 class Duration { 16294 enum class Unit { 16295 Auto, 16296 Nanoseconds, 16297 Microseconds, 16298 Milliseconds, 16299 Seconds, 16300 Minutes 16301 }; 16302 static const uint64_t s_nanosecondsInAMicrosecond = 1000; 16303 static const uint64_t s_nanosecondsInAMillisecond = 1000 * s_nanosecondsInAMicrosecond; 16304 static const uint64_t s_nanosecondsInASecond = 1000 * s_nanosecondsInAMillisecond; 16305 static const uint64_t s_nanosecondsInAMinute = 60 * s_nanosecondsInASecond; 16306 16307 double m_inNanoseconds; 16308 Unit m_units; 16309 16310 public: 16311 explicit Duration(double inNanoseconds, Unit units = Unit::Auto) 16312 : m_inNanoseconds(inNanoseconds), 16313 m_units(units) { 16314 if (m_units == Unit::Auto) { 16315 if (m_inNanoseconds < s_nanosecondsInAMicrosecond) 16316 m_units = Unit::Nanoseconds; 16317 else if (m_inNanoseconds < s_nanosecondsInAMillisecond) 16318 m_units = Unit::Microseconds; 16319 else if (m_inNanoseconds < s_nanosecondsInASecond) 16320 m_units = Unit::Milliseconds; 16321 else if (m_inNanoseconds < s_nanosecondsInAMinute) 16322 m_units = Unit::Seconds; 16323 else 16324 m_units = Unit::Minutes; 16325 } 16326 16327 } 16328 16329 auto value() const -> double { 16330 switch (m_units) { 16331 case Unit::Microseconds: 16332 return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMicrosecond); 16333 case Unit::Milliseconds: 16334 return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMillisecond); 16335 case Unit::Seconds: 16336 return m_inNanoseconds / static_cast<double>(s_nanosecondsInASecond); 16337 case Unit::Minutes: 16338 return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMinute); 16339 default: 16340 return m_inNanoseconds; 16341 } 16342 } 16343 auto unitsAsString() const -> std::string { 16344 switch (m_units) { 16345 case Unit::Nanoseconds: 16346 return "ns"; 16347 case Unit::Microseconds: 16348 return "us"; 16349 case Unit::Milliseconds: 16350 return "ms"; 16351 case Unit::Seconds: 16352 return "s"; 16353 case Unit::Minutes: 16354 return "m"; 16355 default: 16356 return "** internal error **"; 16357 } 16358 16359 } 16360 friend auto operator << (std::ostream& os, Duration const& duration) -> std::ostream& { 16361 return os << duration.value() << ' ' << duration.unitsAsString(); 16362 } 16363 }; 16364 } // end anon namespace 16365 16366 class TablePrinter { 16367 std::ostream& m_os; 16368 std::vector<ColumnInfo> m_columnInfos; 16369 std::ostringstream m_oss; 16370 int m_currentColumn = -1; 16371 bool m_isOpen = false; 16372 16373 public: 16374 TablePrinter( std::ostream& os, std::vector<ColumnInfo> columnInfos ) 16375 : m_os( os ), 16376 m_columnInfos( std::move( columnInfos ) ) {} 16377 16378 auto columnInfos() const -> std::vector<ColumnInfo> const& { 16379 return m_columnInfos; 16380 } 16381 16382 void open() { 16383 if (!m_isOpen) { 16384 m_isOpen = true; 16385 *this << RowBreak(); 16386 16387 Columns headerCols; 16388 Spacer spacer(2); 16389 for (auto const& info : m_columnInfos) { 16390 headerCols += Column(info.name).width(static_cast<std::size_t>(info.width - 2)); 16391 headerCols += spacer; 16392 } 16393 m_os << headerCols << '\n'; 16394 16395 m_os << Catch::getLineOfChars<'-'>() << '\n'; 16396 } 16397 } 16398 void close() { 16399 if (m_isOpen) { 16400 *this << RowBreak(); 16401 m_os << std::endl; 16402 m_isOpen = false; 16403 } 16404 } 16405 16406 template<typename T> 16407 friend TablePrinter& operator << (TablePrinter& tp, T const& value) { 16408 tp.m_oss << value; 16409 return tp; 16410 } 16411 16412 friend TablePrinter& operator << (TablePrinter& tp, ColumnBreak) { 16413 auto colStr = tp.m_oss.str(); 16414 const auto strSize = colStr.size(); 16415 tp.m_oss.str(""); 16416 tp.open(); 16417 if (tp.m_currentColumn == static_cast<int>(tp.m_columnInfos.size() - 1)) { 16418 tp.m_currentColumn = -1; 16419 tp.m_os << '\n'; 16420 } 16421 tp.m_currentColumn++; 16422 16423 auto colInfo = tp.m_columnInfos[tp.m_currentColumn]; 16424 auto padding = (strSize + 1 < static_cast<std::size_t>(colInfo.width)) 16425 ? std::string(colInfo.width - (strSize + 1), ' ') 16426 : std::string(); 16427 if (colInfo.justification == ColumnInfo::Left) 16428 tp.m_os << colStr << padding << ' '; 16429 else 16430 tp.m_os << padding << colStr << ' '; 16431 return tp; 16432 } 16433 16434 friend TablePrinter& operator << (TablePrinter& tp, RowBreak) { 16435 if (tp.m_currentColumn > 0) { 16436 tp.m_os << '\n'; 16437 tp.m_currentColumn = -1; 16438 } 16439 return tp; 16440 } 16441 }; 16442 16443 ConsoleReporter::ConsoleReporter(ReporterConfig const& config) 16444 : StreamingReporterBase(config), 16445 m_tablePrinter(new TablePrinter(config.stream(), 16446 [&config]() -> std::vector<ColumnInfo> { 16447 if (config.fullConfig()->benchmarkNoAnalysis()) 16448 { 16449 return{ 16450 { "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 43, ColumnInfo::Left }, 16451 { " samples", 14, ColumnInfo::Right }, 16452 { " iterations", 14, ColumnInfo::Right }, 16453 { " mean", 14, ColumnInfo::Right } 16454 }; 16455 } 16456 else 16457 { 16458 return{ 16459 { "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 43, ColumnInfo::Left }, 16460 { "samples mean std dev", 14, ColumnInfo::Right }, 16461 { "iterations low mean low std dev", 14, ColumnInfo::Right }, 16462 { "estimated high mean high std dev", 14, ColumnInfo::Right } 16463 }; 16464 } 16465 }())) {} 16466 ConsoleReporter::~ConsoleReporter() = default; 16467 16468 std::string ConsoleReporter::getDescription() { 16469 return "Reports test results as plain lines of text"; 16470 } 16471 16472 void ConsoleReporter::noMatchingTestCases(std::string const& spec) { 16473 stream << "No test cases matched '" << spec << '\'' << std::endl; 16474 } 16475 16476 void ConsoleReporter::reportInvalidArguments(std::string const&arg){ 16477 stream << "Invalid Filter: " << arg << std::endl; 16478 } 16479 16480 void ConsoleReporter::assertionStarting(AssertionInfo const&) {} 16481 16482 bool ConsoleReporter::assertionEnded(AssertionStats const& _assertionStats) { 16483 AssertionResult const& result = _assertionStats.assertionResult; 16484 16485 bool includeResults = m_config->includeSuccessfulResults() || !result.isOk(); 16486 16487 // Drop out if result was successful but we're not printing them. 16488 if (!includeResults && result.getResultType() != ResultWas::Warning) 16489 return false; 16490 16491 lazyPrint(); 16492 16493 ConsoleAssertionPrinter printer(stream, _assertionStats, includeResults); 16494 printer.print(); 16495 stream << std::endl; 16496 return true; 16497 } 16498 16499 void ConsoleReporter::sectionStarting(SectionInfo const& _sectionInfo) { 16500 m_tablePrinter->close(); 16501 m_headerPrinted = false; 16502 StreamingReporterBase::sectionStarting(_sectionInfo); 16503 } 16504 void ConsoleReporter::sectionEnded(SectionStats const& _sectionStats) { 16505 m_tablePrinter->close(); 16506 if (_sectionStats.missingAssertions) { 16507 lazyPrint(); 16508 Colour colour(Colour::ResultError); 16509 if (m_sectionStack.size() > 1) 16510 stream << "\nNo assertions in section"; 16511 else 16512 stream << "\nNo assertions in test case"; 16513 stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; 16514 } 16515 double dur = _sectionStats.durationInSeconds; 16516 if (shouldShowDuration(*m_config, dur)) { 16517 stream << getFormattedDuration(dur) << " s: " << _sectionStats.sectionInfo.name << std::endl; 16518 } 16519 if (m_headerPrinted) { 16520 m_headerPrinted = false; 16521 } 16522 StreamingReporterBase::sectionEnded(_sectionStats); 16523 } 16524 16525 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 16526 void ConsoleReporter::benchmarkPreparing(std::string const& name) { 16527 lazyPrintWithoutClosingBenchmarkTable(); 16528 16529 auto nameCol = Column(name).width(static_cast<std::size_t>(m_tablePrinter->columnInfos()[0].width - 2)); 16530 16531 bool firstLine = true; 16532 for (auto line : nameCol) { 16533 if (!firstLine) 16534 (*m_tablePrinter) << ColumnBreak() << ColumnBreak() << ColumnBreak(); 16535 else 16536 firstLine = false; 16537 16538 (*m_tablePrinter) << line << ColumnBreak(); 16539 } 16540 } 16541 16542 void ConsoleReporter::benchmarkStarting(BenchmarkInfo const& info) { 16543 (*m_tablePrinter) << info.samples << ColumnBreak() 16544 << info.iterations << ColumnBreak(); 16545 if (!m_config->benchmarkNoAnalysis()) 16546 (*m_tablePrinter) << Duration(info.estimatedDuration) << ColumnBreak(); 16547 } 16548 void ConsoleReporter::benchmarkEnded(BenchmarkStats<> const& stats) { 16549 if (m_config->benchmarkNoAnalysis()) 16550 { 16551 (*m_tablePrinter) << Duration(stats.mean.point.count()) << ColumnBreak(); 16552 } 16553 else 16554 { 16555 (*m_tablePrinter) << ColumnBreak() 16556 << Duration(stats.mean.point.count()) << ColumnBreak() 16557 << Duration(stats.mean.lower_bound.count()) << ColumnBreak() 16558 << Duration(stats.mean.upper_bound.count()) << ColumnBreak() << ColumnBreak() 16559 << Duration(stats.standardDeviation.point.count()) << ColumnBreak() 16560 << Duration(stats.standardDeviation.lower_bound.count()) << ColumnBreak() 16561 << Duration(stats.standardDeviation.upper_bound.count()) << ColumnBreak() << ColumnBreak() << ColumnBreak() << ColumnBreak() << ColumnBreak(); 16562 } 16563 } 16564 16565 void ConsoleReporter::benchmarkFailed(std::string const& error) { 16566 Colour colour(Colour::Red); 16567 (*m_tablePrinter) 16568 << "Benchmark failed (" << error << ')' 16569 << ColumnBreak() << RowBreak(); 16570 } 16571 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 16572 16573 void ConsoleReporter::testCaseEnded(TestCaseStats const& _testCaseStats) { 16574 m_tablePrinter->close(); 16575 StreamingReporterBase::testCaseEnded(_testCaseStats); 16576 m_headerPrinted = false; 16577 } 16578 void ConsoleReporter::testGroupEnded(TestGroupStats const& _testGroupStats) { 16579 if (currentGroupInfo.used) { 16580 printSummaryDivider(); 16581 stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; 16582 printTotals(_testGroupStats.totals); 16583 stream << '\n' << std::endl; 16584 } 16585 StreamingReporterBase::testGroupEnded(_testGroupStats); 16586 } 16587 void ConsoleReporter::testRunEnded(TestRunStats const& _testRunStats) { 16588 printTotalsDivider(_testRunStats.totals); 16589 printTotals(_testRunStats.totals); 16590 stream << std::endl; 16591 StreamingReporterBase::testRunEnded(_testRunStats); 16592 } 16593 void ConsoleReporter::testRunStarting(TestRunInfo const& _testInfo) { 16594 StreamingReporterBase::testRunStarting(_testInfo); 16595 printTestFilters(); 16596 } 16597 16598 void ConsoleReporter::lazyPrint() { 16599 16600 m_tablePrinter->close(); 16601 lazyPrintWithoutClosingBenchmarkTable(); 16602 } 16603 16604 void ConsoleReporter::lazyPrintWithoutClosingBenchmarkTable() { 16605 16606 if (!currentTestRunInfo.used) 16607 lazyPrintRunInfo(); 16608 if (!currentGroupInfo.used) 16609 lazyPrintGroupInfo(); 16610 16611 if (!m_headerPrinted) { 16612 printTestCaseAndSectionHeader(); 16613 m_headerPrinted = true; 16614 } 16615 } 16616 void ConsoleReporter::lazyPrintRunInfo() { 16617 stream << '\n' << getLineOfChars<'~'>() << '\n'; 16618 Colour colour(Colour::SecondaryText); 16619 stream << currentTestRunInfo->name 16620 << " is a Catch v" << libraryVersion() << " host application.\n" 16621 << "Run with -? for options\n\n"; 16622 16623 if (m_config->rngSeed() != 0) 16624 stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n"; 16625 16626 currentTestRunInfo.used = true; 16627 } 16628 void ConsoleReporter::lazyPrintGroupInfo() { 16629 if (!currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1) { 16630 printClosedHeader("Group: " + currentGroupInfo->name); 16631 currentGroupInfo.used = true; 16632 } 16633 } 16634 void ConsoleReporter::printTestCaseAndSectionHeader() { 16635 assert(!m_sectionStack.empty()); 16636 printOpenHeader(currentTestCaseInfo->name); 16637 16638 if (m_sectionStack.size() > 1) { 16639 Colour colourGuard(Colour::Headers); 16640 16641 auto 16642 it = m_sectionStack.begin() + 1, // Skip first section (test case) 16643 itEnd = m_sectionStack.end(); 16644 for (; it != itEnd; ++it) 16645 printHeaderString(it->name, 2); 16646 } 16647 16648 SourceLineInfo lineInfo = m_sectionStack.back().lineInfo; 16649 16650 stream << getLineOfChars<'-'>() << '\n'; 16651 Colour colourGuard(Colour::FileName); 16652 stream << lineInfo << '\n'; 16653 stream << getLineOfChars<'.'>() << '\n' << std::endl; 16654 } 16655 16656 void ConsoleReporter::printClosedHeader(std::string const& _name) { 16657 printOpenHeader(_name); 16658 stream << getLineOfChars<'.'>() << '\n'; 16659 } 16660 void ConsoleReporter::printOpenHeader(std::string const& _name) { 16661 stream << getLineOfChars<'-'>() << '\n'; 16662 { 16663 Colour colourGuard(Colour::Headers); 16664 printHeaderString(_name); 16665 } 16666 } 16667 16668 // if string has a : in first line will set indent to follow it on 16669 // subsequent lines 16670 void ConsoleReporter::printHeaderString(std::string const& _string, std::size_t indent) { 16671 std::size_t i = _string.find(": "); 16672 if (i != std::string::npos) 16673 i += 2; 16674 else 16675 i = 0; 16676 stream << Column(_string).indent(indent + i).initialIndent(indent) << '\n'; 16677 } 16678 16679 struct SummaryColumn { 16680 16681 SummaryColumn( std::string _label, Colour::Code _colour ) 16682 : label( std::move( _label ) ), 16683 colour( _colour ) {} 16684 SummaryColumn addRow( std::size_t count ) { 16685 ReusableStringStream rss; 16686 rss << count; 16687 std::string row = rss.str(); 16688 for (auto& oldRow : rows) { 16689 while (oldRow.size() < row.size()) 16690 oldRow = ' ' + oldRow; 16691 while (oldRow.size() > row.size()) 16692 row = ' ' + row; 16693 } 16694 rows.push_back(row); 16695 return *this; 16696 } 16697 16698 std::string label; 16699 Colour::Code colour; 16700 std::vector<std::string> rows; 16701 16702 }; 16703 16704 void ConsoleReporter::printTotals( Totals const& totals ) { 16705 if (totals.testCases.total() == 0) { 16706 stream << Colour(Colour::Warning) << "No tests ran\n"; 16707 } else if (totals.assertions.total() > 0 && totals.testCases.allPassed()) { 16708 stream << Colour(Colour::ResultSuccess) << "All tests passed"; 16709 stream << " (" 16710 << pluralise(totals.assertions.passed, "assertion") << " in " 16711 << pluralise(totals.testCases.passed, "test case") << ')' 16712 << '\n'; 16713 } else { 16714 16715 std::vector<SummaryColumn> columns; 16716 columns.push_back(SummaryColumn("", Colour::None) 16717 .addRow(totals.testCases.total()) 16718 .addRow(totals.assertions.total())); 16719 columns.push_back(SummaryColumn("passed", Colour::Success) 16720 .addRow(totals.testCases.passed) 16721 .addRow(totals.assertions.passed)); 16722 columns.push_back(SummaryColumn("failed", Colour::ResultError) 16723 .addRow(totals.testCases.failed) 16724 .addRow(totals.assertions.failed)); 16725 columns.push_back(SummaryColumn("failed as expected", Colour::ResultExpectedFailure) 16726 .addRow(totals.testCases.failedButOk) 16727 .addRow(totals.assertions.failedButOk)); 16728 16729 printSummaryRow("test cases", columns, 0); 16730 printSummaryRow("assertions", columns, 1); 16731 } 16732 } 16733 void ConsoleReporter::printSummaryRow(std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row) { 16734 for (auto col : cols) { 16735 std::string value = col.rows[row]; 16736 if (col.label.empty()) { 16737 stream << label << ": "; 16738 if (value != "0") 16739 stream << value; 16740 else 16741 stream << Colour(Colour::Warning) << "- none -"; 16742 } else if (value != "0") { 16743 stream << Colour(Colour::LightGrey) << " | "; 16744 stream << Colour(col.colour) 16745 << value << ' ' << col.label; 16746 } 16747 } 16748 stream << '\n'; 16749 } 16750 16751 void ConsoleReporter::printTotalsDivider(Totals const& totals) { 16752 if (totals.testCases.total() > 0) { 16753 std::size_t failedRatio = makeRatio(totals.testCases.failed, totals.testCases.total()); 16754 std::size_t failedButOkRatio = makeRatio(totals.testCases.failedButOk, totals.testCases.total()); 16755 std::size_t passedRatio = makeRatio(totals.testCases.passed, totals.testCases.total()); 16756 while (failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH - 1) 16757 findMax(failedRatio, failedButOkRatio, passedRatio)++; 16758 while (failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH - 1) 16759 findMax(failedRatio, failedButOkRatio, passedRatio)--; 16760 16761 stream << Colour(Colour::Error) << std::string(failedRatio, '='); 16762 stream << Colour(Colour::ResultExpectedFailure) << std::string(failedButOkRatio, '='); 16763 if (totals.testCases.allPassed()) 16764 stream << Colour(Colour::ResultSuccess) << std::string(passedRatio, '='); 16765 else 16766 stream << Colour(Colour::Success) << std::string(passedRatio, '='); 16767 } else { 16768 stream << Colour(Colour::Warning) << std::string(CATCH_CONFIG_CONSOLE_WIDTH - 1, '='); 16769 } 16770 stream << '\n'; 16771 } 16772 void ConsoleReporter::printSummaryDivider() { 16773 stream << getLineOfChars<'-'>() << '\n'; 16774 } 16775 16776 void ConsoleReporter::printTestFilters() { 16777 if (m_config->testSpec().hasFilters()) { 16778 Colour guard(Colour::BrightYellow); 16779 stream << "Filters: " << serializeFilters(m_config->getTestsOrTags()) << '\n'; 16780 } 16781 } 16782 16783 CATCH_REGISTER_REPORTER("console", ConsoleReporter) 16784 16785 } // end namespace Catch 16786 16787 #if defined(_MSC_VER) 16788 #pragma warning(pop) 16789 #endif 16790 16791 #if defined(__clang__) 16792 # pragma clang diagnostic pop 16793 #endif 16794 // end catch_reporter_console.cpp 16795 // start catch_reporter_junit.cpp 16796 16797 #include <cassert> 16798 #include <sstream> 16799 #include <ctime> 16800 #include <algorithm> 16801 #include <iomanip> 16802 16803 namespace Catch { 16804 16805 namespace { 16806 std::string getCurrentTimestamp() { 16807 // Beware, this is not reentrant because of backward compatibility issues 16808 // Also, UTC only, again because of backward compatibility (%z is C++11) 16809 time_t rawtime; 16810 std::time(&rawtime); 16811 auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); 16812 16813 #ifdef _MSC_VER 16814 std::tm timeInfo = {}; 16815 gmtime_s(&timeInfo, &rawtime); 16816 #else 16817 std::tm* timeInfo; 16818 timeInfo = std::gmtime(&rawtime); 16819 #endif 16820 16821 char timeStamp[timeStampSize]; 16822 const char * const fmt = "%Y-%m-%dT%H:%M:%SZ"; 16823 16824 #ifdef _MSC_VER 16825 std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); 16826 #else 16827 std::strftime(timeStamp, timeStampSize, fmt, timeInfo); 16828 #endif 16829 return std::string(timeStamp, timeStampSize-1); 16830 } 16831 16832 std::string fileNameTag(const std::vector<std::string> &tags) { 16833 auto it = std::find_if(begin(tags), 16834 end(tags), 16835 [] (std::string const& tag) {return tag.front() == '#'; }); 16836 if (it != tags.end()) 16837 return it->substr(1); 16838 return std::string(); 16839 } 16840 16841 // Formats the duration in seconds to 3 decimal places. 16842 // This is done because some genius defined Maven Surefire schema 16843 // in a way that only accepts 3 decimal places, and tools like 16844 // Jenkins use that schema for validation JUnit reporter output. 16845 std::string formatDuration( double seconds ) { 16846 ReusableStringStream rss; 16847 rss << std::fixed << std::setprecision( 3 ) << seconds; 16848 return rss.str(); 16849 } 16850 16851 } // anonymous namespace 16852 16853 JunitReporter::JunitReporter( ReporterConfig const& _config ) 16854 : CumulativeReporterBase( _config ), 16855 xml( _config.stream() ) 16856 { 16857 m_reporterPrefs.shouldRedirectStdOut = true; 16858 m_reporterPrefs.shouldReportAllAssertions = true; 16859 } 16860 16861 JunitReporter::~JunitReporter() {} 16862 16863 std::string JunitReporter::getDescription() { 16864 return "Reports test results in an XML format that looks like Ant's junitreport target"; 16865 } 16866 16867 void JunitReporter::noMatchingTestCases( std::string const& /*spec*/ ) {} 16868 16869 void JunitReporter::testRunStarting( TestRunInfo const& runInfo ) { 16870 CumulativeReporterBase::testRunStarting( runInfo ); 16871 xml.startElement( "testsuites" ); 16872 } 16873 16874 void JunitReporter::testGroupStarting( GroupInfo const& groupInfo ) { 16875 suiteTimer.start(); 16876 stdOutForSuite.clear(); 16877 stdErrForSuite.clear(); 16878 unexpectedExceptions = 0; 16879 CumulativeReporterBase::testGroupStarting( groupInfo ); 16880 } 16881 16882 void JunitReporter::testCaseStarting( TestCaseInfo const& testCaseInfo ) { 16883 m_okToFail = testCaseInfo.okToFail(); 16884 } 16885 16886 bool JunitReporter::assertionEnded( AssertionStats const& assertionStats ) { 16887 if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException && !m_okToFail ) 16888 unexpectedExceptions++; 16889 return CumulativeReporterBase::assertionEnded( assertionStats ); 16890 } 16891 16892 void JunitReporter::testCaseEnded( TestCaseStats const& testCaseStats ) { 16893 stdOutForSuite += testCaseStats.stdOut; 16894 stdErrForSuite += testCaseStats.stdErr; 16895 CumulativeReporterBase::testCaseEnded( testCaseStats ); 16896 } 16897 16898 void JunitReporter::testGroupEnded( TestGroupStats const& testGroupStats ) { 16899 double suiteTime = suiteTimer.getElapsedSeconds(); 16900 CumulativeReporterBase::testGroupEnded( testGroupStats ); 16901 writeGroup( *m_testGroups.back(), suiteTime ); 16902 } 16903 16904 void JunitReporter::testRunEndedCumulative() { 16905 xml.endElement(); 16906 } 16907 16908 void JunitReporter::writeGroup( TestGroupNode const& groupNode, double suiteTime ) { 16909 XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); 16910 16911 TestGroupStats const& stats = groupNode.value; 16912 xml.writeAttribute( "name", stats.groupInfo.name ); 16913 xml.writeAttribute( "errors", unexpectedExceptions ); 16914 xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions ); 16915 xml.writeAttribute( "tests", stats.totals.assertions.total() ); 16916 xml.writeAttribute( "hostname", "tbd" ); // !TBD 16917 if( m_config->showDurations() == ShowDurations::Never ) 16918 xml.writeAttribute( "time", "" ); 16919 else 16920 xml.writeAttribute( "time", formatDuration( suiteTime ) ); 16921 xml.writeAttribute( "timestamp", getCurrentTimestamp() ); 16922 16923 // Write properties if there are any 16924 if (m_config->hasTestFilters() || m_config->rngSeed() != 0) { 16925 auto properties = xml.scopedElement("properties"); 16926 if (m_config->hasTestFilters()) { 16927 xml.scopedElement("property") 16928 .writeAttribute("name", "filters") 16929 .writeAttribute("value", serializeFilters(m_config->getTestsOrTags())); 16930 } 16931 if (m_config->rngSeed() != 0) { 16932 xml.scopedElement("property") 16933 .writeAttribute("name", "random-seed") 16934 .writeAttribute("value", m_config->rngSeed()); 16935 } 16936 } 16937 16938 // Write test cases 16939 for( auto const& child : groupNode.children ) 16940 writeTestCase( *child ); 16941 16942 xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite ), XmlFormatting::Newline ); 16943 xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite ), XmlFormatting::Newline ); 16944 } 16945 16946 void JunitReporter::writeTestCase( TestCaseNode const& testCaseNode ) { 16947 TestCaseStats const& stats = testCaseNode.value; 16948 16949 // All test cases have exactly one section - which represents the 16950 // test case itself. That section may have 0-n nested sections 16951 assert( testCaseNode.children.size() == 1 ); 16952 SectionNode const& rootSection = *testCaseNode.children.front(); 16953 16954 std::string className = stats.testInfo.className; 16955 16956 if( className.empty() ) { 16957 className = fileNameTag(stats.testInfo.tags); 16958 if ( className.empty() ) 16959 className = "global"; 16960 } 16961 16962 if ( !m_config->name().empty() ) 16963 className = m_config->name() + "." + className; 16964 16965 writeSection( className, "", rootSection, stats.testInfo.okToFail() ); 16966 } 16967 16968 void JunitReporter::writeSection( std::string const& className, 16969 std::string const& rootName, 16970 SectionNode const& sectionNode, 16971 bool testOkToFail) { 16972 std::string name = trim( sectionNode.stats.sectionInfo.name ); 16973 if( !rootName.empty() ) 16974 name = rootName + '/' + name; 16975 16976 if( !sectionNode.assertions.empty() || 16977 !sectionNode.stdOut.empty() || 16978 !sectionNode.stdErr.empty() ) { 16979 XmlWriter::ScopedElement e = xml.scopedElement( "testcase" ); 16980 if( className.empty() ) { 16981 xml.writeAttribute( "classname", name ); 16982 xml.writeAttribute( "name", "root" ); 16983 } 16984 else { 16985 xml.writeAttribute( "classname", className ); 16986 xml.writeAttribute( "name", name ); 16987 } 16988 xml.writeAttribute( "time", formatDuration( sectionNode.stats.durationInSeconds ) ); 16989 // This is not ideal, but it should be enough to mimic gtest's 16990 // junit output. 16991 // Ideally the JUnit reporter would also handle `skipTest` 16992 // events and write those out appropriately. 16993 xml.writeAttribute( "status", "run" ); 16994 16995 if (sectionNode.stats.assertions.failedButOk) { 16996 xml.scopedElement("skipped") 16997 .writeAttribute("message", "TEST_CASE tagged with !mayfail"); 16998 } 16999 17000 writeAssertions( sectionNode ); 17001 17002 if( !sectionNode.stdOut.empty() ) 17003 xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), XmlFormatting::Newline ); 17004 if( !sectionNode.stdErr.empty() ) 17005 xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), XmlFormatting::Newline ); 17006 } 17007 for( auto const& childNode : sectionNode.childSections ) 17008 if( className.empty() ) 17009 writeSection( name, "", *childNode, testOkToFail ); 17010 else 17011 writeSection( className, name, *childNode, testOkToFail ); 17012 } 17013 17014 void JunitReporter::writeAssertions( SectionNode const& sectionNode ) { 17015 for( auto const& assertion : sectionNode.assertions ) 17016 writeAssertion( assertion ); 17017 } 17018 17019 void JunitReporter::writeAssertion( AssertionStats const& stats ) { 17020 AssertionResult const& result = stats.assertionResult; 17021 if( !result.isOk() ) { 17022 std::string elementName; 17023 switch( result.getResultType() ) { 17024 case ResultWas::ThrewException: 17025 case ResultWas::FatalErrorCondition: 17026 elementName = "error"; 17027 break; 17028 case ResultWas::ExplicitFailure: 17029 case ResultWas::ExpressionFailed: 17030 case ResultWas::DidntThrowException: 17031 elementName = "failure"; 17032 break; 17033 17034 // We should never see these here: 17035 case ResultWas::Info: 17036 case ResultWas::Warning: 17037 case ResultWas::Ok: 17038 case ResultWas::Unknown: 17039 case ResultWas::FailureBit: 17040 case ResultWas::Exception: 17041 elementName = "internalError"; 17042 break; 17043 } 17044 17045 XmlWriter::ScopedElement e = xml.scopedElement( elementName ); 17046 17047 xml.writeAttribute( "message", result.getExpression() ); 17048 xml.writeAttribute( "type", result.getTestMacroName() ); 17049 17050 ReusableStringStream rss; 17051 if (stats.totals.assertions.total() > 0) { 17052 rss << "FAILED" << ":\n"; 17053 if (result.hasExpression()) { 17054 rss << " "; 17055 rss << result.getExpressionInMacro(); 17056 rss << '\n'; 17057 } 17058 if (result.hasExpandedExpression()) { 17059 rss << "with expansion:\n"; 17060 rss << Column(result.getExpandedExpression()).indent(2) << '\n'; 17061 } 17062 } else { 17063 rss << '\n'; 17064 } 17065 17066 if( !result.getMessage().empty() ) 17067 rss << result.getMessage() << '\n'; 17068 for( auto const& msg : stats.infoMessages ) 17069 if( msg.type == ResultWas::Info ) 17070 rss << msg.message << '\n'; 17071 17072 rss << "at " << result.getSourceInfo(); 17073 xml.writeText( rss.str(), XmlFormatting::Newline ); 17074 } 17075 } 17076 17077 CATCH_REGISTER_REPORTER( "junit", JunitReporter ) 17078 17079 } // end namespace Catch 17080 // end catch_reporter_junit.cpp 17081 // start catch_reporter_listening.cpp 17082 17083 #include <cassert> 17084 17085 namespace Catch { 17086 17087 ListeningReporter::ListeningReporter() { 17088 // We will assume that listeners will always want all assertions 17089 m_preferences.shouldReportAllAssertions = true; 17090 } 17091 17092 void ListeningReporter::addListener( IStreamingReporterPtr&& listener ) { 17093 m_listeners.push_back( std::move( listener ) ); 17094 } 17095 17096 void ListeningReporter::addReporter(IStreamingReporterPtr&& reporter) { 17097 assert(!m_reporter && "Listening reporter can wrap only 1 real reporter"); 17098 m_reporter = std::move( reporter ); 17099 m_preferences.shouldRedirectStdOut = m_reporter->getPreferences().shouldRedirectStdOut; 17100 } 17101 17102 ReporterPreferences ListeningReporter::getPreferences() const { 17103 return m_preferences; 17104 } 17105 17106 std::set<Verbosity> ListeningReporter::getSupportedVerbosities() { 17107 return std::set<Verbosity>{ }; 17108 } 17109 17110 void ListeningReporter::noMatchingTestCases( std::string const& spec ) { 17111 for ( auto const& listener : m_listeners ) { 17112 listener->noMatchingTestCases( spec ); 17113 } 17114 m_reporter->noMatchingTestCases( spec ); 17115 } 17116 17117 void ListeningReporter::reportInvalidArguments(std::string const&arg){ 17118 for ( auto const& listener : m_listeners ) { 17119 listener->reportInvalidArguments( arg ); 17120 } 17121 m_reporter->reportInvalidArguments( arg ); 17122 } 17123 17124 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 17125 void ListeningReporter::benchmarkPreparing( std::string const& name ) { 17126 for (auto const& listener : m_listeners) { 17127 listener->benchmarkPreparing(name); 17128 } 17129 m_reporter->benchmarkPreparing(name); 17130 } 17131 void ListeningReporter::benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) { 17132 for ( auto const& listener : m_listeners ) { 17133 listener->benchmarkStarting( benchmarkInfo ); 17134 } 17135 m_reporter->benchmarkStarting( benchmarkInfo ); 17136 } 17137 void ListeningReporter::benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) { 17138 for ( auto const& listener : m_listeners ) { 17139 listener->benchmarkEnded( benchmarkStats ); 17140 } 17141 m_reporter->benchmarkEnded( benchmarkStats ); 17142 } 17143 17144 void ListeningReporter::benchmarkFailed( std::string const& error ) { 17145 for (auto const& listener : m_listeners) { 17146 listener->benchmarkFailed(error); 17147 } 17148 m_reporter->benchmarkFailed(error); 17149 } 17150 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 17151 17152 void ListeningReporter::testRunStarting( TestRunInfo const& testRunInfo ) { 17153 for ( auto const& listener : m_listeners ) { 17154 listener->testRunStarting( testRunInfo ); 17155 } 17156 m_reporter->testRunStarting( testRunInfo ); 17157 } 17158 17159 void ListeningReporter::testGroupStarting( GroupInfo const& groupInfo ) { 17160 for ( auto const& listener : m_listeners ) { 17161 listener->testGroupStarting( groupInfo ); 17162 } 17163 m_reporter->testGroupStarting( groupInfo ); 17164 } 17165 17166 void ListeningReporter::testCaseStarting( TestCaseInfo const& testInfo ) { 17167 for ( auto const& listener : m_listeners ) { 17168 listener->testCaseStarting( testInfo ); 17169 } 17170 m_reporter->testCaseStarting( testInfo ); 17171 } 17172 17173 void ListeningReporter::sectionStarting( SectionInfo const& sectionInfo ) { 17174 for ( auto const& listener : m_listeners ) { 17175 listener->sectionStarting( sectionInfo ); 17176 } 17177 m_reporter->sectionStarting( sectionInfo ); 17178 } 17179 17180 void ListeningReporter::assertionStarting( AssertionInfo const& assertionInfo ) { 17181 for ( auto const& listener : m_listeners ) { 17182 listener->assertionStarting( assertionInfo ); 17183 } 17184 m_reporter->assertionStarting( assertionInfo ); 17185 } 17186 17187 // The return value indicates if the messages buffer should be cleared: 17188 bool ListeningReporter::assertionEnded( AssertionStats const& assertionStats ) { 17189 for( auto const& listener : m_listeners ) { 17190 static_cast<void>( listener->assertionEnded( assertionStats ) ); 17191 } 17192 return m_reporter->assertionEnded( assertionStats ); 17193 } 17194 17195 void ListeningReporter::sectionEnded( SectionStats const& sectionStats ) { 17196 for ( auto const& listener : m_listeners ) { 17197 listener->sectionEnded( sectionStats ); 17198 } 17199 m_reporter->sectionEnded( sectionStats ); 17200 } 17201 17202 void ListeningReporter::testCaseEnded( TestCaseStats const& testCaseStats ) { 17203 for ( auto const& listener : m_listeners ) { 17204 listener->testCaseEnded( testCaseStats ); 17205 } 17206 m_reporter->testCaseEnded( testCaseStats ); 17207 } 17208 17209 void ListeningReporter::testGroupEnded( TestGroupStats const& testGroupStats ) { 17210 for ( auto const& listener : m_listeners ) { 17211 listener->testGroupEnded( testGroupStats ); 17212 } 17213 m_reporter->testGroupEnded( testGroupStats ); 17214 } 17215 17216 void ListeningReporter::testRunEnded( TestRunStats const& testRunStats ) { 17217 for ( auto const& listener : m_listeners ) { 17218 listener->testRunEnded( testRunStats ); 17219 } 17220 m_reporter->testRunEnded( testRunStats ); 17221 } 17222 17223 void ListeningReporter::skipTest( TestCaseInfo const& testInfo ) { 17224 for ( auto const& listener : m_listeners ) { 17225 listener->skipTest( testInfo ); 17226 } 17227 m_reporter->skipTest( testInfo ); 17228 } 17229 17230 bool ListeningReporter::isMulti() const { 17231 return true; 17232 } 17233 17234 } // end namespace Catch 17235 // end catch_reporter_listening.cpp 17236 // start catch_reporter_xml.cpp 17237 17238 #if defined(_MSC_VER) 17239 #pragma warning(push) 17240 #pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch 17241 // Note that 4062 (not all labels are handled 17242 // and default is missing) is enabled 17243 #endif 17244 17245 namespace Catch { 17246 XmlReporter::XmlReporter( ReporterConfig const& _config ) 17247 : StreamingReporterBase( _config ), 17248 m_xml(_config.stream()) 17249 { 17250 m_reporterPrefs.shouldRedirectStdOut = true; 17251 m_reporterPrefs.shouldReportAllAssertions = true; 17252 } 17253 17254 XmlReporter::~XmlReporter() = default; 17255 17256 std::string XmlReporter::getDescription() { 17257 return "Reports test results as an XML document"; 17258 } 17259 17260 std::string XmlReporter::getStylesheetRef() const { 17261 return std::string(); 17262 } 17263 17264 void XmlReporter::writeSourceInfo( SourceLineInfo const& sourceInfo ) { 17265 m_xml 17266 .writeAttribute( "filename", sourceInfo.file ) 17267 .writeAttribute( "line", sourceInfo.line ); 17268 } 17269 17270 void XmlReporter::noMatchingTestCases( std::string const& s ) { 17271 StreamingReporterBase::noMatchingTestCases( s ); 17272 } 17273 17274 void XmlReporter::testRunStarting( TestRunInfo const& testInfo ) { 17275 StreamingReporterBase::testRunStarting( testInfo ); 17276 std::string stylesheetRef = getStylesheetRef(); 17277 if( !stylesheetRef.empty() ) 17278 m_xml.writeStylesheetRef( stylesheetRef ); 17279 m_xml.startElement( "Catch" ); 17280 if( !m_config->name().empty() ) 17281 m_xml.writeAttribute( "name", m_config->name() ); 17282 if (m_config->testSpec().hasFilters()) 17283 m_xml.writeAttribute( "filters", serializeFilters( m_config->getTestsOrTags() ) ); 17284 if( m_config->rngSeed() != 0 ) 17285 m_xml.scopedElement( "Randomness" ) 17286 .writeAttribute( "seed", m_config->rngSeed() ); 17287 } 17288 17289 void XmlReporter::testGroupStarting( GroupInfo const& groupInfo ) { 17290 StreamingReporterBase::testGroupStarting( groupInfo ); 17291 m_xml.startElement( "Group" ) 17292 .writeAttribute( "name", groupInfo.name ); 17293 } 17294 17295 void XmlReporter::testCaseStarting( TestCaseInfo const& testInfo ) { 17296 StreamingReporterBase::testCaseStarting(testInfo); 17297 m_xml.startElement( "TestCase" ) 17298 .writeAttribute( "name", trim( testInfo.name ) ) 17299 .writeAttribute( "description", testInfo.description ) 17300 .writeAttribute( "tags", testInfo.tagsAsString() ); 17301 17302 writeSourceInfo( testInfo.lineInfo ); 17303 17304 if ( m_config->showDurations() == ShowDurations::Always ) 17305 m_testCaseTimer.start(); 17306 m_xml.ensureTagClosed(); 17307 } 17308 17309 void XmlReporter::sectionStarting( SectionInfo const& sectionInfo ) { 17310 StreamingReporterBase::sectionStarting( sectionInfo ); 17311 if( m_sectionDepth++ > 0 ) { 17312 m_xml.startElement( "Section" ) 17313 .writeAttribute( "name", trim( sectionInfo.name ) ); 17314 writeSourceInfo( sectionInfo.lineInfo ); 17315 m_xml.ensureTagClosed(); 17316 } 17317 } 17318 17319 void XmlReporter::assertionStarting( AssertionInfo const& ) { } 17320 17321 bool XmlReporter::assertionEnded( AssertionStats const& assertionStats ) { 17322 17323 AssertionResult const& result = assertionStats.assertionResult; 17324 17325 bool includeResults = m_config->includeSuccessfulResults() || !result.isOk(); 17326 17327 if( includeResults || result.getResultType() == ResultWas::Warning ) { 17328 // Print any info messages in <Info> tags. 17329 for( auto const& msg : assertionStats.infoMessages ) { 17330 if( msg.type == ResultWas::Info && includeResults ) { 17331 m_xml.scopedElement( "Info" ) 17332 .writeText( msg.message ); 17333 } else if ( msg.type == ResultWas::Warning ) { 17334 m_xml.scopedElement( "Warning" ) 17335 .writeText( msg.message ); 17336 } 17337 } 17338 } 17339 17340 // Drop out if result was successful but we're not printing them. 17341 if( !includeResults && result.getResultType() != ResultWas::Warning ) 17342 return true; 17343 17344 // Print the expression if there is one. 17345 if( result.hasExpression() ) { 17346 m_xml.startElement( "Expression" ) 17347 .writeAttribute( "success", result.succeeded() ) 17348 .writeAttribute( "type", result.getTestMacroName() ); 17349 17350 writeSourceInfo( result.getSourceInfo() ); 17351 17352 m_xml.scopedElement( "Original" ) 17353 .writeText( result.getExpression() ); 17354 m_xml.scopedElement( "Expanded" ) 17355 .writeText( result.getExpandedExpression() ); 17356 } 17357 17358 // And... Print a result applicable to each result type. 17359 switch( result.getResultType() ) { 17360 case ResultWas::ThrewException: 17361 m_xml.startElement( "Exception" ); 17362 writeSourceInfo( result.getSourceInfo() ); 17363 m_xml.writeText( result.getMessage() ); 17364 m_xml.endElement(); 17365 break; 17366 case ResultWas::FatalErrorCondition: 17367 m_xml.startElement( "FatalErrorCondition" ); 17368 writeSourceInfo( result.getSourceInfo() ); 17369 m_xml.writeText( result.getMessage() ); 17370 m_xml.endElement(); 17371 break; 17372 case ResultWas::Info: 17373 m_xml.scopedElement( "Info" ) 17374 .writeText( result.getMessage() ); 17375 break; 17376 case ResultWas::Warning: 17377 // Warning will already have been written 17378 break; 17379 case ResultWas::ExplicitFailure: 17380 m_xml.startElement( "Failure" ); 17381 writeSourceInfo( result.getSourceInfo() ); 17382 m_xml.writeText( result.getMessage() ); 17383 m_xml.endElement(); 17384 break; 17385 default: 17386 break; 17387 } 17388 17389 if( result.hasExpression() ) 17390 m_xml.endElement(); 17391 17392 return true; 17393 } 17394 17395 void XmlReporter::sectionEnded( SectionStats const& sectionStats ) { 17396 StreamingReporterBase::sectionEnded( sectionStats ); 17397 if( --m_sectionDepth > 0 ) { 17398 XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" ); 17399 e.writeAttribute( "successes", sectionStats.assertions.passed ); 17400 e.writeAttribute( "failures", sectionStats.assertions.failed ); 17401 e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk ); 17402 17403 if ( m_config->showDurations() == ShowDurations::Always ) 17404 e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds ); 17405 17406 m_xml.endElement(); 17407 } 17408 } 17409 17410 void XmlReporter::testCaseEnded( TestCaseStats const& testCaseStats ) { 17411 StreamingReporterBase::testCaseEnded( testCaseStats ); 17412 XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" ); 17413 e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() ); 17414 17415 if ( m_config->showDurations() == ShowDurations::Always ) 17416 e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() ); 17417 17418 if( !testCaseStats.stdOut.empty() ) 17419 m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), XmlFormatting::Newline ); 17420 if( !testCaseStats.stdErr.empty() ) 17421 m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), XmlFormatting::Newline ); 17422 17423 m_xml.endElement(); 17424 } 17425 17426 void XmlReporter::testGroupEnded( TestGroupStats const& testGroupStats ) { 17427 StreamingReporterBase::testGroupEnded( testGroupStats ); 17428 // TODO: Check testGroupStats.aborting and act accordingly. 17429 m_xml.scopedElement( "OverallResults" ) 17430 .writeAttribute( "successes", testGroupStats.totals.assertions.passed ) 17431 .writeAttribute( "failures", testGroupStats.totals.assertions.failed ) 17432 .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk ); 17433 m_xml.scopedElement( "OverallResultsCases") 17434 .writeAttribute( "successes", testGroupStats.totals.testCases.passed ) 17435 .writeAttribute( "failures", testGroupStats.totals.testCases.failed ) 17436 .writeAttribute( "expectedFailures", testGroupStats.totals.testCases.failedButOk ); 17437 m_xml.endElement(); 17438 } 17439 17440 void XmlReporter::testRunEnded( TestRunStats const& testRunStats ) { 17441 StreamingReporterBase::testRunEnded( testRunStats ); 17442 m_xml.scopedElement( "OverallResults" ) 17443 .writeAttribute( "successes", testRunStats.totals.assertions.passed ) 17444 .writeAttribute( "failures", testRunStats.totals.assertions.failed ) 17445 .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk ); 17446 m_xml.scopedElement( "OverallResultsCases") 17447 .writeAttribute( "successes", testRunStats.totals.testCases.passed ) 17448 .writeAttribute( "failures", testRunStats.totals.testCases.failed ) 17449 .writeAttribute( "expectedFailures", testRunStats.totals.testCases.failedButOk ); 17450 m_xml.endElement(); 17451 } 17452 17453 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 17454 void XmlReporter::benchmarkPreparing(std::string const& name) { 17455 m_xml.startElement("BenchmarkResults") 17456 .writeAttribute("name", name); 17457 } 17458 17459 void XmlReporter::benchmarkStarting(BenchmarkInfo const &info) { 17460 m_xml.writeAttribute("samples", info.samples) 17461 .writeAttribute("resamples", info.resamples) 17462 .writeAttribute("iterations", info.iterations) 17463 .writeAttribute("clockResolution", info.clockResolution) 17464 .writeAttribute("estimatedDuration", info.estimatedDuration) 17465 .writeComment("All values in nano seconds"); 17466 } 17467 17468 void XmlReporter::benchmarkEnded(BenchmarkStats<> const& benchmarkStats) { 17469 m_xml.startElement("mean") 17470 .writeAttribute("value", benchmarkStats.mean.point.count()) 17471 .writeAttribute("lowerBound", benchmarkStats.mean.lower_bound.count()) 17472 .writeAttribute("upperBound", benchmarkStats.mean.upper_bound.count()) 17473 .writeAttribute("ci", benchmarkStats.mean.confidence_interval); 17474 m_xml.endElement(); 17475 m_xml.startElement("standardDeviation") 17476 .writeAttribute("value", benchmarkStats.standardDeviation.point.count()) 17477 .writeAttribute("lowerBound", benchmarkStats.standardDeviation.lower_bound.count()) 17478 .writeAttribute("upperBound", benchmarkStats.standardDeviation.upper_bound.count()) 17479 .writeAttribute("ci", benchmarkStats.standardDeviation.confidence_interval); 17480 m_xml.endElement(); 17481 m_xml.startElement("outliers") 17482 .writeAttribute("variance", benchmarkStats.outlierVariance) 17483 .writeAttribute("lowMild", benchmarkStats.outliers.low_mild) 17484 .writeAttribute("lowSevere", benchmarkStats.outliers.low_severe) 17485 .writeAttribute("highMild", benchmarkStats.outliers.high_mild) 17486 .writeAttribute("highSevere", benchmarkStats.outliers.high_severe); 17487 m_xml.endElement(); 17488 m_xml.endElement(); 17489 } 17490 17491 void XmlReporter::benchmarkFailed(std::string const &error) { 17492 m_xml.scopedElement("failed"). 17493 writeAttribute("message", error); 17494 m_xml.endElement(); 17495 } 17496 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 17497 17498 CATCH_REGISTER_REPORTER( "xml", XmlReporter ) 17499 17500 } // end namespace Catch 17501 17502 #if defined(_MSC_VER) 17503 #pragma warning(pop) 17504 #endif 17505 // end catch_reporter_xml.cpp 17506 17507 namespace Catch { 17508 LeakDetector leakDetector; 17509 } 17510 17511 #ifdef __clang__ 17512 #pragma clang diagnostic pop 17513 #endif 17514 17515 // end catch_impl.hpp 17516 #endif 17517 17518 #ifdef CATCH_CONFIG_MAIN 17519 // start catch_default_main.hpp 17520 17521 #ifndef __OBJC__ 17522 17523 #if defined(CATCH_CONFIG_WCHAR) && defined(CATCH_PLATFORM_WINDOWS) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN) 17524 // Standard C/C++ Win32 Unicode wmain entry point 17525 extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) { 17526 #else 17527 // Standard C/C++ main entry point 17528 int main (int argc, char * argv[]) { 17529 #endif 17530 17531 return Catch::Session().run( argc, argv ); 17532 } 17533 17534 #else // __OBJC__ 17535 17536 // Objective-C entry point 17537 int main (int argc, char * const argv[]) { 17538 #if !CATCH_ARC_ENABLED 17539 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 17540 #endif 17541 17542 Catch::registerTestMethods(); 17543 int result = Catch::Session().run( argc, (char**)argv ); 17544 17545 #if !CATCH_ARC_ENABLED 17546 [pool drain]; 17547 #endif 17548 17549 return result; 17550 } 17551 17552 #endif // __OBJC__ 17553 17554 // end catch_default_main.hpp 17555 #endif 17556 17557 #if !defined(CATCH_CONFIG_IMPL_ONLY) 17558 17559 #ifdef CLARA_CONFIG_MAIN_NOT_DEFINED 17560 # undef CLARA_CONFIG_MAIN 17561 #endif 17562 17563 #if !defined(CATCH_CONFIG_DISABLE) 17564 ////// 17565 // If this config identifier is defined then all CATCH macros are prefixed with CATCH_ 17566 #ifdef CATCH_CONFIG_PREFIX_ALL 17567 17568 #define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17569 #define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 17570 17571 #define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17572 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) 17573 #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) 17574 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17575 #define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) 17576 #endif// CATCH_CONFIG_DISABLE_MATCHERS 17577 #define CATCH_REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17578 17579 #define CATCH_CHECK( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17580 #define CATCH_CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 17581 #define CATCH_CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17582 #define CATCH_CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17583 #define CATCH_CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) 17584 17585 #define CATCH_CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17586 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) 17587 #define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 17588 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17589 #define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 17590 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17591 #define CATCH_CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17592 17593 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17594 #define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) 17595 17596 #define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) 17597 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17598 17599 #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) 17600 #define CATCH_UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "CATCH_UNSCOPED_INFO", msg ) 17601 #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) 17602 #define CATCH_CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CATCH_CAPTURE",__VA_ARGS__ ) 17603 17604 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) 17605 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17606 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) 17607 #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) 17608 #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) 17609 #define CATCH_DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ ) 17610 #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17611 #define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17612 #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17613 17614 #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE() 17615 17616 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 17617 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17618 #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) 17619 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17620 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) 17621 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) 17622 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) 17623 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17624 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) 17625 #else 17626 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) ) 17627 #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) ) 17628 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) 17629 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) ) 17630 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) ) 17631 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) ) 17632 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) 17633 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) ) 17634 #endif 17635 17636 #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE) 17637 #define CATCH_STATIC_REQUIRE( ... ) static_assert( __VA_ARGS__ , #__VA_ARGS__ ); CATCH_SUCCEED( #__VA_ARGS__ ) 17638 #define CATCH_STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); CATCH_SUCCEED( #__VA_ARGS__ ) 17639 #else 17640 #define CATCH_STATIC_REQUIRE( ... ) CATCH_REQUIRE( __VA_ARGS__ ) 17641 #define CATCH_STATIC_REQUIRE_FALSE( ... ) CATCH_REQUIRE_FALSE( __VA_ARGS__ ) 17642 #endif 17643 17644 // "BDD-style" convenience wrappers 17645 #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) 17646 #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) 17647 #define CATCH_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc ) 17648 #define CATCH_AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc ) 17649 #define CATCH_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc ) 17650 #define CATCH_AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc ) 17651 #define CATCH_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc ) 17652 #define CATCH_AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc ) 17653 17654 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 17655 #define CATCH_BENCHMARK(...) \ 17656 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__,,)) 17657 #define CATCH_BENCHMARK_ADVANCED(name) \ 17658 INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), name) 17659 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 17660 17661 // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required 17662 #else 17663 17664 #define REQUIRE( ... ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17665 #define REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 17666 17667 #define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17668 #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) 17669 #define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) 17670 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17671 #define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) 17672 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17673 #define REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17674 17675 #define CHECK( ... ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17676 #define CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 17677 #define CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17678 #define CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17679 #define CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) 17680 17681 #define CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17682 #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) 17683 #define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 17684 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17685 #define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 17686 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17687 #define CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17688 17689 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17690 #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) 17691 17692 #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) 17693 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17694 17695 #define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) 17696 #define UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "UNSCOPED_INFO", msg ) 17697 #define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) 17698 #define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE",__VA_ARGS__ ) 17699 17700 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) 17701 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17702 #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) 17703 #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) 17704 #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) 17705 #define DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ ) 17706 #define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17707 #define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17708 #define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17709 #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE() 17710 17711 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 17712 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17713 #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) 17714 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17715 #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) 17716 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) 17717 #define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) 17718 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17719 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) 17720 #define TEMPLATE_LIST_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(__VA_ARGS__) 17721 #define TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17722 #else 17723 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) ) 17724 #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) ) 17725 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) 17726 #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) ) 17727 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) ) 17728 #define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) ) 17729 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) 17730 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) ) 17731 #define TEMPLATE_LIST_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE( __VA_ARGS__ ) ) 17732 #define TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) 17733 #endif 17734 17735 #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE) 17736 #define STATIC_REQUIRE( ... ) static_assert( __VA_ARGS__, #__VA_ARGS__ ); SUCCEED( #__VA_ARGS__ ) 17737 #define STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); SUCCEED( "!(" #__VA_ARGS__ ")" ) 17738 #else 17739 #define STATIC_REQUIRE( ... ) REQUIRE( __VA_ARGS__ ) 17740 #define STATIC_REQUIRE_FALSE( ... ) REQUIRE_FALSE( __VA_ARGS__ ) 17741 #endif 17742 17743 #endif 17744 17745 #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) 17746 17747 // "BDD-style" convenience wrappers 17748 #define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) 17749 #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) 17750 17751 #define GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc ) 17752 #define AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc ) 17753 #define WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc ) 17754 #define AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc ) 17755 #define THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc ) 17756 #define AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc ) 17757 17758 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 17759 #define BENCHMARK(...) \ 17760 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__,,)) 17761 #define BENCHMARK_ADVANCED(name) \ 17762 INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), name) 17763 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 17764 17765 using Catch::Detail::Approx; 17766 17767 #else // CATCH_CONFIG_DISABLE 17768 17769 ////// 17770 // If this config identifier is defined then all CATCH macros are prefixed with CATCH_ 17771 #ifdef CATCH_CONFIG_PREFIX_ALL 17772 17773 #define CATCH_REQUIRE( ... ) (void)(0) 17774 #define CATCH_REQUIRE_FALSE( ... ) (void)(0) 17775 17776 #define CATCH_REQUIRE_THROWS( ... ) (void)(0) 17777 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0) 17778 #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) (void)(0) 17779 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17780 #define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) 17781 #endif// CATCH_CONFIG_DISABLE_MATCHERS 17782 #define CATCH_REQUIRE_NOTHROW( ... ) (void)(0) 17783 17784 #define CATCH_CHECK( ... ) (void)(0) 17785 #define CATCH_CHECK_FALSE( ... ) (void)(0) 17786 #define CATCH_CHECKED_IF( ... ) if (__VA_ARGS__) 17787 #define CATCH_CHECKED_ELSE( ... ) if (!(__VA_ARGS__)) 17788 #define CATCH_CHECK_NOFAIL( ... ) (void)(0) 17789 17790 #define CATCH_CHECK_THROWS( ... ) (void)(0) 17791 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) (void)(0) 17792 #define CATCH_CHECK_THROWS_WITH( expr, matcher ) (void)(0) 17793 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17794 #define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) 17795 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17796 #define CATCH_CHECK_NOTHROW( ... ) (void)(0) 17797 17798 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17799 #define CATCH_CHECK_THAT( arg, matcher ) (void)(0) 17800 17801 #define CATCH_REQUIRE_THAT( arg, matcher ) (void)(0) 17802 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17803 17804 #define CATCH_INFO( msg ) (void)(0) 17805 #define CATCH_UNSCOPED_INFO( msg ) (void)(0) 17806 #define CATCH_WARN( msg ) (void)(0) 17807 #define CATCH_CAPTURE( msg ) (void)(0) 17808 17809 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 17810 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 17811 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) 17812 #define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0) 17813 #define CATCH_SECTION( ... ) 17814 #define CATCH_DYNAMIC_SECTION( ... ) 17815 #define CATCH_FAIL( ... ) (void)(0) 17816 #define CATCH_FAIL_CHECK( ... ) (void)(0) 17817 #define CATCH_SUCCEED( ... ) (void)(0) 17818 17819 #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 17820 17821 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 17822 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) 17823 #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) 17824 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__) 17825 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) 17826 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17827 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17828 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17829 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17830 #else 17831 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) ) 17832 #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) ) 17833 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__ ) ) 17834 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) ) 17835 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17836 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17837 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17838 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17839 #endif 17840 17841 // "BDD-style" convenience wrappers 17842 #define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 17843 #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 ) 17844 #define CATCH_GIVEN( desc ) 17845 #define CATCH_AND_GIVEN( desc ) 17846 #define CATCH_WHEN( desc ) 17847 #define CATCH_AND_WHEN( desc ) 17848 #define CATCH_THEN( desc ) 17849 #define CATCH_AND_THEN( desc ) 17850 17851 #define CATCH_STATIC_REQUIRE( ... ) (void)(0) 17852 #define CATCH_STATIC_REQUIRE_FALSE( ... ) (void)(0) 17853 17854 // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required 17855 #else 17856 17857 #define REQUIRE( ... ) (void)(0) 17858 #define REQUIRE_FALSE( ... ) (void)(0) 17859 17860 #define REQUIRE_THROWS( ... ) (void)(0) 17861 #define REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0) 17862 #define REQUIRE_THROWS_WITH( expr, matcher ) (void)(0) 17863 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17864 #define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) 17865 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17866 #define REQUIRE_NOTHROW( ... ) (void)(0) 17867 17868 #define CHECK( ... ) (void)(0) 17869 #define CHECK_FALSE( ... ) (void)(0) 17870 #define CHECKED_IF( ... ) if (__VA_ARGS__) 17871 #define CHECKED_ELSE( ... ) if (!(__VA_ARGS__)) 17872 #define CHECK_NOFAIL( ... ) (void)(0) 17873 17874 #define CHECK_THROWS( ... ) (void)(0) 17875 #define CHECK_THROWS_AS( expr, exceptionType ) (void)(0) 17876 #define CHECK_THROWS_WITH( expr, matcher ) (void)(0) 17877 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17878 #define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) 17879 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17880 #define CHECK_NOTHROW( ... ) (void)(0) 17881 17882 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17883 #define CHECK_THAT( arg, matcher ) (void)(0) 17884 17885 #define REQUIRE_THAT( arg, matcher ) (void)(0) 17886 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17887 17888 #define INFO( msg ) (void)(0) 17889 #define UNSCOPED_INFO( msg ) (void)(0) 17890 #define WARN( msg ) (void)(0) 17891 #define CAPTURE( msg ) (void)(0) 17892 17893 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 17894 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 17895 #define METHOD_AS_TEST_CASE( method, ... ) 17896 #define REGISTER_TEST_CASE( Function, ... ) (void)(0) 17897 #define SECTION( ... ) 17898 #define DYNAMIC_SECTION( ... ) 17899 #define FAIL( ... ) (void)(0) 17900 #define FAIL_CHECK( ... ) (void)(0) 17901 #define SUCCEED( ... ) (void)(0) 17902 #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 17903 17904 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 17905 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) 17906 #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) 17907 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__) 17908 #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) 17909 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17910 #define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17911 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17912 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17913 #else 17914 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) ) 17915 #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) ) 17916 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__ ) ) 17917 #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) ) 17918 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17919 #define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17920 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17921 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17922 #endif 17923 17924 #define STATIC_REQUIRE( ... ) (void)(0) 17925 #define STATIC_REQUIRE_FALSE( ... ) (void)(0) 17926 17927 #endif 17928 17929 #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) 17930 17931 // "BDD-style" convenience wrappers 17932 #define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) ) 17933 #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className ) 17934 17935 #define GIVEN( desc ) 17936 #define AND_GIVEN( desc ) 17937 #define WHEN( desc ) 17938 #define AND_WHEN( desc ) 17939 #define THEN( desc ) 17940 #define AND_THEN( desc ) 17941 17942 using Catch::Detail::Approx; 17943 17944 #endif 17945 17946 #endif // ! CATCH_CONFIG_IMPL_ONLY 17947 17948 // start catch_reenable_warnings.h 17949 17950 17951 #ifdef __clang__ 17952 # ifdef __ICC // icpc defines the __clang__ macro 17953 # pragma warning(pop) 17954 # else 17955 # pragma clang diagnostic pop 17956 # endif 17957 #elif defined __GNUC__ 17958 # pragma GCC diagnostic pop 17959 #endif 17960 17961 // end catch_reenable_warnings.h 17962 // end catch.hpp 17963 #endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED 17964