File indexing completed on 2024-09-15 04:23:19
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::