catch.hpp (650013B)
1 /* 2 * Catch v2.13.0 3 * Generated: 2020-07-12 20:07:49.015950 4 * ---------------------------------------------------------- 5 * This file has been merged from multiple headers. Please don't edit it directly 6 * Copyright (c) 2020 Two Blue Cubes Ltd. All rights reserved. 7 * 8 * Distributed under the Boost Software License, Version 1.0. (See accompanying 9 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 10 */ 11 #ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED 12 #define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED 13 // start catch.hpp 14 15 16 #define CATCH_VERSION_MAJOR 2 17 #define CATCH_VERSION_MINOR 13 18 #define CATCH_VERSION_PATCH 0 19 20 #ifdef __clang__ 21 # pragma clang system_header 22 #elif defined __GNUC__ 23 # pragma GCC system_header 24 #endif 25 26 // start catch_suppress_warnings.h 27 28 #ifdef __clang__ 29 # ifdef __ICC // icpc defines the __clang__ macro 30 # pragma warning(push) 31 # pragma warning(disable: 161 1682) 32 # else // __ICC 33 # pragma clang diagnostic push 34 # pragma clang diagnostic ignored "-Wpadded" 35 # pragma clang diagnostic ignored "-Wswitch-enum" 36 # pragma clang diagnostic ignored "-Wcovered-switch-default" 37 # endif 38 #elif defined __GNUC__ 39 // Because REQUIREs trigger GCC's -Wparentheses, and because still 40 // supported version of g++ have only buggy support for _Pragmas, 41 // Wparentheses have to be suppressed globally. 42 # pragma GCC diagnostic ignored "-Wparentheses" // See #674 for details 43 44 # pragma GCC diagnostic push 45 # pragma GCC diagnostic ignored "-Wunused-variable" 46 # pragma GCC diagnostic ignored "-Wpadded" 47 #endif 48 // end catch_suppress_warnings.h 49 #if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) 50 # define CATCH_IMPL 51 # define CATCH_CONFIG_ALL_PARTS 52 #endif 53 54 // In the impl file, we want to have access to all parts of the headers 55 // Can also be used to sanely support PCHs 56 #if defined(CATCH_CONFIG_ALL_PARTS) 57 # define CATCH_CONFIG_EXTERNAL_INTERFACES 58 # if defined(CATCH_CONFIG_DISABLE_MATCHERS) 59 # undef CATCH_CONFIG_DISABLE_MATCHERS 60 # endif 61 # if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) 62 # define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER 63 # endif 64 #endif 65 66 #if !defined(CATCH_CONFIG_IMPL_ONLY) 67 // start catch_platform.h 68 69 #ifdef __APPLE__ 70 # include <TargetConditionals.h> 71 # if TARGET_OS_OSX == 1 72 # define CATCH_PLATFORM_MAC 73 # elif TARGET_OS_IPHONE == 1 74 # define CATCH_PLATFORM_IPHONE 75 # endif 76 77 #elif defined(linux) || defined(__linux) || defined(__linux__) 78 # define CATCH_PLATFORM_LINUX 79 80 #elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__) 81 # define CATCH_PLATFORM_WINDOWS 82 #endif 83 84 // end catch_platform.h 85 86 #ifdef CATCH_IMPL 87 # ifndef CLARA_CONFIG_MAIN 88 # define CLARA_CONFIG_MAIN_NOT_DEFINED 89 # define CLARA_CONFIG_MAIN 90 # endif 91 #endif 92 93 // start catch_user_interfaces.h 94 95 namespace Catch { 96 unsigned int rngSeed(); 97 } 98 99 // end catch_user_interfaces.h 100 // start catch_tag_alias_autoregistrar.h 101 102 // start catch_common.h 103 104 // start catch_compiler_capabilities.h 105 106 // Detect a number of compiler features - by compiler 107 // The following features are defined: 108 // 109 // CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? 110 // CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported? 111 // CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported? 112 // CATCH_CONFIG_DISABLE_EXCEPTIONS : Are exceptions enabled? 113 // **************** 114 // Note to maintainers: if new toggles are added please document them 115 // in configuration.md, too 116 // **************** 117 118 // In general each macro has a _NO_<feature name> form 119 // (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature. 120 // Many features, at point of detection, define an _INTERNAL_ macro, so they 121 // can be combined, en-mass, with the _NO_ forms later. 122 123 #ifdef __cplusplus 124 125 # if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L) 126 # define CATCH_CPP14_OR_GREATER 127 # endif 128 129 # if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) 130 # define CATCH_CPP17_OR_GREATER 131 # endif 132 133 #endif 134 135 #if defined(__cpp_lib_uncaught_exceptions) 136 # define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS 137 #endif 138 139 // We have to avoid both ICC and Clang, because they try to mask themselves 140 // as gcc, and we want only GCC in this block 141 #if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) 142 # define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" ) 143 # define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" ) 144 145 # define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) 146 147 #endif 148 149 #if defined(__clang__) 150 151 # define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" ) 152 # define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic pop" ) 153 154 // As of this writing, IBM XL's implementation of __builtin_constant_p has a bug 155 // which results in calls to destructors being emitted for each temporary, 156 // without a matching initialization. In practice, this can result in something 157 // like `std::string::~string` being called on an uninitialized value. 158 // 159 // For example, this code will likely segfault under IBM XL: 160 // ``` 161 // REQUIRE(std::string("12") + "34" == "1234") 162 // ``` 163 // 164 // Therefore, `CATCH_INTERNAL_IGNORE_BUT_WARN` is not implemented. 165 # if !defined(__ibmxl__) 166 # define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) /* NOLINT(cppcoreguidelines-pro-type-vararg, hicpp-vararg) */ 167 # endif 168 169 # define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 170 _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ 171 _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") 172 173 # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ 174 _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) 175 176 # define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ 177 _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" ) 178 179 # define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ 180 _Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" ) 181 182 # define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 183 _Pragma( "clang diagnostic ignored \"-Wunused-template\"" ) 184 185 #endif // __clang__ 186 187 //////////////////////////////////////////////////////////////////////////////// 188 // Assume that non-Windows platforms support posix signals by default 189 #if !defined(CATCH_PLATFORM_WINDOWS) 190 #define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS 191 #endif 192 193 //////////////////////////////////////////////////////////////////////////////// 194 // We know some environments not to support full POSIX signals 195 #if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__) 196 #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS 197 #endif 198 199 #ifdef __OS400__ 200 # define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS 201 # define CATCH_CONFIG_COLOUR_NONE 202 #endif 203 204 //////////////////////////////////////////////////////////////////////////////// 205 // Android somehow still does not support std::to_string 206 #if defined(__ANDROID__) 207 # define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING 208 # define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE 209 #endif 210 211 //////////////////////////////////////////////////////////////////////////////// 212 // Not all Windows environments support SEH properly 213 #if defined(__MINGW32__) 214 # define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH 215 #endif 216 217 //////////////////////////////////////////////////////////////////////////////// 218 // PS4 219 #if defined(__ORBIS__) 220 # define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE 221 #endif 222 223 //////////////////////////////////////////////////////////////////////////////// 224 // Cygwin 225 #ifdef __CYGWIN__ 226 227 // Required for some versions of Cygwin to declare gettimeofday 228 // see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin 229 # define _BSD_SOURCE 230 // some versions of cygwin (most) do not support std::to_string. Use the libstd check. 231 // https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813 232 # if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \ 233 && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF)) 234 235 # define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING 236 237 # endif 238 #endif // __CYGWIN__ 239 240 //////////////////////////////////////////////////////////////////////////////// 241 // Visual C++ 242 #if defined(_MSC_VER) 243 244 # define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) ) 245 # define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) ) 246 247 # if _MSC_VER >= 1900 // Visual Studio 2015 or newer 248 # define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS 249 # endif 250 251 // Universal Windows platform does not support SEH 252 // Or console colours (or console at all...) 253 # if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) 254 # define CATCH_CONFIG_COLOUR_NONE 255 # else 256 # define CATCH_INTERNAL_CONFIG_WINDOWS_SEH 257 # endif 258 259 // MSVC traditional preprocessor needs some workaround for __VA_ARGS__ 260 // _MSVC_TRADITIONAL == 0 means new conformant preprocessor 261 // _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor 262 # if !defined(__clang__) // Handle Clang masquerading for msvc 263 # if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) 264 # define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 265 # endif // MSVC_TRADITIONAL 266 # endif // __clang__ 267 268 #endif // _MSC_VER 269 270 #if defined(_REENTRANT) || defined(_MSC_VER) 271 // Enable async processing, as -pthread is specified or no additional linking is required 272 # define CATCH_INTERNAL_CONFIG_USE_ASYNC 273 #endif // _MSC_VER 274 275 //////////////////////////////////////////////////////////////////////////////// 276 // Check if we are compiled with -fno-exceptions or equivalent 277 #if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND) 278 # define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED 279 #endif 280 281 //////////////////////////////////////////////////////////////////////////////// 282 // DJGPP 283 #ifdef __DJGPP__ 284 # define CATCH_INTERNAL_CONFIG_NO_WCHAR 285 #endif // __DJGPP__ 286 287 //////////////////////////////////////////////////////////////////////////////// 288 // Embarcadero C++Build 289 #if defined(__BORLANDC__) 290 #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN 291 #endif 292 293 //////////////////////////////////////////////////////////////////////////////// 294 295 // Use of __COUNTER__ is suppressed during code analysis in 296 // CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly 297 // handled by it. 298 // Otherwise all supported compilers support COUNTER macro, 299 // but user still might want to turn it off 300 #if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L ) 301 #define CATCH_INTERNAL_CONFIG_COUNTER 302 #endif 303 304 //////////////////////////////////////////////////////////////////////////////// 305 306 // RTX is a special version of Windows that is real time. 307 // This means that it is detected as Windows, but does not provide 308 // the same set of capabilities as real Windows does. 309 #if defined(UNDER_RTSS) || defined(RTX64_BUILD) 310 #define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH 311 #define CATCH_INTERNAL_CONFIG_NO_ASYNC 312 #define CATCH_CONFIG_COLOUR_NONE 313 #endif 314 315 #if !defined(_GLIBCXX_USE_C99_MATH_TR1) 316 #define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER 317 #endif 318 319 // Various stdlib support checks that require __has_include 320 #if defined(__has_include) 321 // Check if string_view is available and usable 322 #if __has_include(<string_view>) && defined(CATCH_CPP17_OR_GREATER) 323 # define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW 324 #endif 325 326 // Check if optional is available and usable 327 # if __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER) 328 # define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL 329 # endif // __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER) 330 331 // Check if byte is available and usable 332 # if __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER) 333 # define CATCH_INTERNAL_CONFIG_CPP17_BYTE 334 # endif // __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER) 335 336 // Check if variant is available and usable 337 # if __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER) 338 # if defined(__clang__) && (__clang_major__ < 8) 339 // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852 340 // fix should be in clang 8, workaround in libstdc++ 8.2 341 # include <ciso646> 342 # if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) 343 # define CATCH_CONFIG_NO_CPP17_VARIANT 344 # else 345 # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT 346 # endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) 347 # else 348 # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT 349 # endif // defined(__clang__) && (__clang_major__ < 8) 350 # endif // __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER) 351 #endif // defined(__has_include) 352 353 #if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) 354 # define CATCH_CONFIG_COUNTER 355 #endif 356 #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) 357 # define CATCH_CONFIG_WINDOWS_SEH 358 #endif 359 // This is set by default, because we assume that unix compilers are posix-signal-compatible by default. 360 #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) 361 # define CATCH_CONFIG_POSIX_SIGNALS 362 #endif 363 // This is set by default, because we assume that compilers with no wchar_t support are just rare exceptions. 364 #if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR) 365 # define CATCH_CONFIG_WCHAR 366 #endif 367 368 #if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING) 369 # define CATCH_CONFIG_CPP11_TO_STRING 370 #endif 371 372 #if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL) 373 # define CATCH_CONFIG_CPP17_OPTIONAL 374 #endif 375 376 #if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) 377 # define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS 378 #endif 379 380 #if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW) 381 # define CATCH_CONFIG_CPP17_STRING_VIEW 382 #endif 383 384 #if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT) 385 # define CATCH_CONFIG_CPP17_VARIANT 386 #endif 387 388 #if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && !defined(CATCH_CONFIG_NO_CPP17_BYTE) && !defined(CATCH_CONFIG_CPP17_BYTE) 389 # define CATCH_CONFIG_CPP17_BYTE 390 #endif 391 392 #if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) 393 # define CATCH_INTERNAL_CONFIG_NEW_CAPTURE 394 #endif 395 396 #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) 397 # define CATCH_CONFIG_NEW_CAPTURE 398 #endif 399 400 #if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 401 # define CATCH_CONFIG_DISABLE_EXCEPTIONS 402 #endif 403 404 #if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN) 405 # define CATCH_CONFIG_POLYFILL_ISNAN 406 #endif 407 408 #if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC) 409 # define CATCH_CONFIG_USE_ASYNC 410 #endif 411 412 #if defined(CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_NO_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_ANDROID_LOGWRITE) 413 # define CATCH_CONFIG_ANDROID_LOGWRITE 414 #endif 415 416 #if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER) 417 # define CATCH_CONFIG_GLOBAL_NEXTAFTER 418 #endif 419 420 // Even if we do not think the compiler has that warning, we still have 421 // to provide a macro that can be used by the code. 422 #if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION) 423 # define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION 424 #endif 425 #if !defined(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION) 426 # define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 427 #endif 428 #if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) 429 # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS 430 #endif 431 #if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS) 432 # define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS 433 #endif 434 #if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS) 435 # define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS 436 #endif 437 #if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS) 438 # define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS 439 #endif 440 441 // The goal of this macro is to avoid evaluation of the arguments, but 442 // still have the compiler warn on problems inside... 443 #if !defined(CATCH_INTERNAL_IGNORE_BUT_WARN) 444 # define CATCH_INTERNAL_IGNORE_BUT_WARN(...) 445 #endif 446 447 #if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10) 448 # undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS 449 #elif defined(__clang__) && (__clang_major__ < 5) 450 # undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS 451 #endif 452 453 #if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS) 454 # define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS 455 #endif 456 457 #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 458 #define CATCH_TRY if ((true)) 459 #define CATCH_CATCH_ALL if ((false)) 460 #define CATCH_CATCH_ANON(type) if ((false)) 461 #else 462 #define CATCH_TRY try 463 #define CATCH_CATCH_ALL catch (...) 464 #define CATCH_CATCH_ANON(type) catch (type) 465 #endif 466 467 #if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) 468 #define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 469 #endif 470 471 // end catch_compiler_capabilities.h 472 #define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line 473 #define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) 474 #ifdef CATCH_CONFIG_COUNTER 475 # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) 476 #else 477 # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) 478 #endif 479 480 #include <iosfwd> 481 #include <string> 482 #include <cstdint> 483 484 // We need a dummy global operator<< so we can bring it into Catch namespace later 485 struct Catch_global_namespace_dummy {}; 486 std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy); 487 488 namespace Catch { 489 490 struct CaseSensitive { enum Choice { 491 Yes, 492 No 493 }; }; 494 495 class NonCopyable { 496 NonCopyable( NonCopyable const& ) = delete; 497 NonCopyable( NonCopyable && ) = delete; 498 NonCopyable& operator = ( NonCopyable const& ) = delete; 499 NonCopyable& operator = ( NonCopyable && ) = delete; 500 501 protected: 502 NonCopyable(); 503 virtual ~NonCopyable(); 504 }; 505 506 struct SourceLineInfo { 507 508 SourceLineInfo() = delete; 509 SourceLineInfo( char const* _file, std::size_t _line ) noexcept 510 : file( _file ), 511 line( _line ) 512 {} 513 514 SourceLineInfo( SourceLineInfo const& other ) = default; 515 SourceLineInfo& operator = ( SourceLineInfo const& ) = default; 516 SourceLineInfo( SourceLineInfo&& ) noexcept = default; 517 SourceLineInfo& operator = ( SourceLineInfo&& ) noexcept = default; 518 519 bool empty() const noexcept { return file[0] == '\0'; } 520 bool operator == ( SourceLineInfo const& other ) const noexcept; 521 bool operator < ( SourceLineInfo const& other ) const noexcept; 522 523 char const* file; 524 std::size_t line; 525 }; 526 527 std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); 528 529 // Bring in operator<< from global namespace into Catch namespace 530 // This is necessary because the overload of operator<< above makes 531 // lookup stop at namespace Catch 532 using ::operator<<; 533 534 // Use this in variadic streaming macros to allow 535 // >> +StreamEndStop 536 // as well as 537 // >> stuff +StreamEndStop 538 struct StreamEndStop { 539 std::string operator+() const; 540 }; 541 template<typename T> 542 T const& operator + ( T const& value, StreamEndStop ) { 543 return value; 544 } 545 } 546 547 #define CATCH_INTERNAL_LINEINFO \ 548 ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) ) 549 550 // end catch_common.h 551 namespace Catch { 552 553 struct RegistrarForTagAliases { 554 RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); 555 }; 556 557 } // end namespace Catch 558 559 #define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \ 560 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 561 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 562 namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \ 563 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 564 565 // end catch_tag_alias_autoregistrar.h 566 // start catch_test_registry.h 567 568 // start catch_interfaces_testcase.h 569 570 #include <vector> 571 572 namespace Catch { 573 574 class TestSpec; 575 576 struct ITestInvoker { 577 virtual void invoke () const = 0; 578 virtual ~ITestInvoker(); 579 }; 580 581 class TestCase; 582 struct IConfig; 583 584 struct ITestCaseRegistry { 585 virtual ~ITestCaseRegistry(); 586 virtual std::vector<TestCase> const& getAllTests() const = 0; 587 virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const = 0; 588 }; 589 590 bool isThrowSafe( TestCase const& testCase, IConfig const& config ); 591 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); 592 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ); 593 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ); 594 595 } 596 597 // end catch_interfaces_testcase.h 598 // start catch_stringref.h 599 600 #include <cstddef> 601 #include <string> 602 #include <iosfwd> 603 #include <cassert> 604 605 namespace Catch { 606 607 /// A non-owning string class (similar to the forthcoming std::string_view) 608 /// Note that, because a StringRef may be a substring of another string, 609 /// it may not be null terminated. 610 class StringRef { 611 public: 612 using size_type = std::size_t; 613 using const_iterator = const char*; 614 615 private: 616 static constexpr char const* const s_empty = ""; 617 618 char const* m_start = s_empty; 619 size_type m_size = 0; 620 621 public: // construction 622 constexpr StringRef() noexcept = default; 623 624 StringRef( char const* rawChars ) noexcept; 625 626 constexpr StringRef( char const* rawChars, size_type size ) noexcept 627 : m_start( rawChars ), 628 m_size( size ) 629 {} 630 631 StringRef( std::string const& stdString ) noexcept 632 : m_start( stdString.c_str() ), 633 m_size( stdString.size() ) 634 {} 635 636 explicit operator std::string() const { 637 return std::string(m_start, m_size); 638 } 639 640 public: // operators 641 auto operator == ( StringRef const& other ) const noexcept -> bool; 642 auto operator != (StringRef const& other) const noexcept -> bool { 643 return !(*this == other); 644 } 645 646 auto operator[] ( size_type index ) const noexcept -> char { 647 assert(index < m_size); 648 return m_start[index]; 649 } 650 651 public: // named queries 652 constexpr auto empty() const noexcept -> bool { 653 return m_size == 0; 654 } 655 constexpr auto size() const noexcept -> size_type { 656 return m_size; 657 } 658 659 // Returns the current start pointer. If the StringRef is not 660 // null-terminated, throws std::domain_exception 661 auto c_str() const -> char const*; 662 663 public: // substrings and searches 664 // Returns a substring of [start, start + length). 665 // If start + length > size(), then the substring is [start, size()). 666 // If start > size(), then the substring is empty. 667 auto substr( size_type start, size_type length ) const noexcept -> StringRef; 668 669 // Returns the current start pointer. May not be null-terminated. 670 auto data() const noexcept -> char const*; 671 672 constexpr auto isNullTerminated() const noexcept -> bool { 673 return m_start[m_size] == '\0'; 674 } 675 676 public: // iterators 677 constexpr const_iterator begin() const { return m_start; } 678 constexpr const_iterator end() const { return m_start + m_size; } 679 }; 680 681 auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&; 682 auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&; 683 684 constexpr auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef { 685 return StringRef( rawChars, size ); 686 } 687 } // namespace Catch 688 689 constexpr auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef { 690 return Catch::StringRef( rawChars, size ); 691 } 692 693 // end catch_stringref.h 694 // start catch_preprocessor.hpp 695 696 697 #define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__ 698 #define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__))) 699 #define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__))) 700 #define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__))) 701 #define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__))) 702 #define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__))) 703 704 #ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 705 #define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__ 706 // MSVC needs more evaluations 707 #define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__))) 708 #define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__)) 709 #else 710 #define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL5(__VA_ARGS__) 711 #endif 712 713 #define CATCH_REC_END(...) 714 #define CATCH_REC_OUT 715 716 #define CATCH_EMPTY() 717 #define CATCH_DEFER(id) id CATCH_EMPTY() 718 719 #define CATCH_REC_GET_END2() 0, CATCH_REC_END 720 #define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2 721 #define CATCH_REC_GET_END(...) CATCH_REC_GET_END1 722 #define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT 723 #define CATCH_REC_NEXT1(test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0) 724 #define CATCH_REC_NEXT(test, next) CATCH_REC_NEXT1(CATCH_REC_GET_END test, next) 725 726 #define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) 727 #define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ ) 728 #define CATCH_REC_LIST2(f, x, peek, ...) f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) 729 730 #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__ ) 731 #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__ ) 732 #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__ ) 733 734 // Applies the function macro `f` to each of the remaining parameters, inserts commas between the results, 735 // and passes userdata as the first parameter to each invocation, 736 // e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c) 737 #define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) 738 739 #define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) 740 741 #define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param) 742 #define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__ 743 #define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__ 744 #define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF 745 #define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__) 746 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 747 #define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__ 748 #define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) 749 #else 750 // MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF 751 #define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__) 752 #define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__ 753 #define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1) 754 #endif 755 756 #define INTERNAL_CATCH_MAKE_NAMESPACE2(...) ns_##__VA_ARGS__ 757 #define INTERNAL_CATCH_MAKE_NAMESPACE(name) INTERNAL_CATCH_MAKE_NAMESPACE2(name) 758 759 #define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__) 760 761 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 762 #define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS_GEN(__VA_ARGS__)>()) 763 #define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)) 764 #else 765 #define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) INTERNAL_CATCH_EXPAND_VARGS(decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS_GEN(__VA_ARGS__)>())) 766 #define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))) 767 #endif 768 769 #define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(...)\ 770 CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,__VA_ARGS__) 771 772 #define INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_0) INTERNAL_CATCH_REMOVE_PARENS(_0) 773 #define INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_0, _1) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_1) 774 #define INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_0, _1, _2) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_1, _2) 775 #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) 776 #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) 777 #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) 778 #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) 779 #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) 780 #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) 781 #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) 782 #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) 783 784 #define INTERNAL_CATCH_VA_NARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N 785 786 #define INTERNAL_CATCH_TYPE_GEN\ 787 template<typename...> struct TypeList {};\ 788 template<typename...Ts>\ 789 constexpr auto get_wrapper() noexcept -> TypeList<Ts...> { return {}; }\ 790 template<template<typename...> class...> struct TemplateTypeList{};\ 791 template<template<typename...> class...Cs>\ 792 constexpr auto get_wrapper() noexcept -> TemplateTypeList<Cs...> { return {}; }\ 793 template<typename...>\ 794 struct append;\ 795 template<typename...>\ 796 struct rewrap;\ 797 template<template<typename...> class, typename...>\ 798 struct create;\ 799 template<template<typename...> class, typename>\ 800 struct convert;\ 801 \ 802 template<typename T> \ 803 struct append<T> { using type = T; };\ 804 template< template<typename...> class L1, typename...E1, template<typename...> class L2, typename...E2, typename...Rest>\ 805 struct append<L1<E1...>, L2<E2...>, Rest...> { using type = typename append<L1<E1...,E2...>, Rest...>::type; };\ 806 template< template<typename...> class L1, typename...E1, typename...Rest>\ 807 struct append<L1<E1...>, TypeList<mpl_::na>, Rest...> { using type = L1<E1...>; };\ 808 \ 809 template< template<typename...> class Container, template<typename...> class List, typename...elems>\ 810 struct rewrap<TemplateTypeList<Container>, List<elems...>> { using type = TypeList<Container<elems...>>; };\ 811 template< template<typename...> class Container, template<typename...> class List, class...Elems, typename...Elements>\ 812 struct rewrap<TemplateTypeList<Container>, List<Elems...>, Elements...> { using type = typename append<TypeList<Container<Elems...>>, typename rewrap<TemplateTypeList<Container>, Elements...>::type>::type; };\ 813 \ 814 template<template <typename...> class Final, template< typename...> class...Containers, typename...Types>\ 815 struct create<Final, TemplateTypeList<Containers...>, TypeList<Types...>> { using type = typename append<Final<>, typename rewrap<TemplateTypeList<Containers>, Types...>::type...>::type; };\ 816 template<template <typename...> class Final, template <typename...> class List, typename...Ts>\ 817 struct convert<Final, List<Ts...>> { using type = typename append<Final<>,TypeList<Ts>...>::type; }; 818 819 #define INTERNAL_CATCH_NTTP_1(signature, ...)\ 820 template<INTERNAL_CATCH_REMOVE_PARENS(signature)> struct Nttp{};\ 821 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 822 constexpr auto get_wrapper() noexcept -> Nttp<__VA_ARGS__> { return {}; } \ 823 template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...> struct NttpTemplateTypeList{};\ 824 template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...Cs>\ 825 constexpr auto get_wrapper() noexcept -> NttpTemplateTypeList<Cs...> { return {}; } \ 826 \ 827 template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 828 struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>> { using type = TypeList<Container<__VA_ARGS__>>; };\ 829 template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature), typename...Elements>\ 830 struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>, Elements...> { using type = typename append<TypeList<Container<__VA_ARGS__>>, typename rewrap<NttpTemplateTypeList<Container>, Elements...>::type>::type; };\ 831 template<template <typename...> class Final, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...Containers, typename...Types>\ 832 struct create<Final, NttpTemplateTypeList<Containers...>, TypeList<Types...>> { using type = typename append<Final<>, typename rewrap<NttpTemplateTypeList<Containers>, Types...>::type...>::type; }; 833 834 #define INTERNAL_CATCH_DECLARE_SIG_TEST0(TestName) 835 #define INTERNAL_CATCH_DECLARE_SIG_TEST1(TestName, signature)\ 836 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 837 static void TestName() 838 #define INTERNAL_CATCH_DECLARE_SIG_TEST_X(TestName, signature, ...)\ 839 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 840 static void TestName() 841 842 #define INTERNAL_CATCH_DEFINE_SIG_TEST0(TestName) 843 #define INTERNAL_CATCH_DEFINE_SIG_TEST1(TestName, signature)\ 844 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 845 static void TestName() 846 #define INTERNAL_CATCH_DEFINE_SIG_TEST_X(TestName, signature,...)\ 847 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 848 static void TestName() 849 850 #define INTERNAL_CATCH_NTTP_REGISTER0(TestFunc, signature)\ 851 template<typename Type>\ 852 void reg_test(TypeList<Type>, Catch::NameAndTags nameAndTags)\ 853 {\ 854 Catch::AutoReg( Catch::makeTestInvoker(&TestFunc<Type>), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), nameAndTags);\ 855 } 856 857 #define INTERNAL_CATCH_NTTP_REGISTER(TestFunc, signature, ...)\ 858 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 859 void reg_test(Nttp<__VA_ARGS__>, Catch::NameAndTags nameAndTags)\ 860 {\ 861 Catch::AutoReg( Catch::makeTestInvoker(&TestFunc<__VA_ARGS__>), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), nameAndTags);\ 862 } 863 864 #define INTERNAL_CATCH_NTTP_REGISTER_METHOD0(TestName, signature, ...)\ 865 template<typename Type>\ 866 void reg_test(TypeList<Type>, Catch::StringRef className, Catch::NameAndTags nameAndTags)\ 867 {\ 868 Catch::AutoReg( Catch::makeTestInvoker(&TestName<Type>::test), CATCH_INTERNAL_LINEINFO, className, nameAndTags);\ 869 } 870 871 #define INTERNAL_CATCH_NTTP_REGISTER_METHOD(TestName, signature, ...)\ 872 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 873 void reg_test(Nttp<__VA_ARGS__>, Catch::StringRef className, Catch::NameAndTags nameAndTags)\ 874 {\ 875 Catch::AutoReg( Catch::makeTestInvoker(&TestName<__VA_ARGS__>::test), CATCH_INTERNAL_LINEINFO, className, nameAndTags);\ 876 } 877 878 #define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0(TestName, ClassName) 879 #define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1(TestName, ClassName, signature)\ 880 template<typename TestType> \ 881 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName)<TestType> { \ 882 void test();\ 883 } 884 885 #define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X(TestName, ClassName, signature, ...)\ 886 template<INTERNAL_CATCH_REMOVE_PARENS(signature)> \ 887 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName)<__VA_ARGS__> { \ 888 void test();\ 889 } 890 891 #define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0(TestName) 892 #define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1(TestName, signature)\ 893 template<typename TestType> \ 894 void INTERNAL_CATCH_MAKE_NAMESPACE(TestName)::TestName<TestType>::test() 895 #define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X(TestName, signature, ...)\ 896 template<INTERNAL_CATCH_REMOVE_PARENS(signature)> \ 897 void INTERNAL_CATCH_MAKE_NAMESPACE(TestName)::TestName<__VA_ARGS__>::test() 898 899 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 900 #define INTERNAL_CATCH_NTTP_0 901 #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) 902 #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__) 903 #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__) 904 #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__) 905 #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__) 906 #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__) 907 #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__) 908 #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__) 909 #else 910 #define INTERNAL_CATCH_NTTP_0(signature) 911 #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__)) 912 #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__)) 913 #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__)) 914 #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__)) 915 #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__)) 916 #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__)) 917 #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__)) 918 #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__)) 919 #endif 920 921 // end catch_preprocessor.hpp 922 // start catch_meta.hpp 923 924 925 #include <type_traits> 926 927 namespace Catch { 928 template<typename T> 929 struct always_false : std::false_type {}; 930 931 template <typename> struct true_given : std::true_type {}; 932 struct is_callable_tester { 933 template <typename Fun, typename... Args> 934 true_given<decltype(std::declval<Fun>()(std::declval<Args>()...))> static test(int); 935 template <typename...> 936 std::false_type static test(...); 937 }; 938 939 template <typename T> 940 struct is_callable; 941 942 template <typename Fun, typename... Args> 943 struct is_callable<Fun(Args...)> : decltype(is_callable_tester::test<Fun, Args...>(0)) {}; 944 945 #if defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703 946 // std::result_of is deprecated in C++17 and removed in C++20. Hence, it is 947 // replaced with std::invoke_result here. 948 template <typename Func, typename... U> 949 using FunctionReturnType = std::remove_reference_t<std::remove_cv_t<std::invoke_result_t<Func, U...>>>; 950 #else 951 // Keep ::type here because we still support C++11 952 template <typename Func, typename... U> 953 using FunctionReturnType = typename std::remove_reference<typename std::remove_cv<typename std::result_of<Func(U...)>::type>::type>::type; 954 #endif 955 956 } // namespace Catch 957 958 namespace mpl_{ 959 struct na; 960 } 961 962 // end catch_meta.hpp 963 namespace Catch { 964 965 template<typename C> 966 class TestInvokerAsMethod : public ITestInvoker { 967 void (C::*m_testAsMethod)(); 968 public: 969 TestInvokerAsMethod( void (C::*testAsMethod)() ) noexcept : m_testAsMethod( testAsMethod ) {} 970 971 void invoke() const override { 972 C obj; 973 (obj.*m_testAsMethod)(); 974 } 975 }; 976 977 auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker*; 978 979 template<typename C> 980 auto makeTestInvoker( void (C::*testAsMethod)() ) noexcept -> ITestInvoker* { 981 return new(std::nothrow) TestInvokerAsMethod<C>( testAsMethod ); 982 } 983 984 struct NameAndTags { 985 NameAndTags( StringRef const& name_ = StringRef(), StringRef const& tags_ = StringRef() ) noexcept; 986 StringRef name; 987 StringRef tags; 988 }; 989 990 struct AutoReg : NonCopyable { 991 AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept; 992 ~AutoReg(); 993 }; 994 995 } // end namespace Catch 996 997 #if defined(CATCH_CONFIG_DISABLE) 998 #define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \ 999 static void TestName() 1000 #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \ 1001 namespace{ \ 1002 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \ 1003 void test(); \ 1004 }; \ 1005 } \ 1006 void TestName::test() 1007 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( TestName, TestFunc, Name, Tags, Signature, ... ) \ 1008 INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature)) 1009 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \ 1010 namespace{ \ 1011 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) { \ 1012 INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, INTERNAL_CATCH_REMOVE_PARENS(Signature));\ 1013 } \ 1014 } \ 1015 INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature)) 1016 1017 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1018 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \ 1019 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__ ) 1020 #else 1021 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \ 1022 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__ ) ) 1023 #endif 1024 1025 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1026 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \ 1027 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__ ) 1028 #else 1029 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \ 1030 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__ ) ) 1031 #endif 1032 1033 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1034 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \ 1035 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__ ) 1036 #else 1037 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \ 1038 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__ ) ) 1039 #endif 1040 1041 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1042 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \ 1043 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__ ) 1044 #else 1045 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \ 1046 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__ ) ) 1047 #endif 1048 #endif 1049 1050 /////////////////////////////////////////////////////////////////////////////// 1051 #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ 1052 static void TestName(); \ 1053 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1054 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1055 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \ 1056 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1057 static void TestName() 1058 #define INTERNAL_CATCH_TESTCASE( ... ) \ 1059 INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ ) 1060 1061 /////////////////////////////////////////////////////////////////////////////// 1062 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ 1063 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1064 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1065 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &QualifiedMethod ), CATCH_INTERNAL_LINEINFO, "&" #QualifiedMethod, Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \ 1066 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 1067 1068 /////////////////////////////////////////////////////////////////////////////// 1069 #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ 1070 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1071 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1072 namespace{ \ 1073 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \ 1074 void test(); \ 1075 }; \ 1076 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ 1077 } \ 1078 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1079 void TestName::test() 1080 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \ 1081 INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ ) 1082 1083 /////////////////////////////////////////////////////////////////////////////// 1084 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ 1085 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1086 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1087 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ 1088 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 1089 1090 /////////////////////////////////////////////////////////////////////////////// 1091 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_2(TestName, TestFunc, Name, Tags, Signature, ... )\ 1092 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1093 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1094 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ 1095 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 1096 INTERNAL_CATCH_DECLARE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature));\ 1097 namespace {\ 1098 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\ 1099 INTERNAL_CATCH_TYPE_GEN\ 1100 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\ 1101 INTERNAL_CATCH_NTTP_REG_GEN(TestFunc,INTERNAL_CATCH_REMOVE_PARENS(Signature))\ 1102 template<typename...Types> \ 1103 struct TestName{\ 1104 TestName(){\ 1105 int index = 0; \ 1106 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\ 1107 using expander = int[];\ 1108 (void)expander{(reg_test(Types{}, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++, 0)... };/* NOLINT */ \ 1109 }\ 1110 };\ 1111 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ 1112 TestName<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(__VA_ARGS__)>();\ 1113 return 0;\ 1114 }();\ 1115 }\ 1116 }\ 1117 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1118 INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc,INTERNAL_CATCH_REMOVE_PARENS(Signature)) 1119 1120 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1121 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \ 1122 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__ ) 1123 #else 1124 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \ 1125 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__ ) ) 1126 #endif 1127 1128 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1129 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \ 1130 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__ ) 1131 #else 1132 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \ 1133 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__ ) ) 1134 #endif 1135 1136 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(TestName, TestFuncName, Name, Tags, Signature, TmplTypes, TypesList) \ 1137 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1138 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1139 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ 1140 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 1141 template<typename TestType> static void TestFuncName(); \ 1142 namespace {\ 1143 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) { \ 1144 INTERNAL_CATCH_TYPE_GEN \ 1145 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature)) \ 1146 template<typename... Types> \ 1147 struct TestName { \ 1148 void reg_tests() { \ 1149 int index = 0; \ 1150 using expander = int[]; \ 1151 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\ 1152 constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\ 1153 constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\ 1154 (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++, 0)... };/* NOLINT */\ 1155 } \ 1156 }; \ 1157 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \ 1158 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; \ 1159 TestInit t; \ 1160 t.reg_tests(); \ 1161 return 0; \ 1162 }(); \ 1163 } \ 1164 } \ 1165 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1166 template<typename TestType> \ 1167 static void TestFuncName() 1168 1169 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1170 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\ 1171 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__) 1172 #else 1173 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\ 1174 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__ ) ) 1175 #endif 1176 1177 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1178 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\ 1179 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__) 1180 #else 1181 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\ 1182 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__ ) ) 1183 #endif 1184 1185 #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2(TestName, TestFunc, Name, Tags, TmplList)\ 1186 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1187 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1188 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 1189 template<typename TestType> static void TestFunc(); \ 1190 namespace {\ 1191 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\ 1192 INTERNAL_CATCH_TYPE_GEN\ 1193 template<typename... Types> \ 1194 struct TestName { \ 1195 void reg_tests() { \ 1196 int index = 0; \ 1197 using expander = int[]; \ 1198 (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++, 0)... };/* NOLINT */\ 1199 } \ 1200 };\ 1201 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \ 1202 using TestInit = typename convert<TestName, TmplList>::type; \ 1203 TestInit t; \ 1204 t.reg_tests(); \ 1205 return 0; \ 1206 }(); \ 1207 }}\ 1208 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1209 template<typename TestType> \ 1210 static void TestFunc() 1211 1212 #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(Name, Tags, TmplList) \ 1213 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 ) 1214 1215 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \ 1216 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1217 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1218 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ 1219 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 1220 namespace {\ 1221 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \ 1222 INTERNAL_CATCH_TYPE_GEN\ 1223 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\ 1224 INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, INTERNAL_CATCH_REMOVE_PARENS(Signature));\ 1225 INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))\ 1226 template<typename...Types> \ 1227 struct TestNameClass{\ 1228 TestNameClass(){\ 1229 int index = 0; \ 1230 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\ 1231 using expander = int[];\ 1232 (void)expander{(reg_test(Types{}, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++, 0)... };/* NOLINT */ \ 1233 }\ 1234 };\ 1235 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ 1236 TestNameClass<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(__VA_ARGS__)>();\ 1237 return 0;\ 1238 }();\ 1239 }\ 1240 }\ 1241 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1242 INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature)) 1243 1244 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1245 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \ 1246 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__ ) 1247 #else 1248 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \ 1249 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__ ) ) 1250 #endif 1251 1252 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1253 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \ 1254 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__ ) 1255 #else 1256 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \ 1257 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__ ) ) 1258 #endif 1259 1260 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2(TestNameClass, TestName, ClassName, Name, Tags, Signature, TmplTypes, TypesList)\ 1261 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1262 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1263 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ 1264 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 1265 template<typename TestType> \ 1266 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \ 1267 void test();\ 1268 };\ 1269 namespace {\ 1270 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestNameClass) {\ 1271 INTERNAL_CATCH_TYPE_GEN \ 1272 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\ 1273 template<typename...Types>\ 1274 struct TestNameClass{\ 1275 void reg_tests(){\ 1276 int index = 0;\ 1277 using expander = int[];\ 1278 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\ 1279 constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\ 1280 constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\ 1281 (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++, 0)... };/* NOLINT */ \ 1282 }\ 1283 };\ 1284 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ 1285 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;\ 1286 TestInit t;\ 1287 t.reg_tests();\ 1288 return 0;\ 1289 }(); \ 1290 }\ 1291 }\ 1292 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1293 template<typename TestType> \ 1294 void TestName<TestType>::test() 1295 1296 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1297 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\ 1298 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__ ) 1299 #else 1300 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\ 1301 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__ ) ) 1302 #endif 1303 1304 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1305 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\ 1306 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__ ) 1307 #else 1308 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\ 1309 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__ ) ) 1310 #endif 1311 1312 #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, TmplList) \ 1313 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1314 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1315 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 1316 template<typename TestType> \ 1317 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \ 1318 void test();\ 1319 };\ 1320 namespace {\ 1321 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \ 1322 INTERNAL_CATCH_TYPE_GEN\ 1323 template<typename...Types>\ 1324 struct TestNameClass{\ 1325 void reg_tests(){\ 1326 int index = 0;\ 1327 using expander = int[];\ 1328 (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++, 0)... };/* NOLINT */ \ 1329 }\ 1330 };\ 1331 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ 1332 using TestInit = typename convert<TestNameClass, TmplList>::type;\ 1333 TestInit t;\ 1334 t.reg_tests();\ 1335 return 0;\ 1336 }(); \ 1337 }}\ 1338 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1339 template<typename TestType> \ 1340 void TestName<TestType>::test() 1341 1342 #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD(ClassName, Name, Tags, TmplList) \ 1343 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 ) 1344 1345 // end catch_test_registry.h 1346 // start catch_capture.hpp 1347 1348 // start catch_assertionhandler.h 1349 1350 // start catch_assertioninfo.h 1351 1352 // start catch_result_type.h 1353 1354 namespace Catch { 1355 1356 // ResultWas::OfType enum 1357 struct ResultWas { enum OfType { 1358 Unknown = -1, 1359 Ok = 0, 1360 Info = 1, 1361 Warning = 2, 1362 1363 FailureBit = 0x10, 1364 1365 ExpressionFailed = FailureBit | 1, 1366 ExplicitFailure = FailureBit | 2, 1367 1368 Exception = 0x100 | FailureBit, 1369 1370 ThrewException = Exception | 1, 1371 DidntThrowException = Exception | 2, 1372 1373 FatalErrorCondition = 0x200 | FailureBit 1374 1375 }; }; 1376 1377 bool isOk( ResultWas::OfType resultType ); 1378 bool isJustInfo( int flags ); 1379 1380 // ResultDisposition::Flags enum 1381 struct ResultDisposition { enum Flags { 1382 Normal = 0x01, 1383 1384 ContinueOnFailure = 0x02, // Failures fail test, but execution continues 1385 FalseTest = 0x04, // Prefix expression with ! 1386 SuppressFail = 0x08 // Failures are reported but do not fail the test 1387 }; }; 1388 1389 ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ); 1390 1391 bool shouldContinueOnFailure( int flags ); 1392 inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; } 1393 bool shouldSuppressFailure( int flags ); 1394 1395 } // end namespace Catch 1396 1397 // end catch_result_type.h 1398 namespace Catch { 1399 1400 struct AssertionInfo 1401 { 1402 StringRef macroName; 1403 SourceLineInfo lineInfo; 1404 StringRef capturedExpression; 1405 ResultDisposition::Flags resultDisposition; 1406 1407 // We want to delete this constructor but a compiler bug in 4.8 means 1408 // the struct is then treated as non-aggregate 1409 //AssertionInfo() = delete; 1410 }; 1411 1412 } // end namespace Catch 1413 1414 // end catch_assertioninfo.h 1415 // start catch_decomposer.h 1416 1417 // start catch_tostring.h 1418 1419 #include <vector> 1420 #include <cstddef> 1421 #include <type_traits> 1422 #include <string> 1423 // start catch_stream.h 1424 1425 #include <iosfwd> 1426 #include <cstddef> 1427 #include <ostream> 1428 1429 namespace Catch { 1430 1431 std::ostream& cout(); 1432 std::ostream& cerr(); 1433 std::ostream& clog(); 1434 1435 class StringRef; 1436 1437 struct IStream { 1438 virtual ~IStream(); 1439 virtual std::ostream& stream() const = 0; 1440 }; 1441 1442 auto makeStream( StringRef const &filename ) -> IStream const*; 1443 1444 class ReusableStringStream : NonCopyable { 1445 std::size_t m_index; 1446 std::ostream* m_oss; 1447 public: 1448 ReusableStringStream(); 1449 ~ReusableStringStream(); 1450 1451 auto str() const -> std::string; 1452 1453 template<typename T> 1454 auto operator << ( T const& value ) -> ReusableStringStream& { 1455 *m_oss << value; 1456 return *this; 1457 } 1458 auto get() -> std::ostream& { return *m_oss; } 1459 }; 1460 } 1461 1462 // end catch_stream.h 1463 // start catch_interfaces_enum_values_registry.h 1464 1465 #include <vector> 1466 1467 namespace Catch { 1468 1469 namespace Detail { 1470 struct EnumInfo { 1471 StringRef m_name; 1472 std::vector<std::pair<int, StringRef>> m_values; 1473 1474 ~EnumInfo(); 1475 1476 StringRef lookup( int value ) const; 1477 }; 1478 } // namespace Detail 1479 1480 struct IMutableEnumValuesRegistry { 1481 virtual ~IMutableEnumValuesRegistry(); 1482 1483 virtual Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::vector<int> const& values ) = 0; 1484 1485 template<typename E> 1486 Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::initializer_list<E> values ) { 1487 static_assert(sizeof(int) >= sizeof(E), "Cannot serialize enum to int"); 1488 std::vector<int> intValues; 1489 intValues.reserve( values.size() ); 1490 for( auto enumValue : values ) 1491 intValues.push_back( static_cast<int>( enumValue ) ); 1492 return registerEnum( enumName, allEnums, intValues ); 1493 } 1494 }; 1495 1496 } // Catch 1497 1498 // end catch_interfaces_enum_values_registry.h 1499 1500 #ifdef CATCH_CONFIG_CPP17_STRING_VIEW 1501 #include <string_view> 1502 #endif 1503 1504 #ifdef __OBJC__ 1505 // start catch_objc_arc.hpp 1506 1507 #import <Foundation/Foundation.h> 1508 1509 #ifdef __has_feature 1510 #define CATCH_ARC_ENABLED __has_feature(objc_arc) 1511 #else 1512 #define CATCH_ARC_ENABLED 0 1513 #endif 1514 1515 void arcSafeRelease( NSObject* obj ); 1516 id performOptionalSelector( id obj, SEL sel ); 1517 1518 #if !CATCH_ARC_ENABLED 1519 inline void arcSafeRelease( NSObject* obj ) { 1520 [obj release]; 1521 } 1522 inline id performOptionalSelector( id obj, SEL sel ) { 1523 if( [obj respondsToSelector: sel] ) 1524 return [obj performSelector: sel]; 1525 return nil; 1526 } 1527 #define CATCH_UNSAFE_UNRETAINED 1528 #define CATCH_ARC_STRONG 1529 #else 1530 inline void arcSafeRelease( NSObject* ){} 1531 inline id performOptionalSelector( id obj, SEL sel ) { 1532 #ifdef __clang__ 1533 #pragma clang diagnostic push 1534 #pragma clang diagnostic ignored "-Warc-performSelector-leaks" 1535 #endif 1536 if( [obj respondsToSelector: sel] ) 1537 return [obj performSelector: sel]; 1538 #ifdef __clang__ 1539 #pragma clang diagnostic pop 1540 #endif 1541 return nil; 1542 } 1543 #define CATCH_UNSAFE_UNRETAINED __unsafe_unretained 1544 #define CATCH_ARC_STRONG __strong 1545 #endif 1546 1547 // end catch_objc_arc.hpp 1548 #endif 1549 1550 #ifdef _MSC_VER 1551 #pragma warning(push) 1552 #pragma warning(disable:4180) // We attempt to stream a function (address) by const&, which MSVC complains about but is harmless 1553 #endif 1554 1555 namespace Catch { 1556 namespace Detail { 1557 1558 extern const std::string unprintableString; 1559 1560 std::string rawMemoryToString( const void *object, std::size_t size ); 1561 1562 template<typename T> 1563 std::string rawMemoryToString( const T& object ) { 1564 return rawMemoryToString( &object, sizeof(object) ); 1565 } 1566 1567 template<typename T> 1568 class IsStreamInsertable { 1569 template<typename Stream, typename U> 1570 static auto test(int) 1571 -> decltype(std::declval<Stream&>() << std::declval<U>(), std::true_type()); 1572 1573 template<typename, typename> 1574 static auto test(...)->std::false_type; 1575 1576 public: 1577 static const bool value = decltype(test<std::ostream, const T&>(0))::value; 1578 }; 1579 1580 template<typename E> 1581 std::string convertUnknownEnumToString( E e ); 1582 1583 template<typename T> 1584 typename std::enable_if< 1585 !std::is_enum<T>::value && !std::is_base_of<std::exception, T>::value, 1586 std::string>::type convertUnstreamable( T const& ) { 1587 return Detail::unprintableString; 1588 } 1589 template<typename T> 1590 typename std::enable_if< 1591 !std::is_enum<T>::value && std::is_base_of<std::exception, T>::value, 1592 std::string>::type convertUnstreamable(T const& ex) { 1593 return ex.what(); 1594 } 1595 1596 template<typename T> 1597 typename std::enable_if< 1598 std::is_enum<T>::value 1599 , std::string>::type convertUnstreamable( T const& value ) { 1600 return convertUnknownEnumToString( value ); 1601 } 1602 1603 #if defined(_MANAGED) 1604 //! Convert a CLR string to a utf8 std::string 1605 template<typename T> 1606 std::string clrReferenceToString( T^ ref ) { 1607 if (ref == nullptr) 1608 return std::string("null"); 1609 auto bytes = System::Text::Encoding::UTF8->GetBytes(ref->ToString()); 1610 cli::pin_ptr<System::Byte> p = &bytes[0]; 1611 return std::string(reinterpret_cast<char const *>(p), bytes->Length); 1612 } 1613 #endif 1614 1615 } // namespace Detail 1616 1617 // If we decide for C++14, change these to enable_if_ts 1618 template <typename T, typename = void> 1619 struct StringMaker { 1620 template <typename Fake = T> 1621 static 1622 typename std::enable_if<::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type 1623 convert(const Fake& value) { 1624 ReusableStringStream rss; 1625 // NB: call using the function-like syntax to avoid ambiguity with 1626 // user-defined templated operator<< under clang. 1627 rss.operator<<(value); 1628 return rss.str(); 1629 } 1630 1631 template <typename Fake = T> 1632 static 1633 typename std::enable_if<!::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type 1634 convert( const Fake& value ) { 1635 #if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER) 1636 return Detail::convertUnstreamable(value); 1637 #else 1638 return CATCH_CONFIG_FALLBACK_STRINGIFIER(value); 1639 #endif 1640 } 1641 }; 1642 1643 namespace Detail { 1644 1645 // This function dispatches all stringification requests inside of Catch. 1646 // Should be preferably called fully qualified, like ::Catch::Detail::stringify 1647 template <typename T> 1648 std::string stringify(const T& e) { 1649 return ::Catch::StringMaker<typename std::remove_cv<typename std::remove_reference<T>::type>::type>::convert(e); 1650 } 1651 1652 template<typename E> 1653 std::string convertUnknownEnumToString( E e ) { 1654 return ::Catch::Detail::stringify(static_cast<typename std::underlying_type<E>::type>(e)); 1655 } 1656 1657 #if defined(_MANAGED) 1658 template <typename T> 1659 std::string stringify( T^ e ) { 1660 return ::Catch::StringMaker<T^>::convert(e); 1661 } 1662 #endif 1663 1664 } // namespace Detail 1665 1666 // Some predefined specializations 1667 1668 template<> 1669 struct StringMaker<std::string> { 1670 static std::string convert(const std::string& str); 1671 }; 1672 1673 #ifdef CATCH_CONFIG_CPP17_STRING_VIEW 1674 template<> 1675 struct StringMaker<std::string_view> { 1676 static std::string convert(std::string_view str); 1677 }; 1678 #endif 1679 1680 template<> 1681 struct StringMaker<char const *> { 1682 static std::string convert(char const * str); 1683 }; 1684 template<> 1685 struct StringMaker<char *> { 1686 static std::string convert(char * str); 1687 }; 1688 1689 #ifdef CATCH_CONFIG_WCHAR 1690 template<> 1691 struct StringMaker<std::wstring> { 1692 static std::string convert(const std::wstring& wstr); 1693 }; 1694 1695 # ifdef CATCH_CONFIG_CPP17_STRING_VIEW 1696 template<> 1697 struct StringMaker<std::wstring_view> { 1698 static std::string convert(std::wstring_view str); 1699 }; 1700 # endif 1701 1702 template<> 1703 struct StringMaker<wchar_t const *> { 1704 static std::string convert(wchar_t const * str); 1705 }; 1706 template<> 1707 struct StringMaker<wchar_t *> { 1708 static std::string convert(wchar_t * str); 1709 }; 1710 #endif 1711 1712 // TBD: Should we use `strnlen` to ensure that we don't go out of the buffer, 1713 // while keeping string semantics? 1714 template<int SZ> 1715 struct StringMaker<char[SZ]> { 1716 static std::string convert(char const* str) { 1717 return ::Catch::Detail::stringify(std::string{ str }); 1718 } 1719 }; 1720 template<int SZ> 1721 struct StringMaker<signed char[SZ]> { 1722 static std::string convert(signed char const* str) { 1723 return ::Catch::Detail::stringify(std::string{ reinterpret_cast<char const *>(str) }); 1724 } 1725 }; 1726 template<int SZ> 1727 struct StringMaker<unsigned char[SZ]> { 1728 static std::string convert(unsigned char const* str) { 1729 return ::Catch::Detail::stringify(std::string{ reinterpret_cast<char const *>(str) }); 1730 } 1731 }; 1732 1733 #if defined(CATCH_CONFIG_CPP17_BYTE) 1734 template<> 1735 struct StringMaker<std::byte> { 1736 static std::string convert(std::byte value); 1737 }; 1738 #endif // defined(CATCH_CONFIG_CPP17_BYTE) 1739 template<> 1740 struct StringMaker<int> { 1741 static std::string convert(int value); 1742 }; 1743 template<> 1744 struct StringMaker<long> { 1745 static std::string convert(long value); 1746 }; 1747 template<> 1748 struct StringMaker<long long> { 1749 static std::string convert(long long value); 1750 }; 1751 template<> 1752 struct StringMaker<unsigned int> { 1753 static std::string convert(unsigned int value); 1754 }; 1755 template<> 1756 struct StringMaker<unsigned long> { 1757 static std::string convert(unsigned long value); 1758 }; 1759 template<> 1760 struct StringMaker<unsigned long long> { 1761 static std::string convert(unsigned long long value); 1762 }; 1763 1764 template<> 1765 struct StringMaker<bool> { 1766 static std::string convert(bool b); 1767 }; 1768 1769 template<> 1770 struct StringMaker<char> { 1771 static std::string convert(char c); 1772 }; 1773 template<> 1774 struct StringMaker<signed char> { 1775 static std::string convert(signed char c); 1776 }; 1777 template<> 1778 struct StringMaker<unsigned char> { 1779 static std::string convert(unsigned char c); 1780 }; 1781 1782 template<> 1783 struct StringMaker<std::nullptr_t> { 1784 static std::string convert(std::nullptr_t); 1785 }; 1786 1787 template<> 1788 struct StringMaker<float> { 1789 static std::string convert(float value); 1790 static int precision; 1791 }; 1792 1793 template<> 1794 struct StringMaker<double> { 1795 static std::string convert(double value); 1796 static int precision; 1797 }; 1798 1799 template <typename T> 1800 struct StringMaker<T*> { 1801 template <typename U> 1802 static std::string convert(U* p) { 1803 if (p) { 1804 return ::Catch::Detail::rawMemoryToString(p); 1805 } else { 1806 return "nullptr"; 1807 } 1808 } 1809 }; 1810 1811 template <typename R, typename C> 1812 struct StringMaker<R C::*> { 1813 static std::string convert(R C::* p) { 1814 if (p) { 1815 return ::Catch::Detail::rawMemoryToString(p); 1816 } else { 1817 return "nullptr"; 1818 } 1819 } 1820 }; 1821 1822 #if defined(_MANAGED) 1823 template <typename T> 1824 struct StringMaker<T^> { 1825 static std::string convert( T^ ref ) { 1826 return ::Catch::Detail::clrReferenceToString(ref); 1827 } 1828 }; 1829 #endif 1830 1831 namespace Detail { 1832 template<typename InputIterator> 1833 std::string rangeToString(InputIterator first, InputIterator last) { 1834 ReusableStringStream rss; 1835 rss << "{ "; 1836 if (first != last) { 1837 rss << ::Catch::Detail::stringify(*first); 1838 for (++first; first != last; ++first) 1839 rss << ", " << ::Catch::Detail::stringify(*first); 1840 } 1841 rss << " }"; 1842 return rss.str(); 1843 } 1844 } 1845 1846 #ifdef __OBJC__ 1847 template<> 1848 struct StringMaker<NSString*> { 1849 static std::string convert(NSString * nsstring) { 1850 if (!nsstring) 1851 return "nil"; 1852 return std::string("@") + [nsstring UTF8String]; 1853 } 1854 }; 1855 template<> 1856 struct StringMaker<NSObject*> { 1857 static std::string convert(NSObject* nsObject) { 1858 return ::Catch::Detail::stringify([nsObject description]); 1859 } 1860 1861 }; 1862 namespace Detail { 1863 inline std::string stringify( NSString* nsstring ) { 1864 return StringMaker<NSString*>::convert( nsstring ); 1865 } 1866 1867 } // namespace Detail 1868 #endif // __OBJC__ 1869 1870 } // namespace Catch 1871 1872 ////////////////////////////////////////////////////// 1873 // Separate std-lib types stringification, so it can be selectively enabled 1874 // This means that we do not bring in 1875 1876 #if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS) 1877 # define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER 1878 # define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER 1879 # define CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER 1880 # define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER 1881 # define CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER 1882 #endif 1883 1884 // Separate std::pair specialization 1885 #if defined(CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER) 1886 #include <utility> 1887 namespace Catch { 1888 template<typename T1, typename T2> 1889 struct StringMaker<std::pair<T1, T2> > { 1890 static std::string convert(const std::pair<T1, T2>& pair) { 1891 ReusableStringStream rss; 1892 rss << "{ " 1893 << ::Catch::Detail::stringify(pair.first) 1894 << ", " 1895 << ::Catch::Detail::stringify(pair.second) 1896 << " }"; 1897 return rss.str(); 1898 } 1899 }; 1900 } 1901 #endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER 1902 1903 #if defined(CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_OPTIONAL) 1904 #include <optional> 1905 namespace Catch { 1906 template<typename T> 1907 struct StringMaker<std::optional<T> > { 1908 static std::string convert(const std::optional<T>& optional) { 1909 ReusableStringStream rss; 1910 if (optional.has_value()) { 1911 rss << ::Catch::Detail::stringify(*optional); 1912 } else { 1913 rss << "{ }"; 1914 } 1915 return rss.str(); 1916 } 1917 }; 1918 } 1919 #endif // CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER 1920 1921 // Separate std::tuple specialization 1922 #if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER) 1923 #include <tuple> 1924 namespace Catch { 1925 namespace Detail { 1926 template< 1927 typename Tuple, 1928 std::size_t N = 0, 1929 bool = (N < std::tuple_size<Tuple>::value) 1930 > 1931 struct TupleElementPrinter { 1932 static void print(const Tuple& tuple, std::ostream& os) { 1933 os << (N ? ", " : " ") 1934 << ::Catch::Detail::stringify(std::get<N>(tuple)); 1935 TupleElementPrinter<Tuple, N + 1>::print(tuple, os); 1936 } 1937 }; 1938 1939 template< 1940 typename Tuple, 1941 std::size_t N 1942 > 1943 struct TupleElementPrinter<Tuple, N, false> { 1944 static void print(const Tuple&, std::ostream&) {} 1945 }; 1946 1947 } 1948 1949 template<typename ...Types> 1950 struct StringMaker<std::tuple<Types...>> { 1951 static std::string convert(const std::tuple<Types...>& tuple) { 1952 ReusableStringStream rss; 1953 rss << '{'; 1954 Detail::TupleElementPrinter<std::tuple<Types...>>::print(tuple, rss.get()); 1955 rss << " }"; 1956 return rss.str(); 1957 } 1958 }; 1959 } 1960 #endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER 1961 1962 #if defined(CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_VARIANT) 1963 #include <variant> 1964 namespace Catch { 1965 template<> 1966 struct StringMaker<std::monostate> { 1967 static std::string convert(const std::monostate&) { 1968 return "{ }"; 1969 } 1970 }; 1971 1972 template<typename... Elements> 1973 struct StringMaker<std::variant<Elements...>> { 1974 static std::string convert(const std::variant<Elements...>& variant) { 1975 if (variant.valueless_by_exception()) { 1976 return "{valueless variant}"; 1977 } else { 1978 return std::visit( 1979 [](const auto& value) { 1980 return ::Catch::Detail::stringify(value); 1981 }, 1982 variant 1983 ); 1984 } 1985 } 1986 }; 1987 } 1988 #endif // CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER 1989 1990 namespace Catch { 1991 // Import begin/ end from std here 1992 using std::begin; 1993 using std::end; 1994 1995 namespace detail { 1996 template <typename...> 1997 struct void_type { 1998 using type = void; 1999 }; 2000 2001 template <typename T, typename = void> 2002 struct is_range_impl : std::false_type { 2003 }; 2004 2005 template <typename T> 2006 struct is_range_impl<T, typename void_type<decltype(begin(std::declval<T>()))>::type> : std::true_type { 2007 }; 2008 } // namespace detail 2009 2010 template <typename T> 2011 struct is_range : detail::is_range_impl<T> { 2012 }; 2013 2014 #if defined(_MANAGED) // Managed types are never ranges 2015 template <typename T> 2016 struct is_range<T^> { 2017 static const bool value = false; 2018 }; 2019 #endif 2020 2021 template<typename Range> 2022 std::string rangeToString( Range const& range ) { 2023 return ::Catch::Detail::rangeToString( begin( range ), end( range ) ); 2024 } 2025 2026 // Handle vector<bool> specially 2027 template<typename Allocator> 2028 std::string rangeToString( std::vector<bool, Allocator> const& v ) { 2029 ReusableStringStream rss; 2030 rss << "{ "; 2031 bool first = true; 2032 for( bool b : v ) { 2033 if( first ) 2034 first = false; 2035 else 2036 rss << ", "; 2037 rss << ::Catch::Detail::stringify( b ); 2038 } 2039 rss << " }"; 2040 return rss.str(); 2041 } 2042 2043 template<typename R> 2044 struct StringMaker<R, typename std::enable_if<is_range<R>::value && !::Catch::Detail::IsStreamInsertable<R>::value>::type> { 2045 static std::string convert( R const& range ) { 2046 return rangeToString( range ); 2047 } 2048 }; 2049 2050 template <typename T, int SZ> 2051 struct StringMaker<T[SZ]> { 2052 static std::string convert(T const(&arr)[SZ]) { 2053 return rangeToString(arr); 2054 } 2055 }; 2056 2057 } // namespace Catch 2058 2059 // Separate std::chrono::duration specialization 2060 #if defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) 2061 #include <ctime> 2062 #include <ratio> 2063 #include <chrono> 2064 2065 namespace Catch { 2066 2067 template <class Ratio> 2068 struct ratio_string { 2069 static std::string symbol(); 2070 }; 2071 2072 template <class Ratio> 2073 std::string ratio_string<Ratio>::symbol() { 2074 Catch::ReusableStringStream rss; 2075 rss << '[' << Ratio::num << '/' 2076 << Ratio::den << ']'; 2077 return rss.str(); 2078 } 2079 template <> 2080 struct ratio_string<std::atto> { 2081 static std::string symbol(); 2082 }; 2083 template <> 2084 struct ratio_string<std::femto> { 2085 static std::string symbol(); 2086 }; 2087 template <> 2088 struct ratio_string<std::pico> { 2089 static std::string symbol(); 2090 }; 2091 template <> 2092 struct ratio_string<std::nano> { 2093 static std::string symbol(); 2094 }; 2095 template <> 2096 struct ratio_string<std::micro> { 2097 static std::string symbol(); 2098 }; 2099 template <> 2100 struct ratio_string<std::milli> { 2101 static std::string symbol(); 2102 }; 2103 2104 //////////// 2105 // std::chrono::duration specializations 2106 template<typename Value, typename Ratio> 2107 struct StringMaker<std::chrono::duration<Value, Ratio>> { 2108 static std::string convert(std::chrono::duration<Value, Ratio> const& duration) { 2109 ReusableStringStream rss; 2110 rss << duration.count() << ' ' << ratio_string<Ratio>::symbol() << 's'; 2111 return rss.str(); 2112 } 2113 }; 2114 template<typename Value> 2115 struct StringMaker<std::chrono::duration<Value, std::ratio<1>>> { 2116 static std::string convert(std::chrono::duration<Value, std::ratio<1>> const& duration) { 2117 ReusableStringStream rss; 2118 rss << duration.count() << " s"; 2119 return rss.str(); 2120 } 2121 }; 2122 template<typename Value> 2123 struct StringMaker<std::chrono::duration<Value, std::ratio<60>>> { 2124 static std::string convert(std::chrono::duration<Value, std::ratio<60>> const& duration) { 2125 ReusableStringStream rss; 2126 rss << duration.count() << " m"; 2127 return rss.str(); 2128 } 2129 }; 2130 template<typename Value> 2131 struct StringMaker<std::chrono::duration<Value, std::ratio<3600>>> { 2132 static std::string convert(std::chrono::duration<Value, std::ratio<3600>> const& duration) { 2133 ReusableStringStream rss; 2134 rss << duration.count() << " h"; 2135 return rss.str(); 2136 } 2137 }; 2138 2139 //////////// 2140 // std::chrono::time_point specialization 2141 // Generic time_point cannot be specialized, only std::chrono::time_point<system_clock> 2142 template<typename Clock, typename Duration> 2143 struct StringMaker<std::chrono::time_point<Clock, Duration>> { 2144 static std::string convert(std::chrono::time_point<Clock, Duration> const& time_point) { 2145 return ::Catch::Detail::stringify(time_point.time_since_epoch()) + " since epoch"; 2146 } 2147 }; 2148 // std::chrono::time_point<system_clock> specialization 2149 template<typename Duration> 2150 struct StringMaker<std::chrono::time_point<std::chrono::system_clock, Duration>> { 2151 static std::string convert(std::chrono::time_point<std::chrono::system_clock, Duration> const& time_point) { 2152 auto converted = std::chrono::system_clock::to_time_t(time_point); 2153 2154 #ifdef _MSC_VER 2155 std::tm timeInfo = {}; 2156 gmtime_s(&timeInfo, &converted); 2157 #else 2158 std::tm* timeInfo = std::gmtime(&converted); 2159 #endif 2160 2161 auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); 2162 char timeStamp[timeStampSize]; 2163 const char * const fmt = "%Y-%m-%dT%H:%M:%SZ"; 2164 2165 #ifdef _MSC_VER 2166 std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); 2167 #else 2168 std::strftime(timeStamp, timeStampSize, fmt, timeInfo); 2169 #endif 2170 return std::string(timeStamp); 2171 } 2172 }; 2173 } 2174 #endif // CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER 2175 2176 #define INTERNAL_CATCH_REGISTER_ENUM( enumName, ... ) \ 2177 namespace Catch { \ 2178 template<> struct StringMaker<enumName> { \ 2179 static std::string convert( enumName value ) { \ 2180 static const auto& enumInfo = ::Catch::getMutableRegistryHub().getMutableEnumValuesRegistry().registerEnum( #enumName, #__VA_ARGS__, { __VA_ARGS__ } ); \ 2181 return static_cast<std::string>(enumInfo.lookup( static_cast<int>( value ) )); \ 2182 } \ 2183 }; \ 2184 } 2185 2186 #define CATCH_REGISTER_ENUM( enumName, ... ) INTERNAL_CATCH_REGISTER_ENUM( enumName, __VA_ARGS__ ) 2187 2188 #ifdef _MSC_VER 2189 #pragma warning(pop) 2190 #endif 2191 2192 // end catch_tostring.h 2193 #include <iosfwd> 2194 2195 #ifdef _MSC_VER 2196 #pragma warning(push) 2197 #pragma warning(disable:4389) // '==' : signed/unsigned mismatch 2198 #pragma warning(disable:4018) // more "signed/unsigned mismatch" 2199 #pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform) 2200 #pragma warning(disable:4180) // qualifier applied to function type has no meaning 2201 #pragma warning(disable:4800) // Forcing result to true or false 2202 #endif 2203 2204 namespace Catch { 2205 2206 struct ITransientExpression { 2207 auto isBinaryExpression() const -> bool { return m_isBinaryExpression; } 2208 auto getResult() const -> bool { return m_result; } 2209 virtual void streamReconstructedExpression( std::ostream &os ) const = 0; 2210 2211 ITransientExpression( bool isBinaryExpression, bool result ) 2212 : m_isBinaryExpression( isBinaryExpression ), 2213 m_result( result ) 2214 {} 2215 2216 // We don't actually need a virtual destructor, but many static analysers 2217 // complain if it's not here :-( 2218 virtual ~ITransientExpression(); 2219 2220 bool m_isBinaryExpression; 2221 bool m_result; 2222 2223 }; 2224 2225 void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ); 2226 2227 template<typename LhsT, typename RhsT> 2228 class BinaryExpr : public ITransientExpression { 2229 LhsT m_lhs; 2230 StringRef m_op; 2231 RhsT m_rhs; 2232 2233 void streamReconstructedExpression( std::ostream &os ) const override { 2234 formatReconstructedExpression 2235 ( os, Catch::Detail::stringify( m_lhs ), m_op, Catch::Detail::stringify( m_rhs ) ); 2236 } 2237 2238 public: 2239 BinaryExpr( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs ) 2240 : ITransientExpression{ true, comparisonResult }, 2241 m_lhs( lhs ), 2242 m_op( op ), 2243 m_rhs( rhs ) 2244 {} 2245 2246 template<typename T> 2247 auto operator && ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 2248 static_assert(always_false<T>::value, 2249 "chained comparisons are not supported inside assertions, " 2250 "wrap the expression inside parentheses, or decompose it"); 2251 } 2252 2253 template<typename T> 2254 auto operator || ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 2255 static_assert(always_false<T>::value, 2256 "chained comparisons are not supported inside assertions, " 2257 "wrap the expression inside parentheses, or decompose it"); 2258 } 2259 2260 template<typename T> 2261 auto operator == ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 2262 static_assert(always_false<T>::value, 2263 "chained comparisons are not supported inside assertions, " 2264 "wrap the expression inside parentheses, or decompose it"); 2265 } 2266 2267 template<typename T> 2268 auto operator != ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 2269 static_assert(always_false<T>::value, 2270 "chained comparisons are not supported inside assertions, " 2271 "wrap the expression inside parentheses, or decompose it"); 2272 } 2273 2274 template<typename T> 2275 auto operator > ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 2276 static_assert(always_false<T>::value, 2277 "chained comparisons are not supported inside assertions, " 2278 "wrap the expression inside parentheses, or decompose it"); 2279 } 2280 2281 template<typename T> 2282 auto operator < ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 2283 static_assert(always_false<T>::value, 2284 "chained comparisons are not supported inside assertions, " 2285 "wrap the expression inside parentheses, or decompose it"); 2286 } 2287 2288 template<typename T> 2289 auto operator >= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 2290 static_assert(always_false<T>::value, 2291 "chained comparisons are not supported inside assertions, " 2292 "wrap the expression inside parentheses, or decompose it"); 2293 } 2294 2295 template<typename T> 2296 auto operator <= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 2297 static_assert(always_false<T>::value, 2298 "chained comparisons are not supported inside assertions, " 2299 "wrap the expression inside parentheses, or decompose it"); 2300 } 2301 }; 2302 2303 template<typename LhsT> 2304 class UnaryExpr : public ITransientExpression { 2305 LhsT m_lhs; 2306 2307 void streamReconstructedExpression( std::ostream &os ) const override { 2308 os << Catch::Detail::stringify( m_lhs ); 2309 } 2310 2311 public: 2312 explicit UnaryExpr( LhsT lhs ) 2313 : ITransientExpression{ false, static_cast<bool>(lhs) }, 2314 m_lhs( lhs ) 2315 {} 2316 }; 2317 2318 // Specialised comparison functions to handle equality comparisons between ints and pointers (NULL deduces as an int) 2319 template<typename LhsT, typename RhsT> 2320 auto compareEqual( LhsT const& lhs, RhsT const& rhs ) -> bool { return static_cast<bool>(lhs == rhs); } 2321 template<typename T> 2322 auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); } 2323 template<typename T> 2324 auto compareEqual( T* const& lhs, long rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); } 2325 template<typename T> 2326 auto compareEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; } 2327 template<typename T> 2328 auto compareEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; } 2329 2330 template<typename LhsT, typename RhsT> 2331 auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return static_cast<bool>(lhs != rhs); } 2332 template<typename T> 2333 auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); } 2334 template<typename T> 2335 auto compareNotEqual( T* const& lhs, long rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); } 2336 template<typename T> 2337 auto compareNotEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) != rhs; } 2338 template<typename T> 2339 auto compareNotEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) != rhs; } 2340 2341 template<typename LhsT> 2342 class ExprLhs { 2343 LhsT m_lhs; 2344 public: 2345 explicit ExprLhs( LhsT lhs ) : m_lhs( lhs ) {} 2346 2347 template<typename RhsT> 2348 auto operator == ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const { 2349 return { compareEqual( m_lhs, rhs ), m_lhs, "==", rhs }; 2350 } 2351 auto operator == ( bool rhs ) -> BinaryExpr<LhsT, bool> const { 2352 return { m_lhs == rhs, m_lhs, "==", rhs }; 2353 } 2354 2355 template<typename RhsT> 2356 auto operator != ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const { 2357 return { compareNotEqual( m_lhs, rhs ), m_lhs, "!=", rhs }; 2358 } 2359 auto operator != ( bool rhs ) -> BinaryExpr<LhsT, bool> const { 2360 return { m_lhs != rhs, m_lhs, "!=", rhs }; 2361 } 2362 2363 template<typename RhsT> 2364 auto operator > ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const { 2365 return { static_cast<bool>(m_lhs > rhs), m_lhs, ">", rhs }; 2366 } 2367 template<typename RhsT> 2368 auto operator < ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const { 2369 return { static_cast<bool>(m_lhs < rhs), m_lhs, "<", rhs }; 2370 } 2371 template<typename RhsT> 2372 auto operator >= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const { 2373 return { static_cast<bool>(m_lhs >= rhs), m_lhs, ">=", rhs }; 2374 } 2375 template<typename RhsT> 2376 auto operator <= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const { 2377 return { static_cast<bool>(m_lhs <= rhs), m_lhs, "<=", rhs }; 2378 } 2379 template <typename RhsT> 2380 auto operator | (RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const { 2381 return { static_cast<bool>(m_lhs | rhs), m_lhs, "|", rhs }; 2382 } 2383 template <typename RhsT> 2384 auto operator & (RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const { 2385 return { static_cast<bool>(m_lhs & rhs), m_lhs, "&", rhs }; 2386 } 2387 template <typename RhsT> 2388 auto operator ^ (RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const { 2389 return { static_cast<bool>(m_lhs ^ rhs), m_lhs, "^", rhs }; 2390 } 2391 2392 template<typename RhsT> 2393 auto operator && ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const { 2394 static_assert(always_false<RhsT>::value, 2395 "operator&& is not supported inside assertions, " 2396 "wrap the expression inside parentheses, or decompose it"); 2397 } 2398 2399 template<typename RhsT> 2400 auto operator || ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const { 2401 static_assert(always_false<RhsT>::value, 2402 "operator|| is not supported inside assertions, " 2403 "wrap the expression inside parentheses, or decompose it"); 2404 } 2405 2406 auto makeUnaryExpr() const -> UnaryExpr<LhsT> { 2407 return UnaryExpr<LhsT>{ m_lhs }; 2408 } 2409 }; 2410 2411 void handleExpression( ITransientExpression const& expr ); 2412 2413 template<typename T> 2414 void handleExpression( ExprLhs<T> const& expr ) { 2415 handleExpression( expr.makeUnaryExpr() ); 2416 } 2417 2418 struct Decomposer { 2419 template<typename T> 2420 auto operator <= ( T const& lhs ) -> ExprLhs<T const&> { 2421 return ExprLhs<T const&>{ lhs }; 2422 } 2423 2424 auto operator <=( bool value ) -> ExprLhs<bool> { 2425 return ExprLhs<bool>{ value }; 2426 } 2427 }; 2428 2429 } // end namespace Catch 2430 2431 #ifdef _MSC_VER 2432 #pragma warning(pop) 2433 #endif 2434 2435 // end catch_decomposer.h 2436 // start catch_interfaces_capture.h 2437 2438 #include <string> 2439 #include <chrono> 2440 2441 namespace Catch { 2442 2443 class AssertionResult; 2444 struct AssertionInfo; 2445 struct SectionInfo; 2446 struct SectionEndInfo; 2447 struct MessageInfo; 2448 struct MessageBuilder; 2449 struct Counts; 2450 struct AssertionReaction; 2451 struct SourceLineInfo; 2452 2453 struct ITransientExpression; 2454 struct IGeneratorTracker; 2455 2456 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 2457 struct BenchmarkInfo; 2458 template <typename Duration = std::chrono::duration<double, std::nano>> 2459 struct BenchmarkStats; 2460 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 2461 2462 struct IResultCapture { 2463 2464 virtual ~IResultCapture(); 2465 2466 virtual bool sectionStarted( SectionInfo const& sectionInfo, 2467 Counts& assertions ) = 0; 2468 virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; 2469 virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; 2470 2471 virtual auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& = 0; 2472 2473 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 2474 virtual void benchmarkPreparing( std::string const& name ) = 0; 2475 virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0; 2476 virtual void benchmarkEnded( BenchmarkStats<> const& stats ) = 0; 2477 virtual void benchmarkFailed( std::string const& error ) = 0; 2478 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 2479 2480 virtual void pushScopedMessage( MessageInfo const& message ) = 0; 2481 virtual void popScopedMessage( MessageInfo const& message ) = 0; 2482 2483 virtual void emplaceUnscopedMessage( MessageBuilder const& builder ) = 0; 2484 2485 virtual void handleFatalErrorCondition( StringRef message ) = 0; 2486 2487 virtual void handleExpr 2488 ( AssertionInfo const& info, 2489 ITransientExpression const& expr, 2490 AssertionReaction& reaction ) = 0; 2491 virtual void handleMessage 2492 ( AssertionInfo const& info, 2493 ResultWas::OfType resultType, 2494 StringRef const& message, 2495 AssertionReaction& reaction ) = 0; 2496 virtual void handleUnexpectedExceptionNotThrown 2497 ( AssertionInfo const& info, 2498 AssertionReaction& reaction ) = 0; 2499 virtual void handleUnexpectedInflightException 2500 ( AssertionInfo const& info, 2501 std::string const& message, 2502 AssertionReaction& reaction ) = 0; 2503 virtual void handleIncomplete 2504 ( AssertionInfo const& info ) = 0; 2505 virtual void handleNonExpr 2506 ( AssertionInfo const &info, 2507 ResultWas::OfType resultType, 2508 AssertionReaction &reaction ) = 0; 2509 2510 virtual bool lastAssertionPassed() = 0; 2511 virtual void assertionPassed() = 0; 2512 2513 // Deprecated, do not use: 2514 virtual std::string getCurrentTestName() const = 0; 2515 virtual const AssertionResult* getLastResult() const = 0; 2516 virtual void exceptionEarlyReported() = 0; 2517 }; 2518 2519 IResultCapture& getResultCapture(); 2520 } 2521 2522 // end catch_interfaces_capture.h 2523 namespace Catch { 2524 2525 struct TestFailureException{}; 2526 struct AssertionResultData; 2527 struct IResultCapture; 2528 class RunContext; 2529 2530 class LazyExpression { 2531 friend class AssertionHandler; 2532 friend struct AssertionStats; 2533 friend class RunContext; 2534 2535 ITransientExpression const* m_transientExpression = nullptr; 2536 bool m_isNegated; 2537 public: 2538 LazyExpression( bool isNegated ); 2539 LazyExpression( LazyExpression const& other ); 2540 LazyExpression& operator = ( LazyExpression const& ) = delete; 2541 2542 explicit operator bool() const; 2543 2544 friend auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream&; 2545 }; 2546 2547 struct AssertionReaction { 2548 bool shouldDebugBreak = false; 2549 bool shouldThrow = false; 2550 }; 2551 2552 class AssertionHandler { 2553 AssertionInfo m_assertionInfo; 2554 AssertionReaction m_reaction; 2555 bool m_completed = false; 2556 IResultCapture& m_resultCapture; 2557 2558 public: 2559 AssertionHandler 2560 ( StringRef const& macroName, 2561 SourceLineInfo const& lineInfo, 2562 StringRef capturedExpression, 2563 ResultDisposition::Flags resultDisposition ); 2564 ~AssertionHandler() { 2565 if ( !m_completed ) { 2566 m_resultCapture.handleIncomplete( m_assertionInfo ); 2567 } 2568 } 2569 2570 template<typename T> 2571 void handleExpr( ExprLhs<T> const& expr ) { 2572 handleExpr( expr.makeUnaryExpr() ); 2573 } 2574 void handleExpr( ITransientExpression const& expr ); 2575 2576 void handleMessage(ResultWas::OfType resultType, StringRef const& message); 2577 2578 void handleExceptionThrownAsExpected(); 2579 void handleUnexpectedExceptionNotThrown(); 2580 void handleExceptionNotThrownAsExpected(); 2581 void handleThrowingCallSkipped(); 2582 void handleUnexpectedInflightException(); 2583 2584 void complete(); 2585 void setCompleted(); 2586 2587 // query 2588 auto allowThrows() const -> bool; 2589 }; 2590 2591 void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef const& matcherString ); 2592 2593 } // namespace Catch 2594 2595 // end catch_assertionhandler.h 2596 // start catch_message.h 2597 2598 #include <string> 2599 #include <vector> 2600 2601 namespace Catch { 2602 2603 struct MessageInfo { 2604 MessageInfo( StringRef const& _macroName, 2605 SourceLineInfo const& _lineInfo, 2606 ResultWas::OfType _type ); 2607 2608 StringRef macroName; 2609 std::string message; 2610 SourceLineInfo lineInfo; 2611 ResultWas::OfType type; 2612 unsigned int sequence; 2613 2614 bool operator == ( MessageInfo const& other ) const; 2615 bool operator < ( MessageInfo const& other ) const; 2616 private: 2617 static unsigned int globalCount; 2618 }; 2619 2620 struct MessageStream { 2621 2622 template<typename T> 2623 MessageStream& operator << ( T const& value ) { 2624 m_stream << value; 2625 return *this; 2626 } 2627 2628 ReusableStringStream m_stream; 2629 }; 2630 2631 struct MessageBuilder : MessageStream { 2632 MessageBuilder( StringRef const& macroName, 2633 SourceLineInfo const& lineInfo, 2634 ResultWas::OfType type ); 2635 2636 template<typename T> 2637 MessageBuilder& operator << ( T const& value ) { 2638 m_stream << value; 2639 return *this; 2640 } 2641 2642 MessageInfo m_info; 2643 }; 2644 2645 class ScopedMessage { 2646 public: 2647 explicit ScopedMessage( MessageBuilder const& builder ); 2648 ScopedMessage( ScopedMessage& duplicate ) = delete; 2649 ScopedMessage( ScopedMessage&& old ); 2650 ~ScopedMessage(); 2651 2652 MessageInfo m_info; 2653 bool m_moved; 2654 }; 2655 2656 class Capturer { 2657 std::vector<MessageInfo> m_messages; 2658 IResultCapture& m_resultCapture = getResultCapture(); 2659 size_t m_captured = 0; 2660 public: 2661 Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names ); 2662 ~Capturer(); 2663 2664 void captureValue( size_t index, std::string const& value ); 2665 2666 template<typename T> 2667 void captureValues( size_t index, T const& value ) { 2668 captureValue( index, Catch::Detail::stringify( value ) ); 2669 } 2670 2671 template<typename T, typename... Ts> 2672 void captureValues( size_t index, T const& value, Ts const&... values ) { 2673 captureValue( index, Catch::Detail::stringify(value) ); 2674 captureValues( index+1, values... ); 2675 } 2676 }; 2677 2678 } // end namespace Catch 2679 2680 // end catch_message.h 2681 #if !defined(CATCH_CONFIG_DISABLE) 2682 2683 #if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION) 2684 #define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__ 2685 #else 2686 #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION" 2687 #endif 2688 2689 #if defined(CATCH_CONFIG_FAST_COMPILE) || defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 2690 2691 /////////////////////////////////////////////////////////////////////////////// 2692 // Another way to speed-up compilation is to omit local try-catch for REQUIRE* 2693 // macros. 2694 #define INTERNAL_CATCH_TRY 2695 #define INTERNAL_CATCH_CATCH( capturer ) 2696 2697 #else // CATCH_CONFIG_FAST_COMPILE 2698 2699 #define INTERNAL_CATCH_TRY try 2700 #define INTERNAL_CATCH_CATCH( handler ) catch(...) { handler.handleUnexpectedInflightException(); } 2701 2702 #endif 2703 2704 #define INTERNAL_CATCH_REACT( handler ) handler.complete(); 2705 2706 /////////////////////////////////////////////////////////////////////////////// 2707 #define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \ 2708 do { \ 2709 CATCH_INTERNAL_IGNORE_BUT_WARN(__VA_ARGS__); \ 2710 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ 2711 INTERNAL_CATCH_TRY { \ 2712 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 2713 CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ 2714 catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); \ 2715 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 2716 } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ 2717 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2718 } while( (void)0, (false) && static_cast<bool>( !!(__VA_ARGS__) ) ) 2719 2720 /////////////////////////////////////////////////////////////////////////////// 2721 #define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \ 2722 INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \ 2723 if( Catch::getResultCapture().lastAssertionPassed() ) 2724 2725 /////////////////////////////////////////////////////////////////////////////// 2726 #define INTERNAL_CATCH_ELSE( macroName, resultDisposition, ... ) \ 2727 INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \ 2728 if( !Catch::getResultCapture().lastAssertionPassed() ) 2729 2730 /////////////////////////////////////////////////////////////////////////////// 2731 #define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \ 2732 do { \ 2733 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ 2734 try { \ 2735 static_cast<void>(__VA_ARGS__); \ 2736 catchAssertionHandler.handleExceptionNotThrownAsExpected(); \ 2737 } \ 2738 catch( ... ) { \ 2739 catchAssertionHandler.handleUnexpectedInflightException(); \ 2740 } \ 2741 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2742 } while( false ) 2743 2744 /////////////////////////////////////////////////////////////////////////////// 2745 #define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \ 2746 do { \ 2747 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \ 2748 if( catchAssertionHandler.allowThrows() ) \ 2749 try { \ 2750 static_cast<void>(__VA_ARGS__); \ 2751 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 2752 } \ 2753 catch( ... ) { \ 2754 catchAssertionHandler.handleExceptionThrownAsExpected(); \ 2755 } \ 2756 else \ 2757 catchAssertionHandler.handleThrowingCallSkipped(); \ 2758 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2759 } while( false ) 2760 2761 /////////////////////////////////////////////////////////////////////////////// 2762 #define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \ 2763 do { \ 2764 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \ 2765 if( catchAssertionHandler.allowThrows() ) \ 2766 try { \ 2767 static_cast<void>(expr); \ 2768 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 2769 } \ 2770 catch( exceptionType const& ) { \ 2771 catchAssertionHandler.handleExceptionThrownAsExpected(); \ 2772 } \ 2773 catch( ... ) { \ 2774 catchAssertionHandler.handleUnexpectedInflightException(); \ 2775 } \ 2776 else \ 2777 catchAssertionHandler.handleThrowingCallSkipped(); \ 2778 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2779 } while( false ) 2780 2781 /////////////////////////////////////////////////////////////////////////////// 2782 #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \ 2783 do { \ 2784 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::StringRef(), resultDisposition ); \ 2785 catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \ 2786 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2787 } while( false ) 2788 2789 /////////////////////////////////////////////////////////////////////////////// 2790 #define INTERNAL_CATCH_CAPTURE( varName, macroName, ... ) \ 2791 auto varName = Catch::Capturer( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info, #__VA_ARGS__ ); \ 2792 varName.captureValues( 0, __VA_ARGS__ ) 2793 2794 /////////////////////////////////////////////////////////////////////////////// 2795 #define INTERNAL_CATCH_INFO( macroName, log ) \ 2796 Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log ); 2797 2798 /////////////////////////////////////////////////////////////////////////////// 2799 #define INTERNAL_CATCH_UNSCOPED_INFO( macroName, log ) \ 2800 Catch::getResultCapture().emplaceUnscopedMessage( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log ) 2801 2802 /////////////////////////////////////////////////////////////////////////////// 2803 // Although this is matcher-based, it can be used with just a string 2804 #define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \ 2805 do { \ 2806 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ 2807 if( catchAssertionHandler.allowThrows() ) \ 2808 try { \ 2809 static_cast<void>(__VA_ARGS__); \ 2810 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 2811 } \ 2812 catch( ... ) { \ 2813 Catch::handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher##_catch_sr ); \ 2814 } \ 2815 else \ 2816 catchAssertionHandler.handleThrowingCallSkipped(); \ 2817 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2818 } while( false ) 2819 2820 #endif // CATCH_CONFIG_DISABLE 2821 2822 // end catch_capture.hpp 2823 // start catch_section.h 2824 2825 // start catch_section_info.h 2826 2827 // start catch_totals.h 2828 2829 #include <cstddef> 2830 2831 namespace Catch { 2832 2833 struct Counts { 2834 Counts operator - ( Counts const& other ) const; 2835 Counts& operator += ( Counts const& other ); 2836 2837 std::size_t total() const; 2838 bool allPassed() const; 2839 bool allOk() const; 2840 2841 std::size_t passed = 0; 2842 std::size_t failed = 0; 2843 std::size_t failedButOk = 0; 2844 }; 2845 2846 struct Totals { 2847 2848 Totals operator - ( Totals const& other ) const; 2849 Totals& operator += ( Totals const& other ); 2850 2851 Totals delta( Totals const& prevTotals ) const; 2852 2853 int error = 0; 2854 Counts assertions; 2855 Counts testCases; 2856 }; 2857 } 2858 2859 // end catch_totals.h 2860 #include <string> 2861 2862 namespace Catch { 2863 2864 struct SectionInfo { 2865 SectionInfo 2866 ( SourceLineInfo const& _lineInfo, 2867 std::string const& _name ); 2868 2869 // Deprecated 2870 SectionInfo 2871 ( SourceLineInfo const& _lineInfo, 2872 std::string const& _name, 2873 std::string const& ) : SectionInfo( _lineInfo, _name ) {} 2874 2875 std::string name; 2876 std::string description; // !Deprecated: this will always be empty 2877 SourceLineInfo lineInfo; 2878 }; 2879 2880 struct SectionEndInfo { 2881 SectionInfo sectionInfo; 2882 Counts prevAssertions; 2883 double durationInSeconds; 2884 }; 2885 2886 } // end namespace Catch 2887 2888 // end catch_section_info.h 2889 // start catch_timer.h 2890 2891 #include <cstdint> 2892 2893 namespace Catch { 2894 2895 auto getCurrentNanosecondsSinceEpoch() -> uint64_t; 2896 auto getEstimatedClockResolution() -> uint64_t; 2897 2898 class Timer { 2899 uint64_t m_nanoseconds = 0; 2900 public: 2901 void start(); 2902 auto getElapsedNanoseconds() const -> uint64_t; 2903 auto getElapsedMicroseconds() const -> uint64_t; 2904 auto getElapsedMilliseconds() const -> unsigned int; 2905 auto getElapsedSeconds() const -> double; 2906 }; 2907 2908 } // namespace Catch 2909 2910 // end catch_timer.h 2911 #include <string> 2912 2913 namespace Catch { 2914 2915 class Section : NonCopyable { 2916 public: 2917 Section( SectionInfo const& info ); 2918 ~Section(); 2919 2920 // This indicates whether the section should be executed or not 2921 explicit operator bool() const; 2922 2923 private: 2924 SectionInfo m_info; 2925 2926 std::string m_name; 2927 Counts m_assertions; 2928 bool m_sectionIncluded; 2929 Timer m_timer; 2930 }; 2931 2932 } // end namespace Catch 2933 2934 #define INTERNAL_CATCH_SECTION( ... ) \ 2935 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 2936 CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ 2937 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \ 2938 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 2939 2940 #define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \ 2941 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 2942 CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ 2943 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, (Catch::ReusableStringStream() << __VA_ARGS__).str() ) ) \ 2944 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 2945 2946 // end catch_section.h 2947 // start catch_interfaces_exception.h 2948 2949 // start catch_interfaces_registry_hub.h 2950 2951 #include <string> 2952 #include <memory> 2953 2954 namespace Catch { 2955 2956 class TestCase; 2957 struct ITestCaseRegistry; 2958 struct IExceptionTranslatorRegistry; 2959 struct IExceptionTranslator; 2960 struct IReporterRegistry; 2961 struct IReporterFactory; 2962 struct ITagAliasRegistry; 2963 struct IMutableEnumValuesRegistry; 2964 2965 class StartupExceptionRegistry; 2966 2967 using IReporterFactoryPtr = std::shared_ptr<IReporterFactory>; 2968 2969 struct IRegistryHub { 2970 virtual ~IRegistryHub(); 2971 2972 virtual IReporterRegistry const& getReporterRegistry() const = 0; 2973 virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; 2974 virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0; 2975 virtual IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const = 0; 2976 2977 virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0; 2978 }; 2979 2980 struct IMutableRegistryHub { 2981 virtual ~IMutableRegistryHub(); 2982 virtual void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) = 0; 2983 virtual void registerListener( IReporterFactoryPtr const& factory ) = 0; 2984 virtual void registerTest( TestCase const& testInfo ) = 0; 2985 virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; 2986 virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0; 2987 virtual void registerStartupException() noexcept = 0; 2988 virtual IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() = 0; 2989 }; 2990 2991 IRegistryHub const& getRegistryHub(); 2992 IMutableRegistryHub& getMutableRegistryHub(); 2993 void cleanUp(); 2994 std::string translateActiveException(); 2995 2996 } 2997 2998 // end catch_interfaces_registry_hub.h 2999 #if defined(CATCH_CONFIG_DISABLE) 3000 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( translatorName, signature) \ 3001 static std::string translatorName( signature ) 3002 #endif 3003 3004 #include <exception> 3005 #include <string> 3006 #include <vector> 3007 3008 namespace Catch { 3009 using exceptionTranslateFunction = std::string(*)(); 3010 3011 struct IExceptionTranslator; 3012 using ExceptionTranslators = std::vector<std::unique_ptr<IExceptionTranslator const>>; 3013 3014 struct IExceptionTranslator { 3015 virtual ~IExceptionTranslator(); 3016 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0; 3017 }; 3018 3019 struct IExceptionTranslatorRegistry { 3020 virtual ~IExceptionTranslatorRegistry(); 3021 3022 virtual std::string translateActiveException() const = 0; 3023 }; 3024 3025 class ExceptionTranslatorRegistrar { 3026 template<typename T> 3027 class ExceptionTranslator : public IExceptionTranslator { 3028 public: 3029 3030 ExceptionTranslator( std::string(*translateFunction)( T& ) ) 3031 : m_translateFunction( translateFunction ) 3032 {} 3033 3034 std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override { 3035 #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 3036 return ""; 3037 #else 3038 try { 3039 if( it == itEnd ) 3040 std::rethrow_exception(std::current_exception()); 3041 else 3042 return (*it)->translate( it+1, itEnd ); 3043 } 3044 catch( T& ex ) { 3045 return m_translateFunction( ex ); 3046 } 3047 #endif 3048 } 3049 3050 protected: 3051 std::string(*m_translateFunction)( T& ); 3052 }; 3053 3054 public: 3055 template<typename T> 3056 ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) { 3057 getMutableRegistryHub().registerTranslator 3058 ( new ExceptionTranslator<T>( translateFunction ) ); 3059 } 3060 }; 3061 } 3062 3063 /////////////////////////////////////////////////////////////////////////////// 3064 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \ 3065 static std::string translatorName( signature ); \ 3066 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 3067 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 3068 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); } \ 3069 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 3070 static std::string translatorName( signature ) 3071 3072 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) 3073 3074 // end catch_interfaces_exception.h 3075 // start catch_approx.h 3076 3077 #include <type_traits> 3078 3079 namespace Catch { 3080 namespace Detail { 3081 3082 class Approx { 3083 private: 3084 bool equalityComparisonImpl(double other) const; 3085 // Validates the new margin (margin >= 0) 3086 // out-of-line to avoid including stdexcept in the header 3087 void setMargin(double margin); 3088 // Validates the new epsilon (0 < epsilon < 1) 3089 // out-of-line to avoid including stdexcept in the header 3090 void setEpsilon(double epsilon); 3091 3092 public: 3093 explicit Approx ( double value ); 3094 3095 static Approx custom(); 3096 3097 Approx operator-() const; 3098 3099 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3100 Approx operator()( T const& value ) { 3101 Approx approx( static_cast<double>(value) ); 3102 approx.m_epsilon = m_epsilon; 3103 approx.m_margin = m_margin; 3104 approx.m_scale = m_scale; 3105 return approx; 3106 } 3107 3108 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3109 explicit Approx( T const& value ): Approx(static_cast<double>(value)) 3110 {} 3111 3112 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3113 friend bool operator == ( const T& lhs, Approx const& rhs ) { 3114 auto lhs_v = static_cast<double>(lhs); 3115 return rhs.equalityComparisonImpl(lhs_v); 3116 } 3117 3118 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3119 friend bool operator == ( Approx const& lhs, const T& rhs ) { 3120 return operator==( rhs, lhs ); 3121 } 3122 3123 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3124 friend bool operator != ( T const& lhs, Approx const& rhs ) { 3125 return !operator==( lhs, rhs ); 3126 } 3127 3128 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3129 friend bool operator != ( Approx const& lhs, T const& rhs ) { 3130 return !operator==( rhs, lhs ); 3131 } 3132 3133 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3134 friend bool operator <= ( T const& lhs, Approx const& rhs ) { 3135 return static_cast<double>(lhs) < rhs.m_value || lhs == rhs; 3136 } 3137 3138 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3139 friend bool operator <= ( Approx const& lhs, T const& rhs ) { 3140 return lhs.m_value < static_cast<double>(rhs) || lhs == rhs; 3141 } 3142 3143 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3144 friend bool operator >= ( T const& lhs, Approx const& rhs ) { 3145 return static_cast<double>(lhs) > rhs.m_value || lhs == rhs; 3146 } 3147 3148 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3149 friend bool operator >= ( Approx const& lhs, T const& rhs ) { 3150 return lhs.m_value > static_cast<double>(rhs) || lhs == rhs; 3151 } 3152 3153 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3154 Approx& epsilon( T const& newEpsilon ) { 3155 double epsilonAsDouble = static_cast<double>(newEpsilon); 3156 setEpsilon(epsilonAsDouble); 3157 return *this; 3158 } 3159 3160 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3161 Approx& margin( T const& newMargin ) { 3162 double marginAsDouble = static_cast<double>(newMargin); 3163 setMargin(marginAsDouble); 3164 return *this; 3165 } 3166 3167 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3168 Approx& scale( T const& newScale ) { 3169 m_scale = static_cast<double>(newScale); 3170 return *this; 3171 } 3172 3173 std::string toString() const; 3174 3175 private: 3176 double m_epsilon; 3177 double m_margin; 3178 double m_scale; 3179 double m_value; 3180 }; 3181 } // end namespace Detail 3182 3183 namespace literals { 3184 Detail::Approx operator "" _a(long double val); 3185 Detail::Approx operator "" _a(unsigned long long val); 3186 } // end namespace literals 3187 3188 template<> 3189 struct StringMaker<Catch::Detail::Approx> { 3190 static std::string convert(Catch::Detail::Approx const& value); 3191 }; 3192 3193 } // end namespace Catch 3194 3195 // end catch_approx.h 3196 // start catch_string_manip.h 3197 3198 #include <string> 3199 #include <iosfwd> 3200 #include <vector> 3201 3202 namespace Catch { 3203 3204 bool startsWith( std::string const& s, std::string const& prefix ); 3205 bool startsWith( std::string const& s, char prefix ); 3206 bool endsWith( std::string const& s, std::string const& suffix ); 3207 bool endsWith( std::string const& s, char suffix ); 3208 bool contains( std::string const& s, std::string const& infix ); 3209 void toLowerInPlace( std::string& s ); 3210 std::string toLower( std::string const& s ); 3211 //! Returns a new string without whitespace at the start/end 3212 std::string trim( std::string const& str ); 3213 //! Returns a substring of the original ref without whitespace. Beware lifetimes! 3214 StringRef trim(StringRef ref); 3215 3216 // !!! Be aware, returns refs into original string - make sure original string outlives them 3217 std::vector<StringRef> splitStringRef( StringRef str, char delimiter ); 3218 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ); 3219 3220 struct pluralise { 3221 pluralise( std::size_t count, std::string const& label ); 3222 3223 friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); 3224 3225 std::size_t m_count; 3226 std::string m_label; 3227 }; 3228 } 3229 3230 // end catch_string_manip.h 3231 #ifndef CATCH_CONFIG_DISABLE_MATCHERS 3232 // start catch_capture_matchers.h 3233 3234 // start catch_matchers.h 3235 3236 #include <string> 3237 #include <vector> 3238 3239 namespace Catch { 3240 namespace Matchers { 3241 namespace Impl { 3242 3243 template<typename ArgT> struct MatchAllOf; 3244 template<typename ArgT> struct MatchAnyOf; 3245 template<typename ArgT> struct MatchNotOf; 3246 3247 class MatcherUntypedBase { 3248 public: 3249 MatcherUntypedBase() = default; 3250 MatcherUntypedBase ( MatcherUntypedBase const& ) = default; 3251 MatcherUntypedBase& operator = ( MatcherUntypedBase const& ) = delete; 3252 std::string toString() const; 3253 3254 protected: 3255 virtual ~MatcherUntypedBase(); 3256 virtual std::string describe() const = 0; 3257 mutable std::string m_cachedToString; 3258 }; 3259 3260 #ifdef __clang__ 3261 # pragma clang diagnostic push 3262 # pragma clang diagnostic ignored "-Wnon-virtual-dtor" 3263 #endif 3264 3265 template<typename ObjectT> 3266 struct MatcherMethod { 3267 virtual bool match( ObjectT const& arg ) const = 0; 3268 }; 3269 3270 #if defined(__OBJC__) 3271 // Hack to fix Catch GH issue #1661. Could use id for generic Object support. 3272 // use of const for Object pointers is very uncommon and under ARC it causes some kind of signature mismatch that breaks compilation 3273 template<> 3274 struct MatcherMethod<NSString*> { 3275 virtual bool match( NSString* arg ) const = 0; 3276 }; 3277 #endif 3278 3279 #ifdef __clang__ 3280 # pragma clang diagnostic pop 3281 #endif 3282 3283 template<typename T> 3284 struct MatcherBase : MatcherUntypedBase, MatcherMethod<T> { 3285 3286 MatchAllOf<T> operator && ( MatcherBase const& other ) const; 3287 MatchAnyOf<T> operator || ( MatcherBase const& other ) const; 3288 MatchNotOf<T> operator ! () const; 3289 }; 3290 3291 template<typename ArgT> 3292 struct MatchAllOf : MatcherBase<ArgT> { 3293 bool match( ArgT const& arg ) const override { 3294 for( auto matcher : m_matchers ) { 3295 if (!matcher->match(arg)) 3296 return false; 3297 } 3298 return true; 3299 } 3300 std::string describe() const override { 3301 std::string description; 3302 description.reserve( 4 + m_matchers.size()*32 ); 3303 description += "( "; 3304 bool first = true; 3305 for( auto matcher : m_matchers ) { 3306 if( first ) 3307 first = false; 3308 else 3309 description += " and "; 3310 description += matcher->toString(); 3311 } 3312 description += " )"; 3313 return description; 3314 } 3315 3316 MatchAllOf<ArgT> operator && ( MatcherBase<ArgT> const& other ) { 3317 auto copy(*this); 3318 copy.m_matchers.push_back( &other ); 3319 return copy; 3320 } 3321 3322 std::vector<MatcherBase<ArgT> const*> m_matchers; 3323 }; 3324 template<typename ArgT> 3325 struct MatchAnyOf : MatcherBase<ArgT> { 3326 3327 bool match( ArgT const& arg ) const override { 3328 for( auto matcher : m_matchers ) { 3329 if (matcher->match(arg)) 3330 return true; 3331 } 3332 return false; 3333 } 3334 std::string describe() const override { 3335 std::string description; 3336 description.reserve( 4 + m_matchers.size()*32 ); 3337 description += "( "; 3338 bool first = true; 3339 for( auto matcher : m_matchers ) { 3340 if( first ) 3341 first = false; 3342 else 3343 description += " or "; 3344 description += matcher->toString(); 3345 } 3346 description += " )"; 3347 return description; 3348 } 3349 3350 MatchAnyOf<ArgT> operator || ( MatcherBase<ArgT> const& other ) { 3351 auto copy(*this); 3352 copy.m_matchers.push_back( &other ); 3353 return copy; 3354 } 3355 3356 std::vector<MatcherBase<ArgT> const*> m_matchers; 3357 }; 3358 3359 template<typename ArgT> 3360 struct MatchNotOf : MatcherBase<ArgT> { 3361 3362 MatchNotOf( MatcherBase<ArgT> const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {} 3363 3364 bool match( ArgT const& arg ) const override { 3365 return !m_underlyingMatcher.match( arg ); 3366 } 3367 3368 std::string describe() const override { 3369 return "not " + m_underlyingMatcher.toString(); 3370 } 3371 MatcherBase<ArgT> const& m_underlyingMatcher; 3372 }; 3373 3374 template<typename T> 3375 MatchAllOf<T> MatcherBase<T>::operator && ( MatcherBase const& other ) const { 3376 return MatchAllOf<T>() && *this && other; 3377 } 3378 template<typename T> 3379 MatchAnyOf<T> MatcherBase<T>::operator || ( MatcherBase const& other ) const { 3380 return MatchAnyOf<T>() || *this || other; 3381 } 3382 template<typename T> 3383 MatchNotOf<T> MatcherBase<T>::operator ! () const { 3384 return MatchNotOf<T>( *this ); 3385 } 3386 3387 } // namespace Impl 3388 3389 } // namespace Matchers 3390 3391 using namespace Matchers; 3392 using Matchers::Impl::MatcherBase; 3393 3394 } // namespace Catch 3395 3396 // end catch_matchers.h 3397 // start catch_matchers_exception.hpp 3398 3399 namespace Catch { 3400 namespace Matchers { 3401 namespace Exception { 3402 3403 class ExceptionMessageMatcher : public MatcherBase<std::exception> { 3404 std::string m_message; 3405 public: 3406 3407 ExceptionMessageMatcher(std::string const& message): 3408 m_message(message) 3409 {} 3410 3411 bool match(std::exception const& ex) const override; 3412 3413 std::string describe() const override; 3414 }; 3415 3416 } // namespace Exception 3417 3418 Exception::ExceptionMessageMatcher Message(std::string const& message); 3419 3420 } // namespace Matchers 3421 } // namespace Catch 3422 3423 // end catch_matchers_exception.hpp 3424 // start catch_matchers_floating.h 3425 3426 namespace Catch { 3427 namespace Matchers { 3428 3429 namespace Floating { 3430 3431 enum class FloatingPointKind : uint8_t; 3432 3433 struct WithinAbsMatcher : MatcherBase<double> { 3434 WithinAbsMatcher(double target, double margin); 3435 bool match(double const& matchee) const override; 3436 std::string describe() const override; 3437 private: 3438 double m_target; 3439 double m_margin; 3440 }; 3441 3442 struct WithinUlpsMatcher : MatcherBase<double> { 3443 WithinUlpsMatcher(double target, uint64_t ulps, FloatingPointKind baseType); 3444 bool match(double const& matchee) const override; 3445 std::string describe() const override; 3446 private: 3447 double m_target; 3448 uint64_t m_ulps; 3449 FloatingPointKind m_type; 3450 }; 3451 3452 // Given IEEE-754 format for floats and doubles, we can assume 3453 // that float -> double promotion is lossless. Given this, we can 3454 // assume that if we do the standard relative comparison of 3455 // |lhs - rhs| <= epsilon * max(fabs(lhs), fabs(rhs)), then we get 3456 // the same result if we do this for floats, as if we do this for 3457 // doubles that were promoted from floats. 3458 struct WithinRelMatcher : MatcherBase<double> { 3459 WithinRelMatcher(double target, double epsilon); 3460 bool match(double const& matchee) const override; 3461 std::string describe() const override; 3462 private: 3463 double m_target; 3464 double m_epsilon; 3465 }; 3466 3467 } // namespace Floating 3468 3469 // The following functions create the actual matcher objects. 3470 // This allows the types to be inferred 3471 Floating::WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff); 3472 Floating::WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff); 3473 Floating::WithinAbsMatcher WithinAbs(double target, double margin); 3474 Floating::WithinRelMatcher WithinRel(double target, double eps); 3475 // defaults epsilon to 100*numeric_limits<double>::epsilon() 3476 Floating::WithinRelMatcher WithinRel(double target); 3477 Floating::WithinRelMatcher WithinRel(float target, float eps); 3478 // defaults epsilon to 100*numeric_limits<float>::epsilon() 3479 Floating::WithinRelMatcher WithinRel(float target); 3480 3481 } // namespace Matchers 3482 } // namespace Catch 3483 3484 // end catch_matchers_floating.h 3485 // start catch_matchers_generic.hpp 3486 3487 #include <functional> 3488 #include <string> 3489 3490 namespace Catch { 3491 namespace Matchers { 3492 namespace Generic { 3493 3494 namespace Detail { 3495 std::string finalizeDescription(const std::string& desc); 3496 } 3497 3498 template <typename T> 3499 class PredicateMatcher : public MatcherBase<T> { 3500 std::function<bool(T const&)> m_predicate; 3501 std::string m_description; 3502 public: 3503 3504 PredicateMatcher(std::function<bool(T const&)> const& elem, std::string const& descr) 3505 :m_predicate(std::move(elem)), 3506 m_description(Detail::finalizeDescription(descr)) 3507 {} 3508 3509 bool match( T const& item ) const override { 3510 return m_predicate(item); 3511 } 3512 3513 std::string describe() const override { 3514 return m_description; 3515 } 3516 }; 3517 3518 } // namespace Generic 3519 3520 // The following functions create the actual matcher objects. 3521 // The user has to explicitly specify type to the function, because 3522 // inferring std::function<bool(T const&)> is hard (but possible) and 3523 // requires a lot of TMP. 3524 template<typename T> 3525 Generic::PredicateMatcher<T> Predicate(std::function<bool(T const&)> const& predicate, std::string const& description = "") { 3526 return Generic::PredicateMatcher<T>(predicate, description); 3527 } 3528 3529 } // namespace Matchers 3530 } // namespace Catch 3531 3532 // end catch_matchers_generic.hpp 3533 // start catch_matchers_string.h 3534 3535 #include <string> 3536 3537 namespace Catch { 3538 namespace Matchers { 3539 3540 namespace StdString { 3541 3542 struct CasedString 3543 { 3544 CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ); 3545 std::string adjustString( std::string const& str ) const; 3546 std::string caseSensitivitySuffix() const; 3547 3548 CaseSensitive::Choice m_caseSensitivity; 3549 std::string m_str; 3550 }; 3551 3552 struct StringMatcherBase : MatcherBase<std::string> { 3553 StringMatcherBase( std::string const& operation, CasedString const& comparator ); 3554 std::string describe() const override; 3555 3556 CasedString m_comparator; 3557 std::string m_operation; 3558 }; 3559 3560 struct EqualsMatcher : StringMatcherBase { 3561 EqualsMatcher( CasedString const& comparator ); 3562 bool match( std::string const& source ) const override; 3563 }; 3564 struct ContainsMatcher : StringMatcherBase { 3565 ContainsMatcher( CasedString const& comparator ); 3566 bool match( std::string const& source ) const override; 3567 }; 3568 struct StartsWithMatcher : StringMatcherBase { 3569 StartsWithMatcher( CasedString const& comparator ); 3570 bool match( std::string const& source ) const override; 3571 }; 3572 struct EndsWithMatcher : StringMatcherBase { 3573 EndsWithMatcher( CasedString const& comparator ); 3574 bool match( std::string const& source ) const override; 3575 }; 3576 3577 struct RegexMatcher : MatcherBase<std::string> { 3578 RegexMatcher( std::string regex, CaseSensitive::Choice caseSensitivity ); 3579 bool match( std::string const& matchee ) const override; 3580 std::string describe() const override; 3581 3582 private: 3583 std::string m_regex; 3584 CaseSensitive::Choice m_caseSensitivity; 3585 }; 3586 3587 } // namespace StdString 3588 3589 // The following functions create the actual matcher objects. 3590 // This allows the types to be inferred 3591 3592 StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); 3593 StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); 3594 StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); 3595 StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); 3596 StdString::RegexMatcher Matches( std::string const& regex, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); 3597 3598 } // namespace Matchers 3599 } // namespace Catch 3600 3601 // end catch_matchers_string.h 3602 // start catch_matchers_vector.h 3603 3604 #include <algorithm> 3605 3606 namespace Catch { 3607 namespace Matchers { 3608 3609 namespace Vector { 3610 template<typename T, typename Alloc> 3611 struct ContainsElementMatcher : MatcherBase<std::vector<T, Alloc>> { 3612 3613 ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {} 3614 3615 bool match(std::vector<T, Alloc> const &v) const override { 3616 for (auto const& el : v) { 3617 if (el == m_comparator) { 3618 return true; 3619 } 3620 } 3621 return false; 3622 } 3623 3624 std::string describe() const override { 3625 return "Contains: " + ::Catch::Detail::stringify( m_comparator ); 3626 } 3627 3628 T const& m_comparator; 3629 }; 3630 3631 template<typename T, typename AllocComp, typename AllocMatch> 3632 struct ContainsMatcher : MatcherBase<std::vector<T, AllocMatch>> { 3633 3634 ContainsMatcher(std::vector<T, AllocComp> const &comparator) : m_comparator( comparator ) {} 3635 3636 bool match(std::vector<T, AllocMatch> const &v) const override { 3637 // !TBD: see note in EqualsMatcher 3638 if (m_comparator.size() > v.size()) 3639 return false; 3640 for (auto const& comparator : m_comparator) { 3641 auto present = false; 3642 for (const auto& el : v) { 3643 if (el == comparator) { 3644 present = true; 3645 break; 3646 } 3647 } 3648 if (!present) { 3649 return false; 3650 } 3651 } 3652 return true; 3653 } 3654 std::string describe() const override { 3655 return "Contains: " + ::Catch::Detail::stringify( m_comparator ); 3656 } 3657 3658 std::vector<T, AllocComp> const& m_comparator; 3659 }; 3660 3661 template<typename T, typename AllocComp, typename AllocMatch> 3662 struct EqualsMatcher : MatcherBase<std::vector<T, AllocMatch>> { 3663 3664 EqualsMatcher(std::vector<T, AllocComp> const &comparator) : m_comparator( comparator ) {} 3665 3666 bool match(std::vector<T, AllocMatch> const &v) const override { 3667 // !TBD: This currently works if all elements can be compared using != 3668 // - a more general approach would be via a compare template that defaults 3669 // to using !=. but could be specialised for, e.g. std::vector<T, Alloc> etc 3670 // - then just call that directly 3671 if (m_comparator.size() != v.size()) 3672 return false; 3673 for (std::size_t i = 0; i < v.size(); ++i) 3674 if (m_comparator[i] != v[i]) 3675 return false; 3676 return true; 3677 } 3678 std::string describe() const override { 3679 return "Equals: " + ::Catch::Detail::stringify( m_comparator ); 3680 } 3681 std::vector<T, AllocComp> const& m_comparator; 3682 }; 3683 3684 template<typename T, typename AllocComp, typename AllocMatch> 3685 struct ApproxMatcher : MatcherBase<std::vector<T, AllocMatch>> { 3686 3687 ApproxMatcher(std::vector<T, AllocComp> const& comparator) : m_comparator( comparator ) {} 3688 3689 bool match(std::vector<T, AllocMatch> const &v) const override { 3690 if (m_comparator.size() != v.size()) 3691 return false; 3692 for (std::size_t i = 0; i < v.size(); ++i) 3693 if (m_comparator[i] != approx(v[i])) 3694 return false; 3695 return true; 3696 } 3697 std::string describe() const override { 3698 return "is approx: " + ::Catch::Detail::stringify( m_comparator ); 3699 } 3700 template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3701 ApproxMatcher& epsilon( T const& newEpsilon ) { 3702 approx.epsilon(newEpsilon); 3703 return *this; 3704 } 3705 template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3706 ApproxMatcher& margin( T const& newMargin ) { 3707 approx.margin(newMargin); 3708 return *this; 3709 } 3710 template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3711 ApproxMatcher& scale( T const& newScale ) { 3712 approx.scale(newScale); 3713 return *this; 3714 } 3715 3716 std::vector<T, AllocComp> const& m_comparator; 3717 mutable Catch::Detail::Approx approx = Catch::Detail::Approx::custom(); 3718 }; 3719 3720 template<typename T, typename AllocComp, typename AllocMatch> 3721 struct UnorderedEqualsMatcher : MatcherBase<std::vector<T, AllocMatch>> { 3722 UnorderedEqualsMatcher(std::vector<T, AllocComp> const& target) : m_target(target) {} 3723 bool match(std::vector<T, AllocMatch> const& vec) const override { 3724 if (m_target.size() != vec.size()) { 3725 return false; 3726 } 3727 return std::is_permutation(m_target.begin(), m_target.end(), vec.begin()); 3728 } 3729 3730 std::string describe() const override { 3731 return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target); 3732 } 3733 private: 3734 std::vector<T, AllocComp> const& m_target; 3735 }; 3736 3737 } // namespace Vector 3738 3739 // The following functions create the actual matcher objects. 3740 // This allows the types to be inferred 3741 3742 template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp> 3743 Vector::ContainsMatcher<T, AllocComp, AllocMatch> Contains( std::vector<T, AllocComp> const& comparator ) { 3744 return Vector::ContainsMatcher<T, AllocComp, AllocMatch>( comparator ); 3745 } 3746 3747 template<typename T, typename Alloc = std::allocator<T>> 3748 Vector::ContainsElementMatcher<T, Alloc> VectorContains( T const& comparator ) { 3749 return Vector::ContainsElementMatcher<T, Alloc>( comparator ); 3750 } 3751 3752 template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp> 3753 Vector::EqualsMatcher<T, AllocComp, AllocMatch> Equals( std::vector<T, AllocComp> const& comparator ) { 3754 return Vector::EqualsMatcher<T, AllocComp, AllocMatch>( comparator ); 3755 } 3756 3757 template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp> 3758 Vector::ApproxMatcher<T, AllocComp, AllocMatch> Approx( std::vector<T, AllocComp> const& comparator ) { 3759 return Vector::ApproxMatcher<T, AllocComp, AllocMatch>( comparator ); 3760 } 3761 3762 template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp> 3763 Vector::UnorderedEqualsMatcher<T, AllocComp, AllocMatch> UnorderedEquals(std::vector<T, AllocComp> const& target) { 3764 return Vector::UnorderedEqualsMatcher<T, AllocComp, AllocMatch>( target ); 3765 } 3766 3767 } // namespace Matchers 3768 } // namespace Catch 3769 3770 // end catch_matchers_vector.h 3771 namespace Catch { 3772 3773 template<typename ArgT, typename MatcherT> 3774 class MatchExpr : public ITransientExpression { 3775 ArgT const& m_arg; 3776 MatcherT m_matcher; 3777 StringRef m_matcherString; 3778 public: 3779 MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString ) 3780 : ITransientExpression{ true, matcher.match( arg ) }, 3781 m_arg( arg ), 3782 m_matcher( matcher ), 3783 m_matcherString( matcherString ) 3784 {} 3785 3786 void streamReconstructedExpression( std::ostream &os ) const override { 3787 auto matcherAsString = m_matcher.toString(); 3788 os << Catch::Detail::stringify( m_arg ) << ' '; 3789 if( matcherAsString == Detail::unprintableString ) 3790 os << m_matcherString; 3791 else 3792 os << matcherAsString; 3793 } 3794 }; 3795 3796 using StringMatcher = Matchers::Impl::MatcherBase<std::string>; 3797 3798 void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString ); 3799 3800 template<typename ArgT, typename MatcherT> 3801 auto makeMatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString ) -> MatchExpr<ArgT, MatcherT> { 3802 return MatchExpr<ArgT, MatcherT>( arg, matcher, matcherString ); 3803 } 3804 3805 } // namespace Catch 3806 3807 /////////////////////////////////////////////////////////////////////////////// 3808 #define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ 3809 do { \ 3810 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ 3811 INTERNAL_CATCH_TRY { \ 3812 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher, #matcher##_catch_sr ) ); \ 3813 } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ 3814 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 3815 } while( false ) 3816 3817 /////////////////////////////////////////////////////////////////////////////// 3818 #define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \ 3819 do { \ 3820 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ 3821 if( catchAssertionHandler.allowThrows() ) \ 3822 try { \ 3823 static_cast<void>(__VA_ARGS__ ); \ 3824 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 3825 } \ 3826 catch( exceptionType const& ex ) { \ 3827 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( ex, matcher, #matcher##_catch_sr ) ); \ 3828 } \ 3829 catch( ... ) { \ 3830 catchAssertionHandler.handleUnexpectedInflightException(); \ 3831 } \ 3832 else \ 3833 catchAssertionHandler.handleThrowingCallSkipped(); \ 3834 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 3835 } while( false ) 3836 3837 // end catch_capture_matchers.h 3838 #endif 3839 // start catch_generators.hpp 3840 3841 // start catch_interfaces_generatortracker.h 3842 3843 3844 #include <memory> 3845 3846 namespace Catch { 3847 3848 namespace Generators { 3849 class GeneratorUntypedBase { 3850 public: 3851 GeneratorUntypedBase() = default; 3852 virtual ~GeneratorUntypedBase(); 3853 // Attempts to move the generator to the next element 3854 // 3855 // Returns true iff the move succeeded (and a valid element 3856 // can be retrieved). 3857 virtual bool next() = 0; 3858 }; 3859 using GeneratorBasePtr = std::unique_ptr<GeneratorUntypedBase>; 3860 3861 } // namespace Generators 3862 3863 struct IGeneratorTracker { 3864 virtual ~IGeneratorTracker(); 3865 virtual auto hasGenerator() const -> bool = 0; 3866 virtual auto getGenerator() const -> Generators::GeneratorBasePtr const& = 0; 3867 virtual void setGenerator( Generators::GeneratorBasePtr&& generator ) = 0; 3868 }; 3869 3870 } // namespace Catch 3871 3872 // end catch_interfaces_generatortracker.h 3873 // start catch_enforce.h 3874 3875 #include <exception> 3876 3877 namespace Catch { 3878 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 3879 template <typename Ex> 3880 [[noreturn]] 3881 void throw_exception(Ex const& e) { 3882 throw e; 3883 } 3884 #else // ^^ Exceptions are enabled // Exceptions are disabled vv 3885 [[noreturn]] 3886 void throw_exception(std::exception const& e); 3887 #endif 3888 3889 [[noreturn]] 3890 void throw_logic_error(std::string const& msg); 3891 [[noreturn]] 3892 void throw_domain_error(std::string const& msg); 3893 [[noreturn]] 3894 void throw_runtime_error(std::string const& msg); 3895 3896 } // namespace Catch; 3897 3898 #define CATCH_MAKE_MSG(...) \ 3899 (Catch::ReusableStringStream() << __VA_ARGS__).str() 3900 3901 #define CATCH_INTERNAL_ERROR(...) \ 3902 Catch::throw_logic_error(CATCH_MAKE_MSG( CATCH_INTERNAL_LINEINFO << ": Internal Catch2 error: " << __VA_ARGS__)) 3903 3904 #define CATCH_ERROR(...) \ 3905 Catch::throw_domain_error(CATCH_MAKE_MSG( __VA_ARGS__ )) 3906 3907 #define CATCH_RUNTIME_ERROR(...) \ 3908 Catch::throw_runtime_error(CATCH_MAKE_MSG( __VA_ARGS__ )) 3909 3910 #define CATCH_ENFORCE( condition, ... ) \ 3911 do{ if( !(condition) ) CATCH_ERROR( __VA_ARGS__ ); } while(false) 3912 3913 // end catch_enforce.h 3914 #include <memory> 3915 #include <vector> 3916 #include <cassert> 3917 3918 #include <utility> 3919 #include <exception> 3920 3921 namespace Catch { 3922 3923 class GeneratorException : public std::exception { 3924 const char* const m_msg = ""; 3925 3926 public: 3927 GeneratorException(const char* msg): 3928 m_msg(msg) 3929 {} 3930 3931 const char* what() const noexcept override final; 3932 }; 3933 3934 namespace Generators { 3935 3936 // !TBD move this into its own location? 3937 namespace pf{ 3938 template<typename T, typename... Args> 3939 std::unique_ptr<T> make_unique( Args&&... args ) { 3940 return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); 3941 } 3942 } 3943 3944 template<typename T> 3945 struct IGenerator : GeneratorUntypedBase { 3946 virtual ~IGenerator() = default; 3947 3948 // Returns the current element of the generator 3949 // 3950 // \Precondition The generator is either freshly constructed, 3951 // or the last call to `next()` returned true 3952 virtual T const& get() const = 0; 3953 using type = T; 3954 }; 3955 3956 template<typename T> 3957 class SingleValueGenerator final : public IGenerator<T> { 3958 T m_value; 3959 public: 3960 SingleValueGenerator(T&& value) : m_value(std::move(value)) {} 3961 3962 T const& get() const override { 3963 return m_value; 3964 } 3965 bool next() override { 3966 return false; 3967 } 3968 }; 3969 3970 template<typename T> 3971 class FixedValuesGenerator final : public IGenerator<T> { 3972 static_assert(!std::is_same<T, bool>::value, 3973 "FixedValuesGenerator does not support bools because of std::vector<bool>" 3974 "specialization, use SingleValue Generator instead."); 3975 std::vector<T> m_values; 3976 size_t m_idx = 0; 3977 public: 3978 FixedValuesGenerator( std::initializer_list<T> values ) : m_values( values ) {} 3979 3980 T const& get() const override { 3981 return m_values[m_idx]; 3982 } 3983 bool next() override { 3984 ++m_idx; 3985 return m_idx < m_values.size(); 3986 } 3987 }; 3988 3989 template <typename T> 3990 class GeneratorWrapper final { 3991 std::unique_ptr<IGenerator<T>> m_generator; 3992 public: 3993 GeneratorWrapper(std::unique_ptr<IGenerator<T>> generator): 3994 m_generator(std::move(generator)) 3995 {} 3996 T const& get() const { 3997 return m_generator->get(); 3998 } 3999 bool next() { 4000 return m_generator->next(); 4001 } 4002 }; 4003 4004 template <typename T> 4005 GeneratorWrapper<T> value(T&& value) { 4006 return GeneratorWrapper<T>(pf::make_unique<SingleValueGenerator<T>>(std::forward<T>(value))); 4007 } 4008 template <typename T> 4009 GeneratorWrapper<T> values(std::initializer_list<T> values) { 4010 return GeneratorWrapper<T>(pf::make_unique<FixedValuesGenerator<T>>(values)); 4011 } 4012 4013 template<typename T> 4014 class Generators : public IGenerator<T> { 4015 std::vector<GeneratorWrapper<T>> m_generators; 4016 size_t m_current = 0; 4017 4018 void populate(GeneratorWrapper<T>&& generator) { 4019 m_generators.emplace_back(std::move(generator)); 4020 } 4021 void populate(T&& val) { 4022 m_generators.emplace_back(value(std::forward<T>(val))); 4023 } 4024 template<typename U> 4025 void populate(U&& val) { 4026 populate(T(std::forward<U>(val))); 4027 } 4028 template<typename U, typename... Gs> 4029 void populate(U&& valueOrGenerator, Gs &&... moreGenerators) { 4030 populate(std::forward<U>(valueOrGenerator)); 4031 populate(std::forward<Gs>(moreGenerators)...); 4032 } 4033 4034 public: 4035 template <typename... Gs> 4036 Generators(Gs &&... moreGenerators) { 4037 m_generators.reserve(sizeof...(Gs)); 4038 populate(std::forward<Gs>(moreGenerators)...); 4039 } 4040 4041 T const& get() const override { 4042 return m_generators[m_current].get(); 4043 } 4044 4045 bool next() override { 4046 if (m_current >= m_generators.size()) { 4047 return false; 4048 } 4049 const bool current_status = m_generators[m_current].next(); 4050 if (!current_status) { 4051 ++m_current; 4052 } 4053 return m_current < m_generators.size(); 4054 } 4055 }; 4056 4057 template<typename... Ts> 4058 GeneratorWrapper<std::tuple<Ts...>> table( std::initializer_list<std::tuple<typename std::decay<Ts>::type...>> tuples ) { 4059 return values<std::tuple<Ts...>>( tuples ); 4060 } 4061 4062 // Tag type to signal that a generator sequence should convert arguments to a specific type 4063 template <typename T> 4064 struct as {}; 4065 4066 template<typename T, typename... Gs> 4067 auto makeGenerators( GeneratorWrapper<T>&& generator, Gs &&... moreGenerators ) -> Generators<T> { 4068 return Generators<T>(std::move(generator), std::forward<Gs>(moreGenerators)...); 4069 } 4070 template<typename T> 4071 auto makeGenerators( GeneratorWrapper<T>&& generator ) -> Generators<T> { 4072 return Generators<T>(std::move(generator)); 4073 } 4074 template<typename T, typename... Gs> 4075 auto makeGenerators( T&& val, Gs &&... moreGenerators ) -> Generators<T> { 4076 return makeGenerators( value( std::forward<T>( val ) ), std::forward<Gs>( moreGenerators )... ); 4077 } 4078 template<typename T, typename U, typename... Gs> 4079 auto makeGenerators( as<T>, U&& val, Gs &&... moreGenerators ) -> Generators<T> { 4080 return makeGenerators( value( T( std::forward<U>( val ) ) ), std::forward<Gs>( moreGenerators )... ); 4081 } 4082 4083 auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker&; 4084 4085 template<typename L> 4086 // Note: The type after -> is weird, because VS2015 cannot parse 4087 // the expression used in the typedef inside, when it is in 4088 // return type. Yeah. 4089 auto generate( StringRef generatorName, SourceLineInfo const& lineInfo, L const& generatorExpression ) -> decltype(std::declval<decltype(generatorExpression())>().get()) { 4090 using UnderlyingType = typename decltype(generatorExpression())::type; 4091 4092 IGeneratorTracker& tracker = acquireGeneratorTracker( generatorName, lineInfo ); 4093 if (!tracker.hasGenerator()) { 4094 tracker.setGenerator(pf::make_unique<Generators<UnderlyingType>>(generatorExpression())); 4095 } 4096 4097 auto const& generator = static_cast<IGenerator<UnderlyingType> const&>( *tracker.getGenerator() ); 4098 return generator.get(); 4099 } 4100 4101 } // namespace Generators 4102 } // namespace Catch 4103 4104 #define GENERATE( ... ) \ 4105 Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \ 4106 CATCH_INTERNAL_LINEINFO, \ 4107 [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace) 4108 #define GENERATE_COPY( ... ) \ 4109 Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \ 4110 CATCH_INTERNAL_LINEINFO, \ 4111 [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace) 4112 #define GENERATE_REF( ... ) \ 4113 Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \ 4114 CATCH_INTERNAL_LINEINFO, \ 4115 [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace) 4116 4117 // end catch_generators.hpp 4118 // start catch_generators_generic.hpp 4119 4120 namespace Catch { 4121 namespace Generators { 4122 4123 template <typename T> 4124 class TakeGenerator : public IGenerator<T> { 4125 GeneratorWrapper<T> m_generator; 4126 size_t m_returned = 0; 4127 size_t m_target; 4128 public: 4129 TakeGenerator(size_t target, GeneratorWrapper<T>&& generator): 4130 m_generator(std::move(generator)), 4131 m_target(target) 4132 { 4133 assert(target != 0 && "Empty generators are not allowed"); 4134 } 4135 T const& get() const override { 4136 return m_generator.get(); 4137 } 4138 bool next() override { 4139 ++m_returned; 4140 if (m_returned >= m_target) { 4141 return false; 4142 } 4143 4144 const auto success = m_generator.next(); 4145 // If the underlying generator does not contain enough values 4146 // then we cut short as well 4147 if (!success) { 4148 m_returned = m_target; 4149 } 4150 return success; 4151 } 4152 }; 4153 4154 template <typename T> 4155 GeneratorWrapper<T> take(size_t target, GeneratorWrapper<T>&& generator) { 4156 return GeneratorWrapper<T>(pf::make_unique<TakeGenerator<T>>(target, std::move(generator))); 4157 } 4158 4159 template <typename T, typename Predicate> 4160 class FilterGenerator : public IGenerator<T> { 4161 GeneratorWrapper<T> m_generator; 4162 Predicate m_predicate; 4163 public: 4164 template <typename P = Predicate> 4165 FilterGenerator(P&& pred, GeneratorWrapper<T>&& generator): 4166 m_generator(std::move(generator)), 4167 m_predicate(std::forward<P>(pred)) 4168 { 4169 if (!m_predicate(m_generator.get())) { 4170 // It might happen that there are no values that pass the 4171 // filter. In that case we throw an exception. 4172 auto has_initial_value = next(); 4173 if (!has_initial_value) { 4174 Catch::throw_exception(GeneratorException("No valid value found in filtered generator")); 4175 } 4176 } 4177 } 4178 4179 T const& get() const override { 4180 return m_generator.get(); 4181 } 4182 4183 bool next() override { 4184 bool success = m_generator.next(); 4185 if (!success) { 4186 return false; 4187 } 4188 while (!m_predicate(m_generator.get()) && (success = m_generator.next()) == true); 4189 return success; 4190 } 4191 }; 4192 4193 template <typename T, typename Predicate> 4194 GeneratorWrapper<T> filter(Predicate&& pred, GeneratorWrapper<T>&& generator) { 4195 return GeneratorWrapper<T>(std::unique_ptr<IGenerator<T>>(pf::make_unique<FilterGenerator<T, Predicate>>(std::forward<Predicate>(pred), std::move(generator)))); 4196 } 4197 4198 template <typename T> 4199 class RepeatGenerator : public IGenerator<T> { 4200 static_assert(!std::is_same<T, bool>::value, 4201 "RepeatGenerator currently does not support bools" 4202 "because of std::vector<bool> specialization"); 4203 GeneratorWrapper<T> m_generator; 4204 mutable std::vector<T> m_returned; 4205 size_t m_target_repeats; 4206 size_t m_current_repeat = 0; 4207 size_t m_repeat_index = 0; 4208 public: 4209 RepeatGenerator(size_t repeats, GeneratorWrapper<T>&& generator): 4210 m_generator(std::move(generator)), 4211 m_target_repeats(repeats) 4212 { 4213 assert(m_target_repeats > 0 && "Repeat generator must repeat at least once"); 4214 } 4215 4216 T const& get() const override { 4217 if (m_current_repeat == 0) { 4218 m_returned.push_back(m_generator.get()); 4219 return m_returned.back(); 4220 } 4221 return m_returned[m_repeat_index]; 4222 } 4223 4224 bool next() override { 4225 // There are 2 basic cases: 4226 // 1) We are still reading the generator 4227 // 2) We are reading our own cache 4228 4229 // In the first case, we need to poke the underlying generator. 4230 // If it happily moves, we are left in that state, otherwise it is time to start reading from our cache 4231 if (m_current_repeat == 0) { 4232 const auto success = m_generator.next(); 4233 if (!success) { 4234 ++m_current_repeat; 4235 } 4236 return m_current_repeat < m_target_repeats; 4237 } 4238 4239 // In the second case, we need to move indices forward and check that we haven't run up against the end 4240 ++m_repeat_index; 4241 if (m_repeat_index == m_returned.size()) { 4242 m_repeat_index = 0; 4243 ++m_current_repeat; 4244 } 4245 return m_current_repeat < m_target_repeats; 4246 } 4247 }; 4248 4249 template <typename T> 4250 GeneratorWrapper<T> repeat(size_t repeats, GeneratorWrapper<T>&& generator) { 4251 return GeneratorWrapper<T>(pf::make_unique<RepeatGenerator<T>>(repeats, std::move(generator))); 4252 } 4253 4254 template <typename T, typename U, typename Func> 4255 class MapGenerator : public IGenerator<T> { 4256 // TBD: provide static assert for mapping function, for friendly error message 4257 GeneratorWrapper<U> m_generator; 4258 Func m_function; 4259 // To avoid returning dangling reference, we have to save the values 4260 T m_cache; 4261 public: 4262 template <typename F2 = Func> 4263 MapGenerator(F2&& function, GeneratorWrapper<U>&& generator) : 4264 m_generator(std::move(generator)), 4265 m_function(std::forward<F2>(function)), 4266 m_cache(m_function(m_generator.get())) 4267 {} 4268 4269 T const& get() const override { 4270 return m_cache; 4271 } 4272 bool next() override { 4273 const auto success = m_generator.next(); 4274 if (success) { 4275 m_cache = m_function(m_generator.get()); 4276 } 4277 return success; 4278 } 4279 }; 4280 4281 template <typename Func, typename U, typename T = FunctionReturnType<Func, U>> 4282 GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) { 4283 return GeneratorWrapper<T>( 4284 pf::make_unique<MapGenerator<T, U, Func>>(std::forward<Func>(function), std::move(generator)) 4285 ); 4286 } 4287 4288 template <typename T, typename U, typename Func> 4289 GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) { 4290 return GeneratorWrapper<T>( 4291 pf::make_unique<MapGenerator<T, U, Func>>(std::forward<Func>(function), std::move(generator)) 4292 ); 4293 } 4294 4295 template <typename T> 4296 class ChunkGenerator final : public IGenerator<std::vector<T>> { 4297 std::vector<T> m_chunk; 4298 size_t m_chunk_size; 4299 GeneratorWrapper<T> m_generator; 4300 bool m_used_up = false; 4301 public: 4302 ChunkGenerator(size_t size, GeneratorWrapper<T> generator) : 4303 m_chunk_size(size), m_generator(std::move(generator)) 4304 { 4305 m_chunk.reserve(m_chunk_size); 4306 if (m_chunk_size != 0) { 4307 m_chunk.push_back(m_generator.get()); 4308 for (size_t i = 1; i < m_chunk_size; ++i) { 4309 if (!m_generator.next()) { 4310 Catch::throw_exception(GeneratorException("Not enough values to initialize the first chunk")); 4311 } 4312 m_chunk.push_back(m_generator.get()); 4313 } 4314 } 4315 } 4316 std::vector<T> const& get() const override { 4317 return m_chunk; 4318 } 4319 bool next() override { 4320 m_chunk.clear(); 4321 for (size_t idx = 0; idx < m_chunk_size; ++idx) { 4322 if (!m_generator.next()) { 4323 return false; 4324 } 4325 m_chunk.push_back(m_generator.get()); 4326 } 4327 return true; 4328 } 4329 }; 4330 4331 template <typename T> 4332 GeneratorWrapper<std::vector<T>> chunk(size_t size, GeneratorWrapper<T>&& generator) { 4333 return GeneratorWrapper<std::vector<T>>( 4334 pf::make_unique<ChunkGenerator<T>>(size, std::move(generator)) 4335 ); 4336 } 4337 4338 } // namespace Generators 4339 } // namespace Catch 4340 4341 // end catch_generators_generic.hpp 4342 // start catch_generators_specific.hpp 4343 4344 // start catch_context.h 4345 4346 #include <memory> 4347 4348 namespace Catch { 4349 4350 struct IResultCapture; 4351 struct IRunner; 4352 struct IConfig; 4353 struct IMutableContext; 4354 4355 using IConfigPtr = std::shared_ptr<IConfig const>; 4356 4357 struct IContext 4358 { 4359 virtual ~IContext(); 4360 4361 virtual IResultCapture* getResultCapture() = 0; 4362 virtual IRunner* getRunner() = 0; 4363 virtual IConfigPtr const& getConfig() const = 0; 4364 }; 4365 4366 struct IMutableContext : IContext 4367 { 4368 virtual ~IMutableContext(); 4369 virtual void setResultCapture( IResultCapture* resultCapture ) = 0; 4370 virtual void setRunner( IRunner* runner ) = 0; 4371 virtual void setConfig( IConfigPtr const& config ) = 0; 4372 4373 private: 4374 static IMutableContext *currentContext; 4375 friend IMutableContext& getCurrentMutableContext(); 4376 friend void cleanUpContext(); 4377 static void createContext(); 4378 }; 4379 4380 inline IMutableContext& getCurrentMutableContext() 4381 { 4382 if( !IMutableContext::currentContext ) 4383 IMutableContext::createContext(); 4384 // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn) 4385 return *IMutableContext::currentContext; 4386 } 4387 4388 inline IContext& getCurrentContext() 4389 { 4390 return getCurrentMutableContext(); 4391 } 4392 4393 void cleanUpContext(); 4394 4395 class SimplePcg32; 4396 SimplePcg32& rng(); 4397 } 4398 4399 // end catch_context.h 4400 // start catch_interfaces_config.h 4401 4402 // start catch_option.hpp 4403 4404 namespace Catch { 4405 4406 // An optional type 4407 template<typename T> 4408 class Option { 4409 public: 4410 Option() : nullableValue( nullptr ) {} 4411 Option( T const& _value ) 4412 : nullableValue( new( storage ) T( _value ) ) 4413 {} 4414 Option( Option const& _other ) 4415 : nullableValue( _other ? new( storage ) T( *_other ) : nullptr ) 4416 {} 4417 4418 ~Option() { 4419 reset(); 4420 } 4421 4422 Option& operator= ( Option const& _other ) { 4423 if( &_other != this ) { 4424 reset(); 4425 if( _other ) 4426 nullableValue = new( storage ) T( *_other ); 4427 } 4428 return *this; 4429 } 4430 Option& operator = ( T const& _value ) { 4431 reset(); 4432 nullableValue = new( storage ) T( _value ); 4433 return *this; 4434 } 4435 4436 void reset() { 4437 if( nullableValue ) 4438 nullableValue->~T(); 4439 nullableValue = nullptr; 4440 } 4441 4442 T& operator*() { return *nullableValue; } 4443 T const& operator*() const { return *nullableValue; } 4444 T* operator->() { return nullableValue; } 4445 const T* operator->() const { return nullableValue; } 4446 4447 T valueOr( T const& defaultValue ) const { 4448 return nullableValue ? *nullableValue : defaultValue; 4449 } 4450 4451 bool some() const { return nullableValue != nullptr; } 4452 bool none() const { return nullableValue == nullptr; } 4453 4454 bool operator !() const { return nullableValue == nullptr; } 4455 explicit operator bool() const { 4456 return some(); 4457 } 4458 4459 private: 4460 T *nullableValue; 4461 alignas(alignof(T)) char storage[sizeof(T)]; 4462 }; 4463 4464 } // end namespace Catch 4465 4466 // end catch_option.hpp 4467 #include <chrono> 4468 #include <iosfwd> 4469 #include <string> 4470 #include <vector> 4471 #include <memory> 4472 4473 namespace Catch { 4474 4475 enum class Verbosity { 4476 Quiet = 0, 4477 Normal, 4478 High 4479 }; 4480 4481 struct WarnAbout { enum What { 4482 Nothing = 0x00, 4483 NoAssertions = 0x01, 4484 NoTests = 0x02 4485 }; }; 4486 4487 struct ShowDurations { enum OrNot { 4488 DefaultForReporter, 4489 Always, 4490 Never 4491 }; }; 4492 struct RunTests { enum InWhatOrder { 4493 InDeclarationOrder, 4494 InLexicographicalOrder, 4495 InRandomOrder 4496 }; }; 4497 struct UseColour { enum YesOrNo { 4498 Auto, 4499 Yes, 4500 No 4501 }; }; 4502 struct WaitForKeypress { enum When { 4503 Never, 4504 BeforeStart = 1, 4505 BeforeExit = 2, 4506 BeforeStartAndExit = BeforeStart | BeforeExit 4507 }; }; 4508 4509 class TestSpec; 4510 4511 struct IConfig : NonCopyable { 4512 4513 virtual ~IConfig(); 4514 4515 virtual bool allowThrows() const = 0; 4516 virtual std::ostream& stream() const = 0; 4517 virtual std::string name() const = 0; 4518 virtual bool includeSuccessfulResults() const = 0; 4519 virtual bool shouldDebugBreak() const = 0; 4520 virtual bool warnAboutMissingAssertions() const = 0; 4521 virtual bool warnAboutNoTests() const = 0; 4522 virtual int abortAfter() const = 0; 4523 virtual bool showInvisibles() const = 0; 4524 virtual ShowDurations::OrNot showDurations() const = 0; 4525 virtual double minDuration() const = 0; 4526 virtual TestSpec const& testSpec() const = 0; 4527 virtual bool hasTestFilters() const = 0; 4528 virtual std::vector<std::string> const& getTestsOrTags() const = 0; 4529 virtual RunTests::InWhatOrder runOrder() const = 0; 4530 virtual unsigned int rngSeed() const = 0; 4531 virtual UseColour::YesOrNo useColour() const = 0; 4532 virtual std::vector<std::string> const& getSectionsToRun() const = 0; 4533 virtual Verbosity verbosity() const = 0; 4534 4535 virtual bool benchmarkNoAnalysis() const = 0; 4536 virtual int benchmarkSamples() const = 0; 4537 virtual double benchmarkConfidenceInterval() const = 0; 4538 virtual unsigned int benchmarkResamples() const = 0; 4539 virtual std::chrono::milliseconds benchmarkWarmupTime() const = 0; 4540 }; 4541 4542 using IConfigPtr = std::shared_ptr<IConfig const>; 4543 } 4544 4545 // end catch_interfaces_config.h 4546 // start catch_random_number_generator.h 4547 4548 #include <cstdint> 4549 4550 namespace Catch { 4551 4552 // This is a simple implementation of C++11 Uniform Random Number 4553 // Generator. It does not provide all operators, because Catch2 4554 // does not use it, but it should behave as expected inside stdlib's 4555 // distributions. 4556 // The implementation is based on the PCG family (http://pcg-random.org) 4557 class SimplePcg32 { 4558 using state_type = std::uint64_t; 4559 public: 4560 using result_type = std::uint32_t; 4561 static constexpr result_type (min)() { 4562 return 0; 4563 } 4564 static constexpr result_type (max)() { 4565 return static_cast<result_type>(-1); 4566 } 4567 4568 // Provide some default initial state for the default constructor 4569 SimplePcg32():SimplePcg32(0xed743cc4U) {} 4570 4571 explicit SimplePcg32(result_type seed_); 4572 4573 void seed(result_type seed_); 4574 void discard(uint64_t skip); 4575 4576 result_type operator()(); 4577 4578 private: 4579 friend bool operator==(SimplePcg32 const& lhs, SimplePcg32 const& rhs); 4580 friend bool operator!=(SimplePcg32 const& lhs, SimplePcg32 const& rhs); 4581 4582 // In theory we also need operator<< and operator>> 4583 // In practice we do not use them, so we will skip them for now 4584 4585 std::uint64_t m_state; 4586 // This part of the state determines which "stream" of the numbers 4587 // is chosen -- we take it as a constant for Catch2, so we only 4588 // need to deal with seeding the main state. 4589 // Picked by reading 8 bytes from `/dev/random` :-) 4590 static const std::uint64_t s_inc = (0x13ed0cc53f939476ULL << 1ULL) | 1ULL; 4591 }; 4592 4593 } // end namespace Catch 4594 4595 // end catch_random_number_generator.h 4596 #include <random> 4597 4598 namespace Catch { 4599 namespace Generators { 4600 4601 template <typename Float> 4602 class RandomFloatingGenerator final : public IGenerator<Float> { 4603 Catch::SimplePcg32& m_rng; 4604 std::uniform_real_distribution<Float> m_dist; 4605 Float m_current_number; 4606 public: 4607 4608 RandomFloatingGenerator(Float a, Float b): 4609 m_rng(rng()), 4610 m_dist(a, b) { 4611 static_cast<void>(next()); 4612 } 4613 4614 Float const& get() const override { 4615 return m_current_number; 4616 } 4617 bool next() override { 4618 m_current_number = m_dist(m_rng); 4619 return true; 4620 } 4621 }; 4622 4623 template <typename Integer> 4624 class RandomIntegerGenerator final : public IGenerator<Integer> { 4625 Catch::SimplePcg32& m_rng; 4626 std::uniform_int_distribution<Integer> m_dist; 4627 Integer m_current_number; 4628 public: 4629 4630 RandomIntegerGenerator(Integer a, Integer b): 4631 m_rng(rng()), 4632 m_dist(a, b) { 4633 static_cast<void>(next()); 4634 } 4635 4636 Integer const& get() const override { 4637 return m_current_number; 4638 } 4639 bool next() override { 4640 m_current_number = m_dist(m_rng); 4641 return true; 4642 } 4643 }; 4644 4645 // TODO: Ideally this would be also constrained against the various char types, 4646 // but I don't expect users to run into that in practice. 4647 template <typename T> 4648 typename std::enable_if<std::is_integral<T>::value && !std::is_same<T, bool>::value, 4649 GeneratorWrapper<T>>::type 4650 random(T a, T b) { 4651 return GeneratorWrapper<T>( 4652 pf::make_unique<RandomIntegerGenerator<T>>(a, b) 4653 ); 4654 } 4655 4656 template <typename T> 4657 typename std::enable_if<std::is_floating_point<T>::value, 4658 GeneratorWrapper<T>>::type 4659 random(T a, T b) { 4660 return GeneratorWrapper<T>( 4661 pf::make_unique<RandomFloatingGenerator<T>>(a, b) 4662 ); 4663 } 4664 4665 template <typename T> 4666 class RangeGenerator final : public IGenerator<T> { 4667 T m_current; 4668 T m_end; 4669 T m_step; 4670 bool m_positive; 4671 4672 public: 4673 RangeGenerator(T const& start, T const& end, T const& step): 4674 m_current(start), 4675 m_end(end), 4676 m_step(step), 4677 m_positive(m_step > T(0)) 4678 { 4679 assert(m_current != m_end && "Range start and end cannot be equal"); 4680 assert(m_step != T(0) && "Step size cannot be zero"); 4681 assert(((m_positive && m_current <= m_end) || (!m_positive && m_current >= m_end)) && "Step moves away from end"); 4682 } 4683 4684 RangeGenerator(T const& start, T const& end): 4685 RangeGenerator(start, end, (start < end) ? T(1) : T(-1)) 4686 {} 4687 4688 T const& get() const override { 4689 return m_current; 4690 } 4691 4692 bool next() override { 4693 m_current += m_step; 4694 return (m_positive) ? (m_current < m_end) : (m_current > m_end); 4695 } 4696 }; 4697 4698 template <typename T> 4699 GeneratorWrapper<T> range(T const& start, T const& end, T const& step) { 4700 static_assert(std::is_arithmetic<T>::value && !std::is_same<T, bool>::value, "Type must be numeric"); 4701 return GeneratorWrapper<T>(pf::make_unique<RangeGenerator<T>>(start, end, step)); 4702 } 4703 4704 template <typename T> 4705 GeneratorWrapper<T> range(T const& start, T const& end) { 4706 static_assert(std::is_integral<T>::value && !std::is_same<T, bool>::value, "Type must be an integer"); 4707 return GeneratorWrapper<T>(pf::make_unique<RangeGenerator<T>>(start, end)); 4708 } 4709 4710 template <typename T> 4711 class IteratorGenerator final : public IGenerator<T> { 4712 static_assert(!std::is_same<T, bool>::value, 4713 "IteratorGenerator currently does not support bools" 4714 "because of std::vector<bool> specialization"); 4715 4716 std::vector<T> m_elems; 4717 size_t m_current = 0; 4718 public: 4719 template <typename InputIterator, typename InputSentinel> 4720 IteratorGenerator(InputIterator first, InputSentinel last):m_elems(first, last) { 4721 if (m_elems.empty()) { 4722 Catch::throw_exception(GeneratorException("IteratorGenerator received no valid values")); 4723 } 4724 } 4725 4726 T const& get() const override { 4727 return m_elems[m_current]; 4728 } 4729 4730 bool next() override { 4731 ++m_current; 4732 return m_current != m_elems.size(); 4733 } 4734 }; 4735 4736 template <typename InputIterator, 4737 typename InputSentinel, 4738 typename ResultType = typename std::iterator_traits<InputIterator>::value_type> 4739 GeneratorWrapper<ResultType> from_range(InputIterator from, InputSentinel to) { 4740 return GeneratorWrapper<ResultType>(pf::make_unique<IteratorGenerator<ResultType>>(from, to)); 4741 } 4742 4743 template <typename Container, 4744 typename ResultType = typename Container::value_type> 4745 GeneratorWrapper<ResultType> from_range(Container const& cnt) { 4746 return GeneratorWrapper<ResultType>(pf::make_unique<IteratorGenerator<ResultType>>(cnt.begin(), cnt.end())); 4747 } 4748 4749 } // namespace Generators 4750 } // namespace Catch 4751 4752 // end catch_generators_specific.hpp 4753 4754 // These files are included here so the single_include script doesn't put them 4755 // in the conditionally compiled sections 4756 // start catch_test_case_info.h 4757 4758 #include <string> 4759 #include <vector> 4760 #include <memory> 4761 4762 #ifdef __clang__ 4763 #pragma clang diagnostic push 4764 #pragma clang diagnostic ignored "-Wpadded" 4765 #endif 4766 4767 namespace Catch { 4768 4769 struct ITestInvoker; 4770 4771 struct TestCaseInfo { 4772 enum SpecialProperties{ 4773 None = 0, 4774 IsHidden = 1 << 1, 4775 ShouldFail = 1 << 2, 4776 MayFail = 1 << 3, 4777 Throws = 1 << 4, 4778 NonPortable = 1 << 5, 4779 Benchmark = 1 << 6 4780 }; 4781 4782 TestCaseInfo( std::string const& _name, 4783 std::string const& _className, 4784 std::string const& _description, 4785 std::vector<std::string> const& _tags, 4786 SourceLineInfo const& _lineInfo ); 4787 4788 friend void setTags( TestCaseInfo& testCaseInfo, std::vector<std::string> tags ); 4789 4790 bool isHidden() const; 4791 bool throws() const; 4792 bool okToFail() const; 4793 bool expectedToFail() const; 4794 4795 std::string tagsAsString() const; 4796 4797 std::string name; 4798 std::string className; 4799 std::string description; 4800 std::vector<std::string> tags; 4801 std::vector<std::string> lcaseTags; 4802 SourceLineInfo lineInfo; 4803 SpecialProperties properties; 4804 }; 4805 4806 class TestCase : public TestCaseInfo { 4807 public: 4808 4809 TestCase( ITestInvoker* testCase, TestCaseInfo&& info ); 4810 4811 TestCase withName( std::string const& _newName ) const; 4812 4813 void invoke() const; 4814 4815 TestCaseInfo const& getTestCaseInfo() const; 4816 4817 bool operator == ( TestCase const& other ) const; 4818 bool operator < ( TestCase const& other ) const; 4819 4820 private: 4821 std::shared_ptr<ITestInvoker> test; 4822 }; 4823 4824 TestCase makeTestCase( ITestInvoker* testCase, 4825 std::string const& className, 4826 NameAndTags const& nameAndTags, 4827 SourceLineInfo const& lineInfo ); 4828 } 4829 4830 #ifdef __clang__ 4831 #pragma clang diagnostic pop 4832 #endif 4833 4834 // end catch_test_case_info.h 4835 // start catch_interfaces_runner.h 4836 4837 namespace Catch { 4838 4839 struct IRunner { 4840 virtual ~IRunner(); 4841 virtual bool aborting() const = 0; 4842 }; 4843 } 4844 4845 // end catch_interfaces_runner.h 4846 4847 #ifdef __OBJC__ 4848 // start catch_objc.hpp 4849 4850 #import <objc/runtime.h> 4851 4852 #include <string> 4853 4854 // NB. Any general catch headers included here must be included 4855 // in catch.hpp first to make sure they are included by the single 4856 // header for non obj-usage 4857 4858 /////////////////////////////////////////////////////////////////////////////// 4859 // This protocol is really only here for (self) documenting purposes, since 4860 // all its methods are optional. 4861 @protocol OcFixture 4862 4863 @optional 4864 4865 -(void) setUp; 4866 -(void) tearDown; 4867 4868 @end 4869 4870 namespace Catch { 4871 4872 class OcMethod : public ITestInvoker { 4873 4874 public: 4875 OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} 4876 4877 virtual void invoke() const { 4878 id obj = [[m_cls alloc] init]; 4879 4880 performOptionalSelector( obj, @selector(setUp) ); 4881 performOptionalSelector( obj, m_sel ); 4882 performOptionalSelector( obj, @selector(tearDown) ); 4883 4884 arcSafeRelease( obj ); 4885 } 4886 private: 4887 virtual ~OcMethod() {} 4888 4889 Class m_cls; 4890 SEL m_sel; 4891 }; 4892 4893 namespace Detail{ 4894 4895 inline std::string getAnnotation( Class cls, 4896 std::string const& annotationName, 4897 std::string const& testCaseName ) { 4898 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()]; 4899 SEL sel = NSSelectorFromString( selStr ); 4900 arcSafeRelease( selStr ); 4901 id value = performOptionalSelector( cls, sel ); 4902 if( value ) 4903 return [(NSString*)value UTF8String]; 4904 return ""; 4905 } 4906 } 4907 4908 inline std::size_t registerTestMethods() { 4909 std::size_t noTestMethods = 0; 4910 int noClasses = objc_getClassList( nullptr, 0 ); 4911 4912 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); 4913 objc_getClassList( classes, noClasses ); 4914 4915 for( int c = 0; c < noClasses; c++ ) { 4916 Class cls = classes[c]; 4917 { 4918 u_int count; 4919 Method* methods = class_copyMethodList( cls, &count ); 4920 for( u_int m = 0; m < count ; m++ ) { 4921 SEL selector = method_getName(methods[m]); 4922 std::string methodName = sel_getName(selector); 4923 if( startsWith( methodName, "Catch_TestCase_" ) ) { 4924 std::string testCaseName = methodName.substr( 15 ); 4925 std::string name = Detail::getAnnotation( cls, "Name", testCaseName ); 4926 std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); 4927 const char* className = class_getName( cls ); 4928 4929 getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, NameAndTags( name.c_str(), desc.c_str() ), SourceLineInfo("",0) ) ); 4930 noTestMethods++; 4931 } 4932 } 4933 free(methods); 4934 } 4935 } 4936 return noTestMethods; 4937 } 4938 4939 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 4940 4941 namespace Matchers { 4942 namespace Impl { 4943 namespace NSStringMatchers { 4944 4945 struct StringHolder : MatcherBase<NSString*>{ 4946 StringHolder( NSString* substr ) : m_substr( [substr copy] ){} 4947 StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){} 4948 StringHolder() { 4949 arcSafeRelease( m_substr ); 4950 } 4951 4952 bool match( NSString* str ) const override { 4953 return false; 4954 } 4955 4956 NSString* CATCH_ARC_STRONG m_substr; 4957 }; 4958 4959 struct Equals : StringHolder { 4960 Equals( NSString* substr ) : StringHolder( substr ){} 4961 4962 bool match( NSString* str ) const override { 4963 return (str != nil || m_substr == nil ) && 4964 [str isEqualToString:m_substr]; 4965 } 4966 4967 std::string describe() const override { 4968 return "equals string: " + Catch::Detail::stringify( m_substr ); 4969 } 4970 }; 4971 4972 struct Contains : StringHolder { 4973 Contains( NSString* substr ) : StringHolder( substr ){} 4974 4975 bool match( NSString* str ) const override { 4976 return (str != nil || m_substr == nil ) && 4977 [str rangeOfString:m_substr].location != NSNotFound; 4978 } 4979 4980 std::string describe() const override { 4981 return "contains string: " + Catch::Detail::stringify( m_substr ); 4982 } 4983 }; 4984 4985 struct StartsWith : StringHolder { 4986 StartsWith( NSString* substr ) : StringHolder( substr ){} 4987 4988 bool match( NSString* str ) const override { 4989 return (str != nil || m_substr == nil ) && 4990 [str rangeOfString:m_substr].location == 0; 4991 } 4992 4993 std::string describe() const override { 4994 return "starts with: " + Catch::Detail::stringify( m_substr ); 4995 } 4996 }; 4997 struct EndsWith : StringHolder { 4998 EndsWith( NSString* substr ) : StringHolder( substr ){} 4999 5000 bool match( NSString* str ) const override { 5001 return (str != nil || m_substr == nil ) && 5002 [str rangeOfString:m_substr].location == [str length] - [m_substr length]; 5003 } 5004 5005 std::string describe() const override { 5006 return "ends with: " + Catch::Detail::stringify( m_substr ); 5007 } 5008 }; 5009 5010 } // namespace NSStringMatchers 5011 } // namespace Impl 5012 5013 inline Impl::NSStringMatchers::Equals 5014 Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); } 5015 5016 inline Impl::NSStringMatchers::Contains 5017 Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); } 5018 5019 inline Impl::NSStringMatchers::StartsWith 5020 StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); } 5021 5022 inline Impl::NSStringMatchers::EndsWith 5023 EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); } 5024 5025 } // namespace Matchers 5026 5027 using namespace Matchers; 5028 5029 #endif // CATCH_CONFIG_DISABLE_MATCHERS 5030 5031 } // namespace Catch 5032 5033 /////////////////////////////////////////////////////////////////////////////// 5034 #define OC_MAKE_UNIQUE_NAME( root, uniqueSuffix ) root##uniqueSuffix 5035 #define OC_TEST_CASE2( name, desc, uniqueSuffix ) \ 5036 +(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Name_test_, uniqueSuffix ) \ 5037 { \ 5038 return @ name; \ 5039 } \ 5040 +(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Description_test_, uniqueSuffix ) \ 5041 { \ 5042 return @ desc; \ 5043 } \ 5044 -(void) OC_MAKE_UNIQUE_NAME( Catch_TestCase_test_, uniqueSuffix ) 5045 5046 #define OC_TEST_CASE( name, desc ) OC_TEST_CASE2( name, desc, __LINE__ ) 5047 5048 // end catch_objc.hpp 5049 #endif 5050 5051 // Benchmarking needs the externally-facing parts of reporters to work 5052 #if defined(CATCH_CONFIG_EXTERNAL_INTERFACES) || defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 5053 // start catch_external_interfaces.h 5054 5055 // start catch_reporter_bases.hpp 5056 5057 // start catch_interfaces_reporter.h 5058 5059 // start catch_config.hpp 5060 5061 // start catch_test_spec_parser.h 5062 5063 #ifdef __clang__ 5064 #pragma clang diagnostic push 5065 #pragma clang diagnostic ignored "-Wpadded" 5066 #endif 5067 5068 // start catch_test_spec.h 5069 5070 #ifdef __clang__ 5071 #pragma clang diagnostic push 5072 #pragma clang diagnostic ignored "-Wpadded" 5073 #endif 5074 5075 // start catch_wildcard_pattern.h 5076 5077 namespace Catch 5078 { 5079 class WildcardPattern { 5080 enum WildcardPosition { 5081 NoWildcard = 0, 5082 WildcardAtStart = 1, 5083 WildcardAtEnd = 2, 5084 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd 5085 }; 5086 5087 public: 5088 5089 WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity ); 5090 virtual ~WildcardPattern() = default; 5091 virtual bool matches( std::string const& str ) const; 5092 5093 private: 5094 std::string normaliseString( std::string const& str ) const; 5095 CaseSensitive::Choice m_caseSensitivity; 5096 WildcardPosition m_wildcard = NoWildcard; 5097 std::string m_pattern; 5098 }; 5099 } 5100 5101 // end catch_wildcard_pattern.h 5102 #include <string> 5103 #include <vector> 5104 #include <memory> 5105 5106 namespace Catch { 5107 5108 struct IConfig; 5109 5110 class TestSpec { 5111 class Pattern { 5112 public: 5113 explicit Pattern( std::string const& name ); 5114 virtual ~Pattern(); 5115 virtual bool matches( TestCaseInfo const& testCase ) const = 0; 5116 std::string const& name() const; 5117 private: 5118 std::string const m_name; 5119 }; 5120 using PatternPtr = std::shared_ptr<Pattern>; 5121 5122 class NamePattern : public Pattern { 5123 public: 5124 explicit NamePattern( std::string const& name, std::string const& filterString ); 5125 bool matches( TestCaseInfo const& testCase ) const override; 5126 private: 5127 WildcardPattern m_wildcardPattern; 5128 }; 5129 5130 class TagPattern : public Pattern { 5131 public: 5132 explicit TagPattern( std::string const& tag, std::string const& filterString ); 5133 bool matches( TestCaseInfo const& testCase ) const override; 5134 private: 5135 std::string m_tag; 5136 }; 5137 5138 class ExcludedPattern : public Pattern { 5139 public: 5140 explicit ExcludedPattern( PatternPtr const& underlyingPattern ); 5141 bool matches( TestCaseInfo const& testCase ) const override; 5142 private: 5143 PatternPtr m_underlyingPattern; 5144 }; 5145 5146 struct Filter { 5147 std::vector<PatternPtr> m_patterns; 5148 5149 bool matches( TestCaseInfo const& testCase ) const; 5150 std::string name() const; 5151 }; 5152 5153 public: 5154 struct FilterMatch { 5155 std::string name; 5156 std::vector<TestCase const*> tests; 5157 }; 5158 using Matches = std::vector<FilterMatch>; 5159 using vectorStrings = std::vector<std::string>; 5160 5161 bool hasFilters() const; 5162 bool matches( TestCaseInfo const& testCase ) const; 5163 Matches matchesByFilter( std::vector<TestCase> const& testCases, IConfig const& config ) const; 5164 const vectorStrings & getInvalidArgs() const; 5165 5166 private: 5167 std::vector<Filter> m_filters; 5168 std::vector<std::string> m_invalidArgs; 5169 friend class TestSpecParser; 5170 }; 5171 } 5172 5173 #ifdef __clang__ 5174 #pragma clang diagnostic pop 5175 #endif 5176 5177 // end catch_test_spec.h 5178 // start catch_interfaces_tag_alias_registry.h 5179 5180 #include <string> 5181 5182 namespace Catch { 5183 5184 struct TagAlias; 5185 5186 struct ITagAliasRegistry { 5187 virtual ~ITagAliasRegistry(); 5188 // Nullptr if not present 5189 virtual TagAlias const* find( std::string const& alias ) const = 0; 5190 virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; 5191 5192 static ITagAliasRegistry const& get(); 5193 }; 5194 5195 } // end namespace Catch 5196 5197 // end catch_interfaces_tag_alias_registry.h 5198 namespace Catch { 5199 5200 class TestSpecParser { 5201 enum Mode{ None, Name, QuotedName, Tag, EscapedName }; 5202 Mode m_mode = None; 5203 Mode lastMode = None; 5204 bool m_exclusion = false; 5205 std::size_t m_pos = 0; 5206 std::size_t m_realPatternPos = 0; 5207 std::string m_arg; 5208 std::string m_substring; 5209 std::string m_patternName; 5210 std::vector<std::size_t> m_escapeChars; 5211 TestSpec::Filter m_currentFilter; 5212 TestSpec m_testSpec; 5213 ITagAliasRegistry const* m_tagAliases = nullptr; 5214 5215 public: 5216 TestSpecParser( ITagAliasRegistry const& tagAliases ); 5217 5218 TestSpecParser& parse( std::string const& arg ); 5219 TestSpec testSpec(); 5220 5221 private: 5222 bool visitChar( char c ); 5223 void startNewMode( Mode mode ); 5224 bool processNoneChar( char c ); 5225 void processNameChar( char c ); 5226 bool processOtherChar( char c ); 5227 void endMode(); 5228 void escape(); 5229 bool isControlChar( char c ) const; 5230 void saveLastMode(); 5231 void revertBackToLastMode(); 5232 void addFilter(); 5233 bool separate(); 5234 5235 // Handles common preprocessing of the pattern for name/tag patterns 5236 std::string preprocessPattern(); 5237 // Adds the current pattern as a test name 5238 void addNamePattern(); 5239 // Adds the current pattern as a tag 5240 void addTagPattern(); 5241 5242 inline void addCharToPattern(char c) { 5243 m_substring += c; 5244 m_patternName += c; 5245 m_realPatternPos++; 5246 } 5247 5248 }; 5249 TestSpec parseTestSpec( std::string const& arg ); 5250 5251 } // namespace Catch 5252 5253 #ifdef __clang__ 5254 #pragma clang diagnostic pop 5255 #endif 5256 5257 // end catch_test_spec_parser.h 5258 // Libstdc++ doesn't like incomplete classes for unique_ptr 5259 5260 #include <memory> 5261 #include <vector> 5262 #include <string> 5263 5264 #ifndef CATCH_CONFIG_CONSOLE_WIDTH 5265 #define CATCH_CONFIG_CONSOLE_WIDTH 80 5266 #endif 5267 5268 namespace Catch { 5269 5270 struct IStream; 5271 5272 struct ConfigData { 5273 bool listTests = false; 5274 bool listTags = false; 5275 bool listReporters = false; 5276 bool listTestNamesOnly = false; 5277 5278 bool showSuccessfulTests = false; 5279 bool shouldDebugBreak = false; 5280 bool noThrow = false; 5281 bool showHelp = false; 5282 bool showInvisibles = false; 5283 bool filenamesAsTags = false; 5284 bool libIdentify = false; 5285 5286 int abortAfter = -1; 5287 unsigned int rngSeed = 0; 5288 5289 bool benchmarkNoAnalysis = false; 5290 unsigned int benchmarkSamples = 100; 5291 double benchmarkConfidenceInterval = 0.95; 5292 unsigned int benchmarkResamples = 100000; 5293 std::chrono::milliseconds::rep benchmarkWarmupTime = 100; 5294 5295 Verbosity verbosity = Verbosity::Normal; 5296 WarnAbout::What warnings = WarnAbout::Nothing; 5297 ShowDurations::OrNot showDurations = ShowDurations::DefaultForReporter; 5298 double minDuration = -1; 5299 RunTests::InWhatOrder runOrder = RunTests::InDeclarationOrder; 5300 UseColour::YesOrNo useColour = UseColour::Auto; 5301 WaitForKeypress::When waitForKeypress = WaitForKeypress::Never; 5302 5303 std::string outputFilename; 5304 std::string name; 5305 std::string processName; 5306 #ifndef CATCH_CONFIG_DEFAULT_REPORTER 5307 #define CATCH_CONFIG_DEFAULT_REPORTER "console" 5308 #endif 5309 std::string reporterName = CATCH_CONFIG_DEFAULT_REPORTER; 5310 #undef CATCH_CONFIG_DEFAULT_REPORTER 5311 5312 std::vector<std::string> testsOrTags; 5313 std::vector<std::string> sectionsToRun; 5314 }; 5315 5316 class Config : public IConfig { 5317 public: 5318 5319 Config() = default; 5320 Config( ConfigData const& data ); 5321 virtual ~Config() = default; 5322 5323 std::string const& getFilename() const; 5324 5325 bool listTests() const; 5326 bool listTestNamesOnly() const; 5327 bool listTags() const; 5328 bool listReporters() const; 5329 5330 std::string getProcessName() const; 5331 std::string const& getReporterName() const; 5332 5333 std::vector<std::string> const& getTestsOrTags() const override; 5334 std::vector<std::string> const& getSectionsToRun() const override; 5335 5336 TestSpec const& testSpec() const override; 5337 bool hasTestFilters() const override; 5338 5339 bool showHelp() const; 5340 5341 // IConfig interface 5342 bool allowThrows() const override; 5343 std::ostream& stream() const override; 5344 std::string name() const override; 5345 bool includeSuccessfulResults() const override; 5346 bool warnAboutMissingAssertions() const override; 5347 bool warnAboutNoTests() const override; 5348 ShowDurations::OrNot showDurations() const override; 5349 double minDuration() const override; 5350 RunTests::InWhatOrder runOrder() const override; 5351 unsigned int rngSeed() const override; 5352 UseColour::YesOrNo useColour() const override; 5353 bool shouldDebugBreak() const override; 5354 int abortAfter() const override; 5355 bool showInvisibles() const override; 5356 Verbosity verbosity() const override; 5357 bool benchmarkNoAnalysis() const override; 5358 int benchmarkSamples() const override; 5359 double benchmarkConfidenceInterval() const override; 5360 unsigned int benchmarkResamples() const override; 5361 std::chrono::milliseconds benchmarkWarmupTime() const override; 5362 5363 private: 5364 5365 IStream const* openStream(); 5366 ConfigData m_data; 5367 5368 std::unique_ptr<IStream const> m_stream; 5369 TestSpec m_testSpec; 5370 bool m_hasTestFilters = false; 5371 }; 5372 5373 } // end namespace Catch 5374 5375 // end catch_config.hpp 5376 // start catch_assertionresult.h 5377 5378 #include <string> 5379 5380 namespace Catch { 5381 5382 struct AssertionResultData 5383 { 5384 AssertionResultData() = delete; 5385 5386 AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression ); 5387 5388 std::string message; 5389 mutable std::string reconstructedExpression; 5390 LazyExpression lazyExpression; 5391 ResultWas::OfType resultType; 5392 5393 std::string reconstructExpression() const; 5394 }; 5395 5396 class AssertionResult { 5397 public: 5398 AssertionResult() = delete; 5399 AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); 5400 5401 bool isOk() const; 5402 bool succeeded() const; 5403 ResultWas::OfType getResultType() const; 5404 bool hasExpression() const; 5405 bool hasMessage() const; 5406 std::string getExpression() const; 5407 std::string getExpressionInMacro() const; 5408 bool hasExpandedExpression() const; 5409 std::string getExpandedExpression() const; 5410 std::string getMessage() const; 5411 SourceLineInfo getSourceInfo() const; 5412 StringRef getTestMacroName() const; 5413 5414 //protected: 5415 AssertionInfo m_info; 5416 AssertionResultData m_resultData; 5417 }; 5418 5419 } // end namespace Catch 5420 5421 // end catch_assertionresult.h 5422 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 5423 // start catch_estimate.hpp 5424 5425 // Statistics estimates 5426 5427 5428 namespace Catch { 5429 namespace Benchmark { 5430 template <typename Duration> 5431 struct Estimate { 5432 Duration point; 5433 Duration lower_bound; 5434 Duration upper_bound; 5435 double confidence_interval; 5436 5437 template <typename Duration2> 5438 operator Estimate<Duration2>() const { 5439 return { point, lower_bound, upper_bound, confidence_interval }; 5440 } 5441 }; 5442 } // namespace Benchmark 5443 } // namespace Catch 5444 5445 // end catch_estimate.hpp 5446 // start catch_outlier_classification.hpp 5447 5448 // Outlier information 5449 5450 namespace Catch { 5451 namespace Benchmark { 5452 struct OutlierClassification { 5453 int samples_seen = 0; 5454 int low_severe = 0; // more than 3 times IQR below Q1 5455 int low_mild = 0; // 1.5 to 3 times IQR below Q1 5456 int high_mild = 0; // 1.5 to 3 times IQR above Q3 5457 int high_severe = 0; // more than 3 times IQR above Q3 5458 5459 int total() const { 5460 return low_severe + low_mild + high_mild + high_severe; 5461 } 5462 }; 5463 } // namespace Benchmark 5464 } // namespace Catch 5465 5466 // end catch_outlier_classification.hpp 5467 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 5468 5469 #include <string> 5470 #include <iosfwd> 5471 #include <map> 5472 #include <set> 5473 #include <memory> 5474 #include <algorithm> 5475 5476 namespace Catch { 5477 5478 struct ReporterConfig { 5479 explicit ReporterConfig( IConfigPtr const& _fullConfig ); 5480 5481 ReporterConfig( IConfigPtr const& _fullConfig, std::ostream& _stream ); 5482 5483 std::ostream& stream() const; 5484 IConfigPtr fullConfig() const; 5485 5486 private: 5487 std::ostream* m_stream; 5488 IConfigPtr m_fullConfig; 5489 }; 5490 5491 struct ReporterPreferences { 5492 bool shouldRedirectStdOut = false; 5493 bool shouldReportAllAssertions = false; 5494 }; 5495 5496 template<typename T> 5497 struct LazyStat : Option<T> { 5498 LazyStat& operator=( T const& _value ) { 5499 Option<T>::operator=( _value ); 5500 used = false; 5501 return *this; 5502 } 5503 void reset() { 5504 Option<T>::reset(); 5505 used = false; 5506 } 5507 bool used = false; 5508 }; 5509 5510 struct TestRunInfo { 5511 TestRunInfo( std::string const& _name ); 5512 std::string name; 5513 }; 5514 struct GroupInfo { 5515 GroupInfo( std::string const& _name, 5516 std::size_t _groupIndex, 5517 std::size_t _groupsCount ); 5518 5519 std::string name; 5520 std::size_t groupIndex; 5521 std::size_t groupsCounts; 5522 }; 5523 5524 struct AssertionStats { 5525 AssertionStats( AssertionResult const& _assertionResult, 5526 std::vector<MessageInfo> const& _infoMessages, 5527 Totals const& _totals ); 5528 5529 AssertionStats( AssertionStats const& ) = default; 5530 AssertionStats( AssertionStats && ) = default; 5531 AssertionStats& operator = ( AssertionStats const& ) = delete; 5532 AssertionStats& operator = ( AssertionStats && ) = delete; 5533 virtual ~AssertionStats(); 5534 5535 AssertionResult assertionResult; 5536 std::vector<MessageInfo> infoMessages; 5537 Totals totals; 5538 }; 5539 5540 struct SectionStats { 5541 SectionStats( SectionInfo const& _sectionInfo, 5542 Counts const& _assertions, 5543 double _durationInSeconds, 5544 bool _missingAssertions ); 5545 SectionStats( SectionStats const& ) = default; 5546 SectionStats( SectionStats && ) = default; 5547 SectionStats& operator = ( SectionStats const& ) = default; 5548 SectionStats& operator = ( SectionStats && ) = default; 5549 virtual ~SectionStats(); 5550 5551 SectionInfo sectionInfo; 5552 Counts assertions; 5553 double durationInSeconds; 5554 bool missingAssertions; 5555 }; 5556 5557 struct TestCaseStats { 5558 TestCaseStats( TestCaseInfo const& _testInfo, 5559 Totals const& _totals, 5560 std::string const& _stdOut, 5561 std::string const& _stdErr, 5562 bool _aborting ); 5563 5564 TestCaseStats( TestCaseStats const& ) = default; 5565 TestCaseStats( TestCaseStats && ) = default; 5566 TestCaseStats& operator = ( TestCaseStats const& ) = default; 5567 TestCaseStats& operator = ( TestCaseStats && ) = default; 5568 virtual ~TestCaseStats(); 5569 5570 TestCaseInfo testInfo; 5571 Totals totals; 5572 std::string stdOut; 5573 std::string stdErr; 5574 bool aborting; 5575 }; 5576 5577 struct TestGroupStats { 5578 TestGroupStats( GroupInfo const& _groupInfo, 5579 Totals const& _totals, 5580 bool _aborting ); 5581 TestGroupStats( GroupInfo const& _groupInfo ); 5582 5583 TestGroupStats( TestGroupStats const& ) = default; 5584 TestGroupStats( TestGroupStats && ) = default; 5585 TestGroupStats& operator = ( TestGroupStats const& ) = default; 5586 TestGroupStats& operator = ( TestGroupStats && ) = default; 5587 virtual ~TestGroupStats(); 5588 5589 GroupInfo groupInfo; 5590 Totals totals; 5591 bool aborting; 5592 }; 5593 5594 struct TestRunStats { 5595 TestRunStats( TestRunInfo const& _runInfo, 5596 Totals const& _totals, 5597 bool _aborting ); 5598 5599 TestRunStats( TestRunStats const& ) = default; 5600 TestRunStats( TestRunStats && ) = default; 5601 TestRunStats& operator = ( TestRunStats const& ) = default; 5602 TestRunStats& operator = ( TestRunStats && ) = default; 5603 virtual ~TestRunStats(); 5604 5605 TestRunInfo runInfo; 5606 Totals totals; 5607 bool aborting; 5608 }; 5609 5610 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 5611 struct BenchmarkInfo { 5612 std::string name; 5613 double estimatedDuration; 5614 int iterations; 5615 int samples; 5616 unsigned int resamples; 5617 double clockResolution; 5618 double clockCost; 5619 }; 5620 5621 template <class Duration> 5622 struct BenchmarkStats { 5623 BenchmarkInfo info; 5624 5625 std::vector<Duration> samples; 5626 Benchmark::Estimate<Duration> mean; 5627 Benchmark::Estimate<Duration> standardDeviation; 5628 Benchmark::OutlierClassification outliers; 5629 double outlierVariance; 5630 5631 template <typename Duration2> 5632 operator BenchmarkStats<Duration2>() const { 5633 std::vector<Duration2> samples2; 5634 samples2.reserve(samples.size()); 5635 std::transform(samples.begin(), samples.end(), std::back_inserter(samples2), [](Duration d) { return Duration2(d); }); 5636 return { 5637 info, 5638 std::move(samples2), 5639 mean, 5640 standardDeviation, 5641 outliers, 5642 outlierVariance, 5643 }; 5644 } 5645 }; 5646 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 5647 5648 struct IStreamingReporter { 5649 virtual ~IStreamingReporter() = default; 5650 5651 // Implementing class must also provide the following static methods: 5652 // static std::string getDescription(); 5653 // static std::set<Verbosity> getSupportedVerbosities() 5654 5655 virtual ReporterPreferences getPreferences() const = 0; 5656 5657 virtual void noMatchingTestCases( std::string const& spec ) = 0; 5658 5659 virtual void reportInvalidArguments(std::string const&) {} 5660 5661 virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; 5662 virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0; 5663 5664 virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; 5665 virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; 5666 5667 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 5668 virtual void benchmarkPreparing( std::string const& ) {} 5669 virtual void benchmarkStarting( BenchmarkInfo const& ) {} 5670 virtual void benchmarkEnded( BenchmarkStats<> const& ) {} 5671 virtual void benchmarkFailed( std::string const& ) {} 5672 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 5673 5674 virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; 5675 5676 // The return value indicates if the messages buffer should be cleared: 5677 virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; 5678 5679 virtual void sectionEnded( SectionStats const& sectionStats ) = 0; 5680 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; 5681 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; 5682 virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; 5683 5684 virtual void skipTest( TestCaseInfo const& testInfo ) = 0; 5685 5686 // Default empty implementation provided 5687 virtual void fatalErrorEncountered( StringRef name ); 5688 5689 virtual bool isMulti() const; 5690 }; 5691 using IStreamingReporterPtr = std::unique_ptr<IStreamingReporter>; 5692 5693 struct IReporterFactory { 5694 virtual ~IReporterFactory(); 5695 virtual IStreamingReporterPtr create( ReporterConfig const& config ) const = 0; 5696 virtual std::string getDescription() const = 0; 5697 }; 5698 using IReporterFactoryPtr = std::shared_ptr<IReporterFactory>; 5699 5700 struct IReporterRegistry { 5701 using FactoryMap = std::map<std::string, IReporterFactoryPtr>; 5702 using Listeners = std::vector<IReporterFactoryPtr>; 5703 5704 virtual ~IReporterRegistry(); 5705 virtual IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const = 0; 5706 virtual FactoryMap const& getFactories() const = 0; 5707 virtual Listeners const& getListeners() const = 0; 5708 }; 5709 5710 } // end namespace Catch 5711 5712 // end catch_interfaces_reporter.h 5713 #include <algorithm> 5714 #include <cstring> 5715 #include <cfloat> 5716 #include <cstdio> 5717 #include <cassert> 5718 #include <memory> 5719 #include <ostream> 5720 5721 namespace Catch { 5722 void prepareExpandedExpression(AssertionResult& result); 5723 5724 // Returns double formatted as %.3f (format expected on output) 5725 std::string getFormattedDuration( double duration ); 5726 5727 //! Should the reporter show 5728 bool shouldShowDuration( IConfig const& config, double duration ); 5729 5730 std::string serializeFilters( std::vector<std::string> const& container ); 5731 5732 template<typename DerivedT> 5733 struct StreamingReporterBase : IStreamingReporter { 5734 5735 StreamingReporterBase( ReporterConfig const& _config ) 5736 : m_config( _config.fullConfig() ), 5737 stream( _config.stream() ) 5738 { 5739 m_reporterPrefs.shouldRedirectStdOut = false; 5740 if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) ) 5741 CATCH_ERROR( "Verbosity level not supported by this reporter" ); 5742 } 5743 5744 ReporterPreferences getPreferences() const override { 5745 return m_reporterPrefs; 5746 } 5747 5748 static std::set<Verbosity> getSupportedVerbosities() { 5749 return { Verbosity::Normal }; 5750 } 5751 5752 ~StreamingReporterBase() override = default; 5753 5754 void noMatchingTestCases(std::string const&) override {} 5755 5756 void reportInvalidArguments(std::string const&) override {} 5757 5758 void testRunStarting(TestRunInfo const& _testRunInfo) override { 5759 currentTestRunInfo = _testRunInfo; 5760 } 5761 5762 void testGroupStarting(GroupInfo const& _groupInfo) override { 5763 currentGroupInfo = _groupInfo; 5764 } 5765 5766 void testCaseStarting(TestCaseInfo const& _testInfo) override { 5767 currentTestCaseInfo = _testInfo; 5768 } 5769 void sectionStarting(SectionInfo const& _sectionInfo) override { 5770 m_sectionStack.push_back(_sectionInfo); 5771 } 5772 5773 void sectionEnded(SectionStats const& /* _sectionStats */) override { 5774 m_sectionStack.pop_back(); 5775 } 5776 void testCaseEnded(TestCaseStats const& /* _testCaseStats */) override { 5777 currentTestCaseInfo.reset(); 5778 } 5779 void testGroupEnded(TestGroupStats const& /* _testGroupStats */) override { 5780 currentGroupInfo.reset(); 5781 } 5782 void testRunEnded(TestRunStats const& /* _testRunStats */) override { 5783 currentTestCaseInfo.reset(); 5784 currentGroupInfo.reset(); 5785 currentTestRunInfo.reset(); 5786 } 5787 5788 void skipTest(TestCaseInfo const&) override { 5789 // Don't do anything with this by default. 5790 // It can optionally be overridden in the derived class. 5791 } 5792 5793 IConfigPtr m_config; 5794 std::ostream& stream; 5795 5796 LazyStat<TestRunInfo> currentTestRunInfo; 5797 LazyStat<GroupInfo> currentGroupInfo; 5798 LazyStat<TestCaseInfo> currentTestCaseInfo; 5799 5800 std::vector<SectionInfo> m_sectionStack; 5801 ReporterPreferences m_reporterPrefs; 5802 }; 5803 5804 template<typename DerivedT> 5805 struct CumulativeReporterBase : IStreamingReporter { 5806 template<typename T, typename ChildNodeT> 5807 struct Node { 5808 explicit Node( T const& _value ) : value( _value ) {} 5809 virtual ~Node() {} 5810 5811 using ChildNodes = std::vector<std::shared_ptr<ChildNodeT>>; 5812 T value; 5813 ChildNodes children; 5814 }; 5815 struct SectionNode { 5816 explicit SectionNode(SectionStats const& _stats) : stats(_stats) {} 5817 virtual ~SectionNode() = default; 5818 5819 bool operator == (SectionNode const& other) const { 5820 return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; 5821 } 5822 bool operator == (std::shared_ptr<SectionNode> const& other) const { 5823 return operator==(*other); 5824 } 5825 5826 SectionStats stats; 5827 using ChildSections = std::vector<std::shared_ptr<SectionNode>>; 5828 using Assertions = std::vector<AssertionStats>; 5829 ChildSections childSections; 5830 Assertions assertions; 5831 std::string stdOut; 5832 std::string stdErr; 5833 }; 5834 5835 struct BySectionInfo { 5836 BySectionInfo( SectionInfo const& other ) : m_other( other ) {} 5837 BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {} 5838 bool operator() (std::shared_ptr<SectionNode> const& node) const { 5839 return ((node->stats.sectionInfo.name == m_other.name) && 5840 (node->stats.sectionInfo.lineInfo == m_other.lineInfo)); 5841 } 5842 void operator=(BySectionInfo const&) = delete; 5843 5844 private: 5845 SectionInfo const& m_other; 5846 }; 5847 5848 using TestCaseNode = Node<TestCaseStats, SectionNode>; 5849 using TestGroupNode = Node<TestGroupStats, TestCaseNode>; 5850 using TestRunNode = Node<TestRunStats, TestGroupNode>; 5851 5852 CumulativeReporterBase( ReporterConfig const& _config ) 5853 : m_config( _config.fullConfig() ), 5854 stream( _config.stream() ) 5855 { 5856 m_reporterPrefs.shouldRedirectStdOut = false; 5857 if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) ) 5858 CATCH_ERROR( "Verbosity level not supported by this reporter" ); 5859 } 5860 ~CumulativeReporterBase() override = default; 5861 5862 ReporterPreferences getPreferences() const override { 5863 return m_reporterPrefs; 5864 } 5865 5866 static std::set<Verbosity> getSupportedVerbosities() { 5867 return { Verbosity::Normal }; 5868 } 5869 5870 void testRunStarting( TestRunInfo const& ) override {} 5871 void testGroupStarting( GroupInfo const& ) override {} 5872 5873 void testCaseStarting( TestCaseInfo const& ) override {} 5874 5875 void sectionStarting( SectionInfo const& sectionInfo ) override { 5876 SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); 5877 std::shared_ptr<SectionNode> node; 5878 if( m_sectionStack.empty() ) { 5879 if( !m_rootSection ) 5880 m_rootSection = std::make_shared<SectionNode>( incompleteStats ); 5881 node = m_rootSection; 5882 } 5883 else { 5884 SectionNode& parentNode = *m_sectionStack.back(); 5885 auto it = 5886 std::find_if( parentNode.childSections.begin(), 5887 parentNode.childSections.end(), 5888 BySectionInfo( sectionInfo ) ); 5889 if( it == parentNode.childSections.end() ) { 5890 node = std::make_shared<SectionNode>( incompleteStats ); 5891 parentNode.childSections.push_back( node ); 5892 } 5893 else 5894 node = *it; 5895 } 5896 m_sectionStack.push_back( node ); 5897 m_deepestSection = std::move(node); 5898 } 5899 5900 void assertionStarting(AssertionInfo const&) override {} 5901 5902 bool assertionEnded(AssertionStats const& assertionStats) override { 5903 assert(!m_sectionStack.empty()); 5904 // AssertionResult holds a pointer to a temporary DecomposedExpression, 5905 // which getExpandedExpression() calls to build the expression string. 5906 // Our section stack copy of the assertionResult will likely outlive the 5907 // temporary, so it must be expanded or discarded now to avoid calling 5908 // a destroyed object later. 5909 prepareExpandedExpression(const_cast<AssertionResult&>( assertionStats.assertionResult ) ); 5910 SectionNode& sectionNode = *m_sectionStack.back(); 5911 sectionNode.assertions.push_back(assertionStats); 5912 return true; 5913 } 5914 void sectionEnded(SectionStats const& sectionStats) override { 5915 assert(!m_sectionStack.empty()); 5916 SectionNode& node = *m_sectionStack.back(); 5917 node.stats = sectionStats; 5918 m_sectionStack.pop_back(); 5919 } 5920 void testCaseEnded(TestCaseStats const& testCaseStats) override { 5921 auto node = std::make_shared<TestCaseNode>(testCaseStats); 5922 assert(m_sectionStack.size() == 0); 5923 node->children.push_back(m_rootSection); 5924 m_testCases.push_back(node); 5925 m_rootSection.reset(); 5926 5927 assert(m_deepestSection); 5928 m_deepestSection->stdOut = testCaseStats.stdOut; 5929 m_deepestSection->stdErr = testCaseStats.stdErr; 5930 } 5931 void testGroupEnded(TestGroupStats const& testGroupStats) override { 5932 auto node = std::make_shared<TestGroupNode>(testGroupStats); 5933 node->children.swap(m_testCases); 5934 m_testGroups.push_back(node); 5935 } 5936 void testRunEnded(TestRunStats const& testRunStats) override { 5937 auto node = std::make_shared<TestRunNode>(testRunStats); 5938 node->children.swap(m_testGroups); 5939 m_testRuns.push_back(node); 5940 testRunEndedCumulative(); 5941 } 5942 virtual void testRunEndedCumulative() = 0; 5943 5944 void skipTest(TestCaseInfo const&) override {} 5945 5946 IConfigPtr m_config; 5947 std::ostream& stream; 5948 std::vector<AssertionStats> m_assertions; 5949 std::vector<std::vector<std::shared_ptr<SectionNode>>> m_sections; 5950 std::vector<std::shared_ptr<TestCaseNode>> m_testCases; 5951 std::vector<std::shared_ptr<TestGroupNode>> m_testGroups; 5952 5953 std::vector<std::shared_ptr<TestRunNode>> m_testRuns; 5954 5955 std::shared_ptr<SectionNode> m_rootSection; 5956 std::shared_ptr<SectionNode> m_deepestSection; 5957 std::vector<std::shared_ptr<SectionNode>> m_sectionStack; 5958 ReporterPreferences m_reporterPrefs; 5959 }; 5960 5961 template<char C> 5962 char const* getLineOfChars() { 5963 static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0}; 5964 if( !*line ) { 5965 std::memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 ); 5966 line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0; 5967 } 5968 return line; 5969 } 5970 5971 struct TestEventListenerBase : StreamingReporterBase<TestEventListenerBase> { 5972 TestEventListenerBase( ReporterConfig const& _config ); 5973 5974 static std::set<Verbosity> getSupportedVerbosities(); 5975 5976 void assertionStarting(AssertionInfo const&) override; 5977 bool assertionEnded(AssertionStats const&) override; 5978 }; 5979 5980 } // end namespace Catch 5981 5982 // end catch_reporter_bases.hpp 5983 // start catch_console_colour.h 5984 5985 namespace Catch { 5986 5987 struct Colour { 5988 enum Code { 5989 None = 0, 5990 5991 White, 5992 Red, 5993 Green, 5994 Blue, 5995 Cyan, 5996 Yellow, 5997 Grey, 5998 5999 Bright = 0x10, 6000 6001 BrightRed = Bright | Red, 6002 BrightGreen = Bright | Green, 6003 LightGrey = Bright | Grey, 6004 BrightWhite = Bright | White, 6005 BrightYellow = Bright | Yellow, 6006 6007 // By intention 6008 FileName = LightGrey, 6009 Warning = BrightYellow, 6010 ResultError = BrightRed, 6011 ResultSuccess = BrightGreen, 6012 ResultExpectedFailure = Warning, 6013 6014 Error = BrightRed, 6015 Success = Green, 6016 6017 OriginalExpression = Cyan, 6018 ReconstructedExpression = BrightYellow, 6019 6020 SecondaryText = LightGrey, 6021 Headers = White 6022 }; 6023 6024 // Use constructed object for RAII guard 6025 Colour( Code _colourCode ); 6026 Colour( Colour&& other ) noexcept; 6027 Colour& operator=( Colour&& other ) noexcept; 6028 ~Colour(); 6029 6030 // Use static method for one-shot changes 6031 static void use( Code _colourCode ); 6032 6033 private: 6034 bool m_moved = false; 6035 }; 6036 6037 std::ostream& operator << ( std::ostream& os, Colour const& ); 6038 6039 } // end namespace Catch 6040 6041 // end catch_console_colour.h 6042 // start catch_reporter_registrars.hpp 6043 6044 6045 namespace Catch { 6046 6047 template<typename T> 6048 class ReporterRegistrar { 6049 6050 class ReporterFactory : public IReporterFactory { 6051 6052 IStreamingReporterPtr create( ReporterConfig const& config ) const override { 6053 return std::unique_ptr<T>( new T( config ) ); 6054 } 6055 6056 std::string getDescription() const override { 6057 return T::getDescription(); 6058 } 6059 }; 6060 6061 public: 6062 6063 explicit ReporterRegistrar( std::string const& name ) { 6064 getMutableRegistryHub().registerReporter( name, std::make_shared<ReporterFactory>() ); 6065 } 6066 }; 6067 6068 template<typename T> 6069 class ListenerRegistrar { 6070 6071 class ListenerFactory : public IReporterFactory { 6072 6073 IStreamingReporterPtr create( ReporterConfig const& config ) const override { 6074 return std::unique_ptr<T>( new T( config ) ); 6075 } 6076 std::string getDescription() const override { 6077 return std::string(); 6078 } 6079 }; 6080 6081 public: 6082 6083 ListenerRegistrar() { 6084 getMutableRegistryHub().registerListener( std::make_shared<ListenerFactory>() ); 6085 } 6086 }; 6087 } 6088 6089 #if !defined(CATCH_CONFIG_DISABLE) 6090 6091 #define CATCH_REGISTER_REPORTER( name, reporterType ) \ 6092 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 6093 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 6094 namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); } \ 6095 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 6096 6097 #define CATCH_REGISTER_LISTENER( listenerType ) \ 6098 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 6099 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 6100 namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; } \ 6101 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 6102 #else // CATCH_CONFIG_DISABLE 6103 6104 #define CATCH_REGISTER_REPORTER(name, reporterType) 6105 #define CATCH_REGISTER_LISTENER(listenerType) 6106 6107 #endif // CATCH_CONFIG_DISABLE 6108 6109 // end catch_reporter_registrars.hpp 6110 // Allow users to base their work off existing reporters 6111 // start catch_reporter_compact.h 6112 6113 namespace Catch { 6114 6115 struct CompactReporter : StreamingReporterBase<CompactReporter> { 6116 6117 using StreamingReporterBase::StreamingReporterBase; 6118 6119 ~CompactReporter() override; 6120 6121 static std::string getDescription(); 6122 6123 void noMatchingTestCases(std::string const& spec) override; 6124 6125 void assertionStarting(AssertionInfo const&) override; 6126 6127 bool assertionEnded(AssertionStats const& _assertionStats) override; 6128 6129 void sectionEnded(SectionStats const& _sectionStats) override; 6130 6131 void testRunEnded(TestRunStats const& _testRunStats) override; 6132 6133 }; 6134 6135 } // end namespace Catch 6136 6137 // end catch_reporter_compact.h 6138 // start catch_reporter_console.h 6139 6140 #if defined(_MSC_VER) 6141 #pragma warning(push) 6142 #pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch 6143 // Note that 4062 (not all labels are handled 6144 // and default is missing) is enabled 6145 #endif 6146 6147 namespace Catch { 6148 // Fwd decls 6149 struct SummaryColumn; 6150 class TablePrinter; 6151 6152 struct ConsoleReporter : StreamingReporterBase<ConsoleReporter> { 6153 std::unique_ptr<TablePrinter> m_tablePrinter; 6154 6155 ConsoleReporter(ReporterConfig const& config); 6156 ~ConsoleReporter() override; 6157 static std::string getDescription(); 6158 6159 void noMatchingTestCases(std::string const& spec) override; 6160 6161 void reportInvalidArguments(std::string const&arg) override; 6162 6163 void assertionStarting(AssertionInfo const&) override; 6164 6165 bool assertionEnded(AssertionStats const& _assertionStats) override; 6166 6167 void sectionStarting(SectionInfo const& _sectionInfo) override; 6168 void sectionEnded(SectionStats const& _sectionStats) override; 6169 6170 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 6171 void benchmarkPreparing(std::string const& name) override; 6172 void benchmarkStarting(BenchmarkInfo const& info) override; 6173 void benchmarkEnded(BenchmarkStats<> const& stats) override; 6174 void benchmarkFailed(std::string const& error) override; 6175 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 6176 6177 void testCaseEnded(TestCaseStats const& _testCaseStats) override; 6178 void testGroupEnded(TestGroupStats const& _testGroupStats) override; 6179 void testRunEnded(TestRunStats const& _testRunStats) override; 6180 void testRunStarting(TestRunInfo const& _testRunInfo) override; 6181 private: 6182 6183 void lazyPrint(); 6184 6185 void lazyPrintWithoutClosingBenchmarkTable(); 6186 void lazyPrintRunInfo(); 6187 void lazyPrintGroupInfo(); 6188 void printTestCaseAndSectionHeader(); 6189 6190 void printClosedHeader(std::string const& _name); 6191 void printOpenHeader(std::string const& _name); 6192 6193 // if string has a : in first line will set indent to follow it on 6194 // subsequent lines 6195 void printHeaderString(std::string const& _string, std::size_t indent = 0); 6196 6197 void printTotals(Totals const& totals); 6198 void printSummaryRow(std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row); 6199 6200 void printTotalsDivider(Totals const& totals); 6201 void printSummaryDivider(); 6202 void printTestFilters(); 6203 6204 private: 6205 bool m_headerPrinted = false; 6206 }; 6207 6208 } // end namespace Catch 6209 6210 #if defined(_MSC_VER) 6211 #pragma warning(pop) 6212 #endif 6213 6214 // end catch_reporter_console.h 6215 // start catch_reporter_junit.h 6216 6217 // start catch_xmlwriter.h 6218 6219 #include <vector> 6220 6221 namespace Catch { 6222 enum class XmlFormatting { 6223 None = 0x00, 6224 Indent = 0x01, 6225 Newline = 0x02, 6226 }; 6227 6228 XmlFormatting operator | (XmlFormatting lhs, XmlFormatting rhs); 6229 XmlFormatting operator & (XmlFormatting lhs, XmlFormatting rhs); 6230 6231 class XmlEncode { 6232 public: 6233 enum ForWhat { ForTextNodes, ForAttributes }; 6234 6235 XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes ); 6236 6237 void encodeTo( std::ostream& os ) const; 6238 6239 friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ); 6240 6241 private: 6242 std::string m_str; 6243 ForWhat m_forWhat; 6244 }; 6245 6246 class XmlWriter { 6247 public: 6248 6249 class ScopedElement { 6250 public: 6251 ScopedElement( XmlWriter* writer, XmlFormatting fmt ); 6252 6253 ScopedElement( ScopedElement&& other ) noexcept; 6254 ScopedElement& operator=( ScopedElement&& other ) noexcept; 6255 6256 ~ScopedElement(); 6257 6258 ScopedElement& writeText( std::string const& text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent ); 6259 6260 template<typename T> 6261 ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { 6262 m_writer->writeAttribute( name, attribute ); 6263 return *this; 6264 } 6265 6266 private: 6267 mutable XmlWriter* m_writer = nullptr; 6268 XmlFormatting m_fmt; 6269 }; 6270 6271 XmlWriter( std::ostream& os = Catch::cout() ); 6272 ~XmlWriter(); 6273 6274 XmlWriter( XmlWriter const& ) = delete; 6275 XmlWriter& operator=( XmlWriter const& ) = delete; 6276 6277 XmlWriter& startElement( std::string const& name, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); 6278 6279 ScopedElement scopedElement( std::string const& name, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); 6280 6281 XmlWriter& endElement(XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); 6282 6283 XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ); 6284 6285 XmlWriter& writeAttribute( std::string const& name, bool attribute ); 6286 6287 template<typename T> 6288 XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { 6289 ReusableStringStream rss; 6290 rss << attribute; 6291 return writeAttribute( name, rss.str() ); 6292 } 6293 6294 XmlWriter& writeText( std::string const& text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); 6295 6296 XmlWriter& writeComment(std::string const& text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); 6297 6298 void writeStylesheetRef( std::string const& url ); 6299 6300 XmlWriter& writeBlankLine(); 6301 6302 void ensureTagClosed(); 6303 6304 private: 6305 6306 void applyFormatting(XmlFormatting fmt); 6307 6308 void writeDeclaration(); 6309 6310 void newlineIfNecessary(); 6311 6312 bool m_tagIsOpen = false; 6313 bool m_needsNewline = false; 6314 std::vector<std::string> m_tags; 6315 std::string m_indent; 6316 std::ostream& m_os; 6317 }; 6318 6319 } 6320 6321 // end catch_xmlwriter.h 6322 namespace Catch { 6323 6324 class JunitReporter : public CumulativeReporterBase<JunitReporter> { 6325 public: 6326 JunitReporter(ReporterConfig const& _config); 6327 6328 ~JunitReporter() override; 6329 6330 static std::string getDescription(); 6331 6332 void noMatchingTestCases(std::string const& /*spec*/) override; 6333 6334 void testRunStarting(TestRunInfo const& runInfo) override; 6335 6336 void testGroupStarting(GroupInfo const& groupInfo) override; 6337 6338 void testCaseStarting(TestCaseInfo const& testCaseInfo) override; 6339 bool assertionEnded(AssertionStats const& assertionStats) override; 6340 6341 void testCaseEnded(TestCaseStats const& testCaseStats) override; 6342 6343 void testGroupEnded(TestGroupStats const& testGroupStats) override; 6344 6345 void testRunEndedCumulative() override; 6346 6347 void writeGroup(TestGroupNode const& groupNode, double suiteTime); 6348 6349 void writeTestCase(TestCaseNode const& testCaseNode); 6350 6351 void writeSection(std::string const& className, 6352 std::string const& rootName, 6353 SectionNode const& sectionNode); 6354 6355 void writeAssertions(SectionNode const& sectionNode); 6356 void writeAssertion(AssertionStats const& stats); 6357 6358 XmlWriter xml; 6359 Timer suiteTimer; 6360 std::string stdOutForSuite; 6361 std::string stdErrForSuite; 6362 unsigned int unexpectedExceptions = 0; 6363 bool m_okToFail = false; 6364 }; 6365 6366 } // end namespace Catch 6367 6368 // end catch_reporter_junit.h 6369 // start catch_reporter_xml.h 6370 6371 namespace Catch { 6372 class XmlReporter : public StreamingReporterBase<XmlReporter> { 6373 public: 6374 XmlReporter(ReporterConfig const& _config); 6375 6376 ~XmlReporter() override; 6377 6378 static std::string getDescription(); 6379 6380 virtual std::string getStylesheetRef() const; 6381 6382 void writeSourceInfo(SourceLineInfo const& sourceInfo); 6383 6384 public: // StreamingReporterBase 6385 6386 void noMatchingTestCases(std::string const& s) override; 6387 6388 void testRunStarting(TestRunInfo const& testInfo) override; 6389 6390 void testGroupStarting(GroupInfo const& groupInfo) override; 6391 6392 void testCaseStarting(TestCaseInfo const& testInfo) override; 6393 6394 void sectionStarting(SectionInfo const& sectionInfo) override; 6395 6396 void assertionStarting(AssertionInfo const&) override; 6397 6398 bool assertionEnded(AssertionStats const& assertionStats) override; 6399 6400 void sectionEnded(SectionStats const& sectionStats) override; 6401 6402 void testCaseEnded(TestCaseStats const& testCaseStats) override; 6403 6404 void testGroupEnded(TestGroupStats const& testGroupStats) override; 6405 6406 void testRunEnded(TestRunStats const& testRunStats) override; 6407 6408 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 6409 void benchmarkPreparing(std::string const& name) override; 6410 void benchmarkStarting(BenchmarkInfo const&) override; 6411 void benchmarkEnded(BenchmarkStats<> const&) override; 6412 void benchmarkFailed(std::string const&) override; 6413 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 6414 6415 private: 6416 Timer m_testCaseTimer; 6417 XmlWriter m_xml; 6418 int m_sectionDepth = 0; 6419 }; 6420 6421 } // end namespace Catch 6422 6423 // end catch_reporter_xml.h 6424 6425 // end catch_external_interfaces.h 6426 #endif 6427 6428 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 6429 // start catch_benchmarking_all.hpp 6430 6431 // A proxy header that includes all of the benchmarking headers to allow 6432 // concise include of the benchmarking features. You should prefer the 6433 // individual includes in standard use. 6434 6435 // start catch_benchmark.hpp 6436 6437 // Benchmark 6438 6439 // start catch_chronometer.hpp 6440 6441 // User-facing chronometer 6442 6443 6444 // start catch_clock.hpp 6445 6446 // Clocks 6447 6448 6449 #include <chrono> 6450 #include <ratio> 6451 6452 namespace Catch { 6453 namespace Benchmark { 6454 template <typename Clock> 6455 using ClockDuration = typename Clock::duration; 6456 template <typename Clock> 6457 using FloatDuration = std::chrono::duration<double, typename Clock::period>; 6458 6459 template <typename Clock> 6460 using TimePoint = typename Clock::time_point; 6461 6462 using default_clock = std::chrono::steady_clock; 6463 6464 template <typename Clock> 6465 struct now { 6466 TimePoint<Clock> operator()() const { 6467 return Clock::now(); 6468 } 6469 }; 6470 6471 using fp_seconds = std::chrono::duration<double, std::ratio<1>>; 6472 } // namespace Benchmark 6473 } // namespace Catch 6474 6475 // end catch_clock.hpp 6476 // start catch_optimizer.hpp 6477 6478 // Hinting the optimizer 6479 6480 6481 #if defined(_MSC_VER) 6482 # include <atomic> // atomic_thread_fence 6483 #endif 6484 6485 namespace Catch { 6486 namespace Benchmark { 6487 #if defined(__GNUC__) || defined(__clang__) 6488 template <typename T> 6489 inline void keep_memory(T* p) { 6490 asm volatile("" : : "g"(p) : "memory"); 6491 } 6492 inline void keep_memory() { 6493 asm volatile("" : : : "memory"); 6494 } 6495 6496 namespace Detail { 6497 inline void optimizer_barrier() { keep_memory(); } 6498 } // namespace Detail 6499 #elif defined(_MSC_VER) 6500 6501 #pragma optimize("", off) 6502 template <typename T> 6503 inline void keep_memory(T* p) { 6504 // thanks @milleniumbug 6505 *reinterpret_cast<char volatile*>(p) = *reinterpret_cast<char const volatile*>(p); 6506 } 6507 // TODO equivalent keep_memory() 6508 #pragma optimize("", on) 6509 6510 namespace Detail { 6511 inline void optimizer_barrier() { 6512 std::atomic_thread_fence(std::memory_order_seq_cst); 6513 } 6514 } // namespace Detail 6515 6516 #endif 6517 6518 template <typename T> 6519 inline void deoptimize_value(T&& x) { 6520 keep_memory(&x); 6521 } 6522 6523 template <typename Fn, typename... Args> 6524 inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> typename std::enable_if<!std::is_same<void, decltype(fn(args...))>::value>::type { 6525 deoptimize_value(std::forward<Fn>(fn) (std::forward<Args...>(args...))); 6526 } 6527 6528 template <typename Fn, typename... Args> 6529 inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> typename std::enable_if<std::is_same<void, decltype(fn(args...))>::value>::type { 6530 std::forward<Fn>(fn) (std::forward<Args...>(args...)); 6531 } 6532 } // namespace Benchmark 6533 } // namespace Catch 6534 6535 // end catch_optimizer.hpp 6536 // start catch_complete_invoke.hpp 6537 6538 // Invoke with a special case for void 6539 6540 6541 #include <type_traits> 6542 #include <utility> 6543 6544 namespace Catch { 6545 namespace Benchmark { 6546 namespace Detail { 6547 template <typename T> 6548 struct CompleteType { using type = T; }; 6549 template <> 6550 struct CompleteType<void> { struct type {}; }; 6551 6552 template <typename T> 6553 using CompleteType_t = typename CompleteType<T>::type; 6554 6555 template <typename Result> 6556 struct CompleteInvoker { 6557 template <typename Fun, typename... Args> 6558 static Result invoke(Fun&& fun, Args&&... args) { 6559 return std::forward<Fun>(fun)(std::forward<Args>(args)...); 6560 } 6561 }; 6562 template <> 6563 struct CompleteInvoker<void> { 6564 template <typename Fun, typename... Args> 6565 static CompleteType_t<void> invoke(Fun&& fun, Args&&... args) { 6566 std::forward<Fun>(fun)(std::forward<Args>(args)...); 6567 return {}; 6568 } 6569 }; 6570 6571 // invoke and not return void :( 6572 template <typename Fun, typename... Args> 6573 CompleteType_t<FunctionReturnType<Fun, Args...>> complete_invoke(Fun&& fun, Args&&... args) { 6574 return CompleteInvoker<FunctionReturnType<Fun, Args...>>::invoke(std::forward<Fun>(fun), std::forward<Args>(args)...); 6575 } 6576 6577 const std::string benchmarkErrorMsg = "a benchmark failed to run successfully"; 6578 } // namespace Detail 6579 6580 template <typename Fun> 6581 Detail::CompleteType_t<FunctionReturnType<Fun>> user_code(Fun&& fun) { 6582 CATCH_TRY{ 6583 return Detail::complete_invoke(std::forward<Fun>(fun)); 6584 } CATCH_CATCH_ALL{ 6585 getResultCapture().benchmarkFailed(translateActiveException()); 6586 CATCH_RUNTIME_ERROR(Detail::benchmarkErrorMsg); 6587 } 6588 } 6589 } // namespace Benchmark 6590 } // namespace Catch 6591 6592 // end catch_complete_invoke.hpp 6593 namespace Catch { 6594 namespace Benchmark { 6595 namespace Detail { 6596 struct ChronometerConcept { 6597 virtual void start() = 0; 6598 virtual void finish() = 0; 6599 virtual ~ChronometerConcept() = default; 6600 }; 6601 template <typename Clock> 6602 struct ChronometerModel final : public ChronometerConcept { 6603 void start() override { started = Clock::now(); } 6604 void finish() override { finished = Clock::now(); } 6605 6606 ClockDuration<Clock> elapsed() const { return finished - started; } 6607 6608 TimePoint<Clock> started; 6609 TimePoint<Clock> finished; 6610 }; 6611 } // namespace Detail 6612 6613 struct Chronometer { 6614 public: 6615 template <typename Fun> 6616 void measure(Fun&& fun) { measure(std::forward<Fun>(fun), is_callable<Fun(int)>()); } 6617 6618 int runs() const { return k; } 6619 6620 Chronometer(Detail::ChronometerConcept& meter, int k) 6621 : impl(&meter) 6622 , k(k) {} 6623 6624 private: 6625 template <typename Fun> 6626 void measure(Fun&& fun, std::false_type) { 6627 measure([&fun](int) { return fun(); }, std::true_type()); 6628 } 6629 6630 template <typename Fun> 6631 void measure(Fun&& fun, std::true_type) { 6632 Detail::optimizer_barrier(); 6633 impl->start(); 6634 for (int i = 0; i < k; ++i) invoke_deoptimized(fun, i); 6635 impl->finish(); 6636 Detail::optimizer_barrier(); 6637 } 6638 6639 Detail::ChronometerConcept* impl; 6640 int k; 6641 }; 6642 } // namespace Benchmark 6643 } // namespace Catch 6644 6645 // end catch_chronometer.hpp 6646 // start catch_environment.hpp 6647 6648 // Environment information 6649 6650 6651 namespace Catch { 6652 namespace Benchmark { 6653 template <typename Duration> 6654 struct EnvironmentEstimate { 6655 Duration mean; 6656 OutlierClassification outliers; 6657 6658 template <typename Duration2> 6659 operator EnvironmentEstimate<Duration2>() const { 6660 return { mean, outliers }; 6661 } 6662 }; 6663 template <typename Clock> 6664 struct Environment { 6665 using clock_type = Clock; 6666 EnvironmentEstimate<FloatDuration<Clock>> clock_resolution; 6667 EnvironmentEstimate<FloatDuration<Clock>> clock_cost; 6668 }; 6669 } // namespace Benchmark 6670 } // namespace Catch 6671 6672 // end catch_environment.hpp 6673 // start catch_execution_plan.hpp 6674 6675 // Execution plan 6676 6677 6678 // start catch_benchmark_function.hpp 6679 6680 // Dumb std::function implementation for consistent call overhead 6681 6682 6683 #include <cassert> 6684 #include <type_traits> 6685 #include <utility> 6686 #include <memory> 6687 6688 namespace Catch { 6689 namespace Benchmark { 6690 namespace Detail { 6691 template <typename T> 6692 using Decay = typename std::decay<T>::type; 6693 template <typename T, typename U> 6694 struct is_related 6695 : std::is_same<Decay<T>, Decay<U>> {}; 6696 6697 /// We need to reinvent std::function because every piece of code that might add overhead 6698 /// in a measurement context needs to have consistent performance characteristics so that we 6699 /// can account for it in the measurement. 6700 /// Implementations of std::function with optimizations that aren't always applicable, like 6701 /// small buffer optimizations, are not uncommon. 6702 /// This is effectively an implementation of std::function without any such optimizations; 6703 /// it may be slow, but it is consistently slow. 6704 struct BenchmarkFunction { 6705 private: 6706 struct callable { 6707 virtual void call(Chronometer meter) const = 0; 6708 virtual callable* clone() const = 0; 6709 virtual ~callable() = default; 6710 }; 6711 template <typename Fun> 6712 struct model : public callable { 6713 model(Fun&& fun) : fun(std::move(fun)) {} 6714 model(Fun const& fun) : fun(fun) {} 6715 6716 model<Fun>* clone() const override { return new model<Fun>(*this); } 6717 6718 void call(Chronometer meter) const override { 6719 call(meter, is_callable<Fun(Chronometer)>()); 6720 } 6721 void call(Chronometer meter, std::true_type) const { 6722 fun(meter); 6723 } 6724 void call(Chronometer meter, std::false_type) const { 6725 meter.measure(fun); 6726 } 6727 6728 Fun fun; 6729 }; 6730 6731 struct do_nothing { void operator()() const {} }; 6732 6733 template <typename T> 6734 BenchmarkFunction(model<T>* c) : f(c) {} 6735 6736 public: 6737 BenchmarkFunction() 6738 : f(new model<do_nothing>{ {} }) {} 6739 6740 template <typename Fun, 6741 typename std::enable_if<!is_related<Fun, BenchmarkFunction>::value, int>::type = 0> 6742 BenchmarkFunction(Fun&& fun) 6743 : f(new model<typename std::decay<Fun>::type>(std::forward<Fun>(fun))) {} 6744 6745 BenchmarkFunction(BenchmarkFunction&& that) 6746 : f(std::move(that.f)) {} 6747 6748 BenchmarkFunction(BenchmarkFunction const& that) 6749 : f(that.f->clone()) {} 6750 6751 BenchmarkFunction& operator=(BenchmarkFunction&& that) { 6752 f = std::move(that.f); 6753 return *this; 6754 } 6755 6756 BenchmarkFunction& operator=(BenchmarkFunction const& that) { 6757 f.reset(that.f->clone()); 6758 return *this; 6759 } 6760 6761 void operator()(Chronometer meter) const { f->call(meter); } 6762 6763 private: 6764 std::unique_ptr<callable> f; 6765 }; 6766 } // namespace Detail 6767 } // namespace Benchmark 6768 } // namespace Catch 6769 6770 // end catch_benchmark_function.hpp 6771 // start catch_repeat.hpp 6772 6773 // repeat algorithm 6774 6775 6776 #include <type_traits> 6777 #include <utility> 6778 6779 namespace Catch { 6780 namespace Benchmark { 6781 namespace Detail { 6782 template <typename Fun> 6783 struct repeater { 6784 void operator()(int k) const { 6785 for (int i = 0; i < k; ++i) { 6786 fun(); 6787 } 6788 } 6789 Fun fun; 6790 }; 6791 template <typename Fun> 6792 repeater<typename std::decay<Fun>::type> repeat(Fun&& fun) { 6793 return { std::forward<Fun>(fun) }; 6794 } 6795 } // namespace Detail 6796 } // namespace Benchmark 6797 } // namespace Catch 6798 6799 // end catch_repeat.hpp 6800 // start catch_run_for_at_least.hpp 6801 6802 // Run a function for a minimum amount of time 6803 6804 6805 // start catch_measure.hpp 6806 6807 // Measure 6808 6809 6810 // start catch_timing.hpp 6811 6812 // Timing 6813 6814 6815 #include <tuple> 6816 #include <type_traits> 6817 6818 namespace Catch { 6819 namespace Benchmark { 6820 template <typename Duration, typename Result> 6821 struct Timing { 6822 Duration elapsed; 6823 Result result; 6824 int iterations; 6825 }; 6826 template <typename Clock, typename Func, typename... Args> 6827 using TimingOf = Timing<ClockDuration<Clock>, Detail::CompleteType_t<FunctionReturnType<Func, Args...>>>; 6828 } // namespace Benchmark 6829 } // namespace Catch 6830 6831 // end catch_timing.hpp 6832 #include <utility> 6833 6834 namespace Catch { 6835 namespace Benchmark { 6836 namespace Detail { 6837 template <typename Clock, typename Fun, typename... Args> 6838 TimingOf<Clock, Fun, Args...> measure(Fun&& fun, Args&&... args) { 6839 auto start = Clock::now(); 6840 auto&& r = Detail::complete_invoke(fun, std::forward<Args>(args)...); 6841 auto end = Clock::now(); 6842 auto delta = end - start; 6843 return { delta, std::forward<decltype(r)>(r), 1 }; 6844 } 6845 } // namespace Detail 6846 } // namespace Benchmark 6847 } // namespace Catch 6848 6849 // end catch_measure.hpp 6850 #include <utility> 6851 #include <type_traits> 6852 6853 namespace Catch { 6854 namespace Benchmark { 6855 namespace Detail { 6856 template <typename Clock, typename Fun> 6857 TimingOf<Clock, Fun, int> measure_one(Fun&& fun, int iters, std::false_type) { 6858 return Detail::measure<Clock>(fun, iters); 6859 } 6860 template <typename Clock, typename Fun> 6861 TimingOf<Clock, Fun, Chronometer> measure_one(Fun&& fun, int iters, std::true_type) { 6862 Detail::ChronometerModel<Clock> meter; 6863 auto&& result = Detail::complete_invoke(fun, Chronometer(meter, iters)); 6864 6865 return { meter.elapsed(), std::move(result), iters }; 6866 } 6867 6868 template <typename Clock, typename Fun> 6869 using run_for_at_least_argument_t = typename std::conditional<is_callable<Fun(Chronometer)>::value, Chronometer, int>::type; 6870 6871 struct optimized_away_error : std::exception { 6872 const char* what() const noexcept override { 6873 return "could not measure benchmark, maybe it was optimized away"; 6874 } 6875 }; 6876 6877 template <typename Clock, typename Fun> 6878 TimingOf<Clock, Fun, run_for_at_least_argument_t<Clock, Fun>> run_for_at_least(ClockDuration<Clock> how_long, int seed, Fun&& fun) { 6879 auto iters = seed; 6880 while (iters < (1 << 30)) { 6881 auto&& Timing = measure_one<Clock>(fun, iters, is_callable<Fun(Chronometer)>()); 6882 6883 if (Timing.elapsed >= how_long) { 6884 return { Timing.elapsed, std::move(Timing.result), iters }; 6885 } 6886 iters *= 2; 6887 } 6888 throw optimized_away_error{}; 6889 } 6890 } // namespace Detail 6891 } // namespace Benchmark 6892 } // namespace Catch 6893 6894 // end catch_run_for_at_least.hpp 6895 #include <algorithm> 6896 6897 namespace Catch { 6898 namespace Benchmark { 6899 template <typename Duration> 6900 struct ExecutionPlan { 6901 int iterations_per_sample; 6902 Duration estimated_duration; 6903 Detail::BenchmarkFunction benchmark; 6904 Duration warmup_time; 6905 int warmup_iterations; 6906 6907 template <typename Duration2> 6908 operator ExecutionPlan<Duration2>() const { 6909 return { iterations_per_sample, estimated_duration, benchmark, warmup_time, warmup_iterations }; 6910 } 6911 6912 template <typename Clock> 6913 std::vector<FloatDuration<Clock>> run(const IConfig &cfg, Environment<FloatDuration<Clock>> env) const { 6914 // warmup a bit 6915 Detail::run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(warmup_time), warmup_iterations, Detail::repeat(now<Clock>{})); 6916 6917 std::vector<FloatDuration<Clock>> times; 6918 times.reserve(cfg.benchmarkSamples()); 6919 std::generate_n(std::back_inserter(times), cfg.benchmarkSamples(), [this, env] { 6920 Detail::ChronometerModel<Clock> model; 6921 this->benchmark(Chronometer(model, iterations_per_sample)); 6922 auto sample_time = model.elapsed() - env.clock_cost.mean; 6923 if (sample_time < FloatDuration<Clock>::zero()) sample_time = FloatDuration<Clock>::zero(); 6924 return sample_time / iterations_per_sample; 6925 }); 6926 return times; 6927 } 6928 }; 6929 } // namespace Benchmark 6930 } // namespace Catch 6931 6932 // end catch_execution_plan.hpp 6933 // start catch_estimate_clock.hpp 6934 6935 // Environment measurement 6936 6937 6938 // start catch_stats.hpp 6939 6940 // Statistical analysis tools 6941 6942 6943 #include <algorithm> 6944 #include <functional> 6945 #include <vector> 6946 #include <iterator> 6947 #include <numeric> 6948 #include <tuple> 6949 #include <cmath> 6950 #include <utility> 6951 #include <cstddef> 6952 #include <random> 6953 6954 namespace Catch { 6955 namespace Benchmark { 6956 namespace Detail { 6957 using sample = std::vector<double>; 6958 6959 double weighted_average_quantile(int k, int q, std::vector<double>::iterator first, std::vector<double>::iterator last); 6960 6961 template <typename Iterator> 6962 OutlierClassification classify_outliers(Iterator first, Iterator last) { 6963 std::vector<double> copy(first, last); 6964 6965 auto q1 = weighted_average_quantile(1, 4, copy.begin(), copy.end()); 6966 auto q3 = weighted_average_quantile(3, 4, copy.begin(), copy.end()); 6967 auto iqr = q3 - q1; 6968 auto los = q1 - (iqr * 3.); 6969 auto lom = q1 - (iqr * 1.5); 6970 auto him = q3 + (iqr * 1.5); 6971 auto his = q3 + (iqr * 3.); 6972 6973 OutlierClassification o; 6974 for (; first != last; ++first) { 6975 auto&& t = *first; 6976 if (t < los) ++o.low_severe; 6977 else if (t < lom) ++o.low_mild; 6978 else if (t > his) ++o.high_severe; 6979 else if (t > him) ++o.high_mild; 6980 ++o.samples_seen; 6981 } 6982 return o; 6983 } 6984 6985 template <typename Iterator> 6986 double mean(Iterator first, Iterator last) { 6987 auto count = last - first; 6988 double sum = std::accumulate(first, last, 0.); 6989 return sum / count; 6990 } 6991 6992 template <typename URng, typename Iterator, typename Estimator> 6993 sample resample(URng& rng, int resamples, Iterator first, Iterator last, Estimator& estimator) { 6994 auto n = last - first; 6995 std::uniform_int_distribution<decltype(n)> dist(0, n - 1); 6996 6997 sample out; 6998 out.reserve(resamples); 6999 std::generate_n(std::back_inserter(out), resamples, [n, first, &estimator, &dist, &rng] { 7000 std::vector<double> resampled; 7001 resampled.reserve(n); 7002 std::generate_n(std::back_inserter(resampled), n, [first, &dist, &rng] { return first[dist(rng)]; }); 7003 return estimator(resampled.begin(), resampled.end()); 7004 }); 7005 std::sort(out.begin(), out.end()); 7006 return out; 7007 } 7008 7009 template <typename Estimator, typename Iterator> 7010 sample jackknife(Estimator&& estimator, Iterator first, Iterator last) { 7011 auto n = last - first; 7012 auto second = std::next(first); 7013 sample results; 7014 results.reserve(n); 7015 7016 for (auto it = first; it != last; ++it) { 7017 std::iter_swap(it, first); 7018 results.push_back(estimator(second, last)); 7019 } 7020 7021 return results; 7022 } 7023 7024 inline double normal_cdf(double x) { 7025 return std::erfc(-x / std::sqrt(2.0)) / 2.0; 7026 } 7027 7028 double erfc_inv(double x); 7029 7030 double normal_quantile(double p); 7031 7032 template <typename Iterator, typename Estimator> 7033 Estimate<double> bootstrap(double confidence_level, Iterator first, Iterator last, sample const& resample, Estimator&& estimator) { 7034 auto n_samples = last - first; 7035 7036 double point = estimator(first, last); 7037 // Degenerate case with a single sample 7038 if (n_samples == 1) return { point, point, point, confidence_level }; 7039 7040 sample jack = jackknife(estimator, first, last); 7041 double jack_mean = mean(jack.begin(), jack.end()); 7042 double sum_squares, sum_cubes; 7043 std::tie(sum_squares, sum_cubes) = std::accumulate(jack.begin(), jack.end(), std::make_pair(0., 0.), [jack_mean](std::pair<double, double> sqcb, double x) -> std::pair<double, double> { 7044 auto d = jack_mean - x; 7045 auto d2 = d * d; 7046 auto d3 = d2 * d; 7047 return { sqcb.first + d2, sqcb.second + d3 }; 7048 }); 7049 7050 double accel = sum_cubes / (6 * std::pow(sum_squares, 1.5)); 7051 int n = static_cast<int>(resample.size()); 7052 double prob_n = std::count_if(resample.begin(), resample.end(), [point](double x) { return x < point; }) / (double)n; 7053 // degenerate case with uniform samples 7054 if (prob_n == 0) return { point, point, point, confidence_level }; 7055 7056 double bias = normal_quantile(prob_n); 7057 double z1 = normal_quantile((1. - confidence_level) / 2.); 7058 7059 auto cumn = [n](double x) -> int { 7060 return std::lround(normal_cdf(x) * n); }; 7061 auto a = [bias, accel](double b) { return bias + b / (1. - accel * b); }; 7062 double b1 = bias + z1; 7063 double b2 = bias - z1; 7064 double a1 = a(b1); 7065 double a2 = a(b2); 7066 auto lo = std::max(cumn(a1), 0); 7067 auto hi = std::min(cumn(a2), n - 1); 7068 7069 return { point, resample[lo], resample[hi], confidence_level }; 7070 } 7071 7072 double outlier_variance(Estimate<double> mean, Estimate<double> stddev, int n); 7073 7074 struct bootstrap_analysis { 7075 Estimate<double> mean; 7076 Estimate<double> standard_deviation; 7077 double outlier_variance; 7078 }; 7079 7080 bootstrap_analysis analyse_samples(double confidence_level, int n_resamples, std::vector<double>::iterator first, std::vector<double>::iterator last); 7081 } // namespace Detail 7082 } // namespace Benchmark 7083 } // namespace Catch 7084 7085 // end catch_stats.hpp 7086 #include <algorithm> 7087 #include <iterator> 7088 #include <tuple> 7089 #include <vector> 7090 #include <cmath> 7091 7092 namespace Catch { 7093 namespace Benchmark { 7094 namespace Detail { 7095 template <typename Clock> 7096 std::vector<double> resolution(int k) { 7097 std::vector<TimePoint<Clock>> times; 7098 times.reserve(k + 1); 7099 std::generate_n(std::back_inserter(times), k + 1, now<Clock>{}); 7100 7101 std::vector<double> deltas; 7102 deltas.reserve(k); 7103 std::transform(std::next(times.begin()), times.end(), times.begin(), 7104 std::back_inserter(deltas), 7105 [](TimePoint<Clock> a, TimePoint<Clock> b) { return static_cast<double>((a - b).count()); }); 7106 7107 return deltas; 7108 } 7109 7110 const auto warmup_iterations = 10000; 7111 const auto warmup_time = std::chrono::milliseconds(100); 7112 const auto minimum_ticks = 1000; 7113 const auto warmup_seed = 10000; 7114 const auto clock_resolution_estimation_time = std::chrono::milliseconds(500); 7115 const auto clock_cost_estimation_time_limit = std::chrono::seconds(1); 7116 const auto clock_cost_estimation_tick_limit = 100000; 7117 const auto clock_cost_estimation_time = std::chrono::milliseconds(10); 7118 const auto clock_cost_estimation_iterations = 10000; 7119 7120 template <typename Clock> 7121 int warmup() { 7122 return run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(warmup_time), warmup_seed, &resolution<Clock>) 7123 .iterations; 7124 } 7125 template <typename Clock> 7126 EnvironmentEstimate<FloatDuration<Clock>> estimate_clock_resolution(int iterations) { 7127 auto r = run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(clock_resolution_estimation_time), iterations, &resolution<Clock>) 7128 .result; 7129 return { 7130 FloatDuration<Clock>(mean(r.begin(), r.end())), 7131 classify_outliers(r.begin(), r.end()), 7132 }; 7133 } 7134 template <typename Clock> 7135 EnvironmentEstimate<FloatDuration<Clock>> estimate_clock_cost(FloatDuration<Clock> resolution) { 7136 auto time_limit = std::min(resolution * clock_cost_estimation_tick_limit, FloatDuration<Clock>(clock_cost_estimation_time_limit)); 7137 auto time_clock = [](int k) { 7138 return Detail::measure<Clock>([k] { 7139 for (int i = 0; i < k; ++i) { 7140 volatile auto ignored = Clock::now(); 7141 (void)ignored; 7142 } 7143 }).elapsed; 7144 }; 7145 time_clock(1); 7146 int iters = clock_cost_estimation_iterations; 7147 auto&& r = run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(clock_cost_estimation_time), iters, time_clock); 7148 std::vector<double> times; 7149 int nsamples = static_cast<int>(std::ceil(time_limit / r.elapsed)); 7150 times.reserve(nsamples); 7151 std::generate_n(std::back_inserter(times), nsamples, [time_clock, &r] { 7152 return static_cast<double>((time_clock(r.iterations) / r.iterations).count()); 7153 }); 7154 return { 7155 FloatDuration<Clock>(mean(times.begin(), times.end())), 7156 classify_outliers(times.begin(), times.end()), 7157 }; 7158 } 7159 7160 template <typename Clock> 7161 Environment<FloatDuration<Clock>> measure_environment() { 7162 static Environment<FloatDuration<Clock>>* env = nullptr; 7163 if (env) { 7164 return *env; 7165 } 7166 7167 auto iters = Detail::warmup<Clock>(); 7168 auto resolution = Detail::estimate_clock_resolution<Clock>(iters); 7169 auto cost = Detail::estimate_clock_cost<Clock>(resolution.mean); 7170 7171 env = new Environment<FloatDuration<Clock>>{ resolution, cost }; 7172 return *env; 7173 } 7174 } // namespace Detail 7175 } // namespace Benchmark 7176 } // namespace Catch 7177 7178 // end catch_estimate_clock.hpp 7179 // start catch_analyse.hpp 7180 7181 // Run and analyse one benchmark 7182 7183 7184 // start catch_sample_analysis.hpp 7185 7186 // Benchmark results 7187 7188 7189 #include <algorithm> 7190 #include <vector> 7191 #include <string> 7192 #include <iterator> 7193 7194 namespace Catch { 7195 namespace Benchmark { 7196 template <typename Duration> 7197 struct SampleAnalysis { 7198 std::vector<Duration> samples; 7199 Estimate<Duration> mean; 7200 Estimate<Duration> standard_deviation; 7201 OutlierClassification outliers; 7202 double outlier_variance; 7203 7204 template <typename Duration2> 7205 operator SampleAnalysis<Duration2>() const { 7206 std::vector<Duration2> samples2; 7207 samples2.reserve(samples.size()); 7208 std::transform(samples.begin(), samples.end(), std::back_inserter(samples2), [](Duration d) { return Duration2(d); }); 7209 return { 7210 std::move(samples2), 7211 mean, 7212 standard_deviation, 7213 outliers, 7214 outlier_variance, 7215 }; 7216 } 7217 }; 7218 } // namespace Benchmark 7219 } // namespace Catch 7220 7221 // end catch_sample_analysis.hpp 7222 #include <algorithm> 7223 #include <iterator> 7224 #include <vector> 7225 7226 namespace Catch { 7227 namespace Benchmark { 7228 namespace Detail { 7229 template <typename Duration, typename Iterator> 7230 SampleAnalysis<Duration> analyse(const IConfig &cfg, Environment<Duration>, Iterator first, Iterator last) { 7231 if (!cfg.benchmarkNoAnalysis()) { 7232 std::vector<double> samples; 7233 samples.reserve(last - first); 7234 std::transform(first, last, std::back_inserter(samples), [](Duration d) { return d.count(); }); 7235 7236 auto analysis = Catch::Benchmark::Detail::analyse_samples(cfg.benchmarkConfidenceInterval(), cfg.benchmarkResamples(), samples.begin(), samples.end()); 7237 auto outliers = Catch::Benchmark::Detail::classify_outliers(samples.begin(), samples.end()); 7238 7239 auto wrap_estimate = [](Estimate<double> e) { 7240 return Estimate<Duration> { 7241 Duration(e.point), 7242 Duration(e.lower_bound), 7243 Duration(e.upper_bound), 7244 e.confidence_interval, 7245 }; 7246 }; 7247 std::vector<Duration> samples2; 7248 samples2.reserve(samples.size()); 7249 std::transform(samples.begin(), samples.end(), std::back_inserter(samples2), [](double d) { return Duration(d); }); 7250 return { 7251 std::move(samples2), 7252 wrap_estimate(analysis.mean), 7253 wrap_estimate(analysis.standard_deviation), 7254 outliers, 7255 analysis.outlier_variance, 7256 }; 7257 } else { 7258 std::vector<Duration> samples; 7259 samples.reserve(last - first); 7260 7261 Duration mean = Duration(0); 7262 int i = 0; 7263 for (auto it = first; it < last; ++it, ++i) { 7264 samples.push_back(Duration(*it)); 7265 mean += Duration(*it); 7266 } 7267 mean /= i; 7268 7269 return { 7270 std::move(samples), 7271 Estimate<Duration>{mean, mean, mean, 0.0}, 7272 Estimate<Duration>{Duration(0), Duration(0), Duration(0), 0.0}, 7273 OutlierClassification{}, 7274 0.0 7275 }; 7276 } 7277 } 7278 } // namespace Detail 7279 } // namespace Benchmark 7280 } // namespace Catch 7281 7282 // end catch_analyse.hpp 7283 #include <algorithm> 7284 #include <functional> 7285 #include <string> 7286 #include <vector> 7287 #include <cmath> 7288 7289 namespace Catch { 7290 namespace Benchmark { 7291 struct Benchmark { 7292 Benchmark(std::string &&name) 7293 : name(std::move(name)) {} 7294 7295 template <class FUN> 7296 Benchmark(std::string &&name, FUN &&func) 7297 : fun(std::move(func)), name(std::move(name)) {} 7298 7299 template <typename Clock> 7300 ExecutionPlan<FloatDuration<Clock>> prepare(const IConfig &cfg, Environment<FloatDuration<Clock>> env) const { 7301 auto min_time = env.clock_resolution.mean * Detail::minimum_ticks; 7302 auto run_time = std::max(min_time, std::chrono::duration_cast<decltype(min_time)>(cfg.benchmarkWarmupTime())); 7303 auto&& test = Detail::run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(run_time), 1, fun); 7304 int new_iters = static_cast<int>(std::ceil(min_time * test.iterations / test.elapsed)); 7305 return { new_iters, test.elapsed / test.iterations * new_iters * cfg.benchmarkSamples(), fun, std::chrono::duration_cast<FloatDuration<Clock>>(cfg.benchmarkWarmupTime()), Detail::warmup_iterations }; 7306 } 7307 7308 template <typename Clock = default_clock> 7309 void run() { 7310 IConfigPtr cfg = getCurrentContext().getConfig(); 7311 7312 auto env = Detail::measure_environment<Clock>(); 7313 7314 getResultCapture().benchmarkPreparing(name); 7315 CATCH_TRY{ 7316 auto plan = user_code([&] { 7317 return prepare<Clock>(*cfg, env); 7318 }); 7319 7320 BenchmarkInfo info { 7321 name, 7322 plan.estimated_duration.count(), 7323 plan.iterations_per_sample, 7324 cfg->benchmarkSamples(), 7325 cfg->benchmarkResamples(), 7326 env.clock_resolution.mean.count(), 7327 env.clock_cost.mean.count() 7328 }; 7329 7330 getResultCapture().benchmarkStarting(info); 7331 7332 auto samples = user_code([&] { 7333 return plan.template run<Clock>(*cfg, env); 7334 }); 7335 7336 auto analysis = Detail::analyse(*cfg, env, samples.begin(), samples.end()); 7337 BenchmarkStats<FloatDuration<Clock>> stats{ info, analysis.samples, analysis.mean, analysis.standard_deviation, analysis.outliers, analysis.outlier_variance }; 7338 getResultCapture().benchmarkEnded(stats); 7339 7340 } CATCH_CATCH_ALL{ 7341 if (translateActiveException() != Detail::benchmarkErrorMsg) // benchmark errors have been reported, otherwise rethrow. 7342 std::rethrow_exception(std::current_exception()); 7343 } 7344 } 7345 7346 // sets lambda to be used in fun *and* executes benchmark! 7347 template <typename Fun, 7348 typename std::enable_if<!Detail::is_related<Fun, Benchmark>::value, int>::type = 0> 7349 Benchmark & operator=(Fun func) { 7350 fun = Detail::BenchmarkFunction(func); 7351 run(); 7352 return *this; 7353 } 7354 7355 explicit operator bool() { 7356 return true; 7357 } 7358 7359 private: 7360 Detail::BenchmarkFunction fun; 7361 std::string name; 7362 }; 7363 } 7364 } // namespace Catch 7365 7366 #define INTERNAL_CATCH_GET_1_ARG(arg1, arg2, ...) arg1 7367 #define INTERNAL_CATCH_GET_2_ARG(arg1, arg2, ...) arg2 7368 7369 #define INTERNAL_CATCH_BENCHMARK(BenchmarkName, name, benchmarkIndex)\ 7370 if( Catch::Benchmark::Benchmark BenchmarkName{name} ) \ 7371 BenchmarkName = [&](int benchmarkIndex) 7372 7373 #define INTERNAL_CATCH_BENCHMARK_ADVANCED(BenchmarkName, name)\ 7374 if( Catch::Benchmark::Benchmark BenchmarkName{name} ) \ 7375 BenchmarkName = [&] 7376 7377 // end catch_benchmark.hpp 7378 // start catch_constructor.hpp 7379 7380 // Constructor and destructor helpers 7381 7382 7383 #include <type_traits> 7384 7385 namespace Catch { 7386 namespace Benchmark { 7387 namespace Detail { 7388 template <typename T, bool Destruct> 7389 struct ObjectStorage 7390 { 7391 using TStorage = typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type; 7392 7393 ObjectStorage() : data() {} 7394 7395 ObjectStorage(const ObjectStorage& other) 7396 { 7397 new(&data) T(other.stored_object()); 7398 } 7399 7400 ObjectStorage(ObjectStorage&& other) 7401 { 7402 new(&data) T(std::move(other.stored_object())); 7403 } 7404 7405 ~ObjectStorage() { destruct_on_exit<T>(); } 7406 7407 template <typename... Args> 7408 void construct(Args&&... args) 7409 { 7410 new (&data) T(std::forward<Args>(args)...); 7411 } 7412 7413 template <bool AllowManualDestruction = !Destruct> 7414 typename std::enable_if<AllowManualDestruction>::type destruct() 7415 { 7416 stored_object().~T(); 7417 } 7418 7419 private: 7420 // If this is a constructor benchmark, destruct the underlying object 7421 template <typename U> 7422 void destruct_on_exit(typename std::enable_if<Destruct, U>::type* = 0) { destruct<true>(); } 7423 // Otherwise, don't 7424 template <typename U> 7425 void destruct_on_exit(typename std::enable_if<!Destruct, U>::type* = 0) { } 7426 7427 T& stored_object() { 7428 return *static_cast<T*>(static_cast<void*>(&data)); 7429 } 7430 7431 T const& stored_object() const { 7432 return *static_cast<T*>(static_cast<void*>(&data)); 7433 } 7434 7435 TStorage data; 7436 }; 7437 } 7438 7439 template <typename T> 7440 using storage_for = Detail::ObjectStorage<T, true>; 7441 7442 template <typename T> 7443 using destructable_object = Detail::ObjectStorage<T, false>; 7444 } 7445 } 7446 7447 // end catch_constructor.hpp 7448 // end catch_benchmarking_all.hpp 7449 #endif 7450 7451 #endif // ! CATCH_CONFIG_IMPL_ONLY 7452 7453 #ifdef CATCH_IMPL 7454 // start catch_impl.hpp 7455 7456 #ifdef __clang__ 7457 #pragma clang diagnostic push 7458 #pragma clang diagnostic ignored "-Wweak-vtables" 7459 #endif 7460 7461 // Keep these here for external reporters 7462 // start catch_test_case_tracker.h 7463 7464 #include <string> 7465 #include <vector> 7466 #include <memory> 7467 7468 namespace Catch { 7469 namespace TestCaseTracking { 7470 7471 struct NameAndLocation { 7472 std::string name; 7473 SourceLineInfo location; 7474 7475 NameAndLocation( std::string const& _name, SourceLineInfo const& _location ); 7476 friend bool operator==(NameAndLocation const& lhs, NameAndLocation const& rhs) { 7477 return lhs.name == rhs.name 7478 && lhs.location == rhs.location; 7479 } 7480 }; 7481 7482 class ITracker; 7483 7484 using ITrackerPtr = std::shared_ptr<ITracker>; 7485 7486 class ITracker { 7487 NameAndLocation m_nameAndLocation; 7488 7489 public: 7490 ITracker(NameAndLocation const& nameAndLoc) : 7491 m_nameAndLocation(nameAndLoc) 7492 {} 7493 7494 // static queries 7495 NameAndLocation const& nameAndLocation() const { 7496 return m_nameAndLocation; 7497 } 7498 7499 virtual ~ITracker(); 7500 7501 // dynamic queries 7502 virtual bool isComplete() const = 0; // Successfully completed or failed 7503 virtual bool isSuccessfullyCompleted() const = 0; 7504 virtual bool isOpen() const = 0; // Started but not complete 7505 virtual bool hasChildren() const = 0; 7506 virtual bool hasStarted() const = 0; 7507 7508 virtual ITracker& parent() = 0; 7509 7510 // actions 7511 virtual void close() = 0; // Successfully complete 7512 virtual void fail() = 0; 7513 virtual void markAsNeedingAnotherRun() = 0; 7514 7515 virtual void addChild( ITrackerPtr const& child ) = 0; 7516 virtual ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) = 0; 7517 virtual void openChild() = 0; 7518 7519 // Debug/ checking 7520 virtual bool isSectionTracker() const = 0; 7521 virtual bool isGeneratorTracker() const = 0; 7522 }; 7523 7524 class TrackerContext { 7525 7526 enum RunState { 7527 NotStarted, 7528 Executing, 7529 CompletedCycle 7530 }; 7531 7532 ITrackerPtr m_rootTracker; 7533 ITracker* m_currentTracker = nullptr; 7534 RunState m_runState = NotStarted; 7535 7536 public: 7537 7538 ITracker& startRun(); 7539 void endRun(); 7540 7541 void startCycle(); 7542 void completeCycle(); 7543 7544 bool completedCycle() const; 7545 ITracker& currentTracker(); 7546 void setCurrentTracker( ITracker* tracker ); 7547 }; 7548 7549 class TrackerBase : public ITracker { 7550 protected: 7551 enum CycleState { 7552 NotStarted, 7553 Executing, 7554 ExecutingChildren, 7555 NeedsAnotherRun, 7556 CompletedSuccessfully, 7557 Failed 7558 }; 7559 7560 using Children = std::vector<ITrackerPtr>; 7561 TrackerContext& m_ctx; 7562 ITracker* m_parent; 7563 Children m_children; 7564 CycleState m_runState = NotStarted; 7565 7566 public: 7567 TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ); 7568 7569 bool isComplete() const override; 7570 bool isSuccessfullyCompleted() const override; 7571 bool isOpen() const override; 7572 bool hasChildren() const override; 7573 bool hasStarted() const override { 7574 return m_runState != NotStarted; 7575 } 7576 7577 void addChild( ITrackerPtr const& child ) override; 7578 7579 ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) override; 7580 ITracker& parent() override; 7581 7582 void openChild() override; 7583 7584 bool isSectionTracker() const override; 7585 bool isGeneratorTracker() const override; 7586 7587 void open(); 7588 7589 void close() override; 7590 void fail() override; 7591 void markAsNeedingAnotherRun() override; 7592 7593 private: 7594 void moveToParent(); 7595 void moveToThis(); 7596 }; 7597 7598 class SectionTracker : public TrackerBase { 7599 std::vector<std::string> m_filters; 7600 std::string m_trimmed_name; 7601 public: 7602 SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ); 7603 7604 bool isSectionTracker() const override; 7605 7606 bool isComplete() const override; 7607 7608 static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ); 7609 7610 void tryOpen(); 7611 7612 void addInitialFilters( std::vector<std::string> const& filters ); 7613 void addNextFilters( std::vector<std::string> const& filters ); 7614 }; 7615 7616 } // namespace TestCaseTracking 7617 7618 using TestCaseTracking::ITracker; 7619 using TestCaseTracking::TrackerContext; 7620 using TestCaseTracking::SectionTracker; 7621 7622 } // namespace Catch 7623 7624 // end catch_test_case_tracker.h 7625 7626 // start catch_leak_detector.h 7627 7628 namespace Catch { 7629 7630 struct LeakDetector { 7631 LeakDetector(); 7632 ~LeakDetector(); 7633 }; 7634 7635 } 7636 // end catch_leak_detector.h 7637 // Cpp files will be included in the single-header file here 7638 // start catch_stats.cpp 7639 7640 // Statistical analysis tools 7641 7642 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 7643 7644 #include <cassert> 7645 #include <random> 7646 7647 #if defined(CATCH_CONFIG_USE_ASYNC) 7648 #include <future> 7649 #endif 7650 7651 namespace { 7652 double erf_inv(double x) { 7653 // Code accompanying the article "Approximating the erfinv function" in GPU Computing Gems, Volume 2 7654 double w, p; 7655 7656 w = -log((1.0 - x) * (1.0 + x)); 7657 7658 if (w < 6.250000) { 7659 w = w - 3.125000; 7660 p = -3.6444120640178196996e-21; 7661 p = -1.685059138182016589e-19 + p * w; 7662 p = 1.2858480715256400167e-18 + p * w; 7663 p = 1.115787767802518096e-17 + p * w; 7664 p = -1.333171662854620906e-16 + p * w; 7665 p = 2.0972767875968561637e-17 + p * w; 7666 p = 6.6376381343583238325e-15 + p * w; 7667 p = -4.0545662729752068639e-14 + p * w; 7668 p = -8.1519341976054721522e-14 + p * w; 7669 p = 2.6335093153082322977e-12 + p * w; 7670 p = -1.2975133253453532498e-11 + p * w; 7671 p = -5.4154120542946279317e-11 + p * w; 7672 p = 1.051212273321532285e-09 + p * w; 7673 p = -4.1126339803469836976e-09 + p * w; 7674 p = -2.9070369957882005086e-08 + p * w; 7675 p = 4.2347877827932403518e-07 + p * w; 7676 p = -1.3654692000834678645e-06 + p * w; 7677 p = -1.3882523362786468719e-05 + p * w; 7678 p = 0.0001867342080340571352 + p * w; 7679 p = -0.00074070253416626697512 + p * w; 7680 p = -0.0060336708714301490533 + p * w; 7681 p = 0.24015818242558961693 + p * w; 7682 p = 1.6536545626831027356 + p * w; 7683 } else if (w < 16.000000) { 7684 w = sqrt(w) - 3.250000; 7685 p = 2.2137376921775787049e-09; 7686 p = 9.0756561938885390979e-08 + p * w; 7687 p = -2.7517406297064545428e-07 + p * w; 7688 p = 1.8239629214389227755e-08 + p * w; 7689 p = 1.5027403968909827627e-06 + p * w; 7690 p = -4.013867526981545969e-06 + p * w; 7691 p = 2.9234449089955446044e-06 + p * w; 7692 p = 1.2475304481671778723e-05 + p * w; 7693 p = -4.7318229009055733981e-05 + p * w; 7694 p = 6.8284851459573175448e-05 + p * w; 7695 p = 2.4031110387097893999e-05 + p * w; 7696 p = -0.0003550375203628474796 + p * w; 7697 p = 0.00095328937973738049703 + p * w; 7698 p = -0.0016882755560235047313 + p * w; 7699 p = 0.0024914420961078508066 + p * w; 7700 p = -0.0037512085075692412107 + p * w; 7701 p = 0.005370914553590063617 + p * w; 7702 p = 1.0052589676941592334 + p * w; 7703 p = 3.0838856104922207635 + p * w; 7704 } else { 7705 w = sqrt(w) - 5.000000; 7706 p = -2.7109920616438573243e-11; 7707 p = -2.5556418169965252055e-10 + p * w; 7708 p = 1.5076572693500548083e-09 + p * w; 7709 p = -3.7894654401267369937e-09 + p * w; 7710 p = 7.6157012080783393804e-09 + p * w; 7711 p = -1.4960026627149240478e-08 + p * w; 7712 p = 2.9147953450901080826e-08 + p * w; 7713 p = -6.7711997758452339498e-08 + p * w; 7714 p = 2.2900482228026654717e-07 + p * w; 7715 p = -9.9298272942317002539e-07 + p * w; 7716 p = 4.5260625972231537039e-06 + p * w; 7717 p = -1.9681778105531670567e-05 + p * w; 7718 p = 7.5995277030017761139e-05 + p * w; 7719 p = -0.00021503011930044477347 + p * w; 7720 p = -0.00013871931833623122026 + p * w; 7721 p = 1.0103004648645343977 + p * w; 7722 p = 4.8499064014085844221 + p * w; 7723 } 7724 return p * x; 7725 } 7726 7727 double standard_deviation(std::vector<double>::iterator first, std::vector<double>::iterator last) { 7728 auto m = Catch::Benchmark::Detail::mean(first, last); 7729 double variance = std::accumulate(first, last, 0., [m](double a, double b) { 7730 double diff = b - m; 7731 return a + diff * diff; 7732 }) / (last - first); 7733 return std::sqrt(variance); 7734 } 7735 7736 } 7737 7738 namespace Catch { 7739 namespace Benchmark { 7740 namespace Detail { 7741 7742 double weighted_average_quantile(int k, int q, std::vector<double>::iterator first, std::vector<double>::iterator last) { 7743 auto count = last - first; 7744 double idx = (count - 1) * k / static_cast<double>(q); 7745 int j = static_cast<int>(idx); 7746 double g = idx - j; 7747 std::nth_element(first, first + j, last); 7748 auto xj = first[j]; 7749 if (g == 0) return xj; 7750 7751 auto xj1 = *std::min_element(first + (j + 1), last); 7752 return xj + g * (xj1 - xj); 7753 } 7754 7755 double erfc_inv(double x) { 7756 return erf_inv(1.0 - x); 7757 } 7758 7759 double normal_quantile(double p) { 7760 static const double ROOT_TWO = std::sqrt(2.0); 7761 7762 double result = 0.0; 7763 assert(p >= 0 && p <= 1); 7764 if (p < 0 || p > 1) { 7765 return result; 7766 } 7767 7768 result = -erfc_inv(2.0 * p); 7769 // result *= normal distribution standard deviation (1.0) * sqrt(2) 7770 result *= /*sd * */ ROOT_TWO; 7771 // result += normal disttribution mean (0) 7772 return result; 7773 } 7774 7775 double outlier_variance(Estimate<double> mean, Estimate<double> stddev, int n) { 7776 double sb = stddev.point; 7777 double mn = mean.point / n; 7778 double mg_min = mn / 2.; 7779 double sg = std::min(mg_min / 4., sb / std::sqrt(n)); 7780 double sg2 = sg * sg; 7781 double sb2 = sb * sb; 7782 7783 auto c_max = [n, mn, sb2, sg2](double x) -> double { 7784 double k = mn - x; 7785 double d = k * k; 7786 double nd = n * d; 7787 double k0 = -n * nd; 7788 double k1 = sb2 - n * sg2 + nd; 7789 double det = k1 * k1 - 4 * sg2 * k0; 7790 return (int)(-2. * k0 / (k1 + std::sqrt(det))); 7791 }; 7792 7793 auto var_out = [n, sb2, sg2](double c) { 7794 double nc = n - c; 7795 return (nc / n) * (sb2 - nc * sg2); 7796 }; 7797 7798 return std::min(var_out(1), var_out(std::min(c_max(0.), c_max(mg_min)))) / sb2; 7799 } 7800 7801 bootstrap_analysis analyse_samples(double confidence_level, int n_resamples, std::vector<double>::iterator first, std::vector<double>::iterator last) { 7802 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION 7803 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS 7804 static std::random_device entropy; 7805 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 7806 7807 auto n = static_cast<int>(last - first); // seriously, one can't use integral types without hell in C++ 7808 7809 auto mean = &Detail::mean<std::vector<double>::iterator>; 7810 auto stddev = &standard_deviation; 7811 7812 #if defined(CATCH_CONFIG_USE_ASYNC) 7813 auto Estimate = [=](double(*f)(std::vector<double>::iterator, std::vector<double>::iterator)) { 7814 auto seed = entropy(); 7815 return std::async(std::launch::async, [=] { 7816 std::mt19937 rng(seed); 7817 auto resampled = resample(rng, n_resamples, first, last, f); 7818 return bootstrap(confidence_level, first, last, resampled, f); 7819 }); 7820 }; 7821 7822 auto mean_future = Estimate(mean); 7823 auto stddev_future = Estimate(stddev); 7824 7825 auto mean_estimate = mean_future.get(); 7826 auto stddev_estimate = stddev_future.get(); 7827 #else 7828 auto Estimate = [=](double(*f)(std::vector<double>::iterator, std::vector<double>::iterator)) { 7829 auto seed = entropy(); 7830 std::mt19937 rng(seed); 7831 auto resampled = resample(rng, n_resamples, first, last, f); 7832 return bootstrap(confidence_level, first, last, resampled, f); 7833 }; 7834 7835 auto mean_estimate = Estimate(mean); 7836 auto stddev_estimate = Estimate(stddev); 7837 #endif // CATCH_USE_ASYNC 7838 7839 double outlier_variance = Detail::outlier_variance(mean_estimate, stddev_estimate, n); 7840 7841 return { mean_estimate, stddev_estimate, outlier_variance }; 7842 } 7843 } // namespace Detail 7844 } // namespace Benchmark 7845 } // namespace Catch 7846 7847 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 7848 // end catch_stats.cpp 7849 // start catch_approx.cpp 7850 7851 #include <cmath> 7852 #include <limits> 7853 7854 namespace { 7855 7856 // Performs equivalent check of std::fabs(lhs - rhs) <= margin 7857 // But without the subtraction to allow for INFINITY in comparison 7858 bool marginComparison(double lhs, double rhs, double margin) { 7859 return (lhs + margin >= rhs) && (rhs + margin >= lhs); 7860 } 7861 7862 } 7863 7864 namespace Catch { 7865 namespace Detail { 7866 7867 Approx::Approx ( double value ) 7868 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ), 7869 m_margin( 0.0 ), 7870 m_scale( 0.0 ), 7871 m_value( value ) 7872 {} 7873 7874 Approx Approx::custom() { 7875 return Approx( 0 ); 7876 } 7877 7878 Approx Approx::operator-() const { 7879 auto temp(*this); 7880 temp.m_value = -temp.m_value; 7881 return temp; 7882 } 7883 7884 std::string Approx::toString() const { 7885 ReusableStringStream rss; 7886 rss << "Approx( " << ::Catch::Detail::stringify( m_value ) << " )"; 7887 return rss.str(); 7888 } 7889 7890 bool Approx::equalityComparisonImpl(const double other) const { 7891 // First try with fixed margin, then compute margin based on epsilon, scale and Approx's value 7892 // Thanks to Richard Harris for his help refining the scaled margin value 7893 return marginComparison(m_value, other, m_margin) 7894 || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(std::isinf(m_value)? 0 : m_value))); 7895 } 7896 7897 void Approx::setMargin(double newMargin) { 7898 CATCH_ENFORCE(newMargin >= 0, 7899 "Invalid Approx::margin: " << newMargin << '.' 7900 << " Approx::Margin has to be non-negative."); 7901 m_margin = newMargin; 7902 } 7903 7904 void Approx::setEpsilon(double newEpsilon) { 7905 CATCH_ENFORCE(newEpsilon >= 0 && newEpsilon <= 1.0, 7906 "Invalid Approx::epsilon: " << newEpsilon << '.' 7907 << " Approx::epsilon has to be in [0, 1]"); 7908 m_epsilon = newEpsilon; 7909 } 7910 7911 } // end namespace Detail 7912 7913 namespace literals { 7914 Detail::Approx operator "" _a(long double val) { 7915 return Detail::Approx(val); 7916 } 7917 Detail::Approx operator "" _a(unsigned long long val) { 7918 return Detail::Approx(val); 7919 } 7920 } // end namespace literals 7921 7922 std::string StringMaker<Catch::Detail::Approx>::convert(Catch::Detail::Approx const& value) { 7923 return value.toString(); 7924 } 7925 7926 } // end namespace Catch 7927 // end catch_approx.cpp 7928 // start catch_assertionhandler.cpp 7929 7930 // start catch_debugger.h 7931 7932 namespace Catch { 7933 bool isDebuggerActive(); 7934 } 7935 7936 #ifdef CATCH_PLATFORM_MAC 7937 7938 #if defined(__i386__) || defined(__x86_64__) 7939 #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */ 7940 #elif defined(__aarch64__) 7941 #define CATCH_TRAP() __asm__(".inst 0xd4200000") 7942 #endif 7943 7944 #elif defined(CATCH_PLATFORM_IPHONE) 7945 7946 // use inline assembler 7947 #if defined(__i386__) || defined(__x86_64__) 7948 #define CATCH_TRAP() __asm__("int $3") 7949 #elif defined(__aarch64__) 7950 #define CATCH_TRAP() __asm__(".inst 0xd4200000") 7951 #elif defined(__arm__) && !defined(__thumb__) 7952 #define CATCH_TRAP() __asm__(".inst 0xe7f001f0") 7953 #elif defined(__arm__) && defined(__thumb__) 7954 #define CATCH_TRAP() __asm__(".inst 0xde01") 7955 #endif 7956 7957 #elif defined(CATCH_PLATFORM_LINUX) 7958 // If we can use inline assembler, do it because this allows us to break 7959 // directly at the location of the failing check instead of breaking inside 7960 // raise() called from it, i.e. one stack frame below. 7961 #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64)) 7962 #define CATCH_TRAP() asm volatile ("int $3") /* NOLINT */ 7963 #else // Fall back to the generic way. 7964 #include <signal.h> 7965 7966 #define CATCH_TRAP() raise(SIGTRAP) 7967 #endif 7968 #elif defined(_MSC_VER) 7969 #define CATCH_TRAP() __debugbreak() 7970 #elif defined(__MINGW32__) 7971 extern "C" __declspec(dllimport) void __stdcall DebugBreak(); 7972 #define CATCH_TRAP() DebugBreak() 7973 #endif 7974 7975 #ifndef CATCH_BREAK_INTO_DEBUGGER 7976 #ifdef CATCH_TRAP 7977 #define CATCH_BREAK_INTO_DEBUGGER() []{ if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } }() 7978 #else 7979 #define CATCH_BREAK_INTO_DEBUGGER() []{}() 7980 #endif 7981 #endif 7982 7983 // end catch_debugger.h 7984 // start catch_run_context.h 7985 7986 // start catch_fatal_condition.h 7987 7988 // start catch_windows_h_proxy.h 7989 7990 7991 #if defined(CATCH_PLATFORM_WINDOWS) 7992 7993 #if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX) 7994 # define CATCH_DEFINED_NOMINMAX 7995 # define NOMINMAX 7996 #endif 7997 #if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN) 7998 # define CATCH_DEFINED_WIN32_LEAN_AND_MEAN 7999 # define WIN32_LEAN_AND_MEAN 8000 #endif 8001 8002 #ifdef __AFXDLL 8003 #include <AfxWin.h> 8004 #else 8005 #include <windows.h> 8006 #endif 8007 8008 #ifdef CATCH_DEFINED_NOMINMAX 8009 # undef NOMINMAX 8010 #endif 8011 #ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN 8012 # undef WIN32_LEAN_AND_MEAN 8013 #endif 8014 8015 #endif // defined(CATCH_PLATFORM_WINDOWS) 8016 8017 // end catch_windows_h_proxy.h 8018 #if defined( CATCH_CONFIG_WINDOWS_SEH ) 8019 8020 namespace Catch { 8021 8022 struct FatalConditionHandler { 8023 8024 static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo); 8025 FatalConditionHandler(); 8026 static void reset(); 8027 ~FatalConditionHandler(); 8028 8029 private: 8030 static bool isSet; 8031 static ULONG guaranteeSize; 8032 static PVOID exceptionHandlerHandle; 8033 }; 8034 8035 } // namespace Catch 8036 8037 #elif defined ( CATCH_CONFIG_POSIX_SIGNALS ) 8038 8039 #include <signal.h> 8040 8041 namespace Catch { 8042 8043 struct FatalConditionHandler { 8044 8045 static bool isSet; 8046 static struct sigaction oldSigActions[]; 8047 static stack_t oldSigStack; 8048 static char altStackMem[]; 8049 8050 static void handleSignal( int sig ); 8051 8052 FatalConditionHandler(); 8053 ~FatalConditionHandler(); 8054 static void reset(); 8055 }; 8056 8057 } // namespace Catch 8058 8059 #else 8060 8061 namespace Catch { 8062 struct FatalConditionHandler { 8063 void reset(); 8064 }; 8065 } 8066 8067 #endif 8068 8069 // end catch_fatal_condition.h 8070 #include <string> 8071 8072 namespace Catch { 8073 8074 struct IMutableContext; 8075 8076 /////////////////////////////////////////////////////////////////////////// 8077 8078 class RunContext : public IResultCapture, public IRunner { 8079 8080 public: 8081 RunContext( RunContext const& ) = delete; 8082 RunContext& operator =( RunContext const& ) = delete; 8083 8084 explicit RunContext( IConfigPtr const& _config, IStreamingReporterPtr&& reporter ); 8085 8086 ~RunContext() override; 8087 8088 void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ); 8089 void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ); 8090 8091 Totals runTest(TestCase const& testCase); 8092 8093 IConfigPtr config() const; 8094 IStreamingReporter& reporter() const; 8095 8096 public: // IResultCapture 8097 8098 // Assertion handlers 8099 void handleExpr 8100 ( AssertionInfo const& info, 8101 ITransientExpression const& expr, 8102 AssertionReaction& reaction ) override; 8103 void handleMessage 8104 ( AssertionInfo const& info, 8105 ResultWas::OfType resultType, 8106 StringRef const& message, 8107 AssertionReaction& reaction ) override; 8108 void handleUnexpectedExceptionNotThrown 8109 ( AssertionInfo const& info, 8110 AssertionReaction& reaction ) override; 8111 void handleUnexpectedInflightException 8112 ( AssertionInfo const& info, 8113 std::string const& message, 8114 AssertionReaction& reaction ) override; 8115 void handleIncomplete 8116 ( AssertionInfo const& info ) override; 8117 void handleNonExpr 8118 ( AssertionInfo const &info, 8119 ResultWas::OfType resultType, 8120 AssertionReaction &reaction ) override; 8121 8122 bool sectionStarted( SectionInfo const& sectionInfo, Counts& assertions ) override; 8123 8124 void sectionEnded( SectionEndInfo const& endInfo ) override; 8125 void sectionEndedEarly( SectionEndInfo const& endInfo ) override; 8126 8127 auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& override; 8128 8129 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 8130 void benchmarkPreparing( std::string const& name ) override; 8131 void benchmarkStarting( BenchmarkInfo const& info ) override; 8132 void benchmarkEnded( BenchmarkStats<> const& stats ) override; 8133 void benchmarkFailed( std::string const& error ) override; 8134 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 8135 8136 void pushScopedMessage( MessageInfo const& message ) override; 8137 void popScopedMessage( MessageInfo const& message ) override; 8138 8139 void emplaceUnscopedMessage( MessageBuilder const& builder ) override; 8140 8141 std::string getCurrentTestName() const override; 8142 8143 const AssertionResult* getLastResult() const override; 8144 8145 void exceptionEarlyReported() override; 8146 8147 void handleFatalErrorCondition( StringRef message ) override; 8148 8149 bool lastAssertionPassed() override; 8150 8151 void assertionPassed() override; 8152 8153 public: 8154 // !TBD We need to do this another way! 8155 bool aborting() const final; 8156 8157 private: 8158 8159 void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ); 8160 void invokeActiveTestCase(); 8161 8162 void resetAssertionInfo(); 8163 bool testForMissingAssertions( Counts& assertions ); 8164 8165 void assertionEnded( AssertionResult const& result ); 8166 void reportExpr 8167 ( AssertionInfo const &info, 8168 ResultWas::OfType resultType, 8169 ITransientExpression const *expr, 8170 bool negated ); 8171 8172 void populateReaction( AssertionReaction& reaction ); 8173 8174 private: 8175 8176 void handleUnfinishedSections(); 8177 8178 TestRunInfo m_runInfo; 8179 IMutableContext& m_context; 8180 TestCase const* m_activeTestCase = nullptr; 8181 ITracker* m_testCaseTracker = nullptr; 8182 Option<AssertionResult> m_lastResult; 8183 8184 IConfigPtr m_config; 8185 Totals m_totals; 8186 IStreamingReporterPtr m_reporter; 8187 std::vector<MessageInfo> m_messages; 8188 std::vector<ScopedMessage> m_messageScopes; /* Keeps owners of so-called unscoped messages. */ 8189 AssertionInfo m_lastAssertionInfo; 8190 std::vector<SectionEndInfo> m_unfinishedSections; 8191 std::vector<ITracker*> m_activeSections; 8192 TrackerContext m_trackerContext; 8193 bool m_lastAssertionPassed = false; 8194 bool m_shouldReportUnexpected = true; 8195 bool m_includeSuccessfulResults; 8196 }; 8197 8198 void seedRng(IConfig const& config); 8199 unsigned int rngSeed(); 8200 } // end namespace Catch 8201 8202 // end catch_run_context.h 8203 namespace Catch { 8204 8205 namespace { 8206 auto operator <<( std::ostream& os, ITransientExpression const& expr ) -> std::ostream& { 8207 expr.streamReconstructedExpression( os ); 8208 return os; 8209 } 8210 } 8211 8212 LazyExpression::LazyExpression( bool isNegated ) 8213 : m_isNegated( isNegated ) 8214 {} 8215 8216 LazyExpression::LazyExpression( LazyExpression const& other ) : m_isNegated( other.m_isNegated ) {} 8217 8218 LazyExpression::operator bool() const { 8219 return m_transientExpression != nullptr; 8220 } 8221 8222 auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream& { 8223 if( lazyExpr.m_isNegated ) 8224 os << "!"; 8225 8226 if( lazyExpr ) { 8227 if( lazyExpr.m_isNegated && lazyExpr.m_transientExpression->isBinaryExpression() ) 8228 os << "(" << *lazyExpr.m_transientExpression << ")"; 8229 else 8230 os << *lazyExpr.m_transientExpression; 8231 } 8232 else { 8233 os << "{** error - unchecked empty expression requested **}"; 8234 } 8235 return os; 8236 } 8237 8238 AssertionHandler::AssertionHandler 8239 ( StringRef const& macroName, 8240 SourceLineInfo const& lineInfo, 8241 StringRef capturedExpression, 8242 ResultDisposition::Flags resultDisposition ) 8243 : m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition }, 8244 m_resultCapture( getResultCapture() ) 8245 {} 8246 8247 void AssertionHandler::handleExpr( ITransientExpression const& expr ) { 8248 m_resultCapture.handleExpr( m_assertionInfo, expr, m_reaction ); 8249 } 8250 void AssertionHandler::handleMessage(ResultWas::OfType resultType, StringRef const& message) { 8251 m_resultCapture.handleMessage( m_assertionInfo, resultType, message, m_reaction ); 8252 } 8253 8254 auto AssertionHandler::allowThrows() const -> bool { 8255 return getCurrentContext().getConfig()->allowThrows(); 8256 } 8257 8258 void AssertionHandler::complete() { 8259 setCompleted(); 8260 if( m_reaction.shouldDebugBreak ) { 8261 8262 // If you find your debugger stopping you here then go one level up on the 8263 // call-stack for the code that caused it (typically a failed assertion) 8264 8265 // (To go back to the test and change execution, jump over the throw, next) 8266 CATCH_BREAK_INTO_DEBUGGER(); 8267 } 8268 if (m_reaction.shouldThrow) { 8269 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 8270 throw Catch::TestFailureException(); 8271 #else 8272 CATCH_ERROR( "Test failure requires aborting test!" ); 8273 #endif 8274 } 8275 } 8276 void AssertionHandler::setCompleted() { 8277 m_completed = true; 8278 } 8279 8280 void AssertionHandler::handleUnexpectedInflightException() { 8281 m_resultCapture.handleUnexpectedInflightException( m_assertionInfo, Catch::translateActiveException(), m_reaction ); 8282 } 8283 8284 void AssertionHandler::handleExceptionThrownAsExpected() { 8285 m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction); 8286 } 8287 void AssertionHandler::handleExceptionNotThrownAsExpected() { 8288 m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction); 8289 } 8290 8291 void AssertionHandler::handleUnexpectedExceptionNotThrown() { 8292 m_resultCapture.handleUnexpectedExceptionNotThrown( m_assertionInfo, m_reaction ); 8293 } 8294 8295 void AssertionHandler::handleThrowingCallSkipped() { 8296 m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction); 8297 } 8298 8299 // This is the overload that takes a string and infers the Equals matcher from it 8300 // The more general overload, that takes any string matcher, is in catch_capture_matchers.cpp 8301 void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef const& matcherString ) { 8302 handleExceptionMatchExpr( handler, Matchers::Equals( str ), matcherString ); 8303 } 8304 8305 } // namespace Catch 8306 // end catch_assertionhandler.cpp 8307 // start catch_assertionresult.cpp 8308 8309 namespace Catch { 8310 AssertionResultData::AssertionResultData(ResultWas::OfType _resultType, LazyExpression const & _lazyExpression): 8311 lazyExpression(_lazyExpression), 8312 resultType(_resultType) {} 8313 8314 std::string AssertionResultData::reconstructExpression() const { 8315 8316 if( reconstructedExpression.empty() ) { 8317 if( lazyExpression ) { 8318 ReusableStringStream rss; 8319 rss << lazyExpression; 8320 reconstructedExpression = rss.str(); 8321 } 8322 } 8323 return reconstructedExpression; 8324 } 8325 8326 AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) 8327 : m_info( info ), 8328 m_resultData( data ) 8329 {} 8330 8331 // Result was a success 8332 bool AssertionResult::succeeded() const { 8333 return Catch::isOk( m_resultData.resultType ); 8334 } 8335 8336 // Result was a success, or failure is suppressed 8337 bool AssertionResult::isOk() const { 8338 return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition ); 8339 } 8340 8341 ResultWas::OfType AssertionResult::getResultType() const { 8342 return m_resultData.resultType; 8343 } 8344 8345 bool AssertionResult::hasExpression() const { 8346 return !m_info.capturedExpression.empty(); 8347 } 8348 8349 bool AssertionResult::hasMessage() const { 8350 return !m_resultData.message.empty(); 8351 } 8352 8353 std::string AssertionResult::getExpression() const { 8354 // Possibly overallocating by 3 characters should be basically free 8355 std::string expr; expr.reserve(m_info.capturedExpression.size() + 3); 8356 if (isFalseTest(m_info.resultDisposition)) { 8357 expr += "!("; 8358 } 8359 expr += m_info.capturedExpression; 8360 if (isFalseTest(m_info.resultDisposition)) { 8361 expr += ')'; 8362 } 8363 return expr; 8364 } 8365 8366 std::string AssertionResult::getExpressionInMacro() const { 8367 std::string expr; 8368 if( m_info.macroName.empty() ) 8369 expr = static_cast<std::string>(m_info.capturedExpression); 8370 else { 8371 expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 ); 8372 expr += m_info.macroName; 8373 expr += "( "; 8374 expr += m_info.capturedExpression; 8375 expr += " )"; 8376 } 8377 return expr; 8378 } 8379 8380 bool AssertionResult::hasExpandedExpression() const { 8381 return hasExpression() && getExpandedExpression() != getExpression(); 8382 } 8383 8384 std::string AssertionResult::getExpandedExpression() const { 8385 std::string expr = m_resultData.reconstructExpression(); 8386 return expr.empty() 8387 ? getExpression() 8388 : expr; 8389 } 8390 8391 std::string AssertionResult::getMessage() const { 8392 return m_resultData.message; 8393 } 8394 SourceLineInfo AssertionResult::getSourceInfo() const { 8395 return m_info.lineInfo; 8396 } 8397 8398 StringRef AssertionResult::getTestMacroName() const { 8399 return m_info.macroName; 8400 } 8401 8402 } // end namespace Catch 8403 // end catch_assertionresult.cpp 8404 // start catch_capture_matchers.cpp 8405 8406 namespace Catch { 8407 8408 using StringMatcher = Matchers::Impl::MatcherBase<std::string>; 8409 8410 // This is the general overload that takes a any string matcher 8411 // There is another overload, in catch_assertionhandler.h/.cpp, that only takes a string and infers 8412 // the Equals matcher (so the header does not mention matchers) 8413 void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString ) { 8414 std::string exceptionMessage = Catch::translateActiveException(); 8415 MatchExpr<std::string, StringMatcher const&> expr( exceptionMessage, matcher, matcherString ); 8416 handler.handleExpr( expr ); 8417 } 8418 8419 } // namespace Catch 8420 // end catch_capture_matchers.cpp 8421 // start catch_commandline.cpp 8422 8423 // start catch_commandline.h 8424 8425 // start catch_clara.h 8426 8427 // Use Catch's value for console width (store Clara's off to the side, if present) 8428 #ifdef CLARA_CONFIG_CONSOLE_WIDTH 8429 #define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 8430 #undef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 8431 #endif 8432 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH-1 8433 8434 #ifdef __clang__ 8435 #pragma clang diagnostic push 8436 #pragma clang diagnostic ignored "-Wweak-vtables" 8437 #pragma clang diagnostic ignored "-Wexit-time-destructors" 8438 #pragma clang diagnostic ignored "-Wshadow" 8439 #endif 8440 8441 // start clara.hpp 8442 // Copyright 2017 Two Blue Cubes Ltd. All rights reserved. 8443 // 8444 // Distributed under the Boost Software License, Version 1.0. (See accompanying 8445 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8446 // 8447 // See https://github.com/philsquared/Clara for more details 8448 8449 // Clara v1.1.5 8450 8451 8452 #ifndef CATCH_CLARA_CONFIG_CONSOLE_WIDTH 8453 #define CATCH_CLARA_CONFIG_CONSOLE_WIDTH 80 8454 #endif 8455 8456 #ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 8457 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CLARA_CONFIG_CONSOLE_WIDTH 8458 #endif 8459 8460 #ifndef CLARA_CONFIG_OPTIONAL_TYPE 8461 #ifdef __has_include 8462 #if __has_include(<optional>) && __cplusplus >= 201703L 8463 #include <optional> 8464 #define CLARA_CONFIG_OPTIONAL_TYPE std::optional 8465 #endif 8466 #endif 8467 #endif 8468 8469 // ----------- #included from clara_textflow.hpp ----------- 8470 8471 // TextFlowCpp 8472 // 8473 // A single-header library for wrapping and laying out basic text, by Phil Nash 8474 // 8475 // Distributed under the Boost Software License, Version 1.0. (See accompanying 8476 // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8477 // 8478 // This project is hosted at https://github.com/philsquared/textflowcpp 8479 8480 8481 #include <cassert> 8482 #include <ostream> 8483 #include <sstream> 8484 #include <vector> 8485 8486 #ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 8487 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 80 8488 #endif 8489 8490 namespace Catch { 8491 namespace clara { 8492 namespace TextFlow { 8493 8494 inline auto isWhitespace(char c) -> bool { 8495 static std::string chars = " \t\n\r"; 8496 return chars.find(c) != std::string::npos; 8497 } 8498 inline auto isBreakableBefore(char c) -> bool { 8499 static std::string chars = "[({<|"; 8500 return chars.find(c) != std::string::npos; 8501 } 8502 inline auto isBreakableAfter(char c) -> bool { 8503 static std::string chars = "])}>.,:;*+-=&/\\"; 8504 return chars.find(c) != std::string::npos; 8505 } 8506 8507 class Columns; 8508 8509 class Column { 8510 std::vector<std::string> m_strings; 8511 size_t m_width = CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH; 8512 size_t m_indent = 0; 8513 size_t m_initialIndent = std::string::npos; 8514 8515 public: 8516 class iterator { 8517 friend Column; 8518 8519 Column const& m_column; 8520 size_t m_stringIndex = 0; 8521 size_t m_pos = 0; 8522 8523 size_t m_len = 0; 8524 size_t m_end = 0; 8525 bool m_suffix = false; 8526 8527 iterator(Column const& column, size_t stringIndex) 8528 : m_column(column), 8529 m_stringIndex(stringIndex) {} 8530 8531 auto line() const -> std::string const& { return m_column.m_strings[m_stringIndex]; } 8532 8533 auto isBoundary(size_t at) const -> bool { 8534 assert(at > 0); 8535 assert(at <= line().size()); 8536 8537 return at == line().size() || 8538 (isWhitespace(line()[at]) && !isWhitespace(line()[at - 1])) || 8539 isBreakableBefore(line()[at]) || 8540 isBreakableAfter(line()[at - 1]); 8541 } 8542 8543 void calcLength() { 8544 assert(m_stringIndex < m_column.m_strings.size()); 8545 8546 m_suffix = false; 8547 auto width = m_column.m_width - indent(); 8548 m_end = m_pos; 8549 if (line()[m_pos] == '\n') { 8550 ++m_end; 8551 } 8552 while (m_end < line().size() && line()[m_end] != '\n') 8553 ++m_end; 8554 8555 if (m_end < m_pos + width) { 8556 m_len = m_end - m_pos; 8557 } else { 8558 size_t len = width; 8559 while (len > 0 && !isBoundary(m_pos + len)) 8560 --len; 8561 while (len > 0 && isWhitespace(line()[m_pos + len - 1])) 8562 --len; 8563 8564 if (len > 0) { 8565 m_len = len; 8566 } else { 8567 m_suffix = true; 8568 m_len = width - 1; 8569 } 8570 } 8571 } 8572 8573 auto indent() const -> size_t { 8574 auto initial = m_pos == 0 && m_stringIndex == 0 ? m_column.m_initialIndent : std::string::npos; 8575 return initial == std::string::npos ? m_column.m_indent : initial; 8576 } 8577 8578 auto addIndentAndSuffix(std::string const &plain) const -> std::string { 8579 return std::string(indent(), ' ') + (m_suffix ? plain + "-" : plain); 8580 } 8581 8582 public: 8583 using difference_type = std::ptrdiff_t; 8584 using value_type = std::string; 8585 using pointer = value_type * ; 8586 using reference = value_type & ; 8587 using iterator_category = std::forward_iterator_tag; 8588 8589 explicit iterator(Column const& column) : m_column(column) { 8590 assert(m_column.m_width > m_column.m_indent); 8591 assert(m_column.m_initialIndent == std::string::npos || m_column.m_width > m_column.m_initialIndent); 8592 calcLength(); 8593 if (m_len == 0) 8594 m_stringIndex++; // Empty string 8595 } 8596 8597 auto operator *() const -> std::string { 8598 assert(m_stringIndex < m_column.m_strings.size()); 8599 assert(m_pos <= m_end); 8600 return addIndentAndSuffix(line().substr(m_pos, m_len)); 8601 } 8602 8603 auto operator ++() -> iterator& { 8604 m_pos += m_len; 8605 if (m_pos < line().size() && line()[m_pos] == '\n') 8606 m_pos += 1; 8607 else 8608 while (m_pos < line().size() && isWhitespace(line()[m_pos])) 8609 ++m_pos; 8610 8611 if (m_pos == line().size()) { 8612 m_pos = 0; 8613 ++m_stringIndex; 8614 } 8615 if (m_stringIndex < m_column.m_strings.size()) 8616 calcLength(); 8617 return *this; 8618 } 8619 auto operator ++(int) -> iterator { 8620 iterator prev(*this); 8621 operator++(); 8622 return prev; 8623 } 8624 8625 auto operator ==(iterator const& other) const -> bool { 8626 return 8627 m_pos == other.m_pos && 8628 m_stringIndex == other.m_stringIndex && 8629 &m_column == &other.m_column; 8630 } 8631 auto operator !=(iterator const& other) const -> bool { 8632 return !operator==(other); 8633 } 8634 }; 8635 using const_iterator = iterator; 8636 8637 explicit Column(std::string const& text) { m_strings.push_back(text); } 8638 8639 auto width(size_t newWidth) -> Column& { 8640 assert(newWidth > 0); 8641 m_width = newWidth; 8642 return *this; 8643 } 8644 auto indent(size_t newIndent) -> Column& { 8645 m_indent = newIndent; 8646 return *this; 8647 } 8648 auto initialIndent(size_t newIndent) -> Column& { 8649 m_initialIndent = newIndent; 8650 return *this; 8651 } 8652 8653 auto width() const -> size_t { return m_width; } 8654 auto begin() const -> iterator { return iterator(*this); } 8655 auto end() const -> iterator { return { *this, m_strings.size() }; } 8656 8657 inline friend std::ostream& operator << (std::ostream& os, Column const& col) { 8658 bool first = true; 8659 for (auto line : col) { 8660 if (first) 8661 first = false; 8662 else 8663 os << "\n"; 8664 os << line; 8665 } 8666 return os; 8667 } 8668 8669 auto operator + (Column const& other)->Columns; 8670 8671 auto toString() const -> std::string { 8672 std::ostringstream oss; 8673 oss << *this; 8674 return oss.str(); 8675 } 8676 }; 8677 8678 class Spacer : public Column { 8679 8680 public: 8681 explicit Spacer(size_t spaceWidth) : Column("") { 8682 width(spaceWidth); 8683 } 8684 }; 8685 8686 class Columns { 8687 std::vector<Column> m_columns; 8688 8689 public: 8690 8691 class iterator { 8692 friend Columns; 8693 struct EndTag {}; 8694 8695 std::vector<Column> const& m_columns; 8696 std::vector<Column::iterator> m_iterators; 8697 size_t m_activeIterators; 8698 8699 iterator(Columns const& columns, EndTag) 8700 : m_columns(columns.m_columns), 8701 m_activeIterators(0) { 8702 m_iterators.reserve(m_columns.size()); 8703 8704 for (auto const& col : m_columns) 8705 m_iterators.push_back(col.end()); 8706 } 8707 8708 public: 8709 using difference_type = std::ptrdiff_t; 8710 using value_type = std::string; 8711 using pointer = value_type * ; 8712 using reference = value_type & ; 8713 using iterator_category = std::forward_iterator_tag; 8714 8715 explicit iterator(Columns const& columns) 8716 : m_columns(columns.m_columns), 8717 m_activeIterators(m_columns.size()) { 8718 m_iterators.reserve(m_columns.size()); 8719 8720 for (auto const& col : m_columns) 8721 m_iterators.push_back(col.begin()); 8722 } 8723 8724 auto operator ==(iterator const& other) const -> bool { 8725 return m_iterators == other.m_iterators; 8726 } 8727 auto operator !=(iterator const& other) const -> bool { 8728 return m_iterators != other.m_iterators; 8729 } 8730 auto operator *() const -> std::string { 8731 std::string row, padding; 8732 8733 for (size_t i = 0; i < m_columns.size(); ++i) { 8734 auto width = m_columns[i].width(); 8735 if (m_iterators[i] != m_columns[i].end()) { 8736 std::string col = *m_iterators[i]; 8737 row += padding + col; 8738 if (col.size() < width) 8739 padding = std::string(width - col.size(), ' '); 8740 else 8741 padding = ""; 8742 } else { 8743 padding += std::string(width, ' '); 8744 } 8745 } 8746 return row; 8747 } 8748 auto operator ++() -> iterator& { 8749 for (size_t i = 0; i < m_columns.size(); ++i) { 8750 if (m_iterators[i] != m_columns[i].end()) 8751 ++m_iterators[i]; 8752 } 8753 return *this; 8754 } 8755 auto operator ++(int) -> iterator { 8756 iterator prev(*this); 8757 operator++(); 8758 return prev; 8759 } 8760 }; 8761 using const_iterator = iterator; 8762 8763 auto begin() const -> iterator { return iterator(*this); } 8764 auto end() const -> iterator { return { *this, iterator::EndTag() }; } 8765 8766 auto operator += (Column const& col) -> Columns& { 8767 m_columns.push_back(col); 8768 return *this; 8769 } 8770 auto operator + (Column const& col) -> Columns { 8771 Columns combined = *this; 8772 combined += col; 8773 return combined; 8774 } 8775 8776 inline friend std::ostream& operator << (std::ostream& os, Columns const& cols) { 8777 8778 bool first = true; 8779 for (auto line : cols) { 8780 if (first) 8781 first = false; 8782 else 8783 os << "\n"; 8784 os << line; 8785 } 8786 return os; 8787 } 8788 8789 auto toString() const -> std::string { 8790 std::ostringstream oss; 8791 oss << *this; 8792 return oss.str(); 8793 } 8794 }; 8795 8796 inline auto Column::operator + (Column const& other) -> Columns { 8797 Columns cols; 8798 cols += *this; 8799 cols += other; 8800 return cols; 8801 } 8802 } 8803 8804 } 8805 } 8806 8807 // ----------- end of #include from clara_textflow.hpp ----------- 8808 // ........... back in clara.hpp 8809 8810 #include <cctype> 8811 #include <string> 8812 #include <memory> 8813 #include <set> 8814 #include <algorithm> 8815 8816 #if !defined(CATCH_PLATFORM_WINDOWS) && ( defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) ) 8817 #define CATCH_PLATFORM_WINDOWS 8818 #endif 8819 8820 namespace Catch { namespace clara { 8821 namespace detail { 8822 8823 // Traits for extracting arg and return type of lambdas (for single argument lambdas) 8824 template<typename L> 8825 struct UnaryLambdaTraits : UnaryLambdaTraits<decltype( &L::operator() )> {}; 8826 8827 template<typename ClassT, typename ReturnT, typename... Args> 8828 struct UnaryLambdaTraits<ReturnT( ClassT::* )( Args... ) const> { 8829 static const bool isValid = false; 8830 }; 8831 8832 template<typename ClassT, typename ReturnT, typename ArgT> 8833 struct UnaryLambdaTraits<ReturnT( ClassT::* )( ArgT ) const> { 8834 static const bool isValid = true; 8835 using ArgType = typename std::remove_const<typename std::remove_reference<ArgT>::type>::type; 8836 using ReturnType = ReturnT; 8837 }; 8838 8839 class TokenStream; 8840 8841 // Transport for raw args (copied from main args, or supplied via init list for testing) 8842 class Args { 8843 friend TokenStream; 8844 std::string m_exeName; 8845 std::vector<std::string> m_args; 8846 8847 public: 8848 Args( int argc, char const* const* argv ) 8849 : m_exeName(argv[0]), 8850 m_args(argv + 1, argv + argc) {} 8851 8852 Args( std::initializer_list<std::string> args ) 8853 : m_exeName( *args.begin() ), 8854 m_args( args.begin()+1, args.end() ) 8855 {} 8856 8857 auto exeName() const -> std::string { 8858 return m_exeName; 8859 } 8860 }; 8861 8862 // Wraps a token coming from a token stream. These may not directly correspond to strings as a single string 8863 // may encode an option + its argument if the : or = form is used 8864 enum class TokenType { 8865 Option, Argument 8866 }; 8867 struct Token { 8868 TokenType type; 8869 std::string token; 8870 }; 8871 8872 inline auto isOptPrefix( char c ) -> bool { 8873 return c == '-' 8874 #ifdef CATCH_PLATFORM_WINDOWS 8875 || c == '/' 8876 #endif 8877 ; 8878 } 8879 8880 // Abstracts iterators into args as a stream of tokens, with option arguments uniformly handled 8881 class TokenStream { 8882 using Iterator = std::vector<std::string>::const_iterator; 8883 Iterator it; 8884 Iterator itEnd; 8885 std::vector<Token> m_tokenBuffer; 8886 8887 void loadBuffer() { 8888 m_tokenBuffer.resize( 0 ); 8889 8890 // Skip any empty strings 8891 while( it != itEnd && it->empty() ) 8892 ++it; 8893 8894 if( it != itEnd ) { 8895 auto const &next = *it; 8896 if( isOptPrefix( next[0] ) ) { 8897 auto delimiterPos = next.find_first_of( " :=" ); 8898 if( delimiterPos != std::string::npos ) { 8899 m_tokenBuffer.push_back( { TokenType::Option, next.substr( 0, delimiterPos ) } ); 8900 m_tokenBuffer.push_back( { TokenType::Argument, next.substr( delimiterPos + 1 ) } ); 8901 } else { 8902 if( next[1] != '-' && next.size() > 2 ) { 8903 std::string opt = "- "; 8904 for( size_t i = 1; i < next.size(); ++i ) { 8905 opt[1] = next[i]; 8906 m_tokenBuffer.push_back( { TokenType::Option, opt } ); 8907 } 8908 } else { 8909 m_tokenBuffer.push_back( { TokenType::Option, next } ); 8910 } 8911 } 8912 } else { 8913 m_tokenBuffer.push_back( { TokenType::Argument, next } ); 8914 } 8915 } 8916 } 8917 8918 public: 8919 explicit TokenStream( Args const &args ) : TokenStream( args.m_args.begin(), args.m_args.end() ) {} 8920 8921 TokenStream( Iterator it, Iterator itEnd ) : it( it ), itEnd( itEnd ) { 8922 loadBuffer(); 8923 } 8924 8925 explicit operator bool() const { 8926 return !m_tokenBuffer.empty() || it != itEnd; 8927 } 8928 8929 auto count() const -> size_t { return m_tokenBuffer.size() + (itEnd - it); } 8930 8931 auto operator*() const -> Token { 8932 assert( !m_tokenBuffer.empty() ); 8933 return m_tokenBuffer.front(); 8934 } 8935 8936 auto operator->() const -> Token const * { 8937 assert( !m_tokenBuffer.empty() ); 8938 return &m_tokenBuffer.front(); 8939 } 8940 8941 auto operator++() -> TokenStream & { 8942 if( m_tokenBuffer.size() >= 2 ) { 8943 m_tokenBuffer.erase( m_tokenBuffer.begin() ); 8944 } else { 8945 if( it != itEnd ) 8946 ++it; 8947 loadBuffer(); 8948 } 8949 return *this; 8950 } 8951 }; 8952 8953 class ResultBase { 8954 public: 8955 enum Type { 8956 Ok, LogicError, RuntimeError 8957 }; 8958 8959 protected: 8960 ResultBase( Type type ) : m_type( type ) {} 8961 virtual ~ResultBase() = default; 8962 8963 virtual void enforceOk() const = 0; 8964 8965 Type m_type; 8966 }; 8967 8968 template<typename T> 8969 class ResultValueBase : public ResultBase { 8970 public: 8971 auto value() const -> T const & { 8972 enforceOk(); 8973 return m_value; 8974 } 8975 8976 protected: 8977 ResultValueBase( Type type ) : ResultBase( type ) {} 8978 8979 ResultValueBase( ResultValueBase const &other ) : ResultBase( other ) { 8980 if( m_type == ResultBase::Ok ) 8981 new( &m_value ) T( other.m_value ); 8982 } 8983 8984 ResultValueBase( Type, T const &value ) : ResultBase( Ok ) { 8985 new( &m_value ) T( value ); 8986 } 8987 8988 auto operator=( ResultValueBase const &other ) -> ResultValueBase & { 8989 if( m_type == ResultBase::Ok ) 8990 m_value.~T(); 8991 ResultBase::operator=(other); 8992 if( m_type == ResultBase::Ok ) 8993 new( &m_value ) T( other.m_value ); 8994 return *this; 8995 } 8996 8997 ~ResultValueBase() override { 8998 if( m_type == Ok ) 8999 m_value.~T(); 9000 } 9001 9002 union { 9003 T m_value; 9004 }; 9005 }; 9006 9007 template<> 9008 class ResultValueBase<void> : public ResultBase { 9009 protected: 9010 using ResultBase::ResultBase; 9011 }; 9012 9013 template<typename T = void> 9014 class BasicResult : public ResultValueBase<T> { 9015 public: 9016 template<typename U> 9017 explicit BasicResult( BasicResult<U> const &other ) 9018 : ResultValueBase<T>( other.type() ), 9019 m_errorMessage( other.errorMessage() ) 9020 { 9021 assert( type() != ResultBase::Ok ); 9022 } 9023 9024 template<typename U> 9025 static auto ok( U const &value ) -> BasicResult { return { ResultBase::Ok, value }; } 9026 static auto ok() -> BasicResult { return { ResultBase::Ok }; } 9027 static auto logicError( std::string const &message ) -> BasicResult { return { ResultBase::LogicError, message }; } 9028 static auto runtimeError( std::string const &message ) -> BasicResult { return { ResultBase::RuntimeError, message }; } 9029 9030 explicit operator bool() const { return m_type == ResultBase::Ok; } 9031 auto type() const -> ResultBase::Type { return m_type; } 9032 auto errorMessage() const -> std::string { return m_errorMessage; } 9033 9034 protected: 9035 void enforceOk() const override { 9036 9037 // Errors shouldn't reach this point, but if they do 9038 // the actual error message will be in m_errorMessage 9039 assert( m_type != ResultBase::LogicError ); 9040 assert( m_type != ResultBase::RuntimeError ); 9041 if( m_type != ResultBase::Ok ) 9042 std::abort(); 9043 } 9044 9045 std::string m_errorMessage; // Only populated if resultType is an error 9046 9047 BasicResult( ResultBase::Type type, std::string const &message ) 9048 : ResultValueBase<T>(type), 9049 m_errorMessage(message) 9050 { 9051 assert( m_type != ResultBase::Ok ); 9052 } 9053 9054 using ResultValueBase<T>::ResultValueBase; 9055 using ResultBase::m_type; 9056 }; 9057 9058 enum class ParseResultType { 9059 Matched, NoMatch, ShortCircuitAll, ShortCircuitSame 9060 }; 9061 9062 class ParseState { 9063 public: 9064 9065 ParseState( ParseResultType type, TokenStream const &remainingTokens ) 9066 : m_type(type), 9067 m_remainingTokens( remainingTokens ) 9068 {} 9069 9070 auto type() const -> ParseResultType { return m_type; } 9071 auto remainingTokens() const -> TokenStream { return m_remainingTokens; } 9072 9073 private: 9074 ParseResultType m_type; 9075 TokenStream m_remainingTokens; 9076 }; 9077 9078 using Result = BasicResult<void>; 9079 using ParserResult = BasicResult<ParseResultType>; 9080 using InternalParseResult = BasicResult<ParseState>; 9081 9082 struct HelpColumns { 9083 std::string left; 9084 std::string right; 9085 }; 9086 9087 template<typename T> 9088 inline auto convertInto( std::string const &source, T& target ) -> ParserResult { 9089 std::stringstream ss; 9090 ss << source; 9091 ss >> target; 9092 if( ss.fail() ) 9093 return ParserResult::runtimeError( "Unable to convert '" + source + "' to destination type" ); 9094 else 9095 return ParserResult::ok( ParseResultType::Matched ); 9096 } 9097 inline auto convertInto( std::string const &source, std::string& target ) -> ParserResult { 9098 target = source; 9099 return ParserResult::ok( ParseResultType::Matched ); 9100 } 9101 inline auto convertInto( std::string const &source, bool &target ) -> ParserResult { 9102 std::string srcLC = source; 9103 std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( unsigned char c ) { return static_cast<char>( std::tolower(c) ); } ); 9104 if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on") 9105 target = true; 9106 else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off") 9107 target = false; 9108 else 9109 return ParserResult::runtimeError( "Expected a boolean value but did not recognise: '" + source + "'" ); 9110 return ParserResult::ok( ParseResultType::Matched ); 9111 } 9112 #ifdef CLARA_CONFIG_OPTIONAL_TYPE 9113 template<typename T> 9114 inline auto convertInto( std::string const &source, CLARA_CONFIG_OPTIONAL_TYPE<T>& target ) -> ParserResult { 9115 T temp; 9116 auto result = convertInto( source, temp ); 9117 if( result ) 9118 target = std::move(temp); 9119 return result; 9120 } 9121 #endif // CLARA_CONFIG_OPTIONAL_TYPE 9122 9123 struct NonCopyable { 9124 NonCopyable() = default; 9125 NonCopyable( NonCopyable const & ) = delete; 9126 NonCopyable( NonCopyable && ) = delete; 9127 NonCopyable &operator=( NonCopyable const & ) = delete; 9128 NonCopyable &operator=( NonCopyable && ) = delete; 9129 }; 9130 9131 struct BoundRef : NonCopyable { 9132 virtual ~BoundRef() = default; 9133 virtual auto isContainer() const -> bool { return false; } 9134 virtual auto isFlag() const -> bool { return false; } 9135 }; 9136 struct BoundValueRefBase : BoundRef { 9137 virtual auto setValue( std::string const &arg ) -> ParserResult = 0; 9138 }; 9139 struct BoundFlagRefBase : BoundRef { 9140 virtual auto setFlag( bool flag ) -> ParserResult = 0; 9141 virtual auto isFlag() const -> bool { return true; } 9142 }; 9143 9144 template<typename T> 9145 struct BoundValueRef : BoundValueRefBase { 9146 T &m_ref; 9147 9148 explicit BoundValueRef( T &ref ) : m_ref( ref ) {} 9149 9150 auto setValue( std::string const &arg ) -> ParserResult override { 9151 return convertInto( arg, m_ref ); 9152 } 9153 }; 9154 9155 template<typename T> 9156 struct BoundValueRef<std::vector<T>> : BoundValueRefBase { 9157 std::vector<T> &m_ref; 9158 9159 explicit BoundValueRef( std::vector<T> &ref ) : m_ref( ref ) {} 9160 9161 auto isContainer() const -> bool override { return true; } 9162 9163 auto setValue( std::string const &arg ) -> ParserResult override { 9164 T temp; 9165 auto result = convertInto( arg, temp ); 9166 if( result ) 9167 m_ref.push_back( temp ); 9168 return result; 9169 } 9170 }; 9171 9172 struct BoundFlagRef : BoundFlagRefBase { 9173 bool &m_ref; 9174 9175 explicit BoundFlagRef( bool &ref ) : m_ref( ref ) {} 9176 9177 auto setFlag( bool flag ) -> ParserResult override { 9178 m_ref = flag; 9179 return ParserResult::ok( ParseResultType::Matched ); 9180 } 9181 }; 9182 9183 template<typename ReturnType> 9184 struct LambdaInvoker { 9185 static_assert( std::is_same<ReturnType, ParserResult>::value, "Lambda must return void or clara::ParserResult" ); 9186 9187 template<typename L, typename ArgType> 9188 static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult { 9189 return lambda( arg ); 9190 } 9191 }; 9192 9193 template<> 9194 struct LambdaInvoker<void> { 9195 template<typename L, typename ArgType> 9196 static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult { 9197 lambda( arg ); 9198 return ParserResult::ok( ParseResultType::Matched ); 9199 } 9200 }; 9201 9202 template<typename ArgType, typename L> 9203 inline auto invokeLambda( L const &lambda, std::string const &arg ) -> ParserResult { 9204 ArgType temp{}; 9205 auto result = convertInto( arg, temp ); 9206 return !result 9207 ? result 9208 : LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( lambda, temp ); 9209 } 9210 9211 template<typename L> 9212 struct BoundLambda : BoundValueRefBase { 9213 L m_lambda; 9214 9215 static_assert( UnaryLambdaTraits<L>::isValid, "Supplied lambda must take exactly one argument" ); 9216 explicit BoundLambda( L const &lambda ) : m_lambda( lambda ) {} 9217 9218 auto setValue( std::string const &arg ) -> ParserResult override { 9219 return invokeLambda<typename UnaryLambdaTraits<L>::ArgType>( m_lambda, arg ); 9220 } 9221 }; 9222 9223 template<typename L> 9224 struct BoundFlagLambda : BoundFlagRefBase { 9225 L m_lambda; 9226 9227 static_assert( UnaryLambdaTraits<L>::isValid, "Supplied lambda must take exactly one argument" ); 9228 static_assert( std::is_same<typename UnaryLambdaTraits<L>::ArgType, bool>::value, "flags must be boolean" ); 9229 9230 explicit BoundFlagLambda( L const &lambda ) : m_lambda( lambda ) {} 9231 9232 auto setFlag( bool flag ) -> ParserResult override { 9233 return LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( m_lambda, flag ); 9234 } 9235 }; 9236 9237 enum class Optionality { Optional, Required }; 9238 9239 struct Parser; 9240 9241 class ParserBase { 9242 public: 9243 virtual ~ParserBase() = default; 9244 virtual auto validate() const -> Result { return Result::ok(); } 9245 virtual auto parse( std::string const& exeName, TokenStream const &tokens) const -> InternalParseResult = 0; 9246 virtual auto cardinality() const -> size_t { return 1; } 9247 9248 auto parse( Args const &args ) const -> InternalParseResult { 9249 return parse( args.exeName(), TokenStream( args ) ); 9250 } 9251 }; 9252 9253 template<typename DerivedT> 9254 class ComposableParserImpl : public ParserBase { 9255 public: 9256 template<typename T> 9257 auto operator|( T const &other ) const -> Parser; 9258 9259 template<typename T> 9260 auto operator+( T const &other ) const -> Parser; 9261 }; 9262 9263 // Common code and state for Args and Opts 9264 template<typename DerivedT> 9265 class ParserRefImpl : public ComposableParserImpl<DerivedT> { 9266 protected: 9267 Optionality m_optionality = Optionality::Optional; 9268 std::shared_ptr<BoundRef> m_ref; 9269 std::string m_hint; 9270 std::string m_description; 9271 9272 explicit ParserRefImpl( std::shared_ptr<BoundRef> const &ref ) : m_ref( ref ) {} 9273 9274 public: 9275 template<typename T> 9276 ParserRefImpl( T &ref, std::string const &hint ) 9277 : m_ref( std::make_shared<BoundValueRef<T>>( ref ) ), 9278 m_hint( hint ) 9279 {} 9280 9281 template<typename LambdaT> 9282 ParserRefImpl( LambdaT const &ref, std::string const &hint ) 9283 : m_ref( std::make_shared<BoundLambda<LambdaT>>( ref ) ), 9284 m_hint(hint) 9285 {} 9286 9287 auto operator()( std::string const &description ) -> DerivedT & { 9288 m_description = description; 9289 return static_cast<DerivedT &>( *this ); 9290 } 9291 9292 auto optional() -> DerivedT & { 9293 m_optionality = Optionality::Optional; 9294 return static_cast<DerivedT &>( *this ); 9295 }; 9296 9297 auto required() -> DerivedT & { 9298 m_optionality = Optionality::Required; 9299 return static_cast<DerivedT &>( *this ); 9300 }; 9301 9302 auto isOptional() const -> bool { 9303 return m_optionality == Optionality::Optional; 9304 } 9305 9306 auto cardinality() const -> size_t override { 9307 if( m_ref->isContainer() ) 9308 return 0; 9309 else 9310 return 1; 9311 } 9312 9313 auto hint() const -> std::string { return m_hint; } 9314 }; 9315 9316 class ExeName : public ComposableParserImpl<ExeName> { 9317 std::shared_ptr<std::string> m_name; 9318 std::shared_ptr<BoundValueRefBase> m_ref; 9319 9320 template<typename LambdaT> 9321 static auto makeRef(LambdaT const &lambda) -> std::shared_ptr<BoundValueRefBase> { 9322 return std::make_shared<BoundLambda<LambdaT>>( lambda) ; 9323 } 9324 9325 public: 9326 ExeName() : m_name( std::make_shared<std::string>( "<executable>" ) ) {} 9327 9328 explicit ExeName( std::string &ref ) : ExeName() { 9329 m_ref = std::make_shared<BoundValueRef<std::string>>( ref ); 9330 } 9331 9332 template<typename LambdaT> 9333 explicit ExeName( LambdaT const& lambda ) : ExeName() { 9334 m_ref = std::make_shared<BoundLambda<LambdaT>>( lambda ); 9335 } 9336 9337 // The exe name is not parsed out of the normal tokens, but is handled specially 9338 auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override { 9339 return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) ); 9340 } 9341 9342 auto name() const -> std::string { return *m_name; } 9343 auto set( std::string const& newName ) -> ParserResult { 9344 9345 auto lastSlash = newName.find_last_of( "\\/" ); 9346 auto filename = ( lastSlash == std::string::npos ) 9347 ? newName 9348 : newName.substr( lastSlash+1 ); 9349 9350 *m_name = filename; 9351 if( m_ref ) 9352 return m_ref->setValue( filename ); 9353 else 9354 return ParserResult::ok( ParseResultType::Matched ); 9355 } 9356 }; 9357 9358 class Arg : public ParserRefImpl<Arg> { 9359 public: 9360 using ParserRefImpl::ParserRefImpl; 9361 9362 auto parse( std::string const &, TokenStream const &tokens ) const -> InternalParseResult override { 9363 auto validationResult = validate(); 9364 if( !validationResult ) 9365 return InternalParseResult( validationResult ); 9366 9367 auto remainingTokens = tokens; 9368 auto const &token = *remainingTokens; 9369 if( token.type != TokenType::Argument ) 9370 return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) ); 9371 9372 assert( !m_ref->isFlag() ); 9373 auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() ); 9374 9375 auto result = valueRef->setValue( remainingTokens->token ); 9376 if( !result ) 9377 return InternalParseResult( result ); 9378 else 9379 return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) ); 9380 } 9381 }; 9382 9383 inline auto normaliseOpt( std::string const &optName ) -> std::string { 9384 #ifdef CATCH_PLATFORM_WINDOWS 9385 if( optName[0] == '/' ) 9386 return "-" + optName.substr( 1 ); 9387 else 9388 #endif 9389 return optName; 9390 } 9391 9392 class Opt : public ParserRefImpl<Opt> { 9393 protected: 9394 std::vector<std::string> m_optNames; 9395 9396 public: 9397 template<typename LambdaT> 9398 explicit Opt( LambdaT const &ref ) : ParserRefImpl( std::make_shared<BoundFlagLambda<LambdaT>>( ref ) ) {} 9399 9400 explicit Opt( bool &ref ) : ParserRefImpl( std::make_shared<BoundFlagRef>( ref ) ) {} 9401 9402 template<typename LambdaT> 9403 Opt( LambdaT const &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {} 9404 9405 template<typename T> 9406 Opt( T &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {} 9407 9408 auto operator[]( std::string const &optName ) -> Opt & { 9409 m_optNames.push_back( optName ); 9410 return *this; 9411 } 9412 9413 auto getHelpColumns() const -> std::vector<HelpColumns> { 9414 std::ostringstream oss; 9415 bool first = true; 9416 for( auto const &opt : m_optNames ) { 9417 if (first) 9418 first = false; 9419 else 9420 oss << ", "; 9421 oss << opt; 9422 } 9423 if( !m_hint.empty() ) 9424 oss << " <" << m_hint << ">"; 9425 return { { oss.str(), m_description } }; 9426 } 9427 9428 auto isMatch( std::string const &optToken ) const -> bool { 9429 auto normalisedToken = normaliseOpt( optToken ); 9430 for( auto const &name : m_optNames ) { 9431 if( normaliseOpt( name ) == normalisedToken ) 9432 return true; 9433 } 9434 return false; 9435 } 9436 9437 using ParserBase::parse; 9438 9439 auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override { 9440 auto validationResult = validate(); 9441 if( !validationResult ) 9442 return InternalParseResult( validationResult ); 9443 9444 auto remainingTokens = tokens; 9445 if( remainingTokens && remainingTokens->type == TokenType::Option ) { 9446 auto const &token = *remainingTokens; 9447 if( isMatch(token.token ) ) { 9448 if( m_ref->isFlag() ) { 9449 auto flagRef = static_cast<detail::BoundFlagRefBase*>( m_ref.get() ); 9450 auto result = flagRef->setFlag( true ); 9451 if( !result ) 9452 return InternalParseResult( result ); 9453 if( result.value() == ParseResultType::ShortCircuitAll ) 9454 return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) ); 9455 } else { 9456 auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() ); 9457 ++remainingTokens; 9458 if( !remainingTokens ) 9459 return InternalParseResult::runtimeError( "Expected argument following " + token.token ); 9460 auto const &argToken = *remainingTokens; 9461 if( argToken.type != TokenType::Argument ) 9462 return InternalParseResult::runtimeError( "Expected argument following " + token.token ); 9463 auto result = valueRef->setValue( argToken.token ); 9464 if( !result ) 9465 return InternalParseResult( result ); 9466 if( result.value() == ParseResultType::ShortCircuitAll ) 9467 return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) ); 9468 } 9469 return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) ); 9470 } 9471 } 9472 return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) ); 9473 } 9474 9475 auto validate() const -> Result override { 9476 if( m_optNames.empty() ) 9477 return Result::logicError( "No options supplied to Opt" ); 9478 for( auto const &name : m_optNames ) { 9479 if( name.empty() ) 9480 return Result::logicError( "Option name cannot be empty" ); 9481 #ifdef CATCH_PLATFORM_WINDOWS 9482 if( name[0] != '-' && name[0] != '/' ) 9483 return Result::logicError( "Option name must begin with '-' or '/'" ); 9484 #else 9485 if( name[0] != '-' ) 9486 return Result::logicError( "Option name must begin with '-'" ); 9487 #endif 9488 } 9489 return ParserRefImpl::validate(); 9490 } 9491 }; 9492 9493 struct Help : Opt { 9494 Help( bool &showHelpFlag ) 9495 : Opt([&]( bool flag ) { 9496 showHelpFlag = flag; 9497 return ParserResult::ok( ParseResultType::ShortCircuitAll ); 9498 }) 9499 { 9500 static_cast<Opt &>( *this ) 9501 ("display usage information") 9502 ["-?"]["-h"]["--help"] 9503 .optional(); 9504 } 9505 }; 9506 9507 struct Parser : ParserBase { 9508 9509 mutable ExeName m_exeName; 9510 std::vector<Opt> m_options; 9511 std::vector<Arg> m_args; 9512 9513 auto operator|=( ExeName const &exeName ) -> Parser & { 9514 m_exeName = exeName; 9515 return *this; 9516 } 9517 9518 auto operator|=( Arg const &arg ) -> Parser & { 9519 m_args.push_back(arg); 9520 return *this; 9521 } 9522 9523 auto operator|=( Opt const &opt ) -> Parser & { 9524 m_options.push_back(opt); 9525 return *this; 9526 } 9527 9528 auto operator|=( Parser const &other ) -> Parser & { 9529 m_options.insert(m_options.end(), other.m_options.begin(), other.m_options.end()); 9530 m_args.insert(m_args.end(), other.m_args.begin(), other.m_args.end()); 9531 return *this; 9532 } 9533 9534 template<typename T> 9535 auto operator|( T const &other ) const -> Parser { 9536 return Parser( *this ) |= other; 9537 } 9538 9539 // Forward deprecated interface with '+' instead of '|' 9540 template<typename T> 9541 auto operator+=( T const &other ) -> Parser & { return operator|=( other ); } 9542 template<typename T> 9543 auto operator+( T const &other ) const -> Parser { return operator|( other ); } 9544 9545 auto getHelpColumns() const -> std::vector<HelpColumns> { 9546 std::vector<HelpColumns> cols; 9547 for (auto const &o : m_options) { 9548 auto childCols = o.getHelpColumns(); 9549 cols.insert( cols.end(), childCols.begin(), childCols.end() ); 9550 } 9551 return cols; 9552 } 9553 9554 void writeToStream( std::ostream &os ) const { 9555 if (!m_exeName.name().empty()) { 9556 os << "usage:\n" << " " << m_exeName.name() << " "; 9557 bool required = true, first = true; 9558 for( auto const &arg : m_args ) { 9559 if (first) 9560 first = false; 9561 else 9562 os << " "; 9563 if( arg.isOptional() && required ) { 9564 os << "["; 9565 required = false; 9566 } 9567 os << "<" << arg.hint() << ">"; 9568 if( arg.cardinality() == 0 ) 9569 os << " ... "; 9570 } 9571 if( !required ) 9572 os << "]"; 9573 if( !m_options.empty() ) 9574 os << " options"; 9575 os << "\n\nwhere options are:" << std::endl; 9576 } 9577 9578 auto rows = getHelpColumns(); 9579 size_t consoleWidth = CATCH_CLARA_CONFIG_CONSOLE_WIDTH; 9580 size_t optWidth = 0; 9581 for( auto const &cols : rows ) 9582 optWidth = (std::max)(optWidth, cols.left.size() + 2); 9583 9584 optWidth = (std::min)(optWidth, consoleWidth/2); 9585 9586 for( auto const &cols : rows ) { 9587 auto row = 9588 TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) + 9589 TextFlow::Spacer(4) + 9590 TextFlow::Column( cols.right ).width( consoleWidth - 7 - optWidth ); 9591 os << row << std::endl; 9592 } 9593 } 9594 9595 friend auto operator<<( std::ostream &os, Parser const &parser ) -> std::ostream& { 9596 parser.writeToStream( os ); 9597 return os; 9598 } 9599 9600 auto validate() const -> Result override { 9601 for( auto const &opt : m_options ) { 9602 auto result = opt.validate(); 9603 if( !result ) 9604 return result; 9605 } 9606 for( auto const &arg : m_args ) { 9607 auto result = arg.validate(); 9608 if( !result ) 9609 return result; 9610 } 9611 return Result::ok(); 9612 } 9613 9614 using ParserBase::parse; 9615 9616 auto parse( std::string const& exeName, TokenStream const &tokens ) const -> InternalParseResult override { 9617 9618 struct ParserInfo { 9619 ParserBase const* parser = nullptr; 9620 size_t count = 0; 9621 }; 9622 const size_t totalParsers = m_options.size() + m_args.size(); 9623 assert( totalParsers < 512 ); 9624 // ParserInfo parseInfos[totalParsers]; // <-- this is what we really want to do 9625 ParserInfo parseInfos[512]; 9626 9627 { 9628 size_t i = 0; 9629 for (auto const &opt : m_options) parseInfos[i++].parser = &opt; 9630 for (auto const &arg : m_args) parseInfos[i++].parser = &arg; 9631 } 9632 9633 m_exeName.set( exeName ); 9634 9635 auto result = InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) ); 9636 while( result.value().remainingTokens() ) { 9637 bool tokenParsed = false; 9638 9639 for( size_t i = 0; i < totalParsers; ++i ) { 9640 auto& parseInfo = parseInfos[i]; 9641 if( parseInfo.parser->cardinality() == 0 || parseInfo.count < parseInfo.parser->cardinality() ) { 9642 result = parseInfo.parser->parse(exeName, result.value().remainingTokens()); 9643 if (!result) 9644 return result; 9645 if (result.value().type() != ParseResultType::NoMatch) { 9646 tokenParsed = true; 9647 ++parseInfo.count; 9648 break; 9649 } 9650 } 9651 } 9652 9653 if( result.value().type() == ParseResultType::ShortCircuitAll ) 9654 return result; 9655 if( !tokenParsed ) 9656 return InternalParseResult::runtimeError( "Unrecognised token: " + result.value().remainingTokens()->token ); 9657 } 9658 // !TBD Check missing required options 9659 return result; 9660 } 9661 }; 9662 9663 template<typename DerivedT> 9664 template<typename T> 9665 auto ComposableParserImpl<DerivedT>::operator|( T const &other ) const -> Parser { 9666 return Parser() | static_cast<DerivedT const &>( *this ) | other; 9667 } 9668 } // namespace detail 9669 9670 // A Combined parser 9671 using detail::Parser; 9672 9673 // A parser for options 9674 using detail::Opt; 9675 9676 // A parser for arguments 9677 using detail::Arg; 9678 9679 // Wrapper for argc, argv from main() 9680 using detail::Args; 9681 9682 // Specifies the name of the executable 9683 using detail::ExeName; 9684 9685 // Convenience wrapper for option parser that specifies the help option 9686 using detail::Help; 9687 9688 // enum of result types from a parse 9689 using detail::ParseResultType; 9690 9691 // Result type for parser operation 9692 using detail::ParserResult; 9693 9694 }} // namespace Catch::clara 9695 9696 // end clara.hpp 9697 #ifdef __clang__ 9698 #pragma clang diagnostic pop 9699 #endif 9700 9701 // Restore Clara's value for console width, if present 9702 #ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH 9703 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH 9704 #undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH 9705 #endif 9706 9707 // end catch_clara.h 9708 namespace Catch { 9709 9710 clara::Parser makeCommandLineParser( ConfigData& config ); 9711 9712 } // end namespace Catch 9713 9714 // end catch_commandline.h 9715 #include <fstream> 9716 #include <ctime> 9717 9718 namespace Catch { 9719 9720 clara::Parser makeCommandLineParser( ConfigData& config ) { 9721 9722 using namespace clara; 9723 9724 auto const setWarning = [&]( std::string const& warning ) { 9725 auto warningSet = [&]() { 9726 if( warning == "NoAssertions" ) 9727 return WarnAbout::NoAssertions; 9728 9729 if ( warning == "NoTests" ) 9730 return WarnAbout::NoTests; 9731 9732 return WarnAbout::Nothing; 9733 }(); 9734 9735 if (warningSet == WarnAbout::Nothing) 9736 return ParserResult::runtimeError( "Unrecognised warning: '" + warning + "'" ); 9737 config.warnings = static_cast<WarnAbout::What>( config.warnings | warningSet ); 9738 return ParserResult::ok( ParseResultType::Matched ); 9739 }; 9740 auto const loadTestNamesFromFile = [&]( std::string const& filename ) { 9741 std::ifstream f( filename.c_str() ); 9742 if( !f.is_open() ) 9743 return ParserResult::runtimeError( "Unable to load input file: '" + filename + "'" ); 9744 9745 std::string line; 9746 while( std::getline( f, line ) ) { 9747 line = trim(line); 9748 if( !line.empty() && !startsWith( line, '#' ) ) { 9749 if( !startsWith( line, '"' ) ) 9750 line = '"' + line + '"'; 9751 config.testsOrTags.push_back( line ); 9752 config.testsOrTags.emplace_back( "," ); 9753 } 9754 } 9755 //Remove comma in the end 9756 if(!config.testsOrTags.empty()) 9757 config.testsOrTags.erase( config.testsOrTags.end()-1 ); 9758 9759 return ParserResult::ok( ParseResultType::Matched ); 9760 }; 9761 auto const setTestOrder = [&]( std::string const& order ) { 9762 if( startsWith( "declared", order ) ) 9763 config.runOrder = RunTests::InDeclarationOrder; 9764 else if( startsWith( "lexical", order ) ) 9765 config.runOrder = RunTests::InLexicographicalOrder; 9766 else if( startsWith( "random", order ) ) 9767 config.runOrder = RunTests::InRandomOrder; 9768 else 9769 return clara::ParserResult::runtimeError( "Unrecognised ordering: '" + order + "'" ); 9770 return ParserResult::ok( ParseResultType::Matched ); 9771 }; 9772 auto const setRngSeed = [&]( std::string const& seed ) { 9773 if( seed != "time" ) 9774 return clara::detail::convertInto( seed, config.rngSeed ); 9775 config.rngSeed = static_cast<unsigned int>( std::time(nullptr) ); 9776 return ParserResult::ok( ParseResultType::Matched ); 9777 }; 9778 auto const setColourUsage = [&]( std::string const& useColour ) { 9779 auto mode = toLower( useColour ); 9780 9781 if( mode == "yes" ) 9782 config.useColour = UseColour::Yes; 9783 else if( mode == "no" ) 9784 config.useColour = UseColour::No; 9785 else if( mode == "auto" ) 9786 config.useColour = UseColour::Auto; 9787 else 9788 return ParserResult::runtimeError( "colour mode must be one of: auto, yes or no. '" + useColour + "' not recognised" ); 9789 return ParserResult::ok( ParseResultType::Matched ); 9790 }; 9791 auto const setWaitForKeypress = [&]( std::string const& keypress ) { 9792 auto keypressLc = toLower( keypress ); 9793 if (keypressLc == "never") 9794 config.waitForKeypress = WaitForKeypress::Never; 9795 else if( keypressLc == "start" ) 9796 config.waitForKeypress = WaitForKeypress::BeforeStart; 9797 else if( keypressLc == "exit" ) 9798 config.waitForKeypress = WaitForKeypress::BeforeExit; 9799 else if( keypressLc == "both" ) 9800 config.waitForKeypress = WaitForKeypress::BeforeStartAndExit; 9801 else 9802 return ParserResult::runtimeError( "keypress argument must be one of: never, start, exit or both. '" + keypress + "' not recognised" ); 9803 return ParserResult::ok( ParseResultType::Matched ); 9804 }; 9805 auto const setVerbosity = [&]( std::string const& verbosity ) { 9806 auto lcVerbosity = toLower( verbosity ); 9807 if( lcVerbosity == "quiet" ) 9808 config.verbosity = Verbosity::Quiet; 9809 else if( lcVerbosity == "normal" ) 9810 config.verbosity = Verbosity::Normal; 9811 else if( lcVerbosity == "high" ) 9812 config.verbosity = Verbosity::High; 9813 else 9814 return ParserResult::runtimeError( "Unrecognised verbosity, '" + verbosity + "'" ); 9815 return ParserResult::ok( ParseResultType::Matched ); 9816 }; 9817 auto const setReporter = [&]( std::string const& reporter ) { 9818 IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); 9819 9820 auto lcReporter = toLower( reporter ); 9821 auto result = factories.find( lcReporter ); 9822 9823 if( factories.end() != result ) 9824 config.reporterName = lcReporter; 9825 else 9826 return ParserResult::runtimeError( "Unrecognized reporter, '" + reporter + "'. Check available with --list-reporters" ); 9827 return ParserResult::ok( ParseResultType::Matched ); 9828 }; 9829 9830 auto cli 9831 = ExeName( config.processName ) 9832 | Help( config.showHelp ) 9833 | Opt( config.listTests ) 9834 ["-l"]["--list-tests"] 9835 ( "list all/matching test cases" ) 9836 | Opt( config.listTags ) 9837 ["-t"]["--list-tags"] 9838 ( "list all/matching tags" ) 9839 | Opt( config.showSuccessfulTests ) 9840 ["-s"]["--success"] 9841 ( "include successful tests in output" ) 9842 | Opt( config.shouldDebugBreak ) 9843 ["-b"]["--break"] 9844 ( "break into debugger on failure" ) 9845 | Opt( config.noThrow ) 9846 ["-e"]["--nothrow"] 9847 ( "skip exception tests" ) 9848 | Opt( config.showInvisibles ) 9849 ["-i"]["--invisibles"] 9850 ( "show invisibles (tabs, newlines)" ) 9851 | Opt( config.outputFilename, "filename" ) 9852 ["-o"]["--out"] 9853 ( "output filename" ) 9854 | Opt( setReporter, "name" ) 9855 ["-r"]["--reporter"] 9856 ( "reporter to use (defaults to console)" ) 9857 | Opt( config.name, "name" ) 9858 ["-n"]["--name"] 9859 ( "suite name" ) 9860 | Opt( [&]( bool ){ config.abortAfter = 1; } ) 9861 ["-a"]["--abort"] 9862 ( "abort at first failure" ) 9863 | Opt( [&]( int x ){ config.abortAfter = x; }, "no. failures" ) 9864 ["-x"]["--abortx"] 9865 ( "abort after x failures" ) 9866 | Opt( setWarning, "warning name" ) 9867 ["-w"]["--warn"] 9868 ( "enable warnings" ) 9869 | Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" ) 9870 ["-d"]["--durations"] 9871 ( "show test durations" ) 9872 | Opt( config.minDuration, "seconds" ) 9873 ["-D"]["--min-duration"] 9874 ( "show test durations for tests taking at least the given number of seconds" ) 9875 | Opt( loadTestNamesFromFile, "filename" ) 9876 ["-f"]["--input-file"] 9877 ( "load test names to run from a file" ) 9878 | Opt( config.filenamesAsTags ) 9879 ["-#"]["--filenames-as-tags"] 9880 ( "adds a tag for the filename" ) 9881 | Opt( config.sectionsToRun, "section name" ) 9882 ["-c"]["--section"] 9883 ( "specify section to run" ) 9884 | Opt( setVerbosity, "quiet|normal|high" ) 9885 ["-v"]["--verbosity"] 9886 ( "set output verbosity" ) 9887 | Opt( config.listTestNamesOnly ) 9888 ["--list-test-names-only"] 9889 ( "list all/matching test cases names only" ) 9890 | Opt( config.listReporters ) 9891 ["--list-reporters"] 9892 ( "list all reporters" ) 9893 | Opt( setTestOrder, "decl|lex|rand" ) 9894 ["--order"] 9895 ( "test case order (defaults to decl)" ) 9896 | Opt( setRngSeed, "'time'|number" ) 9897 ["--rng-seed"] 9898 ( "set a specific seed for random numbers" ) 9899 | Opt( setColourUsage, "yes|no" ) 9900 ["--use-colour"] 9901 ( "should output be colourised" ) 9902 | Opt( config.libIdentify ) 9903 ["--libidentify"] 9904 ( "report name and version according to libidentify standard" ) 9905 | Opt( setWaitForKeypress, "never|start|exit|both" ) 9906 ["--wait-for-keypress"] 9907 ( "waits for a keypress before exiting" ) 9908 | Opt( config.benchmarkSamples, "samples" ) 9909 ["--benchmark-samples"] 9910 ( "number of samples to collect (default: 100)" ) 9911 | Opt( config.benchmarkResamples, "resamples" ) 9912 ["--benchmark-resamples"] 9913 ( "number of resamples for the bootstrap (default: 100000)" ) 9914 | Opt( config.benchmarkConfidenceInterval, "confidence interval" ) 9915 ["--benchmark-confidence-interval"] 9916 ( "confidence interval for the bootstrap (between 0 and 1, default: 0.95)" ) 9917 | Opt( config.benchmarkNoAnalysis ) 9918 ["--benchmark-no-analysis"] 9919 ( "perform only measurements; do not perform any analysis" ) 9920 | Opt( config.benchmarkWarmupTime, "benchmarkWarmupTime" ) 9921 ["--benchmark-warmup-time"] 9922 ( "amount of time in milliseconds spent on warming up each test (default: 100)" ) 9923 | Arg( config.testsOrTags, "test name|pattern|tags" ) 9924 ( "which test or tests to use" ); 9925 9926 return cli; 9927 } 9928 9929 } // end namespace Catch 9930 // end catch_commandline.cpp 9931 // start catch_common.cpp 9932 9933 #include <cstring> 9934 #include <ostream> 9935 9936 namespace Catch { 9937 9938 bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const noexcept { 9939 return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0); 9940 } 9941 bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const noexcept { 9942 // We can assume that the same file will usually have the same pointer. 9943 // Thus, if the pointers are the same, there is no point in calling the strcmp 9944 return line < other.line || ( line == other.line && file != other.file && (std::strcmp(file, other.file) < 0)); 9945 } 9946 9947 std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { 9948 #ifndef __GNUG__ 9949 os << info.file << '(' << info.line << ')'; 9950 #else 9951 os << info.file << ':' << info.line; 9952 #endif 9953 return os; 9954 } 9955 9956 std::string StreamEndStop::operator+() const { 9957 return std::string(); 9958 } 9959 9960 NonCopyable::NonCopyable() = default; 9961 NonCopyable::~NonCopyable() = default; 9962 9963 } 9964 // end catch_common.cpp 9965 // start catch_config.cpp 9966 9967 namespace Catch { 9968 9969 Config::Config( ConfigData const& data ) 9970 : m_data( data ), 9971 m_stream( openStream() ) 9972 { 9973 // We need to trim filter specs to avoid trouble with superfluous 9974 // whitespace (esp. important for bdd macros, as those are manually 9975 // aligned with whitespace). 9976 9977 for (auto& elem : m_data.testsOrTags) { 9978 elem = trim(elem); 9979 } 9980 for (auto& elem : m_data.sectionsToRun) { 9981 elem = trim(elem); 9982 } 9983 9984 TestSpecParser parser(ITagAliasRegistry::get()); 9985 if (!m_data.testsOrTags.empty()) { 9986 m_hasTestFilters = true; 9987 for (auto const& testOrTags : m_data.testsOrTags) { 9988 parser.parse(testOrTags); 9989 } 9990 } 9991 m_testSpec = parser.testSpec(); 9992 } 9993 9994 std::string const& Config::getFilename() const { 9995 return m_data.outputFilename ; 9996 } 9997 9998 bool Config::listTests() const { return m_data.listTests; } 9999 bool Config::listTestNamesOnly() const { return m_data.listTestNamesOnly; } 10000 bool Config::listTags() const { return m_data.listTags; } 10001 bool Config::listReporters() const { return m_data.listReporters; } 10002 10003 std::string Config::getProcessName() const { return m_data.processName; } 10004 std::string const& Config::getReporterName() const { return m_data.reporterName; } 10005 10006 std::vector<std::string> const& Config::getTestsOrTags() const { return m_data.testsOrTags; } 10007 std::vector<std::string> const& Config::getSectionsToRun() const { return m_data.sectionsToRun; } 10008 10009 TestSpec const& Config::testSpec() const { return m_testSpec; } 10010 bool Config::hasTestFilters() const { return m_hasTestFilters; } 10011 10012 bool Config::showHelp() const { return m_data.showHelp; } 10013 10014 // IConfig interface 10015 bool Config::allowThrows() const { return !m_data.noThrow; } 10016 std::ostream& Config::stream() const { return m_stream->stream(); } 10017 std::string Config::name() const { return m_data.name.empty() ? m_data.processName : m_data.name; } 10018 bool Config::includeSuccessfulResults() const { return m_data.showSuccessfulTests; } 10019 bool Config::warnAboutMissingAssertions() const { return !!(m_data.warnings & WarnAbout::NoAssertions); } 10020 bool Config::warnAboutNoTests() const { return !!(m_data.warnings & WarnAbout::NoTests); } 10021 ShowDurations::OrNot Config::showDurations() const { return m_data.showDurations; } 10022 double Config::minDuration() const { return m_data.minDuration; } 10023 RunTests::InWhatOrder Config::runOrder() const { return m_data.runOrder; } 10024 unsigned int Config::rngSeed() const { return m_data.rngSeed; } 10025 UseColour::YesOrNo Config::useColour() const { return m_data.useColour; } 10026 bool Config::shouldDebugBreak() const { return m_data.shouldDebugBreak; } 10027 int Config::abortAfter() const { return m_data.abortAfter; } 10028 bool Config::showInvisibles() const { return m_data.showInvisibles; } 10029 Verbosity Config::verbosity() const { return m_data.verbosity; } 10030 10031 bool Config::benchmarkNoAnalysis() const { return m_data.benchmarkNoAnalysis; } 10032 int Config::benchmarkSamples() const { return m_data.benchmarkSamples; } 10033 double Config::benchmarkConfidenceInterval() const { return m_data.benchmarkConfidenceInterval; } 10034 unsigned int Config::benchmarkResamples() const { return m_data.benchmarkResamples; } 10035 std::chrono::milliseconds Config::benchmarkWarmupTime() const { return std::chrono::milliseconds(m_data.benchmarkWarmupTime); } 10036 10037 IStream const* Config::openStream() { 10038 return Catch::makeStream(m_data.outputFilename); 10039 } 10040 10041 } // end namespace Catch 10042 // end catch_config.cpp 10043 // start catch_console_colour.cpp 10044 10045 #if defined(__clang__) 10046 # pragma clang diagnostic push 10047 # pragma clang diagnostic ignored "-Wexit-time-destructors" 10048 #endif 10049 10050 // start catch_errno_guard.h 10051 10052 namespace Catch { 10053 10054 class ErrnoGuard { 10055 public: 10056 ErrnoGuard(); 10057 ~ErrnoGuard(); 10058 private: 10059 int m_oldErrno; 10060 }; 10061 10062 } 10063 10064 // end catch_errno_guard.h 10065 #include <sstream> 10066 10067 namespace Catch { 10068 namespace { 10069 10070 struct IColourImpl { 10071 virtual ~IColourImpl() = default; 10072 virtual void use( Colour::Code _colourCode ) = 0; 10073 }; 10074 10075 struct NoColourImpl : IColourImpl { 10076 void use( Colour::Code ) override {} 10077 10078 static IColourImpl* instance() { 10079 static NoColourImpl s_instance; 10080 return &s_instance; 10081 } 10082 }; 10083 10084 } // anon namespace 10085 } // namespace Catch 10086 10087 #if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI ) 10088 # ifdef CATCH_PLATFORM_WINDOWS 10089 # define CATCH_CONFIG_COLOUR_WINDOWS 10090 # else 10091 # define CATCH_CONFIG_COLOUR_ANSI 10092 # endif 10093 #endif 10094 10095 #if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) ///////////////////////////////////////// 10096 10097 namespace Catch { 10098 namespace { 10099 10100 class Win32ColourImpl : public IColourImpl { 10101 public: 10102 Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) ) 10103 { 10104 CONSOLE_SCREEN_BUFFER_INFO csbiInfo; 10105 GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo ); 10106 originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY ); 10107 originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ); 10108 } 10109 10110 void use( Colour::Code _colourCode ) override { 10111 switch( _colourCode ) { 10112 case Colour::None: return setTextAttribute( originalForegroundAttributes ); 10113 case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); 10114 case Colour::Red: return setTextAttribute( FOREGROUND_RED ); 10115 case Colour::Green: return setTextAttribute( FOREGROUND_GREEN ); 10116 case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE ); 10117 case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN ); 10118 case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN ); 10119 case Colour::Grey: return setTextAttribute( 0 ); 10120 10121 case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY ); 10122 case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED ); 10123 case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN ); 10124 case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); 10125 case Colour::BrightYellow: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN ); 10126 10127 case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" ); 10128 10129 default: 10130 CATCH_ERROR( "Unknown colour requested" ); 10131 } 10132 } 10133 10134 private: 10135 void setTextAttribute( WORD _textAttribute ) { 10136 SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes ); 10137 } 10138 HANDLE stdoutHandle; 10139 WORD originalForegroundAttributes; 10140 WORD originalBackgroundAttributes; 10141 }; 10142 10143 IColourImpl* platformColourInstance() { 10144 static Win32ColourImpl s_instance; 10145 10146 IConfigPtr config = getCurrentContext().getConfig(); 10147 UseColour::YesOrNo colourMode = config 10148 ? config->useColour() 10149 : UseColour::Auto; 10150 if( colourMode == UseColour::Auto ) 10151 colourMode = UseColour::Yes; 10152 return colourMode == UseColour::Yes 10153 ? &s_instance 10154 : NoColourImpl::instance(); 10155 } 10156 10157 } // end anon namespace 10158 } // end namespace Catch 10159 10160 #elif defined( CATCH_CONFIG_COLOUR_ANSI ) ////////////////////////////////////// 10161 10162 #include <unistd.h> 10163 10164 namespace Catch { 10165 namespace { 10166 10167 // use POSIX/ ANSI console terminal codes 10168 // Thanks to Adam Strzelecki for original contribution 10169 // (http://github.com/nanoant) 10170 // https://github.com/philsquared/Catch/pull/131 10171 class PosixColourImpl : public IColourImpl { 10172 public: 10173 void use( Colour::Code _colourCode ) override { 10174 switch( _colourCode ) { 10175 case Colour::None: 10176 case Colour::White: return setColour( "[0m" ); 10177 case Colour::Red: return setColour( "[0;31m" ); 10178 case Colour::Green: return setColour( "[0;32m" ); 10179 case Colour::Blue: return setColour( "[0;34m" ); 10180 case Colour::Cyan: return setColour( "[0;36m" ); 10181 case Colour::Yellow: return setColour( "[0;33m" ); 10182 case Colour::Grey: return setColour( "[1;30m" ); 10183 10184 case Colour::LightGrey: return setColour( "[0;37m" ); 10185 case Colour::BrightRed: return setColour( "[1;31m" ); 10186 case Colour::BrightGreen: return setColour( "[1;32m" ); 10187 case Colour::BrightWhite: return setColour( "[1;37m" ); 10188 case Colour::BrightYellow: return setColour( "[1;33m" ); 10189 10190 case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" ); 10191 default: CATCH_INTERNAL_ERROR( "Unknown colour requested" ); 10192 } 10193 } 10194 static IColourImpl* instance() { 10195 static PosixColourImpl s_instance; 10196 return &s_instance; 10197 } 10198 10199 private: 10200 void setColour( const char* _escapeCode ) { 10201 getCurrentContext().getConfig()->stream() 10202 << '\033' << _escapeCode; 10203 } 10204 }; 10205 10206 bool useColourOnPlatform() { 10207 return 10208 #if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE) 10209 !isDebuggerActive() && 10210 #endif 10211 #if !(defined(__DJGPP__) && defined(__STRICT_ANSI__)) 10212 isatty(STDOUT_FILENO) 10213 #else 10214 false 10215 #endif 10216 ; 10217 } 10218 IColourImpl* platformColourInstance() { 10219 ErrnoGuard guard; 10220 IConfigPtr config = getCurrentContext().getConfig(); 10221 UseColour::YesOrNo colourMode = config 10222 ? config->useColour() 10223 : UseColour::Auto; 10224 if( colourMode == UseColour::Auto ) 10225 colourMode = useColourOnPlatform() 10226 ? UseColour::Yes 10227 : UseColour::No; 10228 return colourMode == UseColour::Yes 10229 ? PosixColourImpl::instance() 10230 : NoColourImpl::instance(); 10231 } 10232 10233 } // end anon namespace 10234 } // end namespace Catch 10235 10236 #else // not Windows or ANSI /////////////////////////////////////////////// 10237 10238 namespace Catch { 10239 10240 static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); } 10241 10242 } // end namespace Catch 10243 10244 #endif // Windows/ ANSI/ None 10245 10246 namespace Catch { 10247 10248 Colour::Colour( Code _colourCode ) { use( _colourCode ); } 10249 Colour::Colour( Colour&& other ) noexcept { 10250 m_moved = other.m_moved; 10251 other.m_moved = true; 10252 } 10253 Colour& Colour::operator=( Colour&& other ) noexcept { 10254 m_moved = other.m_moved; 10255 other.m_moved = true; 10256 return *this; 10257 } 10258 10259 Colour::~Colour(){ if( !m_moved ) use( None ); } 10260 10261 void Colour::use( Code _colourCode ) { 10262 static IColourImpl* impl = platformColourInstance(); 10263 // Strictly speaking, this cannot possibly happen. 10264 // However, under some conditions it does happen (see #1626), 10265 // and this change is small enough that we can let practicality 10266 // triumph over purity in this case. 10267 if (impl != nullptr) { 10268 impl->use( _colourCode ); 10269 } 10270 } 10271 10272 std::ostream& operator << ( std::ostream& os, Colour const& ) { 10273 return os; 10274 } 10275 10276 } // end namespace Catch 10277 10278 #if defined(__clang__) 10279 # pragma clang diagnostic pop 10280 #endif 10281 10282 // end catch_console_colour.cpp 10283 // start catch_context.cpp 10284 10285 namespace Catch { 10286 10287 class Context : public IMutableContext, NonCopyable { 10288 10289 public: // IContext 10290 IResultCapture* getResultCapture() override { 10291 return m_resultCapture; 10292 } 10293 IRunner* getRunner() override { 10294 return m_runner; 10295 } 10296 10297 IConfigPtr const& getConfig() const override { 10298 return m_config; 10299 } 10300 10301 ~Context() override; 10302 10303 public: // IMutableContext 10304 void setResultCapture( IResultCapture* resultCapture ) override { 10305 m_resultCapture = resultCapture; 10306 } 10307 void setRunner( IRunner* runner ) override { 10308 m_runner = runner; 10309 } 10310 void setConfig( IConfigPtr const& config ) override { 10311 m_config = config; 10312 } 10313 10314 friend IMutableContext& getCurrentMutableContext(); 10315 10316 private: 10317 IConfigPtr m_config; 10318 IRunner* m_runner = nullptr; 10319 IResultCapture* m_resultCapture = nullptr; 10320 }; 10321 10322 IMutableContext *IMutableContext::currentContext = nullptr; 10323 10324 void IMutableContext::createContext() 10325 { 10326 currentContext = new Context(); 10327 } 10328 10329 void cleanUpContext() { 10330 delete IMutableContext::currentContext; 10331 IMutableContext::currentContext = nullptr; 10332 } 10333 IContext::~IContext() = default; 10334 IMutableContext::~IMutableContext() = default; 10335 Context::~Context() = default; 10336 10337 SimplePcg32& rng() { 10338 static SimplePcg32 s_rng; 10339 return s_rng; 10340 } 10341 10342 } 10343 // end catch_context.cpp 10344 // start catch_debug_console.cpp 10345 10346 // start catch_debug_console.h 10347 10348 #include <string> 10349 10350 namespace Catch { 10351 void writeToDebugConsole( std::string const& text ); 10352 } 10353 10354 // end catch_debug_console.h 10355 #if defined(CATCH_CONFIG_ANDROID_LOGWRITE) 10356 #include <android/log.h> 10357 10358 namespace Catch { 10359 void writeToDebugConsole( std::string const& text ) { 10360 __android_log_write( ANDROID_LOG_DEBUG, "Catch", text.c_str() ); 10361 } 10362 } 10363 10364 #elif defined(CATCH_PLATFORM_WINDOWS) 10365 10366 namespace Catch { 10367 void writeToDebugConsole( std::string const& text ) { 10368 ::OutputDebugStringA( text.c_str() ); 10369 } 10370 } 10371 10372 #else 10373 10374 namespace Catch { 10375 void writeToDebugConsole( std::string const& text ) { 10376 // !TBD: Need a version for Mac/ XCode and other IDEs 10377 Catch::cout() << text; 10378 } 10379 } 10380 10381 #endif // Platform 10382 // end catch_debug_console.cpp 10383 // start catch_debugger.cpp 10384 10385 #if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE) 10386 10387 # include <cassert> 10388 # include <sys/types.h> 10389 # include <unistd.h> 10390 # include <cstddef> 10391 # include <ostream> 10392 10393 #ifdef __apple_build_version__ 10394 // These headers will only compile with AppleClang (XCode) 10395 // For other compilers (Clang, GCC, ... ) we need to exclude them 10396 # include <sys/sysctl.h> 10397 #endif 10398 10399 namespace Catch { 10400 #ifdef __apple_build_version__ 10401 // The following function is taken directly from the following technical note: 10402 // https://developer.apple.com/library/archive/qa/qa1361/_index.html 10403 10404 // Returns true if the current process is being debugged (either 10405 // running under the debugger or has a debugger attached post facto). 10406 bool isDebuggerActive(){ 10407 int mib[4]; 10408 struct kinfo_proc info; 10409 std::size_t size; 10410 10411 // Initialize the flags so that, if sysctl fails for some bizarre 10412 // reason, we get a predictable result. 10413 10414 info.kp_proc.p_flag = 0; 10415 10416 // Initialize mib, which tells sysctl the info we want, in this case 10417 // we're looking for information about a specific process ID. 10418 10419 mib[0] = CTL_KERN; 10420 mib[1] = KERN_PROC; 10421 mib[2] = KERN_PROC_PID; 10422 mib[3] = getpid(); 10423 10424 // Call sysctl. 10425 10426 size = sizeof(info); 10427 if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, nullptr, 0) != 0 ) { 10428 Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; 10429 return false; 10430 } 10431 10432 // We're being debugged if the P_TRACED flag is set. 10433 10434 return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); 10435 } 10436 #else 10437 bool isDebuggerActive() { 10438 // We need to find another way to determine this for non-appleclang compilers on macOS 10439 return false; 10440 } 10441 #endif 10442 } // namespace Catch 10443 10444 #elif defined(CATCH_PLATFORM_LINUX) 10445 #include <fstream> 10446 #include <string> 10447 10448 namespace Catch{ 10449 // The standard POSIX way of detecting a debugger is to attempt to 10450 // ptrace() the process, but this needs to be done from a child and not 10451 // this process itself to still allow attaching to this process later 10452 // if wanted, so is rather heavy. Under Linux we have the PID of the 10453 // "debugger" (which doesn't need to be gdb, of course, it could also 10454 // be strace, for example) in /proc/$PID/status, so just get it from 10455 // there instead. 10456 bool isDebuggerActive(){ 10457 // Libstdc++ has a bug, where std::ifstream sets errno to 0 10458 // This way our users can properly assert over errno values 10459 ErrnoGuard guard; 10460 std::ifstream in("/proc/self/status"); 10461 for( std::string line; std::getline(in, line); ) { 10462 static const int PREFIX_LEN = 11; 10463 if( line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0 ) { 10464 // We're traced if the PID is not 0 and no other PID starts 10465 // with 0 digit, so it's enough to check for just a single 10466 // character. 10467 return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0'; 10468 } 10469 } 10470 10471 return false; 10472 } 10473 } // namespace Catch 10474 #elif defined(_MSC_VER) 10475 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); 10476 namespace Catch { 10477 bool isDebuggerActive() { 10478 return IsDebuggerPresent() != 0; 10479 } 10480 } 10481 #elif defined(__MINGW32__) 10482 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); 10483 namespace Catch { 10484 bool isDebuggerActive() { 10485 return IsDebuggerPresent() != 0; 10486 } 10487 } 10488 #else 10489 namespace Catch { 10490 bool isDebuggerActive() { return false; } 10491 } 10492 #endif // Platform 10493 // end catch_debugger.cpp 10494 // start catch_decomposer.cpp 10495 10496 namespace Catch { 10497 10498 ITransientExpression::~ITransientExpression() = default; 10499 10500 void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ) { 10501 if( lhs.size() + rhs.size() < 40 && 10502 lhs.find('\n') == std::string::npos && 10503 rhs.find('\n') == std::string::npos ) 10504 os << lhs << " " << op << " " << rhs; 10505 else 10506 os << lhs << "\n" << op << "\n" << rhs; 10507 } 10508 } 10509 // end catch_decomposer.cpp 10510 // start catch_enforce.cpp 10511 10512 #include <stdexcept> 10513 10514 namespace Catch { 10515 #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER) 10516 [[noreturn]] 10517 void throw_exception(std::exception const& e) { 10518 Catch::cerr() << "Catch will terminate because it needed to throw an exception.\n" 10519 << "The message was: " << e.what() << '\n'; 10520 std::terminate(); 10521 } 10522 #endif 10523 10524 [[noreturn]] 10525 void throw_logic_error(std::string const& msg) { 10526 throw_exception(std::logic_error(msg)); 10527 } 10528 10529 [[noreturn]] 10530 void throw_domain_error(std::string const& msg) { 10531 throw_exception(std::domain_error(msg)); 10532 } 10533 10534 [[noreturn]] 10535 void throw_runtime_error(std::string const& msg) { 10536 throw_exception(std::runtime_error(msg)); 10537 } 10538 10539 } // namespace Catch; 10540 // end catch_enforce.cpp 10541 // start catch_enum_values_registry.cpp 10542 // start catch_enum_values_registry.h 10543 10544 #include <vector> 10545 #include <memory> 10546 10547 namespace Catch { 10548 10549 namespace Detail { 10550 10551 std::unique_ptr<EnumInfo> makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ); 10552 10553 class EnumValuesRegistry : public IMutableEnumValuesRegistry { 10554 10555 std::vector<std::unique_ptr<EnumInfo>> m_enumInfos; 10556 10557 EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::vector<int> const& values) override; 10558 }; 10559 10560 std::vector<StringRef> parseEnums( StringRef enums ); 10561 10562 } // Detail 10563 10564 } // Catch 10565 10566 // end catch_enum_values_registry.h 10567 10568 #include <map> 10569 #include <cassert> 10570 10571 namespace Catch { 10572 10573 IMutableEnumValuesRegistry::~IMutableEnumValuesRegistry() {} 10574 10575 namespace Detail { 10576 10577 namespace { 10578 // Extracts the actual name part of an enum instance 10579 // In other words, it returns the Blue part of Bikeshed::Colour::Blue 10580 StringRef extractInstanceName(StringRef enumInstance) { 10581 // Find last occurence of ":" 10582 size_t name_start = enumInstance.size(); 10583 while (name_start > 0 && enumInstance[name_start - 1] != ':') { 10584 --name_start; 10585 } 10586 return enumInstance.substr(name_start, enumInstance.size() - name_start); 10587 } 10588 } 10589 10590 std::vector<StringRef> parseEnums( StringRef enums ) { 10591 auto enumValues = splitStringRef( enums, ',' ); 10592 std::vector<StringRef> parsed; 10593 parsed.reserve( enumValues.size() ); 10594 for( auto const& enumValue : enumValues ) { 10595 parsed.push_back(trim(extractInstanceName(enumValue))); 10596 } 10597 return parsed; 10598 } 10599 10600 EnumInfo::~EnumInfo() {} 10601 10602 StringRef EnumInfo::lookup( int value ) const { 10603 for( auto const& valueToName : m_values ) { 10604 if( valueToName.first == value ) 10605 return valueToName.second; 10606 } 10607 return "{** unexpected enum value **}"_sr; 10608 } 10609 10610 std::unique_ptr<EnumInfo> makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ) { 10611 std::unique_ptr<EnumInfo> enumInfo( new EnumInfo ); 10612 enumInfo->m_name = enumName; 10613 enumInfo->m_values.reserve( values.size() ); 10614 10615 const auto valueNames = Catch::Detail::parseEnums( allValueNames ); 10616 assert( valueNames.size() == values.size() ); 10617 std::size_t i = 0; 10618 for( auto value : values ) 10619 enumInfo->m_values.emplace_back(value, valueNames[i++]); 10620 10621 return enumInfo; 10622 } 10623 10624 EnumInfo const& EnumValuesRegistry::registerEnum( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ) { 10625 m_enumInfos.push_back(makeEnumInfo(enumName, allValueNames, values)); 10626 return *m_enumInfos.back(); 10627 } 10628 10629 } // Detail 10630 } // Catch 10631 10632 // end catch_enum_values_registry.cpp 10633 // start catch_errno_guard.cpp 10634 10635 #include <cerrno> 10636 10637 namespace Catch { 10638 ErrnoGuard::ErrnoGuard():m_oldErrno(errno){} 10639 ErrnoGuard::~ErrnoGuard() { errno = m_oldErrno; } 10640 } 10641 // end catch_errno_guard.cpp 10642 // start catch_exception_translator_registry.cpp 10643 10644 // start catch_exception_translator_registry.h 10645 10646 #include <vector> 10647 #include <string> 10648 #include <memory> 10649 10650 namespace Catch { 10651 10652 class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { 10653 public: 10654 ~ExceptionTranslatorRegistry(); 10655 virtual void registerTranslator( const IExceptionTranslator* translator ); 10656 std::string translateActiveException() const override; 10657 std::string tryTranslators() const; 10658 10659 private: 10660 std::vector<std::unique_ptr<IExceptionTranslator const>> m_translators; 10661 }; 10662 } 10663 10664 // end catch_exception_translator_registry.h 10665 #ifdef __OBJC__ 10666 #import "Foundation/Foundation.h" 10667 #endif 10668 10669 namespace Catch { 10670 10671 ExceptionTranslatorRegistry::~ExceptionTranslatorRegistry() { 10672 } 10673 10674 void ExceptionTranslatorRegistry::registerTranslator( const IExceptionTranslator* translator ) { 10675 m_translators.push_back( std::unique_ptr<const IExceptionTranslator>( translator ) ); 10676 } 10677 10678 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 10679 std::string ExceptionTranslatorRegistry::translateActiveException() const { 10680 try { 10681 #ifdef __OBJC__ 10682 // In Objective-C try objective-c exceptions first 10683 @try { 10684 return tryTranslators(); 10685 } 10686 @catch (NSException *exception) { 10687 return Catch::Detail::stringify( [exception description] ); 10688 } 10689 #else 10690 // Compiling a mixed mode project with MSVC means that CLR 10691 // exceptions will be caught in (...) as well. However, these 10692 // do not fill-in std::current_exception and thus lead to crash 10693 // when attempting rethrow. 10694 // /EHa switch also causes structured exceptions to be caught 10695 // here, but they fill-in current_exception properly, so 10696 // at worst the output should be a little weird, instead of 10697 // causing a crash. 10698 if (std::current_exception() == nullptr) { 10699 return "Non C++ exception. Possibly a CLR exception."; 10700 } 10701 return tryTranslators(); 10702 #endif 10703 } 10704 catch( TestFailureException& ) { 10705 std::rethrow_exception(std::current_exception()); 10706 } 10707 catch( std::exception& ex ) { 10708 return ex.what(); 10709 } 10710 catch( std::string& msg ) { 10711 return msg; 10712 } 10713 catch( const char* msg ) { 10714 return msg; 10715 } 10716 catch(...) { 10717 return "Unknown exception"; 10718 } 10719 } 10720 10721 std::string ExceptionTranslatorRegistry::tryTranslators() const { 10722 if (m_translators.empty()) { 10723 std::rethrow_exception(std::current_exception()); 10724 } else { 10725 return m_translators[0]->translate(m_translators.begin() + 1, m_translators.end()); 10726 } 10727 } 10728 10729 #else // ^^ Exceptions are enabled // Exceptions are disabled vv 10730 std::string ExceptionTranslatorRegistry::translateActiveException() const { 10731 CATCH_INTERNAL_ERROR("Attempted to translate active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!"); 10732 } 10733 10734 std::string ExceptionTranslatorRegistry::tryTranslators() const { 10735 CATCH_INTERNAL_ERROR("Attempted to use exception translators under CATCH_CONFIG_DISABLE_EXCEPTIONS!"); 10736 } 10737 #endif 10738 10739 } 10740 // end catch_exception_translator_registry.cpp 10741 // start catch_fatal_condition.cpp 10742 10743 #if defined(__GNUC__) 10744 # pragma GCC diagnostic push 10745 # pragma GCC diagnostic ignored "-Wmissing-field-initializers" 10746 #endif 10747 10748 #if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS ) 10749 10750 namespace { 10751 // Report the error condition 10752 void reportFatal( char const * const message ) { 10753 Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message ); 10754 } 10755 } 10756 10757 #endif // signals/SEH handling 10758 10759 #if defined( CATCH_CONFIG_WINDOWS_SEH ) 10760 10761 namespace Catch { 10762 struct SignalDefs { DWORD id; const char* name; }; 10763 10764 // There is no 1-1 mapping between signals and windows exceptions. 10765 // Windows can easily distinguish between SO and SigSegV, 10766 // but SigInt, SigTerm, etc are handled differently. 10767 static SignalDefs signalDefs[] = { 10768 { static_cast<DWORD>(EXCEPTION_ILLEGAL_INSTRUCTION), "SIGILL - Illegal instruction signal" }, 10769 { static_cast<DWORD>(EXCEPTION_STACK_OVERFLOW), "SIGSEGV - Stack overflow" }, 10770 { static_cast<DWORD>(EXCEPTION_ACCESS_VIOLATION), "SIGSEGV - Segmentation violation signal" }, 10771 { static_cast<DWORD>(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error" }, 10772 }; 10773 10774 LONG CALLBACK FatalConditionHandler::handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) { 10775 for (auto const& def : signalDefs) { 10776 if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) { 10777 reportFatal(def.name); 10778 } 10779 } 10780 // If its not an exception we care about, pass it along. 10781 // This stops us from eating debugger breaks etc. 10782 return EXCEPTION_CONTINUE_SEARCH; 10783 } 10784 10785 FatalConditionHandler::FatalConditionHandler() { 10786 isSet = true; 10787 // 32k seems enough for Catch to handle stack overflow, 10788 // but the value was found experimentally, so there is no strong guarantee 10789 guaranteeSize = 32 * 1024; 10790 exceptionHandlerHandle = nullptr; 10791 // Register as first handler in current chain 10792 exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException); 10793 // Pass in guarantee size to be filled 10794 SetThreadStackGuarantee(&guaranteeSize); 10795 } 10796 10797 void FatalConditionHandler::reset() { 10798 if (isSet) { 10799 RemoveVectoredExceptionHandler(exceptionHandlerHandle); 10800 SetThreadStackGuarantee(&guaranteeSize); 10801 exceptionHandlerHandle = nullptr; 10802 isSet = false; 10803 } 10804 } 10805 10806 FatalConditionHandler::~FatalConditionHandler() { 10807 reset(); 10808 } 10809 10810 bool FatalConditionHandler::isSet = false; 10811 ULONG FatalConditionHandler::guaranteeSize = 0; 10812 PVOID FatalConditionHandler::exceptionHandlerHandle = nullptr; 10813 10814 } // namespace Catch 10815 10816 #elif defined( CATCH_CONFIG_POSIX_SIGNALS ) 10817 10818 namespace Catch { 10819 10820 struct SignalDefs { 10821 int id; 10822 const char* name; 10823 }; 10824 10825 // 32kb for the alternate stack seems to be sufficient. However, this value 10826 // is experimentally determined, so that's not guaranteed. 10827 static constexpr std::size_t sigStackSize = 32768 >= MINSIGSTKSZ ? 32768 : MINSIGSTKSZ; 10828 10829 static SignalDefs signalDefs[] = { 10830 { SIGINT, "SIGINT - Terminal interrupt signal" }, 10831 { SIGILL, "SIGILL - Illegal instruction signal" }, 10832 { SIGFPE, "SIGFPE - Floating point error signal" }, 10833 { SIGSEGV, "SIGSEGV - Segmentation violation signal" }, 10834 { SIGTERM, "SIGTERM - Termination request signal" }, 10835 { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" } 10836 }; 10837 10838 void FatalConditionHandler::handleSignal( int sig ) { 10839 char const * name = "<unknown signal>"; 10840 for (auto const& def : signalDefs) { 10841 if (sig == def.id) { 10842 name = def.name; 10843 break; 10844 } 10845 } 10846 reset(); 10847 reportFatal(name); 10848 raise( sig ); 10849 } 10850 10851 FatalConditionHandler::FatalConditionHandler() { 10852 isSet = true; 10853 stack_t sigStack; 10854 sigStack.ss_sp = altStackMem; 10855 sigStack.ss_size = sigStackSize; 10856 sigStack.ss_flags = 0; 10857 sigaltstack(&sigStack, &oldSigStack); 10858 struct sigaction sa = { }; 10859 10860 sa.sa_handler = handleSignal; 10861 sa.sa_flags = SA_ONSTACK; 10862 for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) { 10863 sigaction(signalDefs[i].id, &sa, &oldSigActions[i]); 10864 } 10865 } 10866 10867 FatalConditionHandler::~FatalConditionHandler() { 10868 reset(); 10869 } 10870 10871 void FatalConditionHandler::reset() { 10872 if( isSet ) { 10873 // Set signals back to previous values -- hopefully nobody overwrote them in the meantime 10874 for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) { 10875 sigaction(signalDefs[i].id, &oldSigActions[i], nullptr); 10876 } 10877 // Return the old stack 10878 sigaltstack(&oldSigStack, nullptr); 10879 isSet = false; 10880 } 10881 } 10882 10883 bool FatalConditionHandler::isSet = false; 10884 struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {}; 10885 stack_t FatalConditionHandler::oldSigStack = {}; 10886 char FatalConditionHandler::altStackMem[sigStackSize] = {}; 10887 10888 } // namespace Catch 10889 10890 #else 10891 10892 namespace Catch { 10893 void FatalConditionHandler::reset() {} 10894 } 10895 10896 #endif // signals/SEH handling 10897 10898 #if defined(__GNUC__) 10899 # pragma GCC diagnostic pop 10900 #endif 10901 // end catch_fatal_condition.cpp 10902 // start catch_generators.cpp 10903 10904 #include <limits> 10905 #include <set> 10906 10907 namespace Catch { 10908 10909 IGeneratorTracker::~IGeneratorTracker() {} 10910 10911 const char* GeneratorException::what() const noexcept { 10912 return m_msg; 10913 } 10914 10915 namespace Generators { 10916 10917 GeneratorUntypedBase::~GeneratorUntypedBase() {} 10918 10919 auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& { 10920 return getResultCapture().acquireGeneratorTracker( generatorName, lineInfo ); 10921 } 10922 10923 } // namespace Generators 10924 } // namespace Catch 10925 // end catch_generators.cpp 10926 // start catch_interfaces_capture.cpp 10927 10928 namespace Catch { 10929 IResultCapture::~IResultCapture() = default; 10930 } 10931 // end catch_interfaces_capture.cpp 10932 // start catch_interfaces_config.cpp 10933 10934 namespace Catch { 10935 IConfig::~IConfig() = default; 10936 } 10937 // end catch_interfaces_config.cpp 10938 // start catch_interfaces_exception.cpp 10939 10940 namespace Catch { 10941 IExceptionTranslator::~IExceptionTranslator() = default; 10942 IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() = default; 10943 } 10944 // end catch_interfaces_exception.cpp 10945 // start catch_interfaces_registry_hub.cpp 10946 10947 namespace Catch { 10948 IRegistryHub::~IRegistryHub() = default; 10949 IMutableRegistryHub::~IMutableRegistryHub() = default; 10950 } 10951 // end catch_interfaces_registry_hub.cpp 10952 // start catch_interfaces_reporter.cpp 10953 10954 // start catch_reporter_listening.h 10955 10956 namespace Catch { 10957 10958 class ListeningReporter : public IStreamingReporter { 10959 using Reporters = std::vector<IStreamingReporterPtr>; 10960 Reporters m_listeners; 10961 IStreamingReporterPtr m_reporter = nullptr; 10962 ReporterPreferences m_preferences; 10963 10964 public: 10965 ListeningReporter(); 10966 10967 void addListener( IStreamingReporterPtr&& listener ); 10968 void addReporter( IStreamingReporterPtr&& reporter ); 10969 10970 public: // IStreamingReporter 10971 10972 ReporterPreferences getPreferences() const override; 10973 10974 void noMatchingTestCases( std::string const& spec ) override; 10975 10976 void reportInvalidArguments(std::string const&arg) override; 10977 10978 static std::set<Verbosity> getSupportedVerbosities(); 10979 10980 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 10981 void benchmarkPreparing(std::string const& name) override; 10982 void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) override; 10983 void benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) override; 10984 void benchmarkFailed(std::string const&) override; 10985 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 10986 10987 void testRunStarting( TestRunInfo const& testRunInfo ) override; 10988 void testGroupStarting( GroupInfo const& groupInfo ) override; 10989 void testCaseStarting( TestCaseInfo const& testInfo ) override; 10990 void sectionStarting( SectionInfo const& sectionInfo ) override; 10991 void assertionStarting( AssertionInfo const& assertionInfo ) override; 10992 10993 // The return value indicates if the messages buffer should be cleared: 10994 bool assertionEnded( AssertionStats const& assertionStats ) override; 10995 void sectionEnded( SectionStats const& sectionStats ) override; 10996 void testCaseEnded( TestCaseStats const& testCaseStats ) override; 10997 void testGroupEnded( TestGroupStats const& testGroupStats ) override; 10998 void testRunEnded( TestRunStats const& testRunStats ) override; 10999 11000 void skipTest( TestCaseInfo const& testInfo ) override; 11001 bool isMulti() const override; 11002 11003 }; 11004 11005 } // end namespace Catch 11006 11007 // end catch_reporter_listening.h 11008 namespace Catch { 11009 11010 ReporterConfig::ReporterConfig( IConfigPtr const& _fullConfig ) 11011 : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} 11012 11013 ReporterConfig::ReporterConfig( IConfigPtr const& _fullConfig, std::ostream& _stream ) 11014 : m_stream( &_stream ), m_fullConfig( _fullConfig ) {} 11015 11016 std::ostream& ReporterConfig::stream() const { return *m_stream; } 11017 IConfigPtr ReporterConfig::fullConfig() const { return m_fullConfig; } 11018 11019 TestRunInfo::TestRunInfo( std::string const& _name ) : name( _name ) {} 11020 11021 GroupInfo::GroupInfo( std::string const& _name, 11022 std::size_t _groupIndex, 11023 std::size_t _groupsCount ) 11024 : name( _name ), 11025 groupIndex( _groupIndex ), 11026 groupsCounts( _groupsCount ) 11027 {} 11028 11029 AssertionStats::AssertionStats( AssertionResult const& _assertionResult, 11030 std::vector<MessageInfo> const& _infoMessages, 11031 Totals const& _totals ) 11032 : assertionResult( _assertionResult ), 11033 infoMessages( _infoMessages ), 11034 totals( _totals ) 11035 { 11036 assertionResult.m_resultData.lazyExpression.m_transientExpression = _assertionResult.m_resultData.lazyExpression.m_transientExpression; 11037 11038 if( assertionResult.hasMessage() ) { 11039 // Copy message into messages list. 11040 // !TBD This should have been done earlier, somewhere 11041 MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); 11042 builder << assertionResult.getMessage(); 11043 builder.m_info.message = builder.m_stream.str(); 11044 11045 infoMessages.push_back( builder.m_info ); 11046 } 11047 } 11048 11049 AssertionStats::~AssertionStats() = default; 11050 11051 SectionStats::SectionStats( SectionInfo const& _sectionInfo, 11052 Counts const& _assertions, 11053 double _durationInSeconds, 11054 bool _missingAssertions ) 11055 : sectionInfo( _sectionInfo ), 11056 assertions( _assertions ), 11057 durationInSeconds( _durationInSeconds ), 11058 missingAssertions( _missingAssertions ) 11059 {} 11060 11061 SectionStats::~SectionStats() = default; 11062 11063 TestCaseStats::TestCaseStats( TestCaseInfo const& _testInfo, 11064 Totals const& _totals, 11065 std::string const& _stdOut, 11066 std::string const& _stdErr, 11067 bool _aborting ) 11068 : testInfo( _testInfo ), 11069 totals( _totals ), 11070 stdOut( _stdOut ), 11071 stdErr( _stdErr ), 11072 aborting( _aborting ) 11073 {} 11074 11075 TestCaseStats::~TestCaseStats() = default; 11076 11077 TestGroupStats::TestGroupStats( GroupInfo const& _groupInfo, 11078 Totals const& _totals, 11079 bool _aborting ) 11080 : groupInfo( _groupInfo ), 11081 totals( _totals ), 11082 aborting( _aborting ) 11083 {} 11084 11085 TestGroupStats::TestGroupStats( GroupInfo const& _groupInfo ) 11086 : groupInfo( _groupInfo ), 11087 aborting( false ) 11088 {} 11089 11090 TestGroupStats::~TestGroupStats() = default; 11091 11092 TestRunStats::TestRunStats( TestRunInfo const& _runInfo, 11093 Totals const& _totals, 11094 bool _aborting ) 11095 : runInfo( _runInfo ), 11096 totals( _totals ), 11097 aborting( _aborting ) 11098 {} 11099 11100 TestRunStats::~TestRunStats() = default; 11101 11102 void IStreamingReporter::fatalErrorEncountered( StringRef ) {} 11103 bool IStreamingReporter::isMulti() const { return false; } 11104 11105 IReporterFactory::~IReporterFactory() = default; 11106 IReporterRegistry::~IReporterRegistry() = default; 11107 11108 } // end namespace Catch 11109 // end catch_interfaces_reporter.cpp 11110 // start catch_interfaces_runner.cpp 11111 11112 namespace Catch { 11113 IRunner::~IRunner() = default; 11114 } 11115 // end catch_interfaces_runner.cpp 11116 // start catch_interfaces_testcase.cpp 11117 11118 namespace Catch { 11119 ITestInvoker::~ITestInvoker() = default; 11120 ITestCaseRegistry::~ITestCaseRegistry() = default; 11121 } 11122 // end catch_interfaces_testcase.cpp 11123 // start catch_leak_detector.cpp 11124 11125 #ifdef CATCH_CONFIG_WINDOWS_CRTDBG 11126 #include <crtdbg.h> 11127 11128 namespace Catch { 11129 11130 LeakDetector::LeakDetector() { 11131 int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); 11132 flag |= _CRTDBG_LEAK_CHECK_DF; 11133 flag |= _CRTDBG_ALLOC_MEM_DF; 11134 _CrtSetDbgFlag(flag); 11135 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); 11136 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); 11137 // Change this to leaking allocation's number to break there 11138 _CrtSetBreakAlloc(-1); 11139 } 11140 } 11141 11142 #else 11143 11144 Catch::LeakDetector::LeakDetector() {} 11145 11146 #endif 11147 11148 Catch::LeakDetector::~LeakDetector() { 11149 Catch::cleanUp(); 11150 } 11151 // end catch_leak_detector.cpp 11152 // start catch_list.cpp 11153 11154 // start catch_list.h 11155 11156 #include <set> 11157 11158 namespace Catch { 11159 11160 std::size_t listTests( Config const& config ); 11161 11162 std::size_t listTestsNamesOnly( Config const& config ); 11163 11164 struct TagInfo { 11165 void add( std::string const& spelling ); 11166 std::string all() const; 11167 11168 std::set<std::string> spellings; 11169 std::size_t count = 0; 11170 }; 11171 11172 std::size_t listTags( Config const& config ); 11173 11174 std::size_t listReporters(); 11175 11176 Option<std::size_t> list( std::shared_ptr<Config> const& config ); 11177 11178 } // end namespace Catch 11179 11180 // end catch_list.h 11181 // start catch_text.h 11182 11183 namespace Catch { 11184 using namespace clara::TextFlow; 11185 } 11186 11187 // end catch_text.h 11188 #include <limits> 11189 #include <algorithm> 11190 #include <iomanip> 11191 11192 namespace Catch { 11193 11194 std::size_t listTests( Config const& config ) { 11195 TestSpec const& testSpec = config.testSpec(); 11196 if( config.hasTestFilters() ) 11197 Catch::cout() << "Matching test cases:\n"; 11198 else { 11199 Catch::cout() << "All available test cases:\n"; 11200 } 11201 11202 auto matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); 11203 for( auto const& testCaseInfo : matchedTestCases ) { 11204 Colour::Code colour = testCaseInfo.isHidden() 11205 ? Colour::SecondaryText 11206 : Colour::None; 11207 Colour colourGuard( colour ); 11208 11209 Catch::cout() << Column( testCaseInfo.name ).initialIndent( 2 ).indent( 4 ) << "\n"; 11210 if( config.verbosity() >= Verbosity::High ) { 11211 Catch::cout() << Column( Catch::Detail::stringify( testCaseInfo.lineInfo ) ).indent(4) << std::endl; 11212 std::string description = testCaseInfo.description; 11213 if( description.empty() ) 11214 description = "(NO DESCRIPTION)"; 11215 Catch::cout() << Column( description ).indent(4) << std::endl; 11216 } 11217 if( !testCaseInfo.tags.empty() ) 11218 Catch::cout() << Column( testCaseInfo.tagsAsString() ).indent( 6 ) << "\n"; 11219 } 11220 11221 if( !config.hasTestFilters() ) 11222 Catch::cout() << pluralise( matchedTestCases.size(), "test case" ) << '\n' << std::endl; 11223 else 11224 Catch::cout() << pluralise( matchedTestCases.size(), "matching test case" ) << '\n' << std::endl; 11225 return matchedTestCases.size(); 11226 } 11227 11228 std::size_t listTestsNamesOnly( Config const& config ) { 11229 TestSpec const& testSpec = config.testSpec(); 11230 std::size_t matchedTests = 0; 11231 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); 11232 for( auto const& testCaseInfo : matchedTestCases ) { 11233 matchedTests++; 11234 if( startsWith( testCaseInfo.name, '#' ) ) 11235 Catch::cout() << '"' << testCaseInfo.name << '"'; 11236 else 11237 Catch::cout() << testCaseInfo.name; 11238 if ( config.verbosity() >= Verbosity::High ) 11239 Catch::cout() << "\t@" << testCaseInfo.lineInfo; 11240 Catch::cout() << std::endl; 11241 } 11242 return matchedTests; 11243 } 11244 11245 void TagInfo::add( std::string const& spelling ) { 11246 ++count; 11247 spellings.insert( spelling ); 11248 } 11249 11250 std::string TagInfo::all() const { 11251 size_t size = 0; 11252 for (auto const& spelling : spellings) { 11253 // Add 2 for the brackes 11254 size += spelling.size() + 2; 11255 } 11256 11257 std::string out; out.reserve(size); 11258 for (auto const& spelling : spellings) { 11259 out += '['; 11260 out += spelling; 11261 out += ']'; 11262 } 11263 return out; 11264 } 11265 11266 std::size_t listTags( Config const& config ) { 11267 TestSpec const& testSpec = config.testSpec(); 11268 if( config.hasTestFilters() ) 11269 Catch::cout() << "Tags for matching test cases:\n"; 11270 else { 11271 Catch::cout() << "All available tags:\n"; 11272 } 11273 11274 std::map<std::string, TagInfo> tagCounts; 11275 11276 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); 11277 for( auto const& testCase : matchedTestCases ) { 11278 for( auto const& tagName : testCase.getTestCaseInfo().tags ) { 11279 std::string lcaseTagName = toLower( tagName ); 11280 auto countIt = tagCounts.find( lcaseTagName ); 11281 if( countIt == tagCounts.end() ) 11282 countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first; 11283 countIt->second.add( tagName ); 11284 } 11285 } 11286 11287 for( auto const& tagCount : tagCounts ) { 11288 ReusableStringStream rss; 11289 rss << " " << std::setw(2) << tagCount.second.count << " "; 11290 auto str = rss.str(); 11291 auto wrapper = Column( tagCount.second.all() ) 11292 .initialIndent( 0 ) 11293 .indent( str.size() ) 11294 .width( CATCH_CONFIG_CONSOLE_WIDTH-10 ); 11295 Catch::cout() << str << wrapper << '\n'; 11296 } 11297 Catch::cout() << pluralise( tagCounts.size(), "tag" ) << '\n' << std::endl; 11298 return tagCounts.size(); 11299 } 11300 11301 std::size_t listReporters() { 11302 Catch::cout() << "Available reporters:\n"; 11303 IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); 11304 std::size_t maxNameLen = 0; 11305 for( auto const& factoryKvp : factories ) 11306 maxNameLen = (std::max)( maxNameLen, factoryKvp.first.size() ); 11307 11308 for( auto const& factoryKvp : factories ) { 11309 Catch::cout() 11310 << Column( factoryKvp.first + ":" ) 11311 .indent(2) 11312 .width( 5+maxNameLen ) 11313 + Column( factoryKvp.second->getDescription() ) 11314 .initialIndent(0) 11315 .indent(2) 11316 .width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) 11317 << "\n"; 11318 } 11319 Catch::cout() << std::endl; 11320 return factories.size(); 11321 } 11322 11323 Option<std::size_t> list( std::shared_ptr<Config> const& config ) { 11324 Option<std::size_t> listedCount; 11325 getCurrentMutableContext().setConfig( config ); 11326 if( config->listTests() ) 11327 listedCount = listedCount.valueOr(0) + listTests( *config ); 11328 if( config->listTestNamesOnly() ) 11329 listedCount = listedCount.valueOr(0) + listTestsNamesOnly( *config ); 11330 if( config->listTags() ) 11331 listedCount = listedCount.valueOr(0) + listTags( *config ); 11332 if( config->listReporters() ) 11333 listedCount = listedCount.valueOr(0) + listReporters(); 11334 return listedCount; 11335 } 11336 11337 } // end namespace Catch 11338 // end catch_list.cpp 11339 // start catch_matchers.cpp 11340 11341 namespace Catch { 11342 namespace Matchers { 11343 namespace Impl { 11344 11345 std::string MatcherUntypedBase::toString() const { 11346 if( m_cachedToString.empty() ) 11347 m_cachedToString = describe(); 11348 return m_cachedToString; 11349 } 11350 11351 MatcherUntypedBase::~MatcherUntypedBase() = default; 11352 11353 } // namespace Impl 11354 } // namespace Matchers 11355 11356 using namespace Matchers; 11357 using Matchers::Impl::MatcherBase; 11358 11359 } // namespace Catch 11360 // end catch_matchers.cpp 11361 // start catch_matchers_exception.cpp 11362 11363 namespace Catch { 11364 namespace Matchers { 11365 namespace Exception { 11366 11367 bool ExceptionMessageMatcher::match(std::exception const& ex) const { 11368 return ex.what() == m_message; 11369 } 11370 11371 std::string ExceptionMessageMatcher::describe() const { 11372 return "exception message matches \"" + m_message + "\""; 11373 } 11374 11375 } 11376 Exception::ExceptionMessageMatcher Message(std::string const& message) { 11377 return Exception::ExceptionMessageMatcher(message); 11378 } 11379 11380 // namespace Exception 11381 } // namespace Matchers 11382 } // namespace Catch 11383 // end catch_matchers_exception.cpp 11384 // start catch_matchers_floating.cpp 11385 11386 // start catch_polyfills.hpp 11387 11388 namespace Catch { 11389 bool isnan(float f); 11390 bool isnan(double d); 11391 } 11392 11393 // end catch_polyfills.hpp 11394 // start catch_to_string.hpp 11395 11396 #include <string> 11397 11398 namespace Catch { 11399 template <typename T> 11400 std::string to_string(T const& t) { 11401 #if defined(CATCH_CONFIG_CPP11_TO_STRING) 11402 return std::to_string(t); 11403 #else 11404 ReusableStringStream rss; 11405 rss << t; 11406 return rss.str(); 11407 #endif 11408 } 11409 } // end namespace Catch 11410 11411 // end catch_to_string.hpp 11412 #include <algorithm> 11413 #include <cmath> 11414 #include <cstdlib> 11415 #include <cstdint> 11416 #include <cstring> 11417 #include <sstream> 11418 #include <type_traits> 11419 #include <iomanip> 11420 #include <limits> 11421 11422 namespace Catch { 11423 namespace { 11424 11425 int32_t convert(float f) { 11426 static_assert(sizeof(float) == sizeof(int32_t), "Important ULP matcher assumption violated"); 11427 int32_t i; 11428 std::memcpy(&i, &f, sizeof(f)); 11429 return i; 11430 } 11431 11432 int64_t convert(double d) { 11433 static_assert(sizeof(double) == sizeof(int64_t), "Important ULP matcher assumption violated"); 11434 int64_t i; 11435 std::memcpy(&i, &d, sizeof(d)); 11436 return i; 11437 } 11438 11439 template <typename FP> 11440 bool almostEqualUlps(FP lhs, FP rhs, uint64_t maxUlpDiff) { 11441 // Comparison with NaN should always be false. 11442 // This way we can rule it out before getting into the ugly details 11443 if (Catch::isnan(lhs) || Catch::isnan(rhs)) { 11444 return false; 11445 } 11446 11447 auto lc = convert(lhs); 11448 auto rc = convert(rhs); 11449 11450 if ((lc < 0) != (rc < 0)) { 11451 // Potentially we can have +0 and -0 11452 return lhs == rhs; 11453 } 11454 11455 auto ulpDiff = std::abs(lc - rc); 11456 return static_cast<uint64_t>(ulpDiff) <= maxUlpDiff; 11457 } 11458 11459 #if defined(CATCH_CONFIG_GLOBAL_NEXTAFTER) 11460 11461 float nextafter(float x, float y) { 11462 return ::nextafterf(x, y); 11463 } 11464 11465 double nextafter(double x, double y) { 11466 return ::nextafter(x, y); 11467 } 11468 11469 #endif // ^^^ CATCH_CONFIG_GLOBAL_NEXTAFTER ^^^ 11470 11471 template <typename FP> 11472 FP step(FP start, FP direction, uint64_t steps) { 11473 for (uint64_t i = 0; i < steps; ++i) { 11474 #if defined(CATCH_CONFIG_GLOBAL_NEXTAFTER) 11475 start = Catch::nextafter(start, direction); 11476 #else 11477 start = std::nextafter(start, direction); 11478 #endif 11479 } 11480 return start; 11481 } 11482 11483 // Performs equivalent check of std::fabs(lhs - rhs) <= margin 11484 // But without the subtraction to allow for INFINITY in comparison 11485 bool marginComparison(double lhs, double rhs, double margin) { 11486 return (lhs + margin >= rhs) && (rhs + margin >= lhs); 11487 } 11488 11489 template <typename FloatingPoint> 11490 void write(std::ostream& out, FloatingPoint num) { 11491 out << std::scientific 11492 << std::setprecision(std::numeric_limits<FloatingPoint>::max_digits10 - 1) 11493 << num; 11494 } 11495 11496 } // end anonymous namespace 11497 11498 namespace Matchers { 11499 namespace Floating { 11500 11501 enum class FloatingPointKind : uint8_t { 11502 Float, 11503 Double 11504 }; 11505 11506 WithinAbsMatcher::WithinAbsMatcher(double target, double margin) 11507 :m_target{ target }, m_margin{ margin } { 11508 CATCH_ENFORCE(margin >= 0, "Invalid margin: " << margin << '.' 11509 << " Margin has to be non-negative."); 11510 } 11511 11512 // Performs equivalent check of std::fabs(lhs - rhs) <= margin 11513 // But without the subtraction to allow for INFINITY in comparison 11514 bool WithinAbsMatcher::match(double const& matchee) const { 11515 return (matchee + m_margin >= m_target) && (m_target + m_margin >= matchee); 11516 } 11517 11518 std::string WithinAbsMatcher::describe() const { 11519 return "is within " + ::Catch::Detail::stringify(m_margin) + " of " + ::Catch::Detail::stringify(m_target); 11520 } 11521 11522 WithinUlpsMatcher::WithinUlpsMatcher(double target, uint64_t ulps, FloatingPointKind baseType) 11523 :m_target{ target }, m_ulps{ ulps }, m_type{ baseType } { 11524 CATCH_ENFORCE(m_type == FloatingPointKind::Double 11525 || m_ulps < (std::numeric_limits<uint32_t>::max)(), 11526 "Provided ULP is impossibly large for a float comparison."); 11527 } 11528 11529 #if defined(__clang__) 11530 #pragma clang diagnostic push 11531 // Clang <3.5 reports on the default branch in the switch below 11532 #pragma clang diagnostic ignored "-Wunreachable-code" 11533 #endif 11534 11535 bool WithinUlpsMatcher::match(double const& matchee) const { 11536 switch (m_type) { 11537 case FloatingPointKind::Float: 11538 return almostEqualUlps<float>(static_cast<float>(matchee), static_cast<float>(m_target), m_ulps); 11539 case FloatingPointKind::Double: 11540 return almostEqualUlps<double>(matchee, m_target, m_ulps); 11541 default: 11542 CATCH_INTERNAL_ERROR( "Unknown FloatingPointKind value" ); 11543 } 11544 } 11545 11546 #if defined(__clang__) 11547 #pragma clang diagnostic pop 11548 #endif 11549 11550 std::string WithinUlpsMatcher::describe() const { 11551 std::stringstream ret; 11552 11553 ret << "is within " << m_ulps << " ULPs of "; 11554 11555 if (m_type == FloatingPointKind::Float) { 11556 write(ret, static_cast<float>(m_target)); 11557 ret << 'f'; 11558 } else { 11559 write(ret, m_target); 11560 } 11561 11562 ret << " (["; 11563 if (m_type == FloatingPointKind::Double) { 11564 write(ret, step(m_target, static_cast<double>(-INFINITY), m_ulps)); 11565 ret << ", "; 11566 write(ret, step(m_target, static_cast<double>( INFINITY), m_ulps)); 11567 } else { 11568 // We have to cast INFINITY to float because of MinGW, see #1782 11569 write(ret, step(static_cast<float>(m_target), static_cast<float>(-INFINITY), m_ulps)); 11570 ret << ", "; 11571 write(ret, step(static_cast<float>(m_target), static_cast<float>( INFINITY), m_ulps)); 11572 } 11573 ret << "])"; 11574 11575 return ret.str(); 11576 } 11577 11578 WithinRelMatcher::WithinRelMatcher(double target, double epsilon): 11579 m_target(target), 11580 m_epsilon(epsilon){ 11581 CATCH_ENFORCE(m_epsilon >= 0., "Relative comparison with epsilon < 0 does not make sense."); 11582 CATCH_ENFORCE(m_epsilon < 1., "Relative comparison with epsilon >= 1 does not make sense."); 11583 } 11584 11585 bool WithinRelMatcher::match(double const& matchee) const { 11586 const auto relMargin = m_epsilon * (std::max)(std::fabs(matchee), std::fabs(m_target)); 11587 return marginComparison(matchee, m_target, 11588 std::isinf(relMargin)? 0 : relMargin); 11589 } 11590 11591 std::string WithinRelMatcher::describe() const { 11592 Catch::ReusableStringStream sstr; 11593 sstr << "and " << m_target << " are within " << m_epsilon * 100. << "% of each other"; 11594 return sstr.str(); 11595 } 11596 11597 }// namespace Floating 11598 11599 Floating::WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff) { 11600 return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Double); 11601 } 11602 11603 Floating::WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff) { 11604 return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Float); 11605 } 11606 11607 Floating::WithinAbsMatcher WithinAbs(double target, double margin) { 11608 return Floating::WithinAbsMatcher(target, margin); 11609 } 11610 11611 Floating::WithinRelMatcher WithinRel(double target, double eps) { 11612 return Floating::WithinRelMatcher(target, eps); 11613 } 11614 11615 Floating::WithinRelMatcher WithinRel(double target) { 11616 return Floating::WithinRelMatcher(target, std::numeric_limits<double>::epsilon() * 100); 11617 } 11618 11619 Floating::WithinRelMatcher WithinRel(float target, float eps) { 11620 return Floating::WithinRelMatcher(target, eps); 11621 } 11622 11623 Floating::WithinRelMatcher WithinRel(float target) { 11624 return Floating::WithinRelMatcher(target, std::numeric_limits<float>::epsilon() * 100); 11625 } 11626 11627 } // namespace Matchers 11628 } // namespace Catch 11629 11630 // end catch_matchers_floating.cpp 11631 // start catch_matchers_generic.cpp 11632 11633 std::string Catch::Matchers::Generic::Detail::finalizeDescription(const std::string& desc) { 11634 if (desc.empty()) { 11635 return "matches undescribed predicate"; 11636 } else { 11637 return "matches predicate: \"" + desc + '"'; 11638 } 11639 } 11640 // end catch_matchers_generic.cpp 11641 // start catch_matchers_string.cpp 11642 11643 #include <regex> 11644 11645 namespace Catch { 11646 namespace Matchers { 11647 11648 namespace StdString { 11649 11650 CasedString::CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ) 11651 : m_caseSensitivity( caseSensitivity ), 11652 m_str( adjustString( str ) ) 11653 {} 11654 std::string CasedString::adjustString( std::string const& str ) const { 11655 return m_caseSensitivity == CaseSensitive::No 11656 ? toLower( str ) 11657 : str; 11658 } 11659 std::string CasedString::caseSensitivitySuffix() const { 11660 return m_caseSensitivity == CaseSensitive::No 11661 ? " (case insensitive)" 11662 : std::string(); 11663 } 11664 11665 StringMatcherBase::StringMatcherBase( std::string const& operation, CasedString const& comparator ) 11666 : m_comparator( comparator ), 11667 m_operation( operation ) { 11668 } 11669 11670 std::string StringMatcherBase::describe() const { 11671 std::string description; 11672 description.reserve(5 + m_operation.size() + m_comparator.m_str.size() + 11673 m_comparator.caseSensitivitySuffix().size()); 11674 description += m_operation; 11675 description += ": \""; 11676 description += m_comparator.m_str; 11677 description += "\""; 11678 description += m_comparator.caseSensitivitySuffix(); 11679 return description; 11680 } 11681 11682 EqualsMatcher::EqualsMatcher( CasedString const& comparator ) : StringMatcherBase( "equals", comparator ) {} 11683 11684 bool EqualsMatcher::match( std::string const& source ) const { 11685 return m_comparator.adjustString( source ) == m_comparator.m_str; 11686 } 11687 11688 ContainsMatcher::ContainsMatcher( CasedString const& comparator ) : StringMatcherBase( "contains", comparator ) {} 11689 11690 bool ContainsMatcher::match( std::string const& source ) const { 11691 return contains( m_comparator.adjustString( source ), m_comparator.m_str ); 11692 } 11693 11694 StartsWithMatcher::StartsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "starts with", comparator ) {} 11695 11696 bool StartsWithMatcher::match( std::string const& source ) const { 11697 return startsWith( m_comparator.adjustString( source ), m_comparator.m_str ); 11698 } 11699 11700 EndsWithMatcher::EndsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "ends with", comparator ) {} 11701 11702 bool EndsWithMatcher::match( std::string const& source ) const { 11703 return endsWith( m_comparator.adjustString( source ), m_comparator.m_str ); 11704 } 11705 11706 RegexMatcher::RegexMatcher(std::string regex, CaseSensitive::Choice caseSensitivity): m_regex(std::move(regex)), m_caseSensitivity(caseSensitivity) {} 11707 11708 bool RegexMatcher::match(std::string const& matchee) const { 11709 auto flags = std::regex::ECMAScript; // ECMAScript is the default syntax option anyway 11710 if (m_caseSensitivity == CaseSensitive::Choice::No) { 11711 flags |= std::regex::icase; 11712 } 11713 auto reg = std::regex(m_regex, flags); 11714 return std::regex_match(matchee, reg); 11715 } 11716 11717 std::string RegexMatcher::describe() const { 11718 return "matches " + ::Catch::Detail::stringify(m_regex) + ((m_caseSensitivity == CaseSensitive::Choice::Yes)? " case sensitively" : " case insensitively"); 11719 } 11720 11721 } // namespace StdString 11722 11723 StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity ) { 11724 return StdString::EqualsMatcher( StdString::CasedString( str, caseSensitivity) ); 11725 } 11726 StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity ) { 11727 return StdString::ContainsMatcher( StdString::CasedString( str, caseSensitivity) ); 11728 } 11729 StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) { 11730 return StdString::EndsWithMatcher( StdString::CasedString( str, caseSensitivity) ); 11731 } 11732 StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) { 11733 return StdString::StartsWithMatcher( StdString::CasedString( str, caseSensitivity) ); 11734 } 11735 11736 StdString::RegexMatcher Matches(std::string const& regex, CaseSensitive::Choice caseSensitivity) { 11737 return StdString::RegexMatcher(regex, caseSensitivity); 11738 } 11739 11740 } // namespace Matchers 11741 } // namespace Catch 11742 // end catch_matchers_string.cpp 11743 // start catch_message.cpp 11744 11745 // start catch_uncaught_exceptions.h 11746 11747 namespace Catch { 11748 bool uncaught_exceptions(); 11749 } // end namespace Catch 11750 11751 // end catch_uncaught_exceptions.h 11752 #include <cassert> 11753 #include <stack> 11754 11755 namespace Catch { 11756 11757 MessageInfo::MessageInfo( StringRef const& _macroName, 11758 SourceLineInfo const& _lineInfo, 11759 ResultWas::OfType _type ) 11760 : macroName( _macroName ), 11761 lineInfo( _lineInfo ), 11762 type( _type ), 11763 sequence( ++globalCount ) 11764 {} 11765 11766 bool MessageInfo::operator==( MessageInfo const& other ) const { 11767 return sequence == other.sequence; 11768 } 11769 11770 bool MessageInfo::operator<( MessageInfo const& other ) const { 11771 return sequence < other.sequence; 11772 } 11773 11774 // This may need protecting if threading support is added 11775 unsigned int MessageInfo::globalCount = 0; 11776 11777 //////////////////////////////////////////////////////////////////////////// 11778 11779 Catch::MessageBuilder::MessageBuilder( StringRef const& macroName, 11780 SourceLineInfo const& lineInfo, 11781 ResultWas::OfType type ) 11782 :m_info(macroName, lineInfo, type) {} 11783 11784 //////////////////////////////////////////////////////////////////////////// 11785 11786 ScopedMessage::ScopedMessage( MessageBuilder const& builder ) 11787 : m_info( builder.m_info ), m_moved() 11788 { 11789 m_info.message = builder.m_stream.str(); 11790 getResultCapture().pushScopedMessage( m_info ); 11791 } 11792 11793 ScopedMessage::ScopedMessage( ScopedMessage&& old ) 11794 : m_info( old.m_info ), m_moved() 11795 { 11796 old.m_moved = true; 11797 } 11798 11799 ScopedMessage::~ScopedMessage() { 11800 if ( !uncaught_exceptions() && !m_moved ){ 11801 getResultCapture().popScopedMessage(m_info); 11802 } 11803 } 11804 11805 Capturer::Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names ) { 11806 auto trimmed = [&] (size_t start, size_t end) { 11807 while (names[start] == ',' || isspace(static_cast<unsigned char>(names[start]))) { 11808 ++start; 11809 } 11810 while (names[end] == ',' || isspace(static_cast<unsigned char>(names[end]))) { 11811 --end; 11812 } 11813 return names.substr(start, end - start + 1); 11814 }; 11815 auto skipq = [&] (size_t start, char quote) { 11816 for (auto i = start + 1; i < names.size() ; ++i) { 11817 if (names[i] == quote) 11818 return i; 11819 if (names[i] == '\\') 11820 ++i; 11821 } 11822 CATCH_INTERNAL_ERROR("CAPTURE parsing encountered unmatched quote"); 11823 }; 11824 11825 size_t start = 0; 11826 std::stack<char> openings; 11827 for (size_t pos = 0; pos < names.size(); ++pos) { 11828 char c = names[pos]; 11829 switch (c) { 11830 case '[': 11831 case '{': 11832 case '(': 11833 // It is basically impossible to disambiguate between 11834 // comparison and start of template args in this context 11835 // case '<': 11836 openings.push(c); 11837 break; 11838 case ']': 11839 case '}': 11840 case ')': 11841 // case '>': 11842 openings.pop(); 11843 break; 11844 case '"': 11845 case '\'': 11846 pos = skipq(pos, c); 11847 break; 11848 case ',': 11849 if (start != pos && openings.empty()) { 11850 m_messages.emplace_back(macroName, lineInfo, resultType); 11851 m_messages.back().message = static_cast<std::string>(trimmed(start, pos)); 11852 m_messages.back().message += " := "; 11853 start = pos; 11854 } 11855 } 11856 } 11857 assert(openings.empty() && "Mismatched openings"); 11858 m_messages.emplace_back(macroName, lineInfo, resultType); 11859 m_messages.back().message = static_cast<std::string>(trimmed(start, names.size() - 1)); 11860 m_messages.back().message += " := "; 11861 } 11862 Capturer::~Capturer() { 11863 if ( !uncaught_exceptions() ){ 11864 assert( m_captured == m_messages.size() ); 11865 for( size_t i = 0; i < m_captured; ++i ) 11866 m_resultCapture.popScopedMessage( m_messages[i] ); 11867 } 11868 } 11869 11870 void Capturer::captureValue( size_t index, std::string const& value ) { 11871 assert( index < m_messages.size() ); 11872 m_messages[index].message += value; 11873 m_resultCapture.pushScopedMessage( m_messages[index] ); 11874 m_captured++; 11875 } 11876 11877 } // end namespace Catch 11878 // end catch_message.cpp 11879 // start catch_output_redirect.cpp 11880 11881 // start catch_output_redirect.h 11882 #ifndef TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H 11883 #define TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H 11884 11885 #include <cstdio> 11886 #include <iosfwd> 11887 #include <string> 11888 11889 namespace Catch { 11890 11891 class RedirectedStream { 11892 std::ostream& m_originalStream; 11893 std::ostream& m_redirectionStream; 11894 std::streambuf* m_prevBuf; 11895 11896 public: 11897 RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream ); 11898 ~RedirectedStream(); 11899 }; 11900 11901 class RedirectedStdOut { 11902 ReusableStringStream m_rss; 11903 RedirectedStream m_cout; 11904 public: 11905 RedirectedStdOut(); 11906 auto str() const -> std::string; 11907 }; 11908 11909 // StdErr has two constituent streams in C++, std::cerr and std::clog 11910 // This means that we need to redirect 2 streams into 1 to keep proper 11911 // order of writes 11912 class RedirectedStdErr { 11913 ReusableStringStream m_rss; 11914 RedirectedStream m_cerr; 11915 RedirectedStream m_clog; 11916 public: 11917 RedirectedStdErr(); 11918 auto str() const -> std::string; 11919 }; 11920 11921 class RedirectedStreams { 11922 public: 11923 RedirectedStreams(RedirectedStreams const&) = delete; 11924 RedirectedStreams& operator=(RedirectedStreams const&) = delete; 11925 RedirectedStreams(RedirectedStreams&&) = delete; 11926 RedirectedStreams& operator=(RedirectedStreams&&) = delete; 11927 11928 RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr); 11929 ~RedirectedStreams(); 11930 private: 11931 std::string& m_redirectedCout; 11932 std::string& m_redirectedCerr; 11933 RedirectedStdOut m_redirectedStdOut; 11934 RedirectedStdErr m_redirectedStdErr; 11935 }; 11936 11937 #if defined(CATCH_CONFIG_NEW_CAPTURE) 11938 11939 // Windows's implementation of std::tmpfile is terrible (it tries 11940 // to create a file inside system folder, thus requiring elevated 11941 // privileges for the binary), so we have to use tmpnam(_s) and 11942 // create the file ourselves there. 11943 class TempFile { 11944 public: 11945 TempFile(TempFile const&) = delete; 11946 TempFile& operator=(TempFile const&) = delete; 11947 TempFile(TempFile&&) = delete; 11948 TempFile& operator=(TempFile&&) = delete; 11949 11950 TempFile(); 11951 ~TempFile(); 11952 11953 std::FILE* getFile(); 11954 std::string getContents(); 11955 11956 private: 11957 std::FILE* m_file = nullptr; 11958 #if defined(_MSC_VER) 11959 char m_buffer[L_tmpnam] = { 0 }; 11960 #endif 11961 }; 11962 11963 class OutputRedirect { 11964 public: 11965 OutputRedirect(OutputRedirect const&) = delete; 11966 OutputRedirect& operator=(OutputRedirect const&) = delete; 11967 OutputRedirect(OutputRedirect&&) = delete; 11968 OutputRedirect& operator=(OutputRedirect&&) = delete; 11969 11970 OutputRedirect(std::string& stdout_dest, std::string& stderr_dest); 11971 ~OutputRedirect(); 11972 11973 private: 11974 int m_originalStdout = -1; 11975 int m_originalStderr = -1; 11976 TempFile m_stdoutFile; 11977 TempFile m_stderrFile; 11978 std::string& m_stdoutDest; 11979 std::string& m_stderrDest; 11980 }; 11981 11982 #endif 11983 11984 } // end namespace Catch 11985 11986 #endif // TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H 11987 // end catch_output_redirect.h 11988 #include <cstdio> 11989 #include <cstring> 11990 #include <fstream> 11991 #include <sstream> 11992 #include <stdexcept> 11993 11994 #if defined(CATCH_CONFIG_NEW_CAPTURE) 11995 #if defined(_MSC_VER) 11996 #include <io.h> //_dup and _dup2 11997 #define dup _dup 11998 #define dup2 _dup2 11999 #define fileno _fileno 12000 #else 12001 #include <unistd.h> // dup and dup2 12002 #endif 12003 #endif 12004 12005 namespace Catch { 12006 12007 RedirectedStream::RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream ) 12008 : m_originalStream( originalStream ), 12009 m_redirectionStream( redirectionStream ), 12010 m_prevBuf( m_originalStream.rdbuf() ) 12011 { 12012 m_originalStream.rdbuf( m_redirectionStream.rdbuf() ); 12013 } 12014 12015 RedirectedStream::~RedirectedStream() { 12016 m_originalStream.rdbuf( m_prevBuf ); 12017 } 12018 12019 RedirectedStdOut::RedirectedStdOut() : m_cout( Catch::cout(), m_rss.get() ) {} 12020 auto RedirectedStdOut::str() const -> std::string { return m_rss.str(); } 12021 12022 RedirectedStdErr::RedirectedStdErr() 12023 : m_cerr( Catch::cerr(), m_rss.get() ), 12024 m_clog( Catch::clog(), m_rss.get() ) 12025 {} 12026 auto RedirectedStdErr::str() const -> std::string { return m_rss.str(); } 12027 12028 RedirectedStreams::RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr) 12029 : m_redirectedCout(redirectedCout), 12030 m_redirectedCerr(redirectedCerr) 12031 {} 12032 12033 RedirectedStreams::~RedirectedStreams() { 12034 m_redirectedCout += m_redirectedStdOut.str(); 12035 m_redirectedCerr += m_redirectedStdErr.str(); 12036 } 12037 12038 #if defined(CATCH_CONFIG_NEW_CAPTURE) 12039 12040 #if defined(_MSC_VER) 12041 TempFile::TempFile() { 12042 if (tmpnam_s(m_buffer)) { 12043 CATCH_RUNTIME_ERROR("Could not get a temp filename"); 12044 } 12045 if (fopen_s(&m_file, m_buffer, "w")) { 12046 char buffer[100]; 12047 if (strerror_s(buffer, errno)) { 12048 CATCH_RUNTIME_ERROR("Could not translate errno to a string"); 12049 } 12050 CATCH_RUNTIME_ERROR("Could not open the temp file: '" << m_buffer << "' because: " << buffer); 12051 } 12052 } 12053 #else 12054 TempFile::TempFile() { 12055 m_file = std::tmpfile(); 12056 if (!m_file) { 12057 CATCH_RUNTIME_ERROR("Could not create a temp file."); 12058 } 12059 } 12060 12061 #endif 12062 12063 TempFile::~TempFile() { 12064 // TBD: What to do about errors here? 12065 std::fclose(m_file); 12066 // We manually create the file on Windows only, on Linux 12067 // it will be autodeleted 12068 #if defined(_MSC_VER) 12069 std::remove(m_buffer); 12070 #endif 12071 } 12072 12073 FILE* TempFile::getFile() { 12074 return m_file; 12075 } 12076 12077 std::string TempFile::getContents() { 12078 std::stringstream sstr; 12079 char buffer[100] = {}; 12080 std::rewind(m_file); 12081 while (std::fgets(buffer, sizeof(buffer), m_file)) { 12082 sstr << buffer; 12083 } 12084 return sstr.str(); 12085 } 12086 12087 OutputRedirect::OutputRedirect(std::string& stdout_dest, std::string& stderr_dest) : 12088 m_originalStdout(dup(1)), 12089 m_originalStderr(dup(2)), 12090 m_stdoutDest(stdout_dest), 12091 m_stderrDest(stderr_dest) { 12092 dup2(fileno(m_stdoutFile.getFile()), 1); 12093 dup2(fileno(m_stderrFile.getFile()), 2); 12094 } 12095 12096 OutputRedirect::~OutputRedirect() { 12097 Catch::cout() << std::flush; 12098 fflush(stdout); 12099 // Since we support overriding these streams, we flush cerr 12100 // even though std::cerr is unbuffered 12101 Catch::cerr() << std::flush; 12102 Catch::clog() << std::flush; 12103 fflush(stderr); 12104 12105 dup2(m_originalStdout, 1); 12106 dup2(m_originalStderr, 2); 12107 12108 m_stdoutDest += m_stdoutFile.getContents(); 12109 m_stderrDest += m_stderrFile.getContents(); 12110 } 12111 12112 #endif // CATCH_CONFIG_NEW_CAPTURE 12113 12114 } // namespace Catch 12115 12116 #if defined(CATCH_CONFIG_NEW_CAPTURE) 12117 #if defined(_MSC_VER) 12118 #undef dup 12119 #undef dup2 12120 #undef fileno 12121 #endif 12122 #endif 12123 // end catch_output_redirect.cpp 12124 // start catch_polyfills.cpp 12125 12126 #include <cmath> 12127 12128 namespace Catch { 12129 12130 #if !defined(CATCH_CONFIG_POLYFILL_ISNAN) 12131 bool isnan(float f) { 12132 return std::isnan(f); 12133 } 12134 bool isnan(double d) { 12135 return std::isnan(d); 12136 } 12137 #else 12138 // For now we only use this for embarcadero 12139 bool isnan(float f) { 12140 return std::_isnan(f); 12141 } 12142 bool isnan(double d) { 12143 return std::_isnan(d); 12144 } 12145 #endif 12146 12147 } // end namespace Catch 12148 // end catch_polyfills.cpp 12149 // start catch_random_number_generator.cpp 12150 12151 namespace Catch { 12152 12153 namespace { 12154 12155 #if defined(_MSC_VER) 12156 #pragma warning(push) 12157 #pragma warning(disable:4146) // we negate uint32 during the rotate 12158 #endif 12159 // Safe rotr implementation thanks to John Regehr 12160 uint32_t rotate_right(uint32_t val, uint32_t count) { 12161 const uint32_t mask = 31; 12162 count &= mask; 12163 return (val >> count) | (val << (-count & mask)); 12164 } 12165 12166 #if defined(_MSC_VER) 12167 #pragma warning(pop) 12168 #endif 12169 12170 } 12171 12172 SimplePcg32::SimplePcg32(result_type seed_) { 12173 seed(seed_); 12174 } 12175 12176 void SimplePcg32::seed(result_type seed_) { 12177 m_state = 0; 12178 (*this)(); 12179 m_state += seed_; 12180 (*this)(); 12181 } 12182 12183 void SimplePcg32::discard(uint64_t skip) { 12184 // We could implement this to run in O(log n) steps, but this 12185 // should suffice for our use case. 12186 for (uint64_t s = 0; s < skip; ++s) { 12187 static_cast<void>((*this)()); 12188 } 12189 } 12190 12191 SimplePcg32::result_type SimplePcg32::operator()() { 12192 // prepare the output value 12193 const uint32_t xorshifted = static_cast<uint32_t>(((m_state >> 18u) ^ m_state) >> 27u); 12194 const auto output = rotate_right(xorshifted, m_state >> 59u); 12195 12196 // advance state 12197 m_state = m_state * 6364136223846793005ULL + s_inc; 12198 12199 return output; 12200 } 12201 12202 bool operator==(SimplePcg32 const& lhs, SimplePcg32 const& rhs) { 12203 return lhs.m_state == rhs.m_state; 12204 } 12205 12206 bool operator!=(SimplePcg32 const& lhs, SimplePcg32 const& rhs) { 12207 return lhs.m_state != rhs.m_state; 12208 } 12209 } 12210 // end catch_random_number_generator.cpp 12211 // start catch_registry_hub.cpp 12212 12213 // start catch_test_case_registry_impl.h 12214 12215 #include <vector> 12216 #include <set> 12217 #include <algorithm> 12218 #include <ios> 12219 12220 namespace Catch { 12221 12222 class TestCase; 12223 struct IConfig; 12224 12225 std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ); 12226 12227 bool isThrowSafe( TestCase const& testCase, IConfig const& config ); 12228 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); 12229 12230 void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ); 12231 12232 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ); 12233 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ); 12234 12235 class TestRegistry : public ITestCaseRegistry { 12236 public: 12237 virtual ~TestRegistry() = default; 12238 12239 virtual void registerTest( TestCase const& testCase ); 12240 12241 std::vector<TestCase> const& getAllTests() const override; 12242 std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const override; 12243 12244 private: 12245 std::vector<TestCase> m_functions; 12246 mutable RunTests::InWhatOrder m_currentSortOrder = RunTests::InDeclarationOrder; 12247 mutable std::vector<TestCase> m_sortedFunctions; 12248 std::size_t m_unnamedCount = 0; 12249 std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised 12250 }; 12251 12252 /////////////////////////////////////////////////////////////////////////// 12253 12254 class TestInvokerAsFunction : public ITestInvoker { 12255 void(*m_testAsFunction)(); 12256 public: 12257 TestInvokerAsFunction( void(*testAsFunction)() ) noexcept; 12258 12259 void invoke() const override; 12260 }; 12261 12262 std::string extractClassName( StringRef const& classOrQualifiedMethodName ); 12263 12264 /////////////////////////////////////////////////////////////////////////// 12265 12266 } // end namespace Catch 12267 12268 // end catch_test_case_registry_impl.h 12269 // start catch_reporter_registry.h 12270 12271 #include <map> 12272 12273 namespace Catch { 12274 12275 class ReporterRegistry : public IReporterRegistry { 12276 12277 public: 12278 12279 ~ReporterRegistry() override; 12280 12281 IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const override; 12282 12283 void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ); 12284 void registerListener( IReporterFactoryPtr const& factory ); 12285 12286 FactoryMap const& getFactories() const override; 12287 Listeners const& getListeners() const override; 12288 12289 private: 12290 FactoryMap m_factories; 12291 Listeners m_listeners; 12292 }; 12293 } 12294 12295 // end catch_reporter_registry.h 12296 // start catch_tag_alias_registry.h 12297 12298 // start catch_tag_alias.h 12299 12300 #include <string> 12301 12302 namespace Catch { 12303 12304 struct TagAlias { 12305 TagAlias(std::string const& _tag, SourceLineInfo _lineInfo); 12306 12307 std::string tag; 12308 SourceLineInfo lineInfo; 12309 }; 12310 12311 } // end namespace Catch 12312 12313 // end catch_tag_alias.h 12314 #include <map> 12315 12316 namespace Catch { 12317 12318 class TagAliasRegistry : public ITagAliasRegistry { 12319 public: 12320 ~TagAliasRegistry() override; 12321 TagAlias const* find( std::string const& alias ) const override; 12322 std::string expandAliases( std::string const& unexpandedTestSpec ) const override; 12323 void add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ); 12324 12325 private: 12326 std::map<std::string, TagAlias> m_registry; 12327 }; 12328 12329 } // end namespace Catch 12330 12331 // end catch_tag_alias_registry.h 12332 // start catch_startup_exception_registry.h 12333 12334 #include <vector> 12335 #include <exception> 12336 12337 namespace Catch { 12338 12339 class StartupExceptionRegistry { 12340 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 12341 public: 12342 void add(std::exception_ptr const& exception) noexcept; 12343 std::vector<std::exception_ptr> const& getExceptions() const noexcept; 12344 private: 12345 std::vector<std::exception_ptr> m_exceptions; 12346 #endif 12347 }; 12348 12349 } // end namespace Catch 12350 12351 // end catch_startup_exception_registry.h 12352 // start catch_singletons.hpp 12353 12354 namespace Catch { 12355 12356 struct ISingleton { 12357 virtual ~ISingleton(); 12358 }; 12359 12360 void addSingleton( ISingleton* singleton ); 12361 void cleanupSingletons(); 12362 12363 template<typename SingletonImplT, typename InterfaceT = SingletonImplT, typename MutableInterfaceT = InterfaceT> 12364 class Singleton : SingletonImplT, public ISingleton { 12365 12366 static auto getInternal() -> Singleton* { 12367 static Singleton* s_instance = nullptr; 12368 if( !s_instance ) { 12369 s_instance = new Singleton; 12370 addSingleton( s_instance ); 12371 } 12372 return s_instance; 12373 } 12374 12375 public: 12376 static auto get() -> InterfaceT const& { 12377 return *getInternal(); 12378 } 12379 static auto getMutable() -> MutableInterfaceT& { 12380 return *getInternal(); 12381 } 12382 }; 12383 12384 } // namespace Catch 12385 12386 // end catch_singletons.hpp 12387 namespace Catch { 12388 12389 namespace { 12390 12391 class RegistryHub : public IRegistryHub, public IMutableRegistryHub, 12392 private NonCopyable { 12393 12394 public: // IRegistryHub 12395 RegistryHub() = default; 12396 IReporterRegistry const& getReporterRegistry() const override { 12397 return m_reporterRegistry; 12398 } 12399 ITestCaseRegistry const& getTestCaseRegistry() const override { 12400 return m_testCaseRegistry; 12401 } 12402 IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const override { 12403 return m_exceptionTranslatorRegistry; 12404 } 12405 ITagAliasRegistry const& getTagAliasRegistry() const override { 12406 return m_tagAliasRegistry; 12407 } 12408 StartupExceptionRegistry const& getStartupExceptionRegistry() const override { 12409 return m_exceptionRegistry; 12410 } 12411 12412 public: // IMutableRegistryHub 12413 void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) override { 12414 m_reporterRegistry.registerReporter( name, factory ); 12415 } 12416 void registerListener( IReporterFactoryPtr const& factory ) override { 12417 m_reporterRegistry.registerListener( factory ); 12418 } 12419 void registerTest( TestCase const& testInfo ) override { 12420 m_testCaseRegistry.registerTest( testInfo ); 12421 } 12422 void registerTranslator( const IExceptionTranslator* translator ) override { 12423 m_exceptionTranslatorRegistry.registerTranslator( translator ); 12424 } 12425 void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) override { 12426 m_tagAliasRegistry.add( alias, tag, lineInfo ); 12427 } 12428 void registerStartupException() noexcept override { 12429 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 12430 m_exceptionRegistry.add(std::current_exception()); 12431 #else 12432 CATCH_INTERNAL_ERROR("Attempted to register active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!"); 12433 #endif 12434 } 12435 IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() override { 12436 return m_enumValuesRegistry; 12437 } 12438 12439 private: 12440 TestRegistry m_testCaseRegistry; 12441 ReporterRegistry m_reporterRegistry; 12442 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; 12443 TagAliasRegistry m_tagAliasRegistry; 12444 StartupExceptionRegistry m_exceptionRegistry; 12445 Detail::EnumValuesRegistry m_enumValuesRegistry; 12446 }; 12447 } 12448 12449 using RegistryHubSingleton = Singleton<RegistryHub, IRegistryHub, IMutableRegistryHub>; 12450 12451 IRegistryHub const& getRegistryHub() { 12452 return RegistryHubSingleton::get(); 12453 } 12454 IMutableRegistryHub& getMutableRegistryHub() { 12455 return RegistryHubSingleton::getMutable(); 12456 } 12457 void cleanUp() { 12458 cleanupSingletons(); 12459 cleanUpContext(); 12460 } 12461 std::string translateActiveException() { 12462 return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); 12463 } 12464 12465 } // end namespace Catch 12466 // end catch_registry_hub.cpp 12467 // start catch_reporter_registry.cpp 12468 12469 namespace Catch { 12470 12471 ReporterRegistry::~ReporterRegistry() = default; 12472 12473 IStreamingReporterPtr ReporterRegistry::create( std::string const& name, IConfigPtr const& config ) const { 12474 auto it = m_factories.find( name ); 12475 if( it == m_factories.end() ) 12476 return nullptr; 12477 return it->second->create( ReporterConfig( config ) ); 12478 } 12479 12480 void ReporterRegistry::registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) { 12481 m_factories.emplace(name, factory); 12482 } 12483 void ReporterRegistry::registerListener( IReporterFactoryPtr const& factory ) { 12484 m_listeners.push_back( factory ); 12485 } 12486 12487 IReporterRegistry::FactoryMap const& ReporterRegistry::getFactories() const { 12488 return m_factories; 12489 } 12490 IReporterRegistry::Listeners const& ReporterRegistry::getListeners() const { 12491 return m_listeners; 12492 } 12493 12494 } 12495 // end catch_reporter_registry.cpp 12496 // start catch_result_type.cpp 12497 12498 namespace Catch { 12499 12500 bool isOk( ResultWas::OfType resultType ) { 12501 return ( resultType & ResultWas::FailureBit ) == 0; 12502 } 12503 bool isJustInfo( int flags ) { 12504 return flags == ResultWas::Info; 12505 } 12506 12507 ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { 12508 return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( rhs ) ); 12509 } 12510 12511 bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; } 12512 bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; } 12513 12514 } // end namespace Catch 12515 // end catch_result_type.cpp 12516 // start catch_run_context.cpp 12517 12518 #include <cassert> 12519 #include <algorithm> 12520 #include <sstream> 12521 12522 namespace Catch { 12523 12524 namespace Generators { 12525 struct GeneratorTracker : TestCaseTracking::TrackerBase, IGeneratorTracker { 12526 GeneratorBasePtr m_generator; 12527 12528 GeneratorTracker( TestCaseTracking::NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) 12529 : TrackerBase( nameAndLocation, ctx, parent ) 12530 {} 12531 ~GeneratorTracker(); 12532 12533 static GeneratorTracker& acquire( TrackerContext& ctx, TestCaseTracking::NameAndLocation const& nameAndLocation ) { 12534 std::shared_ptr<GeneratorTracker> tracker; 12535 12536 ITracker& currentTracker = ctx.currentTracker(); 12537 // Under specific circumstances, the generator we want 12538 // to acquire is also the current tracker. If this is 12539 // the case, we have to avoid looking through current 12540 // tracker's children, and instead return the current 12541 // tracker. 12542 // A case where this check is important is e.g. 12543 // for (int i = 0; i < 5; ++i) { 12544 // int n = GENERATE(1, 2); 12545 // } 12546 // 12547 // without it, the code above creates 5 nested generators. 12548 if (currentTracker.nameAndLocation() == nameAndLocation) { 12549 auto thisTracker = currentTracker.parent().findChild(nameAndLocation); 12550 assert(thisTracker); 12551 assert(thisTracker->isGeneratorTracker()); 12552 tracker = std::static_pointer_cast<GeneratorTracker>(thisTracker); 12553 } else if ( TestCaseTracking::ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) { 12554 assert( childTracker ); 12555 assert( childTracker->isGeneratorTracker() ); 12556 tracker = std::static_pointer_cast<GeneratorTracker>( childTracker ); 12557 } else { 12558 tracker = std::make_shared<GeneratorTracker>( nameAndLocation, ctx, ¤tTracker ); 12559 currentTracker.addChild( tracker ); 12560 } 12561 12562 if( !tracker->isComplete() ) { 12563 tracker->open(); 12564 } 12565 12566 return *tracker; 12567 } 12568 12569 // TrackerBase interface 12570 bool isGeneratorTracker() const override { return true; } 12571 auto hasGenerator() const -> bool override { 12572 return !!m_generator; 12573 } 12574 void close() override { 12575 TrackerBase::close(); 12576 // If a generator has a child (it is followed by a section) 12577 // and none of its children have started, then we must wait 12578 // until later to start consuming its values. 12579 // This catches cases where `GENERATE` is placed between two 12580 // `SECTION`s. 12581 // **The check for m_children.empty cannot be removed**. 12582 // doing so would break `GENERATE` _not_ followed by `SECTION`s. 12583 const bool should_wait_for_child = 12584 !m_children.empty() && 12585 std::find_if( m_children.begin(), 12586 m_children.end(), 12587 []( TestCaseTracking::ITrackerPtr tracker ) { 12588 return tracker->hasStarted(); 12589 } ) == m_children.end(); 12590 12591 // This check is a bit tricky, because m_generator->next() 12592 // has a side-effect, where it consumes generator's current 12593 // value, but we do not want to invoke the side-effect if 12594 // this generator is still waiting for any child to start. 12595 if ( should_wait_for_child || 12596 ( m_runState == CompletedSuccessfully && 12597 m_generator->next() ) ) { 12598 m_children.clear(); 12599 m_runState = Executing; 12600 } 12601 } 12602 12603 // IGeneratorTracker interface 12604 auto getGenerator() const -> GeneratorBasePtr const& override { 12605 return m_generator; 12606 } 12607 void setGenerator( GeneratorBasePtr&& generator ) override { 12608 m_generator = std::move( generator ); 12609 } 12610 }; 12611 GeneratorTracker::~GeneratorTracker() {} 12612 } 12613 12614 RunContext::RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter) 12615 : m_runInfo(_config->name()), 12616 m_context(getCurrentMutableContext()), 12617 m_config(_config), 12618 m_reporter(std::move(reporter)), 12619 m_lastAssertionInfo{ StringRef(), SourceLineInfo("",0), StringRef(), ResultDisposition::Normal }, 12620 m_includeSuccessfulResults( m_config->includeSuccessfulResults() || m_reporter->getPreferences().shouldReportAllAssertions ) 12621 { 12622 m_context.setRunner(this); 12623 m_context.setConfig(m_config); 12624 m_context.setResultCapture(this); 12625 m_reporter->testRunStarting(m_runInfo); 12626 } 12627 12628 RunContext::~RunContext() { 12629 m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, aborting())); 12630 } 12631 12632 void RunContext::testGroupStarting(std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount) { 12633 m_reporter->testGroupStarting(GroupInfo(testSpec, groupIndex, groupsCount)); 12634 } 12635 12636 void RunContext::testGroupEnded(std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount) { 12637 m_reporter->testGroupEnded(TestGroupStats(GroupInfo(testSpec, groupIndex, groupsCount), totals, aborting())); 12638 } 12639 12640 Totals RunContext::runTest(TestCase const& testCase) { 12641 Totals prevTotals = m_totals; 12642 12643 std::string redirectedCout; 12644 std::string redirectedCerr; 12645 12646 auto const& testInfo = testCase.getTestCaseInfo(); 12647 12648 m_reporter->testCaseStarting(testInfo); 12649 12650 m_activeTestCase = &testCase; 12651 12652 ITracker& rootTracker = m_trackerContext.startRun(); 12653 assert(rootTracker.isSectionTracker()); 12654 static_cast<SectionTracker&>(rootTracker).addInitialFilters(m_config->getSectionsToRun()); 12655 do { 12656 m_trackerContext.startCycle(); 12657 m_testCaseTracker = &SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(testInfo.name, testInfo.lineInfo)); 12658 runCurrentTest(redirectedCout, redirectedCerr); 12659 } while (!m_testCaseTracker->isSuccessfullyCompleted() && !aborting()); 12660 12661 Totals deltaTotals = m_totals.delta(prevTotals); 12662 if (testInfo.expectedToFail() && deltaTotals.testCases.passed > 0) { 12663 deltaTotals.assertions.failed++; 12664 deltaTotals.testCases.passed--; 12665 deltaTotals.testCases.failed++; 12666 } 12667 m_totals.testCases += deltaTotals.testCases; 12668 m_reporter->testCaseEnded(TestCaseStats(testInfo, 12669 deltaTotals, 12670 redirectedCout, 12671 redirectedCerr, 12672 aborting())); 12673 12674 m_activeTestCase = nullptr; 12675 m_testCaseTracker = nullptr; 12676 12677 return deltaTotals; 12678 } 12679 12680 IConfigPtr RunContext::config() const { 12681 return m_config; 12682 } 12683 12684 IStreamingReporter& RunContext::reporter() const { 12685 return *m_reporter; 12686 } 12687 12688 void RunContext::assertionEnded(AssertionResult const & result) { 12689 if (result.getResultType() == ResultWas::Ok) { 12690 m_totals.assertions.passed++; 12691 m_lastAssertionPassed = true; 12692 } else if (!result.isOk()) { 12693 m_lastAssertionPassed = false; 12694 if( m_activeTestCase->getTestCaseInfo().okToFail() ) 12695 m_totals.assertions.failedButOk++; 12696 else 12697 m_totals.assertions.failed++; 12698 } 12699 else { 12700 m_lastAssertionPassed = true; 12701 } 12702 12703 // We have no use for the return value (whether messages should be cleared), because messages were made scoped 12704 // and should be let to clear themselves out. 12705 static_cast<void>(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals))); 12706 12707 if (result.getResultType() != ResultWas::Warning) 12708 m_messageScopes.clear(); 12709 12710 // Reset working state 12711 resetAssertionInfo(); 12712 m_lastResult = result; 12713 } 12714 void RunContext::resetAssertionInfo() { 12715 m_lastAssertionInfo.macroName = StringRef(); 12716 m_lastAssertionInfo.capturedExpression = "{Unknown expression after the reported line}"_sr; 12717 } 12718 12719 bool RunContext::sectionStarted(SectionInfo const & sectionInfo, Counts & assertions) { 12720 ITracker& sectionTracker = SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(sectionInfo.name, sectionInfo.lineInfo)); 12721 if (!sectionTracker.isOpen()) 12722 return false; 12723 m_activeSections.push_back(§ionTracker); 12724 12725 m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; 12726 12727 m_reporter->sectionStarting(sectionInfo); 12728 12729 assertions = m_totals.assertions; 12730 12731 return true; 12732 } 12733 auto RunContext::acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& { 12734 using namespace Generators; 12735 GeneratorTracker& tracker = GeneratorTracker::acquire(m_trackerContext, 12736 TestCaseTracking::NameAndLocation( static_cast<std::string>(generatorName), lineInfo ) ); 12737 m_lastAssertionInfo.lineInfo = lineInfo; 12738 return tracker; 12739 } 12740 12741 bool RunContext::testForMissingAssertions(Counts& assertions) { 12742 if (assertions.total() != 0) 12743 return false; 12744 if (!m_config->warnAboutMissingAssertions()) 12745 return false; 12746 if (m_trackerContext.currentTracker().hasChildren()) 12747 return false; 12748 m_totals.assertions.failed++; 12749 assertions.failed++; 12750 return true; 12751 } 12752 12753 void RunContext::sectionEnded(SectionEndInfo const & endInfo) { 12754 Counts assertions = m_totals.assertions - endInfo.prevAssertions; 12755 bool missingAssertions = testForMissingAssertions(assertions); 12756 12757 if (!m_activeSections.empty()) { 12758 m_activeSections.back()->close(); 12759 m_activeSections.pop_back(); 12760 } 12761 12762 m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions)); 12763 m_messages.clear(); 12764 m_messageScopes.clear(); 12765 } 12766 12767 void RunContext::sectionEndedEarly(SectionEndInfo const & endInfo) { 12768 if (m_unfinishedSections.empty()) 12769 m_activeSections.back()->fail(); 12770 else 12771 m_activeSections.back()->close(); 12772 m_activeSections.pop_back(); 12773 12774 m_unfinishedSections.push_back(endInfo); 12775 } 12776 12777 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 12778 void RunContext::benchmarkPreparing(std::string const& name) { 12779 m_reporter->benchmarkPreparing(name); 12780 } 12781 void RunContext::benchmarkStarting( BenchmarkInfo const& info ) { 12782 m_reporter->benchmarkStarting( info ); 12783 } 12784 void RunContext::benchmarkEnded( BenchmarkStats<> const& stats ) { 12785 m_reporter->benchmarkEnded( stats ); 12786 } 12787 void RunContext::benchmarkFailed(std::string const & error) { 12788 m_reporter->benchmarkFailed(error); 12789 } 12790 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 12791 12792 void RunContext::pushScopedMessage(MessageInfo const & message) { 12793 m_messages.push_back(message); 12794 } 12795 12796 void RunContext::popScopedMessage(MessageInfo const & message) { 12797 m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end()); 12798 } 12799 12800 void RunContext::emplaceUnscopedMessage( MessageBuilder const& builder ) { 12801 m_messageScopes.emplace_back( builder ); 12802 } 12803 12804 std::string RunContext::getCurrentTestName() const { 12805 return m_activeTestCase 12806 ? m_activeTestCase->getTestCaseInfo().name 12807 : std::string(); 12808 } 12809 12810 const AssertionResult * RunContext::getLastResult() const { 12811 return &(*m_lastResult); 12812 } 12813 12814 void RunContext::exceptionEarlyReported() { 12815 m_shouldReportUnexpected = false; 12816 } 12817 12818 void RunContext::handleFatalErrorCondition( StringRef message ) { 12819 // First notify reporter that bad things happened 12820 m_reporter->fatalErrorEncountered(message); 12821 12822 // Don't rebuild the result -- the stringification itself can cause more fatal errors 12823 // Instead, fake a result data. 12824 AssertionResultData tempResult( ResultWas::FatalErrorCondition, { false } ); 12825 tempResult.message = static_cast<std::string>(message); 12826 AssertionResult result(m_lastAssertionInfo, tempResult); 12827 12828 assertionEnded(result); 12829 12830 handleUnfinishedSections(); 12831 12832 // Recreate section for test case (as we will lose the one that was in scope) 12833 auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); 12834 SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name); 12835 12836 Counts assertions; 12837 assertions.failed = 1; 12838 SectionStats testCaseSectionStats(testCaseSection, assertions, 0, false); 12839 m_reporter->sectionEnded(testCaseSectionStats); 12840 12841 auto const& testInfo = m_activeTestCase->getTestCaseInfo(); 12842 12843 Totals deltaTotals; 12844 deltaTotals.testCases.failed = 1; 12845 deltaTotals.assertions.failed = 1; 12846 m_reporter->testCaseEnded(TestCaseStats(testInfo, 12847 deltaTotals, 12848 std::string(), 12849 std::string(), 12850 false)); 12851 m_totals.testCases.failed++; 12852 testGroupEnded(std::string(), m_totals, 1, 1); 12853 m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, false)); 12854 } 12855 12856 bool RunContext::lastAssertionPassed() { 12857 return m_lastAssertionPassed; 12858 } 12859 12860 void RunContext::assertionPassed() { 12861 m_lastAssertionPassed = true; 12862 ++m_totals.assertions.passed; 12863 resetAssertionInfo(); 12864 m_messageScopes.clear(); 12865 } 12866 12867 bool RunContext::aborting() const { 12868 return m_totals.assertions.failed >= static_cast<std::size_t>(m_config->abortAfter()); 12869 } 12870 12871 void RunContext::runCurrentTest(std::string & redirectedCout, std::string & redirectedCerr) { 12872 auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); 12873 SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name); 12874 m_reporter->sectionStarting(testCaseSection); 12875 Counts prevAssertions = m_totals.assertions; 12876 double duration = 0; 12877 m_shouldReportUnexpected = true; 12878 m_lastAssertionInfo = { "TEST_CASE"_sr, testCaseInfo.lineInfo, StringRef(), ResultDisposition::Normal }; 12879 12880 seedRng(*m_config); 12881 12882 Timer timer; 12883 CATCH_TRY { 12884 if (m_reporter->getPreferences().shouldRedirectStdOut) { 12885 #if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) 12886 RedirectedStreams redirectedStreams(redirectedCout, redirectedCerr); 12887 12888 timer.start(); 12889 invokeActiveTestCase(); 12890 #else 12891 OutputRedirect r(redirectedCout, redirectedCerr); 12892 timer.start(); 12893 invokeActiveTestCase(); 12894 #endif 12895 } else { 12896 timer.start(); 12897 invokeActiveTestCase(); 12898 } 12899 duration = timer.getElapsedSeconds(); 12900 } CATCH_CATCH_ANON (TestFailureException&) { 12901 // This just means the test was aborted due to failure 12902 } CATCH_CATCH_ALL { 12903 // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions 12904 // are reported without translation at the point of origin. 12905 if( m_shouldReportUnexpected ) { 12906 AssertionReaction dummyReaction; 12907 handleUnexpectedInflightException( m_lastAssertionInfo, translateActiveException(), dummyReaction ); 12908 } 12909 } 12910 Counts assertions = m_totals.assertions - prevAssertions; 12911 bool missingAssertions = testForMissingAssertions(assertions); 12912 12913 m_testCaseTracker->close(); 12914 handleUnfinishedSections(); 12915 m_messages.clear(); 12916 m_messageScopes.clear(); 12917 12918 SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions); 12919 m_reporter->sectionEnded(testCaseSectionStats); 12920 } 12921 12922 void RunContext::invokeActiveTestCase() { 12923 FatalConditionHandler fatalConditionHandler; // Handle signals 12924 m_activeTestCase->invoke(); 12925 fatalConditionHandler.reset(); 12926 } 12927 12928 void RunContext::handleUnfinishedSections() { 12929 // If sections ended prematurely due to an exception we stored their 12930 // infos here so we can tear them down outside the unwind process. 12931 for (auto it = m_unfinishedSections.rbegin(), 12932 itEnd = m_unfinishedSections.rend(); 12933 it != itEnd; 12934 ++it) 12935 sectionEnded(*it); 12936 m_unfinishedSections.clear(); 12937 } 12938 12939 void RunContext::handleExpr( 12940 AssertionInfo const& info, 12941 ITransientExpression const& expr, 12942 AssertionReaction& reaction 12943 ) { 12944 m_reporter->assertionStarting( info ); 12945 12946 bool negated = isFalseTest( info.resultDisposition ); 12947 bool result = expr.getResult() != negated; 12948 12949 if( result ) { 12950 if (!m_includeSuccessfulResults) { 12951 assertionPassed(); 12952 } 12953 else { 12954 reportExpr(info, ResultWas::Ok, &expr, negated); 12955 } 12956 } 12957 else { 12958 reportExpr(info, ResultWas::ExpressionFailed, &expr, negated ); 12959 populateReaction( reaction ); 12960 } 12961 } 12962 void RunContext::reportExpr( 12963 AssertionInfo const &info, 12964 ResultWas::OfType resultType, 12965 ITransientExpression const *expr, 12966 bool negated ) { 12967 12968 m_lastAssertionInfo = info; 12969 AssertionResultData data( resultType, LazyExpression( negated ) ); 12970 12971 AssertionResult assertionResult{ info, data }; 12972 assertionResult.m_resultData.lazyExpression.m_transientExpression = expr; 12973 12974 assertionEnded( assertionResult ); 12975 } 12976 12977 void RunContext::handleMessage( 12978 AssertionInfo const& info, 12979 ResultWas::OfType resultType, 12980 StringRef const& message, 12981 AssertionReaction& reaction 12982 ) { 12983 m_reporter->assertionStarting( info ); 12984 12985 m_lastAssertionInfo = info; 12986 12987 AssertionResultData data( resultType, LazyExpression( false ) ); 12988 data.message = static_cast<std::string>(message); 12989 AssertionResult assertionResult{ m_lastAssertionInfo, data }; 12990 assertionEnded( assertionResult ); 12991 if( !assertionResult.isOk() ) 12992 populateReaction( reaction ); 12993 } 12994 void RunContext::handleUnexpectedExceptionNotThrown( 12995 AssertionInfo const& info, 12996 AssertionReaction& reaction 12997 ) { 12998 handleNonExpr(info, Catch::ResultWas::DidntThrowException, reaction); 12999 } 13000 13001 void RunContext::handleUnexpectedInflightException( 13002 AssertionInfo const& info, 13003 std::string const& message, 13004 AssertionReaction& reaction 13005 ) { 13006 m_lastAssertionInfo = info; 13007 13008 AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) ); 13009 data.message = message; 13010 AssertionResult assertionResult{ info, data }; 13011 assertionEnded( assertionResult ); 13012 populateReaction( reaction ); 13013 } 13014 13015 void RunContext::populateReaction( AssertionReaction& reaction ) { 13016 reaction.shouldDebugBreak = m_config->shouldDebugBreak(); 13017 reaction.shouldThrow = aborting() || (m_lastAssertionInfo.resultDisposition & ResultDisposition::Normal); 13018 } 13019 13020 void RunContext::handleIncomplete( 13021 AssertionInfo const& info 13022 ) { 13023 m_lastAssertionInfo = info; 13024 13025 AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) ); 13026 data.message = "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE"; 13027 AssertionResult assertionResult{ info, data }; 13028 assertionEnded( assertionResult ); 13029 } 13030 void RunContext::handleNonExpr( 13031 AssertionInfo const &info, 13032 ResultWas::OfType resultType, 13033 AssertionReaction &reaction 13034 ) { 13035 m_lastAssertionInfo = info; 13036 13037 AssertionResultData data( resultType, LazyExpression( false ) ); 13038 AssertionResult assertionResult{ info, data }; 13039 assertionEnded( assertionResult ); 13040 13041 if( !assertionResult.isOk() ) 13042 populateReaction( reaction ); 13043 } 13044 13045 IResultCapture& getResultCapture() { 13046 if (auto* capture = getCurrentContext().getResultCapture()) 13047 return *capture; 13048 else 13049 CATCH_INTERNAL_ERROR("No result capture instance"); 13050 } 13051 13052 void seedRng(IConfig const& config) { 13053 if (config.rngSeed() != 0) { 13054 std::srand(config.rngSeed()); 13055 rng().seed(config.rngSeed()); 13056 } 13057 } 13058 13059 unsigned int rngSeed() { 13060 return getCurrentContext().getConfig()->rngSeed(); 13061 } 13062 13063 } 13064 // end catch_run_context.cpp 13065 // start catch_section.cpp 13066 13067 namespace Catch { 13068 13069 Section::Section( SectionInfo const& info ) 13070 : m_info( info ), 13071 m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) ) 13072 { 13073 m_timer.start(); 13074 } 13075 13076 Section::~Section() { 13077 if( m_sectionIncluded ) { 13078 SectionEndInfo endInfo{ m_info, m_assertions, m_timer.getElapsedSeconds() }; 13079 if( uncaught_exceptions() ) 13080 getResultCapture().sectionEndedEarly( endInfo ); 13081 else 13082 getResultCapture().sectionEnded( endInfo ); 13083 } 13084 } 13085 13086 // This indicates whether the section should be executed or not 13087 Section::operator bool() const { 13088 return m_sectionIncluded; 13089 } 13090 13091 } // end namespace Catch 13092 // end catch_section.cpp 13093 // start catch_section_info.cpp 13094 13095 namespace Catch { 13096 13097 SectionInfo::SectionInfo 13098 ( SourceLineInfo const& _lineInfo, 13099 std::string const& _name ) 13100 : name( _name ), 13101 lineInfo( _lineInfo ) 13102 {} 13103 13104 } // end namespace Catch 13105 // end catch_section_info.cpp 13106 // start catch_session.cpp 13107 13108 // start catch_session.h 13109 13110 #include <memory> 13111 13112 namespace Catch { 13113 13114 class Session : NonCopyable { 13115 public: 13116 13117 Session(); 13118 ~Session() override; 13119 13120 void showHelp() const; 13121 void libIdentify(); 13122 13123 int applyCommandLine( int argc, char const * const * argv ); 13124 #if defined(CATCH_CONFIG_WCHAR) && defined(_WIN32) && defined(UNICODE) 13125 int applyCommandLine( int argc, wchar_t const * const * argv ); 13126 #endif 13127 13128 void useConfigData( ConfigData const& configData ); 13129 13130 template<typename CharT> 13131 int run(int argc, CharT const * const argv[]) { 13132 if (m_startupExceptions) 13133 return 1; 13134 int returnCode = applyCommandLine(argc, argv); 13135 if (returnCode == 0) 13136 returnCode = run(); 13137 return returnCode; 13138 } 13139 13140 int run(); 13141 13142 clara::Parser const& cli() const; 13143 void cli( clara::Parser const& newParser ); 13144 ConfigData& configData(); 13145 Config& config(); 13146 private: 13147 int runInternal(); 13148 13149 clara::Parser m_cli; 13150 ConfigData m_configData; 13151 std::shared_ptr<Config> m_config; 13152 bool m_startupExceptions = false; 13153 }; 13154 13155 } // end namespace Catch 13156 13157 // end catch_session.h 13158 // start catch_version.h 13159 13160 #include <iosfwd> 13161 13162 namespace Catch { 13163 13164 // Versioning information 13165 struct Version { 13166 Version( Version const& ) = delete; 13167 Version& operator=( Version const& ) = delete; 13168 Version( unsigned int _majorVersion, 13169 unsigned int _minorVersion, 13170 unsigned int _patchNumber, 13171 char const * const _branchName, 13172 unsigned int _buildNumber ); 13173 13174 unsigned int const majorVersion; 13175 unsigned int const minorVersion; 13176 unsigned int const patchNumber; 13177 13178 // buildNumber is only used if branchName is not null 13179 char const * const branchName; 13180 unsigned int const buildNumber; 13181 13182 friend std::ostream& operator << ( std::ostream& os, Version const& version ); 13183 }; 13184 13185 Version const& libraryVersion(); 13186 } 13187 13188 // end catch_version.h 13189 #include <cstdlib> 13190 #include <iomanip> 13191 #include <set> 13192 #include <iterator> 13193 13194 namespace Catch { 13195 13196 namespace { 13197 const int MaxExitCode = 255; 13198 13199 IStreamingReporterPtr createReporter(std::string const& reporterName, IConfigPtr const& config) { 13200 auto reporter = Catch::getRegistryHub().getReporterRegistry().create(reporterName, config); 13201 CATCH_ENFORCE(reporter, "No reporter registered with name: '" << reporterName << "'"); 13202 13203 return reporter; 13204 } 13205 13206 IStreamingReporterPtr makeReporter(std::shared_ptr<Config> const& config) { 13207 if (Catch::getRegistryHub().getReporterRegistry().getListeners().empty()) { 13208 return createReporter(config->getReporterName(), config); 13209 } 13210 13211 // On older platforms, returning std::unique_ptr<ListeningReporter> 13212 // when the return type is std::unique_ptr<IStreamingReporter> 13213 // doesn't compile without a std::move call. However, this causes 13214 // a warning on newer platforms. Thus, we have to work around 13215 // it a bit and downcast the pointer manually. 13216 auto ret = std::unique_ptr<IStreamingReporter>(new ListeningReporter); 13217 auto& multi = static_cast<ListeningReporter&>(*ret); 13218 auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners(); 13219 for (auto const& listener : listeners) { 13220 multi.addListener(listener->create(Catch::ReporterConfig(config))); 13221 } 13222 multi.addReporter(createReporter(config->getReporterName(), config)); 13223 return ret; 13224 } 13225 13226 class TestGroup { 13227 public: 13228 explicit TestGroup(std::shared_ptr<Config> const& config) 13229 : m_config{config} 13230 , m_context{config, makeReporter(config)} 13231 { 13232 auto const& allTestCases = getAllTestCasesSorted(*m_config); 13233 m_matches = m_config->testSpec().matchesByFilter(allTestCases, *m_config); 13234 auto const& invalidArgs = m_config->testSpec().getInvalidArgs(); 13235 13236 if (m_matches.empty() && invalidArgs.empty()) { 13237 for (auto const& test : allTestCases) 13238 if (!test.isHidden()) 13239 m_tests.emplace(&test); 13240 } else { 13241 for (auto const& match : m_matches) 13242 m_tests.insert(match.tests.begin(), match.tests.end()); 13243 } 13244 } 13245 13246 Totals execute() { 13247 auto const& invalidArgs = m_config->testSpec().getInvalidArgs(); 13248 Totals totals; 13249 m_context.testGroupStarting(m_config->name(), 1, 1); 13250 for (auto const& testCase : m_tests) { 13251 if (!m_context.aborting()) 13252 totals += m_context.runTest(*testCase); 13253 else 13254 m_context.reporter().skipTest(*testCase); 13255 } 13256 13257 for (auto const& match : m_matches) { 13258 if (match.tests.empty()) { 13259 m_context.reporter().noMatchingTestCases(match.name); 13260 totals.error = -1; 13261 } 13262 } 13263 13264 if (!invalidArgs.empty()) { 13265 for (auto const& invalidArg: invalidArgs) 13266 m_context.reporter().reportInvalidArguments(invalidArg); 13267 } 13268 13269 m_context.testGroupEnded(m_config->name(), totals, 1, 1); 13270 return totals; 13271 } 13272 13273 private: 13274 using Tests = std::set<TestCase const*>; 13275 13276 std::shared_ptr<Config> m_config; 13277 RunContext m_context; 13278 Tests m_tests; 13279 TestSpec::Matches m_matches; 13280 }; 13281 13282 void applyFilenamesAsTags(Catch::IConfig const& config) { 13283 auto& tests = const_cast<std::vector<TestCase>&>(getAllTestCasesSorted(config)); 13284 for (auto& testCase : tests) { 13285 auto tags = testCase.tags; 13286 13287 std::string filename = testCase.lineInfo.file; 13288 auto lastSlash = filename.find_last_of("\\/"); 13289 if (lastSlash != std::string::npos) { 13290 filename.erase(0, lastSlash); 13291 filename[0] = '#'; 13292 } 13293 13294 auto lastDot = filename.find_last_of('.'); 13295 if (lastDot != std::string::npos) { 13296 filename.erase(lastDot); 13297 } 13298 13299 tags.push_back(std::move(filename)); 13300 setTags(testCase, tags); 13301 } 13302 } 13303 13304 } // anon namespace 13305 13306 Session::Session() { 13307 static bool alreadyInstantiated = false; 13308 if( alreadyInstantiated ) { 13309 CATCH_TRY { CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" ); } 13310 CATCH_CATCH_ALL { getMutableRegistryHub().registerStartupException(); } 13311 } 13312 13313 // There cannot be exceptions at startup in no-exception mode. 13314 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 13315 const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions(); 13316 if ( !exceptions.empty() ) { 13317 config(); 13318 getCurrentMutableContext().setConfig(m_config); 13319 13320 m_startupExceptions = true; 13321 Colour colourGuard( Colour::Red ); 13322 Catch::cerr() << "Errors occurred during startup!" << '\n'; 13323 // iterate over all exceptions and notify user 13324 for ( const auto& ex_ptr : exceptions ) { 13325 try { 13326 std::rethrow_exception(ex_ptr); 13327 } catch ( std::exception const& ex ) { 13328 Catch::cerr() << Column( ex.what() ).indent(2) << '\n'; 13329 } 13330 } 13331 } 13332 #endif 13333 13334 alreadyInstantiated = true; 13335 m_cli = makeCommandLineParser( m_configData ); 13336 } 13337 Session::~Session() { 13338 Catch::cleanUp(); 13339 } 13340 13341 void Session::showHelp() const { 13342 Catch::cout() 13343 << "\nCatch v" << libraryVersion() << "\n" 13344 << m_cli << std::endl 13345 << "For more detailed usage please see the project docs\n" << std::endl; 13346 } 13347 void Session::libIdentify() { 13348 Catch::cout() 13349 << std::left << std::setw(16) << "description: " << "A Catch2 test executable\n" 13350 << std::left << std::setw(16) << "category: " << "testframework\n" 13351 << std::left << std::setw(16) << "framework: " << "Catch Test\n" 13352 << std::left << std::setw(16) << "version: " << libraryVersion() << std::endl; 13353 } 13354 13355 int Session::applyCommandLine( int argc, char const * const * argv ) { 13356 if( m_startupExceptions ) 13357 return 1; 13358 13359 auto result = m_cli.parse( clara::Args( argc, argv ) ); 13360 if( !result ) { 13361 config(); 13362 getCurrentMutableContext().setConfig(m_config); 13363 Catch::cerr() 13364 << Colour( Colour::Red ) 13365 << "\nError(s) in input:\n" 13366 << Column( result.errorMessage() ).indent( 2 ) 13367 << "\n\n"; 13368 Catch::cerr() << "Run with -? for usage\n" << std::endl; 13369 return MaxExitCode; 13370 } 13371 13372 if( m_configData.showHelp ) 13373 showHelp(); 13374 if( m_configData.libIdentify ) 13375 libIdentify(); 13376 m_config.reset(); 13377 return 0; 13378 } 13379 13380 #if defined(CATCH_CONFIG_WCHAR) && defined(_WIN32) && defined(UNICODE) 13381 int Session::applyCommandLine( int argc, wchar_t const * const * argv ) { 13382 13383 char **utf8Argv = new char *[ argc ]; 13384 13385 for ( int i = 0; i < argc; ++i ) { 13386 int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, nullptr, 0, nullptr, nullptr ); 13387 13388 utf8Argv[ i ] = new char[ bufSize ]; 13389 13390 WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, nullptr, nullptr ); 13391 } 13392 13393 int returnCode = applyCommandLine( argc, utf8Argv ); 13394 13395 for ( int i = 0; i < argc; ++i ) 13396 delete [] utf8Argv[ i ]; 13397 13398 delete [] utf8Argv; 13399 13400 return returnCode; 13401 } 13402 #endif 13403 13404 void Session::useConfigData( ConfigData const& configData ) { 13405 m_configData = configData; 13406 m_config.reset(); 13407 } 13408 13409 int Session::run() { 13410 if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) { 13411 Catch::cout() << "...waiting for enter/ return before starting" << std::endl; 13412 static_cast<void>(std::getchar()); 13413 } 13414 int exitCode = runInternal(); 13415 if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) { 13416 Catch::cout() << "...waiting for enter/ return before exiting, with code: " << exitCode << std::endl; 13417 static_cast<void>(std::getchar()); 13418 } 13419 return exitCode; 13420 } 13421 13422 clara::Parser const& Session::cli() const { 13423 return m_cli; 13424 } 13425 void Session::cli( clara::Parser const& newParser ) { 13426 m_cli = newParser; 13427 } 13428 ConfigData& Session::configData() { 13429 return m_configData; 13430 } 13431 Config& Session::config() { 13432 if( !m_config ) 13433 m_config = std::make_shared<Config>( m_configData ); 13434 return *m_config; 13435 } 13436 13437 int Session::runInternal() { 13438 if( m_startupExceptions ) 13439 return 1; 13440 13441 if (m_configData.showHelp || m_configData.libIdentify) { 13442 return 0; 13443 } 13444 13445 CATCH_TRY { 13446 config(); // Force config to be constructed 13447 13448 seedRng( *m_config ); 13449 13450 if( m_configData.filenamesAsTags ) 13451 applyFilenamesAsTags( *m_config ); 13452 13453 // Handle list request 13454 if( Option<std::size_t> listed = list( m_config ) ) 13455 return static_cast<int>( *listed ); 13456 13457 TestGroup tests { m_config }; 13458 auto const totals = tests.execute(); 13459 13460 if( m_config->warnAboutNoTests() && totals.error == -1 ) 13461 return 2; 13462 13463 // Note that on unices only the lower 8 bits are usually used, clamping 13464 // the return value to 255 prevents false negative when some multiple 13465 // of 256 tests has failed 13466 return (std::min) (MaxExitCode, (std::max) (totals.error, static_cast<int>(totals.assertions.failed))); 13467 } 13468 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 13469 catch( std::exception& ex ) { 13470 Catch::cerr() << ex.what() << std::endl; 13471 return MaxExitCode; 13472 } 13473 #endif 13474 } 13475 13476 } // end namespace Catch 13477 // end catch_session.cpp 13478 // start catch_singletons.cpp 13479 13480 #include <vector> 13481 13482 namespace Catch { 13483 13484 namespace { 13485 static auto getSingletons() -> std::vector<ISingleton*>*& { 13486 static std::vector<ISingleton*>* g_singletons = nullptr; 13487 if( !g_singletons ) 13488 g_singletons = new std::vector<ISingleton*>(); 13489 return g_singletons; 13490 } 13491 } 13492 13493 ISingleton::~ISingleton() {} 13494 13495 void addSingleton(ISingleton* singleton ) { 13496 getSingletons()->push_back( singleton ); 13497 } 13498 void cleanupSingletons() { 13499 auto& singletons = getSingletons(); 13500 for( auto singleton : *singletons ) 13501 delete singleton; 13502 delete singletons; 13503 singletons = nullptr; 13504 } 13505 13506 } // namespace Catch 13507 // end catch_singletons.cpp 13508 // start catch_startup_exception_registry.cpp 13509 13510 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 13511 namespace Catch { 13512 void StartupExceptionRegistry::add( std::exception_ptr const& exception ) noexcept { 13513 CATCH_TRY { 13514 m_exceptions.push_back(exception); 13515 } CATCH_CATCH_ALL { 13516 // If we run out of memory during start-up there's really not a lot more we can do about it 13517 std::terminate(); 13518 } 13519 } 13520 13521 std::vector<std::exception_ptr> const& StartupExceptionRegistry::getExceptions() const noexcept { 13522 return m_exceptions; 13523 } 13524 13525 } // end namespace Catch 13526 #endif 13527 // end catch_startup_exception_registry.cpp 13528 // start catch_stream.cpp 13529 13530 #include <cstdio> 13531 #include <iostream> 13532 #include <fstream> 13533 #include <sstream> 13534 #include <vector> 13535 #include <memory> 13536 13537 namespace Catch { 13538 13539 Catch::IStream::~IStream() = default; 13540 13541 namespace Detail { namespace { 13542 template<typename WriterF, std::size_t bufferSize=256> 13543 class StreamBufImpl : public std::streambuf { 13544 char data[bufferSize]; 13545 WriterF m_writer; 13546 13547 public: 13548 StreamBufImpl() { 13549 setp( data, data + sizeof(data) ); 13550 } 13551 13552 ~StreamBufImpl() noexcept { 13553 StreamBufImpl::sync(); 13554 } 13555 13556 private: 13557 int overflow( int c ) override { 13558 sync(); 13559 13560 if( c != EOF ) { 13561 if( pbase() == epptr() ) 13562 m_writer( std::string( 1, static_cast<char>( c ) ) ); 13563 else 13564 sputc( static_cast<char>( c ) ); 13565 } 13566 return 0; 13567 } 13568 13569 int sync() override { 13570 if( pbase() != pptr() ) { 13571 m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) ); 13572 setp( pbase(), epptr() ); 13573 } 13574 return 0; 13575 } 13576 }; 13577 13578 /////////////////////////////////////////////////////////////////////////// 13579 13580 struct OutputDebugWriter { 13581 13582 void operator()( std::string const&str ) { 13583 writeToDebugConsole( str ); 13584 } 13585 }; 13586 13587 /////////////////////////////////////////////////////////////////////////// 13588 13589 class FileStream : public IStream { 13590 mutable std::ofstream m_ofs; 13591 public: 13592 FileStream( StringRef filename ) { 13593 m_ofs.open( filename.c_str() ); 13594 CATCH_ENFORCE( !m_ofs.fail(), "Unable to open file: '" << filename << "'" ); 13595 } 13596 ~FileStream() override = default; 13597 public: // IStream 13598 std::ostream& stream() const override { 13599 return m_ofs; 13600 } 13601 }; 13602 13603 /////////////////////////////////////////////////////////////////////////// 13604 13605 class CoutStream : public IStream { 13606 mutable std::ostream m_os; 13607 public: 13608 // Store the streambuf from cout up-front because 13609 // cout may get redirected when running tests 13610 CoutStream() : m_os( Catch::cout().rdbuf() ) {} 13611 ~CoutStream() override = default; 13612 13613 public: // IStream 13614 std::ostream& stream() const override { return m_os; } 13615 }; 13616 13617 /////////////////////////////////////////////////////////////////////////// 13618 13619 class DebugOutStream : public IStream { 13620 std::unique_ptr<StreamBufImpl<OutputDebugWriter>> m_streamBuf; 13621 mutable std::ostream m_os; 13622 public: 13623 DebugOutStream() 13624 : m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ), 13625 m_os( m_streamBuf.get() ) 13626 {} 13627 13628 ~DebugOutStream() override = default; 13629 13630 public: // IStream 13631 std::ostream& stream() const override { return m_os; } 13632 }; 13633 13634 }} // namespace anon::detail 13635 13636 /////////////////////////////////////////////////////////////////////////// 13637 13638 auto makeStream( StringRef const &filename ) -> IStream const* { 13639 if( filename.empty() ) 13640 return new Detail::CoutStream(); 13641 else if( filename[0] == '%' ) { 13642 if( filename == "%debug" ) 13643 return new Detail::DebugOutStream(); 13644 else 13645 CATCH_ERROR( "Unrecognised stream: '" << filename << "'" ); 13646 } 13647 else 13648 return new Detail::FileStream( filename ); 13649 } 13650 13651 // This class encapsulates the idea of a pool of ostringstreams that can be reused. 13652 struct StringStreams { 13653 std::vector<std::unique_ptr<std::ostringstream>> m_streams; 13654 std::vector<std::size_t> m_unused; 13655 std::ostringstream m_referenceStream; // Used for copy state/ flags from 13656 13657 auto add() -> std::size_t { 13658 if( m_unused.empty() ) { 13659 m_streams.push_back( std::unique_ptr<std::ostringstream>( new std::ostringstream ) ); 13660 return m_streams.size()-1; 13661 } 13662 else { 13663 auto index = m_unused.back(); 13664 m_unused.pop_back(); 13665 return index; 13666 } 13667 } 13668 13669 void release( std::size_t index ) { 13670 m_streams[index]->copyfmt( m_referenceStream ); // Restore initial flags and other state 13671 m_unused.push_back(index); 13672 } 13673 }; 13674 13675 ReusableStringStream::ReusableStringStream() 13676 : m_index( Singleton<StringStreams>::getMutable().add() ), 13677 m_oss( Singleton<StringStreams>::getMutable().m_streams[m_index].get() ) 13678 {} 13679 13680 ReusableStringStream::~ReusableStringStream() { 13681 static_cast<std::ostringstream*>( m_oss )->str(""); 13682 m_oss->clear(); 13683 Singleton<StringStreams>::getMutable().release( m_index ); 13684 } 13685 13686 auto ReusableStringStream::str() const -> std::string { 13687 return static_cast<std::ostringstream*>( m_oss )->str(); 13688 } 13689 13690 /////////////////////////////////////////////////////////////////////////// 13691 13692 #ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions 13693 std::ostream& cout() { return std::cout; } 13694 std::ostream& cerr() { return std::cerr; } 13695 std::ostream& clog() { return std::clog; } 13696 #endif 13697 } 13698 // end catch_stream.cpp 13699 // start catch_string_manip.cpp 13700 13701 #include <algorithm> 13702 #include <ostream> 13703 #include <cstring> 13704 #include <cctype> 13705 #include <vector> 13706 13707 namespace Catch { 13708 13709 namespace { 13710 char toLowerCh(char c) { 13711 return static_cast<char>( std::tolower( static_cast<unsigned char>(c) ) ); 13712 } 13713 } 13714 13715 bool startsWith( std::string const& s, std::string const& prefix ) { 13716 return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin()); 13717 } 13718 bool startsWith( std::string const& s, char prefix ) { 13719 return !s.empty() && s[0] == prefix; 13720 } 13721 bool endsWith( std::string const& s, std::string const& suffix ) { 13722 return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin()); 13723 } 13724 bool endsWith( std::string const& s, char suffix ) { 13725 return !s.empty() && s[s.size()-1] == suffix; 13726 } 13727 bool contains( std::string const& s, std::string const& infix ) { 13728 return s.find( infix ) != std::string::npos; 13729 } 13730 void toLowerInPlace( std::string& s ) { 13731 std::transform( s.begin(), s.end(), s.begin(), toLowerCh ); 13732 } 13733 std::string toLower( std::string const& s ) { 13734 std::string lc = s; 13735 toLowerInPlace( lc ); 13736 return lc; 13737 } 13738 std::string trim( std::string const& str ) { 13739 static char const* whitespaceChars = "\n\r\t "; 13740 std::string::size_type start = str.find_first_not_of( whitespaceChars ); 13741 std::string::size_type end = str.find_last_not_of( whitespaceChars ); 13742 13743 return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string(); 13744 } 13745 13746 StringRef trim(StringRef ref) { 13747 const auto is_ws = [](char c) { 13748 return c == ' ' || c == '\t' || c == '\n' || c == '\r'; 13749 }; 13750 size_t real_begin = 0; 13751 while (real_begin < ref.size() && is_ws(ref[real_begin])) { ++real_begin; } 13752 size_t real_end = ref.size(); 13753 while (real_end > real_begin && is_ws(ref[real_end - 1])) { --real_end; } 13754 13755 return ref.substr(real_begin, real_end - real_begin); 13756 } 13757 13758 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) { 13759 bool replaced = false; 13760 std::size_t i = str.find( replaceThis ); 13761 while( i != std::string::npos ) { 13762 replaced = true; 13763 str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() ); 13764 if( i < str.size()-withThis.size() ) 13765 i = str.find( replaceThis, i+withThis.size() ); 13766 else 13767 i = std::string::npos; 13768 } 13769 return replaced; 13770 } 13771 13772 std::vector<StringRef> splitStringRef( StringRef str, char delimiter ) { 13773 std::vector<StringRef> subStrings; 13774 std::size_t start = 0; 13775 for(std::size_t pos = 0; pos < str.size(); ++pos ) { 13776 if( str[pos] == delimiter ) { 13777 if( pos - start > 1 ) 13778 subStrings.push_back( str.substr( start, pos-start ) ); 13779 start = pos+1; 13780 } 13781 } 13782 if( start < str.size() ) 13783 subStrings.push_back( str.substr( start, str.size()-start ) ); 13784 return subStrings; 13785 } 13786 13787 pluralise::pluralise( std::size_t count, std::string const& label ) 13788 : m_count( count ), 13789 m_label( label ) 13790 {} 13791 13792 std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { 13793 os << pluraliser.m_count << ' ' << pluraliser.m_label; 13794 if( pluraliser.m_count != 1 ) 13795 os << 's'; 13796 return os; 13797 } 13798 13799 } 13800 // end catch_string_manip.cpp 13801 // start catch_stringref.cpp 13802 13803 #include <algorithm> 13804 #include <ostream> 13805 #include <cstring> 13806 #include <cstdint> 13807 13808 namespace Catch { 13809 StringRef::StringRef( char const* rawChars ) noexcept 13810 : StringRef( rawChars, static_cast<StringRef::size_type>(std::strlen(rawChars) ) ) 13811 {} 13812 13813 auto StringRef::c_str() const -> char const* { 13814 CATCH_ENFORCE(isNullTerminated(), "Called StringRef::c_str() on a non-null-terminated instance"); 13815 return m_start; 13816 } 13817 auto StringRef::data() const noexcept -> char const* { 13818 return m_start; 13819 } 13820 13821 auto StringRef::substr( size_type start, size_type size ) const noexcept -> StringRef { 13822 if (start < m_size) { 13823 return StringRef(m_start + start, (std::min)(m_size - start, size)); 13824 } else { 13825 return StringRef(); 13826 } 13827 } 13828 auto StringRef::operator == ( StringRef const& other ) const noexcept -> bool { 13829 return m_size == other.m_size 13830 && (std::memcmp( m_start, other.m_start, m_size ) == 0); 13831 } 13832 13833 auto operator << ( std::ostream& os, StringRef const& str ) -> std::ostream& { 13834 return os.write(str.data(), str.size()); 13835 } 13836 13837 auto operator+=( std::string& lhs, StringRef const& rhs ) -> std::string& { 13838 lhs.append(rhs.data(), rhs.size()); 13839 return lhs; 13840 } 13841 13842 } // namespace Catch 13843 // end catch_stringref.cpp 13844 // start catch_tag_alias.cpp 13845 13846 namespace Catch { 13847 TagAlias::TagAlias(std::string const & _tag, SourceLineInfo _lineInfo): tag(_tag), lineInfo(_lineInfo) {} 13848 } 13849 // end catch_tag_alias.cpp 13850 // start catch_tag_alias_autoregistrar.cpp 13851 13852 namespace Catch { 13853 13854 RegistrarForTagAliases::RegistrarForTagAliases(char const* alias, char const* tag, SourceLineInfo const& lineInfo) { 13855 CATCH_TRY { 13856 getMutableRegistryHub().registerTagAlias(alias, tag, lineInfo); 13857 } CATCH_CATCH_ALL { 13858 // Do not throw when constructing global objects, instead register the exception to be processed later 13859 getMutableRegistryHub().registerStartupException(); 13860 } 13861 } 13862 13863 } 13864 // end catch_tag_alias_autoregistrar.cpp 13865 // start catch_tag_alias_registry.cpp 13866 13867 #include <sstream> 13868 13869 namespace Catch { 13870 13871 TagAliasRegistry::~TagAliasRegistry() {} 13872 13873 TagAlias const* TagAliasRegistry::find( std::string const& alias ) const { 13874 auto it = m_registry.find( alias ); 13875 if( it != m_registry.end() ) 13876 return &(it->second); 13877 else 13878 return nullptr; 13879 } 13880 13881 std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const { 13882 std::string expandedTestSpec = unexpandedTestSpec; 13883 for( auto const& registryKvp : m_registry ) { 13884 std::size_t pos = expandedTestSpec.find( registryKvp.first ); 13885 if( pos != std::string::npos ) { 13886 expandedTestSpec = expandedTestSpec.substr( 0, pos ) + 13887 registryKvp.second.tag + 13888 expandedTestSpec.substr( pos + registryKvp.first.size() ); 13889 } 13890 } 13891 return expandedTestSpec; 13892 } 13893 13894 void TagAliasRegistry::add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) { 13895 CATCH_ENFORCE( startsWith(alias, "[@") && endsWith(alias, ']'), 13896 "error: tag alias, '" << alias << "' is not of the form [@alias name].\n" << lineInfo ); 13897 13898 CATCH_ENFORCE( m_registry.insert(std::make_pair(alias, TagAlias(tag, lineInfo))).second, 13899 "error: tag alias, '" << alias << "' already registered.\n" 13900 << "\tFirst seen at: " << find(alias)->lineInfo << "\n" 13901 << "\tRedefined at: " << lineInfo ); 13902 } 13903 13904 ITagAliasRegistry::~ITagAliasRegistry() {} 13905 13906 ITagAliasRegistry const& ITagAliasRegistry::get() { 13907 return getRegistryHub().getTagAliasRegistry(); 13908 } 13909 13910 } // end namespace Catch 13911 // end catch_tag_alias_registry.cpp 13912 // start catch_test_case_info.cpp 13913 13914 #include <cctype> 13915 #include <exception> 13916 #include <algorithm> 13917 #include <sstream> 13918 13919 namespace Catch { 13920 13921 namespace { 13922 TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) { 13923 if( startsWith( tag, '.' ) || 13924 tag == "!hide" ) 13925 return TestCaseInfo::IsHidden; 13926 else if( tag == "!throws" ) 13927 return TestCaseInfo::Throws; 13928 else if( tag == "!shouldfail" ) 13929 return TestCaseInfo::ShouldFail; 13930 else if( tag == "!mayfail" ) 13931 return TestCaseInfo::MayFail; 13932 else if( tag == "!nonportable" ) 13933 return TestCaseInfo::NonPortable; 13934 else if( tag == "!benchmark" ) 13935 return static_cast<TestCaseInfo::SpecialProperties>( TestCaseInfo::Benchmark | TestCaseInfo::IsHidden ); 13936 else 13937 return TestCaseInfo::None; 13938 } 13939 bool isReservedTag( std::string const& tag ) { 13940 return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( static_cast<unsigned char>(tag[0]) ); 13941 } 13942 void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { 13943 CATCH_ENFORCE( !isReservedTag(tag), 13944 "Tag name: [" << tag << "] is not allowed.\n" 13945 << "Tag names starting with non alphanumeric characters are reserved\n" 13946 << _lineInfo ); 13947 } 13948 } 13949 13950 TestCase makeTestCase( ITestInvoker* _testCase, 13951 std::string const& _className, 13952 NameAndTags const& nameAndTags, 13953 SourceLineInfo const& _lineInfo ) 13954 { 13955 bool isHidden = false; 13956 13957 // Parse out tags 13958 std::vector<std::string> tags; 13959 std::string desc, tag; 13960 bool inTag = false; 13961 for (char c : nameAndTags.tags) { 13962 if( !inTag ) { 13963 if( c == '[' ) 13964 inTag = true; 13965 else 13966 desc += c; 13967 } 13968 else { 13969 if( c == ']' ) { 13970 TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag ); 13971 if( ( prop & TestCaseInfo::IsHidden ) != 0 ) 13972 isHidden = true; 13973 else if( prop == TestCaseInfo::None ) 13974 enforceNotReservedTag( tag, _lineInfo ); 13975 13976 // Merged hide tags like `[.approvals]` should be added as 13977 // `[.][approvals]`. The `[.]` is added at later point, so 13978 // we only strip the prefix 13979 if (startsWith(tag, '.') && tag.size() > 1) { 13980 tag.erase(0, 1); 13981 } 13982 tags.push_back( tag ); 13983 tag.clear(); 13984 inTag = false; 13985 } 13986 else 13987 tag += c; 13988 } 13989 } 13990 if( isHidden ) { 13991 // Add all "hidden" tags to make them behave identically 13992 tags.insert( tags.end(), { ".", "!hide" } ); 13993 } 13994 13995 TestCaseInfo info( static_cast<std::string>(nameAndTags.name), _className, desc, tags, _lineInfo ); 13996 return TestCase( _testCase, std::move(info) ); 13997 } 13998 13999 void setTags( TestCaseInfo& testCaseInfo, std::vector<std::string> tags ) { 14000 std::sort(begin(tags), end(tags)); 14001 tags.erase(std::unique(begin(tags), end(tags)), end(tags)); 14002 testCaseInfo.lcaseTags.clear(); 14003 14004 for( auto const& tag : tags ) { 14005 std::string lcaseTag = toLower( tag ); 14006 testCaseInfo.properties = static_cast<TestCaseInfo::SpecialProperties>( testCaseInfo.properties | parseSpecialTag( lcaseTag ) ); 14007 testCaseInfo.lcaseTags.push_back( lcaseTag ); 14008 } 14009 testCaseInfo.tags = std::move(tags); 14010 } 14011 14012 TestCaseInfo::TestCaseInfo( std::string const& _name, 14013 std::string const& _className, 14014 std::string const& _description, 14015 std::vector<std::string> const& _tags, 14016 SourceLineInfo const& _lineInfo ) 14017 : name( _name ), 14018 className( _className ), 14019 description( _description ), 14020 lineInfo( _lineInfo ), 14021 properties( None ) 14022 { 14023 setTags( *this, _tags ); 14024 } 14025 14026 bool TestCaseInfo::isHidden() const { 14027 return ( properties & IsHidden ) != 0; 14028 } 14029 bool TestCaseInfo::throws() const { 14030 return ( properties & Throws ) != 0; 14031 } 14032 bool TestCaseInfo::okToFail() const { 14033 return ( properties & (ShouldFail | MayFail ) ) != 0; 14034 } 14035 bool TestCaseInfo::expectedToFail() const { 14036 return ( properties & (ShouldFail ) ) != 0; 14037 } 14038 14039 std::string TestCaseInfo::tagsAsString() const { 14040 std::string ret; 14041 // '[' and ']' per tag 14042 std::size_t full_size = 2 * tags.size(); 14043 for (const auto& tag : tags) { 14044 full_size += tag.size(); 14045 } 14046 ret.reserve(full_size); 14047 for (const auto& tag : tags) { 14048 ret.push_back('['); 14049 ret.append(tag); 14050 ret.push_back(']'); 14051 } 14052 14053 return ret; 14054 } 14055 14056 TestCase::TestCase( ITestInvoker* testCase, TestCaseInfo&& info ) : TestCaseInfo( std::move(info) ), test( testCase ) {} 14057 14058 TestCase TestCase::withName( std::string const& _newName ) const { 14059 TestCase other( *this ); 14060 other.name = _newName; 14061 return other; 14062 } 14063 14064 void TestCase::invoke() const { 14065 test->invoke(); 14066 } 14067 14068 bool TestCase::operator == ( TestCase const& other ) const { 14069 return test.get() == other.test.get() && 14070 name == other.name && 14071 className == other.className; 14072 } 14073 14074 bool TestCase::operator < ( TestCase const& other ) const { 14075 return name < other.name; 14076 } 14077 14078 TestCaseInfo const& TestCase::getTestCaseInfo() const 14079 { 14080 return *this; 14081 } 14082 14083 } // end namespace Catch 14084 // end catch_test_case_info.cpp 14085 // start catch_test_case_registry_impl.cpp 14086 14087 #include <algorithm> 14088 #include <sstream> 14089 14090 namespace Catch { 14091 14092 namespace { 14093 struct TestHasher { 14094 explicit TestHasher(Catch::SimplePcg32& rng) { 14095 basis = rng(); 14096 basis <<= 32; 14097 basis |= rng(); 14098 } 14099 14100 uint64_t basis; 14101 14102 uint64_t operator()(TestCase const& t) const { 14103 // Modified FNV-1a hash 14104 static constexpr uint64_t prime = 1099511628211; 14105 uint64_t hash = basis; 14106 for (const char c : t.name) { 14107 hash ^= c; 14108 hash *= prime; 14109 } 14110 return hash; 14111 } 14112 }; 14113 } // end unnamed namespace 14114 14115 std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) { 14116 switch( config.runOrder() ) { 14117 case RunTests::InDeclarationOrder: 14118 // already in declaration order 14119 break; 14120 14121 case RunTests::InLexicographicalOrder: { 14122 std::vector<TestCase> sorted = unsortedTestCases; 14123 std::sort( sorted.begin(), sorted.end() ); 14124 return sorted; 14125 } 14126 14127 case RunTests::InRandomOrder: { 14128 seedRng( config ); 14129 TestHasher h( rng() ); 14130 14131 using hashedTest = std::pair<uint64_t, TestCase const*>; 14132 std::vector<hashedTest> indexed_tests; 14133 indexed_tests.reserve( unsortedTestCases.size() ); 14134 14135 for (auto const& testCase : unsortedTestCases) { 14136 indexed_tests.emplace_back(h(testCase), &testCase); 14137 } 14138 14139 std::sort(indexed_tests.begin(), indexed_tests.end(), 14140 [](hashedTest const& lhs, hashedTest const& rhs) { 14141 if (lhs.first == rhs.first) { 14142 return lhs.second->name < rhs.second->name; 14143 } 14144 return lhs.first < rhs.first; 14145 }); 14146 14147 std::vector<TestCase> sorted; 14148 sorted.reserve( indexed_tests.size() ); 14149 14150 for (auto const& hashed : indexed_tests) { 14151 sorted.emplace_back(*hashed.second); 14152 } 14153 14154 return sorted; 14155 } 14156 } 14157 return unsortedTestCases; 14158 } 14159 14160 bool isThrowSafe( TestCase const& testCase, IConfig const& config ) { 14161 return !testCase.throws() || config.allowThrows(); 14162 } 14163 14164 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) { 14165 return testSpec.matches( testCase ) && isThrowSafe( testCase, config ); 14166 } 14167 14168 void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) { 14169 std::set<TestCase> seenFunctions; 14170 for( auto const& function : functions ) { 14171 auto prev = seenFunctions.insert( function ); 14172 CATCH_ENFORCE( prev.second, 14173 "error: TEST_CASE( \"" << function.name << "\" ) already defined.\n" 14174 << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n" 14175 << "\tRedefined at " << function.getTestCaseInfo().lineInfo ); 14176 } 14177 } 14178 14179 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) { 14180 std::vector<TestCase> filtered; 14181 filtered.reserve( testCases.size() ); 14182 for (auto const& testCase : testCases) { 14183 if ((!testSpec.hasFilters() && !testCase.isHidden()) || 14184 (testSpec.hasFilters() && matchTest(testCase, testSpec, config))) { 14185 filtered.push_back(testCase); 14186 } 14187 } 14188 return filtered; 14189 } 14190 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) { 14191 return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config ); 14192 } 14193 14194 void TestRegistry::registerTest( TestCase const& testCase ) { 14195 std::string name = testCase.getTestCaseInfo().name; 14196 if( name.empty() ) { 14197 ReusableStringStream rss; 14198 rss << "Anonymous test case " << ++m_unnamedCount; 14199 return registerTest( testCase.withName( rss.str() ) ); 14200 } 14201 m_functions.push_back( testCase ); 14202 } 14203 14204 std::vector<TestCase> const& TestRegistry::getAllTests() const { 14205 return m_functions; 14206 } 14207 std::vector<TestCase> const& TestRegistry::getAllTestsSorted( IConfig const& config ) const { 14208 if( m_sortedFunctions.empty() ) 14209 enforceNoDuplicateTestCases( m_functions ); 14210 14211 if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) { 14212 m_sortedFunctions = sortTests( config, m_functions ); 14213 m_currentSortOrder = config.runOrder(); 14214 } 14215 return m_sortedFunctions; 14216 } 14217 14218 /////////////////////////////////////////////////////////////////////////// 14219 TestInvokerAsFunction::TestInvokerAsFunction( void(*testAsFunction)() ) noexcept : m_testAsFunction( testAsFunction ) {} 14220 14221 void TestInvokerAsFunction::invoke() const { 14222 m_testAsFunction(); 14223 } 14224 14225 std::string extractClassName( StringRef const& classOrQualifiedMethodName ) { 14226 std::string className(classOrQualifiedMethodName); 14227 if( startsWith( className, '&' ) ) 14228 { 14229 std::size_t lastColons = className.rfind( "::" ); 14230 std::size_t penultimateColons = className.rfind( "::", lastColons-1 ); 14231 if( penultimateColons == std::string::npos ) 14232 penultimateColons = 1; 14233 className = className.substr( penultimateColons, lastColons-penultimateColons ); 14234 } 14235 return className; 14236 } 14237 14238 } // end namespace Catch 14239 // end catch_test_case_registry_impl.cpp 14240 // start catch_test_case_tracker.cpp 14241 14242 #include <algorithm> 14243 #include <cassert> 14244 #include <stdexcept> 14245 #include <memory> 14246 #include <sstream> 14247 14248 #if defined(__clang__) 14249 # pragma clang diagnostic push 14250 # pragma clang diagnostic ignored "-Wexit-time-destructors" 14251 #endif 14252 14253 namespace Catch { 14254 namespace TestCaseTracking { 14255 14256 NameAndLocation::NameAndLocation( std::string const& _name, SourceLineInfo const& _location ) 14257 : name( _name ), 14258 location( _location ) 14259 {} 14260 14261 ITracker::~ITracker() = default; 14262 14263 ITracker& TrackerContext::startRun() { 14264 m_rootTracker = std::make_shared<SectionTracker>( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, nullptr ); 14265 m_currentTracker = nullptr; 14266 m_runState = Executing; 14267 return *m_rootTracker; 14268 } 14269 14270 void TrackerContext::endRun() { 14271 m_rootTracker.reset(); 14272 m_currentTracker = nullptr; 14273 m_runState = NotStarted; 14274 } 14275 14276 void TrackerContext::startCycle() { 14277 m_currentTracker = m_rootTracker.get(); 14278 m_runState = Executing; 14279 } 14280 void TrackerContext::completeCycle() { 14281 m_runState = CompletedCycle; 14282 } 14283 14284 bool TrackerContext::completedCycle() const { 14285 return m_runState == CompletedCycle; 14286 } 14287 ITracker& TrackerContext::currentTracker() { 14288 return *m_currentTracker; 14289 } 14290 void TrackerContext::setCurrentTracker( ITracker* tracker ) { 14291 m_currentTracker = tracker; 14292 } 14293 14294 TrackerBase::TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ): 14295 ITracker(nameAndLocation), 14296 m_ctx( ctx ), 14297 m_parent( parent ) 14298 {} 14299 14300 bool TrackerBase::isComplete() const { 14301 return m_runState == CompletedSuccessfully || m_runState == Failed; 14302 } 14303 bool TrackerBase::isSuccessfullyCompleted() const { 14304 return m_runState == CompletedSuccessfully; 14305 } 14306 bool TrackerBase::isOpen() const { 14307 return m_runState != NotStarted && !isComplete(); 14308 } 14309 bool TrackerBase::hasChildren() const { 14310 return !m_children.empty(); 14311 } 14312 14313 void TrackerBase::addChild( ITrackerPtr const& child ) { 14314 m_children.push_back( child ); 14315 } 14316 14317 ITrackerPtr TrackerBase::findChild( NameAndLocation const& nameAndLocation ) { 14318 auto it = std::find_if( m_children.begin(), m_children.end(), 14319 [&nameAndLocation]( ITrackerPtr const& tracker ){ 14320 return 14321 tracker->nameAndLocation().location == nameAndLocation.location && 14322 tracker->nameAndLocation().name == nameAndLocation.name; 14323 } ); 14324 return( it != m_children.end() ) 14325 ? *it 14326 : nullptr; 14327 } 14328 ITracker& TrackerBase::parent() { 14329 assert( m_parent ); // Should always be non-null except for root 14330 return *m_parent; 14331 } 14332 14333 void TrackerBase::openChild() { 14334 if( m_runState != ExecutingChildren ) { 14335 m_runState = ExecutingChildren; 14336 if( m_parent ) 14337 m_parent->openChild(); 14338 } 14339 } 14340 14341 bool TrackerBase::isSectionTracker() const { return false; } 14342 bool TrackerBase::isGeneratorTracker() const { return false; } 14343 14344 void TrackerBase::open() { 14345 m_runState = Executing; 14346 moveToThis(); 14347 if( m_parent ) 14348 m_parent->openChild(); 14349 } 14350 14351 void TrackerBase::close() { 14352 14353 // Close any still open children (e.g. generators) 14354 while( &m_ctx.currentTracker() != this ) 14355 m_ctx.currentTracker().close(); 14356 14357 switch( m_runState ) { 14358 case NeedsAnotherRun: 14359 break; 14360 14361 case Executing: 14362 m_runState = CompletedSuccessfully; 14363 break; 14364 case ExecutingChildren: 14365 if( std::all_of(m_children.begin(), m_children.end(), [](ITrackerPtr const& t){ return t->isComplete(); }) ) 14366 m_runState = CompletedSuccessfully; 14367 break; 14368 14369 case NotStarted: 14370 case CompletedSuccessfully: 14371 case Failed: 14372 CATCH_INTERNAL_ERROR( "Illogical state: " << m_runState ); 14373 14374 default: 14375 CATCH_INTERNAL_ERROR( "Unknown state: " << m_runState ); 14376 } 14377 moveToParent(); 14378 m_ctx.completeCycle(); 14379 } 14380 void TrackerBase::fail() { 14381 m_runState = Failed; 14382 if( m_parent ) 14383 m_parent->markAsNeedingAnotherRun(); 14384 moveToParent(); 14385 m_ctx.completeCycle(); 14386 } 14387 void TrackerBase::markAsNeedingAnotherRun() { 14388 m_runState = NeedsAnotherRun; 14389 } 14390 14391 void TrackerBase::moveToParent() { 14392 assert( m_parent ); 14393 m_ctx.setCurrentTracker( m_parent ); 14394 } 14395 void TrackerBase::moveToThis() { 14396 m_ctx.setCurrentTracker( this ); 14397 } 14398 14399 SectionTracker::SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) 14400 : TrackerBase( nameAndLocation, ctx, parent ), 14401 m_trimmed_name(trim(nameAndLocation.name)) 14402 { 14403 if( parent ) { 14404 while( !parent->isSectionTracker() ) 14405 parent = &parent->parent(); 14406 14407 SectionTracker& parentSection = static_cast<SectionTracker&>( *parent ); 14408 addNextFilters( parentSection.m_filters ); 14409 } 14410 } 14411 14412 bool SectionTracker::isComplete() const { 14413 bool complete = true; 14414 14415 if (m_filters.empty() 14416 || m_filters[0] == "" 14417 || std::find(m_filters.begin(), m_filters.end(), m_trimmed_name) != m_filters.end()) { 14418 complete = TrackerBase::isComplete(); 14419 } 14420 return complete; 14421 } 14422 14423 bool SectionTracker::isSectionTracker() const { return true; } 14424 14425 SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) { 14426 std::shared_ptr<SectionTracker> section; 14427 14428 ITracker& currentTracker = ctx.currentTracker(); 14429 if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) { 14430 assert( childTracker ); 14431 assert( childTracker->isSectionTracker() ); 14432 section = std::static_pointer_cast<SectionTracker>( childTracker ); 14433 } 14434 else { 14435 section = std::make_shared<SectionTracker>( nameAndLocation, ctx, ¤tTracker ); 14436 currentTracker.addChild( section ); 14437 } 14438 if( !ctx.completedCycle() ) 14439 section->tryOpen(); 14440 return *section; 14441 } 14442 14443 void SectionTracker::tryOpen() { 14444 if( !isComplete() ) 14445 open(); 14446 } 14447 14448 void SectionTracker::addInitialFilters( std::vector<std::string> const& filters ) { 14449 if( !filters.empty() ) { 14450 m_filters.reserve( m_filters.size() + filters.size() + 2 ); 14451 m_filters.emplace_back(""); // Root - should never be consulted 14452 m_filters.emplace_back(""); // Test Case - not a section filter 14453 m_filters.insert( m_filters.end(), filters.begin(), filters.end() ); 14454 } 14455 } 14456 void SectionTracker::addNextFilters( std::vector<std::string> const& filters ) { 14457 if( filters.size() > 1 ) 14458 m_filters.insert( m_filters.end(), filters.begin()+1, filters.end() ); 14459 } 14460 14461 } // namespace TestCaseTracking 14462 14463 using TestCaseTracking::ITracker; 14464 using TestCaseTracking::TrackerContext; 14465 using TestCaseTracking::SectionTracker; 14466 14467 } // namespace Catch 14468 14469 #if defined(__clang__) 14470 # pragma clang diagnostic pop 14471 #endif 14472 // end catch_test_case_tracker.cpp 14473 // start catch_test_registry.cpp 14474 14475 namespace Catch { 14476 14477 auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker* { 14478 return new(std::nothrow) TestInvokerAsFunction( testAsFunction ); 14479 } 14480 14481 NameAndTags::NameAndTags( StringRef const& name_ , StringRef const& tags_ ) noexcept : name( name_ ), tags( tags_ ) {} 14482 14483 AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept { 14484 CATCH_TRY { 14485 getMutableRegistryHub() 14486 .registerTest( 14487 makeTestCase( 14488 invoker, 14489 extractClassName( classOrMethod ), 14490 nameAndTags, 14491 lineInfo)); 14492 } CATCH_CATCH_ALL { 14493 // Do not throw when constructing global objects, instead register the exception to be processed later 14494 getMutableRegistryHub().registerStartupException(); 14495 } 14496 } 14497 14498 AutoReg::~AutoReg() = default; 14499 } 14500 // end catch_test_registry.cpp 14501 // start catch_test_spec.cpp 14502 14503 #include <algorithm> 14504 #include <string> 14505 #include <vector> 14506 #include <memory> 14507 14508 namespace Catch { 14509 14510 TestSpec::Pattern::Pattern( std::string const& name ) 14511 : m_name( name ) 14512 {} 14513 14514 TestSpec::Pattern::~Pattern() = default; 14515 14516 std::string const& TestSpec::Pattern::name() const { 14517 return m_name; 14518 } 14519 14520 TestSpec::NamePattern::NamePattern( std::string const& name, std::string const& filterString ) 14521 : Pattern( filterString ) 14522 , m_wildcardPattern( toLower( name ), CaseSensitive::No ) 14523 {} 14524 14525 bool TestSpec::NamePattern::matches( TestCaseInfo const& testCase ) const { 14526 return m_wildcardPattern.matches( testCase.name ); 14527 } 14528 14529 TestSpec::TagPattern::TagPattern( std::string const& tag, std::string const& filterString ) 14530 : Pattern( filterString ) 14531 , m_tag( toLower( tag ) ) 14532 {} 14533 14534 bool TestSpec::TagPattern::matches( TestCaseInfo const& testCase ) const { 14535 return std::find(begin(testCase.lcaseTags), 14536 end(testCase.lcaseTags), 14537 m_tag) != end(testCase.lcaseTags); 14538 } 14539 14540 TestSpec::ExcludedPattern::ExcludedPattern( PatternPtr const& underlyingPattern ) 14541 : Pattern( underlyingPattern->name() ) 14542 , m_underlyingPattern( underlyingPattern ) 14543 {} 14544 14545 bool TestSpec::ExcludedPattern::matches( TestCaseInfo const& testCase ) const { 14546 return !m_underlyingPattern->matches( testCase ); 14547 } 14548 14549 bool TestSpec::Filter::matches( TestCaseInfo const& testCase ) const { 14550 return std::all_of( m_patterns.begin(), m_patterns.end(), [&]( PatternPtr const& p ){ return p->matches( testCase ); } ); 14551 } 14552 14553 std::string TestSpec::Filter::name() const { 14554 std::string name; 14555 for( auto const& p : m_patterns ) 14556 name += p->name(); 14557 return name; 14558 } 14559 14560 bool TestSpec::hasFilters() const { 14561 return !m_filters.empty(); 14562 } 14563 14564 bool TestSpec::matches( TestCaseInfo const& testCase ) const { 14565 return std::any_of( m_filters.begin(), m_filters.end(), [&]( Filter const& f ){ return f.matches( testCase ); } ); 14566 } 14567 14568 TestSpec::Matches TestSpec::matchesByFilter( std::vector<TestCase> const& testCases, IConfig const& config ) const 14569 { 14570 Matches matches( m_filters.size() ); 14571 std::transform( m_filters.begin(), m_filters.end(), matches.begin(), [&]( Filter const& filter ){ 14572 std::vector<TestCase const*> currentMatches; 14573 for( auto const& test : testCases ) 14574 if( isThrowSafe( test, config ) && filter.matches( test ) ) 14575 currentMatches.emplace_back( &test ); 14576 return FilterMatch{ filter.name(), currentMatches }; 14577 } ); 14578 return matches; 14579 } 14580 14581 const TestSpec::vectorStrings& TestSpec::getInvalidArgs() const{ 14582 return (m_invalidArgs); 14583 } 14584 14585 } 14586 // end catch_test_spec.cpp 14587 // start catch_test_spec_parser.cpp 14588 14589 namespace Catch { 14590 14591 TestSpecParser::TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {} 14592 14593 TestSpecParser& TestSpecParser::parse( std::string const& arg ) { 14594 m_mode = None; 14595 m_exclusion = false; 14596 m_arg = m_tagAliases->expandAliases( arg ); 14597 m_escapeChars.clear(); 14598 m_substring.reserve(m_arg.size()); 14599 m_patternName.reserve(m_arg.size()); 14600 m_realPatternPos = 0; 14601 14602 for( m_pos = 0; m_pos < m_arg.size(); ++m_pos ) 14603 //if visitChar fails 14604 if( !visitChar( m_arg[m_pos] ) ){ 14605 m_testSpec.m_invalidArgs.push_back(arg); 14606 break; 14607 } 14608 endMode(); 14609 return *this; 14610 } 14611 TestSpec TestSpecParser::testSpec() { 14612 addFilter(); 14613 return m_testSpec; 14614 } 14615 bool TestSpecParser::visitChar( char c ) { 14616 if( (m_mode != EscapedName) && (c == '\\') ) { 14617 escape(); 14618 addCharToPattern(c); 14619 return true; 14620 }else if((m_mode != EscapedName) && (c == ',') ) { 14621 return separate(); 14622 } 14623 14624 switch( m_mode ) { 14625 case None: 14626 if( processNoneChar( c ) ) 14627 return true; 14628 break; 14629 case Name: 14630 processNameChar( c ); 14631 break; 14632 case EscapedName: 14633 endMode(); 14634 addCharToPattern(c); 14635 return true; 14636 default: 14637 case Tag: 14638 case QuotedName: 14639 if( processOtherChar( c ) ) 14640 return true; 14641 break; 14642 } 14643 14644 m_substring += c; 14645 if( !isControlChar( c ) ) { 14646 m_patternName += c; 14647 m_realPatternPos++; 14648 } 14649 return true; 14650 } 14651 // Two of the processing methods return true to signal the caller to return 14652 // without adding the given character to the current pattern strings 14653 bool TestSpecParser::processNoneChar( char c ) { 14654 switch( c ) { 14655 case ' ': 14656 return true; 14657 case '~': 14658 m_exclusion = true; 14659 return false; 14660 case '[': 14661 startNewMode( Tag ); 14662 return false; 14663 case '"': 14664 startNewMode( QuotedName ); 14665 return false; 14666 default: 14667 startNewMode( Name ); 14668 return false; 14669 } 14670 } 14671 void TestSpecParser::processNameChar( char c ) { 14672 if( c == '[' ) { 14673 if( m_substring == "exclude:" ) 14674 m_exclusion = true; 14675 else 14676 endMode(); 14677 startNewMode( Tag ); 14678 } 14679 } 14680 bool TestSpecParser::processOtherChar( char c ) { 14681 if( !isControlChar( c ) ) 14682 return false; 14683 m_substring += c; 14684 endMode(); 14685 return true; 14686 } 14687 void TestSpecParser::startNewMode( Mode mode ) { 14688 m_mode = mode; 14689 } 14690 void TestSpecParser::endMode() { 14691 switch( m_mode ) { 14692 case Name: 14693 case QuotedName: 14694 return addNamePattern(); 14695 case Tag: 14696 return addTagPattern(); 14697 case EscapedName: 14698 revertBackToLastMode(); 14699 return; 14700 case None: 14701 default: 14702 return startNewMode( None ); 14703 } 14704 } 14705 void TestSpecParser::escape() { 14706 saveLastMode(); 14707 m_mode = EscapedName; 14708 m_escapeChars.push_back(m_realPatternPos); 14709 } 14710 bool TestSpecParser::isControlChar( char c ) const { 14711 switch( m_mode ) { 14712 default: 14713 return false; 14714 case None: 14715 return c == '~'; 14716 case Name: 14717 return c == '['; 14718 case EscapedName: 14719 return true; 14720 case QuotedName: 14721 return c == '"'; 14722 case Tag: 14723 return c == '[' || c == ']'; 14724 } 14725 } 14726 14727 void TestSpecParser::addFilter() { 14728 if( !m_currentFilter.m_patterns.empty() ) { 14729 m_testSpec.m_filters.push_back( m_currentFilter ); 14730 m_currentFilter = TestSpec::Filter(); 14731 } 14732 } 14733 14734 void TestSpecParser::saveLastMode() { 14735 lastMode = m_mode; 14736 } 14737 14738 void TestSpecParser::revertBackToLastMode() { 14739 m_mode = lastMode; 14740 } 14741 14742 bool TestSpecParser::separate() { 14743 if( (m_mode==QuotedName) || (m_mode==Tag) ){ 14744 //invalid argument, signal failure to previous scope. 14745 m_mode = None; 14746 m_pos = m_arg.size(); 14747 m_substring.clear(); 14748 m_patternName.clear(); 14749 m_realPatternPos = 0; 14750 return false; 14751 } 14752 endMode(); 14753 addFilter(); 14754 return true; //success 14755 } 14756 14757 std::string TestSpecParser::preprocessPattern() { 14758 std::string token = m_patternName; 14759 for (std::size_t i = 0; i < m_escapeChars.size(); ++i) 14760 token = token.substr(0, m_escapeChars[i] - i) + token.substr(m_escapeChars[i] - i + 1); 14761 m_escapeChars.clear(); 14762 if (startsWith(token, "exclude:")) { 14763 m_exclusion = true; 14764 token = token.substr(8); 14765 } 14766 14767 m_patternName.clear(); 14768 m_realPatternPos = 0; 14769 14770 return token; 14771 } 14772 14773 void TestSpecParser::addNamePattern() { 14774 auto token = preprocessPattern(); 14775 14776 if (!token.empty()) { 14777 TestSpec::PatternPtr pattern = std::make_shared<TestSpec::NamePattern>(token, m_substring); 14778 if (m_exclusion) 14779 pattern = std::make_shared<TestSpec::ExcludedPattern>(pattern); 14780 m_currentFilter.m_patterns.push_back(pattern); 14781 } 14782 m_substring.clear(); 14783 m_exclusion = false; 14784 m_mode = None; 14785 } 14786 14787 void TestSpecParser::addTagPattern() { 14788 auto token = preprocessPattern(); 14789 14790 if (!token.empty()) { 14791 // If the tag pattern is the "hide and tag" shorthand (e.g. [.foo]) 14792 // we have to create a separate hide tag and shorten the real one 14793 if (token.size() > 1 && token[0] == '.') { 14794 token.erase(token.begin()); 14795 TestSpec::PatternPtr pattern = std::make_shared<TestSpec::TagPattern>(".", m_substring); 14796 if (m_exclusion) { 14797 pattern = std::make_shared<TestSpec::ExcludedPattern>(pattern); 14798 } 14799 m_currentFilter.m_patterns.push_back(pattern); 14800 } 14801 14802 TestSpec::PatternPtr pattern = std::make_shared<TestSpec::TagPattern>(token, m_substring); 14803 14804 if (m_exclusion) { 14805 pattern = std::make_shared<TestSpec::ExcludedPattern>(pattern); 14806 } 14807 m_currentFilter.m_patterns.push_back(pattern); 14808 } 14809 m_substring.clear(); 14810 m_exclusion = false; 14811 m_mode = None; 14812 } 14813 14814 TestSpec parseTestSpec( std::string const& arg ) { 14815 return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec(); 14816 } 14817 14818 } // namespace Catch 14819 // end catch_test_spec_parser.cpp 14820 // start catch_timer.cpp 14821 14822 #include <chrono> 14823 14824 static const uint64_t nanosecondsInSecond = 1000000000; 14825 14826 namespace Catch { 14827 14828 auto getCurrentNanosecondsSinceEpoch() -> uint64_t { 14829 return std::chrono::duration_cast<std::chrono::nanoseconds>( std::chrono::high_resolution_clock::now().time_since_epoch() ).count(); 14830 } 14831 14832 namespace { 14833 auto estimateClockResolution() -> uint64_t { 14834 uint64_t sum = 0; 14835 static const uint64_t iterations = 1000000; 14836 14837 auto startTime = getCurrentNanosecondsSinceEpoch(); 14838 14839 for( std::size_t i = 0; i < iterations; ++i ) { 14840 14841 uint64_t ticks; 14842 uint64_t baseTicks = getCurrentNanosecondsSinceEpoch(); 14843 do { 14844 ticks = getCurrentNanosecondsSinceEpoch(); 14845 } while( ticks == baseTicks ); 14846 14847 auto delta = ticks - baseTicks; 14848 sum += delta; 14849 14850 // If we have been calibrating for over 3 seconds -- the clock 14851 // is terrible and we should move on. 14852 // TBD: How to signal that the measured resolution is probably wrong? 14853 if (ticks > startTime + 3 * nanosecondsInSecond) { 14854 return sum / ( i + 1u ); 14855 } 14856 } 14857 14858 // We're just taking the mean, here. To do better we could take the std. dev and exclude outliers 14859 // - and potentially do more iterations if there's a high variance. 14860 return sum/iterations; 14861 } 14862 } 14863 auto getEstimatedClockResolution() -> uint64_t { 14864 static auto s_resolution = estimateClockResolution(); 14865 return s_resolution; 14866 } 14867 14868 void Timer::start() { 14869 m_nanoseconds = getCurrentNanosecondsSinceEpoch(); 14870 } 14871 auto Timer::getElapsedNanoseconds() const -> uint64_t { 14872 return getCurrentNanosecondsSinceEpoch() - m_nanoseconds; 14873 } 14874 auto Timer::getElapsedMicroseconds() const -> uint64_t { 14875 return getElapsedNanoseconds()/1000; 14876 } 14877 auto Timer::getElapsedMilliseconds() const -> unsigned int { 14878 return static_cast<unsigned int>(getElapsedMicroseconds()/1000); 14879 } 14880 auto Timer::getElapsedSeconds() const -> double { 14881 return getElapsedMicroseconds()/1000000.0; 14882 } 14883 14884 } // namespace Catch 14885 // end catch_timer.cpp 14886 // start catch_tostring.cpp 14887 14888 #if defined(__clang__) 14889 # pragma clang diagnostic push 14890 # pragma clang diagnostic ignored "-Wexit-time-destructors" 14891 # pragma clang diagnostic ignored "-Wglobal-constructors" 14892 #endif 14893 14894 // Enable specific decls locally 14895 #if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) 14896 #define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER 14897 #endif 14898 14899 #include <cmath> 14900 #include <iomanip> 14901 14902 namespace Catch { 14903 14904 namespace Detail { 14905 14906 const std::string unprintableString = "{?}"; 14907 14908 namespace { 14909 const int hexThreshold = 255; 14910 14911 struct Endianness { 14912 enum Arch { Big, Little }; 14913 14914 static Arch which() { 14915 int one = 1; 14916 // If the lowest byte we read is non-zero, we can assume 14917 // that little endian format is used. 14918 auto value = *reinterpret_cast<char*>(&one); 14919 return value ? Little : Big; 14920 } 14921 }; 14922 } 14923 14924 std::string rawMemoryToString( const void *object, std::size_t size ) { 14925 // Reverse order for little endian architectures 14926 int i = 0, end = static_cast<int>( size ), inc = 1; 14927 if( Endianness::which() == Endianness::Little ) { 14928 i = end-1; 14929 end = inc = -1; 14930 } 14931 14932 unsigned char const *bytes = static_cast<unsigned char const *>(object); 14933 ReusableStringStream rss; 14934 rss << "0x" << std::setfill('0') << std::hex; 14935 for( ; i != end; i += inc ) 14936 rss << std::setw(2) << static_cast<unsigned>(bytes[i]); 14937 return rss.str(); 14938 } 14939 } 14940 14941 template<typename T> 14942 std::string fpToString( T value, int precision ) { 14943 if (Catch::isnan(value)) { 14944 return "nan"; 14945 } 14946 14947 ReusableStringStream rss; 14948 rss << std::setprecision( precision ) 14949 << std::fixed 14950 << value; 14951 std::string d = rss.str(); 14952 std::size_t i = d.find_last_not_of( '0' ); 14953 if( i != std::string::npos && i != d.size()-1 ) { 14954 if( d[i] == '.' ) 14955 i++; 14956 d = d.substr( 0, i+1 ); 14957 } 14958 return d; 14959 } 14960 14961 //// ======================================================= //// 14962 // 14963 // Out-of-line defs for full specialization of StringMaker 14964 // 14965 //// ======================================================= //// 14966 14967 std::string StringMaker<std::string>::convert(const std::string& str) { 14968 if (!getCurrentContext().getConfig()->showInvisibles()) { 14969 return '"' + str + '"'; 14970 } 14971 14972 std::string s("\""); 14973 for (char c : str) { 14974 switch (c) { 14975 case '\n': 14976 s.append("\\n"); 14977 break; 14978 case '\t': 14979 s.append("\\t"); 14980 break; 14981 default: 14982 s.push_back(c); 14983 break; 14984 } 14985 } 14986 s.append("\""); 14987 return s; 14988 } 14989 14990 #ifdef CATCH_CONFIG_CPP17_STRING_VIEW 14991 std::string StringMaker<std::string_view>::convert(std::string_view str) { 14992 return ::Catch::Detail::stringify(std::string{ str }); 14993 } 14994 #endif 14995 14996 std::string StringMaker<char const*>::convert(char const* str) { 14997 if (str) { 14998 return ::Catch::Detail::stringify(std::string{ str }); 14999 } else { 15000 return{ "{null string}" }; 15001 } 15002 } 15003 std::string StringMaker<char*>::convert(char* str) { 15004 if (str) { 15005 return ::Catch::Detail::stringify(std::string{ str }); 15006 } else { 15007 return{ "{null string}" }; 15008 } 15009 } 15010 15011 #ifdef CATCH_CONFIG_WCHAR 15012 std::string StringMaker<std::wstring>::convert(const std::wstring& wstr) { 15013 std::string s; 15014 s.reserve(wstr.size()); 15015 for (auto c : wstr) { 15016 s += (c <= 0xff) ? static_cast<char>(c) : '?'; 15017 } 15018 return ::Catch::Detail::stringify(s); 15019 } 15020 15021 # ifdef CATCH_CONFIG_CPP17_STRING_VIEW 15022 std::string StringMaker<std::wstring_view>::convert(std::wstring_view str) { 15023 return StringMaker<std::wstring>::convert(std::wstring(str)); 15024 } 15025 # endif 15026 15027 std::string StringMaker<wchar_t const*>::convert(wchar_t const * str) { 15028 if (str) { 15029 return ::Catch::Detail::stringify(std::wstring{ str }); 15030 } else { 15031 return{ "{null string}" }; 15032 } 15033 } 15034 std::string StringMaker<wchar_t *>::convert(wchar_t * str) { 15035 if (str) { 15036 return ::Catch::Detail::stringify(std::wstring{ str }); 15037 } else { 15038 return{ "{null string}" }; 15039 } 15040 } 15041 #endif 15042 15043 #if defined(CATCH_CONFIG_CPP17_BYTE) 15044 #include <cstddef> 15045 std::string StringMaker<std::byte>::convert(std::byte value) { 15046 return ::Catch::Detail::stringify(std::to_integer<unsigned long long>(value)); 15047 } 15048 #endif // defined(CATCH_CONFIG_CPP17_BYTE) 15049 15050 std::string StringMaker<int>::convert(int value) { 15051 return ::Catch::Detail::stringify(static_cast<long long>(value)); 15052 } 15053 std::string StringMaker<long>::convert(long value) { 15054 return ::Catch::Detail::stringify(static_cast<long long>(value)); 15055 } 15056 std::string StringMaker<long long>::convert(long long value) { 15057 ReusableStringStream rss; 15058 rss << value; 15059 if (value > Detail::hexThreshold) { 15060 rss << " (0x" << std::hex << value << ')'; 15061 } 15062 return rss.str(); 15063 } 15064 15065 std::string StringMaker<unsigned int>::convert(unsigned int value) { 15066 return ::Catch::Detail::stringify(static_cast<unsigned long long>(value)); 15067 } 15068 std::string StringMaker<unsigned long>::convert(unsigned long value) { 15069 return ::Catch::Detail::stringify(static_cast<unsigned long long>(value)); 15070 } 15071 std::string StringMaker<unsigned long long>::convert(unsigned long long value) { 15072 ReusableStringStream rss; 15073 rss << value; 15074 if (value > Detail::hexThreshold) { 15075 rss << " (0x" << std::hex << value << ')'; 15076 } 15077 return rss.str(); 15078 } 15079 15080 std::string StringMaker<bool>::convert(bool b) { 15081 return b ? "true" : "false"; 15082 } 15083 15084 std::string StringMaker<signed char>::convert(signed char value) { 15085 if (value == '\r') { 15086 return "'\\r'"; 15087 } else if (value == '\f') { 15088 return "'\\f'"; 15089 } else if (value == '\n') { 15090 return "'\\n'"; 15091 } else if (value == '\t') { 15092 return "'\\t'"; 15093 } else if ('\0' <= value && value < ' ') { 15094 return ::Catch::Detail::stringify(static_cast<unsigned int>(value)); 15095 } else { 15096 char chstr[] = "' '"; 15097 chstr[1] = value; 15098 return chstr; 15099 } 15100 } 15101 std::string StringMaker<char>::convert(char c) { 15102 return ::Catch::Detail::stringify(static_cast<signed char>(c)); 15103 } 15104 std::string StringMaker<unsigned char>::convert(unsigned char c) { 15105 return ::Catch::Detail::stringify(static_cast<char>(c)); 15106 } 15107 15108 std::string StringMaker<std::nullptr_t>::convert(std::nullptr_t) { 15109 return "nullptr"; 15110 } 15111 15112 int StringMaker<float>::precision = 5; 15113 15114 std::string StringMaker<float>::convert(float value) { 15115 return fpToString(value, precision) + 'f'; 15116 } 15117 15118 int StringMaker<double>::precision = 10; 15119 15120 std::string StringMaker<double>::convert(double value) { 15121 return fpToString(value, precision); 15122 } 15123 15124 std::string ratio_string<std::atto>::symbol() { return "a"; } 15125 std::string ratio_string<std::femto>::symbol() { return "f"; } 15126 std::string ratio_string<std::pico>::symbol() { return "p"; } 15127 std::string ratio_string<std::nano>::symbol() { return "n"; } 15128 std::string ratio_string<std::micro>::symbol() { return "u"; } 15129 std::string ratio_string<std::milli>::symbol() { return "m"; } 15130 15131 } // end namespace Catch 15132 15133 #if defined(__clang__) 15134 # pragma clang diagnostic pop 15135 #endif 15136 15137 // end catch_tostring.cpp 15138 // start catch_totals.cpp 15139 15140 namespace Catch { 15141 15142 Counts Counts::operator - ( Counts const& other ) const { 15143 Counts diff; 15144 diff.passed = passed - other.passed; 15145 diff.failed = failed - other.failed; 15146 diff.failedButOk = failedButOk - other.failedButOk; 15147 return diff; 15148 } 15149 15150 Counts& Counts::operator += ( Counts const& other ) { 15151 passed += other.passed; 15152 failed += other.failed; 15153 failedButOk += other.failedButOk; 15154 return *this; 15155 } 15156 15157 std::size_t Counts::total() const { 15158 return passed + failed + failedButOk; 15159 } 15160 bool Counts::allPassed() const { 15161 return failed == 0 && failedButOk == 0; 15162 } 15163 bool Counts::allOk() const { 15164 return failed == 0; 15165 } 15166 15167 Totals Totals::operator - ( Totals const& other ) const { 15168 Totals diff; 15169 diff.assertions = assertions - other.assertions; 15170 diff.testCases = testCases - other.testCases; 15171 return diff; 15172 } 15173 15174 Totals& Totals::operator += ( Totals const& other ) { 15175 assertions += other.assertions; 15176 testCases += other.testCases; 15177 return *this; 15178 } 15179 15180 Totals Totals::delta( Totals const& prevTotals ) const { 15181 Totals diff = *this - prevTotals; 15182 if( diff.assertions.failed > 0 ) 15183 ++diff.testCases.failed; 15184 else if( diff.assertions.failedButOk > 0 ) 15185 ++diff.testCases.failedButOk; 15186 else 15187 ++diff.testCases.passed; 15188 return diff; 15189 } 15190 15191 } 15192 // end catch_totals.cpp 15193 // start catch_uncaught_exceptions.cpp 15194 15195 #include <exception> 15196 15197 namespace Catch { 15198 bool uncaught_exceptions() { 15199 #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 15200 return false; 15201 #elif defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) 15202 return std::uncaught_exceptions() > 0; 15203 #else 15204 return std::uncaught_exception(); 15205 #endif 15206 } 15207 } // end namespace Catch 15208 // end catch_uncaught_exceptions.cpp 15209 // start catch_version.cpp 15210 15211 #include <ostream> 15212 15213 namespace Catch { 15214 15215 Version::Version 15216 ( unsigned int _majorVersion, 15217 unsigned int _minorVersion, 15218 unsigned int _patchNumber, 15219 char const * const _branchName, 15220 unsigned int _buildNumber ) 15221 : majorVersion( _majorVersion ), 15222 minorVersion( _minorVersion ), 15223 patchNumber( _patchNumber ), 15224 branchName( _branchName ), 15225 buildNumber( _buildNumber ) 15226 {} 15227 15228 std::ostream& operator << ( std::ostream& os, Version const& version ) { 15229 os << version.majorVersion << '.' 15230 << version.minorVersion << '.' 15231 << version.patchNumber; 15232 // branchName is never null -> 0th char is \0 if it is empty 15233 if (version.branchName[0]) { 15234 os << '-' << version.branchName 15235 << '.' << version.buildNumber; 15236 } 15237 return os; 15238 } 15239 15240 Version const& libraryVersion() { 15241 static Version version( 2, 13, 0, "", 0 ); 15242 return version; 15243 } 15244 15245 } 15246 // end catch_version.cpp 15247 // start catch_wildcard_pattern.cpp 15248 15249 namespace Catch { 15250 15251 WildcardPattern::WildcardPattern( std::string const& pattern, 15252 CaseSensitive::Choice caseSensitivity ) 15253 : m_caseSensitivity( caseSensitivity ), 15254 m_pattern( normaliseString( pattern ) ) 15255 { 15256 if( startsWith( m_pattern, '*' ) ) { 15257 m_pattern = m_pattern.substr( 1 ); 15258 m_wildcard = WildcardAtStart; 15259 } 15260 if( endsWith( m_pattern, '*' ) ) { 15261 m_pattern = m_pattern.substr( 0, m_pattern.size()-1 ); 15262 m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd ); 15263 } 15264 } 15265 15266 bool WildcardPattern::matches( std::string const& str ) const { 15267 switch( m_wildcard ) { 15268 case NoWildcard: 15269 return m_pattern == normaliseString( str ); 15270 case WildcardAtStart: 15271 return endsWith( normaliseString( str ), m_pattern ); 15272 case WildcardAtEnd: 15273 return startsWith( normaliseString( str ), m_pattern ); 15274 case WildcardAtBothEnds: 15275 return contains( normaliseString( str ), m_pattern ); 15276 default: 15277 CATCH_INTERNAL_ERROR( "Unknown enum" ); 15278 } 15279 } 15280 15281 std::string WildcardPattern::normaliseString( std::string const& str ) const { 15282 return trim( m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str ); 15283 } 15284 } 15285 // end catch_wildcard_pattern.cpp 15286 // start catch_xmlwriter.cpp 15287 15288 #include <iomanip> 15289 #include <type_traits> 15290 15291 namespace Catch { 15292 15293 namespace { 15294 15295 size_t trailingBytes(unsigned char c) { 15296 if ((c & 0xE0) == 0xC0) { 15297 return 2; 15298 } 15299 if ((c & 0xF0) == 0xE0) { 15300 return 3; 15301 } 15302 if ((c & 0xF8) == 0xF0) { 15303 return 4; 15304 } 15305 CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered"); 15306 } 15307 15308 uint32_t headerValue(unsigned char c) { 15309 if ((c & 0xE0) == 0xC0) { 15310 return c & 0x1F; 15311 } 15312 if ((c & 0xF0) == 0xE0) { 15313 return c & 0x0F; 15314 } 15315 if ((c & 0xF8) == 0xF0) { 15316 return c & 0x07; 15317 } 15318 CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered"); 15319 } 15320 15321 void hexEscapeChar(std::ostream& os, unsigned char c) { 15322 std::ios_base::fmtflags f(os.flags()); 15323 os << "\\x" 15324 << std::uppercase << std::hex << std::setfill('0') << std::setw(2) 15325 << static_cast<int>(c); 15326 os.flags(f); 15327 } 15328 15329 bool shouldNewline(XmlFormatting fmt) { 15330 return !!(static_cast<std::underlying_type<XmlFormatting>::type>(fmt & XmlFormatting::Newline)); 15331 } 15332 15333 bool shouldIndent(XmlFormatting fmt) { 15334 return !!(static_cast<std::underlying_type<XmlFormatting>::type>(fmt & XmlFormatting::Indent)); 15335 } 15336 15337 } // anonymous namespace 15338 15339 XmlFormatting operator | (XmlFormatting lhs, XmlFormatting rhs) { 15340 return static_cast<XmlFormatting>( 15341 static_cast<std::underlying_type<XmlFormatting>::type>(lhs) | 15342 static_cast<std::underlying_type<XmlFormatting>::type>(rhs) 15343 ); 15344 } 15345 15346 XmlFormatting operator & (XmlFormatting lhs, XmlFormatting rhs) { 15347 return static_cast<XmlFormatting>( 15348 static_cast<std::underlying_type<XmlFormatting>::type>(lhs) & 15349 static_cast<std::underlying_type<XmlFormatting>::type>(rhs) 15350 ); 15351 } 15352 15353 XmlEncode::XmlEncode( std::string const& str, ForWhat forWhat ) 15354 : m_str( str ), 15355 m_forWhat( forWhat ) 15356 {} 15357 15358 void XmlEncode::encodeTo( std::ostream& os ) const { 15359 // Apostrophe escaping not necessary if we always use " to write attributes 15360 // (see: http://www.w3.org/TR/xml/#syntax) 15361 15362 for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) { 15363 unsigned char c = m_str[idx]; 15364 switch (c) { 15365 case '<': os << "<"; break; 15366 case '&': os << "&"; break; 15367 15368 case '>': 15369 // See: http://www.w3.org/TR/xml/#syntax 15370 if (idx > 2 && m_str[idx - 1] == ']' && m_str[idx - 2] == ']') 15371 os << ">"; 15372 else 15373 os << c; 15374 break; 15375 15376 case '\"': 15377 if (m_forWhat == ForAttributes) 15378 os << """; 15379 else 15380 os << c; 15381 break; 15382 15383 default: 15384 // Check for control characters and invalid utf-8 15385 15386 // Escape control characters in standard ascii 15387 // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0 15388 if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) { 15389 hexEscapeChar(os, c); 15390 break; 15391 } 15392 15393 // Plain ASCII: Write it to stream 15394 if (c < 0x7F) { 15395 os << c; 15396 break; 15397 } 15398 15399 // UTF-8 territory 15400 // Check if the encoding is valid and if it is not, hex escape bytes. 15401 // Important: We do not check the exact decoded values for validity, only the encoding format 15402 // First check that this bytes is a valid lead byte: 15403 // This means that it is not encoded as 1111 1XXX 15404 // Or as 10XX XXXX 15405 if (c < 0xC0 || 15406 c >= 0xF8) { 15407 hexEscapeChar(os, c); 15408 break; 15409 } 15410 15411 auto encBytes = trailingBytes(c); 15412 // Are there enough bytes left to avoid accessing out-of-bounds memory? 15413 if (idx + encBytes - 1 >= m_str.size()) { 15414 hexEscapeChar(os, c); 15415 break; 15416 } 15417 // The header is valid, check data 15418 // The next encBytes bytes must together be a valid utf-8 15419 // This means: bitpattern 10XX XXXX and the extracted value is sane (ish) 15420 bool valid = true; 15421 uint32_t value = headerValue(c); 15422 for (std::size_t n = 1; n < encBytes; ++n) { 15423 unsigned char nc = m_str[idx + n]; 15424 valid &= ((nc & 0xC0) == 0x80); 15425 value = (value << 6) | (nc & 0x3F); 15426 } 15427 15428 if ( 15429 // Wrong bit pattern of following bytes 15430 (!valid) || 15431 // Overlong encodings 15432 (value < 0x80) || 15433 (0x80 <= value && value < 0x800 && encBytes > 2) || 15434 (0x800 < value && value < 0x10000 && encBytes > 3) || 15435 // Encoded value out of range 15436 (value >= 0x110000) 15437 ) { 15438 hexEscapeChar(os, c); 15439 break; 15440 } 15441 15442 // If we got here, this is in fact a valid(ish) utf-8 sequence 15443 for (std::size_t n = 0; n < encBytes; ++n) { 15444 os << m_str[idx + n]; 15445 } 15446 idx += encBytes - 1; 15447 break; 15448 } 15449 } 15450 } 15451 15452 std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) { 15453 xmlEncode.encodeTo( os ); 15454 return os; 15455 } 15456 15457 XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer, XmlFormatting fmt ) 15458 : m_writer( writer ), 15459 m_fmt(fmt) 15460 {} 15461 15462 XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) noexcept 15463 : m_writer( other.m_writer ), 15464 m_fmt(other.m_fmt) 15465 { 15466 other.m_writer = nullptr; 15467 other.m_fmt = XmlFormatting::None; 15468 } 15469 XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) noexcept { 15470 if ( m_writer ) { 15471 m_writer->endElement(); 15472 } 15473 m_writer = other.m_writer; 15474 other.m_writer = nullptr; 15475 m_fmt = other.m_fmt; 15476 other.m_fmt = XmlFormatting::None; 15477 return *this; 15478 } 15479 15480 XmlWriter::ScopedElement::~ScopedElement() { 15481 if (m_writer) { 15482 m_writer->endElement(m_fmt); 15483 } 15484 } 15485 15486 XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText( std::string const& text, XmlFormatting fmt ) { 15487 m_writer->writeText( text, fmt ); 15488 return *this; 15489 } 15490 15491 XmlWriter::XmlWriter( std::ostream& os ) : m_os( os ) 15492 { 15493 writeDeclaration(); 15494 } 15495 15496 XmlWriter::~XmlWriter() { 15497 while (!m_tags.empty()) { 15498 endElement(); 15499 } 15500 newlineIfNecessary(); 15501 } 15502 15503 XmlWriter& XmlWriter::startElement( std::string const& name, XmlFormatting fmt ) { 15504 ensureTagClosed(); 15505 newlineIfNecessary(); 15506 if (shouldIndent(fmt)) { 15507 m_os << m_indent; 15508 m_indent += " "; 15509 } 15510 m_os << '<' << name; 15511 m_tags.push_back( name ); 15512 m_tagIsOpen = true; 15513 applyFormatting(fmt); 15514 return *this; 15515 } 15516 15517 XmlWriter::ScopedElement XmlWriter::scopedElement( std::string const& name, XmlFormatting fmt ) { 15518 ScopedElement scoped( this, fmt ); 15519 startElement( name, fmt ); 15520 return scoped; 15521 } 15522 15523 XmlWriter& XmlWriter::endElement(XmlFormatting fmt) { 15524 m_indent = m_indent.substr(0, m_indent.size() - 2); 15525 15526 if( m_tagIsOpen ) { 15527 m_os << "/>"; 15528 m_tagIsOpen = false; 15529 } else { 15530 newlineIfNecessary(); 15531 if (shouldIndent(fmt)) { 15532 m_os << m_indent; 15533 } 15534 m_os << "</" << m_tags.back() << ">"; 15535 } 15536 m_os << std::flush; 15537 applyFormatting(fmt); 15538 m_tags.pop_back(); 15539 return *this; 15540 } 15541 15542 XmlWriter& XmlWriter::writeAttribute( std::string const& name, std::string const& attribute ) { 15543 if( !name.empty() && !attribute.empty() ) 15544 m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"'; 15545 return *this; 15546 } 15547 15548 XmlWriter& XmlWriter::writeAttribute( std::string const& name, bool attribute ) { 15549 m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"'; 15550 return *this; 15551 } 15552 15553 XmlWriter& XmlWriter::writeText( std::string const& text, XmlFormatting fmt) { 15554 if( !text.empty() ){ 15555 bool tagWasOpen = m_tagIsOpen; 15556 ensureTagClosed(); 15557 if (tagWasOpen && shouldIndent(fmt)) { 15558 m_os << m_indent; 15559 } 15560 m_os << XmlEncode( text ); 15561 applyFormatting(fmt); 15562 } 15563 return *this; 15564 } 15565 15566 XmlWriter& XmlWriter::writeComment( std::string const& text, XmlFormatting fmt) { 15567 ensureTagClosed(); 15568 if (shouldIndent(fmt)) { 15569 m_os << m_indent; 15570 } 15571 m_os << "<!--" << text << "-->"; 15572 applyFormatting(fmt); 15573 return *this; 15574 } 15575 15576 void XmlWriter::writeStylesheetRef( std::string const& url ) { 15577 m_os << "<?xml-stylesheet type=\"text/xsl\" href=\"" << url << "\"?>\n"; 15578 } 15579 15580 XmlWriter& XmlWriter::writeBlankLine() { 15581 ensureTagClosed(); 15582 m_os << '\n'; 15583 return *this; 15584 } 15585 15586 void XmlWriter::ensureTagClosed() { 15587 if( m_tagIsOpen ) { 15588 m_os << '>' << std::flush; 15589 newlineIfNecessary(); 15590 m_tagIsOpen = false; 15591 } 15592 } 15593 15594 void XmlWriter::applyFormatting(XmlFormatting fmt) { 15595 m_needsNewline = shouldNewline(fmt); 15596 } 15597 15598 void XmlWriter::writeDeclaration() { 15599 m_os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; 15600 } 15601 15602 void XmlWriter::newlineIfNecessary() { 15603 if( m_needsNewline ) { 15604 m_os << std::endl; 15605 m_needsNewline = false; 15606 } 15607 } 15608 } 15609 // end catch_xmlwriter.cpp 15610 // start catch_reporter_bases.cpp 15611 15612 #include <cstring> 15613 #include <cfloat> 15614 #include <cstdio> 15615 #include <cassert> 15616 #include <memory> 15617 15618 namespace Catch { 15619 void prepareExpandedExpression(AssertionResult& result) { 15620 result.getExpandedExpression(); 15621 } 15622 15623 // Because formatting using c++ streams is stateful, drop down to C is required 15624 // Alternatively we could use stringstream, but its performance is... not good. 15625 std::string getFormattedDuration( double duration ) { 15626 // Max exponent + 1 is required to represent the whole part 15627 // + 1 for decimal point 15628 // + 3 for the 3 decimal places 15629 // + 1 for null terminator 15630 const std::size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1; 15631 char buffer[maxDoubleSize]; 15632 15633 // Save previous errno, to prevent sprintf from overwriting it 15634 ErrnoGuard guard; 15635 #ifdef _MSC_VER 15636 sprintf_s(buffer, "%.3f", duration); 15637 #else 15638 std::sprintf(buffer, "%.3f", duration); 15639 #endif 15640 return std::string(buffer); 15641 } 15642 15643 bool shouldShowDuration( IConfig const& config, double duration ) { 15644 if ( config.showDurations() == ShowDurations::Always ) { 15645 return true; 15646 } 15647 if ( config.showDurations() == ShowDurations::Never ) { 15648 return false; 15649 } 15650 const double min = config.minDuration(); 15651 return min >= 0 && duration >= min; 15652 } 15653 15654 std::string serializeFilters( std::vector<std::string> const& container ) { 15655 ReusableStringStream oss; 15656 bool first = true; 15657 for (auto&& filter : container) 15658 { 15659 if (!first) 15660 oss << ' '; 15661 else 15662 first = false; 15663 15664 oss << filter; 15665 } 15666 return oss.str(); 15667 } 15668 15669 TestEventListenerBase::TestEventListenerBase(ReporterConfig const & _config) 15670 :StreamingReporterBase(_config) {} 15671 15672 std::set<Verbosity> TestEventListenerBase::getSupportedVerbosities() { 15673 return { Verbosity::Quiet, Verbosity::Normal, Verbosity::High }; 15674 } 15675 15676 void TestEventListenerBase::assertionStarting(AssertionInfo const &) {} 15677 15678 bool TestEventListenerBase::assertionEnded(AssertionStats const &) { 15679 return false; 15680 } 15681 15682 } // end namespace Catch 15683 // end catch_reporter_bases.cpp 15684 // start catch_reporter_compact.cpp 15685 15686 namespace { 15687 15688 #ifdef CATCH_PLATFORM_MAC 15689 const char* failedString() { return "FAILED"; } 15690 const char* passedString() { return "PASSED"; } 15691 #else 15692 const char* failedString() { return "failed"; } 15693 const char* passedString() { return "passed"; } 15694 #endif 15695 15696 // Colour::LightGrey 15697 Catch::Colour::Code dimColour() { return Catch::Colour::FileName; } 15698 15699 std::string bothOrAll( std::size_t count ) { 15700 return count == 1 ? std::string() : 15701 count == 2 ? "both " : "all " ; 15702 } 15703 15704 } // anon namespace 15705 15706 namespace Catch { 15707 namespace { 15708 // Colour, message variants: 15709 // - white: No tests ran. 15710 // - red: Failed [both/all] N test cases, failed [both/all] M assertions. 15711 // - white: Passed [both/all] N test cases (no assertions). 15712 // - red: Failed N tests cases, failed M assertions. 15713 // - green: Passed [both/all] N tests cases with M assertions. 15714 void printTotals(std::ostream& out, const Totals& totals) { 15715 if (totals.testCases.total() == 0) { 15716 out << "No tests ran."; 15717 } else if (totals.testCases.failed == totals.testCases.total()) { 15718 Colour colour(Colour::ResultError); 15719 const std::string qualify_assertions_failed = 15720 totals.assertions.failed == totals.assertions.total() ? 15721 bothOrAll(totals.assertions.failed) : std::string(); 15722 out << 15723 "Failed " << bothOrAll(totals.testCases.failed) 15724 << pluralise(totals.testCases.failed, "test case") << ", " 15725 "failed " << qualify_assertions_failed << 15726 pluralise(totals.assertions.failed, "assertion") << '.'; 15727 } else if (totals.assertions.total() == 0) { 15728 out << 15729 "Passed " << bothOrAll(totals.testCases.total()) 15730 << pluralise(totals.testCases.total(), "test case") 15731 << " (no assertions)."; 15732 } else if (totals.assertions.failed) { 15733 Colour colour(Colour::ResultError); 15734 out << 15735 "Failed " << pluralise(totals.testCases.failed, "test case") << ", " 15736 "failed " << pluralise(totals.assertions.failed, "assertion") << '.'; 15737 } else { 15738 Colour colour(Colour::ResultSuccess); 15739 out << 15740 "Passed " << bothOrAll(totals.testCases.passed) 15741 << pluralise(totals.testCases.passed, "test case") << 15742 " with " << pluralise(totals.assertions.passed, "assertion") << '.'; 15743 } 15744 } 15745 15746 // Implementation of CompactReporter formatting 15747 class AssertionPrinter { 15748 public: 15749 AssertionPrinter& operator= (AssertionPrinter const&) = delete; 15750 AssertionPrinter(AssertionPrinter const&) = delete; 15751 AssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages) 15752 : stream(_stream) 15753 , result(_stats.assertionResult) 15754 , messages(_stats.infoMessages) 15755 , itMessage(_stats.infoMessages.begin()) 15756 , printInfoMessages(_printInfoMessages) {} 15757 15758 void print() { 15759 printSourceInfo(); 15760 15761 itMessage = messages.begin(); 15762 15763 switch (result.getResultType()) { 15764 case ResultWas::Ok: 15765 printResultType(Colour::ResultSuccess, passedString()); 15766 printOriginalExpression(); 15767 printReconstructedExpression(); 15768 if (!result.hasExpression()) 15769 printRemainingMessages(Colour::None); 15770 else 15771 printRemainingMessages(); 15772 break; 15773 case ResultWas::ExpressionFailed: 15774 if (result.isOk()) 15775 printResultType(Colour::ResultSuccess, failedString() + std::string(" - but was ok")); 15776 else 15777 printResultType(Colour::Error, failedString()); 15778 printOriginalExpression(); 15779 printReconstructedExpression(); 15780 printRemainingMessages(); 15781 break; 15782 case ResultWas::ThrewException: 15783 printResultType(Colour::Error, failedString()); 15784 printIssue("unexpected exception with message:"); 15785 printMessage(); 15786 printExpressionWas(); 15787 printRemainingMessages(); 15788 break; 15789 case ResultWas::FatalErrorCondition: 15790 printResultType(Colour::Error, failedString()); 15791 printIssue("fatal error condition with message:"); 15792 printMessage(); 15793 printExpressionWas(); 15794 printRemainingMessages(); 15795 break; 15796 case ResultWas::DidntThrowException: 15797 printResultType(Colour::Error, failedString()); 15798 printIssue("expected exception, got none"); 15799 printExpressionWas(); 15800 printRemainingMessages(); 15801 break; 15802 case ResultWas::Info: 15803 printResultType(Colour::None, "info"); 15804 printMessage(); 15805 printRemainingMessages(); 15806 break; 15807 case ResultWas::Warning: 15808 printResultType(Colour::None, "warning"); 15809 printMessage(); 15810 printRemainingMessages(); 15811 break; 15812 case ResultWas::ExplicitFailure: 15813 printResultType(Colour::Error, failedString()); 15814 printIssue("explicitly"); 15815 printRemainingMessages(Colour::None); 15816 break; 15817 // These cases are here to prevent compiler warnings 15818 case ResultWas::Unknown: 15819 case ResultWas::FailureBit: 15820 case ResultWas::Exception: 15821 printResultType(Colour::Error, "** internal error **"); 15822 break; 15823 } 15824 } 15825 15826 private: 15827 void printSourceInfo() const { 15828 Colour colourGuard(Colour::FileName); 15829 stream << result.getSourceInfo() << ':'; 15830 } 15831 15832 void printResultType(Colour::Code colour, std::string const& passOrFail) const { 15833 if (!passOrFail.empty()) { 15834 { 15835 Colour colourGuard(colour); 15836 stream << ' ' << passOrFail; 15837 } 15838 stream << ':'; 15839 } 15840 } 15841 15842 void printIssue(std::string const& issue) const { 15843 stream << ' ' << issue; 15844 } 15845 15846 void printExpressionWas() { 15847 if (result.hasExpression()) { 15848 stream << ';'; 15849 { 15850 Colour colour(dimColour()); 15851 stream << " expression was:"; 15852 } 15853 printOriginalExpression(); 15854 } 15855 } 15856 15857 void printOriginalExpression() const { 15858 if (result.hasExpression()) { 15859 stream << ' ' << result.getExpression(); 15860 } 15861 } 15862 15863 void printReconstructedExpression() const { 15864 if (result.hasExpandedExpression()) { 15865 { 15866 Colour colour(dimColour()); 15867 stream << " for: "; 15868 } 15869 stream << result.getExpandedExpression(); 15870 } 15871 } 15872 15873 void printMessage() { 15874 if (itMessage != messages.end()) { 15875 stream << " '" << itMessage->message << '\''; 15876 ++itMessage; 15877 } 15878 } 15879 15880 void printRemainingMessages(Colour::Code colour = dimColour()) { 15881 if (itMessage == messages.end()) 15882 return; 15883 15884 const auto itEnd = messages.cend(); 15885 const auto N = static_cast<std::size_t>(std::distance(itMessage, itEnd)); 15886 15887 { 15888 Colour colourGuard(colour); 15889 stream << " with " << pluralise(N, "message") << ':'; 15890 } 15891 15892 while (itMessage != itEnd) { 15893 // If this assertion is a warning ignore any INFO messages 15894 if (printInfoMessages || itMessage->type != ResultWas::Info) { 15895 printMessage(); 15896 if (itMessage != itEnd) { 15897 Colour colourGuard(dimColour()); 15898 stream << " and"; 15899 } 15900 continue; 15901 } 15902 ++itMessage; 15903 } 15904 } 15905 15906 private: 15907 std::ostream& stream; 15908 AssertionResult const& result; 15909 std::vector<MessageInfo> messages; 15910 std::vector<MessageInfo>::const_iterator itMessage; 15911 bool printInfoMessages; 15912 }; 15913 15914 } // anon namespace 15915 15916 std::string CompactReporter::getDescription() { 15917 return "Reports test results on a single line, suitable for IDEs"; 15918 } 15919 15920 void CompactReporter::noMatchingTestCases( std::string const& spec ) { 15921 stream << "No test cases matched '" << spec << '\'' << std::endl; 15922 } 15923 15924 void CompactReporter::assertionStarting( AssertionInfo const& ) {} 15925 15926 bool CompactReporter::assertionEnded( AssertionStats const& _assertionStats ) { 15927 AssertionResult const& result = _assertionStats.assertionResult; 15928 15929 bool printInfoMessages = true; 15930 15931 // Drop out if result was successful and we're not printing those 15932 if( !m_config->includeSuccessfulResults() && result.isOk() ) { 15933 if( result.getResultType() != ResultWas::Warning ) 15934 return false; 15935 printInfoMessages = false; 15936 } 15937 15938 AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); 15939 printer.print(); 15940 15941 stream << std::endl; 15942 return true; 15943 } 15944 15945 void CompactReporter::sectionEnded(SectionStats const& _sectionStats) { 15946 double dur = _sectionStats.durationInSeconds; 15947 if ( shouldShowDuration( *m_config, dur ) ) { 15948 stream << getFormattedDuration( dur ) << " s: " << _sectionStats.sectionInfo.name << std::endl; 15949 } 15950 } 15951 15952 void CompactReporter::testRunEnded( TestRunStats const& _testRunStats ) { 15953 printTotals( stream, _testRunStats.totals ); 15954 stream << '\n' << std::endl; 15955 StreamingReporterBase::testRunEnded( _testRunStats ); 15956 } 15957 15958 CompactReporter::~CompactReporter() {} 15959 15960 CATCH_REGISTER_REPORTER( "compact", CompactReporter ) 15961 15962 } // end namespace Catch 15963 // end catch_reporter_compact.cpp 15964 // start catch_reporter_console.cpp 15965 15966 #include <cfloat> 15967 #include <cstdio> 15968 15969 #if defined(_MSC_VER) 15970 #pragma warning(push) 15971 #pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch 15972 // Note that 4062 (not all labels are handled and default is missing) is enabled 15973 #endif 15974 15975 #if defined(__clang__) 15976 # pragma clang diagnostic push 15977 // For simplicity, benchmarking-only helpers are always enabled 15978 # pragma clang diagnostic ignored "-Wunused-function" 15979 #endif 15980 15981 namespace Catch { 15982 15983 namespace { 15984 15985 // Formatter impl for ConsoleReporter 15986 class ConsoleAssertionPrinter { 15987 public: 15988 ConsoleAssertionPrinter& operator= (ConsoleAssertionPrinter const&) = delete; 15989 ConsoleAssertionPrinter(ConsoleAssertionPrinter const&) = delete; 15990 ConsoleAssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages) 15991 : stream(_stream), 15992 stats(_stats), 15993 result(_stats.assertionResult), 15994 colour(Colour::None), 15995 message(result.getMessage()), 15996 messages(_stats.infoMessages), 15997 printInfoMessages(_printInfoMessages) { 15998 switch (result.getResultType()) { 15999 case ResultWas::Ok: 16000 colour = Colour::Success; 16001 passOrFail = "PASSED"; 16002 //if( result.hasMessage() ) 16003 if (_stats.infoMessages.size() == 1) 16004 messageLabel = "with message"; 16005 if (_stats.infoMessages.size() > 1) 16006 messageLabel = "with messages"; 16007 break; 16008 case ResultWas::ExpressionFailed: 16009 if (result.isOk()) { 16010 colour = Colour::Success; 16011 passOrFail = "FAILED - but was ok"; 16012 } else { 16013 colour = Colour::Error; 16014 passOrFail = "FAILED"; 16015 } 16016 if (_stats.infoMessages.size() == 1) 16017 messageLabel = "with message"; 16018 if (_stats.infoMessages.size() > 1) 16019 messageLabel = "with messages"; 16020 break; 16021 case ResultWas::ThrewException: 16022 colour = Colour::Error; 16023 passOrFail = "FAILED"; 16024 messageLabel = "due to unexpected exception with "; 16025 if (_stats.infoMessages.size() == 1) 16026 messageLabel += "message"; 16027 if (_stats.infoMessages.size() > 1) 16028 messageLabel += "messages"; 16029 break; 16030 case ResultWas::FatalErrorCondition: 16031 colour = Colour::Error; 16032 passOrFail = "FAILED"; 16033 messageLabel = "due to a fatal error condition"; 16034 break; 16035 case ResultWas::DidntThrowException: 16036 colour = Colour::Error; 16037 passOrFail = "FAILED"; 16038 messageLabel = "because no exception was thrown where one was expected"; 16039 break; 16040 case ResultWas::Info: 16041 messageLabel = "info"; 16042 break; 16043 case ResultWas::Warning: 16044 messageLabel = "warning"; 16045 break; 16046 case ResultWas::ExplicitFailure: 16047 passOrFail = "FAILED"; 16048 colour = Colour::Error; 16049 if (_stats.infoMessages.size() == 1) 16050 messageLabel = "explicitly with message"; 16051 if (_stats.infoMessages.size() > 1) 16052 messageLabel = "explicitly with messages"; 16053 break; 16054 // These cases are here to prevent compiler warnings 16055 case ResultWas::Unknown: 16056 case ResultWas::FailureBit: 16057 case ResultWas::Exception: 16058 passOrFail = "** internal error **"; 16059 colour = Colour::Error; 16060 break; 16061 } 16062 } 16063 16064 void print() const { 16065 printSourceInfo(); 16066 if (stats.totals.assertions.total() > 0) { 16067 printResultType(); 16068 printOriginalExpression(); 16069 printReconstructedExpression(); 16070 } else { 16071 stream << '\n'; 16072 } 16073 printMessage(); 16074 } 16075 16076 private: 16077 void printResultType() const { 16078 if (!passOrFail.empty()) { 16079 Colour colourGuard(colour); 16080 stream << passOrFail << ":\n"; 16081 } 16082 } 16083 void printOriginalExpression() const { 16084 if (result.hasExpression()) { 16085 Colour colourGuard(Colour::OriginalExpression); 16086 stream << " "; 16087 stream << result.getExpressionInMacro(); 16088 stream << '\n'; 16089 } 16090 } 16091 void printReconstructedExpression() const { 16092 if (result.hasExpandedExpression()) { 16093 stream << "with expansion:\n"; 16094 Colour colourGuard(Colour::ReconstructedExpression); 16095 stream << Column(result.getExpandedExpression()).indent(2) << '\n'; 16096 } 16097 } 16098 void printMessage() const { 16099 if (!messageLabel.empty()) 16100 stream << messageLabel << ':' << '\n'; 16101 for (auto const& msg : messages) { 16102 // If this assertion is a warning ignore any INFO messages 16103 if (printInfoMessages || msg.type != ResultWas::Info) 16104 stream << Column(msg.message).indent(2) << '\n'; 16105 } 16106 } 16107 void printSourceInfo() const { 16108 Colour colourGuard(Colour::FileName); 16109 stream << result.getSourceInfo() << ": "; 16110 } 16111 16112 std::ostream& stream; 16113 AssertionStats const& stats; 16114 AssertionResult const& result; 16115 Colour::Code colour; 16116 std::string passOrFail; 16117 std::string messageLabel; 16118 std::string message; 16119 std::vector<MessageInfo> messages; 16120 bool printInfoMessages; 16121 }; 16122 16123 std::size_t makeRatio(std::size_t number, std::size_t total) { 16124 std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number / total : 0; 16125 return (ratio == 0 && number > 0) ? 1 : ratio; 16126 } 16127 16128 std::size_t& findMax(std::size_t& i, std::size_t& j, std::size_t& k) { 16129 if (i > j && i > k) 16130 return i; 16131 else if (j > k) 16132 return j; 16133 else 16134 return k; 16135 } 16136 16137 struct ColumnInfo { 16138 enum Justification { Left, Right }; 16139 std::string name; 16140 int width; 16141 Justification justification; 16142 }; 16143 struct ColumnBreak {}; 16144 struct RowBreak {}; 16145 16146 class Duration { 16147 enum class Unit { 16148 Auto, 16149 Nanoseconds, 16150 Microseconds, 16151 Milliseconds, 16152 Seconds, 16153 Minutes 16154 }; 16155 static const uint64_t s_nanosecondsInAMicrosecond = 1000; 16156 static const uint64_t s_nanosecondsInAMillisecond = 1000 * s_nanosecondsInAMicrosecond; 16157 static const uint64_t s_nanosecondsInASecond = 1000 * s_nanosecondsInAMillisecond; 16158 static const uint64_t s_nanosecondsInAMinute = 60 * s_nanosecondsInASecond; 16159 16160 double m_inNanoseconds; 16161 Unit m_units; 16162 16163 public: 16164 explicit Duration(double inNanoseconds, Unit units = Unit::Auto) 16165 : m_inNanoseconds(inNanoseconds), 16166 m_units(units) { 16167 if (m_units == Unit::Auto) { 16168 if (m_inNanoseconds < s_nanosecondsInAMicrosecond) 16169 m_units = Unit::Nanoseconds; 16170 else if (m_inNanoseconds < s_nanosecondsInAMillisecond) 16171 m_units = Unit::Microseconds; 16172 else if (m_inNanoseconds < s_nanosecondsInASecond) 16173 m_units = Unit::Milliseconds; 16174 else if (m_inNanoseconds < s_nanosecondsInAMinute) 16175 m_units = Unit::Seconds; 16176 else 16177 m_units = Unit::Minutes; 16178 } 16179 16180 } 16181 16182 auto value() const -> double { 16183 switch (m_units) { 16184 case Unit::Microseconds: 16185 return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMicrosecond); 16186 case Unit::Milliseconds: 16187 return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMillisecond); 16188 case Unit::Seconds: 16189 return m_inNanoseconds / static_cast<double>(s_nanosecondsInASecond); 16190 case Unit::Minutes: 16191 return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMinute); 16192 default: 16193 return m_inNanoseconds; 16194 } 16195 } 16196 auto unitsAsString() const -> std::string { 16197 switch (m_units) { 16198 case Unit::Nanoseconds: 16199 return "ns"; 16200 case Unit::Microseconds: 16201 return "us"; 16202 case Unit::Milliseconds: 16203 return "ms"; 16204 case Unit::Seconds: 16205 return "s"; 16206 case Unit::Minutes: 16207 return "m"; 16208 default: 16209 return "** internal error **"; 16210 } 16211 16212 } 16213 friend auto operator << (std::ostream& os, Duration const& duration) -> std::ostream& { 16214 return os << duration.value() << ' ' << duration.unitsAsString(); 16215 } 16216 }; 16217 } // end anon namespace 16218 16219 class TablePrinter { 16220 std::ostream& m_os; 16221 std::vector<ColumnInfo> m_columnInfos; 16222 std::ostringstream m_oss; 16223 int m_currentColumn = -1; 16224 bool m_isOpen = false; 16225 16226 public: 16227 TablePrinter( std::ostream& os, std::vector<ColumnInfo> columnInfos ) 16228 : m_os( os ), 16229 m_columnInfos( std::move( columnInfos ) ) {} 16230 16231 auto columnInfos() const -> std::vector<ColumnInfo> const& { 16232 return m_columnInfos; 16233 } 16234 16235 void open() { 16236 if (!m_isOpen) { 16237 m_isOpen = true; 16238 *this << RowBreak(); 16239 16240 Columns headerCols; 16241 Spacer spacer(2); 16242 for (auto const& info : m_columnInfos) { 16243 headerCols += Column(info.name).width(static_cast<std::size_t>(info.width - 2)); 16244 headerCols += spacer; 16245 } 16246 m_os << headerCols << '\n'; 16247 16248 m_os << Catch::getLineOfChars<'-'>() << '\n'; 16249 } 16250 } 16251 void close() { 16252 if (m_isOpen) { 16253 *this << RowBreak(); 16254 m_os << std::endl; 16255 m_isOpen = false; 16256 } 16257 } 16258 16259 template<typename T> 16260 friend TablePrinter& operator << (TablePrinter& tp, T const& value) { 16261 tp.m_oss << value; 16262 return tp; 16263 } 16264 16265 friend TablePrinter& operator << (TablePrinter& tp, ColumnBreak) { 16266 auto colStr = tp.m_oss.str(); 16267 const auto strSize = colStr.size(); 16268 tp.m_oss.str(""); 16269 tp.open(); 16270 if (tp.m_currentColumn == static_cast<int>(tp.m_columnInfos.size() - 1)) { 16271 tp.m_currentColumn = -1; 16272 tp.m_os << '\n'; 16273 } 16274 tp.m_currentColumn++; 16275 16276 auto colInfo = tp.m_columnInfos[tp.m_currentColumn]; 16277 auto padding = (strSize + 1 < static_cast<std::size_t>(colInfo.width)) 16278 ? std::string(colInfo.width - (strSize + 1), ' ') 16279 : std::string(); 16280 if (colInfo.justification == ColumnInfo::Left) 16281 tp.m_os << colStr << padding << ' '; 16282 else 16283 tp.m_os << padding << colStr << ' '; 16284 return tp; 16285 } 16286 16287 friend TablePrinter& operator << (TablePrinter& tp, RowBreak) { 16288 if (tp.m_currentColumn > 0) { 16289 tp.m_os << '\n'; 16290 tp.m_currentColumn = -1; 16291 } 16292 return tp; 16293 } 16294 }; 16295 16296 ConsoleReporter::ConsoleReporter(ReporterConfig const& config) 16297 : StreamingReporterBase(config), 16298 m_tablePrinter(new TablePrinter(config.stream(), 16299 [&config]() -> std::vector<ColumnInfo> { 16300 if (config.fullConfig()->benchmarkNoAnalysis()) 16301 { 16302 return{ 16303 { "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 43, ColumnInfo::Left }, 16304 { " samples", 14, ColumnInfo::Right }, 16305 { " iterations", 14, ColumnInfo::Right }, 16306 { " mean", 14, ColumnInfo::Right } 16307 }; 16308 } 16309 else 16310 { 16311 return{ 16312 { "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 43, ColumnInfo::Left }, 16313 { "samples mean std dev", 14, ColumnInfo::Right }, 16314 { "iterations low mean low std dev", 14, ColumnInfo::Right }, 16315 { "estimated high mean high std dev", 14, ColumnInfo::Right } 16316 }; 16317 } 16318 }())) {} 16319 ConsoleReporter::~ConsoleReporter() = default; 16320 16321 std::string ConsoleReporter::getDescription() { 16322 return "Reports test results as plain lines of text"; 16323 } 16324 16325 void ConsoleReporter::noMatchingTestCases(std::string const& spec) { 16326 stream << "No test cases matched '" << spec << '\'' << std::endl; 16327 } 16328 16329 void ConsoleReporter::reportInvalidArguments(std::string const&arg){ 16330 stream << "Invalid Filter: " << arg << std::endl; 16331 } 16332 16333 void ConsoleReporter::assertionStarting(AssertionInfo const&) {} 16334 16335 bool ConsoleReporter::assertionEnded(AssertionStats const& _assertionStats) { 16336 AssertionResult const& result = _assertionStats.assertionResult; 16337 16338 bool includeResults = m_config->includeSuccessfulResults() || !result.isOk(); 16339 16340 // Drop out if result was successful but we're not printing them. 16341 if (!includeResults && result.getResultType() != ResultWas::Warning) 16342 return false; 16343 16344 lazyPrint(); 16345 16346 ConsoleAssertionPrinter printer(stream, _assertionStats, includeResults); 16347 printer.print(); 16348 stream << std::endl; 16349 return true; 16350 } 16351 16352 void ConsoleReporter::sectionStarting(SectionInfo const& _sectionInfo) { 16353 m_tablePrinter->close(); 16354 m_headerPrinted = false; 16355 StreamingReporterBase::sectionStarting(_sectionInfo); 16356 } 16357 void ConsoleReporter::sectionEnded(SectionStats const& _sectionStats) { 16358 m_tablePrinter->close(); 16359 if (_sectionStats.missingAssertions) { 16360 lazyPrint(); 16361 Colour colour(Colour::ResultError); 16362 if (m_sectionStack.size() > 1) 16363 stream << "\nNo assertions in section"; 16364 else 16365 stream << "\nNo assertions in test case"; 16366 stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; 16367 } 16368 double dur = _sectionStats.durationInSeconds; 16369 if (shouldShowDuration(*m_config, dur)) { 16370 stream << getFormattedDuration(dur) << " s: " << _sectionStats.sectionInfo.name << std::endl; 16371 } 16372 if (m_headerPrinted) { 16373 m_headerPrinted = false; 16374 } 16375 StreamingReporterBase::sectionEnded(_sectionStats); 16376 } 16377 16378 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 16379 void ConsoleReporter::benchmarkPreparing(std::string const& name) { 16380 lazyPrintWithoutClosingBenchmarkTable(); 16381 16382 auto nameCol = Column(name).width(static_cast<std::size_t>(m_tablePrinter->columnInfos()[0].width - 2)); 16383 16384 bool firstLine = true; 16385 for (auto line : nameCol) { 16386 if (!firstLine) 16387 (*m_tablePrinter) << ColumnBreak() << ColumnBreak() << ColumnBreak(); 16388 else 16389 firstLine = false; 16390 16391 (*m_tablePrinter) << line << ColumnBreak(); 16392 } 16393 } 16394 16395 void ConsoleReporter::benchmarkStarting(BenchmarkInfo const& info) { 16396 (*m_tablePrinter) << info.samples << ColumnBreak() 16397 << info.iterations << ColumnBreak(); 16398 if (!m_config->benchmarkNoAnalysis()) 16399 (*m_tablePrinter) << Duration(info.estimatedDuration) << ColumnBreak(); 16400 } 16401 void ConsoleReporter::benchmarkEnded(BenchmarkStats<> const& stats) { 16402 if (m_config->benchmarkNoAnalysis()) 16403 { 16404 (*m_tablePrinter) << Duration(stats.mean.point.count()) << ColumnBreak(); 16405 } 16406 else 16407 { 16408 (*m_tablePrinter) << ColumnBreak() 16409 << Duration(stats.mean.point.count()) << ColumnBreak() 16410 << Duration(stats.mean.lower_bound.count()) << ColumnBreak() 16411 << Duration(stats.mean.upper_bound.count()) << ColumnBreak() << ColumnBreak() 16412 << Duration(stats.standardDeviation.point.count()) << ColumnBreak() 16413 << Duration(stats.standardDeviation.lower_bound.count()) << ColumnBreak() 16414 << Duration(stats.standardDeviation.upper_bound.count()) << ColumnBreak() << ColumnBreak() << ColumnBreak() << ColumnBreak() << ColumnBreak(); 16415 } 16416 } 16417 16418 void ConsoleReporter::benchmarkFailed(std::string const& error) { 16419 Colour colour(Colour::Red); 16420 (*m_tablePrinter) 16421 << "Benchmark failed (" << error << ')' 16422 << ColumnBreak() << RowBreak(); 16423 } 16424 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 16425 16426 void ConsoleReporter::testCaseEnded(TestCaseStats const& _testCaseStats) { 16427 m_tablePrinter->close(); 16428 StreamingReporterBase::testCaseEnded(_testCaseStats); 16429 m_headerPrinted = false; 16430 } 16431 void ConsoleReporter::testGroupEnded(TestGroupStats const& _testGroupStats) { 16432 if (currentGroupInfo.used) { 16433 printSummaryDivider(); 16434 stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; 16435 printTotals(_testGroupStats.totals); 16436 stream << '\n' << std::endl; 16437 } 16438 StreamingReporterBase::testGroupEnded(_testGroupStats); 16439 } 16440 void ConsoleReporter::testRunEnded(TestRunStats const& _testRunStats) { 16441 printTotalsDivider(_testRunStats.totals); 16442 printTotals(_testRunStats.totals); 16443 stream << std::endl; 16444 StreamingReporterBase::testRunEnded(_testRunStats); 16445 } 16446 void ConsoleReporter::testRunStarting(TestRunInfo const& _testInfo) { 16447 StreamingReporterBase::testRunStarting(_testInfo); 16448 printTestFilters(); 16449 } 16450 16451 void ConsoleReporter::lazyPrint() { 16452 16453 m_tablePrinter->close(); 16454 lazyPrintWithoutClosingBenchmarkTable(); 16455 } 16456 16457 void ConsoleReporter::lazyPrintWithoutClosingBenchmarkTable() { 16458 16459 if (!currentTestRunInfo.used) 16460 lazyPrintRunInfo(); 16461 if (!currentGroupInfo.used) 16462 lazyPrintGroupInfo(); 16463 16464 if (!m_headerPrinted) { 16465 printTestCaseAndSectionHeader(); 16466 m_headerPrinted = true; 16467 } 16468 } 16469 void ConsoleReporter::lazyPrintRunInfo() { 16470 stream << '\n' << getLineOfChars<'~'>() << '\n'; 16471 Colour colour(Colour::SecondaryText); 16472 stream << currentTestRunInfo->name 16473 << " is a Catch v" << libraryVersion() << " host application.\n" 16474 << "Run with -? for options\n\n"; 16475 16476 if (m_config->rngSeed() != 0) 16477 stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n"; 16478 16479 currentTestRunInfo.used = true; 16480 } 16481 void ConsoleReporter::lazyPrintGroupInfo() { 16482 if (!currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1) { 16483 printClosedHeader("Group: " + currentGroupInfo->name); 16484 currentGroupInfo.used = true; 16485 } 16486 } 16487 void ConsoleReporter::printTestCaseAndSectionHeader() { 16488 assert(!m_sectionStack.empty()); 16489 printOpenHeader(currentTestCaseInfo->name); 16490 16491 if (m_sectionStack.size() > 1) { 16492 Colour colourGuard(Colour::Headers); 16493 16494 auto 16495 it = m_sectionStack.begin() + 1, // Skip first section (test case) 16496 itEnd = m_sectionStack.end(); 16497 for (; it != itEnd; ++it) 16498 printHeaderString(it->name, 2); 16499 } 16500 16501 SourceLineInfo lineInfo = m_sectionStack.back().lineInfo; 16502 16503 stream << getLineOfChars<'-'>() << '\n'; 16504 Colour colourGuard(Colour::FileName); 16505 stream << lineInfo << '\n'; 16506 stream << getLineOfChars<'.'>() << '\n' << std::endl; 16507 } 16508 16509 void ConsoleReporter::printClosedHeader(std::string const& _name) { 16510 printOpenHeader(_name); 16511 stream << getLineOfChars<'.'>() << '\n'; 16512 } 16513 void ConsoleReporter::printOpenHeader(std::string const& _name) { 16514 stream << getLineOfChars<'-'>() << '\n'; 16515 { 16516 Colour colourGuard(Colour::Headers); 16517 printHeaderString(_name); 16518 } 16519 } 16520 16521 // if string has a : in first line will set indent to follow it on 16522 // subsequent lines 16523 void ConsoleReporter::printHeaderString(std::string const& _string, std::size_t indent) { 16524 std::size_t i = _string.find(": "); 16525 if (i != std::string::npos) 16526 i += 2; 16527 else 16528 i = 0; 16529 stream << Column(_string).indent(indent + i).initialIndent(indent) << '\n'; 16530 } 16531 16532 struct SummaryColumn { 16533 16534 SummaryColumn( std::string _label, Colour::Code _colour ) 16535 : label( std::move( _label ) ), 16536 colour( _colour ) {} 16537 SummaryColumn addRow( std::size_t count ) { 16538 ReusableStringStream rss; 16539 rss << count; 16540 std::string row = rss.str(); 16541 for (auto& oldRow : rows) { 16542 while (oldRow.size() < row.size()) 16543 oldRow = ' ' + oldRow; 16544 while (oldRow.size() > row.size()) 16545 row = ' ' + row; 16546 } 16547 rows.push_back(row); 16548 return *this; 16549 } 16550 16551 std::string label; 16552 Colour::Code colour; 16553 std::vector<std::string> rows; 16554 16555 }; 16556 16557 void ConsoleReporter::printTotals( Totals const& totals ) { 16558 if (totals.testCases.total() == 0) { 16559 stream << Colour(Colour::Warning) << "No tests ran\n"; 16560 } else if (totals.assertions.total() > 0 && totals.testCases.allPassed()) { 16561 stream << Colour(Colour::ResultSuccess) << "All tests passed"; 16562 stream << " (" 16563 << pluralise(totals.assertions.passed, "assertion") << " in " 16564 << pluralise(totals.testCases.passed, "test case") << ')' 16565 << '\n'; 16566 } else { 16567 16568 std::vector<SummaryColumn> columns; 16569 columns.push_back(SummaryColumn("", Colour::None) 16570 .addRow(totals.testCases.total()) 16571 .addRow(totals.assertions.total())); 16572 columns.push_back(SummaryColumn("passed", Colour::Success) 16573 .addRow(totals.testCases.passed) 16574 .addRow(totals.assertions.passed)); 16575 columns.push_back(SummaryColumn("failed", Colour::ResultError) 16576 .addRow(totals.testCases.failed) 16577 .addRow(totals.assertions.failed)); 16578 columns.push_back(SummaryColumn("failed as expected", Colour::ResultExpectedFailure) 16579 .addRow(totals.testCases.failedButOk) 16580 .addRow(totals.assertions.failedButOk)); 16581 16582 printSummaryRow("test cases", columns, 0); 16583 printSummaryRow("assertions", columns, 1); 16584 } 16585 } 16586 void ConsoleReporter::printSummaryRow(std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row) { 16587 for (auto col : cols) { 16588 std::string value = col.rows[row]; 16589 if (col.label.empty()) { 16590 stream << label << ": "; 16591 if (value != "0") 16592 stream << value; 16593 else 16594 stream << Colour(Colour::Warning) << "- none -"; 16595 } else if (value != "0") { 16596 stream << Colour(Colour::LightGrey) << " | "; 16597 stream << Colour(col.colour) 16598 << value << ' ' << col.label; 16599 } 16600 } 16601 stream << '\n'; 16602 } 16603 16604 void ConsoleReporter::printTotalsDivider(Totals const& totals) { 16605 if (totals.testCases.total() > 0) { 16606 std::size_t failedRatio = makeRatio(totals.testCases.failed, totals.testCases.total()); 16607 std::size_t failedButOkRatio = makeRatio(totals.testCases.failedButOk, totals.testCases.total()); 16608 std::size_t passedRatio = makeRatio(totals.testCases.passed, totals.testCases.total()); 16609 while (failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH - 1) 16610 findMax(failedRatio, failedButOkRatio, passedRatio)++; 16611 while (failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH - 1) 16612 findMax(failedRatio, failedButOkRatio, passedRatio)--; 16613 16614 stream << Colour(Colour::Error) << std::string(failedRatio, '='); 16615 stream << Colour(Colour::ResultExpectedFailure) << std::string(failedButOkRatio, '='); 16616 if (totals.testCases.allPassed()) 16617 stream << Colour(Colour::ResultSuccess) << std::string(passedRatio, '='); 16618 else 16619 stream << Colour(Colour::Success) << std::string(passedRatio, '='); 16620 } else { 16621 stream << Colour(Colour::Warning) << std::string(CATCH_CONFIG_CONSOLE_WIDTH - 1, '='); 16622 } 16623 stream << '\n'; 16624 } 16625 void ConsoleReporter::printSummaryDivider() { 16626 stream << getLineOfChars<'-'>() << '\n'; 16627 } 16628 16629 void ConsoleReporter::printTestFilters() { 16630 if (m_config->testSpec().hasFilters()) { 16631 Colour guard(Colour::BrightYellow); 16632 stream << "Filters: " << serializeFilters(m_config->getTestsOrTags()) << '\n'; 16633 } 16634 } 16635 16636 CATCH_REGISTER_REPORTER("console", ConsoleReporter) 16637 16638 } // end namespace Catch 16639 16640 #if defined(_MSC_VER) 16641 #pragma warning(pop) 16642 #endif 16643 16644 #if defined(__clang__) 16645 # pragma clang diagnostic pop 16646 #endif 16647 // end catch_reporter_console.cpp 16648 // start catch_reporter_junit.cpp 16649 16650 #include <cassert> 16651 #include <sstream> 16652 #include <ctime> 16653 #include <algorithm> 16654 16655 namespace Catch { 16656 16657 namespace { 16658 std::string getCurrentTimestamp() { 16659 // Beware, this is not reentrant because of backward compatibility issues 16660 // Also, UTC only, again because of backward compatibility (%z is C++11) 16661 time_t rawtime; 16662 std::time(&rawtime); 16663 auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); 16664 16665 #ifdef _MSC_VER 16666 std::tm timeInfo = {}; 16667 gmtime_s(&timeInfo, &rawtime); 16668 #else 16669 std::tm* timeInfo; 16670 timeInfo = std::gmtime(&rawtime); 16671 #endif 16672 16673 char timeStamp[timeStampSize]; 16674 const char * const fmt = "%Y-%m-%dT%H:%M:%SZ"; 16675 16676 #ifdef _MSC_VER 16677 std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); 16678 #else 16679 std::strftime(timeStamp, timeStampSize, fmt, timeInfo); 16680 #endif 16681 return std::string(timeStamp); 16682 } 16683 16684 std::string fileNameTag(const std::vector<std::string> &tags) { 16685 auto it = std::find_if(begin(tags), 16686 end(tags), 16687 [] (std::string const& tag) {return tag.front() == '#'; }); 16688 if (it != tags.end()) 16689 return it->substr(1); 16690 return std::string(); 16691 } 16692 } // anonymous namespace 16693 16694 JunitReporter::JunitReporter( ReporterConfig const& _config ) 16695 : CumulativeReporterBase( _config ), 16696 xml( _config.stream() ) 16697 { 16698 m_reporterPrefs.shouldRedirectStdOut = true; 16699 m_reporterPrefs.shouldReportAllAssertions = true; 16700 } 16701 16702 JunitReporter::~JunitReporter() {} 16703 16704 std::string JunitReporter::getDescription() { 16705 return "Reports test results in an XML format that looks like Ant's junitreport target"; 16706 } 16707 16708 void JunitReporter::noMatchingTestCases( std::string const& /*spec*/ ) {} 16709 16710 void JunitReporter::testRunStarting( TestRunInfo const& runInfo ) { 16711 CumulativeReporterBase::testRunStarting( runInfo ); 16712 xml.startElement( "testsuites" ); 16713 } 16714 16715 void JunitReporter::testGroupStarting( GroupInfo const& groupInfo ) { 16716 suiteTimer.start(); 16717 stdOutForSuite.clear(); 16718 stdErrForSuite.clear(); 16719 unexpectedExceptions = 0; 16720 CumulativeReporterBase::testGroupStarting( groupInfo ); 16721 } 16722 16723 void JunitReporter::testCaseStarting( TestCaseInfo const& testCaseInfo ) { 16724 m_okToFail = testCaseInfo.okToFail(); 16725 } 16726 16727 bool JunitReporter::assertionEnded( AssertionStats const& assertionStats ) { 16728 if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException && !m_okToFail ) 16729 unexpectedExceptions++; 16730 return CumulativeReporterBase::assertionEnded( assertionStats ); 16731 } 16732 16733 void JunitReporter::testCaseEnded( TestCaseStats const& testCaseStats ) { 16734 stdOutForSuite += testCaseStats.stdOut; 16735 stdErrForSuite += testCaseStats.stdErr; 16736 CumulativeReporterBase::testCaseEnded( testCaseStats ); 16737 } 16738 16739 void JunitReporter::testGroupEnded( TestGroupStats const& testGroupStats ) { 16740 double suiteTime = suiteTimer.getElapsedSeconds(); 16741 CumulativeReporterBase::testGroupEnded( testGroupStats ); 16742 writeGroup( *m_testGroups.back(), suiteTime ); 16743 } 16744 16745 void JunitReporter::testRunEndedCumulative() { 16746 xml.endElement(); 16747 } 16748 16749 void JunitReporter::writeGroup( TestGroupNode const& groupNode, double suiteTime ) { 16750 XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); 16751 16752 TestGroupStats const& stats = groupNode.value; 16753 xml.writeAttribute( "name", stats.groupInfo.name ); 16754 xml.writeAttribute( "errors", unexpectedExceptions ); 16755 xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions ); 16756 xml.writeAttribute( "tests", stats.totals.assertions.total() ); 16757 xml.writeAttribute( "hostname", "tbd" ); // !TBD 16758 if( m_config->showDurations() == ShowDurations::Never ) 16759 xml.writeAttribute( "time", "" ); 16760 else 16761 xml.writeAttribute( "time", suiteTime ); 16762 xml.writeAttribute( "timestamp", getCurrentTimestamp() ); 16763 16764 // Write properties if there are any 16765 if (m_config->hasTestFilters() || m_config->rngSeed() != 0) { 16766 auto properties = xml.scopedElement("properties"); 16767 if (m_config->hasTestFilters()) { 16768 xml.scopedElement("property") 16769 .writeAttribute("name", "filters") 16770 .writeAttribute("value", serializeFilters(m_config->getTestsOrTags())); 16771 } 16772 if (m_config->rngSeed() != 0) { 16773 xml.scopedElement("property") 16774 .writeAttribute("name", "random-seed") 16775 .writeAttribute("value", m_config->rngSeed()); 16776 } 16777 } 16778 16779 // Write test cases 16780 for( auto const& child : groupNode.children ) 16781 writeTestCase( *child ); 16782 16783 xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite ), XmlFormatting::Newline ); 16784 xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite ), XmlFormatting::Newline ); 16785 } 16786 16787 void JunitReporter::writeTestCase( TestCaseNode const& testCaseNode ) { 16788 TestCaseStats const& stats = testCaseNode.value; 16789 16790 // All test cases have exactly one section - which represents the 16791 // test case itself. That section may have 0-n nested sections 16792 assert( testCaseNode.children.size() == 1 ); 16793 SectionNode const& rootSection = *testCaseNode.children.front(); 16794 16795 std::string className = stats.testInfo.className; 16796 16797 if( className.empty() ) { 16798 className = fileNameTag(stats.testInfo.tags); 16799 if ( className.empty() ) 16800 className = "global"; 16801 } 16802 16803 if ( !m_config->name().empty() ) 16804 className = m_config->name() + "." + className; 16805 16806 writeSection( className, "", rootSection ); 16807 } 16808 16809 void JunitReporter::writeSection( std::string const& className, 16810 std::string const& rootName, 16811 SectionNode const& sectionNode ) { 16812 std::string name = trim( sectionNode.stats.sectionInfo.name ); 16813 if( !rootName.empty() ) 16814 name = rootName + '/' + name; 16815 16816 if( !sectionNode.assertions.empty() || 16817 !sectionNode.stdOut.empty() || 16818 !sectionNode.stdErr.empty() ) { 16819 XmlWriter::ScopedElement e = xml.scopedElement( "testcase" ); 16820 if( className.empty() ) { 16821 xml.writeAttribute( "classname", name ); 16822 xml.writeAttribute( "name", "root" ); 16823 } 16824 else { 16825 xml.writeAttribute( "classname", className ); 16826 xml.writeAttribute( "name", name ); 16827 } 16828 xml.writeAttribute( "time", ::Catch::Detail::stringify( sectionNode.stats.durationInSeconds ) ); 16829 // This is not ideal, but it should be enough to mimic gtest's 16830 // junit output. 16831 // Ideally the JUnit reporter would also handle `skipTest` 16832 // events and write those out appropriately. 16833 xml.writeAttribute( "status", "run" ); 16834 16835 writeAssertions( sectionNode ); 16836 16837 if( !sectionNode.stdOut.empty() ) 16838 xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), XmlFormatting::Newline ); 16839 if( !sectionNode.stdErr.empty() ) 16840 xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), XmlFormatting::Newline ); 16841 } 16842 for( auto const& childNode : sectionNode.childSections ) 16843 if( className.empty() ) 16844 writeSection( name, "", *childNode ); 16845 else 16846 writeSection( className, name, *childNode ); 16847 } 16848 16849 void JunitReporter::writeAssertions( SectionNode const& sectionNode ) { 16850 for( auto const& assertion : sectionNode.assertions ) 16851 writeAssertion( assertion ); 16852 } 16853 16854 void JunitReporter::writeAssertion( AssertionStats const& stats ) { 16855 AssertionResult const& result = stats.assertionResult; 16856 if( !result.isOk() ) { 16857 std::string elementName; 16858 switch( result.getResultType() ) { 16859 case ResultWas::ThrewException: 16860 case ResultWas::FatalErrorCondition: 16861 elementName = "error"; 16862 break; 16863 case ResultWas::ExplicitFailure: 16864 case ResultWas::ExpressionFailed: 16865 case ResultWas::DidntThrowException: 16866 elementName = "failure"; 16867 break; 16868 16869 // We should never see these here: 16870 case ResultWas::Info: 16871 case ResultWas::Warning: 16872 case ResultWas::Ok: 16873 case ResultWas::Unknown: 16874 case ResultWas::FailureBit: 16875 case ResultWas::Exception: 16876 elementName = "internalError"; 16877 break; 16878 } 16879 16880 XmlWriter::ScopedElement e = xml.scopedElement( elementName ); 16881 16882 xml.writeAttribute( "message", result.getExpression() ); 16883 xml.writeAttribute( "type", result.getTestMacroName() ); 16884 16885 ReusableStringStream rss; 16886 if (stats.totals.assertions.total() > 0) { 16887 rss << "FAILED" << ":\n"; 16888 if (result.hasExpression()) { 16889 rss << " "; 16890 rss << result.getExpressionInMacro(); 16891 rss << '\n'; 16892 } 16893 if (result.hasExpandedExpression()) { 16894 rss << "with expansion:\n"; 16895 rss << Column(result.getExpandedExpression()).indent(2) << '\n'; 16896 } 16897 } else { 16898 rss << '\n'; 16899 } 16900 16901 if( !result.getMessage().empty() ) 16902 rss << result.getMessage() << '\n'; 16903 for( auto const& msg : stats.infoMessages ) 16904 if( msg.type == ResultWas::Info ) 16905 rss << msg.message << '\n'; 16906 16907 rss << "at " << result.getSourceInfo(); 16908 xml.writeText( rss.str(), XmlFormatting::Newline ); 16909 } 16910 } 16911 16912 CATCH_REGISTER_REPORTER( "junit", JunitReporter ) 16913 16914 } // end namespace Catch 16915 // end catch_reporter_junit.cpp 16916 // start catch_reporter_listening.cpp 16917 16918 #include <cassert> 16919 16920 namespace Catch { 16921 16922 ListeningReporter::ListeningReporter() { 16923 // We will assume that listeners will always want all assertions 16924 m_preferences.shouldReportAllAssertions = true; 16925 } 16926 16927 void ListeningReporter::addListener( IStreamingReporterPtr&& listener ) { 16928 m_listeners.push_back( std::move( listener ) ); 16929 } 16930 16931 void ListeningReporter::addReporter(IStreamingReporterPtr&& reporter) { 16932 assert(!m_reporter && "Listening reporter can wrap only 1 real reporter"); 16933 m_reporter = std::move( reporter ); 16934 m_preferences.shouldRedirectStdOut = m_reporter->getPreferences().shouldRedirectStdOut; 16935 } 16936 16937 ReporterPreferences ListeningReporter::getPreferences() const { 16938 return m_preferences; 16939 } 16940 16941 std::set<Verbosity> ListeningReporter::getSupportedVerbosities() { 16942 return std::set<Verbosity>{ }; 16943 } 16944 16945 void ListeningReporter::noMatchingTestCases( std::string const& spec ) { 16946 for ( auto const& listener : m_listeners ) { 16947 listener->noMatchingTestCases( spec ); 16948 } 16949 m_reporter->noMatchingTestCases( spec ); 16950 } 16951 16952 void ListeningReporter::reportInvalidArguments(std::string const&arg){ 16953 for ( auto const& listener : m_listeners ) { 16954 listener->reportInvalidArguments( arg ); 16955 } 16956 m_reporter->reportInvalidArguments( arg ); 16957 } 16958 16959 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 16960 void ListeningReporter::benchmarkPreparing( std::string const& name ) { 16961 for (auto const& listener : m_listeners) { 16962 listener->benchmarkPreparing(name); 16963 } 16964 m_reporter->benchmarkPreparing(name); 16965 } 16966 void ListeningReporter::benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) { 16967 for ( auto const& listener : m_listeners ) { 16968 listener->benchmarkStarting( benchmarkInfo ); 16969 } 16970 m_reporter->benchmarkStarting( benchmarkInfo ); 16971 } 16972 void ListeningReporter::benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) { 16973 for ( auto const& listener : m_listeners ) { 16974 listener->benchmarkEnded( benchmarkStats ); 16975 } 16976 m_reporter->benchmarkEnded( benchmarkStats ); 16977 } 16978 16979 void ListeningReporter::benchmarkFailed( std::string const& error ) { 16980 for (auto const& listener : m_listeners) { 16981 listener->benchmarkFailed(error); 16982 } 16983 m_reporter->benchmarkFailed(error); 16984 } 16985 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 16986 16987 void ListeningReporter::testRunStarting( TestRunInfo const& testRunInfo ) { 16988 for ( auto const& listener : m_listeners ) { 16989 listener->testRunStarting( testRunInfo ); 16990 } 16991 m_reporter->testRunStarting( testRunInfo ); 16992 } 16993 16994 void ListeningReporter::testGroupStarting( GroupInfo const& groupInfo ) { 16995 for ( auto const& listener : m_listeners ) { 16996 listener->testGroupStarting( groupInfo ); 16997 } 16998 m_reporter->testGroupStarting( groupInfo ); 16999 } 17000 17001 void ListeningReporter::testCaseStarting( TestCaseInfo const& testInfo ) { 17002 for ( auto const& listener : m_listeners ) { 17003 listener->testCaseStarting( testInfo ); 17004 } 17005 m_reporter->testCaseStarting( testInfo ); 17006 } 17007 17008 void ListeningReporter::sectionStarting( SectionInfo const& sectionInfo ) { 17009 for ( auto const& listener : m_listeners ) { 17010 listener->sectionStarting( sectionInfo ); 17011 } 17012 m_reporter->sectionStarting( sectionInfo ); 17013 } 17014 17015 void ListeningReporter::assertionStarting( AssertionInfo const& assertionInfo ) { 17016 for ( auto const& listener : m_listeners ) { 17017 listener->assertionStarting( assertionInfo ); 17018 } 17019 m_reporter->assertionStarting( assertionInfo ); 17020 } 17021 17022 // The return value indicates if the messages buffer should be cleared: 17023 bool ListeningReporter::assertionEnded( AssertionStats const& assertionStats ) { 17024 for( auto const& listener : m_listeners ) { 17025 static_cast<void>( listener->assertionEnded( assertionStats ) ); 17026 } 17027 return m_reporter->assertionEnded( assertionStats ); 17028 } 17029 17030 void ListeningReporter::sectionEnded( SectionStats const& sectionStats ) { 17031 for ( auto const& listener : m_listeners ) { 17032 listener->sectionEnded( sectionStats ); 17033 } 17034 m_reporter->sectionEnded( sectionStats ); 17035 } 17036 17037 void ListeningReporter::testCaseEnded( TestCaseStats const& testCaseStats ) { 17038 for ( auto const& listener : m_listeners ) { 17039 listener->testCaseEnded( testCaseStats ); 17040 } 17041 m_reporter->testCaseEnded( testCaseStats ); 17042 } 17043 17044 void ListeningReporter::testGroupEnded( TestGroupStats const& testGroupStats ) { 17045 for ( auto const& listener : m_listeners ) { 17046 listener->testGroupEnded( testGroupStats ); 17047 } 17048 m_reporter->testGroupEnded( testGroupStats ); 17049 } 17050 17051 void ListeningReporter::testRunEnded( TestRunStats const& testRunStats ) { 17052 for ( auto const& listener : m_listeners ) { 17053 listener->testRunEnded( testRunStats ); 17054 } 17055 m_reporter->testRunEnded( testRunStats ); 17056 } 17057 17058 void ListeningReporter::skipTest( TestCaseInfo const& testInfo ) { 17059 for ( auto const& listener : m_listeners ) { 17060 listener->skipTest( testInfo ); 17061 } 17062 m_reporter->skipTest( testInfo ); 17063 } 17064 17065 bool ListeningReporter::isMulti() const { 17066 return true; 17067 } 17068 17069 } // end namespace Catch 17070 // end catch_reporter_listening.cpp 17071 // start catch_reporter_xml.cpp 17072 17073 #if defined(_MSC_VER) 17074 #pragma warning(push) 17075 #pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch 17076 // Note that 4062 (not all labels are handled 17077 // and default is missing) is enabled 17078 #endif 17079 17080 namespace Catch { 17081 XmlReporter::XmlReporter( ReporterConfig const& _config ) 17082 : StreamingReporterBase( _config ), 17083 m_xml(_config.stream()) 17084 { 17085 m_reporterPrefs.shouldRedirectStdOut = true; 17086 m_reporterPrefs.shouldReportAllAssertions = true; 17087 } 17088 17089 XmlReporter::~XmlReporter() = default; 17090 17091 std::string XmlReporter::getDescription() { 17092 return "Reports test results as an XML document"; 17093 } 17094 17095 std::string XmlReporter::getStylesheetRef() const { 17096 return std::string(); 17097 } 17098 17099 void XmlReporter::writeSourceInfo( SourceLineInfo const& sourceInfo ) { 17100 m_xml 17101 .writeAttribute( "filename", sourceInfo.file ) 17102 .writeAttribute( "line", sourceInfo.line ); 17103 } 17104 17105 void XmlReporter::noMatchingTestCases( std::string const& s ) { 17106 StreamingReporterBase::noMatchingTestCases( s ); 17107 } 17108 17109 void XmlReporter::testRunStarting( TestRunInfo const& testInfo ) { 17110 StreamingReporterBase::testRunStarting( testInfo ); 17111 std::string stylesheetRef = getStylesheetRef(); 17112 if( !stylesheetRef.empty() ) 17113 m_xml.writeStylesheetRef( stylesheetRef ); 17114 m_xml.startElement( "Catch" ); 17115 if( !m_config->name().empty() ) 17116 m_xml.writeAttribute( "name", m_config->name() ); 17117 if (m_config->testSpec().hasFilters()) 17118 m_xml.writeAttribute( "filters", serializeFilters( m_config->getTestsOrTags() ) ); 17119 if( m_config->rngSeed() != 0 ) 17120 m_xml.scopedElement( "Randomness" ) 17121 .writeAttribute( "seed", m_config->rngSeed() ); 17122 } 17123 17124 void XmlReporter::testGroupStarting( GroupInfo const& groupInfo ) { 17125 StreamingReporterBase::testGroupStarting( groupInfo ); 17126 m_xml.startElement( "Group" ) 17127 .writeAttribute( "name", groupInfo.name ); 17128 } 17129 17130 void XmlReporter::testCaseStarting( TestCaseInfo const& testInfo ) { 17131 StreamingReporterBase::testCaseStarting(testInfo); 17132 m_xml.startElement( "TestCase" ) 17133 .writeAttribute( "name", trim( testInfo.name ) ) 17134 .writeAttribute( "description", testInfo.description ) 17135 .writeAttribute( "tags", testInfo.tagsAsString() ); 17136 17137 writeSourceInfo( testInfo.lineInfo ); 17138 17139 if ( m_config->showDurations() == ShowDurations::Always ) 17140 m_testCaseTimer.start(); 17141 m_xml.ensureTagClosed(); 17142 } 17143 17144 void XmlReporter::sectionStarting( SectionInfo const& sectionInfo ) { 17145 StreamingReporterBase::sectionStarting( sectionInfo ); 17146 if( m_sectionDepth++ > 0 ) { 17147 m_xml.startElement( "Section" ) 17148 .writeAttribute( "name", trim( sectionInfo.name ) ); 17149 writeSourceInfo( sectionInfo.lineInfo ); 17150 m_xml.ensureTagClosed(); 17151 } 17152 } 17153 17154 void XmlReporter::assertionStarting( AssertionInfo const& ) { } 17155 17156 bool XmlReporter::assertionEnded( AssertionStats const& assertionStats ) { 17157 17158 AssertionResult const& result = assertionStats.assertionResult; 17159 17160 bool includeResults = m_config->includeSuccessfulResults() || !result.isOk(); 17161 17162 if( includeResults || result.getResultType() == ResultWas::Warning ) { 17163 // Print any info messages in <Info> tags. 17164 for( auto const& msg : assertionStats.infoMessages ) { 17165 if( msg.type == ResultWas::Info && includeResults ) { 17166 m_xml.scopedElement( "Info" ) 17167 .writeText( msg.message ); 17168 } else if ( msg.type == ResultWas::Warning ) { 17169 m_xml.scopedElement( "Warning" ) 17170 .writeText( msg.message ); 17171 } 17172 } 17173 } 17174 17175 // Drop out if result was successful but we're not printing them. 17176 if( !includeResults && result.getResultType() != ResultWas::Warning ) 17177 return true; 17178 17179 // Print the expression if there is one. 17180 if( result.hasExpression() ) { 17181 m_xml.startElement( "Expression" ) 17182 .writeAttribute( "success", result.succeeded() ) 17183 .writeAttribute( "type", result.getTestMacroName() ); 17184 17185 writeSourceInfo( result.getSourceInfo() ); 17186 17187 m_xml.scopedElement( "Original" ) 17188 .writeText( result.getExpression() ); 17189 m_xml.scopedElement( "Expanded" ) 17190 .writeText( result.getExpandedExpression() ); 17191 } 17192 17193 // And... Print a result applicable to each result type. 17194 switch( result.getResultType() ) { 17195 case ResultWas::ThrewException: 17196 m_xml.startElement( "Exception" ); 17197 writeSourceInfo( result.getSourceInfo() ); 17198 m_xml.writeText( result.getMessage() ); 17199 m_xml.endElement(); 17200 break; 17201 case ResultWas::FatalErrorCondition: 17202 m_xml.startElement( "FatalErrorCondition" ); 17203 writeSourceInfo( result.getSourceInfo() ); 17204 m_xml.writeText( result.getMessage() ); 17205 m_xml.endElement(); 17206 break; 17207 case ResultWas::Info: 17208 m_xml.scopedElement( "Info" ) 17209 .writeText( result.getMessage() ); 17210 break; 17211 case ResultWas::Warning: 17212 // Warning will already have been written 17213 break; 17214 case ResultWas::ExplicitFailure: 17215 m_xml.startElement( "Failure" ); 17216 writeSourceInfo( result.getSourceInfo() ); 17217 m_xml.writeText( result.getMessage() ); 17218 m_xml.endElement(); 17219 break; 17220 default: 17221 break; 17222 } 17223 17224 if( result.hasExpression() ) 17225 m_xml.endElement(); 17226 17227 return true; 17228 } 17229 17230 void XmlReporter::sectionEnded( SectionStats const& sectionStats ) { 17231 StreamingReporterBase::sectionEnded( sectionStats ); 17232 if( --m_sectionDepth > 0 ) { 17233 XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" ); 17234 e.writeAttribute( "successes", sectionStats.assertions.passed ); 17235 e.writeAttribute( "failures", sectionStats.assertions.failed ); 17236 e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk ); 17237 17238 if ( m_config->showDurations() == ShowDurations::Always ) 17239 e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds ); 17240 17241 m_xml.endElement(); 17242 } 17243 } 17244 17245 void XmlReporter::testCaseEnded( TestCaseStats const& testCaseStats ) { 17246 StreamingReporterBase::testCaseEnded( testCaseStats ); 17247 XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" ); 17248 e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() ); 17249 17250 if ( m_config->showDurations() == ShowDurations::Always ) 17251 e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() ); 17252 17253 if( !testCaseStats.stdOut.empty() ) 17254 m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), XmlFormatting::Newline ); 17255 if( !testCaseStats.stdErr.empty() ) 17256 m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), XmlFormatting::Newline ); 17257 17258 m_xml.endElement(); 17259 } 17260 17261 void XmlReporter::testGroupEnded( TestGroupStats const& testGroupStats ) { 17262 StreamingReporterBase::testGroupEnded( testGroupStats ); 17263 // TODO: Check testGroupStats.aborting and act accordingly. 17264 m_xml.scopedElement( "OverallResults" ) 17265 .writeAttribute( "successes", testGroupStats.totals.assertions.passed ) 17266 .writeAttribute( "failures", testGroupStats.totals.assertions.failed ) 17267 .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk ); 17268 m_xml.scopedElement( "OverallResultsCases") 17269 .writeAttribute( "successes", testGroupStats.totals.testCases.passed ) 17270 .writeAttribute( "failures", testGroupStats.totals.testCases.failed ) 17271 .writeAttribute( "expectedFailures", testGroupStats.totals.testCases.failedButOk ); 17272 m_xml.endElement(); 17273 } 17274 17275 void XmlReporter::testRunEnded( TestRunStats const& testRunStats ) { 17276 StreamingReporterBase::testRunEnded( testRunStats ); 17277 m_xml.scopedElement( "OverallResults" ) 17278 .writeAttribute( "successes", testRunStats.totals.assertions.passed ) 17279 .writeAttribute( "failures", testRunStats.totals.assertions.failed ) 17280 .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk ); 17281 m_xml.scopedElement( "OverallResultsCases") 17282 .writeAttribute( "successes", testRunStats.totals.testCases.passed ) 17283 .writeAttribute( "failures", testRunStats.totals.testCases.failed ) 17284 .writeAttribute( "expectedFailures", testRunStats.totals.testCases.failedButOk ); 17285 m_xml.endElement(); 17286 } 17287 17288 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 17289 void XmlReporter::benchmarkPreparing(std::string const& name) { 17290 m_xml.startElement("BenchmarkResults") 17291 .writeAttribute("name", name); 17292 } 17293 17294 void XmlReporter::benchmarkStarting(BenchmarkInfo const &info) { 17295 m_xml.writeAttribute("samples", info.samples) 17296 .writeAttribute("resamples", info.resamples) 17297 .writeAttribute("iterations", info.iterations) 17298 .writeAttribute("clockResolution", info.clockResolution) 17299 .writeAttribute("estimatedDuration", info.estimatedDuration) 17300 .writeComment("All values in nano seconds"); 17301 } 17302 17303 void XmlReporter::benchmarkEnded(BenchmarkStats<> const& benchmarkStats) { 17304 m_xml.startElement("mean") 17305 .writeAttribute("value", benchmarkStats.mean.point.count()) 17306 .writeAttribute("lowerBound", benchmarkStats.mean.lower_bound.count()) 17307 .writeAttribute("upperBound", benchmarkStats.mean.upper_bound.count()) 17308 .writeAttribute("ci", benchmarkStats.mean.confidence_interval); 17309 m_xml.endElement(); 17310 m_xml.startElement("standardDeviation") 17311 .writeAttribute("value", benchmarkStats.standardDeviation.point.count()) 17312 .writeAttribute("lowerBound", benchmarkStats.standardDeviation.lower_bound.count()) 17313 .writeAttribute("upperBound", benchmarkStats.standardDeviation.upper_bound.count()) 17314 .writeAttribute("ci", benchmarkStats.standardDeviation.confidence_interval); 17315 m_xml.endElement(); 17316 m_xml.startElement("outliers") 17317 .writeAttribute("variance", benchmarkStats.outlierVariance) 17318 .writeAttribute("lowMild", benchmarkStats.outliers.low_mild) 17319 .writeAttribute("lowSevere", benchmarkStats.outliers.low_severe) 17320 .writeAttribute("highMild", benchmarkStats.outliers.high_mild) 17321 .writeAttribute("highSevere", benchmarkStats.outliers.high_severe); 17322 m_xml.endElement(); 17323 m_xml.endElement(); 17324 } 17325 17326 void XmlReporter::benchmarkFailed(std::string const &error) { 17327 m_xml.scopedElement("failed"). 17328 writeAttribute("message", error); 17329 m_xml.endElement(); 17330 } 17331 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 17332 17333 CATCH_REGISTER_REPORTER( "xml", XmlReporter ) 17334 17335 } // end namespace Catch 17336 17337 #if defined(_MSC_VER) 17338 #pragma warning(pop) 17339 #endif 17340 // end catch_reporter_xml.cpp 17341 17342 namespace Catch { 17343 LeakDetector leakDetector; 17344 } 17345 17346 #ifdef __clang__ 17347 #pragma clang diagnostic pop 17348 #endif 17349 17350 // end catch_impl.hpp 17351 #endif 17352 17353 #ifdef CATCH_CONFIG_MAIN 17354 // start catch_default_main.hpp 17355 17356 #ifndef __OBJC__ 17357 17358 #if defined(CATCH_CONFIG_WCHAR) && defined(CATCH_PLATFORM_WINDOWS) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN) 17359 // Standard C/C++ Win32 Unicode wmain entry point 17360 extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) { 17361 #else 17362 // Standard C/C++ main entry point 17363 int main (int argc, char * argv[]) { 17364 #endif 17365 17366 return Catch::Session().run( argc, argv ); 17367 } 17368 17369 #else // __OBJC__ 17370 17371 // Objective-C entry point 17372 int main (int argc, char * const argv[]) { 17373 #if !CATCH_ARC_ENABLED 17374 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 17375 #endif 17376 17377 Catch::registerTestMethods(); 17378 int result = Catch::Session().run( argc, (char**)argv ); 17379 17380 #if !CATCH_ARC_ENABLED 17381 [pool drain]; 17382 #endif 17383 17384 return result; 17385 } 17386 17387 #endif // __OBJC__ 17388 17389 // end catch_default_main.hpp 17390 #endif 17391 17392 #if !defined(CATCH_CONFIG_IMPL_ONLY) 17393 17394 #ifdef CLARA_CONFIG_MAIN_NOT_DEFINED 17395 # undef CLARA_CONFIG_MAIN 17396 #endif 17397 17398 #if !defined(CATCH_CONFIG_DISABLE) 17399 ////// 17400 // If this config identifier is defined then all CATCH macros are prefixed with CATCH_ 17401 #ifdef CATCH_CONFIG_PREFIX_ALL 17402 17403 #define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17404 #define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 17405 17406 #define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17407 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) 17408 #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) 17409 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17410 #define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) 17411 #endif// CATCH_CONFIG_DISABLE_MATCHERS 17412 #define CATCH_REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17413 17414 #define CATCH_CHECK( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17415 #define CATCH_CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 17416 #define CATCH_CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17417 #define CATCH_CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17418 #define CATCH_CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) 17419 17420 #define CATCH_CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17421 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) 17422 #define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 17423 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17424 #define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 17425 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17426 #define CATCH_CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17427 17428 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17429 #define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) 17430 17431 #define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) 17432 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17433 17434 #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) 17435 #define CATCH_UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "CATCH_UNSCOPED_INFO", msg ) 17436 #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) 17437 #define CATCH_CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CATCH_CAPTURE",__VA_ARGS__ ) 17438 17439 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) 17440 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17441 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) 17442 #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) 17443 #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) 17444 #define CATCH_DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ ) 17445 #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17446 #define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17447 #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17448 17449 #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE() 17450 17451 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 17452 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17453 #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) 17454 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17455 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) 17456 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) 17457 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) 17458 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17459 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) 17460 #else 17461 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) ) 17462 #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) ) 17463 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) 17464 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) ) 17465 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) ) 17466 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) ) 17467 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) 17468 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) ) 17469 #endif 17470 17471 #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE) 17472 #define CATCH_STATIC_REQUIRE( ... ) static_assert( __VA_ARGS__ , #__VA_ARGS__ ); CATCH_SUCCEED( #__VA_ARGS__ ) 17473 #define CATCH_STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); CATCH_SUCCEED( #__VA_ARGS__ ) 17474 #else 17475 #define CATCH_STATIC_REQUIRE( ... ) CATCH_REQUIRE( __VA_ARGS__ ) 17476 #define CATCH_STATIC_REQUIRE_FALSE( ... ) CATCH_REQUIRE_FALSE( __VA_ARGS__ ) 17477 #endif 17478 17479 // "BDD-style" convenience wrappers 17480 #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) 17481 #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) 17482 #define CATCH_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc ) 17483 #define CATCH_AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc ) 17484 #define CATCH_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc ) 17485 #define CATCH_AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc ) 17486 #define CATCH_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc ) 17487 #define CATCH_AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc ) 17488 17489 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 17490 #define CATCH_BENCHMARK(...) \ 17491 INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,)) 17492 #define CATCH_BENCHMARK_ADVANCED(name) \ 17493 INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), name) 17494 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 17495 17496 // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required 17497 #else 17498 17499 #define REQUIRE( ... ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17500 #define REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 17501 17502 #define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17503 #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) 17504 #define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) 17505 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17506 #define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) 17507 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17508 #define REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17509 17510 #define CHECK( ... ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17511 #define CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 17512 #define CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17513 #define CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17514 #define CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) 17515 17516 #define CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17517 #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) 17518 #define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 17519 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17520 #define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 17521 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17522 #define CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17523 17524 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17525 #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) 17526 17527 #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) 17528 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17529 17530 #define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) 17531 #define UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "UNSCOPED_INFO", msg ) 17532 #define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) 17533 #define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE",__VA_ARGS__ ) 17534 17535 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) 17536 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17537 #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) 17538 #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) 17539 #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) 17540 #define DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ ) 17541 #define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17542 #define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17543 #define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17544 #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE() 17545 17546 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 17547 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17548 #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) 17549 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17550 #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) 17551 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) 17552 #define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) 17553 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17554 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) 17555 #define TEMPLATE_LIST_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(__VA_ARGS__) 17556 #define TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17557 #else 17558 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) ) 17559 #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) ) 17560 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) 17561 #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) ) 17562 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) ) 17563 #define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) ) 17564 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) 17565 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) ) 17566 #define TEMPLATE_LIST_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE( __VA_ARGS__ ) ) 17567 #define TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) 17568 #endif 17569 17570 #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE) 17571 #define STATIC_REQUIRE( ... ) static_assert( __VA_ARGS__, #__VA_ARGS__ ); SUCCEED( #__VA_ARGS__ ) 17572 #define STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); SUCCEED( "!(" #__VA_ARGS__ ")" ) 17573 #else 17574 #define STATIC_REQUIRE( ... ) REQUIRE( __VA_ARGS__ ) 17575 #define STATIC_REQUIRE_FALSE( ... ) REQUIRE_FALSE( __VA_ARGS__ ) 17576 #endif 17577 17578 #endif 17579 17580 #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) 17581 17582 // "BDD-style" convenience wrappers 17583 #define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) 17584 #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) 17585 17586 #define GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc ) 17587 #define AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc ) 17588 #define WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc ) 17589 #define AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc ) 17590 #define THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc ) 17591 #define AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc ) 17592 17593 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 17594 #define BENCHMARK(...) \ 17595 INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,)) 17596 #define BENCHMARK_ADVANCED(name) \ 17597 INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), name) 17598 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 17599 17600 using Catch::Detail::Approx; 17601 17602 #else // CATCH_CONFIG_DISABLE 17603 17604 ////// 17605 // If this config identifier is defined then all CATCH macros are prefixed with CATCH_ 17606 #ifdef CATCH_CONFIG_PREFIX_ALL 17607 17608 #define CATCH_REQUIRE( ... ) (void)(0) 17609 #define CATCH_REQUIRE_FALSE( ... ) (void)(0) 17610 17611 #define CATCH_REQUIRE_THROWS( ... ) (void)(0) 17612 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0) 17613 #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) (void)(0) 17614 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17615 #define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) 17616 #endif// CATCH_CONFIG_DISABLE_MATCHERS 17617 #define CATCH_REQUIRE_NOTHROW( ... ) (void)(0) 17618 17619 #define CATCH_CHECK( ... ) (void)(0) 17620 #define CATCH_CHECK_FALSE( ... ) (void)(0) 17621 #define CATCH_CHECKED_IF( ... ) if (__VA_ARGS__) 17622 #define CATCH_CHECKED_ELSE( ... ) if (!(__VA_ARGS__)) 17623 #define CATCH_CHECK_NOFAIL( ... ) (void)(0) 17624 17625 #define CATCH_CHECK_THROWS( ... ) (void)(0) 17626 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) (void)(0) 17627 #define CATCH_CHECK_THROWS_WITH( expr, matcher ) (void)(0) 17628 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17629 #define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) 17630 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17631 #define CATCH_CHECK_NOTHROW( ... ) (void)(0) 17632 17633 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17634 #define CATCH_CHECK_THAT( arg, matcher ) (void)(0) 17635 17636 #define CATCH_REQUIRE_THAT( arg, matcher ) (void)(0) 17637 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17638 17639 #define CATCH_INFO( msg ) (void)(0) 17640 #define CATCH_UNSCOPED_INFO( msg ) (void)(0) 17641 #define CATCH_WARN( msg ) (void)(0) 17642 #define CATCH_CAPTURE( msg ) (void)(0) 17643 17644 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 17645 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 17646 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) 17647 #define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0) 17648 #define CATCH_SECTION( ... ) 17649 #define CATCH_DYNAMIC_SECTION( ... ) 17650 #define CATCH_FAIL( ... ) (void)(0) 17651 #define CATCH_FAIL_CHECK( ... ) (void)(0) 17652 #define CATCH_SUCCEED( ... ) (void)(0) 17653 17654 #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 17655 17656 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 17657 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) 17658 #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) 17659 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__) 17660 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) 17661 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17662 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17663 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17664 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17665 #else 17666 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) ) 17667 #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) ) 17668 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__ ) ) 17669 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) ) 17670 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17671 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17672 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17673 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17674 #endif 17675 17676 // "BDD-style" convenience wrappers 17677 #define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 17678 #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className ) 17679 #define CATCH_GIVEN( desc ) 17680 #define CATCH_AND_GIVEN( desc ) 17681 #define CATCH_WHEN( desc ) 17682 #define CATCH_AND_WHEN( desc ) 17683 #define CATCH_THEN( desc ) 17684 #define CATCH_AND_THEN( desc ) 17685 17686 #define CATCH_STATIC_REQUIRE( ... ) (void)(0) 17687 #define CATCH_STATIC_REQUIRE_FALSE( ... ) (void)(0) 17688 17689 // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required 17690 #else 17691 17692 #define REQUIRE( ... ) (void)(0) 17693 #define REQUIRE_FALSE( ... ) (void)(0) 17694 17695 #define REQUIRE_THROWS( ... ) (void)(0) 17696 #define REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0) 17697 #define REQUIRE_THROWS_WITH( expr, matcher ) (void)(0) 17698 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17699 #define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) 17700 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17701 #define REQUIRE_NOTHROW( ... ) (void)(0) 17702 17703 #define CHECK( ... ) (void)(0) 17704 #define CHECK_FALSE( ... ) (void)(0) 17705 #define CHECKED_IF( ... ) if (__VA_ARGS__) 17706 #define CHECKED_ELSE( ... ) if (!(__VA_ARGS__)) 17707 #define CHECK_NOFAIL( ... ) (void)(0) 17708 17709 #define CHECK_THROWS( ... ) (void)(0) 17710 #define CHECK_THROWS_AS( expr, exceptionType ) (void)(0) 17711 #define CHECK_THROWS_WITH( expr, matcher ) (void)(0) 17712 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17713 #define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) 17714 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17715 #define CHECK_NOTHROW( ... ) (void)(0) 17716 17717 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17718 #define CHECK_THAT( arg, matcher ) (void)(0) 17719 17720 #define REQUIRE_THAT( arg, matcher ) (void)(0) 17721 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17722 17723 #define INFO( msg ) (void)(0) 17724 #define UNSCOPED_INFO( msg ) (void)(0) 17725 #define WARN( msg ) (void)(0) 17726 #define CAPTURE( msg ) (void)(0) 17727 17728 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 17729 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 17730 #define METHOD_AS_TEST_CASE( method, ... ) 17731 #define REGISTER_TEST_CASE( Function, ... ) (void)(0) 17732 #define SECTION( ... ) 17733 #define DYNAMIC_SECTION( ... ) 17734 #define FAIL( ... ) (void)(0) 17735 #define FAIL_CHECK( ... ) (void)(0) 17736 #define SUCCEED( ... ) (void)(0) 17737 #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 17738 17739 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 17740 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) 17741 #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) 17742 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__) 17743 #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) 17744 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17745 #define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17746 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17747 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17748 #else 17749 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) ) 17750 #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) ) 17751 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__ ) ) 17752 #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) ) 17753 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17754 #define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17755 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17756 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17757 #endif 17758 17759 #define STATIC_REQUIRE( ... ) (void)(0) 17760 #define STATIC_REQUIRE_FALSE( ... ) (void)(0) 17761 17762 #endif 17763 17764 #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) 17765 17766 // "BDD-style" convenience wrappers 17767 #define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) ) 17768 #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className ) 17769 17770 #define GIVEN( desc ) 17771 #define AND_GIVEN( desc ) 17772 #define WHEN( desc ) 17773 #define AND_WHEN( desc ) 17774 #define THEN( desc ) 17775 #define AND_THEN( desc ) 17776 17777 using Catch::Detail::Approx; 17778 17779 #endif 17780 17781 #endif // ! CATCH_CONFIG_IMPL_ONLY 17782 17783 // start catch_reenable_warnings.h 17784 17785 17786 #ifdef __clang__ 17787 # ifdef __ICC // icpc defines the __clang__ macro 17788 # pragma warning(pop) 17789 # else 17790 # pragma clang diagnostic pop 17791 # endif 17792 #elif defined __GNUC__ 17793 # pragma GCC diagnostic pop 17794 #endif 17795 17796 // end catch_reenable_warnings.h 17797 // end catch.hpp 17798 #endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED 17799