1 /* 2 * Catch v2.11.0 3 * Generated: 2019-11-15 15:01:56.628356 4 * ---------------------------------------------------------- 5 * This file has been merged from multiple headers. Please don't edit it directly 6 * Copyright (c) 2019 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 11 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(CATCH_CPP17_OR_GREATER) 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 #endif 145 146 #if defined(__clang__) 147 148 # define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" ) 149 # define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic pop" ) 150 151 # define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 152 _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ 153 _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") 154 155 # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ 156 _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) 157 158 # define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ 159 _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" ) 160 161 # define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ 162 _Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" ) 163 164 # define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 165 _Pragma( "clang diagnostic ignored \"-Wunused-template\"" ) 166 167 #endif // __clang__ 168 169 //////////////////////////////////////////////////////////////////////////////// 170 // Assume that non-Windows platforms support posix signals by default 171 #if !defined(CATCH_PLATFORM_WINDOWS) 172 #define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS 173 #endif 174 175 //////////////////////////////////////////////////////////////////////////////// 176 // We know some environments not to support full POSIX signals 177 #if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__) 178 #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS 179 #endif 180 181 #ifdef __OS400__ 182 # define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS 183 # define CATCH_CONFIG_COLOUR_NONE 184 #endif 185 186 //////////////////////////////////////////////////////////////////////////////// 187 // Android somehow still does not support std::to_string 188 #if defined(__ANDROID__) 189 # define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING 190 # define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE 191 #endif 192 193 //////////////////////////////////////////////////////////////////////////////// 194 // Not all Windows environments support SEH properly 195 #if defined(__MINGW32__) 196 # define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH 197 #endif 198 199 //////////////////////////////////////////////////////////////////////////////// 200 // PS4 201 #if defined(__ORBIS__) 202 # define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE 203 #endif 204 205 //////////////////////////////////////////////////////////////////////////////// 206 // Cygwin 207 #ifdef __CYGWIN__ 208 209 // Required for some versions of Cygwin to declare gettimeofday 210 // see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin 211 # define _BSD_SOURCE 212 // some versions of cygwin (most) do not support std::to_string. Use the libstd check. 213 // https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813 214 # if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \ 215 && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF)) 216 217 # define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING 218 219 # endif 220 #endif // __CYGWIN__ 221 222 //////////////////////////////////////////////////////////////////////////////// 223 // Visual C++ 224 #if defined(_MSC_VER) 225 226 # define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) ) 227 # define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) ) 228 229 # if _MSC_VER >= 1900 // Visual Studio 2015 or newer 230 # define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS 231 # endif 232 233 // Universal Windows platform does not support SEH 234 // Or console colours (or console at all...) 235 # if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) 236 # define CATCH_CONFIG_COLOUR_NONE 237 # else 238 # define CATCH_INTERNAL_CONFIG_WINDOWS_SEH 239 # endif 240 241 // MSVC traditional preprocessor needs some workaround for __VA_ARGS__ 242 // _MSVC_TRADITIONAL == 0 means new conformant preprocessor 243 // _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor 244 # if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) 245 # define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 246 # endif 247 #endif // _MSC_VER 248 249 #if defined(_REENTRANT) || defined(_MSC_VER) 250 // Enable async processing, as -pthread is specified or no additional linking is required 251 # define CATCH_INTERNAL_CONFIG_USE_ASYNC 252 #endif // _MSC_VER 253 254 //////////////////////////////////////////////////////////////////////////////// 255 // Check if we are compiled with -fno-exceptions or equivalent 256 #if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND) 257 # define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED 258 #endif 259 260 //////////////////////////////////////////////////////////////////////////////// 261 // DJGPP 262 #ifdef __DJGPP__ 263 # define CATCH_INTERNAL_CONFIG_NO_WCHAR 264 #endif // __DJGPP__ 265 266 //////////////////////////////////////////////////////////////////////////////// 267 // Embarcadero C++Build 268 #if defined(__BORLANDC__) 269 #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN 270 #endif 271 272 //////////////////////////////////////////////////////////////////////////////// 273 274 // Use of __COUNTER__ is suppressed during code analysis in 275 // CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly 276 // handled by it. 277 // Otherwise all supported compilers support COUNTER macro, 278 // but user still might want to turn it off 279 #if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L ) 280 #define CATCH_INTERNAL_CONFIG_COUNTER 281 #endif 282 283 //////////////////////////////////////////////////////////////////////////////// 284 285 // RTX is a special version of Windows that is real time. 286 // This means that it is detected as Windows, but does not provide 287 // the same set of capabilities as real Windows does. 288 #if defined(UNDER_RTSS) || defined(RTX64_BUILD) 289 #define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH 290 #define CATCH_INTERNAL_CONFIG_NO_ASYNC 291 #define CATCH_CONFIG_COLOUR_NONE 292 #endif 293 294 #if defined(__UCLIBC__) 295 #define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER 296 #endif 297 298 // Various stdlib support checks that require __has_include 299 #if defined(__has_include) 300 // Check if string_view is available and usable 301 #if __has_include(<string_view>) && defined(CATCH_CPP17_OR_GREATER) 302 # define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW 303 #endif 304 305 // Check if optional is available and usable 306 # if __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER) 307 # define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL 308 # endif // __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER) 309 310 // Check if byte is available and usable 311 # if __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER) 312 # define CATCH_INTERNAL_CONFIG_CPP17_BYTE 313 # endif // __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER) 314 315 // Check if variant is available and usable 316 # if __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER) 317 # if defined(__clang__) && (__clang_major__ < 8) 318 // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852 319 // fix should be in clang 8, workaround in libstdc++ 8.2 320 # include <ciso646> 321 # if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) 322 # define CATCH_CONFIG_NO_CPP17_VARIANT 323 # else 324 # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT 325 # endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) 326 # else 327 # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT 328 # endif // defined(__clang__) && (__clang_major__ < 8) 329 # endif // __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER) 330 #endif // defined(__has_include) 331 332 #if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) 333 # define CATCH_CONFIG_COUNTER 334 #endif 335 #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) 336 # define CATCH_CONFIG_WINDOWS_SEH 337 #endif 338 // This is set by default, because we assume that unix compilers are posix-signal-compatible by default. 339 #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) 340 # define CATCH_CONFIG_POSIX_SIGNALS 341 #endif 342 // This is set by default, because we assume that compilers with no wchar_t support are just rare exceptions. 343 #if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR) 344 # define CATCH_CONFIG_WCHAR 345 #endif 346 347 #if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING) 348 # define CATCH_CONFIG_CPP11_TO_STRING 349 #endif 350 351 #if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL) 352 # define CATCH_CONFIG_CPP17_OPTIONAL 353 #endif 354 355 #if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) 356 # define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS 357 #endif 358 359 #if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW) 360 # define CATCH_CONFIG_CPP17_STRING_VIEW 361 #endif 362 363 #if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT) 364 # define CATCH_CONFIG_CPP17_VARIANT 365 #endif 366 367 #if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && !defined(CATCH_CONFIG_NO_CPP17_BYTE) && !defined(CATCH_CONFIG_CPP17_BYTE) 368 # define CATCH_CONFIG_CPP17_BYTE 369 #endif 370 371 #if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) 372 # define CATCH_INTERNAL_CONFIG_NEW_CAPTURE 373 #endif 374 375 #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) 376 # define CATCH_CONFIG_NEW_CAPTURE 377 #endif 378 379 #if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 380 # define CATCH_CONFIG_DISABLE_EXCEPTIONS 381 #endif 382 383 #if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN) 384 # define CATCH_CONFIG_POLYFILL_ISNAN 385 #endif 386 387 #if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC) 388 # define CATCH_CONFIG_USE_ASYNC 389 #endif 390 391 #if defined(CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_NO_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_ANDROID_LOGWRITE) 392 # define CATCH_CONFIG_ANDROID_LOGWRITE 393 #endif 394 395 #if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER) 396 # define CATCH_CONFIG_GLOBAL_NEXTAFTER 397 #endif 398 399 // Even if we do not think the compiler has that warning, we still have 400 // to provide a macro that can be used by the code. 401 #if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION) 402 # define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION 403 #endif 404 #if !defined(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION) 405 # define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 406 #endif 407 #if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) 408 # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS 409 #endif 410 #if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS) 411 # define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS 412 #endif 413 #if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS) 414 # define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS 415 #endif 416 #if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS) 417 # define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS 418 #endif 419 420 #if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10) 421 # undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS 422 #elif defined(__clang__) && (__clang_major__ < 5) 423 # undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS 424 #endif 425 426 #if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS) 427 # define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS 428 #endif 429 430 #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 431 #define CATCH_TRY if ((true)) 432 #define CATCH_CATCH_ALL if ((false)) 433 #define CATCH_CATCH_ANON(type) if ((false)) 434 #else 435 #define CATCH_TRY try 436 #define CATCH_CATCH_ALL catch (...) 437 #define CATCH_CATCH_ANON(type) catch (type) 438 #endif 439 440 #if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) 441 #define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 442 #endif 443 444 // end catch_compiler_capabilities.h 445 #define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line 446 #define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) 447 #ifdef CATCH_CONFIG_COUNTER 448 # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) 449 #else 450 # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) 451 #endif 452 453 #include <iosfwd> 454 #include <string> 455 #include <cstdint> 456 457 // We need a dummy global operator<< so we can bring it into Catch namespace later 458 struct Catch_global_namespace_dummy {}; 459 std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy); 460 461 namespace Catch { 462 463 struct CaseSensitive { enum Choice { 464 Yes, 465 No 466 }; }; 467 468 class NonCopyable { 469 NonCopyable( NonCopyable const& ) = delete; 470 NonCopyable( NonCopyable && ) = delete; 471 NonCopyable& operator = ( NonCopyable const& ) = delete; 472 NonCopyable& operator = ( NonCopyable && ) = delete; 473 474 protected: 475 NonCopyable(); 476 virtual ~NonCopyable(); 477 }; 478 479 struct SourceLineInfo { 480 481 SourceLineInfo() = delete; 482 SourceLineInfo( char const* _file, std::size_t _line ) noexcept 483 : file( _file ), 484 line( _line ) 485 {} 486 487 SourceLineInfo( SourceLineInfo const& other ) = default; 488 SourceLineInfo& operator = ( SourceLineInfo const& ) = default; 489 SourceLineInfo( SourceLineInfo&& ) noexcept = default; 490 SourceLineInfo& operator = ( SourceLineInfo&& ) noexcept = default; 491 492 bool empty() const noexcept { return file[0] == '\0'; } 493 bool operator == ( SourceLineInfo const& other ) const noexcept; 494 bool operator < ( SourceLineInfo const& other ) const noexcept; 495 496 char const* file; 497 std::size_t line; 498 }; 499 500 std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); 501 502 // Bring in operator<< from global namespace into Catch namespace 503 // This is necessary because the overload of operator<< above makes 504 // lookup stop at namespace Catch 505 using ::operator<<; 506 507 // Use this in variadic streaming macros to allow 508 // >> +StreamEndStop 509 // as well as 510 // >> stuff +StreamEndStop 511 struct StreamEndStop { 512 std::string operator+() const; 513 }; 514 template<typename T> 515 T const& operator + ( T const& value, StreamEndStop ) { 516 return value; 517 } 518 } 519 520 #define CATCH_INTERNAL_LINEINFO \ 521 ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) ) 522 523 // end catch_common.h 524 namespace Catch { 525 526 struct RegistrarForTagAliases { 527 RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); 528 }; 529 530 } // end namespace Catch 531 532 #define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \ 533 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 534 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 535 namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \ 536 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 537 538 // end catch_tag_alias_autoregistrar.h 539 // start catch_test_registry.h 540 541 // start catch_interfaces_testcase.h 542 543 #include <vector> 544 545 namespace Catch { 546 547 class TestSpec; 548 549 struct ITestInvoker { 550 virtual void invoke () const = 0; 551 virtual ~ITestInvoker(); 552 }; 553 554 class TestCase; 555 struct IConfig; 556 557 struct ITestCaseRegistry { 558 virtual ~ITestCaseRegistry(); 559 virtual std::vector<TestCase> const& getAllTests() const = 0; 560 virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const = 0; 561 }; 562 563 bool isThrowSafe( TestCase const& testCase, IConfig const& config ); 564 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); 565 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ); 566 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ); 567 568 } 569 570 // end catch_interfaces_testcase.h 571 // start catch_stringref.h 572 573 #include <cstddef> 574 #include <string> 575 #include <iosfwd> 576 #include <cassert> 577 578 namespace Catch { 579 580 /// A non-owning string class (similar to the forthcoming std::string_view) 581 /// Note that, because a StringRef may be a substring of another string, 582 /// it may not be null terminated. 583 class StringRef { 584 public: 585 using size_type = std::size_t; 586 using const_iterator = const char*; 587 588 private: 589 static constexpr char const* const s_empty = ""; 590 591 char const* m_start = s_empty; 592 size_type m_size = 0; 593 594 public: // construction 595 constexpr StringRef() noexcept = default; 596 597 StringRef( char const* rawChars ) noexcept; 598 599 constexpr StringRef( char const* rawChars, size_type size ) noexcept 600 : m_start( rawChars ), 601 m_size( size ) 602 {} 603 604 StringRef( std::string const& stdString ) noexcept 605 : m_start( stdString.c_str() ), 606 m_size( stdString.size() ) 607 {} 608 609 explicit operator std::string() const { 610 return std::string(m_start, m_size); 611 } 612 613 public: // operators 614 auto operator == ( StringRef const& other ) const noexcept -> bool; 615 auto operator != (StringRef const& other) const noexcept -> bool { 616 return !(*this == other); 617 } 618 619 auto operator[] ( size_type index ) const noexcept -> char { 620 assert(index < m_size); 621 return m_start[index]; 622 } 623 624 public: // named queries 625 constexpr auto empty() const noexcept -> bool { 626 return m_size == 0; 627 } 628 constexpr auto size() const noexcept -> size_type { 629 return m_size; 630 } 631 632 // Returns the current start pointer. If the StringRef is not 633 // null-terminated, throws std::domain_exception 634 auto c_str() const -> char const*; 635 636 public: // substrings and searches 637 // Returns a substring of [start, start + length). 638 // If start + length > size(), then the substring is [start, size()). 639 // If start > size(), then the substring is empty. 640 auto substr( size_type start, size_type length ) const noexcept -> StringRef; 641 642 // Returns the current start pointer. May not be null-terminated. 643 auto data() const noexcept -> char const*; 644 645 constexpr auto isNullTerminated() const noexcept -> bool { 646 return m_start[m_size] == '\0'; 647 } 648 649 public: // iterators 650 constexpr const_iterator begin() const { return m_start; } 651 constexpr const_iterator end() const { return m_start + m_size; } 652 }; 653 654 auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&; 655 auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&; 656 657 constexpr auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef { 658 return StringRef( rawChars, size ); 659 } 660 } // namespace Catch 661 662 constexpr auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef { 663 return Catch::StringRef( rawChars, size ); 664 } 665 666 // end catch_stringref.h 667 // start catch_preprocessor.hpp 668 669 670 #define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__ 671 #define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__))) 672 #define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__))) 673 #define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__))) 674 #define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__))) 675 #define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__))) 676 677 #ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 678 #define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__ 679 // MSVC needs more evaluations 680 #define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__))) 681 #define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__)) 682 #else 683 #define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL5(__VA_ARGS__) 684 #endif 685 686 #define CATCH_REC_END(...) 687 #define CATCH_REC_OUT 688 689 #define CATCH_EMPTY() 690 #define CATCH_DEFER(id) id CATCH_EMPTY() 691 692 #define CATCH_REC_GET_END2() 0, CATCH_REC_END 693 #define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2 694 #define CATCH_REC_GET_END(...) CATCH_REC_GET_END1 695 #define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT 696 #define CATCH_REC_NEXT1(test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0) 697 #define CATCH_REC_NEXT(test, next) CATCH_REC_NEXT1(CATCH_REC_GET_END test, next) 698 699 #define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) 700 #define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ ) 701 #define CATCH_REC_LIST2(f, x, peek, ...) f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) 702 703 #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__ ) 704 #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__ ) 705 #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__ ) 706 707 // Applies the function macro `f` to each of the remaining parameters, inserts commas between the results, 708 // and passes userdata as the first parameter to each invocation, 709 // e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c) 710 #define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) 711 712 #define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) 713 714 #define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param) 715 #define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__ 716 #define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__ 717 #define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF 718 #define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__) 719 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 720 #define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__ 721 #define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) 722 #else 723 // MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF 724 #define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__) 725 #define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__ 726 #define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1) 727 #endif 728 729 #define INTERNAL_CATCH_MAKE_NAMESPACE2(...) ns_##__VA_ARGS__ 730 #define INTERNAL_CATCH_MAKE_NAMESPACE(name) INTERNAL_CATCH_MAKE_NAMESPACE2(name) 731 732 #define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__) 733 734 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 735 #define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS_GEN(__VA_ARGS__)>()) 736 #define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)) 737 #else 738 #define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) INTERNAL_CATCH_EXPAND_VARGS(decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS_GEN(__VA_ARGS__)>())) 739 #define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))) 740 #endif 741 742 #define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(...)\ 743 CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,__VA_ARGS__) 744 745 #define INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_0) INTERNAL_CATCH_REMOVE_PARENS(_0) 746 #define INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_0, _1) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_1) 747 #define INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_0, _1, _2) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_1, _2) 748 #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) 749 #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) 750 #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) 751 #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, _4, _5, _6) 752 #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) 753 #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) 754 #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) 755 #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) 756 757 #define INTERNAL_CATCH_VA_NARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N 758 759 #define INTERNAL_CATCH_TYPE_GEN\ 760 template<typename...> struct TypeList {};\ 761 template<typename...Ts>\ 762 constexpr auto get_wrapper() noexcept -> TypeList<Ts...> { return {}; }\ 763 template<template<typename...> class...> struct TemplateTypeList{};\ 764 template<template<typename...> class...Cs>\ 765 constexpr auto get_wrapper() noexcept -> TemplateTypeList<Cs...> { return {}; }\ 766 template<typename...>\ 767 struct append;\ 768 template<typename...>\ 769 struct rewrap;\ 770 template<template<typename...> class, typename...>\ 771 struct create;\ 772 template<template<typename...> class, typename>\ 773 struct convert;\ 774 \ 775 template<typename T> \ 776 struct append<T> { using type = T; };\ 777 template< template<typename...> class L1, typename...E1, template<typename...> class L2, typename...E2, typename...Rest>\ 778 struct append<L1<E1...>, L2<E2...>, Rest...> { using type = typename append<L1<E1...,E2...>, Rest...>::type; };\ 779 template< template<typename...> class L1, typename...E1, typename...Rest>\ 780 struct append<L1<E1...>, TypeList<mpl_::na>, Rest...> { using type = L1<E1...>; };\ 781 \ 782 template< template<typename...> class Container, template<typename...> class List, typename...elems>\ 783 struct rewrap<TemplateTypeList<Container>, List<elems...>> { using type = TypeList<Container<elems...>>; };\ 784 template< template<typename...> class Container, template<typename...> class List, class...Elems, typename...Elements>\ 785 struct rewrap<TemplateTypeList<Container>, List<Elems...>, Elements...> { using type = typename append<TypeList<Container<Elems...>>, typename rewrap<TemplateTypeList<Container>, Elements...>::type>::type; };\ 786 \ 787 template<template <typename...> class Final, template< typename...> class...Containers, typename...Types>\ 788 struct create<Final, TemplateTypeList<Containers...>, TypeList<Types...>> { using type = typename append<Final<>, typename rewrap<TemplateTypeList<Containers>, Types...>::type...>::type; };\ 789 template<template <typename...> class Final, template <typename...> class List, typename...Ts>\ 790 struct convert<Final, List<Ts...>> { using type = typename append<Final<>,TypeList<Ts>...>::type; }; 791 792 #define INTERNAL_CATCH_NTTP_1(signature, ...)\ 793 template<INTERNAL_CATCH_REMOVE_PARENS(signature)> struct Nttp{};\ 794 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 795 constexpr auto get_wrapper() noexcept -> Nttp<__VA_ARGS__> { return {}; } \ 796 template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...> struct NttpTemplateTypeList{};\ 797 template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...Cs>\ 798 constexpr auto get_wrapper() noexcept -> NttpTemplateTypeList<Cs...> { return {}; } \ 799 \ 800 template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 801 struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>> { using type = TypeList<Container<__VA_ARGS__>>; };\ 802 template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature), typename...Elements>\ 803 struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>, Elements...> { using type = typename append<TypeList<Container<__VA_ARGS__>>, typename rewrap<NttpTemplateTypeList<Container>, Elements...>::type>::type; };\ 804 template<template <typename...> class Final, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...Containers, typename...Types>\ 805 struct create<Final, NttpTemplateTypeList<Containers...>, TypeList<Types...>> { using type = typename append<Final<>, typename rewrap<NttpTemplateTypeList<Containers>, Types...>::type...>::type; }; 806 807 #define INTERNAL_CATCH_DECLARE_SIG_TEST0(TestName) 808 #define INTERNAL_CATCH_DECLARE_SIG_TEST1(TestName, signature)\ 809 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 810 static void TestName() 811 #define INTERNAL_CATCH_DECLARE_SIG_TEST_X(TestName, signature, ...)\ 812 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 813 static void TestName() 814 815 #define INTERNAL_CATCH_DEFINE_SIG_TEST0(TestName) 816 #define INTERNAL_CATCH_DEFINE_SIG_TEST1(TestName, signature)\ 817 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 818 static void TestName() 819 #define INTERNAL_CATCH_DEFINE_SIG_TEST_X(TestName, signature,...)\ 820 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 821 static void TestName() 822 823 #define INTERNAL_CATCH_NTTP_REGISTER0(TestFunc, signature)\ 824 template<typename Type>\ 825 void reg_test(TypeList<Type>, Catch::NameAndTags nameAndTags)\ 826 {\ 827 Catch::AutoReg( Catch::makeTestInvoker(&TestFunc<Type>), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), nameAndTags);\ 828 } 829 830 #define INTERNAL_CATCH_NTTP_REGISTER(TestFunc, signature, ...)\ 831 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 832 void reg_test(Nttp<__VA_ARGS__>, Catch::NameAndTags nameAndTags)\ 833 {\ 834 Catch::AutoReg( Catch::makeTestInvoker(&TestFunc<__VA_ARGS__>), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), nameAndTags);\ 835 } 836 837 #define INTERNAL_CATCH_NTTP_REGISTER_METHOD0(TestName, signature, ...)\ 838 template<typename Type>\ 839 void reg_test(TypeList<Type>, Catch::StringRef className, Catch::NameAndTags nameAndTags)\ 840 {\ 841 Catch::AutoReg( Catch::makeTestInvoker(&TestName<Type>::test), CATCH_INTERNAL_LINEINFO, className, nameAndTags);\ 842 } 843 844 #define INTERNAL_CATCH_NTTP_REGISTER_METHOD(TestName, signature, ...)\ 845 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 846 void reg_test(Nttp<__VA_ARGS__>, Catch::StringRef className, Catch::NameAndTags nameAndTags)\ 847 {\ 848 Catch::AutoReg( Catch::makeTestInvoker(&TestName<__VA_ARGS__>::test), CATCH_INTERNAL_LINEINFO, className, nameAndTags);\ 849 } 850 851 #define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0(TestName, ClassName) 852 #define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1(TestName, ClassName, signature)\ 853 template<typename TestType> \ 854 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName)<TestType> { \ 855 void test();\ 856 } 857 858 #define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X(TestName, ClassName, signature, ...)\ 859 template<INTERNAL_CATCH_REMOVE_PARENS(signature)> \ 860 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName)<__VA_ARGS__> { \ 861 void test();\ 862 } 863 864 #define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0(TestName) 865 #define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1(TestName, signature)\ 866 template<typename TestType> \ 867 void INTERNAL_CATCH_MAKE_NAMESPACE(TestName)::TestName<TestType>::test() 868 #define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X(TestName, signature, ...)\ 869 template<INTERNAL_CATCH_REMOVE_PARENS(signature)> \ 870 void INTERNAL_CATCH_MAKE_NAMESPACE(TestName)::TestName<__VA_ARGS__>::test() 871 872 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 873 #define INTERNAL_CATCH_NTTP_0 874 #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) 875 #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__) 876 #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__) 877 #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__) 878 #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__) 879 #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__) 880 #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__) 881 #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__) 882 #else 883 #define INTERNAL_CATCH_NTTP_0(signature) 884 #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__)) 885 #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__)) 886 #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__)) 887 #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__)) 888 #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__)) 889 #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__)) 890 #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__)) 891 #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__)) 892 #endif 893 894 // end catch_preprocessor.hpp 895 // start catch_meta.hpp 896 897 898 #include <type_traits> 899 900 namespace Catch { 901 template<typename T> 902 struct always_false : std::false_type {}; 903 904 template <typename> struct true_given : std::true_type {}; 905 struct is_callable_tester { 906 template <typename Fun, typename... Args> 907 true_given<decltype(std::declval<Fun>()(std::declval<Args>()...))> static test(int); 908 template <typename...> 909 std::false_type static test(...); 910 }; 911 912 template <typename T> 913 struct is_callable; 914 915 template <typename Fun, typename... Args> 916 struct is_callable<Fun(Args...)> : decltype(is_callable_tester::test<Fun, Args...>(0)) {}; 917 918 #if defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703 919 // std::result_of is deprecated in C++17 and removed in C++20. Hence, it is 920 // replaced with std::invoke_result here. Also *_t format is preferred over 921 // typename *::type format. 922 template <typename Func, typename U> 923 using FunctionReturnType = std::remove_reference_t<std::remove_cv_t<std::invoke_result_t<Func, U>>>; 924 #else 925 template <typename Func, typename U> 926 using FunctionReturnType = typename std::remove_reference<typename std::remove_cv<typename std::result_of<Func(U)>::type>::type>::type; 927 #endif 928 929 } // namespace Catch 930 931 namespace mpl_{ 932 struct na; 933 } 934 935 // end catch_meta.hpp 936 namespace Catch { 937 938 template<typename C> 939 class TestInvokerAsMethod : public ITestInvoker { 940 void (C::*m_testAsMethod)(); 941 public: 942 TestInvokerAsMethod( void (C::*testAsMethod)() ) noexcept : m_testAsMethod( testAsMethod ) {} 943 944 void invoke() const override { 945 C obj; 946 (obj.*m_testAsMethod)(); 947 } 948 }; 949 950 auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker*; 951 952 template<typename C> 953 auto makeTestInvoker( void (C::*testAsMethod)() ) noexcept -> ITestInvoker* { 954 return new(std::nothrow) TestInvokerAsMethod<C>( testAsMethod ); 955 } 956 957 struct NameAndTags { 958 NameAndTags( StringRef const& name_ = StringRef(), StringRef const& tags_ = StringRef() ) noexcept; 959 StringRef name; 960 StringRef tags; 961 }; 962 963 struct AutoReg : NonCopyable { 964 AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept; 965 ~AutoReg(); 966 }; 967 968 } // end namespace Catch 969 970 #if defined(CATCH_CONFIG_DISABLE) 971 #define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \ 972 static void TestName() 973 #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \ 974 namespace{ \ 975 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \ 976 void test(); \ 977 }; \ 978 } \ 979 void TestName::test() 980 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( TestName, TestFunc, Name, Tags, Signature, ... ) \ 981 INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature)) 982 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \ 983 namespace{ \ 984 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) { \ 985 INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, INTERNAL_CATCH_REMOVE_PARENS(Signature));\ 986 } \ 987 } \ 988 INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature)) 989 990 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 991 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \ 992 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__ ) 993 #else 994 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \ 995 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__ ) ) 996 #endif 997 998 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 999 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \ 1000 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__ ) 1001 #else 1002 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \ 1003 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__ ) ) 1004 #endif 1005 1006 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1007 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \ 1008 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__ ) 1009 #else 1010 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \ 1011 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__ ) ) 1012 #endif 1013 1014 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1015 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \ 1016 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__ ) 1017 #else 1018 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \ 1019 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__ ) ) 1020 #endif 1021 #endif 1022 1023 /////////////////////////////////////////////////////////////////////////////// 1024 #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ 1025 static void TestName(); \ 1026 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1027 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1028 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \ 1029 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1030 static void TestName() 1031 #define INTERNAL_CATCH_TESTCASE( ... ) \ 1032 INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ ) 1033 1034 /////////////////////////////////////////////////////////////////////////////// 1035 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ 1036 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1037 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1038 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &QualifiedMethod ), CATCH_INTERNAL_LINEINFO, "&" #QualifiedMethod, Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \ 1039 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 1040 1041 /////////////////////////////////////////////////////////////////////////////// 1042 #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ 1043 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1044 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1045 namespace{ \ 1046 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \ 1047 void test(); \ 1048 }; \ 1049 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ 1050 } \ 1051 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1052 void TestName::test() 1053 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \ 1054 INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ ) 1055 1056 /////////////////////////////////////////////////////////////////////////////// 1057 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ 1058 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1059 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1060 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ 1061 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 1062 1063 /////////////////////////////////////////////////////////////////////////////// 1064 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_2(TestName, TestFunc, Name, Tags, Signature, ... )\ 1065 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1066 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1067 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ 1068 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 1069 INTERNAL_CATCH_DECLARE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature));\ 1070 namespace {\ 1071 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\ 1072 INTERNAL_CATCH_TYPE_GEN\ 1073 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\ 1074 INTERNAL_CATCH_NTTP_REG_GEN(TestFunc,INTERNAL_CATCH_REMOVE_PARENS(Signature))\ 1075 template<typename...Types> \ 1076 struct TestName{\ 1077 TestName(){\ 1078 int index = 0; \ 1079 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\ 1080 using expander = int[];\ 1081 (void)expander{(reg_test(Types{}, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++, 0)... };/* NOLINT */ \ 1082 }\ 1083 };\ 1084 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ 1085 TestName<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(__VA_ARGS__)>();\ 1086 return 0;\ 1087 }();\ 1088 }\ 1089 }\ 1090 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1091 INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc,INTERNAL_CATCH_REMOVE_PARENS(Signature)) 1092 1093 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1094 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \ 1095 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__ ) 1096 #else 1097 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \ 1098 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__ ) ) 1099 #endif 1100 1101 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1102 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \ 1103 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__ ) 1104 #else 1105 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \ 1106 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__ ) ) 1107 #endif 1108 1109 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(TestName, TestFuncName, Name, Tags, Signature, TmplTypes, TypesList) \ 1110 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1111 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1112 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ 1113 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 1114 template<typename TestType> static void TestFuncName(); \ 1115 namespace {\ 1116 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) { \ 1117 INTERNAL_CATCH_TYPE_GEN \ 1118 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature)) \ 1119 template<typename... Types> \ 1120 struct TestName { \ 1121 void reg_tests() { \ 1122 int index = 0; \ 1123 using expander = int[]; \ 1124 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\ 1125 constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\ 1126 constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\ 1127 (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 */\ 1128 } \ 1129 }; \ 1130 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \ 1131 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; \ 1132 TestInit t; \ 1133 t.reg_tests(); \ 1134 return 0; \ 1135 }(); \ 1136 } \ 1137 } \ 1138 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1139 template<typename TestType> \ 1140 static void TestFuncName() 1141 1142 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1143 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\ 1144 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__) 1145 #else 1146 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\ 1147 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__ ) ) 1148 #endif 1149 1150 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1151 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\ 1152 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__) 1153 #else 1154 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\ 1155 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__ ) ) 1156 #endif 1157 1158 #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2(TestName, TestFunc, Name, Tags, TmplList)\ 1159 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1160 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1161 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 1162 template<typename TestType> static void TestFunc(); \ 1163 namespace {\ 1164 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\ 1165 INTERNAL_CATCH_TYPE_GEN\ 1166 template<typename... Types> \ 1167 struct TestName { \ 1168 void reg_tests() { \ 1169 int index = 0; \ 1170 using expander = int[]; \ 1171 (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 */\ 1172 } \ 1173 };\ 1174 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \ 1175 using TestInit = typename convert<TestName, TmplList>::type; \ 1176 TestInit t; \ 1177 t.reg_tests(); \ 1178 return 0; \ 1179 }(); \ 1180 }}\ 1181 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1182 template<typename TestType> \ 1183 static void TestFunc() 1184 1185 #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(Name, Tags, TmplList) \ 1186 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 ) 1187 1188 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \ 1189 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1190 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1191 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ 1192 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 1193 namespace {\ 1194 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \ 1195 INTERNAL_CATCH_TYPE_GEN\ 1196 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\ 1197 INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, INTERNAL_CATCH_REMOVE_PARENS(Signature));\ 1198 INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))\ 1199 template<typename...Types> \ 1200 struct TestNameClass{\ 1201 TestNameClass(){\ 1202 int index = 0; \ 1203 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\ 1204 using expander = int[];\ 1205 (void)expander{(reg_test(Types{}, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++, 0)... };/* NOLINT */ \ 1206 }\ 1207 };\ 1208 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ 1209 TestNameClass<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(__VA_ARGS__)>();\ 1210 return 0;\ 1211 }();\ 1212 }\ 1213 }\ 1214 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1215 INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature)) 1216 1217 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1218 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \ 1219 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__ ) 1220 #else 1221 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \ 1222 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__ ) ) 1223 #endif 1224 1225 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1226 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \ 1227 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__ ) 1228 #else 1229 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \ 1230 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__ ) ) 1231 #endif 1232 1233 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2(TestNameClass, TestName, ClassName, Name, Tags, Signature, TmplTypes, TypesList)\ 1234 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1235 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1236 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ 1237 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 1238 template<typename TestType> \ 1239 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \ 1240 void test();\ 1241 };\ 1242 namespace {\ 1243 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestNameClass) {\ 1244 INTERNAL_CATCH_TYPE_GEN \ 1245 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\ 1246 template<typename...Types>\ 1247 struct TestNameClass{\ 1248 void reg_tests(){\ 1249 int index = 0;\ 1250 using expander = int[];\ 1251 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\ 1252 constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\ 1253 constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\ 1254 (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 */ \ 1255 }\ 1256 };\ 1257 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ 1258 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;\ 1259 TestInit t;\ 1260 t.reg_tests();\ 1261 return 0;\ 1262 }(); \ 1263 }\ 1264 }\ 1265 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1266 template<typename TestType> \ 1267 void TestName<TestType>::test() 1268 1269 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1270 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\ 1271 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__ ) 1272 #else 1273 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\ 1274 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__ ) ) 1275 #endif 1276 1277 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1278 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\ 1279 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__ ) 1280 #else 1281 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\ 1282 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__ ) ) 1283 #endif 1284 1285 #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, TmplList) \ 1286 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1287 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1288 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 1289 template<typename TestType> \ 1290 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \ 1291 void test();\ 1292 };\ 1293 namespace {\ 1294 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \ 1295 INTERNAL_CATCH_TYPE_GEN\ 1296 template<typename...Types>\ 1297 struct TestNameClass{\ 1298 void reg_tests(){\ 1299 int index = 0;\ 1300 using expander = int[];\ 1301 (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 */ \ 1302 }\ 1303 };\ 1304 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ 1305 using TestInit = typename convert<TestNameClass, TmplList>::type;\ 1306 TestInit t;\ 1307 t.reg_tests();\ 1308 return 0;\ 1309 }(); \ 1310 }}\ 1311 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1312 template<typename TestType> \ 1313 void TestName<TestType>::test() 1314 1315 #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD(ClassName, Name, Tags, TmplList) \ 1316 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 ) 1317 1318 // end catch_test_registry.h 1319 // start catch_capture.hpp 1320 1321 // start catch_assertionhandler.h 1322 1323 // start catch_assertioninfo.h 1324 1325 // start catch_result_type.h 1326 1327 namespace Catch { 1328 1329 // ResultWas::OfType enum 1330 struct ResultWas { enum OfType { 1331 Unknown = -1, 1332 Ok = 0, 1333 Info = 1, 1334 Warning = 2, 1335 1336 FailureBit = 0x10, 1337 1338 ExpressionFailed = FailureBit | 1, 1339 ExplicitFailure = FailureBit | 2, 1340 1341 Exception = 0x100 | FailureBit, 1342 1343 ThrewException = Exception | 1, 1344 DidntThrowException = Exception | 2, 1345 1346 FatalErrorCondition = 0x200 | FailureBit 1347 1348 }; }; 1349 1350 bool isOk( ResultWas::OfType resultType ); 1351 bool isJustInfo( int flags ); 1352 1353 // ResultDisposition::Flags enum 1354 struct ResultDisposition { enum Flags { 1355 Normal = 0x01, 1356 1357 ContinueOnFailure = 0x02, // Failures fail test, but execution continues 1358 FalseTest = 0x04, // Prefix expression with ! 1359 SuppressFail = 0x08 // Failures are reported but do not fail the test 1360 }; }; 1361 1362 ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ); 1363 1364 bool shouldContinueOnFailure( int flags ); 1365 inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; } 1366 bool shouldSuppressFailure( int flags ); 1367 1368 } // end namespace Catch 1369 1370 // end catch_result_type.h 1371 namespace Catch { 1372 1373 struct AssertionInfo 1374 { 1375 StringRef macroName; 1376 SourceLineInfo lineInfo; 1377 StringRef capturedExpression; 1378 ResultDisposition::Flags resultDisposition; 1379 1380 // We want to delete this constructor but a compiler bug in 4.8 means 1381 // the struct is then treated as non-aggregate 1382 //AssertionInfo() = delete; 1383 }; 1384 1385 } // end namespace Catch 1386 1387 // end catch_assertioninfo.h 1388 // start catch_decomposer.h 1389 1390 // start catch_tostring.h 1391 1392 #include <vector> 1393 #include <cstddef> 1394 #include <type_traits> 1395 #include <string> 1396 // start catch_stream.h 1397 1398 #include <iosfwd> 1399 #include <cstddef> 1400 #include <ostream> 1401 1402 namespace Catch { 1403 1404 std::ostream& cout(); 1405 std::ostream& cerr(); 1406 std::ostream& clog(); 1407 1408 class StringRef; 1409 1410 struct IStream { 1411 virtual ~IStream(); 1412 virtual std::ostream& stream() const = 0; 1413 }; 1414 1415 auto makeStream( StringRef const &filename ) -> IStream const*; 1416 1417 class ReusableStringStream : NonCopyable { 1418 std::size_t m_index; 1419 std::ostream* m_oss; 1420 public: 1421 ReusableStringStream(); 1422 ~ReusableStringStream(); 1423 1424 auto str() const -> std::string; 1425 1426 template<typename T> 1427 auto operator << ( T const& value ) -> ReusableStringStream& { 1428 *m_oss << value; 1429 return *this; 1430 } 1431 auto get() -> std::ostream& { return *m_oss; } 1432 }; 1433 } 1434 1435 // end catch_stream.h 1436 // start catch_interfaces_enum_values_registry.h 1437 1438 #include <vector> 1439 1440 namespace Catch { 1441 1442 namespace Detail { 1443 struct EnumInfo { 1444 StringRef m_name; 1445 std::vector<std::pair<int, StringRef>> m_values; 1446 1447 ~EnumInfo(); 1448 1449 StringRef lookup( int value ) const; 1450 }; 1451 } // namespace Detail 1452 1453 struct IMutableEnumValuesRegistry { 1454 virtual ~IMutableEnumValuesRegistry(); 1455 1456 virtual Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::vector<int> const& values ) = 0; 1457 1458 template<typename E> 1459 Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::initializer_list<E> values ) { 1460 static_assert(sizeof(int) >= sizeof(E), "Cannot serialize enum to int"); 1461 std::vector<int> intValues; 1462 intValues.reserve( values.size() ); 1463 for( auto enumValue : values ) 1464 intValues.push_back( static_cast<int>( enumValue ) ); 1465 return registerEnum( enumName, allEnums, intValues ); 1466 } 1467 }; 1468 1469 } // Catch 1470 1471 // end catch_interfaces_enum_values_registry.h 1472 1473 #ifdef CATCH_CONFIG_CPP17_STRING_VIEW 1474 #include <string_view> 1475 #endif 1476 1477 #ifdef __OBJC__ 1478 // start catch_objc_arc.hpp 1479 1480 #import <Foundation/Foundation.h> 1481 1482 #ifdef __has_feature 1483 #define CATCH_ARC_ENABLED __has_feature(objc_arc) 1484 #else 1485 #define CATCH_ARC_ENABLED 0 1486 #endif 1487 1488 void arcSafeRelease( NSObject* obj ); 1489 id performOptionalSelector( id obj, SEL sel ); 1490 1491 #if !CATCH_ARC_ENABLED 1492 inline void arcSafeRelease( NSObject* obj ) { 1493 [obj release]; 1494 } 1495 inline id performOptionalSelector( id obj, SEL sel ) { 1496 if( [obj respondsToSelector: sel] ) 1497 return [obj performSelector: sel]; 1498 return nil; 1499 } 1500 #define CATCH_UNSAFE_UNRETAINED 1501 #define CATCH_ARC_STRONG 1502 #else 1503 inline void arcSafeRelease( NSObject* ){} 1504 inline id performOptionalSelector( id obj, SEL sel ) { 1505 #ifdef __clang__ 1506 #pragma clang diagnostic push 1507 #pragma clang diagnostic ignored "-Warc-performSelector-leaks" 1508 #endif 1509 if( [obj respondsToSelector: sel] ) 1510 return [obj performSelector: sel]; 1511 #ifdef __clang__ 1512 #pragma clang diagnostic pop 1513 #endif 1514 return nil; 1515 } 1516 #define CATCH_UNSAFE_UNRETAINED __unsafe_unretained 1517 #define CATCH_ARC_STRONG __strong 1518 #endif 1519 1520 // end catch_objc_arc.hpp 1521 #endif 1522 1523 #ifdef _MSC_VER 1524 #pragma warning(push) 1525 #pragma warning(disable:4180) // We attempt to stream a function (address) by const&, which MSVC complains about but is harmless 1526 #endif 1527 1528 namespace Catch { 1529 namespace Detail { 1530 1531 extern const std::string unprintableString; 1532 1533 std::string rawMemoryToString( const void *object, std::size_t size ); 1534 1535 template<typename T> 1536 std::string rawMemoryToString( const T& object ) { 1537 return rawMemoryToString( &object, sizeof(object) ); 1538 } 1539 1540 template<typename T> 1541 class IsStreamInsertable { 1542 template<typename Stream, typename U> 1543 static auto test(int) 1544 -> decltype(std::declval<Stream&>() << std::declval<U>(), std::true_type()); 1545 1546 template<typename, typename> 1547 static auto test(...)->std::false_type; 1548 1549 public: 1550 static const bool value = decltype(test<std::ostream, const T&>(0))::value; 1551 }; 1552 1553 template<typename E> 1554 std::string convertUnknownEnumToString( E e ); 1555 1556 template<typename T> 1557 typename std::enable_if< 1558 !std::is_enum<T>::value && !std::is_base_of<std::exception, T>::value, 1559 std::string>::type convertUnstreamable( T const& ) { 1560 return Detail::unprintableString; 1561 } 1562 template<typename T> 1563 typename std::enable_if< 1564 !std::is_enum<T>::value && std::is_base_of<std::exception, T>::value, 1565 std::string>::type convertUnstreamable(T const& ex) { 1566 return ex.what(); 1567 } 1568 1569 template<typename T> 1570 typename std::enable_if< 1571 std::is_enum<T>::value 1572 , std::string>::type convertUnstreamable( T const& value ) { 1573 return convertUnknownEnumToString( value ); 1574 } 1575 1576 #if defined(_MANAGED) 1577 //! Convert a CLR string to a utf8 std::string 1578 template<typename T> 1579 std::string clrReferenceToString( T^ ref ) { 1580 if (ref == nullptr) 1581 return std::string("null"); 1582 auto bytes = System::Text::Encoding::UTF8->GetBytes(ref->ToString()); 1583 cli::pin_ptr<System::Byte> p = &bytes[0]; 1584 return std::string(reinterpret_cast<char const *>(p), bytes->Length); 1585 } 1586 #endif 1587 1588 } // namespace Detail 1589 1590 // If we decide for C++14, change these to enable_if_ts 1591 template <typename T, typename = void> 1592 struct StringMaker { 1593 template <typename Fake = T> 1594 static 1595 typename std::enable_if<::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type 1596 convert(const Fake& value) { 1597 ReusableStringStream rss; 1598 // NB: call using the function-like syntax to avoid ambiguity with 1599 // user-defined templated operator<< under clang. 1600 rss.operator<<(value); 1601 return rss.str(); 1602 } 1603 1604 template <typename Fake = T> 1605 static 1606 typename std::enable_if<!::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type 1607 convert( const Fake& value ) { 1608 #if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER) 1609 return Detail::convertUnstreamable(value); 1610 #else 1611 return CATCH_CONFIG_FALLBACK_STRINGIFIER(value); 1612 #endif 1613 } 1614 }; 1615 1616 namespace Detail { 1617 1618 // This function dispatches all stringification requests inside of Catch. 1619 // Should be preferably called fully qualified, like ::Catch::Detail::stringify 1620 template <typename T> 1621 std::string stringify(const T& e) { 1622 return ::Catch::StringMaker<typename std::remove_cv<typename std::remove_reference<T>::type>::type>::convert(e); 1623 } 1624 1625 template<typename E> 1626 std::string convertUnknownEnumToString( E e ) { 1627 return ::Catch::Detail::stringify(static_cast<typename std::underlying_type<E>::type>(e)); 1628 } 1629 1630 #if defined(_MANAGED) 1631 template <typename T> 1632 std::string stringify( T^ e ) { 1633 return ::Catch::StringMaker<T^>::convert(e); 1634 } 1635 #endif 1636 1637 } // namespace Detail 1638 1639 // Some predefined specializations 1640 1641 template<> 1642 struct StringMaker<std::string> { 1643 static std::string convert(const std::string& str); 1644 }; 1645 1646 #ifdef CATCH_CONFIG_CPP17_STRING_VIEW 1647 template<> 1648 struct StringMaker<std::string_view> { 1649 static std::string convert(std::string_view str); 1650 }; 1651 #endif 1652 1653 template<> 1654 struct StringMaker<char const *> { 1655 static std::string convert(char const * str); 1656 }; 1657 template<> 1658 struct StringMaker<char *> { 1659 static std::string convert(char * str); 1660 }; 1661 1662 #ifdef CATCH_CONFIG_WCHAR 1663 template<> 1664 struct StringMaker<std::wstring> { 1665 static std::string convert(const std::wstring& wstr); 1666 }; 1667 1668 # ifdef CATCH_CONFIG_CPP17_STRING_VIEW 1669 template<> 1670 struct StringMaker<std::wstring_view> { 1671 static std::string convert(std::wstring_view str); 1672 }; 1673 # endif 1674 1675 template<> 1676 struct StringMaker<wchar_t const *> { 1677 static std::string convert(wchar_t const * str); 1678 }; 1679 template<> 1680 struct StringMaker<wchar_t *> { 1681 static std::string convert(wchar_t * str); 1682 }; 1683 #endif 1684 1685 // TBD: Should we use `strnlen` to ensure that we don't go out of the buffer, 1686 // while keeping string semantics? 1687 template<int SZ> 1688 struct StringMaker<char[SZ]> { 1689 static std::string convert(char const* str) { 1690 return ::Catch::Detail::stringify(std::string{ str }); 1691 } 1692 }; 1693 template<int SZ> 1694 struct StringMaker<signed char[SZ]> { 1695 static std::string convert(signed char const* str) { 1696 return ::Catch::Detail::stringify(std::string{ reinterpret_cast<char const *>(str) }); 1697 } 1698 }; 1699 template<int SZ> 1700 struct StringMaker<unsigned char[SZ]> { 1701 static std::string convert(unsigned char const* str) { 1702 return ::Catch::Detail::stringify(std::string{ reinterpret_cast<char const *>(str) }); 1703 } 1704 }; 1705 1706 #if defined(CATCH_CONFIG_CPP17_BYTE) 1707 template<> 1708 struct StringMaker<std::byte> { 1709 static std::string convert(std::byte value); 1710 }; 1711 #endif // defined(CATCH_CONFIG_CPP17_BYTE) 1712 template<> 1713 struct StringMaker<int> { 1714 static std::string convert(int value); 1715 }; 1716 template<> 1717 struct StringMaker<long> { 1718 static std::string convert(long value); 1719 }; 1720 template<> 1721 struct StringMaker<long long> { 1722 static std::string convert(long long value); 1723 }; 1724 template<> 1725 struct StringMaker<unsigned int> { 1726 static std::string convert(unsigned int value); 1727 }; 1728 template<> 1729 struct StringMaker<unsigned long> { 1730 static std::string convert(unsigned long value); 1731 }; 1732 template<> 1733 struct StringMaker<unsigned long long> { 1734 static std::string convert(unsigned long long value); 1735 }; 1736 1737 template<> 1738 struct StringMaker<bool> { 1739 static std::string convert(bool b); 1740 }; 1741 1742 template<> 1743 struct StringMaker<char> { 1744 static std::string convert(char c); 1745 }; 1746 template<> 1747 struct StringMaker<signed char> { 1748 static std::string convert(signed char c); 1749 }; 1750 template<> 1751 struct StringMaker<unsigned char> { 1752 static std::string convert(unsigned char c); 1753 }; 1754 1755 template<> 1756 struct StringMaker<std::nullptr_t> { 1757 static std::string convert(std::nullptr_t); 1758 }; 1759 1760 template<> 1761 struct StringMaker<float> { 1762 static std::string convert(float value); 1763 static int precision; 1764 }; 1765 1766 template<> 1767 struct StringMaker<double> { 1768 static std::string convert(double value); 1769 static int precision; 1770 }; 1771 1772 template <typename T> 1773 struct StringMaker<T*> { 1774 template <typename U> 1775 static std::string convert(U* p) { 1776 if (p) { 1777 return ::Catch::Detail::rawMemoryToString(p); 1778 } else { 1779 return "nullptr"; 1780 } 1781 } 1782 }; 1783 1784 template <typename R, typename C> 1785 struct StringMaker<R C::*> { 1786 static std::string convert(R C::* p) { 1787 if (p) { 1788 return ::Catch::Detail::rawMemoryToString(p); 1789 } else { 1790 return "nullptr"; 1791 } 1792 } 1793 }; 1794 1795 #if defined(_MANAGED) 1796 template <typename T> 1797 struct StringMaker<T^> { 1798 static std::string convert( T^ ref ) { 1799 return ::Catch::Detail::clrReferenceToString(ref); 1800 } 1801 }; 1802 #endif 1803 1804 namespace Detail { 1805 template<typename InputIterator> 1806 std::string rangeToString(InputIterator first, InputIterator last) { 1807 ReusableStringStream rss; 1808 rss << "{ "; 1809 if (first != last) { 1810 rss << ::Catch::Detail::stringify(*first); 1811 for (++first; first != last; ++first) 1812 rss << ", " << ::Catch::Detail::stringify(*first); 1813 } 1814 rss << " }"; 1815 return rss.str(); 1816 } 1817 } 1818 1819 #ifdef __OBJC__ 1820 template<> 1821 struct StringMaker<NSString*> { 1822 static std::string convert(NSString * nsstring) { 1823 if (!nsstring) 1824 return "nil"; 1825 return std::string("@") + [nsstring UTF8String]; 1826 } 1827 }; 1828 template<> 1829 struct StringMaker<NSObject*> { 1830 static std::string convert(NSObject* nsObject) { 1831 return ::Catch::Detail::stringify([nsObject description]); 1832 } 1833 1834 }; 1835 namespace Detail { 1836 inline std::string stringify( NSString* nsstring ) { 1837 return StringMaker<NSString*>::convert( nsstring ); 1838 } 1839 1840 } // namespace Detail 1841 #endif // __OBJC__ 1842 1843 } // namespace Catch 1844 1845 ////////////////////////////////////////////////////// 1846 // Separate std-lib types stringification, so it can be selectively enabled 1847 // This means that we do not bring in 1848 1849 #if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS) 1850 # define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER 1851 # define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER 1852 # define CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER 1853 # define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER 1854 # define CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER 1855 #endif 1856 1857 // Separate std::pair specialization 1858 #if defined(CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER) 1859 #include <utility> 1860 namespace Catch { 1861 template<typename T1, typename T2> 1862 struct StringMaker<std::pair<T1, T2> > { 1863 static std::string convert(const std::pair<T1, T2>& pair) { 1864 ReusableStringStream rss; 1865 rss << "{ " 1866 << ::Catch::Detail::stringify(pair.first) 1867 << ", " 1868 << ::Catch::Detail::stringify(pair.second) 1869 << " }"; 1870 return rss.str(); 1871 } 1872 }; 1873 } 1874 #endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER 1875 1876 #if defined(CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_OPTIONAL) 1877 #include <optional> 1878 namespace Catch { 1879 template<typename T> 1880 struct StringMaker<std::optional<T> > { 1881 static std::string convert(const std::optional<T>& optional) { 1882 ReusableStringStream rss; 1883 if (optional.has_value()) { 1884 rss << ::Catch::Detail::stringify(*optional); 1885 } else { 1886 rss << "{ }"; 1887 } 1888 return rss.str(); 1889 } 1890 }; 1891 } 1892 #endif // CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER 1893 1894 // Separate std::tuple specialization 1895 #if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER) 1896 #include <tuple> 1897 namespace Catch { 1898 namespace Detail { 1899 template< 1900 typename Tuple, 1901 std::size_t N = 0, 1902 bool = (N < std::tuple_size<Tuple>::value) 1903 > 1904 struct TupleElementPrinter { 1905 static void print(const Tuple& tuple, std::ostream& os) { 1906 os << (N ? ", " : " ") 1907 << ::Catch::Detail::stringify(std::get<N>(tuple)); 1908 TupleElementPrinter<Tuple, N + 1>::print(tuple, os); 1909 } 1910 }; 1911 1912 template< 1913 typename Tuple, 1914 std::size_t N 1915 > 1916 struct TupleElementPrinter<Tuple, N, false> { 1917 static void print(const Tuple&, std::ostream&) {} 1918 }; 1919 1920 } 1921 1922 template<typename ...Types> 1923 struct StringMaker<std::tuple<Types...>> { 1924 static std::string convert(const std::tuple<Types...>& tuple) { 1925 ReusableStringStream rss; 1926 rss << '{'; 1927 Detail::TupleElementPrinter<std::tuple<Types...>>::print(tuple, rss.get()); 1928 rss << " }"; 1929 return rss.str(); 1930 } 1931 }; 1932 } 1933 #endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER 1934 1935 #if defined(CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_VARIANT) 1936 #include <variant> 1937 namespace Catch { 1938 template<> 1939 struct StringMaker<std::monostate> { 1940 static std::string convert(const std::monostate&) { 1941 return "{ }"; 1942 } 1943 }; 1944 1945 template<typename... Elements> 1946 struct StringMaker<std::variant<Elements...>> { 1947 static std::string convert(const std::variant<Elements...>& variant) { 1948 if (variant.valueless_by_exception()) { 1949 return "{valueless variant}"; 1950 } else { 1951 return std::visit( 1952 [](const auto& value) { 1953 return ::Catch::Detail::stringify(value); 1954 }, 1955 variant 1956 ); 1957 } 1958 } 1959 }; 1960 } 1961 #endif // CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER 1962 1963 namespace Catch { 1964 struct not_this_one {}; // Tag type for detecting which begin/ end are being selected 1965 1966 // Import begin/ end from std here so they are considered alongside the fallback (...) overloads in this namespace 1967 using std::begin; 1968 using std::end; 1969 1970 not_this_one begin( ... ); 1971 not_this_one end( ... ); 1972 1973 template <typename T> 1974 struct is_range { 1975 static const bool value = 1976 !std::is_same<decltype(begin(std::declval<T>())), not_this_one>::value && 1977 !std::is_same<decltype(end(std::declval<T>())), not_this_one>::value; 1978 }; 1979 1980 #if defined(_MANAGED) // Managed types are never ranges 1981 template <typename T> 1982 struct is_range<T^> { 1983 static const bool value = false; 1984 }; 1985 #endif 1986 1987 template<typename Range> 1988 std::string rangeToString( Range const& range ) { 1989 return ::Catch::Detail::rangeToString( begin( range ), end( range ) ); 1990 } 1991 1992 // Handle vector<bool> specially 1993 template<typename Allocator> 1994 std::string rangeToString( std::vector<bool, Allocator> const& v ) { 1995 ReusableStringStream rss; 1996 rss << "{ "; 1997 bool first = true; 1998 for( bool b : v ) { 1999 if( first ) 2000 first = false; 2001 else 2002 rss << ", "; 2003 rss << ::Catch::Detail::stringify( b ); 2004 } 2005 rss << " }"; 2006 return rss.str(); 2007 } 2008 2009 template<typename R> 2010 struct StringMaker<R, typename std::enable_if<is_range<R>::value && !::Catch::Detail::IsStreamInsertable<R>::value>::type> { 2011 static std::string convert( R const& range ) { 2012 return rangeToString( range ); 2013 } 2014 }; 2015 2016 template <typename T, int SZ> 2017 struct StringMaker<T[SZ]> { 2018 static std::string convert(T const(&arr)[SZ]) { 2019 return rangeToString(arr); 2020 } 2021 }; 2022 2023 } // namespace Catch 2024 2025 // Separate std::chrono::duration specialization 2026 #if defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) 2027 #include <ctime> 2028 #include <ratio> 2029 #include <chrono> 2030 2031 namespace Catch { 2032 2033 template <class Ratio> 2034 struct ratio_string { 2035 static std::string symbol(); 2036 }; 2037 2038 template <class Ratio> 2039 std::string ratio_string<Ratio>::symbol() { 2040 Catch::ReusableStringStream rss; 2041 rss << '[' << Ratio::num << '/' 2042 << Ratio::den << ']'; 2043 return rss.str(); 2044 } 2045 template <> 2046 struct ratio_string<std::atto> { 2047 static std::string symbol(); 2048 }; 2049 template <> 2050 struct ratio_string<std::femto> { 2051 static std::string symbol(); 2052 }; 2053 template <> 2054 struct ratio_string<std::pico> { 2055 static std::string symbol(); 2056 }; 2057 template <> 2058 struct ratio_string<std::nano> { 2059 static std::string symbol(); 2060 }; 2061 template <> 2062 struct ratio_string<std::micro> { 2063 static std::string symbol(); 2064 }; 2065 template <> 2066 struct ratio_string<std::milli> { 2067 static std::string symbol(); 2068 }; 2069 2070 //////////// 2071 // std::chrono::duration specializations 2072 template<typename Value, typename Ratio> 2073 struct StringMaker<std::chrono::duration<Value, Ratio>> { 2074 static std::string convert(std::chrono::duration<Value, Ratio> const& duration) { 2075 ReusableStringStream rss; 2076 rss << duration.count() << ' ' << ratio_string<Ratio>::symbol() << 's'; 2077 return rss.str(); 2078 } 2079 }; 2080 template<typename Value> 2081 struct StringMaker<std::chrono::duration<Value, std::ratio<1>>> { 2082 static std::string convert(std::chrono::duration<Value, std::ratio<1>> const& duration) { 2083 ReusableStringStream rss; 2084 rss << duration.count() << " s"; 2085 return rss.str(); 2086 } 2087 }; 2088 template<typename Value> 2089 struct StringMaker<std::chrono::duration<Value, std::ratio<60>>> { 2090 static std::string convert(std::chrono::duration<Value, std::ratio<60>> const& duration) { 2091 ReusableStringStream rss; 2092 rss << duration.count() << " m"; 2093 return rss.str(); 2094 } 2095 }; 2096 template<typename Value> 2097 struct StringMaker<std::chrono::duration<Value, std::ratio<3600>>> { 2098 static std::string convert(std::chrono::duration<Value, std::ratio<3600>> const& duration) { 2099 ReusableStringStream rss; 2100 rss << duration.count() << " h"; 2101 return rss.str(); 2102 } 2103 }; 2104 2105 //////////// 2106 // std::chrono::time_point specialization 2107 // Generic time_point cannot be specialized, only std::chrono::time_point<system_clock> 2108 template<typename Clock, typename Duration> 2109 struct StringMaker<std::chrono::time_point<Clock, Duration>> { 2110 static std::string convert(std::chrono::time_point<Clock, Duration> const& time_point) { 2111 return ::Catch::Detail::stringify(time_point.time_since_epoch()) + " since epoch"; 2112 } 2113 }; 2114 // std::chrono::time_point<system_clock> specialization 2115 template<typename Duration> 2116 struct StringMaker<std::chrono::time_point<std::chrono::system_clock, Duration>> { 2117 static std::string convert(std::chrono::time_point<std::chrono::system_clock, Duration> const& time_point) { 2118 auto converted = std::chrono::system_clock::to_time_t(time_point); 2119 2120 #ifdef _MSC_VER 2121 std::tm timeInfo = {}; 2122 gmtime_s(&timeInfo, &converted); 2123 #else 2124 std::tm* timeInfo = std::gmtime(&converted); 2125 #endif 2126 2127 auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); 2128 char timeStamp[timeStampSize]; 2129 const char * const fmt = "%Y-%m-%dT%H:%M:%SZ"; 2130 2131 #ifdef _MSC_VER 2132 std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); 2133 #else 2134 std::strftime(timeStamp, timeStampSize, fmt, timeInfo); 2135 #endif 2136 return std::string(timeStamp); 2137 } 2138 }; 2139 } 2140 #endif // CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER 2141 2142 #define INTERNAL_CATCH_REGISTER_ENUM( enumName, ... ) \ 2143 namespace Catch { \ 2144 template<> struct StringMaker<enumName> { \ 2145 static std::string convert( enumName value ) { \ 2146 static const auto& enumInfo = ::Catch::getMutableRegistryHub().getMutableEnumValuesRegistry().registerEnum( #enumName, #__VA_ARGS__, { __VA_ARGS__ } ); \ 2147 return static_cast<std::string>(enumInfo.lookup( static_cast<int>( value ) )); \ 2148 } \ 2149 }; \ 2150 } 2151 2152 #define CATCH_REGISTER_ENUM( enumName, ... ) INTERNAL_CATCH_REGISTER_ENUM( enumName, __VA_ARGS__ ) 2153 2154 #ifdef _MSC_VER 2155 #pragma warning(pop) 2156 #endif 2157 2158 // end catch_tostring.h 2159 #include <iosfwd> 2160 2161 #ifdef _MSC_VER 2162 #pragma warning(push) 2163 #pragma warning(disable:4389) // '==' : signed/unsigned mismatch 2164 #pragma warning(disable:4018) // more "signed/unsigned mismatch" 2165 #pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform) 2166 #pragma warning(disable:4180) // qualifier applied to function type has no meaning 2167 #pragma warning(disable:4800) // Forcing result to true or false 2168 #endif 2169 2170 namespace Catch { 2171 2172 struct ITransientExpression { 2173 auto isBinaryExpression() const -> bool { return m_isBinaryExpression; } 2174 auto getResult() const -> bool { return m_result; } 2175 virtual void streamReconstructedExpression( std::ostream &os ) const = 0; 2176 2177 ITransientExpression( bool isBinaryExpression, bool result ) 2178 : m_isBinaryExpression( isBinaryExpression ), 2179 m_result( result ) 2180 {} 2181 2182 // We don't actually need a virtual destructor, but many static analysers 2183 // complain if it's not here :-( 2184 virtual ~ITransientExpression(); 2185 2186 bool m_isBinaryExpression; 2187 bool m_result; 2188 2189 }; 2190 2191 void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ); 2192 2193 template<typename LhsT, typename RhsT> 2194 class BinaryExpr : public ITransientExpression { 2195 LhsT m_lhs; 2196 StringRef m_op; 2197 RhsT m_rhs; 2198 2199 void streamReconstructedExpression( std::ostream &os ) const override { 2200 formatReconstructedExpression 2201 ( os, Catch::Detail::stringify( m_lhs ), m_op, Catch::Detail::stringify( m_rhs ) ); 2202 } 2203 2204 public: 2205 BinaryExpr( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs ) 2206 : ITransientExpression{ true, comparisonResult }, 2207 m_lhs( lhs ), 2208 m_op( op ), 2209 m_rhs( rhs ) 2210 {} 2211 2212 template<typename T> 2213 auto operator && ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 2214 static_assert(always_false<T>::value, 2215 "chained comparisons are not supported inside assertions, " 2216 "wrap the expression inside parentheses, or decompose it"); 2217 } 2218 2219 template<typename T> 2220 auto operator || ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 2221 static_assert(always_false<T>::value, 2222 "chained comparisons are not supported inside assertions, " 2223 "wrap the expression inside parentheses, or decompose it"); 2224 } 2225 2226 template<typename T> 2227 auto operator == ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 2228 static_assert(always_false<T>::value, 2229 "chained comparisons are not supported inside assertions, " 2230 "wrap the expression inside parentheses, or decompose it"); 2231 } 2232 2233 template<typename T> 2234 auto operator != ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 2235 static_assert(always_false<T>::value, 2236 "chained comparisons are not supported inside assertions, " 2237 "wrap the expression inside parentheses, or decompose it"); 2238 } 2239 2240 template<typename T> 2241 auto operator > ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 2242 static_assert(always_false<T>::value, 2243 "chained comparisons are not supported inside assertions, " 2244 "wrap the expression inside parentheses, or decompose it"); 2245 } 2246 2247 template<typename T> 2248 auto operator < ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 2249 static_assert(always_false<T>::value, 2250 "chained comparisons are not supported inside assertions, " 2251 "wrap the expression inside parentheses, or decompose it"); 2252 } 2253 2254 template<typename T> 2255 auto operator >= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 2256 static_assert(always_false<T>::value, 2257 "chained comparisons are not supported inside assertions, " 2258 "wrap the expression inside parentheses, or decompose it"); 2259 } 2260 2261 template<typename T> 2262 auto operator <= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 2263 static_assert(always_false<T>::value, 2264 "chained comparisons are not supported inside assertions, " 2265 "wrap the expression inside parentheses, or decompose it"); 2266 } 2267 }; 2268 2269 template<typename LhsT> 2270 class UnaryExpr : public ITransientExpression { 2271 LhsT m_lhs; 2272 2273 void streamReconstructedExpression( std::ostream &os ) const override { 2274 os << Catch::Detail::stringify( m_lhs ); 2275 } 2276 2277 public: 2278 explicit UnaryExpr( LhsT lhs ) 2279 : ITransientExpression{ false, static_cast<bool>(lhs) }, 2280 m_lhs( lhs ) 2281 {} 2282 }; 2283 2284 // Specialised comparison functions to handle equality comparisons between ints and pointers (NULL deduces as an int) 2285 template<typename LhsT, typename RhsT> 2286 auto compareEqual( LhsT const& lhs, RhsT const& rhs ) -> bool { return static_cast<bool>(lhs == rhs); } 2287 template<typename T> 2288 auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); } 2289 template<typename T> 2290 auto compareEqual( T* const& lhs, long rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); } 2291 template<typename T> 2292 auto compareEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; } 2293 template<typename T> 2294 auto compareEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; } 2295 2296 template<typename LhsT, typename RhsT> 2297 auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return static_cast<bool>(lhs != rhs); } 2298 template<typename T> 2299 auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); } 2300 template<typename T> 2301 auto compareNotEqual( T* const& lhs, long rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); } 2302 template<typename T> 2303 auto compareNotEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) != rhs; } 2304 template<typename T> 2305 auto compareNotEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) != rhs; } 2306 2307 template<typename LhsT> 2308 class ExprLhs { 2309 LhsT m_lhs; 2310 public: 2311 explicit ExprLhs( LhsT lhs ) : m_lhs( lhs ) {} 2312 2313 template<typename RhsT> 2314 auto operator == ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const { 2315 return { compareEqual( m_lhs, rhs ), m_lhs, "==", rhs }; 2316 } 2317 auto operator == ( bool rhs ) -> BinaryExpr<LhsT, bool> const { 2318 return { m_lhs == rhs, m_lhs, "==", rhs }; 2319 } 2320 2321 template<typename RhsT> 2322 auto operator != ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const { 2323 return { compareNotEqual( m_lhs, rhs ), m_lhs, "!=", rhs }; 2324 } 2325 auto operator != ( bool rhs ) -> BinaryExpr<LhsT, bool> const { 2326 return { m_lhs != rhs, m_lhs, "!=", rhs }; 2327 } 2328 2329 template<typename RhsT> 2330 auto operator > ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const { 2331 return { static_cast<bool>(m_lhs > rhs), m_lhs, ">", rhs }; 2332 } 2333 template<typename RhsT> 2334 auto operator < ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const { 2335 return { static_cast<bool>(m_lhs < rhs), m_lhs, "<", rhs }; 2336 } 2337 template<typename RhsT> 2338 auto operator >= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const { 2339 return { static_cast<bool>(m_lhs >= rhs), m_lhs, ">=", rhs }; 2340 } 2341 template<typename RhsT> 2342 auto operator <= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const { 2343 return { static_cast<bool>(m_lhs <= rhs), m_lhs, "<=", rhs }; 2344 } 2345 2346 template<typename RhsT> 2347 auto operator && ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const { 2348 static_assert(always_false<RhsT>::value, 2349 "operator&& is not supported inside assertions, " 2350 "wrap the expression inside parentheses, or decompose it"); 2351 } 2352 2353 template<typename RhsT> 2354 auto operator || ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const { 2355 static_assert(always_false<RhsT>::value, 2356 "operator|| is not supported inside assertions, " 2357 "wrap the expression inside parentheses, or decompose it"); 2358 } 2359 2360 auto makeUnaryExpr() const -> UnaryExpr<LhsT> { 2361 return UnaryExpr<LhsT>{ m_lhs }; 2362 } 2363 }; 2364 2365 void handleExpression( ITransientExpression const& expr ); 2366 2367 template<typename T> 2368 void handleExpression( ExprLhs<T> const& expr ) { 2369 handleExpression( expr.makeUnaryExpr() ); 2370 } 2371 2372 struct Decomposer { 2373 template<typename T> 2374 auto operator <= ( T const& lhs ) -> ExprLhs<T const&> { 2375 return ExprLhs<T const&>{ lhs }; 2376 } 2377 2378 auto operator <=( bool value ) -> ExprLhs<bool> { 2379 return ExprLhs<bool>{ value }; 2380 } 2381 }; 2382 2383 } // end namespace Catch 2384 2385 #ifdef _MSC_VER 2386 #pragma warning(pop) 2387 #endif 2388 2389 // end catch_decomposer.h 2390 // start catch_interfaces_capture.h 2391 2392 #include <string> 2393 #include <chrono> 2394 2395 namespace Catch { 2396 2397 class AssertionResult; 2398 struct AssertionInfo; 2399 struct SectionInfo; 2400 struct SectionEndInfo; 2401 struct MessageInfo; 2402 struct MessageBuilder; 2403 struct Counts; 2404 struct AssertionReaction; 2405 struct SourceLineInfo; 2406 2407 struct ITransientExpression; 2408 struct IGeneratorTracker; 2409 2410 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 2411 struct BenchmarkInfo; 2412 template <typename Duration = std::chrono::duration<double, std::nano>> 2413 struct BenchmarkStats; 2414 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 2415 2416 struct IResultCapture { 2417 2418 virtual ~IResultCapture(); 2419 2420 virtual bool sectionStarted( SectionInfo const& sectionInfo, 2421 Counts& assertions ) = 0; 2422 virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; 2423 virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; 2424 2425 virtual auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& = 0; 2426 2427 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 2428 virtual void benchmarkPreparing( std::string const& name ) = 0; 2429 virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0; 2430 virtual void benchmarkEnded( BenchmarkStats<> const& stats ) = 0; 2431 virtual void benchmarkFailed( std::string const& error ) = 0; 2432 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 2433 2434 virtual void pushScopedMessage( MessageInfo const& message ) = 0; 2435 virtual void popScopedMessage( MessageInfo const& message ) = 0; 2436 2437 virtual void emplaceUnscopedMessage( MessageBuilder const& builder ) = 0; 2438 2439 virtual void handleFatalErrorCondition( StringRef message ) = 0; 2440 2441 virtual void handleExpr 2442 ( AssertionInfo const& info, 2443 ITransientExpression const& expr, 2444 AssertionReaction& reaction ) = 0; 2445 virtual void handleMessage 2446 ( AssertionInfo const& info, 2447 ResultWas::OfType resultType, 2448 StringRef const& message, 2449 AssertionReaction& reaction ) = 0; 2450 virtual void handleUnexpectedExceptionNotThrown 2451 ( AssertionInfo const& info, 2452 AssertionReaction& reaction ) = 0; 2453 virtual void handleUnexpectedInflightException 2454 ( AssertionInfo const& info, 2455 std::string const& message, 2456 AssertionReaction& reaction ) = 0; 2457 virtual void handleIncomplete 2458 ( AssertionInfo const& info ) = 0; 2459 virtual void handleNonExpr 2460 ( AssertionInfo const &info, 2461 ResultWas::OfType resultType, 2462 AssertionReaction &reaction ) = 0; 2463 2464 virtual bool lastAssertionPassed() = 0; 2465 virtual void assertionPassed() = 0; 2466 2467 // Deprecated, do not use: 2468 virtual std::string getCurrentTestName() const = 0; 2469 virtual const AssertionResult* getLastResult() const = 0; 2470 virtual void exceptionEarlyReported() = 0; 2471 }; 2472 2473 IResultCapture& getResultCapture(); 2474 } 2475 2476 // end catch_interfaces_capture.h 2477 namespace Catch { 2478 2479 struct TestFailureException{}; 2480 struct AssertionResultData; 2481 struct IResultCapture; 2482 class RunContext; 2483 2484 class LazyExpression { 2485 friend class AssertionHandler; 2486 friend struct AssertionStats; 2487 friend class RunContext; 2488 2489 ITransientExpression const* m_transientExpression = nullptr; 2490 bool m_isNegated; 2491 public: 2492 LazyExpression( bool isNegated ); 2493 LazyExpression( LazyExpression const& other ); 2494 LazyExpression& operator = ( LazyExpression const& ) = delete; 2495 2496 explicit operator bool() const; 2497 2498 friend auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream&; 2499 }; 2500 2501 struct AssertionReaction { 2502 bool shouldDebugBreak = false; 2503 bool shouldThrow = false; 2504 }; 2505 2506 class AssertionHandler { 2507 AssertionInfo m_assertionInfo; 2508 AssertionReaction m_reaction; 2509 bool m_completed = false; 2510 IResultCapture& m_resultCapture; 2511 2512 public: 2513 AssertionHandler 2514 ( StringRef const& macroName, 2515 SourceLineInfo const& lineInfo, 2516 StringRef capturedExpression, 2517 ResultDisposition::Flags resultDisposition ); 2518 ~AssertionHandler() { 2519 if ( !m_completed ) { 2520 m_resultCapture.handleIncomplete( m_assertionInfo ); 2521 } 2522 } 2523 2524 template<typename T> 2525 void handleExpr( ExprLhs<T> const& expr ) { 2526 handleExpr( expr.makeUnaryExpr() ); 2527 } 2528 void handleExpr( ITransientExpression const& expr ); 2529 2530 void handleMessage(ResultWas::OfType resultType, StringRef const& message); 2531 2532 void handleExceptionThrownAsExpected(); 2533 void handleUnexpectedExceptionNotThrown(); 2534 void handleExceptionNotThrownAsExpected(); 2535 void handleThrowingCallSkipped(); 2536 void handleUnexpectedInflightException(); 2537 2538 void complete(); 2539 void setCompleted(); 2540 2541 // query 2542 auto allowThrows() const -> bool; 2543 }; 2544 2545 void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef const& matcherString ); 2546 2547 } // namespace Catch 2548 2549 // end catch_assertionhandler.h 2550 // start catch_message.h 2551 2552 #include <string> 2553 #include <vector> 2554 2555 namespace Catch { 2556 2557 struct MessageInfo { 2558 MessageInfo( StringRef const& _macroName, 2559 SourceLineInfo const& _lineInfo, 2560 ResultWas::OfType _type ); 2561 2562 StringRef macroName; 2563 std::string message; 2564 SourceLineInfo lineInfo; 2565 ResultWas::OfType type; 2566 unsigned int sequence; 2567 2568 bool operator == ( MessageInfo const& other ) const; 2569 bool operator < ( MessageInfo const& other ) const; 2570 private: 2571 static unsigned int globalCount; 2572 }; 2573 2574 struct MessageStream { 2575 2576 template<typename T> 2577 MessageStream& operator << ( T const& value ) { 2578 m_stream << value; 2579 return *this; 2580 } 2581 2582 ReusableStringStream m_stream; 2583 }; 2584 2585 struct MessageBuilder : MessageStream { 2586 MessageBuilder( StringRef const& macroName, 2587 SourceLineInfo const& lineInfo, 2588 ResultWas::OfType type ); 2589 2590 template<typename T> 2591 MessageBuilder& operator << ( T const& value ) { 2592 m_stream << value; 2593 return *this; 2594 } 2595 2596 MessageInfo m_info; 2597 }; 2598 2599 class ScopedMessage { 2600 public: 2601 explicit ScopedMessage( MessageBuilder const& builder ); 2602 ScopedMessage( ScopedMessage& duplicate ) = delete; 2603 ScopedMessage( ScopedMessage&& old ); 2604 ~ScopedMessage(); 2605 2606 MessageInfo m_info; 2607 bool m_moved; 2608 }; 2609 2610 class Capturer { 2611 std::vector<MessageInfo> m_messages; 2612 IResultCapture& m_resultCapture = getResultCapture(); 2613 size_t m_captured = 0; 2614 public: 2615 Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names ); 2616 ~Capturer(); 2617 2618 void captureValue( size_t index, std::string const& value ); 2619 2620 template<typename T> 2621 void captureValues( size_t index, T const& value ) { 2622 captureValue( index, Catch::Detail::stringify( value ) ); 2623 } 2624 2625 template<typename T, typename... Ts> 2626 void captureValues( size_t index, T const& value, Ts const&... values ) { 2627 captureValue( index, Catch::Detail::stringify(value) ); 2628 captureValues( index+1, values... ); 2629 } 2630 }; 2631 2632 } // end namespace Catch 2633 2634 // end catch_message.h 2635 #if !defined(CATCH_CONFIG_DISABLE) 2636 2637 #if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION) 2638 #define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__ 2639 #else 2640 #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION" 2641 #endif 2642 2643 #if defined(CATCH_CONFIG_FAST_COMPILE) || defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 2644 2645 /////////////////////////////////////////////////////////////////////////////// 2646 // Another way to speed-up compilation is to omit local try-catch for REQUIRE* 2647 // macros. 2648 #define INTERNAL_CATCH_TRY 2649 #define INTERNAL_CATCH_CATCH( capturer ) 2650 2651 #else // CATCH_CONFIG_FAST_COMPILE 2652 2653 #define INTERNAL_CATCH_TRY try 2654 #define INTERNAL_CATCH_CATCH( handler ) catch(...) { handler.handleUnexpectedInflightException(); } 2655 2656 #endif 2657 2658 #define INTERNAL_CATCH_REACT( handler ) handler.complete(); 2659 2660 /////////////////////////////////////////////////////////////////////////////// 2661 #define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \ 2662 do { \ 2663 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ 2664 INTERNAL_CATCH_TRY { \ 2665 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 2666 CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ 2667 catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); \ 2668 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 2669 } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ 2670 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2671 } while( (void)0, (false) && static_cast<bool>( !!(__VA_ARGS__) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look 2672 // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. 2673 2674 /////////////////////////////////////////////////////////////////////////////// 2675 #define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \ 2676 INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \ 2677 if( Catch::getResultCapture().lastAssertionPassed() ) 2678 2679 /////////////////////////////////////////////////////////////////////////////// 2680 #define INTERNAL_CATCH_ELSE( macroName, resultDisposition, ... ) \ 2681 INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \ 2682 if( !Catch::getResultCapture().lastAssertionPassed() ) 2683 2684 /////////////////////////////////////////////////////////////////////////////// 2685 #define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \ 2686 do { \ 2687 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ 2688 try { \ 2689 static_cast<void>(__VA_ARGS__); \ 2690 catchAssertionHandler.handleExceptionNotThrownAsExpected(); \ 2691 } \ 2692 catch( ... ) { \ 2693 catchAssertionHandler.handleUnexpectedInflightException(); \ 2694 } \ 2695 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2696 } while( false ) 2697 2698 /////////////////////////////////////////////////////////////////////////////// 2699 #define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \ 2700 do { \ 2701 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \ 2702 if( catchAssertionHandler.allowThrows() ) \ 2703 try { \ 2704 static_cast<void>(__VA_ARGS__); \ 2705 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 2706 } \ 2707 catch( ... ) { \ 2708 catchAssertionHandler.handleExceptionThrownAsExpected(); \ 2709 } \ 2710 else \ 2711 catchAssertionHandler.handleThrowingCallSkipped(); \ 2712 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2713 } while( false ) 2714 2715 /////////////////////////////////////////////////////////////////////////////// 2716 #define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \ 2717 do { \ 2718 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \ 2719 if( catchAssertionHandler.allowThrows() ) \ 2720 try { \ 2721 static_cast<void>(expr); \ 2722 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 2723 } \ 2724 catch( exceptionType const& ) { \ 2725 catchAssertionHandler.handleExceptionThrownAsExpected(); \ 2726 } \ 2727 catch( ... ) { \ 2728 catchAssertionHandler.handleUnexpectedInflightException(); \ 2729 } \ 2730 else \ 2731 catchAssertionHandler.handleThrowingCallSkipped(); \ 2732 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2733 } while( false ) 2734 2735 /////////////////////////////////////////////////////////////////////////////// 2736 #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \ 2737 do { \ 2738 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::StringRef(), resultDisposition ); \ 2739 catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \ 2740 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2741 } while( false ) 2742 2743 /////////////////////////////////////////////////////////////////////////////// 2744 #define INTERNAL_CATCH_CAPTURE( varName, macroName, ... ) \ 2745 auto varName = Catch::Capturer( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info, #__VA_ARGS__ ); \ 2746 varName.captureValues( 0, __VA_ARGS__ ) 2747 2748 /////////////////////////////////////////////////////////////////////////////// 2749 #define INTERNAL_CATCH_INFO( macroName, log ) \ 2750 Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log ); 2751 2752 /////////////////////////////////////////////////////////////////////////////// 2753 #define INTERNAL_CATCH_UNSCOPED_INFO( macroName, log ) \ 2754 Catch::getResultCapture().emplaceUnscopedMessage( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log ) 2755 2756 /////////////////////////////////////////////////////////////////////////////// 2757 // Although this is matcher-based, it can be used with just a string 2758 #define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \ 2759 do { \ 2760 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ 2761 if( catchAssertionHandler.allowThrows() ) \ 2762 try { \ 2763 static_cast<void>(__VA_ARGS__); \ 2764 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 2765 } \ 2766 catch( ... ) { \ 2767 Catch::handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher##_catch_sr ); \ 2768 } \ 2769 else \ 2770 catchAssertionHandler.handleThrowingCallSkipped(); \ 2771 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2772 } while( false ) 2773 2774 #endif // CATCH_CONFIG_DISABLE 2775 2776 // end catch_capture.hpp 2777 // start catch_section.h 2778 2779 // start catch_section_info.h 2780 2781 // start catch_totals.h 2782 2783 #include <cstddef> 2784 2785 namespace Catch { 2786 2787 struct Counts { 2788 Counts operator - ( Counts const& other ) const; 2789 Counts& operator += ( Counts const& other ); 2790 2791 std::size_t total() const; 2792 bool allPassed() const; 2793 bool allOk() const; 2794 2795 std::size_t passed = 0; 2796 std::size_t failed = 0; 2797 std::size_t failedButOk = 0; 2798 }; 2799 2800 struct Totals { 2801 2802 Totals operator - ( Totals const& other ) const; 2803 Totals& operator += ( Totals const& other ); 2804 2805 Totals delta( Totals const& prevTotals ) const; 2806 2807 int error = 0; 2808 Counts assertions; 2809 Counts testCases; 2810 }; 2811 } 2812 2813 // end catch_totals.h 2814 #include <string> 2815 2816 namespace Catch { 2817 2818 struct SectionInfo { 2819 SectionInfo 2820 ( SourceLineInfo const& _lineInfo, 2821 std::string const& _name ); 2822 2823 // Deprecated 2824 SectionInfo 2825 ( SourceLineInfo const& _lineInfo, 2826 std::string const& _name, 2827 std::string const& ) : SectionInfo( _lineInfo, _name ) {} 2828 2829 std::string name; 2830 std::string description; // !Deprecated: this will always be empty 2831 SourceLineInfo lineInfo; 2832 }; 2833 2834 struct SectionEndInfo { 2835 SectionInfo sectionInfo; 2836 Counts prevAssertions; 2837 double durationInSeconds; 2838 }; 2839 2840 } // end namespace Catch 2841 2842 // end catch_section_info.h 2843 // start catch_timer.h 2844 2845 #include <cstdint> 2846 2847 namespace Catch { 2848 2849 auto getCurrentNanosecondsSinceEpoch() -> uint64_t; 2850 auto getEstimatedClockResolution() -> uint64_t; 2851 2852 class Timer { 2853 uint64_t m_nanoseconds = 0; 2854 public: 2855 void start(); 2856 auto getElapsedNanoseconds() const -> uint64_t; 2857 auto getElapsedMicroseconds() const -> uint64_t; 2858 auto getElapsedMilliseconds() const -> unsigned int; 2859 auto getElapsedSeconds() const -> double; 2860 }; 2861 2862 } // namespace Catch 2863 2864 // end catch_timer.h 2865 #include <string> 2866 2867 namespace Catch { 2868 2869 class Section : NonCopyable { 2870 public: 2871 Section( SectionInfo const& info ); 2872 ~Section(); 2873 2874 // This indicates whether the section should be executed or not 2875 explicit operator bool() const; 2876 2877 private: 2878 SectionInfo m_info; 2879 2880 std::string m_name; 2881 Counts m_assertions; 2882 bool m_sectionIncluded; 2883 Timer m_timer; 2884 }; 2885 2886 } // end namespace Catch 2887 2888 #define INTERNAL_CATCH_SECTION( ... ) \ 2889 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 2890 CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ 2891 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \ 2892 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 2893 2894 #define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \ 2895 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 2896 CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ 2897 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, (Catch::ReusableStringStream() << __VA_ARGS__).str() ) ) \ 2898 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 2899 2900 // end catch_section.h 2901 // start catch_interfaces_exception.h 2902 2903 // start catch_interfaces_registry_hub.h 2904 2905 #include <string> 2906 #include <memory> 2907 2908 namespace Catch { 2909 2910 class TestCase; 2911 struct ITestCaseRegistry; 2912 struct IExceptionTranslatorRegistry; 2913 struct IExceptionTranslator; 2914 struct IReporterRegistry; 2915 struct IReporterFactory; 2916 struct ITagAliasRegistry; 2917 struct IMutableEnumValuesRegistry; 2918 2919 class StartupExceptionRegistry; 2920 2921 using IReporterFactoryPtr = std::shared_ptr<IReporterFactory>; 2922 2923 struct IRegistryHub { 2924 virtual ~IRegistryHub(); 2925 2926 virtual IReporterRegistry const& getReporterRegistry() const = 0; 2927 virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; 2928 virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0; 2929 virtual IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const = 0; 2930 2931 virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0; 2932 }; 2933 2934 struct IMutableRegistryHub { 2935 virtual ~IMutableRegistryHub(); 2936 virtual void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) = 0; 2937 virtual void registerListener( IReporterFactoryPtr const& factory ) = 0; 2938 virtual void registerTest( TestCase const& testInfo ) = 0; 2939 virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; 2940 virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0; 2941 virtual void registerStartupException() noexcept = 0; 2942 virtual IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() = 0; 2943 }; 2944 2945 IRegistryHub const& getRegistryHub(); 2946 IMutableRegistryHub& getMutableRegistryHub(); 2947 void cleanUp(); 2948 std::string translateActiveException(); 2949 2950 } 2951 2952 // end catch_interfaces_registry_hub.h 2953 #if defined(CATCH_CONFIG_DISABLE) 2954 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( translatorName, signature) \ 2955 static std::string translatorName( signature ) 2956 #endif 2957 2958 #include <exception> 2959 #include <string> 2960 #include <vector> 2961 2962 namespace Catch { 2963 using exceptionTranslateFunction = std::string(*)(); 2964 2965 struct IExceptionTranslator; 2966 using ExceptionTranslators = std::vector<std::unique_ptr<IExceptionTranslator const>>; 2967 2968 struct IExceptionTranslator { 2969 virtual ~IExceptionTranslator(); 2970 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0; 2971 }; 2972 2973 struct IExceptionTranslatorRegistry { 2974 virtual ~IExceptionTranslatorRegistry(); 2975 2976 virtual std::string translateActiveException() const = 0; 2977 }; 2978 2979 class ExceptionTranslatorRegistrar { 2980 template<typename T> 2981 class ExceptionTranslator : public IExceptionTranslator { 2982 public: 2983 2984 ExceptionTranslator( std::string(*translateFunction)( T& ) ) 2985 : m_translateFunction( translateFunction ) 2986 {} 2987 2988 std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override { 2989 try { 2990 if( it == itEnd ) 2991 std::rethrow_exception(std::current_exception()); 2992 else 2993 return (*it)->translate( it+1, itEnd ); 2994 } 2995 catch( T& ex ) { 2996 return m_translateFunction( ex ); 2997 } 2998 } 2999 3000 protected: 3001 std::string(*m_translateFunction)( T& ); 3002 }; 3003 3004 public: 3005 template<typename T> 3006 ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) { 3007 getMutableRegistryHub().registerTranslator 3008 ( new ExceptionTranslator<T>( translateFunction ) ); 3009 } 3010 }; 3011 } 3012 3013 /////////////////////////////////////////////////////////////////////////////// 3014 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \ 3015 static std::string translatorName( signature ); \ 3016 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 3017 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 3018 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); } \ 3019 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 3020 static std::string translatorName( signature ) 3021 3022 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) 3023 3024 // end catch_interfaces_exception.h 3025 // start catch_approx.h 3026 3027 #include <type_traits> 3028 3029 namespace Catch { 3030 namespace Detail { 3031 3032 class Approx { 3033 private: 3034 bool equalityComparisonImpl(double other) const; 3035 // Validates the new margin (margin >= 0) 3036 // out-of-line to avoid including stdexcept in the header 3037 void setMargin(double margin); 3038 // Validates the new epsilon (0 < epsilon < 1) 3039 // out-of-line to avoid including stdexcept in the header 3040 void setEpsilon(double epsilon); 3041 3042 public: 3043 explicit Approx ( double value ); 3044 3045 static Approx custom(); 3046 3047 Approx operator-() const; 3048 3049 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3050 Approx operator()( T const& value ) { 3051 Approx approx( static_cast<double>(value) ); 3052 approx.m_epsilon = m_epsilon; 3053 approx.m_margin = m_margin; 3054 approx.m_scale = m_scale; 3055 return approx; 3056 } 3057 3058 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3059 explicit Approx( T const& value ): Approx(static_cast<double>(value)) 3060 {} 3061 3062 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3063 friend bool operator == ( const T& lhs, Approx const& rhs ) { 3064 auto lhs_v = static_cast<double>(lhs); 3065 return rhs.equalityComparisonImpl(lhs_v); 3066 } 3067 3068 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3069 friend bool operator == ( Approx const& lhs, const T& rhs ) { 3070 return operator==( rhs, lhs ); 3071 } 3072 3073 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3074 friend bool operator != ( T const& lhs, Approx const& rhs ) { 3075 return !operator==( lhs, rhs ); 3076 } 3077 3078 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3079 friend bool operator != ( Approx const& lhs, T const& rhs ) { 3080 return !operator==( rhs, lhs ); 3081 } 3082 3083 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3084 friend bool operator <= ( T const& lhs, Approx const& rhs ) { 3085 return static_cast<double>(lhs) < rhs.m_value || lhs == rhs; 3086 } 3087 3088 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3089 friend bool operator <= ( Approx const& lhs, T const& rhs ) { 3090 return lhs.m_value < static_cast<double>(rhs) || lhs == rhs; 3091 } 3092 3093 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3094 friend bool operator >= ( T const& lhs, Approx const& rhs ) { 3095 return static_cast<double>(lhs) > rhs.m_value || lhs == rhs; 3096 } 3097 3098 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3099 friend bool operator >= ( Approx const& lhs, T const& rhs ) { 3100 return lhs.m_value > static_cast<double>(rhs) || lhs == rhs; 3101 } 3102 3103 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3104 Approx& epsilon( T const& newEpsilon ) { 3105 double epsilonAsDouble = static_cast<double>(newEpsilon); 3106 setEpsilon(epsilonAsDouble); 3107 return *this; 3108 } 3109 3110 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3111 Approx& margin( T const& newMargin ) { 3112 double marginAsDouble = static_cast<double>(newMargin); 3113 setMargin(marginAsDouble); 3114 return *this; 3115 } 3116 3117 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3118 Approx& scale( T const& newScale ) { 3119 m_scale = static_cast<double>(newScale); 3120 return *this; 3121 } 3122 3123 std::string toString() const; 3124 3125 private: 3126 double m_epsilon; 3127 double m_margin; 3128 double m_scale; 3129 double m_value; 3130 }; 3131 } // end namespace Detail 3132 3133 namespace literals { 3134 Detail::Approx operator "" _a(long double val); 3135 Detail::Approx operator "" _a(unsigned long long val); 3136 } // end namespace literals 3137 3138 template<> 3139 struct StringMaker<Catch::Detail::Approx> { 3140 static std::string convert(Catch::Detail::Approx const& value); 3141 }; 3142 3143 } // end namespace Catch 3144 3145 // end catch_approx.h 3146 // start catch_string_manip.h 3147 3148 #include <string> 3149 #include <iosfwd> 3150 #include <vector> 3151 3152 namespace Catch { 3153 3154 bool startsWith( std::string const& s, std::string const& prefix ); 3155 bool startsWith( std::string const& s, char prefix ); 3156 bool endsWith( std::string const& s, std::string const& suffix ); 3157 bool endsWith( std::string const& s, char suffix ); 3158 bool contains( std::string const& s, std::string const& infix ); 3159 void toLowerInPlace( std::string& s ); 3160 std::string toLower( std::string const& s ); 3161 //! Returns a new string without whitespace at the start/end 3162 std::string trim( std::string const& str ); 3163 //! Returns a substring of the original ref without whitespace. Beware lifetimes! 3164 StringRef trim(StringRef ref); 3165 3166 // !!! Be aware, returns refs into original string - make sure original string outlives them 3167 std::vector<StringRef> splitStringRef( StringRef str, char delimiter ); 3168 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ); 3169 3170 struct pluralise { 3171 pluralise( std::size_t count, std::string const& label ); 3172 3173 friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); 3174 3175 std::size_t m_count; 3176 std::string m_label; 3177 }; 3178 } 3179 3180 // end catch_string_manip.h 3181 #ifndef CATCH_CONFIG_DISABLE_MATCHERS 3182 // start catch_capture_matchers.h 3183 3184 // start catch_matchers.h 3185 3186 #include <string> 3187 #include <vector> 3188 3189 namespace Catch { 3190 namespace Matchers { 3191 namespace Impl { 3192 3193 template<typename ArgT> struct MatchAllOf; 3194 template<typename ArgT> struct MatchAnyOf; 3195 template<typename ArgT> struct MatchNotOf; 3196 3197 class MatcherUntypedBase { 3198 public: 3199 MatcherUntypedBase() = default; 3200 MatcherUntypedBase ( MatcherUntypedBase const& ) = default; 3201 MatcherUntypedBase& operator = ( MatcherUntypedBase const& ) = delete; 3202 std::string toString() const; 3203 3204 protected: 3205 virtual ~MatcherUntypedBase(); 3206 virtual std::string describe() const = 0; 3207 mutable std::string m_cachedToString; 3208 }; 3209 3210 #ifdef __clang__ 3211 # pragma clang diagnostic push 3212 # pragma clang diagnostic ignored "-Wnon-virtual-dtor" 3213 #endif 3214 3215 template<typename ObjectT> 3216 struct MatcherMethod { 3217 virtual bool match( ObjectT const& arg ) const = 0; 3218 }; 3219 3220 #if defined(__OBJC__) 3221 // Hack to fix Catch GH issue #1661. Could use id for generic Object support. 3222 // use of const for Object pointers is very uncommon and under ARC it causes some kind of signature mismatch that breaks compilation 3223 template<> 3224 struct MatcherMethod<NSString*> { 3225 virtual bool match( NSString* arg ) const = 0; 3226 }; 3227 #endif 3228 3229 #ifdef __clang__ 3230 # pragma clang diagnostic pop 3231 #endif 3232 3233 template<typename T> 3234 struct MatcherBase : MatcherUntypedBase, MatcherMethod<T> { 3235 3236 MatchAllOf<T> operator && ( MatcherBase const& other ) const; 3237 MatchAnyOf<T> operator || ( MatcherBase const& other ) const; 3238 MatchNotOf<T> operator ! () const; 3239 }; 3240 3241 template<typename ArgT> 3242 struct MatchAllOf : MatcherBase<ArgT> { 3243 bool match( ArgT const& arg ) const override { 3244 for( auto matcher : m_matchers ) { 3245 if (!matcher->match(arg)) 3246 return false; 3247 } 3248 return true; 3249 } 3250 std::string describe() const override { 3251 std::string description; 3252 description.reserve( 4 + m_matchers.size()*32 ); 3253 description += "( "; 3254 bool first = true; 3255 for( auto matcher : m_matchers ) { 3256 if( first ) 3257 first = false; 3258 else 3259 description += " and "; 3260 description += matcher->toString(); 3261 } 3262 description += " )"; 3263 return description; 3264 } 3265 3266 MatchAllOf<ArgT>& operator && ( MatcherBase<ArgT> const& other ) { 3267 m_matchers.push_back( &other ); 3268 return *this; 3269 } 3270 3271 std::vector<MatcherBase<ArgT> const*> m_matchers; 3272 }; 3273 template<typename ArgT> 3274 struct MatchAnyOf : MatcherBase<ArgT> { 3275 3276 bool match( ArgT const& arg ) const override { 3277 for( auto matcher : m_matchers ) { 3278 if (matcher->match(arg)) 3279 return true; 3280 } 3281 return false; 3282 } 3283 std::string describe() const override { 3284 std::string description; 3285 description.reserve( 4 + m_matchers.size()*32 ); 3286 description += "( "; 3287 bool first = true; 3288 for( auto matcher : m_matchers ) { 3289 if( first ) 3290 first = false; 3291 else 3292 description += " or "; 3293 description += matcher->toString(); 3294 } 3295 description += " )"; 3296 return description; 3297 } 3298 3299 MatchAnyOf<ArgT>& operator || ( MatcherBase<ArgT> const& other ) { 3300 m_matchers.push_back( &other ); 3301 return *this; 3302 } 3303 3304 std::vector<MatcherBase<ArgT> const*> m_matchers; 3305 }; 3306 3307 template<typename ArgT> 3308 struct MatchNotOf : MatcherBase<ArgT> { 3309 3310 MatchNotOf( MatcherBase<ArgT> const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {} 3311 3312 bool match( ArgT const& arg ) const override { 3313 return !m_underlyingMatcher.match( arg ); 3314 } 3315 3316 std::string describe() const override { 3317 return "not " + m_underlyingMatcher.toString(); 3318 } 3319 MatcherBase<ArgT> const& m_underlyingMatcher; 3320 }; 3321 3322 template<typename T> 3323 MatchAllOf<T> MatcherBase<T>::operator && ( MatcherBase const& other ) const { 3324 return MatchAllOf<T>() && *this && other; 3325 } 3326 template<typename T> 3327 MatchAnyOf<T> MatcherBase<T>::operator || ( MatcherBase const& other ) const { 3328 return MatchAnyOf<T>() || *this || other; 3329 } 3330 template<typename T> 3331 MatchNotOf<T> MatcherBase<T>::operator ! () const { 3332 return MatchNotOf<T>( *this ); 3333 } 3334 3335 } // namespace Impl 3336 3337 } // namespace Matchers 3338 3339 using namespace Matchers; 3340 using Matchers::Impl::MatcherBase; 3341 3342 } // namespace Catch 3343 3344 // end catch_matchers.h 3345 // start catch_matchers_exception.hpp 3346 3347 namespace Catch { 3348 namespace Matchers { 3349 namespace Exception { 3350 3351 class ExceptionMessageMatcher : public MatcherBase<std::exception> { 3352 std::string m_message; 3353 public: 3354 3355 ExceptionMessageMatcher(std::string const& message): 3356 m_message(message) 3357 {} 3358 3359 bool match(std::exception const& ex) const override; 3360 3361 std::string describe() const override; 3362 }; 3363 3364 } // namespace Exception 3365 3366 Exception::ExceptionMessageMatcher Message(std::string const& message); 3367 3368 } // namespace Matchers 3369 } // namespace Catch 3370 3371 // end catch_matchers_exception.hpp 3372 // start catch_matchers_floating.h 3373 3374 namespace Catch { 3375 namespace Matchers { 3376 3377 namespace Floating { 3378 3379 enum class FloatingPointKind : uint8_t; 3380 3381 struct WithinAbsMatcher : MatcherBase<double> { 3382 WithinAbsMatcher(double target, double margin); 3383 bool match(double const& matchee) const override; 3384 std::string describe() const override; 3385 private: 3386 double m_target; 3387 double m_margin; 3388 }; 3389 3390 struct WithinUlpsMatcher : MatcherBase<double> { 3391 WithinUlpsMatcher(double target, uint64_t ulps, FloatingPointKind baseType); 3392 bool match(double const& matchee) const override; 3393 std::string describe() const override; 3394 private: 3395 double m_target; 3396 uint64_t m_ulps; 3397 FloatingPointKind m_type; 3398 }; 3399 3400 // Given IEEE-754 format for floats and doubles, we can assume 3401 // that float -> double promotion is lossless. Given this, we can 3402 // assume that if we do the standard relative comparison of 3403 // |lhs - rhs| <= epsilon * max(fabs(lhs), fabs(rhs)), then we get 3404 // the same result if we do this for floats, as if we do this for 3405 // doubles that were promoted from floats. 3406 struct WithinRelMatcher : MatcherBase<double> { 3407 WithinRelMatcher(double target, double epsilon); 3408 bool match(double const& matchee) const override; 3409 std::string describe() const override; 3410 private: 3411 double m_target; 3412 double m_epsilon; 3413 }; 3414 3415 } // namespace Floating 3416 3417 // The following functions create the actual matcher objects. 3418 // This allows the types to be inferred 3419 Floating::WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff); 3420 Floating::WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff); 3421 Floating::WithinAbsMatcher WithinAbs(double target, double margin); 3422 Floating::WithinRelMatcher WithinRel(double target, double eps); 3423 // defaults epsilon to 100*numeric_limits<double>::epsilon() 3424 Floating::WithinRelMatcher WithinRel(double target); 3425 Floating::WithinRelMatcher WithinRel(float target, float eps); 3426 // defaults epsilon to 100*numeric_limits<float>::epsilon() 3427 Floating::WithinRelMatcher WithinRel(float target); 3428 3429 } // namespace Matchers 3430 } // namespace Catch 3431 3432 // end catch_matchers_floating.h 3433 // start catch_matchers_generic.hpp 3434 3435 #include <functional> 3436 #include <string> 3437 3438 namespace Catch { 3439 namespace Matchers { 3440 namespace Generic { 3441 3442 namespace Detail { 3443 std::string finalizeDescription(const std::string& desc); 3444 } 3445 3446 template <typename T> 3447 class PredicateMatcher : public MatcherBase<T> { 3448 std::function<bool(T const&)> m_predicate; 3449 std::string m_description; 3450 public: 3451 3452 PredicateMatcher(std::function<bool(T const&)> const& elem, std::string const& descr) 3453 :m_predicate(std::move(elem)), 3454 m_description(Detail::finalizeDescription(descr)) 3455 {} 3456 3457 bool match( T const& item ) const override { 3458 return m_predicate(item); 3459 } 3460 3461 std::string describe() const override { 3462 return m_description; 3463 } 3464 }; 3465 3466 } // namespace Generic 3467 3468 // The following functions create the actual matcher objects. 3469 // The user has to explicitly specify type to the function, because 3470 // inferring std::function<bool(T const&)> is hard (but possible) and 3471 // requires a lot of TMP. 3472 template<typename T> 3473 Generic::PredicateMatcher<T> Predicate(std::function<bool(T const&)> const& predicate, std::string const& description = "") { 3474 return Generic::PredicateMatcher<T>(predicate, description); 3475 } 3476 3477 } // namespace Matchers 3478 } // namespace Catch 3479 3480 // end catch_matchers_generic.hpp 3481 // start catch_matchers_string.h 3482 3483 #include <string> 3484 3485 namespace Catch { 3486 namespace Matchers { 3487 3488 namespace StdString { 3489 3490 struct CasedString 3491 { 3492 CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ); 3493 std::string adjustString( std::string const& str ) const; 3494 std::string caseSensitivitySuffix() const; 3495 3496 CaseSensitive::Choice m_caseSensitivity; 3497 std::string m_str; 3498 }; 3499 3500 struct StringMatcherBase : MatcherBase<std::string> { 3501 StringMatcherBase( std::string const& operation, CasedString const& comparator ); 3502 std::string describe() const override; 3503 3504 CasedString m_comparator; 3505 std::string m_operation; 3506 }; 3507 3508 struct EqualsMatcher : StringMatcherBase { 3509 EqualsMatcher( CasedString const& comparator ); 3510 bool match( std::string const& source ) const override; 3511 }; 3512 struct ContainsMatcher : StringMatcherBase { 3513 ContainsMatcher( CasedString const& comparator ); 3514 bool match( std::string const& source ) const override; 3515 }; 3516 struct StartsWithMatcher : StringMatcherBase { 3517 StartsWithMatcher( CasedString const& comparator ); 3518 bool match( std::string const& source ) const override; 3519 }; 3520 struct EndsWithMatcher : StringMatcherBase { 3521 EndsWithMatcher( CasedString const& comparator ); 3522 bool match( std::string const& source ) const override; 3523 }; 3524 3525 struct RegexMatcher : MatcherBase<std::string> { 3526 RegexMatcher( std::string regex, CaseSensitive::Choice caseSensitivity ); 3527 bool match( std::string const& matchee ) const override; 3528 std::string describe() const override; 3529 3530 private: 3531 std::string m_regex; 3532 CaseSensitive::Choice m_caseSensitivity; 3533 }; 3534 3535 } // namespace StdString 3536 3537 // The following functions create the actual matcher objects. 3538 // This allows the types to be inferred 3539 3540 StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); 3541 StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); 3542 StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); 3543 StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); 3544 StdString::RegexMatcher Matches( std::string const& regex, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); 3545 3546 } // namespace Matchers 3547 } // namespace Catch 3548 3549 // end catch_matchers_string.h 3550 // start catch_matchers_vector.h 3551 3552 #include <algorithm> 3553 3554 namespace Catch { 3555 namespace Matchers { 3556 3557 namespace Vector { 3558 template<typename T> 3559 struct ContainsElementMatcher : MatcherBase<std::vector<T>> { 3560 3561 ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {} 3562 3563 bool match(std::vector<T> const &v) const override { 3564 for (auto const& el : v) { 3565 if (el == m_comparator) { 3566 return true; 3567 } 3568 } 3569 return false; 3570 } 3571 3572 std::string describe() const override { 3573 return "Contains: " + ::Catch::Detail::stringify( m_comparator ); 3574 } 3575 3576 T const& m_comparator; 3577 }; 3578 3579 template<typename T> 3580 struct ContainsMatcher : MatcherBase<std::vector<T>> { 3581 3582 ContainsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {} 3583 3584 bool match(std::vector<T> const &v) const override { 3585 // !TBD: see note in EqualsMatcher 3586 if (m_comparator.size() > v.size()) 3587 return false; 3588 for (auto const& comparator : m_comparator) { 3589 auto present = false; 3590 for (const auto& el : v) { 3591 if (el == comparator) { 3592 present = true; 3593 break; 3594 } 3595 } 3596 if (!present) { 3597 return false; 3598 } 3599 } 3600 return true; 3601 } 3602 std::string describe() const override { 3603 return "Contains: " + ::Catch::Detail::stringify( m_comparator ); 3604 } 3605 3606 std::vector<T> const& m_comparator; 3607 }; 3608 3609 template<typename T> 3610 struct EqualsMatcher : MatcherBase<std::vector<T>> { 3611 3612 EqualsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {} 3613 3614 bool match(std::vector<T> const &v) const override { 3615 // !TBD: This currently works if all elements can be compared using != 3616 // - a more general approach would be via a compare template that defaults 3617 // to using !=. but could be specialised for, e.g. std::vector<T> etc 3618 // - then just call that directly 3619 if (m_comparator.size() != v.size()) 3620 return false; 3621 for (std::size_t i = 0; i < v.size(); ++i) 3622 if (m_comparator[i] != v[i]) 3623 return false; 3624 return true; 3625 } 3626 std::string describe() const override { 3627 return "Equals: " + ::Catch::Detail::stringify( m_comparator ); 3628 } 3629 std::vector<T> const& m_comparator; 3630 }; 3631 3632 template<typename T> 3633 struct ApproxMatcher : MatcherBase<std::vector<T>> { 3634 3635 ApproxMatcher(std::vector<T> const& comparator) : m_comparator( comparator ) {} 3636 3637 bool match(std::vector<T> const &v) const override { 3638 if (m_comparator.size() != v.size()) 3639 return false; 3640 for (std::size_t i = 0; i < v.size(); ++i) 3641 if (m_comparator[i] != approx(v[i])) 3642 return false; 3643 return true; 3644 } 3645 std::string describe() const override { 3646 return "is approx: " + ::Catch::Detail::stringify( m_comparator ); 3647 } 3648 template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3649 ApproxMatcher& epsilon( T const& newEpsilon ) { 3650 approx.epsilon(newEpsilon); 3651 return *this; 3652 } 3653 template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3654 ApproxMatcher& margin( T const& newMargin ) { 3655 approx.margin(newMargin); 3656 return *this; 3657 } 3658 template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3659 ApproxMatcher& scale( T const& newScale ) { 3660 approx.scale(newScale); 3661 return *this; 3662 } 3663 3664 std::vector<T> const& m_comparator; 3665 mutable Catch::Detail::Approx approx = Catch::Detail::Approx::custom(); 3666 }; 3667 3668 template<typename T> 3669 struct UnorderedEqualsMatcher : MatcherBase<std::vector<T>> { 3670 UnorderedEqualsMatcher(std::vector<T> const& target) : m_target(target) {} 3671 bool match(std::vector<T> const& vec) const override { 3672 // Note: This is a reimplementation of std::is_permutation, 3673 // because I don't want to include <algorithm> inside the common path 3674 if (m_target.size() != vec.size()) { 3675 return false; 3676 } 3677 return std::is_permutation(m_target.begin(), m_target.end(), vec.begin()); 3678 } 3679 3680 std::string describe() const override { 3681 return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target); 3682 } 3683 private: 3684 std::vector<T> const& m_target; 3685 }; 3686 3687 } // namespace Vector 3688 3689 // The following functions create the actual matcher objects. 3690 // This allows the types to be inferred 3691 3692 template<typename T> 3693 Vector::ContainsMatcher<T> Contains( std::vector<T> const& comparator ) { 3694 return Vector::ContainsMatcher<T>( comparator ); 3695 } 3696 3697 template<typename T> 3698 Vector::ContainsElementMatcher<T> VectorContains( T const& comparator ) { 3699 return Vector::ContainsElementMatcher<T>( comparator ); 3700 } 3701 3702 template<typename T> 3703 Vector::EqualsMatcher<T> Equals( std::vector<T> const& comparator ) { 3704 return Vector::EqualsMatcher<T>( comparator ); 3705 } 3706 3707 template<typename T> 3708 Vector::ApproxMatcher<T> Approx( std::vector<T> const& comparator ) { 3709 return Vector::ApproxMatcher<T>( comparator ); 3710 } 3711 3712 template<typename T> 3713 Vector::UnorderedEqualsMatcher<T> UnorderedEquals(std::vector<T> const& target) { 3714 return Vector::UnorderedEqualsMatcher<T>(target); 3715 } 3716 3717 } // namespace Matchers 3718 } // namespace Catch 3719 3720 // end catch_matchers_vector.h 3721 namespace Catch { 3722 3723 template<typename ArgT, typename MatcherT> 3724 class MatchExpr : public ITransientExpression { 3725 ArgT const& m_arg; 3726 MatcherT m_matcher; 3727 StringRef m_matcherString; 3728 public: 3729 MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString ) 3730 : ITransientExpression{ true, matcher.match( arg ) }, 3731 m_arg( arg ), 3732 m_matcher( matcher ), 3733 m_matcherString( matcherString ) 3734 {} 3735 3736 void streamReconstructedExpression( std::ostream &os ) const override { 3737 auto matcherAsString = m_matcher.toString(); 3738 os << Catch::Detail::stringify( m_arg ) << ' '; 3739 if( matcherAsString == Detail::unprintableString ) 3740 os << m_matcherString; 3741 else 3742 os << matcherAsString; 3743 } 3744 }; 3745 3746 using StringMatcher = Matchers::Impl::MatcherBase<std::string>; 3747 3748 void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString ); 3749 3750 template<typename ArgT, typename MatcherT> 3751 auto makeMatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString ) -> MatchExpr<ArgT, MatcherT> { 3752 return MatchExpr<ArgT, MatcherT>( arg, matcher, matcherString ); 3753 } 3754 3755 } // namespace Catch 3756 3757 /////////////////////////////////////////////////////////////////////////////// 3758 #define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ 3759 do { \ 3760 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ 3761 INTERNAL_CATCH_TRY { \ 3762 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher, #matcher##_catch_sr ) ); \ 3763 } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ 3764 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 3765 } while( false ) 3766 3767 /////////////////////////////////////////////////////////////////////////////// 3768 #define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \ 3769 do { \ 3770 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ 3771 if( catchAssertionHandler.allowThrows() ) \ 3772 try { \ 3773 static_cast<void>(__VA_ARGS__ ); \ 3774 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 3775 } \ 3776 catch( exceptionType const& ex ) { \ 3777 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( ex, matcher, #matcher##_catch_sr ) ); \ 3778 } \ 3779 catch( ... ) { \ 3780 catchAssertionHandler.handleUnexpectedInflightException(); \ 3781 } \ 3782 else \ 3783 catchAssertionHandler.handleThrowingCallSkipped(); \ 3784 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 3785 } while( false ) 3786 3787 // end catch_capture_matchers.h 3788 #endif 3789 // start catch_generators.hpp 3790 3791 // start catch_interfaces_generatortracker.h 3792 3793 3794 #include <memory> 3795 3796 namespace Catch { 3797 3798 namespace Generators { 3799 class GeneratorUntypedBase { 3800 public: 3801 GeneratorUntypedBase() = default; 3802 virtual ~GeneratorUntypedBase(); 3803 // Attempts to move the generator to the next element 3804 // 3805 // Returns true iff the move succeeded (and a valid element 3806 // can be retrieved). 3807 virtual bool next() = 0; 3808 }; 3809 using GeneratorBasePtr = std::unique_ptr<GeneratorUntypedBase>; 3810 3811 } // namespace Generators 3812 3813 struct IGeneratorTracker { 3814 virtual ~IGeneratorTracker(); 3815 virtual auto hasGenerator() const -> bool = 0; 3816 virtual auto getGenerator() const -> Generators::GeneratorBasePtr const& = 0; 3817 virtual void setGenerator( Generators::GeneratorBasePtr&& generator ) = 0; 3818 }; 3819 3820 } // namespace Catch 3821 3822 // end catch_interfaces_generatortracker.h 3823 // start catch_enforce.h 3824 3825 #include <exception> 3826 3827 namespace Catch { 3828 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 3829 template <typename Ex> 3830 [[noreturn]] 3831 void throw_exception(Ex const& e) { 3832 throw e; 3833 } 3834 #else // ^^ Exceptions are enabled // Exceptions are disabled vv 3835 [[noreturn]] 3836 void throw_exception(std::exception const& e); 3837 #endif 3838 3839 [[noreturn]] 3840 void throw_logic_error(std::string const& msg); 3841 [[noreturn]] 3842 void throw_domain_error(std::string const& msg); 3843 [[noreturn]] 3844 void throw_runtime_error(std::string const& msg); 3845 3846 } // namespace Catch; 3847 3848 #define CATCH_MAKE_MSG(...) \ 3849 (Catch::ReusableStringStream() << __VA_ARGS__).str() 3850 3851 #define CATCH_INTERNAL_ERROR(...) \ 3852 Catch::throw_logic_error(CATCH_MAKE_MSG( CATCH_INTERNAL_LINEINFO << ": Internal Catch2 error: " << __VA_ARGS__)) 3853 3854 #define CATCH_ERROR(...) \ 3855 Catch::throw_domain_error(CATCH_MAKE_MSG( __VA_ARGS__ )) 3856 3857 #define CATCH_RUNTIME_ERROR(...) \ 3858 Catch::throw_runtime_error(CATCH_MAKE_MSG( __VA_ARGS__ )) 3859 3860 #define CATCH_ENFORCE( condition, ... ) \ 3861 do{ if( !(condition) ) CATCH_ERROR( __VA_ARGS__ ); } while(false) 3862 3863 // end catch_enforce.h 3864 #include <memory> 3865 #include <vector> 3866 #include <cassert> 3867 3868 #include <utility> 3869 #include <exception> 3870 3871 namespace Catch { 3872 3873 class GeneratorException : public std::exception { 3874 const char* const m_msg = ""; 3875 3876 public: 3877 GeneratorException(const char* msg): 3878 m_msg(msg) 3879 {} 3880 3881 const char* what() const noexcept override final; 3882 }; 3883 3884 namespace Generators { 3885 3886 // !TBD move this into its own location? 3887 namespace pf{ 3888 template<typename T, typename... Args> 3889 std::unique_ptr<T> make_unique( Args&&... args ) { 3890 return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); 3891 } 3892 } 3893 3894 template<typename T> 3895 struct IGenerator : GeneratorUntypedBase { 3896 virtual ~IGenerator() = default; 3897 3898 // Returns the current element of the generator 3899 // 3900 // \Precondition The generator is either freshly constructed, 3901 // or the last call to `next()` returned true 3902 virtual T const& get() const = 0; 3903 using type = T; 3904 }; 3905 3906 template<typename T> 3907 class SingleValueGenerator final : public IGenerator<T> { 3908 T m_value; 3909 public: 3910 SingleValueGenerator(T const& value) : m_value( value ) {} 3911 SingleValueGenerator(T&& value) : m_value(std::move(value)) {} 3912 3913 T const& get() const override { 3914 return m_value; 3915 } 3916 bool next() override { 3917 return false; 3918 } 3919 }; 3920 3921 template<typename T> 3922 class FixedValuesGenerator final : public IGenerator<T> { 3923 static_assert(!std::is_same<T, bool>::value, 3924 "FixedValuesGenerator does not support bools because of std::vector<bool>" 3925 "specialization, use SingleValue Generator instead."); 3926 std::vector<T> m_values; 3927 size_t m_idx = 0; 3928 public: 3929 FixedValuesGenerator( std::initializer_list<T> values ) : m_values( values ) {} 3930 3931 T const& get() const override { 3932 return m_values[m_idx]; 3933 } 3934 bool next() override { 3935 ++m_idx; 3936 return m_idx < m_values.size(); 3937 } 3938 }; 3939 3940 template <typename T> 3941 class GeneratorWrapper final { 3942 std::unique_ptr<IGenerator<T>> m_generator; 3943 public: 3944 GeneratorWrapper(std::unique_ptr<IGenerator<T>> generator): 3945 m_generator(std::move(generator)) 3946 {} 3947 T const& get() const { 3948 return m_generator->get(); 3949 } 3950 bool next() { 3951 return m_generator->next(); 3952 } 3953 }; 3954 3955 template <typename T> 3956 GeneratorWrapper<T> value(T&& value) { 3957 return GeneratorWrapper<T>(pf::make_unique<SingleValueGenerator<T>>(std::forward<T>(value))); 3958 } 3959 template <typename T> 3960 GeneratorWrapper<T> values(std::initializer_list<T> values) { 3961 return GeneratorWrapper<T>(pf::make_unique<FixedValuesGenerator<T>>(values)); 3962 } 3963 3964 template<typename T> 3965 class Generators : public IGenerator<T> { 3966 std::vector<GeneratorWrapper<T>> m_generators; 3967 size_t m_current = 0; 3968 3969 void populate(GeneratorWrapper<T>&& generator) { 3970 m_generators.emplace_back(std::move(generator)); 3971 } 3972 void populate(T&& val) { 3973 m_generators.emplace_back(value(std::move(val))); 3974 } 3975 template<typename U> 3976 void populate(U&& val) { 3977 populate(T(std::move(val))); 3978 } 3979 template<typename U, typename... Gs> 3980 void populate(U&& valueOrGenerator, Gs... moreGenerators) { 3981 populate(std::forward<U>(valueOrGenerator)); 3982 populate(std::forward<Gs>(moreGenerators)...); 3983 } 3984 3985 public: 3986 template <typename... Gs> 3987 Generators(Gs... moreGenerators) { 3988 m_generators.reserve(sizeof...(Gs)); 3989 populate(std::forward<Gs>(moreGenerators)...); 3990 } 3991 3992 T const& get() const override { 3993 return m_generators[m_current].get(); 3994 } 3995 3996 bool next() override { 3997 if (m_current >= m_generators.size()) { 3998 return false; 3999 } 4000 const bool current_status = m_generators[m_current].next(); 4001 if (!current_status) { 4002 ++m_current; 4003 } 4004 return m_current < m_generators.size(); 4005 } 4006 }; 4007 4008 template<typename... Ts> 4009 GeneratorWrapper<std::tuple<Ts...>> table( std::initializer_list<std::tuple<typename std::decay<Ts>::type...>> tuples ) { 4010 return values<std::tuple<Ts...>>( tuples ); 4011 } 4012 4013 // Tag type to signal that a generator sequence should convert arguments to a specific type 4014 template <typename T> 4015 struct as {}; 4016 4017 template<typename T, typename... Gs> 4018 auto makeGenerators( GeneratorWrapper<T>&& generator, Gs... moreGenerators ) -> Generators<T> { 4019 return Generators<T>(std::move(generator), std::forward<Gs>(moreGenerators)...); 4020 } 4021 template<typename T> 4022 auto makeGenerators( GeneratorWrapper<T>&& generator ) -> Generators<T> { 4023 return Generators<T>(std::move(generator)); 4024 } 4025 template<typename T, typename... Gs> 4026 auto makeGenerators( T&& val, Gs... moreGenerators ) -> Generators<T> { 4027 return makeGenerators( value( std::forward<T>( val ) ), std::forward<Gs>( moreGenerators )... ); 4028 } 4029 template<typename T, typename U, typename... Gs> 4030 auto makeGenerators( as<T>, U&& val, Gs... moreGenerators ) -> Generators<T> { 4031 return makeGenerators( value( T( std::forward<U>( val ) ) ), std::forward<Gs>( moreGenerators )... ); 4032 } 4033 4034 auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker&; 4035 4036 template<typename L> 4037 // Note: The type after -> is weird, because VS2015 cannot parse 4038 // the expression used in the typedef inside, when it is in 4039 // return type. Yeah. 4040 auto generate( SourceLineInfo const& lineInfo, L const& generatorExpression ) -> decltype(std::declval<decltype(generatorExpression())>().get()) { 4041 using UnderlyingType = typename decltype(generatorExpression())::type; 4042 4043 IGeneratorTracker& tracker = acquireGeneratorTracker( lineInfo ); 4044 if (!tracker.hasGenerator()) { 4045 tracker.setGenerator(pf::make_unique<Generators<UnderlyingType>>(generatorExpression())); 4046 } 4047 4048 auto const& generator = static_cast<IGenerator<UnderlyingType> const&>( *tracker.getGenerator() ); 4049 return generator.get(); 4050 } 4051 4052 } // namespace Generators 4053 } // namespace Catch 4054 4055 #define GENERATE( ... ) \ 4056 Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) 4057 #define GENERATE_COPY( ... ) \ 4058 Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) 4059 #define GENERATE_REF( ... ) \ 4060 Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) 4061 4062 // end catch_generators.hpp 4063 // start catch_generators_generic.hpp 4064 4065 namespace Catch { 4066 namespace Generators { 4067 4068 template <typename T> 4069 class TakeGenerator : public IGenerator<T> { 4070 GeneratorWrapper<T> m_generator; 4071 size_t m_returned = 0; 4072 size_t m_target; 4073 public: 4074 TakeGenerator(size_t target, GeneratorWrapper<T>&& generator): 4075 m_generator(std::move(generator)), 4076 m_target(target) 4077 { 4078 assert(target != 0 && "Empty generators are not allowed"); 4079 } 4080 T const& get() const override { 4081 return m_generator.get(); 4082 } 4083 bool next() override { 4084 ++m_returned; 4085 if (m_returned >= m_target) { 4086 return false; 4087 } 4088 4089 const auto success = m_generator.next(); 4090 // If the underlying generator does not contain enough values 4091 // then we cut short as well 4092 if (!success) { 4093 m_returned = m_target; 4094 } 4095 return success; 4096 } 4097 }; 4098 4099 template <typename T> 4100 GeneratorWrapper<T> take(size_t target, GeneratorWrapper<T>&& generator) { 4101 return GeneratorWrapper<T>(pf::make_unique<TakeGenerator<T>>(target, std::move(generator))); 4102 } 4103 4104 template <typename T, typename Predicate> 4105 class FilterGenerator : public IGenerator<T> { 4106 GeneratorWrapper<T> m_generator; 4107 Predicate m_predicate; 4108 public: 4109 template <typename P = Predicate> 4110 FilterGenerator(P&& pred, GeneratorWrapper<T>&& generator): 4111 m_generator(std::move(generator)), 4112 m_predicate(std::forward<P>(pred)) 4113 { 4114 if (!m_predicate(m_generator.get())) { 4115 // It might happen that there are no values that pass the 4116 // filter. In that case we throw an exception. 4117 auto has_initial_value = next(); 4118 if (!has_initial_value) { 4119 Catch::throw_exception(GeneratorException("No valid value found in filtered generator")); 4120 } 4121 } 4122 } 4123 4124 T const& get() const override { 4125 return m_generator.get(); 4126 } 4127 4128 bool next() override { 4129 bool success = m_generator.next(); 4130 if (!success) { 4131 return false; 4132 } 4133 while (!m_predicate(m_generator.get()) && (success = m_generator.next()) == true); 4134 return success; 4135 } 4136 }; 4137 4138 template <typename T, typename Predicate> 4139 GeneratorWrapper<T> filter(Predicate&& pred, GeneratorWrapper<T>&& generator) { 4140 return GeneratorWrapper<T>(std::unique_ptr<IGenerator<T>>(pf::make_unique<FilterGenerator<T, Predicate>>(std::forward<Predicate>(pred), std::move(generator)))); 4141 } 4142 4143 template <typename T> 4144 class RepeatGenerator : public IGenerator<T> { 4145 static_assert(!std::is_same<T, bool>::value, 4146 "RepeatGenerator currently does not support bools" 4147 "because of std::vector<bool> specialization"); 4148 GeneratorWrapper<T> m_generator; 4149 mutable std::vector<T> m_returned; 4150 size_t m_target_repeats; 4151 size_t m_current_repeat = 0; 4152 size_t m_repeat_index = 0; 4153 public: 4154 RepeatGenerator(size_t repeats, GeneratorWrapper<T>&& generator): 4155 m_generator(std::move(generator)), 4156 m_target_repeats(repeats) 4157 { 4158 assert(m_target_repeats > 0 && "Repeat generator must repeat at least once"); 4159 } 4160 4161 T const& get() const override { 4162 if (m_current_repeat == 0) { 4163 m_returned.push_back(m_generator.get()); 4164 return m_returned.back(); 4165 } 4166 return m_returned[m_repeat_index]; 4167 } 4168 4169 bool next() override { 4170 // There are 2 basic cases: 4171 // 1) We are still reading the generator 4172 // 2) We are reading our own cache 4173 4174 // In the first case, we need to poke the underlying generator. 4175 // If it happily moves, we are left in that state, otherwise it is time to start reading from our cache 4176 if (m_current_repeat == 0) { 4177 const auto success = m_generator.next(); 4178 if (!success) { 4179 ++m_current_repeat; 4180 } 4181 return m_current_repeat < m_target_repeats; 4182 } 4183 4184 // In the second case, we need to move indices forward and check that we haven't run up against the end 4185 ++m_repeat_index; 4186 if (m_repeat_index == m_returned.size()) { 4187 m_repeat_index = 0; 4188 ++m_current_repeat; 4189 } 4190 return m_current_repeat < m_target_repeats; 4191 } 4192 }; 4193 4194 template <typename T> 4195 GeneratorWrapper<T> repeat(size_t repeats, GeneratorWrapper<T>&& generator) { 4196 return GeneratorWrapper<T>(pf::make_unique<RepeatGenerator<T>>(repeats, std::move(generator))); 4197 } 4198 4199 template <typename T, typename U, typename Func> 4200 class MapGenerator : public IGenerator<T> { 4201 // TBD: provide static assert for mapping function, for friendly error message 4202 GeneratorWrapper<U> m_generator; 4203 Func m_function; 4204 // To avoid returning dangling reference, we have to save the values 4205 T m_cache; 4206 public: 4207 template <typename F2 = Func> 4208 MapGenerator(F2&& function, GeneratorWrapper<U>&& generator) : 4209 m_generator(std::move(generator)), 4210 m_function(std::forward<F2>(function)), 4211 m_cache(m_function(m_generator.get())) 4212 {} 4213 4214 T const& get() const override { 4215 return m_cache; 4216 } 4217 bool next() override { 4218 const auto success = m_generator.next(); 4219 if (success) { 4220 m_cache = m_function(m_generator.get()); 4221 } 4222 return success; 4223 } 4224 }; 4225 4226 template <typename Func, typename U, typename T = FunctionReturnType<Func, U>> 4227 GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) { 4228 return GeneratorWrapper<T>( 4229 pf::make_unique<MapGenerator<T, U, Func>>(std::forward<Func>(function), std::move(generator)) 4230 ); 4231 } 4232 4233 template <typename T, typename U, typename Func> 4234 GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) { 4235 return GeneratorWrapper<T>( 4236 pf::make_unique<MapGenerator<T, U, Func>>(std::forward<Func>(function), std::move(generator)) 4237 ); 4238 } 4239 4240 template <typename T> 4241 class ChunkGenerator final : public IGenerator<std::vector<T>> { 4242 std::vector<T> m_chunk; 4243 size_t m_chunk_size; 4244 GeneratorWrapper<T> m_generator; 4245 bool m_used_up = false; 4246 public: 4247 ChunkGenerator(size_t size, GeneratorWrapper<T> generator) : 4248 m_chunk_size(size), m_generator(std::move(generator)) 4249 { 4250 m_chunk.reserve(m_chunk_size); 4251 if (m_chunk_size != 0) { 4252 m_chunk.push_back(m_generator.get()); 4253 for (size_t i = 1; i < m_chunk_size; ++i) { 4254 if (!m_generator.next()) { 4255 Catch::throw_exception(GeneratorException("Not enough values to initialize the first chunk")); 4256 } 4257 m_chunk.push_back(m_generator.get()); 4258 } 4259 } 4260 } 4261 std::vector<T> const& get() const override { 4262 return m_chunk; 4263 } 4264 bool next() override { 4265 m_chunk.clear(); 4266 for (size_t idx = 0; idx < m_chunk_size; ++idx) { 4267 if (!m_generator.next()) { 4268 return false; 4269 } 4270 m_chunk.push_back(m_generator.get()); 4271 } 4272 return true; 4273 } 4274 }; 4275 4276 template <typename T> 4277 GeneratorWrapper<std::vector<T>> chunk(size_t size, GeneratorWrapper<T>&& generator) { 4278 return GeneratorWrapper<std::vector<T>>( 4279 pf::make_unique<ChunkGenerator<T>>(size, std::move(generator)) 4280 ); 4281 } 4282 4283 } // namespace Generators 4284 } // namespace Catch 4285 4286 // end catch_generators_generic.hpp 4287 // start catch_generators_specific.hpp 4288 4289 // start catch_context.h 4290 4291 #include <memory> 4292 4293 namespace Catch { 4294 4295 struct IResultCapture; 4296 struct IRunner; 4297 struct IConfig; 4298 struct IMutableContext; 4299 4300 using IConfigPtr = std::shared_ptr<IConfig const>; 4301 4302 struct IContext 4303 { 4304 virtual ~IContext(); 4305 4306 virtual IResultCapture* getResultCapture() = 0; 4307 virtual IRunner* getRunner() = 0; 4308 virtual IConfigPtr const& getConfig() const = 0; 4309 }; 4310 4311 struct IMutableContext : IContext 4312 { 4313 virtual ~IMutableContext(); 4314 virtual void setResultCapture( IResultCapture* resultCapture ) = 0; 4315 virtual void setRunner( IRunner* runner ) = 0; 4316 virtual void setConfig( IConfigPtr const& config ) = 0; 4317 4318 private: 4319 static IMutableContext *currentContext; 4320 friend IMutableContext& getCurrentMutableContext(); 4321 friend void cleanUpContext(); 4322 static void createContext(); 4323 }; 4324 4325 inline IMutableContext& getCurrentMutableContext() 4326 { 4327 if( !IMutableContext::currentContext ) 4328 IMutableContext::createContext(); 4329 // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn) 4330 return *IMutableContext::currentContext; 4331 } 4332 4333 inline IContext& getCurrentContext() 4334 { 4335 return getCurrentMutableContext(); 4336 } 4337 4338 void cleanUpContext(); 4339 4340 class SimplePcg32; 4341 SimplePcg32& rng(); 4342 } 4343 4344 // end catch_context.h 4345 // start catch_interfaces_config.h 4346 4347 // start catch_option.hpp 4348 4349 namespace Catch { 4350 4351 // An optional type 4352 template<typename T> 4353 class Option { 4354 public: 4355 Option() : nullableValue( nullptr ) {} 4356 Option( T const& _value ) 4357 : nullableValue( new( storage ) T( _value ) ) 4358 {} 4359 Option( Option const& _other ) 4360 : nullableValue( _other ? new( storage ) T( *_other ) : nullptr ) 4361 {} 4362 4363 ~Option() { 4364 reset(); 4365 } 4366 4367 Option& operator= ( Option const& _other ) { 4368 if( &_other != this ) { 4369 reset(); 4370 if( _other ) 4371 nullableValue = new( storage ) T( *_other ); 4372 } 4373 return *this; 4374 } 4375 Option& operator = ( T const& _value ) { 4376 reset(); 4377 nullableValue = new( storage ) T( _value ); 4378 return *this; 4379 } 4380 4381 void reset() { 4382 if( nullableValue ) 4383 nullableValue->~T(); 4384 nullableValue = nullptr; 4385 } 4386 4387 T& operator*() { return *nullableValue; } 4388 T const& operator*() const { return *nullableValue; } 4389 T* operator->() { return nullableValue; } 4390 const T* operator->() const { return nullableValue; } 4391 4392 T valueOr( T const& defaultValue ) const { 4393 return nullableValue ? *nullableValue : defaultValue; 4394 } 4395 4396 bool some() const { return nullableValue != nullptr; } 4397 bool none() const { return nullableValue == nullptr; } 4398 4399 bool operator !() const { return nullableValue == nullptr; } 4400 explicit operator bool() const { 4401 return some(); 4402 } 4403 4404 private: 4405 T *nullableValue; 4406 alignas(alignof(T)) char storage[sizeof(T)]; 4407 }; 4408 4409 } // end namespace Catch 4410 4411 // end catch_option.hpp 4412 #include <iosfwd> 4413 #include <string> 4414 #include <vector> 4415 #include <memory> 4416 4417 namespace Catch { 4418 4419 enum class Verbosity { 4420 Quiet = 0, 4421 Normal, 4422 High 4423 }; 4424 4425 struct WarnAbout { enum What { 4426 Nothing = 0x00, 4427 NoAssertions = 0x01, 4428 NoTests = 0x02 4429 }; }; 4430 4431 struct ShowDurations { enum OrNot { 4432 DefaultForReporter, 4433 Always, 4434 Never 4435 }; }; 4436 struct RunTests { enum InWhatOrder { 4437 InDeclarationOrder, 4438 InLexicographicalOrder, 4439 InRandomOrder 4440 }; }; 4441 struct UseColour { enum YesOrNo { 4442 Auto, 4443 Yes, 4444 No 4445 }; }; 4446 struct WaitForKeypress { enum When { 4447 Never, 4448 BeforeStart = 1, 4449 BeforeExit = 2, 4450 BeforeStartAndExit = BeforeStart | BeforeExit 4451 }; }; 4452 4453 class TestSpec; 4454 4455 struct IConfig : NonCopyable { 4456 4457 virtual ~IConfig(); 4458 4459 virtual bool allowThrows() const = 0; 4460 virtual std::ostream& stream() const = 0; 4461 virtual std::string name() const = 0; 4462 virtual bool includeSuccessfulResults() const = 0; 4463 virtual bool shouldDebugBreak() const = 0; 4464 virtual bool warnAboutMissingAssertions() const = 0; 4465 virtual bool warnAboutNoTests() const = 0; 4466 virtual int abortAfter() const = 0; 4467 virtual bool showInvisibles() const = 0; 4468 virtual ShowDurations::OrNot showDurations() const = 0; 4469 virtual TestSpec const& testSpec() const = 0; 4470 virtual bool hasTestFilters() const = 0; 4471 virtual std::vector<std::string> const& getTestsOrTags() const = 0; 4472 virtual RunTests::InWhatOrder runOrder() const = 0; 4473 virtual unsigned int rngSeed() const = 0; 4474 virtual UseColour::YesOrNo useColour() const = 0; 4475 virtual std::vector<std::string> const& getSectionsToRun() const = 0; 4476 virtual Verbosity verbosity() const = 0; 4477 4478 virtual bool benchmarkNoAnalysis() const = 0; 4479 virtual int benchmarkSamples() const = 0; 4480 virtual double benchmarkConfidenceInterval() const = 0; 4481 virtual unsigned int benchmarkResamples() const = 0; 4482 }; 4483 4484 using IConfigPtr = std::shared_ptr<IConfig const>; 4485 } 4486 4487 // end catch_interfaces_config.h 4488 // start catch_random_number_generator.h 4489 4490 #include <cstdint> 4491 4492 namespace Catch { 4493 4494 // This is a simple implementation of C++11 Uniform Random Number 4495 // Generator. It does not provide all operators, because Catch2 4496 // does not use it, but it should behave as expected inside stdlib's 4497 // distributions. 4498 // The implementation is based on the PCG family (http://pcg-random.org) 4499 class SimplePcg32 { 4500 using state_type = std::uint64_t; 4501 public: 4502 using result_type = std::uint32_t; 4503 static constexpr result_type (min)() { 4504 return 0; 4505 } 4506 static constexpr result_type (max)() { 4507 return static_cast<result_type>(-1); 4508 } 4509 4510 // Provide some default initial state for the default constructor 4511 SimplePcg32():SimplePcg32(0xed743cc4U) {} 4512 4513 explicit SimplePcg32(result_type seed_); 4514 4515 void seed(result_type seed_); 4516 void discard(uint64_t skip); 4517 4518 result_type operator()(); 4519 4520 private: 4521 friend bool operator==(SimplePcg32 const& lhs, SimplePcg32 const& rhs); 4522 friend bool operator!=(SimplePcg32 const& lhs, SimplePcg32 const& rhs); 4523 4524 // In theory we also need operator<< and operator>> 4525 // In practice we do not use them, so we will skip them for now 4526 4527 std::uint64_t m_state; 4528 // This part of the state determines which "stream" of the numbers 4529 // is chosen -- we take it as a constant for Catch2, so we only 4530 // need to deal with seeding the main state. 4531 // Picked by reading 8 bytes from `/dev/random` :-) 4532 static const std::uint64_t s_inc = (0x13ed0cc53f939476ULL << 1ULL) | 1ULL; 4533 }; 4534 4535 } // end namespace Catch 4536 4537 // end catch_random_number_generator.h 4538 #include <random> 4539 4540 namespace Catch { 4541 namespace Generators { 4542 4543 template <typename Float> 4544 class RandomFloatingGenerator final : public IGenerator<Float> { 4545 Catch::SimplePcg32& m_rng; 4546 std::uniform_real_distribution<Float> m_dist; 4547 Float m_current_number; 4548 public: 4549 4550 RandomFloatingGenerator(Float a, Float b): 4551 m_rng(rng()), 4552 m_dist(a, b) { 4553 static_cast<void>(next()); 4554 } 4555 4556 Float const& get() const override { 4557 return m_current_number; 4558 } 4559 bool next() override { 4560 m_current_number = m_dist(m_rng); 4561 return true; 4562 } 4563 }; 4564 4565 template <typename Integer> 4566 class RandomIntegerGenerator final : public IGenerator<Integer> { 4567 Catch::SimplePcg32& m_rng; 4568 std::uniform_int_distribution<Integer> m_dist; 4569 Integer m_current_number; 4570 public: 4571 4572 RandomIntegerGenerator(Integer a, Integer b): 4573 m_rng(rng()), 4574 m_dist(a, b) { 4575 static_cast<void>(next()); 4576 } 4577 4578 Integer const& get() const override { 4579 return m_current_number; 4580 } 4581 bool next() override { 4582 m_current_number = m_dist(m_rng); 4583 return true; 4584 } 4585 }; 4586 4587 // TODO: Ideally this would be also constrained against the various char types, 4588 // but I don't expect users to run into that in practice. 4589 template <typename T> 4590 typename std::enable_if<std::is_integral<T>::value && !std::is_same<T, bool>::value, 4591 GeneratorWrapper<T>>::type 4592 random(T a, T b) { 4593 return GeneratorWrapper<T>( 4594 pf::make_unique<RandomIntegerGenerator<T>>(a, b) 4595 ); 4596 } 4597 4598 template <typename T> 4599 typename std::enable_if<std::is_floating_point<T>::value, 4600 GeneratorWrapper<T>>::type 4601 random(T a, T b) { 4602 return GeneratorWrapper<T>( 4603 pf::make_unique<RandomFloatingGenerator<T>>(a, b) 4604 ); 4605 } 4606 4607 template <typename T> 4608 class RangeGenerator final : public IGenerator<T> { 4609 T m_current; 4610 T m_end; 4611 T m_step; 4612 bool m_positive; 4613 4614 public: 4615 RangeGenerator(T const& start, T const& end, T const& step): 4616 m_current(start), 4617 m_end(end), 4618 m_step(step), 4619 m_positive(m_step > T(0)) 4620 { 4621 assert(m_current != m_end && "Range start and end cannot be equal"); 4622 assert(m_step != T(0) && "Step size cannot be zero"); 4623 assert(((m_positive && m_current <= m_end) || (!m_positive && m_current >= m_end)) && "Step moves away from end"); 4624 } 4625 4626 RangeGenerator(T const& start, T const& end): 4627 RangeGenerator(start, end, (start < end) ? T(1) : T(-1)) 4628 {} 4629 4630 T const& get() const override { 4631 return m_current; 4632 } 4633 4634 bool next() override { 4635 m_current += m_step; 4636 return (m_positive) ? (m_current < m_end) : (m_current > m_end); 4637 } 4638 }; 4639 4640 template <typename T> 4641 GeneratorWrapper<T> range(T const& start, T const& end, T const& step) { 4642 static_assert(std::is_arithmetic<T>::value && !std::is_same<T, bool>::value, "Type must be numeric"); 4643 return GeneratorWrapper<T>(pf::make_unique<RangeGenerator<T>>(start, end, step)); 4644 } 4645 4646 template <typename T> 4647 GeneratorWrapper<T> range(T const& start, T const& end) { 4648 static_assert(std::is_integral<T>::value && !std::is_same<T, bool>::value, "Type must be an integer"); 4649 return GeneratorWrapper<T>(pf::make_unique<RangeGenerator<T>>(start, end)); 4650 } 4651 4652 template <typename T> 4653 class IteratorGenerator final : public IGenerator<T> { 4654 static_assert(!std::is_same<T, bool>::value, 4655 "IteratorGenerator currently does not support bools" 4656 "because of std::vector<bool> specialization"); 4657 4658 std::vector<T> m_elems; 4659 size_t m_current = 0; 4660 public: 4661 template <typename InputIterator, typename InputSentinel> 4662 IteratorGenerator(InputIterator first, InputSentinel last):m_elems(first, last) { 4663 if (m_elems.empty()) { 4664 Catch::throw_exception(GeneratorException("IteratorGenerator received no valid values")); 4665 } 4666 } 4667 4668 T const& get() const override { 4669 return m_elems[m_current]; 4670 } 4671 4672 bool next() override { 4673 ++m_current; 4674 return m_current != m_elems.size(); 4675 } 4676 }; 4677 4678 template <typename InputIterator, 4679 typename InputSentinel, 4680 typename ResultType = typename std::iterator_traits<InputIterator>::value_type> 4681 GeneratorWrapper<ResultType> from_range(InputIterator from, InputSentinel to) { 4682 return GeneratorWrapper<ResultType>(pf::make_unique<IteratorGenerator<ResultType>>(from, to)); 4683 } 4684 4685 template <typename Container, 4686 typename ResultType = typename Container::value_type> 4687 GeneratorWrapper<ResultType> from_range(Container const& cnt) { 4688 return GeneratorWrapper<ResultType>(pf::make_unique<IteratorGenerator<ResultType>>(cnt.begin(), cnt.end())); 4689 } 4690 4691 } // namespace Generators 4692 } // namespace Catch 4693 4694 // end catch_generators_specific.hpp 4695 4696 // These files are included here so the single_include script doesn't put them 4697 // in the conditionally compiled sections 4698 // start catch_test_case_info.h 4699 4700 #include <string> 4701 #include <vector> 4702 #include <memory> 4703 4704 #ifdef __clang__ 4705 #pragma clang diagnostic push 4706 #pragma clang diagnostic ignored "-Wpadded" 4707 #endif 4708 4709 namespace Catch { 4710 4711 struct ITestInvoker; 4712 4713 struct TestCaseInfo { 4714 enum SpecialProperties{ 4715 None = 0, 4716 IsHidden = 1 << 1, 4717 ShouldFail = 1 << 2, 4718 MayFail = 1 << 3, 4719 Throws = 1 << 4, 4720 NonPortable = 1 << 5, 4721 Benchmark = 1 << 6 4722 }; 4723 4724 TestCaseInfo( std::string const& _name, 4725 std::string const& _className, 4726 std::string const& _description, 4727 std::vector<std::string> const& _tags, 4728 SourceLineInfo const& _lineInfo ); 4729 4730 friend void setTags( TestCaseInfo& testCaseInfo, std::vector<std::string> tags ); 4731 4732 bool isHidden() const; 4733 bool throws() const; 4734 bool okToFail() const; 4735 bool expectedToFail() const; 4736 4737 std::string tagsAsString() const; 4738 4739 std::string name; 4740 std::string className; 4741 std::string description; 4742 std::vector<std::string> tags; 4743 std::vector<std::string> lcaseTags; 4744 SourceLineInfo lineInfo; 4745 SpecialProperties properties; 4746 }; 4747 4748 class TestCase : public TestCaseInfo { 4749 public: 4750 4751 TestCase( ITestInvoker* testCase, TestCaseInfo&& info ); 4752 4753 TestCase withName( std::string const& _newName ) const; 4754 4755 void invoke() const; 4756 4757 TestCaseInfo const& getTestCaseInfo() const; 4758 4759 bool operator == ( TestCase const& other ) const; 4760 bool operator < ( TestCase const& other ) const; 4761 4762 private: 4763 std::shared_ptr<ITestInvoker> test; 4764 }; 4765 4766 TestCase makeTestCase( ITestInvoker* testCase, 4767 std::string const& className, 4768 NameAndTags const& nameAndTags, 4769 SourceLineInfo const& lineInfo ); 4770 } 4771 4772 #ifdef __clang__ 4773 #pragma clang diagnostic pop 4774 #endif 4775 4776 // end catch_test_case_info.h 4777 // start catch_interfaces_runner.h 4778 4779 namespace Catch { 4780 4781 struct IRunner { 4782 virtual ~IRunner(); 4783 virtual bool aborting() const = 0; 4784 }; 4785 } 4786 4787 // end catch_interfaces_runner.h 4788 4789 #ifdef __OBJC__ 4790 // start catch_objc.hpp 4791 4792 #import <objc/runtime.h> 4793 4794 #include <string> 4795 4796 // NB. Any general catch headers included here must be included 4797 // in catch.hpp first to make sure they are included by the single 4798 // header for non obj-usage 4799 4800 /////////////////////////////////////////////////////////////////////////////// 4801 // This protocol is really only here for (self) documenting purposes, since 4802 // all its methods are optional. 4803 @protocol OcFixture 4804 4805 @optional 4806 4807 -(void) setUp; 4808 -(void) tearDown; 4809 4810 @end 4811 4812 namespace Catch { 4813 4814 class OcMethod : public ITestInvoker { 4815 4816 public: 4817 OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} 4818 4819 virtual void invoke() const { 4820 id obj = [[m_cls alloc] init]; 4821 4822 performOptionalSelector( obj, @selector(setUp) ); 4823 performOptionalSelector( obj, m_sel ); 4824 performOptionalSelector( obj, @selector(tearDown) ); 4825 4826 arcSafeRelease( obj ); 4827 } 4828 private: 4829 virtual ~OcMethod() {} 4830 4831 Class m_cls; 4832 SEL m_sel; 4833 }; 4834 4835 namespace Detail{ 4836 4837 inline std::string getAnnotation( Class cls, 4838 std::string const& annotationName, 4839 std::string const& testCaseName ) { 4840 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()]; 4841 SEL sel = NSSelectorFromString( selStr ); 4842 arcSafeRelease( selStr ); 4843 id value = performOptionalSelector( cls, sel ); 4844 if( value ) 4845 return [(NSString*)value UTF8String]; 4846 return ""; 4847 } 4848 } 4849 4850 inline std::size_t registerTestMethods() { 4851 std::size_t noTestMethods = 0; 4852 int noClasses = objc_getClassList( nullptr, 0 ); 4853 4854 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); 4855 objc_getClassList( classes, noClasses ); 4856 4857 for( int c = 0; c < noClasses; c++ ) { 4858 Class cls = classes[c]; 4859 { 4860 u_int count; 4861 Method* methods = class_copyMethodList( cls, &count ); 4862 for( u_int m = 0; m < count ; m++ ) { 4863 SEL selector = method_getName(methods[m]); 4864 std::string methodName = sel_getName(selector); 4865 if( startsWith( methodName, "Catch_TestCase_" ) ) { 4866 std::string testCaseName = methodName.substr( 15 ); 4867 std::string name = Detail::getAnnotation( cls, "Name", testCaseName ); 4868 std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); 4869 const char* className = class_getName( cls ); 4870 4871 getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, NameAndTags( name.c_str(), desc.c_str() ), SourceLineInfo("",0) ) ); 4872 noTestMethods++; 4873 } 4874 } 4875 free(methods); 4876 } 4877 } 4878 return noTestMethods; 4879 } 4880 4881 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 4882 4883 namespace Matchers { 4884 namespace Impl { 4885 namespace NSStringMatchers { 4886 4887 struct StringHolder : MatcherBase<NSString*>{ 4888 StringHolder( NSString* substr ) : m_substr( [substr copy] ){} 4889 StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){} 4890 StringHolder() { 4891 arcSafeRelease( m_substr ); 4892 } 4893 4894 bool match( NSString* str ) const override { 4895 return false; 4896 } 4897 4898 NSString* CATCH_ARC_STRONG m_substr; 4899 }; 4900 4901 struct Equals : StringHolder { 4902 Equals( NSString* substr ) : StringHolder( substr ){} 4903 4904 bool match( NSString* str ) const override { 4905 return (str != nil || m_substr == nil ) && 4906 [str isEqualToString:m_substr]; 4907 } 4908 4909 std::string describe() const override { 4910 return "equals string: " + Catch::Detail::stringify( m_substr ); 4911 } 4912 }; 4913 4914 struct Contains : StringHolder { 4915 Contains( NSString* substr ) : StringHolder( substr ){} 4916 4917 bool match( NSString* str ) const override { 4918 return (str != nil || m_substr == nil ) && 4919 [str rangeOfString:m_substr].location != NSNotFound; 4920 } 4921 4922 std::string describe() const override { 4923 return "contains string: " + Catch::Detail::stringify( m_substr ); 4924 } 4925 }; 4926 4927 struct StartsWith : StringHolder { 4928 StartsWith( NSString* substr ) : StringHolder( substr ){} 4929 4930 bool match( NSString* str ) const override { 4931 return (str != nil || m_substr == nil ) && 4932 [str rangeOfString:m_substr].location == 0; 4933 } 4934 4935 std::string describe() const override { 4936 return "starts with: " + Catch::Detail::stringify( m_substr ); 4937 } 4938 }; 4939 struct EndsWith : StringHolder { 4940 EndsWith( NSString* substr ) : StringHolder( substr ){} 4941 4942 bool match( NSString* str ) const override { 4943 return (str != nil || m_substr == nil ) && 4944 [str rangeOfString:m_substr].location == [str length] - [m_substr length]; 4945 } 4946 4947 std::string describe() const override { 4948 return "ends with: " + Catch::Detail::stringify( m_substr ); 4949 } 4950 }; 4951 4952 } // namespace NSStringMatchers 4953 } // namespace Impl 4954 4955 inline Impl::NSStringMatchers::Equals 4956 Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); } 4957 4958 inline Impl::NSStringMatchers::Contains 4959 Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); } 4960 4961 inline Impl::NSStringMatchers::StartsWith 4962 StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); } 4963 4964 inline Impl::NSStringMatchers::EndsWith 4965 EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); } 4966 4967 } // namespace Matchers 4968 4969 using namespace Matchers; 4970 4971 #endif // CATCH_CONFIG_DISABLE_MATCHERS 4972 4973 } // namespace Catch 4974 4975 /////////////////////////////////////////////////////////////////////////////// 4976 #define OC_MAKE_UNIQUE_NAME( root, uniqueSuffix ) root##uniqueSuffix 4977 #define OC_TEST_CASE2( name, desc, uniqueSuffix ) \ 4978 +(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Name_test_, uniqueSuffix ) \ 4979 { \ 4980 return @ name; \ 4981 } \ 4982 +(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Description_test_, uniqueSuffix ) \ 4983 { \ 4984 return @ desc; \ 4985 } \ 4986 -(void) OC_MAKE_UNIQUE_NAME( Catch_TestCase_test_, uniqueSuffix ) 4987 4988 #define OC_TEST_CASE( name, desc ) OC_TEST_CASE2( name, desc, __LINE__ ) 4989 4990 // end catch_objc.hpp 4991 #endif 4992 4993 // Benchmarking needs the externally-facing parts of reporters to work 4994 #if defined(CATCH_CONFIG_EXTERNAL_INTERFACES) || defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 4995 // start catch_external_interfaces.h 4996 4997 // start catch_reporter_bases.hpp 4998 4999 // start catch_interfaces_reporter.h 5000 5001 // start catch_config.hpp 5002 5003 // start catch_test_spec_parser.h 5004 5005 #ifdef __clang__ 5006 #pragma clang diagnostic push 5007 #pragma clang diagnostic ignored "-Wpadded" 5008 #endif 5009 5010 // start catch_test_spec.h 5011 5012 #ifdef __clang__ 5013 #pragma clang diagnostic push 5014 #pragma clang diagnostic ignored "-Wpadded" 5015 #endif 5016 5017 // start catch_wildcard_pattern.h 5018 5019 namespace Catch 5020 { 5021 class WildcardPattern { 5022 enum WildcardPosition { 5023 NoWildcard = 0, 5024 WildcardAtStart = 1, 5025 WildcardAtEnd = 2, 5026 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd 5027 }; 5028 5029 public: 5030 5031 WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity ); 5032 virtual ~WildcardPattern() = default; 5033 virtual bool matches( std::string const& str ) const; 5034 5035 private: 5036 std::string normaliseString( std::string const& str ) const; 5037 CaseSensitive::Choice m_caseSensitivity; 5038 WildcardPosition m_wildcard = NoWildcard; 5039 std::string m_pattern; 5040 }; 5041 } 5042 5043 // end catch_wildcard_pattern.h 5044 #include <string> 5045 #include <vector> 5046 #include <memory> 5047 5048 namespace Catch { 5049 5050 struct IConfig; 5051 5052 class TestSpec { 5053 class Pattern { 5054 public: 5055 explicit Pattern( std::string const& name ); 5056 virtual ~Pattern(); 5057 virtual bool matches( TestCaseInfo const& testCase ) const = 0; 5058 std::string const& name() const; 5059 private: 5060 std::string const m_name; 5061 }; 5062 using PatternPtr = std::shared_ptr<Pattern>; 5063 5064 class NamePattern : public Pattern { 5065 public: 5066 explicit NamePattern( std::string const& name, std::string const& filterString ); 5067 bool matches( TestCaseInfo const& testCase ) const override; 5068 private: 5069 WildcardPattern m_wildcardPattern; 5070 }; 5071 5072 class TagPattern : public Pattern { 5073 public: 5074 explicit TagPattern( std::string const& tag, std::string const& filterString ); 5075 bool matches( TestCaseInfo const& testCase ) const override; 5076 private: 5077 std::string m_tag; 5078 }; 5079 5080 class ExcludedPattern : public Pattern { 5081 public: 5082 explicit ExcludedPattern( PatternPtr const& underlyingPattern ); 5083 bool matches( TestCaseInfo const& testCase ) const override; 5084 private: 5085 PatternPtr m_underlyingPattern; 5086 }; 5087 5088 struct Filter { 5089 std::vector<PatternPtr> m_patterns; 5090 5091 bool matches( TestCaseInfo const& testCase ) const; 5092 std::string name() const; 5093 }; 5094 5095 public: 5096 struct FilterMatch { 5097 std::string name; 5098 std::vector<TestCase const*> tests; 5099 }; 5100 using Matches = std::vector<FilterMatch>; 5101 using vectorStrings = std::vector<std::string>; 5102 5103 bool hasFilters() const; 5104 bool matches( TestCaseInfo const& testCase ) const; 5105 Matches matchesByFilter( std::vector<TestCase> const& testCases, IConfig const& config ) const; 5106 const vectorStrings & getInvalidArgs() const; 5107 5108 private: 5109 std::vector<Filter> m_filters; 5110 std::vector<std::string> m_invalidArgs; 5111 friend class TestSpecParser; 5112 }; 5113 } 5114 5115 #ifdef __clang__ 5116 #pragma clang diagnostic pop 5117 #endif 5118 5119 // end catch_test_spec.h 5120 // start catch_interfaces_tag_alias_registry.h 5121 5122 #include <string> 5123 5124 namespace Catch { 5125 5126 struct TagAlias; 5127 5128 struct ITagAliasRegistry { 5129 virtual ~ITagAliasRegistry(); 5130 // Nullptr if not present 5131 virtual TagAlias const* find( std::string const& alias ) const = 0; 5132 virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; 5133 5134 static ITagAliasRegistry const& get(); 5135 }; 5136 5137 } // end namespace Catch 5138 5139 // end catch_interfaces_tag_alias_registry.h 5140 namespace Catch { 5141 5142 class TestSpecParser { 5143 enum Mode{ None, Name, QuotedName, Tag, EscapedName }; 5144 Mode m_mode = None; 5145 Mode lastMode = None; 5146 bool m_exclusion = false; 5147 std::size_t m_pos = 0; 5148 std::size_t m_realPatternPos = 0; 5149 std::string m_arg; 5150 std::string m_substring; 5151 std::string m_patternName; 5152 std::vector<std::size_t> m_escapeChars; 5153 TestSpec::Filter m_currentFilter; 5154 TestSpec m_testSpec; 5155 ITagAliasRegistry const* m_tagAliases = nullptr; 5156 5157 public: 5158 TestSpecParser( ITagAliasRegistry const& tagAliases ); 5159 5160 TestSpecParser& parse( std::string const& arg ); 5161 TestSpec testSpec(); 5162 5163 private: 5164 bool visitChar( char c ); 5165 void startNewMode( Mode mode ); 5166 bool processNoneChar( char c ); 5167 void processNameChar( char c ); 5168 bool processOtherChar( char c ); 5169 void endMode(); 5170 void escape(); 5171 bool isControlChar( char c ) const; 5172 void saveLastMode(); 5173 void revertBackToLastMode(); 5174 void addFilter(); 5175 bool separate(); 5176 5177 // Handles common preprocessing of the pattern for name/tag patterns 5178 std::string preprocessPattern(); 5179 // Adds the current pattern as a test name 5180 void addNamePattern(); 5181 // Adds the current pattern as a tag 5182 void addTagPattern(); 5183 5184 inline void addCharToPattern(char c) { 5185 m_substring += c; 5186 m_patternName += c; 5187 m_realPatternPos++; 5188 } 5189 5190 }; 5191 TestSpec parseTestSpec( std::string const& arg ); 5192 5193 } // namespace Catch 5194 5195 #ifdef __clang__ 5196 #pragma clang diagnostic pop 5197 #endif 5198 5199 // end catch_test_spec_parser.h 5200 // Libstdc++ doesn't like incomplete classes for unique_ptr 5201 5202 #include <memory> 5203 #include <vector> 5204 #include <string> 5205 5206 #ifndef CATCH_CONFIG_CONSOLE_WIDTH 5207 #define CATCH_CONFIG_CONSOLE_WIDTH 80 5208 #endif 5209 5210 namespace Catch { 5211 5212 struct IStream; 5213 5214 struct ConfigData { 5215 bool listTests = false; 5216 bool listTags = false; 5217 bool listReporters = false; 5218 bool listTestNamesOnly = false; 5219 5220 bool showSuccessfulTests = false; 5221 bool shouldDebugBreak = false; 5222 bool noThrow = false; 5223 bool showHelp = false; 5224 bool showInvisibles = false; 5225 bool filenamesAsTags = false; 5226 bool libIdentify = false; 5227 5228 int abortAfter = -1; 5229 unsigned int rngSeed = 0; 5230 5231 bool benchmarkNoAnalysis = false; 5232 unsigned int benchmarkSamples = 100; 5233 double benchmarkConfidenceInterval = 0.95; 5234 unsigned int benchmarkResamples = 100000; 5235 5236 Verbosity verbosity = Verbosity::Normal; 5237 WarnAbout::What warnings = WarnAbout::Nothing; 5238 ShowDurations::OrNot showDurations = ShowDurations::DefaultForReporter; 5239 RunTests::InWhatOrder runOrder = RunTests::InDeclarationOrder; 5240 UseColour::YesOrNo useColour = UseColour::Auto; 5241 WaitForKeypress::When waitForKeypress = WaitForKeypress::Never; 5242 5243 std::string outputFilename; 5244 std::string name; 5245 std::string processName; 5246 #ifndef CATCH_CONFIG_DEFAULT_REPORTER 5247 #define CATCH_CONFIG_DEFAULT_REPORTER "console" 5248 #endif 5249 std::string reporterName = CATCH_CONFIG_DEFAULT_REPORTER; 5250 #undef CATCH_CONFIG_DEFAULT_REPORTER 5251 5252 std::vector<std::string> testsOrTags; 5253 std::vector<std::string> sectionsToRun; 5254 }; 5255 5256 class Config : public IConfig { 5257 public: 5258 5259 Config() = default; 5260 Config( ConfigData const& data ); 5261 virtual ~Config() = default; 5262 5263 std::string const& getFilename() const; 5264 5265 bool listTests() const; 5266 bool listTestNamesOnly() const; 5267 bool listTags() const; 5268 bool listReporters() const; 5269 5270 std::string getProcessName() const; 5271 std::string const& getReporterName() const; 5272 5273 std::vector<std::string> const& getTestsOrTags() const override; 5274 std::vector<std::string> const& getSectionsToRun() const override; 5275 5276 TestSpec const& testSpec() const override; 5277 bool hasTestFilters() const override; 5278 5279 bool showHelp() const; 5280 5281 // IConfig interface 5282 bool allowThrows() const override; 5283 std::ostream& stream() const override; 5284 std::string name() const override; 5285 bool includeSuccessfulResults() const override; 5286 bool warnAboutMissingAssertions() const override; 5287 bool warnAboutNoTests() const override; 5288 ShowDurations::OrNot showDurations() const override; 5289 RunTests::InWhatOrder runOrder() const override; 5290 unsigned int rngSeed() const override; 5291 UseColour::YesOrNo useColour() const override; 5292 bool shouldDebugBreak() const override; 5293 int abortAfter() const override; 5294 bool showInvisibles() const override; 5295 Verbosity verbosity() const override; 5296 bool benchmarkNoAnalysis() const override; 5297 int benchmarkSamples() const override; 5298 double benchmarkConfidenceInterval() const override; 5299 unsigned int benchmarkResamples() const override; 5300 5301 private: 5302 5303 IStream const* openStream(); 5304 ConfigData m_data; 5305 5306 std::unique_ptr<IStream const> m_stream; 5307 TestSpec m_testSpec; 5308 bool m_hasTestFilters = false; 5309 }; 5310 5311 } // end namespace Catch 5312 5313 // end catch_config.hpp 5314 // start catch_assertionresult.h 5315 5316 #include <string> 5317 5318 namespace Catch { 5319 5320 struct AssertionResultData 5321 { 5322 AssertionResultData() = delete; 5323 5324 AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression ); 5325 5326 std::string message; 5327 mutable std::string reconstructedExpression; 5328 LazyExpression lazyExpression; 5329 ResultWas::OfType resultType; 5330 5331 std::string reconstructExpression() const; 5332 }; 5333 5334 class AssertionResult { 5335 public: 5336 AssertionResult() = delete; 5337 AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); 5338 5339 bool isOk() const; 5340 bool succeeded() const; 5341 ResultWas::OfType getResultType() const; 5342 bool hasExpression() const; 5343 bool hasMessage() const; 5344 std::string getExpression() const; 5345 std::string getExpressionInMacro() const; 5346 bool hasExpandedExpression() const; 5347 std::string getExpandedExpression() const; 5348 std::string getMessage() const; 5349 SourceLineInfo getSourceInfo() const; 5350 StringRef getTestMacroName() const; 5351 5352 //protected: 5353 AssertionInfo m_info; 5354 AssertionResultData m_resultData; 5355 }; 5356 5357 } // end namespace Catch 5358 5359 // end catch_assertionresult.h 5360 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 5361 // start catch_estimate.hpp 5362 5363 // Statistics estimates 5364 5365 5366 namespace Catch { 5367 namespace Benchmark { 5368 template <typename Duration> 5369 struct Estimate { 5370 Duration point; 5371 Duration lower_bound; 5372 Duration upper_bound; 5373 double confidence_interval; 5374 5375 template <typename Duration2> 5376 operator Estimate<Duration2>() const { 5377 return { point, lower_bound, upper_bound, confidence_interval }; 5378 } 5379 }; 5380 } // namespace Benchmark 5381 } // namespace Catch 5382 5383 // end catch_estimate.hpp 5384 // start catch_outlier_classification.hpp 5385 5386 // Outlier information 5387 5388 namespace Catch { 5389 namespace Benchmark { 5390 struct OutlierClassification { 5391 int samples_seen = 0; 5392 int low_severe = 0; // more than 3 times IQR below Q1 5393 int low_mild = 0; // 1.5 to 3 times IQR below Q1 5394 int high_mild = 0; // 1.5 to 3 times IQR above Q3 5395 int high_severe = 0; // more than 3 times IQR above Q3 5396 5397 int total() const { 5398 return low_severe + low_mild + high_mild + high_severe; 5399 } 5400 }; 5401 } // namespace Benchmark 5402 } // namespace Catch 5403 5404 // end catch_outlier_classification.hpp 5405 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 5406 5407 #include <string> 5408 #include <iosfwd> 5409 #include <map> 5410 #include <set> 5411 #include <memory> 5412 #include <algorithm> 5413 5414 namespace Catch { 5415 5416 struct ReporterConfig { 5417 explicit ReporterConfig( IConfigPtr const& _fullConfig ); 5418 5419 ReporterConfig( IConfigPtr const& _fullConfig, std::ostream& _stream ); 5420 5421 std::ostream& stream() const; 5422 IConfigPtr fullConfig() const; 5423 5424 private: 5425 std::ostream* m_stream; 5426 IConfigPtr m_fullConfig; 5427 }; 5428 5429 struct ReporterPreferences { 5430 bool shouldRedirectStdOut = false; 5431 bool shouldReportAllAssertions = false; 5432 }; 5433 5434 template<typename T> 5435 struct LazyStat : Option<T> { 5436 LazyStat& operator=( T const& _value ) { 5437 Option<T>::operator=( _value ); 5438 used = false; 5439 return *this; 5440 } 5441 void reset() { 5442 Option<T>::reset(); 5443 used = false; 5444 } 5445 bool used = false; 5446 }; 5447 5448 struct TestRunInfo { 5449 TestRunInfo( std::string const& _name ); 5450 std::string name; 5451 }; 5452 struct GroupInfo { 5453 GroupInfo( std::string const& _name, 5454 std::size_t _groupIndex, 5455 std::size_t _groupsCount ); 5456 5457 std::string name; 5458 std::size_t groupIndex; 5459 std::size_t groupsCounts; 5460 }; 5461 5462 struct AssertionStats { 5463 AssertionStats( AssertionResult const& _assertionResult, 5464 std::vector<MessageInfo> const& _infoMessages, 5465 Totals const& _totals ); 5466 5467 AssertionStats( AssertionStats const& ) = default; 5468 AssertionStats( AssertionStats && ) = default; 5469 AssertionStats& operator = ( AssertionStats const& ) = delete; 5470 AssertionStats& operator = ( AssertionStats && ) = delete; 5471 virtual ~AssertionStats(); 5472 5473 AssertionResult assertionResult; 5474 std::vector<MessageInfo> infoMessages; 5475 Totals totals; 5476 }; 5477 5478 struct SectionStats { 5479 SectionStats( SectionInfo const& _sectionInfo, 5480 Counts const& _assertions, 5481 double _durationInSeconds, 5482 bool _missingAssertions ); 5483 SectionStats( SectionStats const& ) = default; 5484 SectionStats( SectionStats && ) = default; 5485 SectionStats& operator = ( SectionStats const& ) = default; 5486 SectionStats& operator = ( SectionStats && ) = default; 5487 virtual ~SectionStats(); 5488 5489 SectionInfo sectionInfo; 5490 Counts assertions; 5491 double durationInSeconds; 5492 bool missingAssertions; 5493 }; 5494 5495 struct TestCaseStats { 5496 TestCaseStats( TestCaseInfo const& _testInfo, 5497 Totals const& _totals, 5498 std::string const& _stdOut, 5499 std::string const& _stdErr, 5500 bool _aborting ); 5501 5502 TestCaseStats( TestCaseStats const& ) = default; 5503 TestCaseStats( TestCaseStats && ) = default; 5504 TestCaseStats& operator = ( TestCaseStats const& ) = default; 5505 TestCaseStats& operator = ( TestCaseStats && ) = default; 5506 virtual ~TestCaseStats(); 5507 5508 TestCaseInfo testInfo; 5509 Totals totals; 5510 std::string stdOut; 5511 std::string stdErr; 5512 bool aborting; 5513 }; 5514 5515 struct TestGroupStats { 5516 TestGroupStats( GroupInfo const& _groupInfo, 5517 Totals const& _totals, 5518 bool _aborting ); 5519 TestGroupStats( GroupInfo const& _groupInfo ); 5520 5521 TestGroupStats( TestGroupStats const& ) = default; 5522 TestGroupStats( TestGroupStats && ) = default; 5523 TestGroupStats& operator = ( TestGroupStats const& ) = default; 5524 TestGroupStats& operator = ( TestGroupStats && ) = default; 5525 virtual ~TestGroupStats(); 5526 5527 GroupInfo groupInfo; 5528 Totals totals; 5529 bool aborting; 5530 }; 5531 5532 struct TestRunStats { 5533 TestRunStats( TestRunInfo const& _runInfo, 5534 Totals const& _totals, 5535 bool _aborting ); 5536 5537 TestRunStats( TestRunStats const& ) = default; 5538 TestRunStats( TestRunStats && ) = default; 5539 TestRunStats& operator = ( TestRunStats const& ) = default; 5540 TestRunStats& operator = ( TestRunStats && ) = default; 5541 virtual ~TestRunStats(); 5542 5543 TestRunInfo runInfo; 5544 Totals totals; 5545 bool aborting; 5546 }; 5547 5548 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 5549 struct BenchmarkInfo { 5550 std::string name; 5551 double estimatedDuration; 5552 int iterations; 5553 int samples; 5554 unsigned int resamples; 5555 double clockResolution; 5556 double clockCost; 5557 }; 5558 5559 template <class Duration> 5560 struct BenchmarkStats { 5561 BenchmarkInfo info; 5562 5563 std::vector<Duration> samples; 5564 Benchmark::Estimate<Duration> mean; 5565 Benchmark::Estimate<Duration> standardDeviation; 5566 Benchmark::OutlierClassification outliers; 5567 double outlierVariance; 5568 5569 template <typename Duration2> 5570 operator BenchmarkStats<Duration2>() const { 5571 std::vector<Duration2> samples2; 5572 samples2.reserve(samples.size()); 5573 std::transform(samples.begin(), samples.end(), std::back_inserter(samples2), [](Duration d) { return Duration2(d); }); 5574 return { 5575 info, 5576 std::move(samples2), 5577 mean, 5578 standardDeviation, 5579 outliers, 5580 outlierVariance, 5581 }; 5582 } 5583 }; 5584 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 5585 5586 struct IStreamingReporter { 5587 virtual ~IStreamingReporter() = default; 5588 5589 // Implementing class must also provide the following static methods: 5590 // static std::string getDescription(); 5591 // static std::set<Verbosity> getSupportedVerbosities() 5592 5593 virtual ReporterPreferences getPreferences() const = 0; 5594 5595 virtual void noMatchingTestCases( std::string const& spec ) = 0; 5596 5597 virtual void reportInvalidArguments(std::string const&) {} 5598 5599 virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; 5600 virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0; 5601 5602 virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; 5603 virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; 5604 5605 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 5606 virtual void benchmarkPreparing( std::string const& ) {} 5607 virtual void benchmarkStarting( BenchmarkInfo const& ) {} 5608 virtual void benchmarkEnded( BenchmarkStats<> const& ) {} 5609 virtual void benchmarkFailed( std::string const& ) {} 5610 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 5611 5612 virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; 5613 5614 // The return value indicates if the messages buffer should be cleared: 5615 virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; 5616 5617 virtual void sectionEnded( SectionStats const& sectionStats ) = 0; 5618 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; 5619 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; 5620 virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; 5621 5622 virtual void skipTest( TestCaseInfo const& testInfo ) = 0; 5623 5624 // Default empty implementation provided 5625 virtual void fatalErrorEncountered( StringRef name ); 5626 5627 virtual bool isMulti() const; 5628 }; 5629 using IStreamingReporterPtr = std::unique_ptr<IStreamingReporter>; 5630 5631 struct IReporterFactory { 5632 virtual ~IReporterFactory(); 5633 virtual IStreamingReporterPtr create( ReporterConfig const& config ) const = 0; 5634 virtual std::string getDescription() const = 0; 5635 }; 5636 using IReporterFactoryPtr = std::shared_ptr<IReporterFactory>; 5637 5638 struct IReporterRegistry { 5639 using FactoryMap = std::map<std::string, IReporterFactoryPtr>; 5640 using Listeners = std::vector<IReporterFactoryPtr>; 5641 5642 virtual ~IReporterRegistry(); 5643 virtual IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const = 0; 5644 virtual FactoryMap const& getFactories() const = 0; 5645 virtual Listeners const& getListeners() const = 0; 5646 }; 5647 5648 } // end namespace Catch 5649 5650 // end catch_interfaces_reporter.h 5651 #include <algorithm> 5652 #include <cstring> 5653 #include <cfloat> 5654 #include <cstdio> 5655 #include <cassert> 5656 #include <memory> 5657 #include <ostream> 5658 5659 namespace Catch { 5660 void prepareExpandedExpression(AssertionResult& result); 5661 5662 // Returns double formatted as %.3f (format expected on output) 5663 std::string getFormattedDuration( double duration ); 5664 5665 std::string serializeFilters( std::vector<std::string> const& container ); 5666 5667 template<typename DerivedT> 5668 struct StreamingReporterBase : IStreamingReporter { 5669 5670 StreamingReporterBase( ReporterConfig const& _config ) 5671 : m_config( _config.fullConfig() ), 5672 stream( _config.stream() ) 5673 { 5674 m_reporterPrefs.shouldRedirectStdOut = false; 5675 if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) ) 5676 CATCH_ERROR( "Verbosity level not supported by this reporter" ); 5677 } 5678 5679 ReporterPreferences getPreferences() const override { 5680 return m_reporterPrefs; 5681 } 5682 5683 static std::set<Verbosity> getSupportedVerbosities() { 5684 return { Verbosity::Normal }; 5685 } 5686 5687 ~StreamingReporterBase() override = default; 5688 5689 void noMatchingTestCases(std::string const&) override {} 5690 5691 void reportInvalidArguments(std::string const&) override {} 5692 5693 void testRunStarting(TestRunInfo const& _testRunInfo) override { 5694 currentTestRunInfo = _testRunInfo; 5695 } 5696 5697 void testGroupStarting(GroupInfo const& _groupInfo) override { 5698 currentGroupInfo = _groupInfo; 5699 } 5700 5701 void testCaseStarting(TestCaseInfo const& _testInfo) override { 5702 currentTestCaseInfo = _testInfo; 5703 } 5704 void sectionStarting(SectionInfo const& _sectionInfo) override { 5705 m_sectionStack.push_back(_sectionInfo); 5706 } 5707 5708 void sectionEnded(SectionStats const& /* _sectionStats */) override { 5709 m_sectionStack.pop_back(); 5710 } 5711 void testCaseEnded(TestCaseStats const& /* _testCaseStats */) override { 5712 currentTestCaseInfo.reset(); 5713 } 5714 void testGroupEnded(TestGroupStats const& /* _testGroupStats */) override { 5715 currentGroupInfo.reset(); 5716 } 5717 void testRunEnded(TestRunStats const& /* _testRunStats */) override { 5718 currentTestCaseInfo.reset(); 5719 currentGroupInfo.reset(); 5720 currentTestRunInfo.reset(); 5721 } 5722 5723 void skipTest(TestCaseInfo const&) override { 5724 // Don't do anything with this by default. 5725 // It can optionally be overridden in the derived class. 5726 } 5727 5728 IConfigPtr m_config; 5729 std::ostream& stream; 5730 5731 LazyStat<TestRunInfo> currentTestRunInfo; 5732 LazyStat<GroupInfo> currentGroupInfo; 5733 LazyStat<TestCaseInfo> currentTestCaseInfo; 5734 5735 std::vector<SectionInfo> m_sectionStack; 5736 ReporterPreferences m_reporterPrefs; 5737 }; 5738 5739 template<typename DerivedT> 5740 struct CumulativeReporterBase : IStreamingReporter { 5741 template<typename T, typename ChildNodeT> 5742 struct Node { 5743 explicit Node( T const& _value ) : value( _value ) {} 5744 virtual ~Node() {} 5745 5746 using ChildNodes = std::vector<std::shared_ptr<ChildNodeT>>; 5747 T value; 5748 ChildNodes children; 5749 }; 5750 struct SectionNode { 5751 explicit SectionNode(SectionStats const& _stats) : stats(_stats) {} 5752 virtual ~SectionNode() = default; 5753 5754 bool operator == (SectionNode const& other) const { 5755 return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; 5756 } 5757 bool operator == (std::shared_ptr<SectionNode> const& other) const { 5758 return operator==(*other); 5759 } 5760 5761 SectionStats stats; 5762 using ChildSections = std::vector<std::shared_ptr<SectionNode>>; 5763 using Assertions = std::vector<AssertionStats>; 5764 ChildSections childSections; 5765 Assertions assertions; 5766 std::string stdOut; 5767 std::string stdErr; 5768 }; 5769 5770 struct BySectionInfo { 5771 BySectionInfo( SectionInfo const& other ) : m_other( other ) {} 5772 BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {} 5773 bool operator() (std::shared_ptr<SectionNode> const& node) const { 5774 return ((node->stats.sectionInfo.name == m_other.name) && 5775 (node->stats.sectionInfo.lineInfo == m_other.lineInfo)); 5776 } 5777 void operator=(BySectionInfo const&) = delete; 5778 5779 private: 5780 SectionInfo const& m_other; 5781 }; 5782 5783 using TestCaseNode = Node<TestCaseStats, SectionNode>; 5784 using TestGroupNode = Node<TestGroupStats, TestCaseNode>; 5785 using TestRunNode = Node<TestRunStats, TestGroupNode>; 5786 5787 CumulativeReporterBase( ReporterConfig const& _config ) 5788 : m_config( _config.fullConfig() ), 5789 stream( _config.stream() ) 5790 { 5791 m_reporterPrefs.shouldRedirectStdOut = false; 5792 if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) ) 5793 CATCH_ERROR( "Verbosity level not supported by this reporter" ); 5794 } 5795 ~CumulativeReporterBase() override = default; 5796 5797 ReporterPreferences getPreferences() const override { 5798 return m_reporterPrefs; 5799 } 5800 5801 static std::set<Verbosity> getSupportedVerbosities() { 5802 return { Verbosity::Normal }; 5803 } 5804 5805 void testRunStarting( TestRunInfo const& ) override {} 5806 void testGroupStarting( GroupInfo const& ) override {} 5807 5808 void testCaseStarting( TestCaseInfo const& ) override {} 5809 5810 void sectionStarting( SectionInfo const& sectionInfo ) override { 5811 SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); 5812 std::shared_ptr<SectionNode> node; 5813 if( m_sectionStack.empty() ) { 5814 if( !m_rootSection ) 5815 m_rootSection = std::make_shared<SectionNode>( incompleteStats ); 5816 node = m_rootSection; 5817 } 5818 else { 5819 SectionNode& parentNode = *m_sectionStack.back(); 5820 auto it = 5821 std::find_if( parentNode.childSections.begin(), 5822 parentNode.childSections.end(), 5823 BySectionInfo( sectionInfo ) ); 5824 if( it == parentNode.childSections.end() ) { 5825 node = std::make_shared<SectionNode>( incompleteStats ); 5826 parentNode.childSections.push_back( node ); 5827 } 5828 else 5829 node = *it; 5830 } 5831 m_sectionStack.push_back( node ); 5832 m_deepestSection = std::move(node); 5833 } 5834 5835 void assertionStarting(AssertionInfo const&) override {} 5836 5837 bool assertionEnded(AssertionStats const& assertionStats) override { 5838 assert(!m_sectionStack.empty()); 5839 // AssertionResult holds a pointer to a temporary DecomposedExpression, 5840 // which getExpandedExpression() calls to build the expression string. 5841 // Our section stack copy of the assertionResult will likely outlive the 5842 // temporary, so it must be expanded or discarded now to avoid calling 5843 // a destroyed object later. 5844 prepareExpandedExpression(const_cast<AssertionResult&>( assertionStats.assertionResult ) ); 5845 SectionNode& sectionNode = *m_sectionStack.back(); 5846 sectionNode.assertions.push_back(assertionStats); 5847 return true; 5848 } 5849 void sectionEnded(SectionStats const& sectionStats) override { 5850 assert(!m_sectionStack.empty()); 5851 SectionNode& node = *m_sectionStack.back(); 5852 node.stats = sectionStats; 5853 m_sectionStack.pop_back(); 5854 } 5855 void testCaseEnded(TestCaseStats const& testCaseStats) override { 5856 auto node = std::make_shared<TestCaseNode>(testCaseStats); 5857 assert(m_sectionStack.size() == 0); 5858 node->children.push_back(m_rootSection); 5859 m_testCases.push_back(node); 5860 m_rootSection.reset(); 5861 5862 assert(m_deepestSection); 5863 m_deepestSection->stdOut = testCaseStats.stdOut; 5864 m_deepestSection->stdErr = testCaseStats.stdErr; 5865 } 5866 void testGroupEnded(TestGroupStats const& testGroupStats) override { 5867 auto node = std::make_shared<TestGroupNode>(testGroupStats); 5868 node->children.swap(m_testCases); 5869 m_testGroups.push_back(node); 5870 } 5871 void testRunEnded(TestRunStats const& testRunStats) override { 5872 auto node = std::make_shared<TestRunNode>(testRunStats); 5873 node->children.swap(m_testGroups); 5874 m_testRuns.push_back(node); 5875 testRunEndedCumulative(); 5876 } 5877 virtual void testRunEndedCumulative() = 0; 5878 5879 void skipTest(TestCaseInfo const&) override {} 5880 5881 IConfigPtr m_config; 5882 std::ostream& stream; 5883 std::vector<AssertionStats> m_assertions; 5884 std::vector<std::vector<std::shared_ptr<SectionNode>>> m_sections; 5885 std::vector<std::shared_ptr<TestCaseNode>> m_testCases; 5886 std::vector<std::shared_ptr<TestGroupNode>> m_testGroups; 5887 5888 std::vector<std::shared_ptr<TestRunNode>> m_testRuns; 5889 5890 std::shared_ptr<SectionNode> m_rootSection; 5891 std::shared_ptr<SectionNode> m_deepestSection; 5892 std::vector<std::shared_ptr<SectionNode>> m_sectionStack; 5893 ReporterPreferences m_reporterPrefs; 5894 }; 5895 5896 template<char C> 5897 char const* getLineOfChars() { 5898 static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0}; 5899 if( !*line ) { 5900 std::memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 ); 5901 line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0; 5902 } 5903 return line; 5904 } 5905 5906 struct TestEventListenerBase : StreamingReporterBase<TestEventListenerBase> { 5907 TestEventListenerBase( ReporterConfig const& _config ); 5908 5909 static std::set<Verbosity> getSupportedVerbosities(); 5910 5911 void assertionStarting(AssertionInfo const&) override; 5912 bool assertionEnded(AssertionStats const&) override; 5913 }; 5914 5915 } // end namespace Catch 5916 5917 // end catch_reporter_bases.hpp 5918 // start catch_console_colour.h 5919 5920 namespace Catch { 5921 5922 struct Colour { 5923 enum Code { 5924 None = 0, 5925 5926 White, 5927 Red, 5928 Green, 5929 Blue, 5930 Cyan, 5931 Yellow, 5932 Grey, 5933 5934 Bright = 0x10, 5935 5936 BrightRed = Bright | Red, 5937 BrightGreen = Bright | Green, 5938 LightGrey = Bright | Grey, 5939 BrightWhite = Bright | White, 5940 BrightYellow = Bright | Yellow, 5941 5942 // By intention 5943 FileName = LightGrey, 5944 Warning = BrightYellow, 5945 ResultError = BrightRed, 5946 ResultSuccess = BrightGreen, 5947 ResultExpectedFailure = Warning, 5948 5949 Error = BrightRed, 5950 Success = Green, 5951 5952 OriginalExpression = Cyan, 5953 ReconstructedExpression = BrightYellow, 5954 5955 SecondaryText = LightGrey, 5956 Headers = White 5957 }; 5958 5959 // Use constructed object for RAII guard 5960 Colour( Code _colourCode ); 5961 Colour( Colour&& other ) noexcept; 5962 Colour& operator=( Colour&& other ) noexcept; 5963 ~Colour(); 5964 5965 // Use static method for one-shot changes 5966 static void use( Code _colourCode ); 5967 5968 private: 5969 bool m_moved = false; 5970 }; 5971 5972 std::ostream& operator << ( std::ostream& os, Colour const& ); 5973 5974 } // end namespace Catch 5975 5976 // end catch_console_colour.h 5977 // start catch_reporter_registrars.hpp 5978 5979 5980 namespace Catch { 5981 5982 template<typename T> 5983 class ReporterRegistrar { 5984 5985 class ReporterFactory : public IReporterFactory { 5986 5987 IStreamingReporterPtr create( ReporterConfig const& config ) const override { 5988 return std::unique_ptr<T>( new T( config ) ); 5989 } 5990 5991 std::string getDescription() const override { 5992 return T::getDescription(); 5993 } 5994 }; 5995 5996 public: 5997 5998 explicit ReporterRegistrar( std::string const& name ) { 5999 getMutableRegistryHub().registerReporter( name, std::make_shared<ReporterFactory>() ); 6000 } 6001 }; 6002 6003 template<typename T> 6004 class ListenerRegistrar { 6005 6006 class ListenerFactory : public IReporterFactory { 6007 6008 IStreamingReporterPtr create( ReporterConfig const& config ) const override { 6009 return std::unique_ptr<T>( new T( config ) ); 6010 } 6011 std::string getDescription() const override { 6012 return std::string(); 6013 } 6014 }; 6015 6016 public: 6017 6018 ListenerRegistrar() { 6019 getMutableRegistryHub().registerListener( std::make_shared<ListenerFactory>() ); 6020 } 6021 }; 6022 } 6023 6024 #if !defined(CATCH_CONFIG_DISABLE) 6025 6026 #define CATCH_REGISTER_REPORTER( name, reporterType ) \ 6027 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 6028 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 6029 namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); } \ 6030 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 6031 6032 #define CATCH_REGISTER_LISTENER( listenerType ) \ 6033 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 6034 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 6035 namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; } \ 6036 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 6037 #else // CATCH_CONFIG_DISABLE 6038 6039 #define CATCH_REGISTER_REPORTER(name, reporterType) 6040 #define CATCH_REGISTER_LISTENER(listenerType) 6041 6042 #endif // CATCH_CONFIG_DISABLE 6043 6044 // end catch_reporter_registrars.hpp 6045 // Allow users to base their work off existing reporters 6046 // start catch_reporter_compact.h 6047 6048 namespace Catch { 6049 6050 struct CompactReporter : StreamingReporterBase<CompactReporter> { 6051 6052 using StreamingReporterBase::StreamingReporterBase; 6053 6054 ~CompactReporter() override; 6055 6056 static std::string getDescription(); 6057 6058 ReporterPreferences getPreferences() const override; 6059 6060 void noMatchingTestCases(std::string const& spec) override; 6061 6062 void assertionStarting(AssertionInfo const&) override; 6063 6064 bool assertionEnded(AssertionStats const& _assertionStats) override; 6065 6066 void sectionEnded(SectionStats const& _sectionStats) override; 6067 6068 void testRunEnded(TestRunStats const& _testRunStats) override; 6069 6070 }; 6071 6072 } // end namespace Catch 6073 6074 // end catch_reporter_compact.h 6075 // start catch_reporter_console.h 6076 6077 #if defined(_MSC_VER) 6078 #pragma warning(push) 6079 #pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch 6080 // Note that 4062 (not all labels are handled 6081 // and default is missing) is enabled 6082 #endif 6083 6084 namespace Catch { 6085 // Fwd decls 6086 struct SummaryColumn; 6087 class TablePrinter; 6088 6089 struct ConsoleReporter : StreamingReporterBase<ConsoleReporter> { 6090 std::unique_ptr<TablePrinter> m_tablePrinter; 6091 6092 ConsoleReporter(ReporterConfig const& config); 6093 ~ConsoleReporter() override; 6094 static std::string getDescription(); 6095 6096 void noMatchingTestCases(std::string const& spec) override; 6097 6098 void reportInvalidArguments(std::string const&arg) override; 6099 6100 void assertionStarting(AssertionInfo const&) override; 6101 6102 bool assertionEnded(AssertionStats const& _assertionStats) override; 6103 6104 void sectionStarting(SectionInfo const& _sectionInfo) override; 6105 void sectionEnded(SectionStats const& _sectionStats) override; 6106 6107 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 6108 void benchmarkPreparing(std::string const& name) override; 6109 void benchmarkStarting(BenchmarkInfo const& info) override; 6110 void benchmarkEnded(BenchmarkStats<> const& stats) override; 6111 void benchmarkFailed(std::string const& error) override; 6112 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 6113 6114 void testCaseEnded(TestCaseStats const& _testCaseStats) override; 6115 void testGroupEnded(TestGroupStats const& _testGroupStats) override; 6116 void testRunEnded(TestRunStats const& _testRunStats) override; 6117 void testRunStarting(TestRunInfo const& _testRunInfo) override; 6118 private: 6119 6120 void lazyPrint(); 6121 6122 void lazyPrintWithoutClosingBenchmarkTable(); 6123 void lazyPrintRunInfo(); 6124 void lazyPrintGroupInfo(); 6125 void printTestCaseAndSectionHeader(); 6126 6127 void printClosedHeader(std::string const& _name); 6128 void printOpenHeader(std::string const& _name); 6129 6130 // if string has a : in first line will set indent to follow it on 6131 // subsequent lines 6132 void printHeaderString(std::string const& _string, std::size_t indent = 0); 6133 6134 void printTotals(Totals const& totals); 6135 void printSummaryRow(std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row); 6136 6137 void printTotalsDivider(Totals const& totals); 6138 void printSummaryDivider(); 6139 void printTestFilters(); 6140 6141 private: 6142 bool m_headerPrinted = false; 6143 }; 6144 6145 } // end namespace Catch 6146 6147 #if defined(_MSC_VER) 6148 #pragma warning(pop) 6149 #endif 6150 6151 // end catch_reporter_console.h 6152 // start catch_reporter_junit.h 6153 6154 // start catch_xmlwriter.h 6155 6156 #include <vector> 6157 6158 namespace Catch { 6159 enum class XmlFormatting { 6160 None = 0x00, 6161 Indent = 0x01, 6162 Newline = 0x02, 6163 }; 6164 6165 XmlFormatting operator | (XmlFormatting lhs, XmlFormatting rhs); 6166 XmlFormatting operator & (XmlFormatting lhs, XmlFormatting rhs); 6167 6168 class XmlEncode { 6169 public: 6170 enum ForWhat { ForTextNodes, ForAttributes }; 6171 6172 XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes ); 6173 6174 void encodeTo( std::ostream& os ) const; 6175 6176 friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ); 6177 6178 private: 6179 std::string m_str; 6180 ForWhat m_forWhat; 6181 }; 6182 6183 class XmlWriter { 6184 public: 6185 6186 class ScopedElement { 6187 public: 6188 ScopedElement( XmlWriter* writer, XmlFormatting fmt ); 6189 6190 ScopedElement( ScopedElement&& other ) noexcept; 6191 ScopedElement& operator=( ScopedElement&& other ) noexcept; 6192 6193 ~ScopedElement(); 6194 6195 ScopedElement& writeText( std::string const& text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent ); 6196 6197 template<typename T> 6198 ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { 6199 m_writer->writeAttribute( name, attribute ); 6200 return *this; 6201 } 6202 6203 private: 6204 mutable XmlWriter* m_writer = nullptr; 6205 XmlFormatting m_fmt; 6206 }; 6207 6208 XmlWriter( std::ostream& os = Catch::cout() ); 6209 ~XmlWriter(); 6210 6211 XmlWriter( XmlWriter const& ) = delete; 6212 XmlWriter& operator=( XmlWriter const& ) = delete; 6213 6214 XmlWriter& startElement( std::string const& name, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); 6215 6216 ScopedElement scopedElement( std::string const& name, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); 6217 6218 XmlWriter& endElement(XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); 6219 6220 XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ); 6221 6222 XmlWriter& writeAttribute( std::string const& name, bool attribute ); 6223 6224 template<typename T> 6225 XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { 6226 ReusableStringStream rss; 6227 rss << attribute; 6228 return writeAttribute( name, rss.str() ); 6229 } 6230 6231 XmlWriter& writeText( std::string const& text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); 6232 6233 XmlWriter& writeComment(std::string const& text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); 6234 6235 void writeStylesheetRef( std::string const& url ); 6236 6237 XmlWriter& writeBlankLine(); 6238 6239 void ensureTagClosed(); 6240 6241 private: 6242 6243 void applyFormatting(XmlFormatting fmt); 6244 6245 void writeDeclaration(); 6246 6247 void newlineIfNecessary(); 6248 6249 bool m_tagIsOpen = false; 6250 bool m_needsNewline = false; 6251 std::vector<std::string> m_tags; 6252 std::string m_indent; 6253 std::ostream& m_os; 6254 }; 6255 6256 } 6257 6258 // end catch_xmlwriter.h 6259 namespace Catch { 6260 6261 class JunitReporter : public CumulativeReporterBase<JunitReporter> { 6262 public: 6263 JunitReporter(ReporterConfig const& _config); 6264 6265 ~JunitReporter() override; 6266 6267 static std::string getDescription(); 6268 6269 void noMatchingTestCases(std::string const& /*spec*/) override; 6270 6271 void testRunStarting(TestRunInfo const& runInfo) override; 6272 6273 void testGroupStarting(GroupInfo const& groupInfo) override; 6274 6275 void testCaseStarting(TestCaseInfo const& testCaseInfo) override; 6276 bool assertionEnded(AssertionStats const& assertionStats) override; 6277 6278 void testCaseEnded(TestCaseStats const& testCaseStats) override; 6279 6280 void testGroupEnded(TestGroupStats const& testGroupStats) override; 6281 6282 void testRunEndedCumulative() override; 6283 6284 void writeGroup(TestGroupNode const& groupNode, double suiteTime); 6285 6286 void writeTestCase(TestCaseNode const& testCaseNode); 6287 6288 void writeSection(std::string const& className, 6289 std::string const& rootName, 6290 SectionNode const& sectionNode); 6291 6292 void writeAssertions(SectionNode const& sectionNode); 6293 void writeAssertion(AssertionStats const& stats); 6294 6295 XmlWriter xml; 6296 Timer suiteTimer; 6297 std::string stdOutForSuite; 6298 std::string stdErrForSuite; 6299 unsigned int unexpectedExceptions = 0; 6300 bool m_okToFail = false; 6301 }; 6302 6303 } // end namespace Catch 6304 6305 // end catch_reporter_junit.h 6306 // start catch_reporter_xml.h 6307 6308 namespace Catch { 6309 class XmlReporter : public StreamingReporterBase<XmlReporter> { 6310 public: 6311 XmlReporter(ReporterConfig const& _config); 6312 6313 ~XmlReporter() override; 6314 6315 static std::string getDescription(); 6316 6317 virtual std::string getStylesheetRef() const; 6318 6319 void writeSourceInfo(SourceLineInfo const& sourceInfo); 6320 6321 public: // StreamingReporterBase 6322 6323 void noMatchingTestCases(std::string const& s) override; 6324 6325 void testRunStarting(TestRunInfo const& testInfo) override; 6326 6327 void testGroupStarting(GroupInfo const& groupInfo) override; 6328 6329 void testCaseStarting(TestCaseInfo const& testInfo) override; 6330 6331 void sectionStarting(SectionInfo const& sectionInfo) override; 6332 6333 void assertionStarting(AssertionInfo const&) override; 6334 6335 bool assertionEnded(AssertionStats const& assertionStats) override; 6336 6337 void sectionEnded(SectionStats const& sectionStats) override; 6338 6339 void testCaseEnded(TestCaseStats const& testCaseStats) override; 6340 6341 void testGroupEnded(TestGroupStats const& testGroupStats) override; 6342 6343 void testRunEnded(TestRunStats const& testRunStats) override; 6344 6345 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 6346 void benchmarkPreparing(std::string const& name) override; 6347 void benchmarkStarting(BenchmarkInfo const&) override; 6348 void benchmarkEnded(BenchmarkStats<> const&) override; 6349 void benchmarkFailed(std::string const&) override; 6350 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 6351 6352 private: 6353 Timer m_testCaseTimer; 6354 XmlWriter m_xml; 6355 int m_sectionDepth = 0; 6356 }; 6357 6358 } // end namespace Catch 6359 6360 // end catch_reporter_xml.h 6361 6362 // end catch_external_interfaces.h 6363 #endif 6364 6365 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 6366 // start catch_benchmarking_all.hpp 6367 6368 // A proxy header that includes all of the benchmarking headers to allow 6369 // concise include of the benchmarking features. You should prefer the 6370 // individual includes in standard use. 6371 6372 // start catch_benchmark.hpp 6373 6374 // Benchmark 6375 6376 // start catch_chronometer.hpp 6377 6378 // User-facing chronometer 6379 6380 6381 // start catch_clock.hpp 6382 6383 // Clocks 6384 6385 6386 #include <chrono> 6387 #include <ratio> 6388 6389 namespace Catch { 6390 namespace Benchmark { 6391 template <typename Clock> 6392 using ClockDuration = typename Clock::duration; 6393 template <typename Clock> 6394 using FloatDuration = std::chrono::duration<double, typename Clock::period>; 6395 6396 template <typename Clock> 6397 using TimePoint = typename Clock::time_point; 6398 6399 using default_clock = std::chrono::steady_clock; 6400 6401 template <typename Clock> 6402 struct now { 6403 TimePoint<Clock> operator()() const { 6404 return Clock::now(); 6405 } 6406 }; 6407 6408 using fp_seconds = std::chrono::duration<double, std::ratio<1>>; 6409 } // namespace Benchmark 6410 } // namespace Catch 6411 6412 // end catch_clock.hpp 6413 // start catch_optimizer.hpp 6414 6415 // Hinting the optimizer 6416 6417 6418 #if defined(_MSC_VER) 6419 # include <atomic> // atomic_thread_fence 6420 #endif 6421 6422 namespace Catch { 6423 namespace Benchmark { 6424 #if defined(__GNUC__) || defined(__clang__) 6425 template <typename T> 6426 inline void keep_memory(T* p) { 6427 asm volatile("" : : "g"(p) : "memory"); 6428 } 6429 inline void keep_memory() { 6430 asm volatile("" : : : "memory"); 6431 } 6432 6433 namespace Detail { 6434 inline void optimizer_barrier() { keep_memory(); } 6435 } // namespace Detail 6436 #elif defined(_MSC_VER) 6437 6438 #pragma optimize("", off) 6439 template <typename T> 6440 inline void keep_memory(T* p) { 6441 // thanks @milleniumbug 6442 *reinterpret_cast<char volatile*>(p) = *reinterpret_cast<char const volatile*>(p); 6443 } 6444 // TODO equivalent keep_memory() 6445 #pragma optimize("", on) 6446 6447 namespace Detail { 6448 inline void optimizer_barrier() { 6449 std::atomic_thread_fence(std::memory_order_seq_cst); 6450 } 6451 } // namespace Detail 6452 6453 #endif 6454 6455 template <typename T> 6456 inline void deoptimize_value(T&& x) { 6457 keep_memory(&x); 6458 } 6459 6460 template <typename Fn, typename... Args> 6461 inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> typename std::enable_if<!std::is_same<void, decltype(fn(args...))>::value>::type { 6462 deoptimize_value(std::forward<Fn>(fn) (std::forward<Args...>(args...))); 6463 } 6464 6465 template <typename Fn, typename... Args> 6466 inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> typename std::enable_if<std::is_same<void, decltype(fn(args...))>::value>::type { 6467 std::forward<Fn>(fn) (std::forward<Args...>(args...)); 6468 } 6469 } // namespace Benchmark 6470 } // namespace Catch 6471 6472 // end catch_optimizer.hpp 6473 // start catch_complete_invoke.hpp 6474 6475 // Invoke with a special case for void 6476 6477 6478 #include <type_traits> 6479 #include <utility> 6480 6481 namespace Catch { 6482 namespace Benchmark { 6483 namespace Detail { 6484 template <typename T> 6485 struct CompleteType { using type = T; }; 6486 template <> 6487 struct CompleteType<void> { struct type {}; }; 6488 6489 template <typename T> 6490 using CompleteType_t = typename CompleteType<T>::type; 6491 6492 template <typename Result> 6493 struct CompleteInvoker { 6494 template <typename Fun, typename... Args> 6495 static Result invoke(Fun&& fun, Args&&... args) { 6496 return std::forward<Fun>(fun)(std::forward<Args>(args)...); 6497 } 6498 }; 6499 template <> 6500 struct CompleteInvoker<void> { 6501 template <typename Fun, typename... Args> 6502 static CompleteType_t<void> invoke(Fun&& fun, Args&&... args) { 6503 std::forward<Fun>(fun)(std::forward<Args>(args)...); 6504 return {}; 6505 } 6506 }; 6507 template <typename Sig> 6508 using ResultOf_t = typename std::result_of<Sig>::type; 6509 6510 // invoke and not return void :( 6511 template <typename Fun, typename... Args> 6512 CompleteType_t<ResultOf_t<Fun(Args...)>> complete_invoke(Fun&& fun, Args&&... args) { 6513 return CompleteInvoker<ResultOf_t<Fun(Args...)>>::invoke(std::forward<Fun>(fun), std::forward<Args>(args)...); 6514 } 6515 6516 const std::string benchmarkErrorMsg = "a benchmark failed to run successfully"; 6517 } // namespace Detail 6518 6519 template <typename Fun> 6520 Detail::CompleteType_t<Detail::ResultOf_t<Fun()>> user_code(Fun&& fun) { 6521 CATCH_TRY{ 6522 return Detail::complete_invoke(std::forward<Fun>(fun)); 6523 } CATCH_CATCH_ALL{ 6524 getResultCapture().benchmarkFailed(translateActiveException()); 6525 CATCH_RUNTIME_ERROR(Detail::benchmarkErrorMsg); 6526 } 6527 } 6528 } // namespace Benchmark 6529 } // namespace Catch 6530 6531 // end catch_complete_invoke.hpp 6532 namespace Catch { 6533 namespace Benchmark { 6534 namespace Detail { 6535 struct ChronometerConcept { 6536 virtual void start() = 0; 6537 virtual void finish() = 0; 6538 virtual ~ChronometerConcept() = default; 6539 }; 6540 template <typename Clock> 6541 struct ChronometerModel final : public ChronometerConcept { 6542 void start() override { started = Clock::now(); } 6543 void finish() override { finished = Clock::now(); } 6544 6545 ClockDuration<Clock> elapsed() const { return finished - started; } 6546 6547 TimePoint<Clock> started; 6548 TimePoint<Clock> finished; 6549 }; 6550 } // namespace Detail 6551 6552 struct Chronometer { 6553 public: 6554 template <typename Fun> 6555 void measure(Fun&& fun) { measure(std::forward<Fun>(fun), is_callable<Fun(int)>()); } 6556 6557 int runs() const { return k; } 6558 6559 Chronometer(Detail::ChronometerConcept& meter, int k) 6560 : impl(&meter) 6561 , k(k) {} 6562 6563 private: 6564 template <typename Fun> 6565 void measure(Fun&& fun, std::false_type) { 6566 measure([&fun](int) { return fun(); }, std::true_type()); 6567 } 6568 6569 template <typename Fun> 6570 void measure(Fun&& fun, std::true_type) { 6571 Detail::optimizer_barrier(); 6572 impl->start(); 6573 for (int i = 0; i < k; ++i) invoke_deoptimized(fun, i); 6574 impl->finish(); 6575 Detail::optimizer_barrier(); 6576 } 6577 6578 Detail::ChronometerConcept* impl; 6579 int k; 6580 }; 6581 } // namespace Benchmark 6582 } // namespace Catch 6583 6584 // end catch_chronometer.hpp 6585 // start catch_environment.hpp 6586 6587 // Environment information 6588 6589 6590 namespace Catch { 6591 namespace Benchmark { 6592 template <typename Duration> 6593 struct EnvironmentEstimate { 6594 Duration mean; 6595 OutlierClassification outliers; 6596 6597 template <typename Duration2> 6598 operator EnvironmentEstimate<Duration2>() const { 6599 return { mean, outliers }; 6600 } 6601 }; 6602 template <typename Clock> 6603 struct Environment { 6604 using clock_type = Clock; 6605 EnvironmentEstimate<FloatDuration<Clock>> clock_resolution; 6606 EnvironmentEstimate<FloatDuration<Clock>> clock_cost; 6607 }; 6608 } // namespace Benchmark 6609 } // namespace Catch 6610 6611 // end catch_environment.hpp 6612 // start catch_execution_plan.hpp 6613 6614 // Execution plan 6615 6616 6617 // start catch_benchmark_function.hpp 6618 6619 // Dumb std::function implementation for consistent call overhead 6620 6621 6622 #include <cassert> 6623 #include <type_traits> 6624 #include <utility> 6625 #include <memory> 6626 6627 namespace Catch { 6628 namespace Benchmark { 6629 namespace Detail { 6630 template <typename T> 6631 using Decay = typename std::decay<T>::type; 6632 template <typename T, typename U> 6633 struct is_related 6634 : std::is_same<Decay<T>, Decay<U>> {}; 6635 6636 /// We need to reinvent std::function because every piece of code that might add overhead 6637 /// in a measurement context needs to have consistent performance characteristics so that we 6638 /// can account for it in the measurement. 6639 /// Implementations of std::function with optimizations that aren't always applicable, like 6640 /// small buffer optimizations, are not uncommon. 6641 /// This is effectively an implementation of std::function without any such optimizations; 6642 /// it may be slow, but it is consistently slow. 6643 struct BenchmarkFunction { 6644 private: 6645 struct callable { 6646 virtual void call(Chronometer meter) const = 0; 6647 virtual callable* clone() const = 0; 6648 virtual ~callable() = default; 6649 }; 6650 template <typename Fun> 6651 struct model : public callable { 6652 model(Fun&& fun) : fun(std::move(fun)) {} 6653 model(Fun const& fun) : fun(fun) {} 6654 6655 model<Fun>* clone() const override { return new model<Fun>(*this); } 6656 6657 void call(Chronometer meter) const override { 6658 call(meter, is_callable<Fun(Chronometer)>()); 6659 } 6660 void call(Chronometer meter, std::true_type) const { 6661 fun(meter); 6662 } 6663 void call(Chronometer meter, std::false_type) const { 6664 meter.measure(fun); 6665 } 6666 6667 Fun fun; 6668 }; 6669 6670 struct do_nothing { void operator()() const {} }; 6671 6672 template <typename T> 6673 BenchmarkFunction(model<T>* c) : f(c) {} 6674 6675 public: 6676 BenchmarkFunction() 6677 : f(new model<do_nothing>{ {} }) {} 6678 6679 template <typename Fun, 6680 typename std::enable_if<!is_related<Fun, BenchmarkFunction>::value, int>::type = 0> 6681 BenchmarkFunction(Fun&& fun) 6682 : f(new model<typename std::decay<Fun>::type>(std::forward<Fun>(fun))) {} 6683 6684 BenchmarkFunction(BenchmarkFunction&& that) 6685 : f(std::move(that.f)) {} 6686 6687 BenchmarkFunction(BenchmarkFunction const& that) 6688 : f(that.f->clone()) {} 6689 6690 BenchmarkFunction& operator=(BenchmarkFunction&& that) { 6691 f = std::move(that.f); 6692 return *this; 6693 } 6694 6695 BenchmarkFunction& operator=(BenchmarkFunction const& that) { 6696 f.reset(that.f->clone()); 6697 return *this; 6698 } 6699 6700 void operator()(Chronometer meter) const { f->call(meter); } 6701 6702 private: 6703 std::unique_ptr<callable> f; 6704 }; 6705 } // namespace Detail 6706 } // namespace Benchmark 6707 } // namespace Catch 6708 6709 // end catch_benchmark_function.hpp 6710 // start catch_repeat.hpp 6711 6712 // repeat algorithm 6713 6714 6715 #include <type_traits> 6716 #include <utility> 6717 6718 namespace Catch { 6719 namespace Benchmark { 6720 namespace Detail { 6721 template <typename Fun> 6722 struct repeater { 6723 void operator()(int k) const { 6724 for (int i = 0; i < k; ++i) { 6725 fun(); 6726 } 6727 } 6728 Fun fun; 6729 }; 6730 template <typename Fun> 6731 repeater<typename std::decay<Fun>::type> repeat(Fun&& fun) { 6732 return { std::forward<Fun>(fun) }; 6733 } 6734 } // namespace Detail 6735 } // namespace Benchmark 6736 } // namespace Catch 6737 6738 // end catch_repeat.hpp 6739 // start catch_run_for_at_least.hpp 6740 6741 // Run a function for a minimum amount of time 6742 6743 6744 // start catch_measure.hpp 6745 6746 // Measure 6747 6748 6749 // start catch_timing.hpp 6750 6751 // Timing 6752 6753 6754 #include <tuple> 6755 #include <type_traits> 6756 6757 namespace Catch { 6758 namespace Benchmark { 6759 template <typename Duration, typename Result> 6760 struct Timing { 6761 Duration elapsed; 6762 Result result; 6763 int iterations; 6764 }; 6765 template <typename Clock, typename Sig> 6766 using TimingOf = Timing<ClockDuration<Clock>, Detail::CompleteType_t<Detail::ResultOf_t<Sig>>>; 6767 } // namespace Benchmark 6768 } // namespace Catch 6769 6770 // end catch_timing.hpp 6771 #include <utility> 6772 6773 namespace Catch { 6774 namespace Benchmark { 6775 namespace Detail { 6776 template <typename Clock, typename Fun, typename... Args> 6777 TimingOf<Clock, Fun(Args...)> measure(Fun&& fun, Args&&... args) { 6778 auto start = Clock::now(); 6779 auto&& r = Detail::complete_invoke(fun, std::forward<Args>(args)...); 6780 auto end = Clock::now(); 6781 auto delta = end - start; 6782 return { delta, std::forward<decltype(r)>(r), 1 }; 6783 } 6784 } // namespace Detail 6785 } // namespace Benchmark 6786 } // namespace Catch 6787 6788 // end catch_measure.hpp 6789 #include <utility> 6790 #include <type_traits> 6791 6792 namespace Catch { 6793 namespace Benchmark { 6794 namespace Detail { 6795 template <typename Clock, typename Fun> 6796 TimingOf<Clock, Fun(int)> measure_one(Fun&& fun, int iters, std::false_type) { 6797 return Detail::measure<Clock>(fun, iters); 6798 } 6799 template <typename Clock, typename Fun> 6800 TimingOf<Clock, Fun(Chronometer)> measure_one(Fun&& fun, int iters, std::true_type) { 6801 Detail::ChronometerModel<Clock> meter; 6802 auto&& result = Detail::complete_invoke(fun, Chronometer(meter, iters)); 6803 6804 return { meter.elapsed(), std::move(result), iters }; 6805 } 6806 6807 template <typename Clock, typename Fun> 6808 using run_for_at_least_argument_t = typename std::conditional<is_callable<Fun(Chronometer)>::value, Chronometer, int>::type; 6809 6810 struct optimized_away_error : std::exception { 6811 const char* what() const noexcept override { 6812 return "could not measure benchmark, maybe it was optimized away"; 6813 } 6814 }; 6815 6816 template <typename Clock, typename Fun> 6817 TimingOf<Clock, Fun(run_for_at_least_argument_t<Clock, Fun>)> run_for_at_least(ClockDuration<Clock> how_long, int seed, Fun&& fun) { 6818 auto iters = seed; 6819 while (iters < (1 << 30)) { 6820 auto&& Timing = measure_one<Clock>(fun, iters, is_callable<Fun(Chronometer)>()); 6821 6822 if (Timing.elapsed >= how_long) { 6823 return { Timing.elapsed, std::move(Timing.result), iters }; 6824 } 6825 iters *= 2; 6826 } 6827 throw optimized_away_error{}; 6828 } 6829 } // namespace Detail 6830 } // namespace Benchmark 6831 } // namespace Catch 6832 6833 // end catch_run_for_at_least.hpp 6834 #include <algorithm> 6835 6836 namespace Catch { 6837 namespace Benchmark { 6838 template <typename Duration> 6839 struct ExecutionPlan { 6840 int iterations_per_sample; 6841 Duration estimated_duration; 6842 Detail::BenchmarkFunction benchmark; 6843 Duration warmup_time; 6844 int warmup_iterations; 6845 6846 template <typename Duration2> 6847 operator ExecutionPlan<Duration2>() const { 6848 return { iterations_per_sample, estimated_duration, benchmark, warmup_time, warmup_iterations }; 6849 } 6850 6851 template <typename Clock> 6852 std::vector<FloatDuration<Clock>> run(const IConfig &cfg, Environment<FloatDuration<Clock>> env) const { 6853 // warmup a bit 6854 Detail::run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(warmup_time), warmup_iterations, Detail::repeat(now<Clock>{})); 6855 6856 std::vector<FloatDuration<Clock>> times; 6857 times.reserve(cfg.benchmarkSamples()); 6858 std::generate_n(std::back_inserter(times), cfg.benchmarkSamples(), [this, env] { 6859 Detail::ChronometerModel<Clock> model; 6860 this->benchmark(Chronometer(model, iterations_per_sample)); 6861 auto sample_time = model.elapsed() - env.clock_cost.mean; 6862 if (sample_time < FloatDuration<Clock>::zero()) sample_time = FloatDuration<Clock>::zero(); 6863 return sample_time / iterations_per_sample; 6864 }); 6865 return times; 6866 } 6867 }; 6868 } // namespace Benchmark 6869 } // namespace Catch 6870 6871 // end catch_execution_plan.hpp 6872 // start catch_estimate_clock.hpp 6873 6874 // Environment measurement 6875 6876 6877 // start catch_stats.hpp 6878 6879 // Statistical analysis tools 6880 6881 6882 #include <algorithm> 6883 #include <functional> 6884 #include <vector> 6885 #include <numeric> 6886 #include <tuple> 6887 #include <cmath> 6888 #include <utility> 6889 #include <cstddef> 6890 6891 namespace Catch { 6892 namespace Benchmark { 6893 namespace Detail { 6894 using sample = std::vector<double>; 6895 6896 double weighted_average_quantile(int k, int q, std::vector<double>::iterator first, std::vector<double>::iterator last); 6897 6898 template <typename Iterator> 6899 OutlierClassification classify_outliers(Iterator first, Iterator last) { 6900 std::vector<double> copy(first, last); 6901 6902 auto q1 = weighted_average_quantile(1, 4, copy.begin(), copy.end()); 6903 auto q3 = weighted_average_quantile(3, 4, copy.begin(), copy.end()); 6904 auto iqr = q3 - q1; 6905 auto los = q1 - (iqr * 3.); 6906 auto lom = q1 - (iqr * 1.5); 6907 auto him = q3 + (iqr * 1.5); 6908 auto his = q3 + (iqr * 3.); 6909 6910 OutlierClassification o; 6911 for (; first != last; ++first) { 6912 auto&& t = *first; 6913 if (t < los) ++o.low_severe; 6914 else if (t < lom) ++o.low_mild; 6915 else if (t > his) ++o.high_severe; 6916 else if (t > him) ++o.high_mild; 6917 ++o.samples_seen; 6918 } 6919 return o; 6920 } 6921 6922 template <typename Iterator> 6923 double mean(Iterator first, Iterator last) { 6924 auto count = last - first; 6925 double sum = std::accumulate(first, last, 0.); 6926 return sum / count; 6927 } 6928 6929 template <typename URng, typename Iterator, typename Estimator> 6930 sample resample(URng& rng, int resamples, Iterator first, Iterator last, Estimator& estimator) { 6931 auto n = last - first; 6932 std::uniform_int_distribution<decltype(n)> dist(0, n - 1); 6933 6934 sample out; 6935 out.reserve(resamples); 6936 std::generate_n(std::back_inserter(out), resamples, [n, first, &estimator, &dist, &rng] { 6937 std::vector<double> resampled; 6938 resampled.reserve(n); 6939 std::generate_n(std::back_inserter(resampled), n, [first, &dist, &rng] { return first[dist(rng)]; }); 6940 return estimator(resampled.begin(), resampled.end()); 6941 }); 6942 std::sort(out.begin(), out.end()); 6943 return out; 6944 } 6945 6946 template <typename Estimator, typename Iterator> 6947 sample jackknife(Estimator&& estimator, Iterator first, Iterator last) { 6948 auto n = last - first; 6949 auto second = std::next(first); 6950 sample results; 6951 results.reserve(n); 6952 6953 for (auto it = first; it != last; ++it) { 6954 std::iter_swap(it, first); 6955 results.push_back(estimator(second, last)); 6956 } 6957 6958 return results; 6959 } 6960 6961 inline double normal_cdf(double x) { 6962 return std::erfc(-x / std::sqrt(2.0)) / 2.0; 6963 } 6964 6965 double erfc_inv(double x); 6966 6967 double normal_quantile(double p); 6968 6969 template <typename Iterator, typename Estimator> 6970 Estimate<double> bootstrap(double confidence_level, Iterator first, Iterator last, sample const& resample, Estimator&& estimator) { 6971 auto n_samples = last - first; 6972 6973 double point = estimator(first, last); 6974 // Degenerate case with a single sample 6975 if (n_samples == 1) return { point, point, point, confidence_level }; 6976 6977 sample jack = jackknife(estimator, first, last); 6978 double jack_mean = mean(jack.begin(), jack.end()); 6979 double sum_squares, sum_cubes; 6980 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> { 6981 auto d = jack_mean - x; 6982 auto d2 = d * d; 6983 auto d3 = d2 * d; 6984 return { sqcb.first + d2, sqcb.second + d3 }; 6985 }); 6986 6987 double accel = sum_cubes / (6 * std::pow(sum_squares, 1.5)); 6988 int n = static_cast<int>(resample.size()); 6989 double prob_n = std::count_if(resample.begin(), resample.end(), [point](double x) { return x < point; }) / (double)n; 6990 // degenerate case with uniform samples 6991 if (prob_n == 0) return { point, point, point, confidence_level }; 6992 6993 double bias = normal_quantile(prob_n); 6994 double z1 = normal_quantile((1. - confidence_level) / 2.); 6995 6996 auto cumn = [n](double x) -> int { 6997 return std::lround(normal_cdf(x) * n); }; 6998 auto a = [bias, accel](double b) { return bias + b / (1. - accel * b); }; 6999 double b1 = bias + z1; 7000 double b2 = bias - z1; 7001 double a1 = a(b1); 7002 double a2 = a(b2); 7003 auto lo = std::max(cumn(a1), 0); 7004 auto hi = std::min(cumn(a2), n - 1); 7005 7006 return { point, resample[lo], resample[hi], confidence_level }; 7007 } 7008 7009 double outlier_variance(Estimate<double> mean, Estimate<double> stddev, int n); 7010 7011 struct bootstrap_analysis { 7012 Estimate<double> mean; 7013 Estimate<double> standard_deviation; 7014 double outlier_variance; 7015 }; 7016 7017 bootstrap_analysis analyse_samples(double confidence_level, int n_resamples, std::vector<double>::iterator first, std::vector<double>::iterator last); 7018 } // namespace Detail 7019 } // namespace Benchmark 7020 } // namespace Catch 7021 7022 // end catch_stats.hpp 7023 #include <algorithm> 7024 #include <iterator> 7025 #include <tuple> 7026 #include <vector> 7027 #include <cmath> 7028 7029 namespace Catch { 7030 namespace Benchmark { 7031 namespace Detail { 7032 template <typename Clock> 7033 std::vector<double> resolution(int k) { 7034 std::vector<TimePoint<Clock>> times; 7035 times.reserve(k + 1); 7036 std::generate_n(std::back_inserter(times), k + 1, now<Clock>{}); 7037 7038 std::vector<double> deltas; 7039 deltas.reserve(k); 7040 std::transform(std::next(times.begin()), times.end(), times.begin(), 7041 std::back_inserter(deltas), 7042 [](TimePoint<Clock> a, TimePoint<Clock> b) { return static_cast<double>((a - b).count()); }); 7043 7044 return deltas; 7045 } 7046 7047 const auto warmup_iterations = 10000; 7048 const auto warmup_time = std::chrono::milliseconds(100); 7049 const auto minimum_ticks = 1000; 7050 const auto warmup_seed = 10000; 7051 const auto clock_resolution_estimation_time = std::chrono::milliseconds(500); 7052 const auto clock_cost_estimation_time_limit = std::chrono::seconds(1); 7053 const auto clock_cost_estimation_tick_limit = 100000; 7054 const auto clock_cost_estimation_time = std::chrono::milliseconds(10); 7055 const auto clock_cost_estimation_iterations = 10000; 7056 7057 template <typename Clock> 7058 int warmup() { 7059 return run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(warmup_time), warmup_seed, &resolution<Clock>) 7060 .iterations; 7061 } 7062 template <typename Clock> 7063 EnvironmentEstimate<FloatDuration<Clock>> estimate_clock_resolution(int iterations) { 7064 auto r = run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(clock_resolution_estimation_time), iterations, &resolution<Clock>) 7065 .result; 7066 return { 7067 FloatDuration<Clock>(mean(r.begin(), r.end())), 7068 classify_outliers(r.begin(), r.end()), 7069 }; 7070 } 7071 template <typename Clock> 7072 EnvironmentEstimate<FloatDuration<Clock>> estimate_clock_cost(FloatDuration<Clock> resolution) { 7073 auto time_limit = std::min(resolution * clock_cost_estimation_tick_limit, FloatDuration<Clock>(clock_cost_estimation_time_limit)); 7074 auto time_clock = [](int k) { 7075 return Detail::measure<Clock>([k] { 7076 for (int i = 0; i < k; ++i) { 7077 volatile auto ignored = Clock::now(); 7078 (void)ignored; 7079 } 7080 }).elapsed; 7081 }; 7082 time_clock(1); 7083 int iters = clock_cost_estimation_iterations; 7084 auto&& r = run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(clock_cost_estimation_time), iters, time_clock); 7085 std::vector<double> times; 7086 int nsamples = static_cast<int>(std::ceil(time_limit / r.elapsed)); 7087 times.reserve(nsamples); 7088 std::generate_n(std::back_inserter(times), nsamples, [time_clock, &r] { 7089 return static_cast<double>((time_clock(r.iterations) / r.iterations).count()); 7090 }); 7091 return { 7092 FloatDuration<Clock>(mean(times.begin(), times.end())), 7093 classify_outliers(times.begin(), times.end()), 7094 }; 7095 } 7096 7097 template <typename Clock> 7098 Environment<FloatDuration<Clock>> measure_environment() { 7099 static Environment<FloatDuration<Clock>>* env = nullptr; 7100 if (env) { 7101 return *env; 7102 } 7103 7104 auto iters = Detail::warmup<Clock>(); 7105 auto resolution = Detail::estimate_clock_resolution<Clock>(iters); 7106 auto cost = Detail::estimate_clock_cost<Clock>(resolution.mean); 7107 7108 env = new Environment<FloatDuration<Clock>>{ resolution, cost }; 7109 return *env; 7110 } 7111 } // namespace Detail 7112 } // namespace Benchmark 7113 } // namespace Catch 7114 7115 // end catch_estimate_clock.hpp 7116 // start catch_analyse.hpp 7117 7118 // Run and analyse one benchmark 7119 7120 7121 // start catch_sample_analysis.hpp 7122 7123 // Benchmark results 7124 7125 7126 #include <algorithm> 7127 #include <vector> 7128 #include <string> 7129 #include <iterator> 7130 7131 namespace Catch { 7132 namespace Benchmark { 7133 template <typename Duration> 7134 struct SampleAnalysis { 7135 std::vector<Duration> samples; 7136 Estimate<Duration> mean; 7137 Estimate<Duration> standard_deviation; 7138 OutlierClassification outliers; 7139 double outlier_variance; 7140 7141 template <typename Duration2> 7142 operator SampleAnalysis<Duration2>() const { 7143 std::vector<Duration2> samples2; 7144 samples2.reserve(samples.size()); 7145 std::transform(samples.begin(), samples.end(), std::back_inserter(samples2), [](Duration d) { return Duration2(d); }); 7146 return { 7147 std::move(samples2), 7148 mean, 7149 standard_deviation, 7150 outliers, 7151 outlier_variance, 7152 }; 7153 } 7154 }; 7155 } // namespace Benchmark 7156 } // namespace Catch 7157 7158 // end catch_sample_analysis.hpp 7159 #include <algorithm> 7160 #include <iterator> 7161 #include <vector> 7162 7163 namespace Catch { 7164 namespace Benchmark { 7165 namespace Detail { 7166 template <typename Duration, typename Iterator> 7167 SampleAnalysis<Duration> analyse(const IConfig &cfg, Environment<Duration>, Iterator first, Iterator last) { 7168 if (!cfg.benchmarkNoAnalysis()) { 7169 std::vector<double> samples; 7170 samples.reserve(last - first); 7171 std::transform(first, last, std::back_inserter(samples), [](Duration d) { return d.count(); }); 7172 7173 auto analysis = Catch::Benchmark::Detail::analyse_samples(cfg.benchmarkConfidenceInterval(), cfg.benchmarkResamples(), samples.begin(), samples.end()); 7174 auto outliers = Catch::Benchmark::Detail::classify_outliers(samples.begin(), samples.end()); 7175 7176 auto wrap_estimate = [](Estimate<double> e) { 7177 return Estimate<Duration> { 7178 Duration(e.point), 7179 Duration(e.lower_bound), 7180 Duration(e.upper_bound), 7181 e.confidence_interval, 7182 }; 7183 }; 7184 std::vector<Duration> samples2; 7185 samples2.reserve(samples.size()); 7186 std::transform(samples.begin(), samples.end(), std::back_inserter(samples2), [](double d) { return Duration(d); }); 7187 return { 7188 std::move(samples2), 7189 wrap_estimate(analysis.mean), 7190 wrap_estimate(analysis.standard_deviation), 7191 outliers, 7192 analysis.outlier_variance, 7193 }; 7194 } else { 7195 std::vector<Duration> samples; 7196 samples.reserve(last - first); 7197 7198 Duration mean = Duration(0); 7199 int i = 0; 7200 for (auto it = first; it < last; ++it, ++i) { 7201 samples.push_back(Duration(*it)); 7202 mean += Duration(*it); 7203 } 7204 mean /= i; 7205 7206 return { 7207 std::move(samples), 7208 Estimate<Duration>{mean, mean, mean, 0.0}, 7209 Estimate<Duration>{Duration(0), Duration(0), Duration(0), 0.0}, 7210 OutlierClassification{}, 7211 0.0 7212 }; 7213 } 7214 } 7215 } // namespace Detail 7216 } // namespace Benchmark 7217 } // namespace Catch 7218 7219 // end catch_analyse.hpp 7220 #include <algorithm> 7221 #include <functional> 7222 #include <string> 7223 #include <vector> 7224 #include <cmath> 7225 7226 namespace Catch { 7227 namespace Benchmark { 7228 struct Benchmark { 7229 Benchmark(std::string &&name) 7230 : name(std::move(name)) {} 7231 7232 template <class FUN> 7233 Benchmark(std::string &&name, FUN &&func) 7234 : fun(std::move(func)), name(std::move(name)) {} 7235 7236 template <typename Clock> 7237 ExecutionPlan<FloatDuration<Clock>> prepare(const IConfig &cfg, Environment<FloatDuration<Clock>> env) const { 7238 auto min_time = env.clock_resolution.mean * Detail::minimum_ticks; 7239 auto run_time = std::max(min_time, std::chrono::duration_cast<decltype(min_time)>(Detail::warmup_time)); 7240 auto&& test = Detail::run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(run_time), 1, fun); 7241 int new_iters = static_cast<int>(std::ceil(min_time * test.iterations / test.elapsed)); 7242 return { new_iters, test.elapsed / test.iterations * new_iters * cfg.benchmarkSamples(), fun, std::chrono::duration_cast<FloatDuration<Clock>>(Detail::warmup_time), Detail::warmup_iterations }; 7243 } 7244 7245 template <typename Clock = default_clock> 7246 void run() { 7247 IConfigPtr cfg = getCurrentContext().getConfig(); 7248 7249 auto env = Detail::measure_environment<Clock>(); 7250 7251 getResultCapture().benchmarkPreparing(name); 7252 CATCH_TRY{ 7253 auto plan = user_code([&] { 7254 return prepare<Clock>(*cfg, env); 7255 }); 7256 7257 BenchmarkInfo info { 7258 name, 7259 plan.estimated_duration.count(), 7260 plan.iterations_per_sample, 7261 cfg->benchmarkSamples(), 7262 cfg->benchmarkResamples(), 7263 env.clock_resolution.mean.count(), 7264 env.clock_cost.mean.count() 7265 }; 7266 7267 getResultCapture().benchmarkStarting(info); 7268 7269 auto samples = user_code([&] { 7270 return plan.template run<Clock>(*cfg, env); 7271 }); 7272 7273 auto analysis = Detail::analyse(*cfg, env, samples.begin(), samples.end()); 7274 BenchmarkStats<FloatDuration<Clock>> stats{ info, analysis.samples, analysis.mean, analysis.standard_deviation, analysis.outliers, analysis.outlier_variance }; 7275 getResultCapture().benchmarkEnded(stats); 7276 7277 } CATCH_CATCH_ALL{ 7278 if (translateActiveException() != Detail::benchmarkErrorMsg) // benchmark errors have been reported, otherwise rethrow. 7279 std::rethrow_exception(std::current_exception()); 7280 } 7281 } 7282 7283 // sets lambda to be used in fun *and* executes benchmark! 7284 template <typename Fun, 7285 typename std::enable_if<!Detail::is_related<Fun, Benchmark>::value, int>::type = 0> 7286 Benchmark & operator=(Fun func) { 7287 fun = Detail::BenchmarkFunction(func); 7288 run(); 7289 return *this; 7290 } 7291 7292 explicit operator bool() { 7293 return true; 7294 } 7295 7296 private: 7297 Detail::BenchmarkFunction fun; 7298 std::string name; 7299 }; 7300 } 7301 } // namespace Catch 7302 7303 #define INTERNAL_CATCH_GET_1_ARG(arg1, arg2, ...) arg1 7304 #define INTERNAL_CATCH_GET_2_ARG(arg1, arg2, ...) arg2 7305 7306 #define INTERNAL_CATCH_BENCHMARK(BenchmarkName, name, benchmarkIndex)\ 7307 if( Catch::Benchmark::Benchmark BenchmarkName{name} ) \ 7308 BenchmarkName = [&](int benchmarkIndex) 7309 7310 #define INTERNAL_CATCH_BENCHMARK_ADVANCED(BenchmarkName, name)\ 7311 if( Catch::Benchmark::Benchmark BenchmarkName{name} ) \ 7312 BenchmarkName = [&] 7313 7314 // end catch_benchmark.hpp 7315 // start catch_constructor.hpp 7316 7317 // Constructor and destructor helpers 7318 7319 7320 #include <type_traits> 7321 7322 namespace Catch { 7323 namespace Detail { 7324 template <typename T, bool Destruct> 7325 struct ObjectStorage 7326 { 7327 using TStorage = typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type; 7328 7329 ObjectStorage() : data() {} 7330 7331 ObjectStorage(const ObjectStorage& other) 7332 { 7333 new(&data) T(other.stored_object()); 7334 } 7335 7336 ObjectStorage(ObjectStorage&& other) 7337 { 7338 new(&data) T(std::move(other.stored_object())); 7339 } 7340 7341 ~ObjectStorage() { destruct_on_exit<T>(); } 7342 7343 template <typename... Args> 7344 void construct(Args&&... args) 7345 { 7346 new (&data) T(std::forward<Args>(args)...); 7347 } 7348 7349 template <bool AllowManualDestruction = !Destruct> 7350 typename std::enable_if<AllowManualDestruction>::type destruct() 7351 { 7352 stored_object().~T(); 7353 } 7354 7355 private: 7356 // If this is a constructor benchmark, destruct the underlying object 7357 template <typename U> 7358 void destruct_on_exit(typename std::enable_if<Destruct, U>::type* = 0) { destruct<true>(); } 7359 // Otherwise, don't 7360 template <typename U> 7361 void destruct_on_exit(typename std::enable_if<!Destruct, U>::type* = 0) { } 7362 7363 T& stored_object() 7364 { 7365 return *static_cast<T*>(static_cast<void*>(&data)); 7366 } 7367 7368 TStorage data; 7369 }; 7370 } 7371 7372 template <typename T> 7373 using storage_for = Detail::ObjectStorage<T, true>; 7374 7375 template <typename T> 7376 using destructable_object = Detail::ObjectStorage<T, false>; 7377 } 7378 7379 // end catch_constructor.hpp 7380 // end catch_benchmarking_all.hpp 7381 #endif 7382 7383 #endif // ! CATCH_CONFIG_IMPL_ONLY 7384 7385 #ifdef CATCH_IMPL 7386 // start catch_impl.hpp 7387 7388 #ifdef __clang__ 7389 #pragma clang diagnostic push 7390 #pragma clang diagnostic ignored "-Wweak-vtables" 7391 #endif 7392 7393 // Keep these here for external reporters 7394 // start catch_test_case_tracker.h 7395 7396 #include <string> 7397 #include <vector> 7398 #include <memory> 7399 7400 namespace Catch { 7401 namespace TestCaseTracking { 7402 7403 struct NameAndLocation { 7404 std::string name; 7405 SourceLineInfo location; 7406 7407 NameAndLocation( std::string const& _name, SourceLineInfo const& _location ); 7408 }; 7409 7410 struct ITracker; 7411 7412 using ITrackerPtr = std::shared_ptr<ITracker>; 7413 7414 struct ITracker { 7415 virtual ~ITracker(); 7416 7417 // static queries 7418 virtual NameAndLocation const& nameAndLocation() const = 0; 7419 7420 // dynamic queries 7421 virtual bool isComplete() const = 0; // Successfully completed or failed 7422 virtual bool isSuccessfullyCompleted() const = 0; 7423 virtual bool isOpen() const = 0; // Started but not complete 7424 virtual bool hasChildren() const = 0; 7425 7426 virtual ITracker& parent() = 0; 7427 7428 // actions 7429 virtual void close() = 0; // Successfully complete 7430 virtual void fail() = 0; 7431 virtual void markAsNeedingAnotherRun() = 0; 7432 7433 virtual void addChild( ITrackerPtr const& child ) = 0; 7434 virtual ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) = 0; 7435 virtual void openChild() = 0; 7436 7437 // Debug/ checking 7438 virtual bool isSectionTracker() const = 0; 7439 virtual bool isGeneratorTracker() const = 0; 7440 }; 7441 7442 class TrackerContext { 7443 7444 enum RunState { 7445 NotStarted, 7446 Executing, 7447 CompletedCycle 7448 }; 7449 7450 ITrackerPtr m_rootTracker; 7451 ITracker* m_currentTracker = nullptr; 7452 RunState m_runState = NotStarted; 7453 7454 public: 7455 7456 ITracker& startRun(); 7457 void endRun(); 7458 7459 void startCycle(); 7460 void completeCycle(); 7461 7462 bool completedCycle() const; 7463 ITracker& currentTracker(); 7464 void setCurrentTracker( ITracker* tracker ); 7465 }; 7466 7467 class TrackerBase : public ITracker { 7468 protected: 7469 enum CycleState { 7470 NotStarted, 7471 Executing, 7472 ExecutingChildren, 7473 NeedsAnotherRun, 7474 CompletedSuccessfully, 7475 Failed 7476 }; 7477 7478 using Children = std::vector<ITrackerPtr>; 7479 NameAndLocation m_nameAndLocation; 7480 TrackerContext& m_ctx; 7481 ITracker* m_parent; 7482 Children m_children; 7483 CycleState m_runState = NotStarted; 7484 7485 public: 7486 TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ); 7487 7488 NameAndLocation const& nameAndLocation() const override; 7489 bool isComplete() const override; 7490 bool isSuccessfullyCompleted() const override; 7491 bool isOpen() const override; 7492 bool hasChildren() const override; 7493 7494 void addChild( ITrackerPtr const& child ) override; 7495 7496 ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) override; 7497 ITracker& parent() override; 7498 7499 void openChild() override; 7500 7501 bool isSectionTracker() const override; 7502 bool isGeneratorTracker() const override; 7503 7504 void open(); 7505 7506 void close() override; 7507 void fail() override; 7508 void markAsNeedingAnotherRun() override; 7509 7510 private: 7511 void moveToParent(); 7512 void moveToThis(); 7513 }; 7514 7515 class SectionTracker : public TrackerBase { 7516 std::vector<std::string> m_filters; 7517 std::string m_trimmed_name; 7518 public: 7519 SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ); 7520 7521 bool isSectionTracker() const override; 7522 7523 bool isComplete() const override; 7524 7525 static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ); 7526 7527 void tryOpen(); 7528 7529 void addInitialFilters( std::vector<std::string> const& filters ); 7530 void addNextFilters( std::vector<std::string> const& filters ); 7531 }; 7532 7533 } // namespace TestCaseTracking 7534 7535 using TestCaseTracking::ITracker; 7536 using TestCaseTracking::TrackerContext; 7537 using TestCaseTracking::SectionTracker; 7538 7539 } // namespace Catch 7540 7541 // end catch_test_case_tracker.h 7542 7543 // start catch_leak_detector.h 7544 7545 namespace Catch { 7546 7547 struct LeakDetector { 7548 LeakDetector(); 7549 ~LeakDetector(); 7550 }; 7551 7552 } 7553 // end catch_leak_detector.h 7554 // Cpp files will be included in the single-header file here 7555 // start catch_stats.cpp 7556 7557 // Statistical analysis tools 7558 7559 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 7560 7561 #include <cassert> 7562 #include <random> 7563 7564 #if defined(CATCH_CONFIG_USE_ASYNC) 7565 #include <future> 7566 #endif 7567 7568 namespace { 7569 double erf_inv(double x) { 7570 // Code accompanying the article "Approximating the erfinv function" in GPU Computing Gems, Volume 2 7571 double w, p; 7572 7573 w = -log((1.0 - x) * (1.0 + x)); 7574 7575 if (w < 6.250000) { 7576 w = w - 3.125000; 7577 p = -3.6444120640178196996e-21; 7578 p = -1.685059138182016589e-19 + p * w; 7579 p = 1.2858480715256400167e-18 + p * w; 7580 p = 1.115787767802518096e-17 + p * w; 7581 p = -1.333171662854620906e-16 + p * w; 7582 p = 2.0972767875968561637e-17 + p * w; 7583 p = 6.6376381343583238325e-15 + p * w; 7584 p = -4.0545662729752068639e-14 + p * w; 7585 p = -8.1519341976054721522e-14 + p * w; 7586 p = 2.6335093153082322977e-12 + p * w; 7587 p = -1.2975133253453532498e-11 + p * w; 7588 p = -5.4154120542946279317e-11 + p * w; 7589 p = 1.051212273321532285e-09 + p * w; 7590 p = -4.1126339803469836976e-09 + p * w; 7591 p = -2.9070369957882005086e-08 + p * w; 7592 p = 4.2347877827932403518e-07 + p * w; 7593 p = -1.3654692000834678645e-06 + p * w; 7594 p = -1.3882523362786468719e-05 + p * w; 7595 p = 0.0001867342080340571352 + p * w; 7596 p = -0.00074070253416626697512 + p * w; 7597 p = -0.0060336708714301490533 + p * w; 7598 p = 0.24015818242558961693 + p * w; 7599 p = 1.6536545626831027356 + p * w; 7600 } else if (w < 16.000000) { 7601 w = sqrt(w) - 3.250000; 7602 p = 2.2137376921775787049e-09; 7603 p = 9.0756561938885390979e-08 + p * w; 7604 p = -2.7517406297064545428e-07 + p * w; 7605 p = 1.8239629214389227755e-08 + p * w; 7606 p = 1.5027403968909827627e-06 + p * w; 7607 p = -4.013867526981545969e-06 + p * w; 7608 p = 2.9234449089955446044e-06 + p * w; 7609 p = 1.2475304481671778723e-05 + p * w; 7610 p = -4.7318229009055733981e-05 + p * w; 7611 p = 6.8284851459573175448e-05 + p * w; 7612 p = 2.4031110387097893999e-05 + p * w; 7613 p = -0.0003550375203628474796 + p * w; 7614 p = 0.00095328937973738049703 + p * w; 7615 p = -0.0016882755560235047313 + p * w; 7616 p = 0.0024914420961078508066 + p * w; 7617 p = -0.0037512085075692412107 + p * w; 7618 p = 0.005370914553590063617 + p * w; 7619 p = 1.0052589676941592334 + p * w; 7620 p = 3.0838856104922207635 + p * w; 7621 } else { 7622 w = sqrt(w) - 5.000000; 7623 p = -2.7109920616438573243e-11; 7624 p = -2.5556418169965252055e-10 + p * w; 7625 p = 1.5076572693500548083e-09 + p * w; 7626 p = -3.7894654401267369937e-09 + p * w; 7627 p = 7.6157012080783393804e-09 + p * w; 7628 p = -1.4960026627149240478e-08 + p * w; 7629 p = 2.9147953450901080826e-08 + p * w; 7630 p = -6.7711997758452339498e-08 + p * w; 7631 p = 2.2900482228026654717e-07 + p * w; 7632 p = -9.9298272942317002539e-07 + p * w; 7633 p = 4.5260625972231537039e-06 + p * w; 7634 p = -1.9681778105531670567e-05 + p * w; 7635 p = 7.5995277030017761139e-05 + p * w; 7636 p = -0.00021503011930044477347 + p * w; 7637 p = -0.00013871931833623122026 + p * w; 7638 p = 1.0103004648645343977 + p * w; 7639 p = 4.8499064014085844221 + p * w; 7640 } 7641 return p * x; 7642 } 7643 7644 double standard_deviation(std::vector<double>::iterator first, std::vector<double>::iterator last) { 7645 auto m = Catch::Benchmark::Detail::mean(first, last); 7646 double variance = std::accumulate(first, last, 0., [m](double a, double b) { 7647 double diff = b - m; 7648 return a + diff * diff; 7649 }) / (last - first); 7650 return std::sqrt(variance); 7651 } 7652 7653 } 7654 7655 namespace Catch { 7656 namespace Benchmark { 7657 namespace Detail { 7658 7659 double weighted_average_quantile(int k, int q, std::vector<double>::iterator first, std::vector<double>::iterator last) { 7660 auto count = last - first; 7661 double idx = (count - 1) * k / static_cast<double>(q); 7662 int j = static_cast<int>(idx); 7663 double g = idx - j; 7664 std::nth_element(first, first + j, last); 7665 auto xj = first[j]; 7666 if (g == 0) return xj; 7667 7668 auto xj1 = *std::min_element(first + (j + 1), last); 7669 return xj + g * (xj1 - xj); 7670 } 7671 7672 double erfc_inv(double x) { 7673 return erf_inv(1.0 - x); 7674 } 7675 7676 double normal_quantile(double p) { 7677 static const double ROOT_TWO = std::sqrt(2.0); 7678 7679 double result = 0.0; 7680 assert(p >= 0 && p <= 1); 7681 if (p < 0 || p > 1) { 7682 return result; 7683 } 7684 7685 result = -erfc_inv(2.0 * p); 7686 // result *= normal distribution standard deviation (1.0) * sqrt(2) 7687 result *= /*sd * */ ROOT_TWO; 7688 // result += normal disttribution mean (0) 7689 return result; 7690 } 7691 7692 double outlier_variance(Estimate<double> mean, Estimate<double> stddev, int n) { 7693 double sb = stddev.point; 7694 double mn = mean.point / n; 7695 double mg_min = mn / 2.; 7696 double sg = std::min(mg_min / 4., sb / std::sqrt(n)); 7697 double sg2 = sg * sg; 7698 double sb2 = sb * sb; 7699 7700 auto c_max = [n, mn, sb2, sg2](double x) -> double { 7701 double k = mn - x; 7702 double d = k * k; 7703 double nd = n * d; 7704 double k0 = -n * nd; 7705 double k1 = sb2 - n * sg2 + nd; 7706 double det = k1 * k1 - 4 * sg2 * k0; 7707 return (int)(-2. * k0 / (k1 + std::sqrt(det))); 7708 }; 7709 7710 auto var_out = [n, sb2, sg2](double c) { 7711 double nc = n - c; 7712 return (nc / n) * (sb2 - nc * sg2); 7713 }; 7714 7715 return std::min(var_out(1), var_out(std::min(c_max(0.), c_max(mg_min)))) / sb2; 7716 } 7717 7718 bootstrap_analysis analyse_samples(double confidence_level, int n_resamples, std::vector<double>::iterator first, std::vector<double>::iterator last) { 7719 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION 7720 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS 7721 static std::random_device entropy; 7722 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 7723 7724 auto n = static_cast<int>(last - first); // seriously, one can't use integral types without hell in C++ 7725 7726 auto mean = &Detail::mean<std::vector<double>::iterator>; 7727 auto stddev = &standard_deviation; 7728 7729 #if defined(CATCH_CONFIG_USE_ASYNC) 7730 auto Estimate = [=](double(*f)(std::vector<double>::iterator, std::vector<double>::iterator)) { 7731 auto seed = entropy(); 7732 return std::async(std::launch::async, [=] { 7733 std::mt19937 rng(seed); 7734 auto resampled = resample(rng, n_resamples, first, last, f); 7735 return bootstrap(confidence_level, first, last, resampled, f); 7736 }); 7737 }; 7738 7739 auto mean_future = Estimate(mean); 7740 auto stddev_future = Estimate(stddev); 7741 7742 auto mean_estimate = mean_future.get(); 7743 auto stddev_estimate = stddev_future.get(); 7744 #else 7745 auto Estimate = [=](double(*f)(std::vector<double>::iterator, std::vector<double>::iterator)) { 7746 auto seed = entropy(); 7747 std::mt19937 rng(seed); 7748 auto resampled = resample(rng, n_resamples, first, last, f); 7749 return bootstrap(confidence_level, first, last, resampled, f); 7750 }; 7751 7752 auto mean_estimate = Estimate(mean); 7753 auto stddev_estimate = Estimate(stddev); 7754 #endif // CATCH_USE_ASYNC 7755 7756 double outlier_variance = Detail::outlier_variance(mean_estimate, stddev_estimate, n); 7757 7758 return { mean_estimate, stddev_estimate, outlier_variance }; 7759 } 7760 } // namespace Detail 7761 } // namespace Benchmark 7762 } // namespace Catch 7763 7764 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 7765 // end catch_stats.cpp 7766 // start catch_approx.cpp 7767 7768 #include <cmath> 7769 #include <limits> 7770 7771 namespace { 7772 7773 // Performs equivalent check of std::fabs(lhs - rhs) <= margin 7774 // But without the subtraction to allow for INFINITY in comparison 7775 bool marginComparison(double lhs, double rhs, double margin) { 7776 return (lhs + margin >= rhs) && (rhs + margin >= lhs); 7777 } 7778 7779 } 7780 7781 namespace Catch { 7782 namespace Detail { 7783 7784 Approx::Approx ( double value ) 7785 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ), 7786 m_margin( 0.0 ), 7787 m_scale( 0.0 ), 7788 m_value( value ) 7789 {} 7790 7791 Approx Approx::custom() { 7792 return Approx( 0 ); 7793 } 7794 7795 Approx Approx::operator-() const { 7796 auto temp(*this); 7797 temp.m_value = -temp.m_value; 7798 return temp; 7799 } 7800 7801 std::string Approx::toString() const { 7802 ReusableStringStream rss; 7803 rss << "Approx( " << ::Catch::Detail::stringify( m_value ) << " )"; 7804 return rss.str(); 7805 } 7806 7807 bool Approx::equalityComparisonImpl(const double other) const { 7808 // First try with fixed margin, then compute margin based on epsilon, scale and Approx's value 7809 // Thanks to Richard Harris for his help refining the scaled margin value 7810 return marginComparison(m_value, other, m_margin) 7811 || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(std::isinf(m_value)? 0 : m_value))); 7812 } 7813 7814 void Approx::setMargin(double newMargin) { 7815 CATCH_ENFORCE(newMargin >= 0, 7816 "Invalid Approx::margin: " << newMargin << '.' 7817 << " Approx::Margin has to be non-negative."); 7818 m_margin = newMargin; 7819 } 7820 7821 void Approx::setEpsilon(double newEpsilon) { 7822 CATCH_ENFORCE(newEpsilon >= 0 && newEpsilon <= 1.0, 7823 "Invalid Approx::epsilon: " << newEpsilon << '.' 7824 << " Approx::epsilon has to be in [0, 1]"); 7825 m_epsilon = newEpsilon; 7826 } 7827 7828 } // end namespace Detail 7829 7830 namespace literals { 7831 Detail::Approx operator "" _a(long double val) { 7832 return Detail::Approx(val); 7833 } 7834 Detail::Approx operator "" _a(unsigned long long val) { 7835 return Detail::Approx(val); 7836 } 7837 } // end namespace literals 7838 7839 std::string StringMaker<Catch::Detail::Approx>::convert(Catch::Detail::Approx const& value) { 7840 return value.toString(); 7841 } 7842 7843 } // end namespace Catch 7844 // end catch_approx.cpp 7845 // start catch_assertionhandler.cpp 7846 7847 // start catch_debugger.h 7848 7849 namespace Catch { 7850 bool isDebuggerActive(); 7851 } 7852 7853 #ifdef CATCH_PLATFORM_MAC 7854 7855 #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */ 7856 7857 #elif defined(CATCH_PLATFORM_LINUX) 7858 // If we can use inline assembler, do it because this allows us to break 7859 // directly at the location of the failing check instead of breaking inside 7860 // raise() called from it, i.e. one stack frame below. 7861 #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64)) 7862 #define CATCH_TRAP() asm volatile ("int $3") /* NOLINT */ 7863 #else // Fall back to the generic way. 7864 #include <signal.h> 7865 7866 #define CATCH_TRAP() raise(SIGTRAP) 7867 #endif 7868 #elif defined(_MSC_VER) 7869 #define CATCH_TRAP() __debugbreak() 7870 #elif defined(__MINGW32__) 7871 extern "C" __declspec(dllimport) void __stdcall DebugBreak(); 7872 #define CATCH_TRAP() DebugBreak() 7873 #endif 7874 7875 #ifdef CATCH_TRAP 7876 #define CATCH_BREAK_INTO_DEBUGGER() []{ if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } }() 7877 #else 7878 #define CATCH_BREAK_INTO_DEBUGGER() []{}() 7879 #endif 7880 7881 // end catch_debugger.h 7882 // start catch_run_context.h 7883 7884 // start catch_fatal_condition.h 7885 7886 // start catch_windows_h_proxy.h 7887 7888 7889 #if defined(CATCH_PLATFORM_WINDOWS) 7890 7891 #if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX) 7892 # define CATCH_DEFINED_NOMINMAX 7893 # define NOMINMAX 7894 #endif 7895 #if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN) 7896 # define CATCH_DEFINED_WIN32_LEAN_AND_MEAN 7897 # define WIN32_LEAN_AND_MEAN 7898 #endif 7899 7900 #ifdef __AFXDLL 7901 #include <AfxWin.h> 7902 #else 7903 #include <windows.h> 7904 #endif 7905 7906 #ifdef CATCH_DEFINED_NOMINMAX 7907 # undef NOMINMAX 7908 #endif 7909 #ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN 7910 # undef WIN32_LEAN_AND_MEAN 7911 #endif 7912 7913 #endif // defined(CATCH_PLATFORM_WINDOWS) 7914 7915 // end catch_windows_h_proxy.h 7916 #if defined( CATCH_CONFIG_WINDOWS_SEH ) 7917 7918 namespace Catch { 7919 7920 struct FatalConditionHandler { 7921 7922 static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo); 7923 FatalConditionHandler(); 7924 static void reset(); 7925 ~FatalConditionHandler(); 7926 7927 private: 7928 static bool isSet; 7929 static ULONG guaranteeSize; 7930 static PVOID exceptionHandlerHandle; 7931 }; 7932 7933 } // namespace Catch 7934 7935 #elif defined ( CATCH_CONFIG_POSIX_SIGNALS ) 7936 7937 #include <signal.h> 7938 7939 namespace Catch { 7940 7941 struct FatalConditionHandler { 7942 7943 static bool isSet; 7944 static struct sigaction oldSigActions[]; 7945 static stack_t oldSigStack; 7946 static char altStackMem[]; 7947 7948 static void handleSignal( int sig ); 7949 7950 FatalConditionHandler(); 7951 ~FatalConditionHandler(); 7952 static void reset(); 7953 }; 7954 7955 } // namespace Catch 7956 7957 #else 7958 7959 namespace Catch { 7960 struct FatalConditionHandler { 7961 void reset(); 7962 }; 7963 } 7964 7965 #endif 7966 7967 // end catch_fatal_condition.h 7968 #include <string> 7969 7970 namespace Catch { 7971 7972 struct IMutableContext; 7973 7974 /////////////////////////////////////////////////////////////////////////// 7975 7976 class RunContext : public IResultCapture, public IRunner { 7977 7978 public: 7979 RunContext( RunContext const& ) = delete; 7980 RunContext& operator =( RunContext const& ) = delete; 7981 7982 explicit RunContext( IConfigPtr const& _config, IStreamingReporterPtr&& reporter ); 7983 7984 ~RunContext() override; 7985 7986 void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ); 7987 void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ); 7988 7989 Totals runTest(TestCase const& testCase); 7990 7991 IConfigPtr config() const; 7992 IStreamingReporter& reporter() const; 7993 7994 public: // IResultCapture 7995 7996 // Assertion handlers 7997 void handleExpr 7998 ( AssertionInfo const& info, 7999 ITransientExpression const& expr, 8000 AssertionReaction& reaction ) override; 8001 void handleMessage 8002 ( AssertionInfo const& info, 8003 ResultWas::OfType resultType, 8004 StringRef const& message, 8005 AssertionReaction& reaction ) override; 8006 void handleUnexpectedExceptionNotThrown 8007 ( AssertionInfo const& info, 8008 AssertionReaction& reaction ) override; 8009 void handleUnexpectedInflightException 8010 ( AssertionInfo const& info, 8011 std::string const& message, 8012 AssertionReaction& reaction ) override; 8013 void handleIncomplete 8014 ( AssertionInfo const& info ) override; 8015 void handleNonExpr 8016 ( AssertionInfo const &info, 8017 ResultWas::OfType resultType, 8018 AssertionReaction &reaction ) override; 8019 8020 bool sectionStarted( SectionInfo const& sectionInfo, Counts& assertions ) override; 8021 8022 void sectionEnded( SectionEndInfo const& endInfo ) override; 8023 void sectionEndedEarly( SectionEndInfo const& endInfo ) override; 8024 8025 auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& override; 8026 8027 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 8028 void benchmarkPreparing( std::string const& name ) override; 8029 void benchmarkStarting( BenchmarkInfo const& info ) override; 8030 void benchmarkEnded( BenchmarkStats<> const& stats ) override; 8031 void benchmarkFailed( std::string const& error ) override; 8032 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 8033 8034 void pushScopedMessage( MessageInfo const& message ) override; 8035 void popScopedMessage( MessageInfo const& message ) override; 8036 8037 void emplaceUnscopedMessage( MessageBuilder const& builder ) override; 8038 8039 std::string getCurrentTestName() const override; 8040 8041 const AssertionResult* getLastResult() const override; 8042 8043 void exceptionEarlyReported() override; 8044 8045 void handleFatalErrorCondition( StringRef message ) override; 8046 8047 bool lastAssertionPassed() override; 8048 8049 void assertionPassed() override; 8050 8051 public: 8052 // !TBD We need to do this another way! 8053 bool aborting() const final; 8054 8055 private: 8056 8057 void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ); 8058 void invokeActiveTestCase(); 8059 8060 void resetAssertionInfo(); 8061 bool testForMissingAssertions( Counts& assertions ); 8062 8063 void assertionEnded( AssertionResult const& result ); 8064 void reportExpr 8065 ( AssertionInfo const &info, 8066 ResultWas::OfType resultType, 8067 ITransientExpression const *expr, 8068 bool negated ); 8069 8070 void populateReaction( AssertionReaction& reaction ); 8071 8072 private: 8073 8074 void handleUnfinishedSections(); 8075 8076 TestRunInfo m_runInfo; 8077 IMutableContext& m_context; 8078 TestCase const* m_activeTestCase = nullptr; 8079 ITracker* m_testCaseTracker = nullptr; 8080 Option<AssertionResult> m_lastResult; 8081 8082 IConfigPtr m_config; 8083 Totals m_totals; 8084 IStreamingReporterPtr m_reporter; 8085 std::vector<MessageInfo> m_messages; 8086 std::vector<ScopedMessage> m_messageScopes; /* Keeps owners of so-called unscoped messages. */ 8087 AssertionInfo m_lastAssertionInfo; 8088 std::vector<SectionEndInfo> m_unfinishedSections; 8089 std::vector<ITracker*> m_activeSections; 8090 TrackerContext m_trackerContext; 8091 bool m_lastAssertionPassed = false; 8092 bool m_shouldReportUnexpected = true; 8093 bool m_includeSuccessfulResults; 8094 }; 8095 8096 void seedRng(IConfig const& config); 8097 unsigned int rngSeed(); 8098 } // end namespace Catch 8099 8100 // end catch_run_context.h 8101 namespace Catch { 8102 8103 namespace { 8104 auto operator <<( std::ostream& os, ITransientExpression const& expr ) -> std::ostream& { 8105 expr.streamReconstructedExpression( os ); 8106 return os; 8107 } 8108 } 8109 8110 LazyExpression::LazyExpression( bool isNegated ) 8111 : m_isNegated( isNegated ) 8112 {} 8113 8114 LazyExpression::LazyExpression( LazyExpression const& other ) : m_isNegated( other.m_isNegated ) {} 8115 8116 LazyExpression::operator bool() const { 8117 return m_transientExpression != nullptr; 8118 } 8119 8120 auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream& { 8121 if( lazyExpr.m_isNegated ) 8122 os << "!"; 8123 8124 if( lazyExpr ) { 8125 if( lazyExpr.m_isNegated && lazyExpr.m_transientExpression->isBinaryExpression() ) 8126 os << "(" << *lazyExpr.m_transientExpression << ")"; 8127 else 8128 os << *lazyExpr.m_transientExpression; 8129 } 8130 else { 8131 os << "{** error - unchecked empty expression requested **}"; 8132 } 8133 return os; 8134 } 8135 8136 AssertionHandler::AssertionHandler 8137 ( StringRef const& macroName, 8138 SourceLineInfo const& lineInfo, 8139 StringRef capturedExpression, 8140 ResultDisposition::Flags resultDisposition ) 8141 : m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition }, 8142 m_resultCapture( getResultCapture() ) 8143 {} 8144 8145 void AssertionHandler::handleExpr( ITransientExpression const& expr ) { 8146 m_resultCapture.handleExpr( m_assertionInfo, expr, m_reaction ); 8147 } 8148 void AssertionHandler::handleMessage(ResultWas::OfType resultType, StringRef const& message) { 8149 m_resultCapture.handleMessage( m_assertionInfo, resultType, message, m_reaction ); 8150 } 8151 8152 auto AssertionHandler::allowThrows() const -> bool { 8153 return getCurrentContext().getConfig()->allowThrows(); 8154 } 8155 8156 void AssertionHandler::complete() { 8157 setCompleted(); 8158 if( m_reaction.shouldDebugBreak ) { 8159 8160 // If you find your debugger stopping you here then go one level up on the 8161 // call-stack for the code that caused it (typically a failed assertion) 8162 8163 // (To go back to the test and change execution, jump over the throw, next) 8164 CATCH_BREAK_INTO_DEBUGGER(); 8165 } 8166 if (m_reaction.shouldThrow) { 8167 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 8168 throw Catch::TestFailureException(); 8169 #else 8170 CATCH_ERROR( "Test failure requires aborting test!" ); 8171 #endif 8172 } 8173 } 8174 void AssertionHandler::setCompleted() { 8175 m_completed = true; 8176 } 8177 8178 void AssertionHandler::handleUnexpectedInflightException() { 8179 m_resultCapture.handleUnexpectedInflightException( m_assertionInfo, Catch::translateActiveException(), m_reaction ); 8180 } 8181 8182 void AssertionHandler::handleExceptionThrownAsExpected() { 8183 m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction); 8184 } 8185 void AssertionHandler::handleExceptionNotThrownAsExpected() { 8186 m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction); 8187 } 8188 8189 void AssertionHandler::handleUnexpectedExceptionNotThrown() { 8190 m_resultCapture.handleUnexpectedExceptionNotThrown( m_assertionInfo, m_reaction ); 8191 } 8192 8193 void AssertionHandler::handleThrowingCallSkipped() { 8194 m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction); 8195 } 8196 8197 // This is the overload that takes a string and infers the Equals matcher from it 8198 // The more general overload, that takes any string matcher, is in catch_capture_matchers.cpp 8199 void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef const& matcherString ) { 8200 handleExceptionMatchExpr( handler, Matchers::Equals( str ), matcherString ); 8201 } 8202 8203 } // namespace Catch 8204 // end catch_assertionhandler.cpp 8205 // start catch_assertionresult.cpp 8206 8207 namespace Catch { 8208 AssertionResultData::AssertionResultData(ResultWas::OfType _resultType, LazyExpression const & _lazyExpression): 8209 lazyExpression(_lazyExpression), 8210 resultType(_resultType) {} 8211 8212 std::string AssertionResultData::reconstructExpression() const { 8213 8214 if( reconstructedExpression.empty() ) { 8215 if( lazyExpression ) { 8216 ReusableStringStream rss; 8217 rss << lazyExpression; 8218 reconstructedExpression = rss.str(); 8219 } 8220 } 8221 return reconstructedExpression; 8222 } 8223 8224 AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) 8225 : m_info( info ), 8226 m_resultData( data ) 8227 {} 8228 8229 // Result was a success 8230 bool AssertionResult::succeeded() const { 8231 return Catch::isOk( m_resultData.resultType ); 8232 } 8233 8234 // Result was a success, or failure is suppressed 8235 bool AssertionResult::isOk() const { 8236 return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition ); 8237 } 8238 8239 ResultWas::OfType AssertionResult::getResultType() const { 8240 return m_resultData.resultType; 8241 } 8242 8243 bool AssertionResult::hasExpression() const { 8244 return !m_info.capturedExpression.empty(); 8245 } 8246 8247 bool AssertionResult::hasMessage() const { 8248 return !m_resultData.message.empty(); 8249 } 8250 8251 std::string AssertionResult::getExpression() const { 8252 // Possibly overallocating by 3 characters should be basically free 8253 std::string expr; expr.reserve(m_info.capturedExpression.size() + 3); 8254 if (isFalseTest(m_info.resultDisposition)) { 8255 expr += "!("; 8256 } 8257 expr += m_info.capturedExpression; 8258 if (isFalseTest(m_info.resultDisposition)) { 8259 expr += ')'; 8260 } 8261 return expr; 8262 } 8263 8264 std::string AssertionResult::getExpressionInMacro() const { 8265 std::string expr; 8266 if( m_info.macroName.empty() ) 8267 expr = static_cast<std::string>(m_info.capturedExpression); 8268 else { 8269 expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 ); 8270 expr += m_info.macroName; 8271 expr += "( "; 8272 expr += m_info.capturedExpression; 8273 expr += " )"; 8274 } 8275 return expr; 8276 } 8277 8278 bool AssertionResult::hasExpandedExpression() const { 8279 return hasExpression() && getExpandedExpression() != getExpression(); 8280 } 8281 8282 std::string AssertionResult::getExpandedExpression() const { 8283 std::string expr = m_resultData.reconstructExpression(); 8284 return expr.empty() 8285 ? getExpression() 8286 : expr; 8287 } 8288 8289 std::string AssertionResult::getMessage() const { 8290 return m_resultData.message; 8291 } 8292 SourceLineInfo AssertionResult::getSourceInfo() const { 8293 return m_info.lineInfo; 8294 } 8295 8296 StringRef AssertionResult::getTestMacroName() const { 8297 return m_info.macroName; 8298 } 8299 8300 } // end namespace Catch 8301 // end catch_assertionresult.cpp 8302 // start catch_capture_matchers.cpp 8303 8304 namespace Catch { 8305 8306 using StringMatcher = Matchers::Impl::MatcherBase<std::string>; 8307 8308 // This is the general overload that takes a any string matcher 8309 // There is another overload, in catch_assertionhandler.h/.cpp, that only takes a string and infers 8310 // the Equals matcher (so the header does not mention matchers) 8311 void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString ) { 8312 std::string exceptionMessage = Catch::translateActiveException(); 8313 MatchExpr<std::string, StringMatcher const&> expr( exceptionMessage, matcher, matcherString ); 8314 handler.handleExpr( expr ); 8315 } 8316 8317 } // namespace Catch 8318 // end catch_capture_matchers.cpp 8319 // start catch_commandline.cpp 8320 8321 // start catch_commandline.h 8322 8323 // start catch_clara.h 8324 8325 // Use Catch's value for console width (store Clara's off to the side, if present) 8326 #ifdef CLARA_CONFIG_CONSOLE_WIDTH 8327 #define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 8328 #undef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 8329 #endif 8330 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH-1 8331 8332 #ifdef __clang__ 8333 #pragma clang diagnostic push 8334 #pragma clang diagnostic ignored "-Wweak-vtables" 8335 #pragma clang diagnostic ignored "-Wexit-time-destructors" 8336 #pragma clang diagnostic ignored "-Wshadow" 8337 #endif 8338 8339 // start clara.hpp 8340 // Copyright 2017 Two Blue Cubes Ltd. All rights reserved. 8341 // 8342 // Distributed under the Boost Software License, Version 1.0. (See accompanying 8343 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8344 // 8345 // See https://github.com/philsquared/Clara for more details 8346 8347 // Clara v1.1.5 8348 8349 8350 #ifndef CATCH_CLARA_CONFIG_CONSOLE_WIDTH 8351 #define CATCH_CLARA_CONFIG_CONSOLE_WIDTH 80 8352 #endif 8353 8354 #ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 8355 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CLARA_CONFIG_CONSOLE_WIDTH 8356 #endif 8357 8358 #ifndef CLARA_CONFIG_OPTIONAL_TYPE 8359 #ifdef __has_include 8360 #if __has_include(<optional>) && __cplusplus >= 201703L 8361 #include <optional> 8362 #define CLARA_CONFIG_OPTIONAL_TYPE std::optional 8363 #endif 8364 #endif 8365 #endif 8366 8367 // ----------- #included from clara_textflow.hpp ----------- 8368 8369 // TextFlowCpp 8370 // 8371 // A single-header library for wrapping and laying out basic text, by Phil Nash 8372 // 8373 // Distributed under the Boost Software License, Version 1.0. (See accompanying 8374 // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8375 // 8376 // This project is hosted at https://github.com/philsquared/textflowcpp 8377 8378 8379 #include <cassert> 8380 #include <ostream> 8381 #include <sstream> 8382 #include <vector> 8383 8384 #ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 8385 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 80 8386 #endif 8387 8388 namespace Catch { 8389 namespace clara { 8390 namespace TextFlow { 8391 8392 inline auto isWhitespace(char c) -> bool { 8393 static std::string chars = " \t\n\r"; 8394 return chars.find(c) != std::string::npos; 8395 } 8396 inline auto isBreakableBefore(char c) -> bool { 8397 static std::string chars = "[({<|"; 8398 return chars.find(c) != std::string::npos; 8399 } 8400 inline auto isBreakableAfter(char c) -> bool { 8401 static std::string chars = "])}>.,:;*+-=&/\\"; 8402 return chars.find(c) != std::string::npos; 8403 } 8404 8405 class Columns; 8406 8407 class Column { 8408 std::vector<std::string> m_strings; 8409 size_t m_width = CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH; 8410 size_t m_indent = 0; 8411 size_t m_initialIndent = std::string::npos; 8412 8413 public: 8414 class iterator { 8415 friend Column; 8416 8417 Column const& m_column; 8418 size_t m_stringIndex = 0; 8419 size_t m_pos = 0; 8420 8421 size_t m_len = 0; 8422 size_t m_end = 0; 8423 bool m_suffix = false; 8424 8425 iterator(Column const& column, size_t stringIndex) 8426 : m_column(column), 8427 m_stringIndex(stringIndex) {} 8428 8429 auto line() const -> std::string const& { return m_column.m_strings[m_stringIndex]; } 8430 8431 auto isBoundary(size_t at) const -> bool { 8432 assert(at > 0); 8433 assert(at <= line().size()); 8434 8435 return at == line().size() || 8436 (isWhitespace(line()[at]) && !isWhitespace(line()[at - 1])) || 8437 isBreakableBefore(line()[at]) || 8438 isBreakableAfter(line()[at - 1]); 8439 } 8440 8441 void calcLength() { 8442 assert(m_stringIndex < m_column.m_strings.size()); 8443 8444 m_suffix = false; 8445 auto width = m_column.m_width - indent(); 8446 m_end = m_pos; 8447 if (line()[m_pos] == '\n') { 8448 ++m_end; 8449 } 8450 while (m_end < line().size() && line()[m_end] != '\n') 8451 ++m_end; 8452 8453 if (m_end < m_pos + width) { 8454 m_len = m_end - m_pos; 8455 } else { 8456 size_t len = width; 8457 while (len > 0 && !isBoundary(m_pos + len)) 8458 --len; 8459 while (len > 0 && isWhitespace(line()[m_pos + len - 1])) 8460 --len; 8461 8462 if (len > 0) { 8463 m_len = len; 8464 } else { 8465 m_suffix = true; 8466 m_len = width - 1; 8467 } 8468 } 8469 } 8470 8471 auto indent() const -> size_t { 8472 auto initial = m_pos == 0 && m_stringIndex == 0 ? m_column.m_initialIndent : std::string::npos; 8473 return initial == std::string::npos ? m_column.m_indent : initial; 8474 } 8475 8476 auto addIndentAndSuffix(std::string const &plain) const -> std::string { 8477 return std::string(indent(), ' ') + (m_suffix ? plain + "-" : plain); 8478 } 8479 8480 public: 8481 using difference_type = std::ptrdiff_t; 8482 using value_type = std::string; 8483 using pointer = value_type * ; 8484 using reference = value_type & ; 8485 using iterator_category = std::forward_iterator_tag; 8486 8487 explicit iterator(Column const& column) : m_column(column) { 8488 assert(m_column.m_width > m_column.m_indent); 8489 assert(m_column.m_initialIndent == std::string::npos || m_column.m_width > m_column.m_initialIndent); 8490 calcLength(); 8491 if (m_len == 0) 8492 m_stringIndex++; // Empty string 8493 } 8494 8495 auto operator *() const -> std::string { 8496 assert(m_stringIndex < m_column.m_strings.size()); 8497 assert(m_pos <= m_end); 8498 return addIndentAndSuffix(line().substr(m_pos, m_len)); 8499 } 8500 8501 auto operator ++() -> iterator& { 8502 m_pos += m_len; 8503 if (m_pos < line().size() && line()[m_pos] == '\n') 8504 m_pos += 1; 8505 else 8506 while (m_pos < line().size() && isWhitespace(line()[m_pos])) 8507 ++m_pos; 8508 8509 if (m_pos == line().size()) { 8510 m_pos = 0; 8511 ++m_stringIndex; 8512 } 8513 if (m_stringIndex < m_column.m_strings.size()) 8514 calcLength(); 8515 return *this; 8516 } 8517 auto operator ++(int) -> iterator { 8518 iterator prev(*this); 8519 operator++(); 8520 return prev; 8521 } 8522 8523 auto operator ==(iterator const& other) const -> bool { 8524 return 8525 m_pos == other.m_pos && 8526 m_stringIndex == other.m_stringIndex && 8527 &m_column == &other.m_column; 8528 } 8529 auto operator !=(iterator const& other) const -> bool { 8530 return !operator==(other); 8531 } 8532 }; 8533 using const_iterator = iterator; 8534 8535 explicit Column(std::string const& text) { m_strings.push_back(text); } 8536 8537 auto width(size_t newWidth) -> Column& { 8538 assert(newWidth > 0); 8539 m_width = newWidth; 8540 return *this; 8541 } 8542 auto indent(size_t newIndent) -> Column& { 8543 m_indent = newIndent; 8544 return *this; 8545 } 8546 auto initialIndent(size_t newIndent) -> Column& { 8547 m_initialIndent = newIndent; 8548 return *this; 8549 } 8550 8551 auto width() const -> size_t { return m_width; } 8552 auto begin() const -> iterator { return iterator(*this); } 8553 auto end() const -> iterator { return { *this, m_strings.size() }; } 8554 8555 inline friend std::ostream& operator << (std::ostream& os, Column const& col) { 8556 bool first = true; 8557 for (auto line : col) { 8558 if (first) 8559 first = false; 8560 else 8561 os << "\n"; 8562 os << line; 8563 } 8564 return os; 8565 } 8566 8567 auto operator + (Column const& other)->Columns; 8568 8569 auto toString() const -> std::string { 8570 std::ostringstream oss; 8571 oss << *this; 8572 return oss.str(); 8573 } 8574 }; 8575 8576 class Spacer : public Column { 8577 8578 public: 8579 explicit Spacer(size_t spaceWidth) : Column("") { 8580 width(spaceWidth); 8581 } 8582 }; 8583 8584 class Columns { 8585 std::vector<Column> m_columns; 8586 8587 public: 8588 8589 class iterator { 8590 friend Columns; 8591 struct EndTag {}; 8592 8593 std::vector<Column> const& m_columns; 8594 std::vector<Column::iterator> m_iterators; 8595 size_t m_activeIterators; 8596 8597 iterator(Columns const& columns, EndTag) 8598 : m_columns(columns.m_columns), 8599 m_activeIterators(0) { 8600 m_iterators.reserve(m_columns.size()); 8601 8602 for (auto const& col : m_columns) 8603 m_iterators.push_back(col.end()); 8604 } 8605 8606 public: 8607 using difference_type = std::ptrdiff_t; 8608 using value_type = std::string; 8609 using pointer = value_type * ; 8610 using reference = value_type & ; 8611 using iterator_category = std::forward_iterator_tag; 8612 8613 explicit iterator(Columns const& columns) 8614 : m_columns(columns.m_columns), 8615 m_activeIterators(m_columns.size()) { 8616 m_iterators.reserve(m_columns.size()); 8617 8618 for (auto const& col : m_columns) 8619 m_iterators.push_back(col.begin()); 8620 } 8621 8622 auto operator ==(iterator const& other) const -> bool { 8623 return m_iterators == other.m_iterators; 8624 } 8625 auto operator !=(iterator const& other) const -> bool { 8626 return m_iterators != other.m_iterators; 8627 } 8628 auto operator *() const -> std::string { 8629 std::string row, padding; 8630 8631 for (size_t i = 0; i < m_columns.size(); ++i) { 8632 auto width = m_columns[i].width(); 8633 if (m_iterators[i] != m_columns[i].end()) { 8634 std::string col = *m_iterators[i]; 8635 row += padding + col; 8636 if (col.size() < width) 8637 padding = std::string(width - col.size(), ' '); 8638 else 8639 padding = ""; 8640 } else { 8641 padding += std::string(width, ' '); 8642 } 8643 } 8644 return row; 8645 } 8646 auto operator ++() -> iterator& { 8647 for (size_t i = 0; i < m_columns.size(); ++i) { 8648 if (m_iterators[i] != m_columns[i].end()) 8649 ++m_iterators[i]; 8650 } 8651 return *this; 8652 } 8653 auto operator ++(int) -> iterator { 8654 iterator prev(*this); 8655 operator++(); 8656 return prev; 8657 } 8658 }; 8659 using const_iterator = iterator; 8660 8661 auto begin() const -> iterator { return iterator(*this); } 8662 auto end() const -> iterator { return { *this, iterator::EndTag() }; } 8663 8664 auto operator += (Column const& col) -> Columns& { 8665 m_columns.push_back(col); 8666 return *this; 8667 } 8668 auto operator + (Column const& col) -> Columns { 8669 Columns combined = *this; 8670 combined += col; 8671 return combined; 8672 } 8673 8674 inline friend std::ostream& operator << (std::ostream& os, Columns const& cols) { 8675 8676 bool first = true; 8677 for (auto line : cols) { 8678 if (first) 8679 first = false; 8680 else 8681 os << "\n"; 8682 os << line; 8683 } 8684 return os; 8685 } 8686 8687 auto toString() const -> std::string { 8688 std::ostringstream oss; 8689 oss << *this; 8690 return oss.str(); 8691 } 8692 }; 8693 8694 inline auto Column::operator + (Column const& other) -> Columns { 8695 Columns cols; 8696 cols += *this; 8697 cols += other; 8698 return cols; 8699 } 8700 } 8701 8702 } 8703 } 8704 8705 // ----------- end of #include from clara_textflow.hpp ----------- 8706 // ........... back in clara.hpp 8707 8708 #include <cctype> 8709 #include <string> 8710 #include <memory> 8711 #include <set> 8712 #include <algorithm> 8713 8714 #if !defined(CATCH_PLATFORM_WINDOWS) && ( defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) ) 8715 #define CATCH_PLATFORM_WINDOWS 8716 #endif 8717 8718 namespace Catch { namespace clara { 8719 namespace detail { 8720 8721 // Traits for extracting arg and return type of lambdas (for single argument lambdas) 8722 template<typename L> 8723 struct UnaryLambdaTraits : UnaryLambdaTraits<decltype( &L::operator() )> {}; 8724 8725 template<typename ClassT, typename ReturnT, typename... Args> 8726 struct UnaryLambdaTraits<ReturnT( ClassT::* )( Args... ) const> { 8727 static const bool isValid = false; 8728 }; 8729 8730 template<typename ClassT, typename ReturnT, typename ArgT> 8731 struct UnaryLambdaTraits<ReturnT( ClassT::* )( ArgT ) const> { 8732 static const bool isValid = true; 8733 using ArgType = typename std::remove_const<typename std::remove_reference<ArgT>::type>::type; 8734 using ReturnType = ReturnT; 8735 }; 8736 8737 class TokenStream; 8738 8739 // Transport for raw args (copied from main args, or supplied via init list for testing) 8740 class Args { 8741 friend TokenStream; 8742 std::string m_exeName; 8743 std::vector<std::string> m_args; 8744 8745 public: 8746 Args( int argc, char const* const* argv ) 8747 : m_exeName(argv[0]), 8748 m_args(argv + 1, argv + argc) {} 8749 8750 Args( std::initializer_list<std::string> args ) 8751 : m_exeName( *args.begin() ), 8752 m_args( args.begin()+1, args.end() ) 8753 {} 8754 8755 auto exeName() const -> std::string { 8756 return m_exeName; 8757 } 8758 }; 8759 8760 // Wraps a token coming from a token stream. These may not directly correspond to strings as a single string 8761 // may encode an option + its argument if the : or = form is used 8762 enum class TokenType { 8763 Option, Argument 8764 }; 8765 struct Token { 8766 TokenType type; 8767 std::string token; 8768 }; 8769 8770 inline auto isOptPrefix( char c ) -> bool { 8771 return c == '-' 8772 #ifdef CATCH_PLATFORM_WINDOWS 8773 || c == '/' 8774 #endif 8775 ; 8776 } 8777 8778 // Abstracts iterators into args as a stream of tokens, with option arguments uniformly handled 8779 class TokenStream { 8780 using Iterator = std::vector<std::string>::const_iterator; 8781 Iterator it; 8782 Iterator itEnd; 8783 std::vector<Token> m_tokenBuffer; 8784 8785 void loadBuffer() { 8786 m_tokenBuffer.resize( 0 ); 8787 8788 // Skip any empty strings 8789 while( it != itEnd && it->empty() ) 8790 ++it; 8791 8792 if( it != itEnd ) { 8793 auto const &next = *it; 8794 if( isOptPrefix( next[0] ) ) { 8795 auto delimiterPos = next.find_first_of( " :=" ); 8796 if( delimiterPos != std::string::npos ) { 8797 m_tokenBuffer.push_back( { TokenType::Option, next.substr( 0, delimiterPos ) } ); 8798 m_tokenBuffer.push_back( { TokenType::Argument, next.substr( delimiterPos + 1 ) } ); 8799 } else { 8800 if( next[1] != '-' && next.size() > 2 ) { 8801 std::string opt = "- "; 8802 for( size_t i = 1; i < next.size(); ++i ) { 8803 opt[1] = next[i]; 8804 m_tokenBuffer.push_back( { TokenType::Option, opt } ); 8805 } 8806 } else { 8807 m_tokenBuffer.push_back( { TokenType::Option, next } ); 8808 } 8809 } 8810 } else { 8811 m_tokenBuffer.push_back( { TokenType::Argument, next } ); 8812 } 8813 } 8814 } 8815 8816 public: 8817 explicit TokenStream( Args const &args ) : TokenStream( args.m_args.begin(), args.m_args.end() ) {} 8818 8819 TokenStream( Iterator it, Iterator itEnd ) : it( it ), itEnd( itEnd ) { 8820 loadBuffer(); 8821 } 8822 8823 explicit operator bool() const { 8824 return !m_tokenBuffer.empty() || it != itEnd; 8825 } 8826 8827 auto count() const -> size_t { return m_tokenBuffer.size() + (itEnd - it); } 8828 8829 auto operator*() const -> Token { 8830 assert( !m_tokenBuffer.empty() ); 8831 return m_tokenBuffer.front(); 8832 } 8833 8834 auto operator->() const -> Token const * { 8835 assert( !m_tokenBuffer.empty() ); 8836 return &m_tokenBuffer.front(); 8837 } 8838 8839 auto operator++() -> TokenStream & { 8840 if( m_tokenBuffer.size() >= 2 ) { 8841 m_tokenBuffer.erase( m_tokenBuffer.begin() ); 8842 } else { 8843 if( it != itEnd ) 8844 ++it; 8845 loadBuffer(); 8846 } 8847 return *this; 8848 } 8849 }; 8850 8851 class ResultBase { 8852 public: 8853 enum Type { 8854 Ok, LogicError, RuntimeError 8855 }; 8856 8857 protected: 8858 ResultBase( Type type ) : m_type( type ) {} 8859 virtual ~ResultBase() = default; 8860 8861 virtual void enforceOk() const = 0; 8862 8863 Type m_type; 8864 }; 8865 8866 template<typename T> 8867 class ResultValueBase : public ResultBase { 8868 public: 8869 auto value() const -> T const & { 8870 enforceOk(); 8871 return m_value; 8872 } 8873 8874 protected: 8875 ResultValueBase( Type type ) : ResultBase( type ) {} 8876 8877 ResultValueBase( ResultValueBase const &other ) : ResultBase( other ) { 8878 if( m_type == ResultBase::Ok ) 8879 new( &m_value ) T( other.m_value ); 8880 } 8881 8882 ResultValueBase( Type, T const &value ) : ResultBase( Ok ) { 8883 new( &m_value ) T( value ); 8884 } 8885 8886 auto operator=( ResultValueBase const &other ) -> ResultValueBase & { 8887 if( m_type == ResultBase::Ok ) 8888 m_value.~T(); 8889 ResultBase::operator=(other); 8890 if( m_type == ResultBase::Ok ) 8891 new( &m_value ) T( other.m_value ); 8892 return *this; 8893 } 8894 8895 ~ResultValueBase() override { 8896 if( m_type == Ok ) 8897 m_value.~T(); 8898 } 8899 8900 union { 8901 T m_value; 8902 }; 8903 }; 8904 8905 template<> 8906 class ResultValueBase<void> : public ResultBase { 8907 protected: 8908 using ResultBase::ResultBase; 8909 }; 8910 8911 template<typename T = void> 8912 class BasicResult : public ResultValueBase<T> { 8913 public: 8914 template<typename U> 8915 explicit BasicResult( BasicResult<U> const &other ) 8916 : ResultValueBase<T>( other.type() ), 8917 m_errorMessage( other.errorMessage() ) 8918 { 8919 assert( type() != ResultBase::Ok ); 8920 } 8921 8922 template<typename U> 8923 static auto ok( U const &value ) -> BasicResult { return { ResultBase::Ok, value }; } 8924 static auto ok() -> BasicResult { return { ResultBase::Ok }; } 8925 static auto logicError( std::string const &message ) -> BasicResult { return { ResultBase::LogicError, message }; } 8926 static auto runtimeError( std::string const &message ) -> BasicResult { return { ResultBase::RuntimeError, message }; } 8927 8928 explicit operator bool() const { return m_type == ResultBase::Ok; } 8929 auto type() const -> ResultBase::Type { return m_type; } 8930 auto errorMessage() const -> std::string { return m_errorMessage; } 8931 8932 protected: 8933 void enforceOk() const override { 8934 8935 // Errors shouldn't reach this point, but if they do 8936 // the actual error message will be in m_errorMessage 8937 assert( m_type != ResultBase::LogicError ); 8938 assert( m_type != ResultBase::RuntimeError ); 8939 if( m_type != ResultBase::Ok ) 8940 std::abort(); 8941 } 8942 8943 std::string m_errorMessage; // Only populated if resultType is an error 8944 8945 BasicResult( ResultBase::Type type, std::string const &message ) 8946 : ResultValueBase<T>(type), 8947 m_errorMessage(message) 8948 { 8949 assert( m_type != ResultBase::Ok ); 8950 } 8951 8952 using ResultValueBase<T>::ResultValueBase; 8953 using ResultBase::m_type; 8954 }; 8955 8956 enum class ParseResultType { 8957 Matched, NoMatch, ShortCircuitAll, ShortCircuitSame 8958 }; 8959 8960 class ParseState { 8961 public: 8962 8963 ParseState( ParseResultType type, TokenStream const &remainingTokens ) 8964 : m_type(type), 8965 m_remainingTokens( remainingTokens ) 8966 {} 8967 8968 auto type() const -> ParseResultType { return m_type; } 8969 auto remainingTokens() const -> TokenStream { return m_remainingTokens; } 8970 8971 private: 8972 ParseResultType m_type; 8973 TokenStream m_remainingTokens; 8974 }; 8975 8976 using Result = BasicResult<void>; 8977 using ParserResult = BasicResult<ParseResultType>; 8978 using InternalParseResult = BasicResult<ParseState>; 8979 8980 struct HelpColumns { 8981 std::string left; 8982 std::string right; 8983 }; 8984 8985 template<typename T> 8986 inline auto convertInto( std::string const &source, T& target ) -> ParserResult { 8987 std::stringstream ss; 8988 ss << source; 8989 ss >> target; 8990 if( ss.fail() ) 8991 return ParserResult::runtimeError( "Unable to convert '" + source + "' to destination type" ); 8992 else 8993 return ParserResult::ok( ParseResultType::Matched ); 8994 } 8995 inline auto convertInto( std::string const &source, std::string& target ) -> ParserResult { 8996 target = source; 8997 return ParserResult::ok( ParseResultType::Matched ); 8998 } 8999 inline auto convertInto( std::string const &source, bool &target ) -> ParserResult { 9000 std::string srcLC = source; 9001 std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( char c ) { return static_cast<char>( std::tolower(c) ); } ); 9002 if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on") 9003 target = true; 9004 else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off") 9005 target = false; 9006 else 9007 return ParserResult::runtimeError( "Expected a boolean value but did not recognise: '" + source + "'" ); 9008 return ParserResult::ok( ParseResultType::Matched ); 9009 } 9010 #ifdef CLARA_CONFIG_OPTIONAL_TYPE 9011 template<typename T> 9012 inline auto convertInto( std::string const &source, CLARA_CONFIG_OPTIONAL_TYPE<T>& target ) -> ParserResult { 9013 T temp; 9014 auto result = convertInto( source, temp ); 9015 if( result ) 9016 target = std::move(temp); 9017 return result; 9018 } 9019 #endif // CLARA_CONFIG_OPTIONAL_TYPE 9020 9021 struct NonCopyable { 9022 NonCopyable() = default; 9023 NonCopyable( NonCopyable const & ) = delete; 9024 NonCopyable( NonCopyable && ) = delete; 9025 NonCopyable &operator=( NonCopyable const & ) = delete; 9026 NonCopyable &operator=( NonCopyable && ) = delete; 9027 }; 9028 9029 struct BoundRef : NonCopyable { 9030 virtual ~BoundRef() = default; 9031 virtual auto isContainer() const -> bool { return false; } 9032 virtual auto isFlag() const -> bool { return false; } 9033 }; 9034 struct BoundValueRefBase : BoundRef { 9035 virtual auto setValue( std::string const &arg ) -> ParserResult = 0; 9036 }; 9037 struct BoundFlagRefBase : BoundRef { 9038 virtual auto setFlag( bool flag ) -> ParserResult = 0; 9039 virtual auto isFlag() const -> bool { return true; } 9040 }; 9041 9042 template<typename T> 9043 struct BoundValueRef : BoundValueRefBase { 9044 T &m_ref; 9045 9046 explicit BoundValueRef( T &ref ) : m_ref( ref ) {} 9047 9048 auto setValue( std::string const &arg ) -> ParserResult override { 9049 return convertInto( arg, m_ref ); 9050 } 9051 }; 9052 9053 template<typename T> 9054 struct BoundValueRef<std::vector<T>> : BoundValueRefBase { 9055 std::vector<T> &m_ref; 9056 9057 explicit BoundValueRef( std::vector<T> &ref ) : m_ref( ref ) {} 9058 9059 auto isContainer() const -> bool override { return true; } 9060 9061 auto setValue( std::string const &arg ) -> ParserResult override { 9062 T temp; 9063 auto result = convertInto( arg, temp ); 9064 if( result ) 9065 m_ref.push_back( temp ); 9066 return result; 9067 } 9068 }; 9069 9070 struct BoundFlagRef : BoundFlagRefBase { 9071 bool &m_ref; 9072 9073 explicit BoundFlagRef( bool &ref ) : m_ref( ref ) {} 9074 9075 auto setFlag( bool flag ) -> ParserResult override { 9076 m_ref = flag; 9077 return ParserResult::ok( ParseResultType::Matched ); 9078 } 9079 }; 9080 9081 template<typename ReturnType> 9082 struct LambdaInvoker { 9083 static_assert( std::is_same<ReturnType, ParserResult>::value, "Lambda must return void or clara::ParserResult" ); 9084 9085 template<typename L, typename ArgType> 9086 static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult { 9087 return lambda( arg ); 9088 } 9089 }; 9090 9091 template<> 9092 struct LambdaInvoker<void> { 9093 template<typename L, typename ArgType> 9094 static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult { 9095 lambda( arg ); 9096 return ParserResult::ok( ParseResultType::Matched ); 9097 } 9098 }; 9099 9100 template<typename ArgType, typename L> 9101 inline auto invokeLambda( L const &lambda, std::string const &arg ) -> ParserResult { 9102 ArgType temp{}; 9103 auto result = convertInto( arg, temp ); 9104 return !result 9105 ? result 9106 : LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( lambda, temp ); 9107 } 9108 9109 template<typename L> 9110 struct BoundLambda : BoundValueRefBase { 9111 L m_lambda; 9112 9113 static_assert( UnaryLambdaTraits<L>::isValid, "Supplied lambda must take exactly one argument" ); 9114 explicit BoundLambda( L const &lambda ) : m_lambda( lambda ) {} 9115 9116 auto setValue( std::string const &arg ) -> ParserResult override { 9117 return invokeLambda<typename UnaryLambdaTraits<L>::ArgType>( m_lambda, arg ); 9118 } 9119 }; 9120 9121 template<typename L> 9122 struct BoundFlagLambda : BoundFlagRefBase { 9123 L m_lambda; 9124 9125 static_assert( UnaryLambdaTraits<L>::isValid, "Supplied lambda must take exactly one argument" ); 9126 static_assert( std::is_same<typename UnaryLambdaTraits<L>::ArgType, bool>::value, "flags must be boolean" ); 9127 9128 explicit BoundFlagLambda( L const &lambda ) : m_lambda( lambda ) {} 9129 9130 auto setFlag( bool flag ) -> ParserResult override { 9131 return LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( m_lambda, flag ); 9132 } 9133 }; 9134 9135 enum class Optionality { Optional, Required }; 9136 9137 struct Parser; 9138 9139 class ParserBase { 9140 public: 9141 virtual ~ParserBase() = default; 9142 virtual auto validate() const -> Result { return Result::ok(); } 9143 virtual auto parse( std::string const& exeName, TokenStream const &tokens) const -> InternalParseResult = 0; 9144 virtual auto cardinality() const -> size_t { return 1; } 9145 9146 auto parse( Args const &args ) const -> InternalParseResult { 9147 return parse( args.exeName(), TokenStream( args ) ); 9148 } 9149 }; 9150 9151 template<typename DerivedT> 9152 class ComposableParserImpl : public ParserBase { 9153 public: 9154 template<typename T> 9155 auto operator|( T const &other ) const -> Parser; 9156 9157 template<typename T> 9158 auto operator+( T const &other ) const -> Parser; 9159 }; 9160 9161 // Common code and state for Args and Opts 9162 template<typename DerivedT> 9163 class ParserRefImpl : public ComposableParserImpl<DerivedT> { 9164 protected: 9165 Optionality m_optionality = Optionality::Optional; 9166 std::shared_ptr<BoundRef> m_ref; 9167 std::string m_hint; 9168 std::string m_description; 9169 9170 explicit ParserRefImpl( std::shared_ptr<BoundRef> const &ref ) : m_ref( ref ) {} 9171 9172 public: 9173 template<typename T> 9174 ParserRefImpl( T &ref, std::string const &hint ) 9175 : m_ref( std::make_shared<BoundValueRef<T>>( ref ) ), 9176 m_hint( hint ) 9177 {} 9178 9179 template<typename LambdaT> 9180 ParserRefImpl( LambdaT const &ref, std::string const &hint ) 9181 : m_ref( std::make_shared<BoundLambda<LambdaT>>( ref ) ), 9182 m_hint(hint) 9183 {} 9184 9185 auto operator()( std::string const &description ) -> DerivedT & { 9186 m_description = description; 9187 return static_cast<DerivedT &>( *this ); 9188 } 9189 9190 auto optional() -> DerivedT & { 9191 m_optionality = Optionality::Optional; 9192 return static_cast<DerivedT &>( *this ); 9193 }; 9194 9195 auto required() -> DerivedT & { 9196 m_optionality = Optionality::Required; 9197 return static_cast<DerivedT &>( *this ); 9198 }; 9199 9200 auto isOptional() const -> bool { 9201 return m_optionality == Optionality::Optional; 9202 } 9203 9204 auto cardinality() const -> size_t override { 9205 if( m_ref->isContainer() ) 9206 return 0; 9207 else 9208 return 1; 9209 } 9210 9211 auto hint() const -> std::string { return m_hint; } 9212 }; 9213 9214 class ExeName : public ComposableParserImpl<ExeName> { 9215 std::shared_ptr<std::string> m_name; 9216 std::shared_ptr<BoundValueRefBase> m_ref; 9217 9218 template<typename LambdaT> 9219 static auto makeRef(LambdaT const &lambda) -> std::shared_ptr<BoundValueRefBase> { 9220 return std::make_shared<BoundLambda<LambdaT>>( lambda) ; 9221 } 9222 9223 public: 9224 ExeName() : m_name( std::make_shared<std::string>( "<executable>" ) ) {} 9225 9226 explicit ExeName( std::string &ref ) : ExeName() { 9227 m_ref = std::make_shared<BoundValueRef<std::string>>( ref ); 9228 } 9229 9230 template<typename LambdaT> 9231 explicit ExeName( LambdaT const& lambda ) : ExeName() { 9232 m_ref = std::make_shared<BoundLambda<LambdaT>>( lambda ); 9233 } 9234 9235 // The exe name is not parsed out of the normal tokens, but is handled specially 9236 auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override { 9237 return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) ); 9238 } 9239 9240 auto name() const -> std::string { return *m_name; } 9241 auto set( std::string const& newName ) -> ParserResult { 9242 9243 auto lastSlash = newName.find_last_of( "\\/" ); 9244 auto filename = ( lastSlash == std::string::npos ) 9245 ? newName 9246 : newName.substr( lastSlash+1 ); 9247 9248 *m_name = filename; 9249 if( m_ref ) 9250 return m_ref->setValue( filename ); 9251 else 9252 return ParserResult::ok( ParseResultType::Matched ); 9253 } 9254 }; 9255 9256 class Arg : public ParserRefImpl<Arg> { 9257 public: 9258 using ParserRefImpl::ParserRefImpl; 9259 9260 auto parse( std::string const &, TokenStream const &tokens ) const -> InternalParseResult override { 9261 auto validationResult = validate(); 9262 if( !validationResult ) 9263 return InternalParseResult( validationResult ); 9264 9265 auto remainingTokens = tokens; 9266 auto const &token = *remainingTokens; 9267 if( token.type != TokenType::Argument ) 9268 return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) ); 9269 9270 assert( !m_ref->isFlag() ); 9271 auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() ); 9272 9273 auto result = valueRef->setValue( remainingTokens->token ); 9274 if( !result ) 9275 return InternalParseResult( result ); 9276 else 9277 return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) ); 9278 } 9279 }; 9280 9281 inline auto normaliseOpt( std::string const &optName ) -> std::string { 9282 #ifdef CATCH_PLATFORM_WINDOWS 9283 if( optName[0] == '/' ) 9284 return "-" + optName.substr( 1 ); 9285 else 9286 #endif 9287 return optName; 9288 } 9289 9290 class Opt : public ParserRefImpl<Opt> { 9291 protected: 9292 std::vector<std::string> m_optNames; 9293 9294 public: 9295 template<typename LambdaT> 9296 explicit Opt( LambdaT const &ref ) : ParserRefImpl( std::make_shared<BoundFlagLambda<LambdaT>>( ref ) ) {} 9297 9298 explicit Opt( bool &ref ) : ParserRefImpl( std::make_shared<BoundFlagRef>( ref ) ) {} 9299 9300 template<typename LambdaT> 9301 Opt( LambdaT const &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {} 9302 9303 template<typename T> 9304 Opt( T &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {} 9305 9306 auto operator[]( std::string const &optName ) -> Opt & { 9307 m_optNames.push_back( optName ); 9308 return *this; 9309 } 9310 9311 auto getHelpColumns() const -> std::vector<HelpColumns> { 9312 std::ostringstream oss; 9313 bool first = true; 9314 for( auto const &opt : m_optNames ) { 9315 if (first) 9316 first = false; 9317 else 9318 oss << ", "; 9319 oss << opt; 9320 } 9321 if( !m_hint.empty() ) 9322 oss << " <" << m_hint << ">"; 9323 return { { oss.str(), m_description } }; 9324 } 9325 9326 auto isMatch( std::string const &optToken ) const -> bool { 9327 auto normalisedToken = normaliseOpt( optToken ); 9328 for( auto const &name : m_optNames ) { 9329 if( normaliseOpt( name ) == normalisedToken ) 9330 return true; 9331 } 9332 return false; 9333 } 9334 9335 using ParserBase::parse; 9336 9337 auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override { 9338 auto validationResult = validate(); 9339 if( !validationResult ) 9340 return InternalParseResult( validationResult ); 9341 9342 auto remainingTokens = tokens; 9343 if( remainingTokens && remainingTokens->type == TokenType::Option ) { 9344 auto const &token = *remainingTokens; 9345 if( isMatch(token.token ) ) { 9346 if( m_ref->isFlag() ) { 9347 auto flagRef = static_cast<detail::BoundFlagRefBase*>( m_ref.get() ); 9348 auto result = flagRef->setFlag( true ); 9349 if( !result ) 9350 return InternalParseResult( result ); 9351 if( result.value() == ParseResultType::ShortCircuitAll ) 9352 return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) ); 9353 } else { 9354 auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() ); 9355 ++remainingTokens; 9356 if( !remainingTokens ) 9357 return InternalParseResult::runtimeError( "Expected argument following " + token.token ); 9358 auto const &argToken = *remainingTokens; 9359 if( argToken.type != TokenType::Argument ) 9360 return InternalParseResult::runtimeError( "Expected argument following " + token.token ); 9361 auto result = valueRef->setValue( argToken.token ); 9362 if( !result ) 9363 return InternalParseResult( result ); 9364 if( result.value() == ParseResultType::ShortCircuitAll ) 9365 return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) ); 9366 } 9367 return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) ); 9368 } 9369 } 9370 return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) ); 9371 } 9372 9373 auto validate() const -> Result override { 9374 if( m_optNames.empty() ) 9375 return Result::logicError( "No options supplied to Opt" ); 9376 for( auto const &name : m_optNames ) { 9377 if( name.empty() ) 9378 return Result::logicError( "Option name cannot be empty" ); 9379 #ifdef CATCH_PLATFORM_WINDOWS 9380 if( name[0] != '-' && name[0] != '/' ) 9381 return Result::logicError( "Option name must begin with '-' or '/'" ); 9382 #else 9383 if( name[0] != '-' ) 9384 return Result::logicError( "Option name must begin with '-'" ); 9385 #endif 9386 } 9387 return ParserRefImpl::validate(); 9388 } 9389 }; 9390 9391 struct Help : Opt { 9392 Help( bool &showHelpFlag ) 9393 : Opt([&]( bool flag ) { 9394 showHelpFlag = flag; 9395 return ParserResult::ok( ParseResultType::ShortCircuitAll ); 9396 }) 9397 { 9398 static_cast<Opt &>( *this ) 9399 ("display usage information") 9400 ["-?"]["-h"]["--help"] 9401 .optional(); 9402 } 9403 }; 9404 9405 struct Parser : ParserBase { 9406 9407 mutable ExeName m_exeName; 9408 std::vector<Opt> m_options; 9409 std::vector<Arg> m_args; 9410 9411 auto operator|=( ExeName const &exeName ) -> Parser & { 9412 m_exeName = exeName; 9413 return *this; 9414 } 9415 9416 auto operator|=( Arg const &arg ) -> Parser & { 9417 m_args.push_back(arg); 9418 return *this; 9419 } 9420 9421 auto operator|=( Opt const &opt ) -> Parser & { 9422 m_options.push_back(opt); 9423 return *this; 9424 } 9425 9426 auto operator|=( Parser const &other ) -> Parser & { 9427 m_options.insert(m_options.end(), other.m_options.begin(), other.m_options.end()); 9428 m_args.insert(m_args.end(), other.m_args.begin(), other.m_args.end()); 9429 return *this; 9430 } 9431 9432 template<typename T> 9433 auto operator|( T const &other ) const -> Parser { 9434 return Parser( *this ) |= other; 9435 } 9436 9437 // Forward deprecated interface with '+' instead of '|' 9438 template<typename T> 9439 auto operator+=( T const &other ) -> Parser & { return operator|=( other ); } 9440 template<typename T> 9441 auto operator+( T const &other ) const -> Parser { return operator|( other ); } 9442 9443 auto getHelpColumns() const -> std::vector<HelpColumns> { 9444 std::vector<HelpColumns> cols; 9445 for (auto const &o : m_options) { 9446 auto childCols = o.getHelpColumns(); 9447 cols.insert( cols.end(), childCols.begin(), childCols.end() ); 9448 } 9449 return cols; 9450 } 9451 9452 void writeToStream( std::ostream &os ) const { 9453 if (!m_exeName.name().empty()) { 9454 os << "usage:\n" << " " << m_exeName.name() << " "; 9455 bool required = true, first = true; 9456 for( auto const &arg : m_args ) { 9457 if (first) 9458 first = false; 9459 else 9460 os << " "; 9461 if( arg.isOptional() && required ) { 9462 os << "["; 9463 required = false; 9464 } 9465 os << "<" << arg.hint() << ">"; 9466 if( arg.cardinality() == 0 ) 9467 os << " ... "; 9468 } 9469 if( !required ) 9470 os << "]"; 9471 if( !m_options.empty() ) 9472 os << " options"; 9473 os << "\n\nwhere options are:" << std::endl; 9474 } 9475 9476 auto rows = getHelpColumns(); 9477 size_t consoleWidth = CATCH_CLARA_CONFIG_CONSOLE_WIDTH; 9478 size_t optWidth = 0; 9479 for( auto const &cols : rows ) 9480 optWidth = (std::max)(optWidth, cols.left.size() + 2); 9481 9482 optWidth = (std::min)(optWidth, consoleWidth/2); 9483 9484 for( auto const &cols : rows ) { 9485 auto row = 9486 TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) + 9487 TextFlow::Spacer(4) + 9488 TextFlow::Column( cols.right ).width( consoleWidth - 7 - optWidth ); 9489 os << row << std::endl; 9490 } 9491 } 9492 9493 friend auto operator<<( std::ostream &os, Parser const &parser ) -> std::ostream& { 9494 parser.writeToStream( os ); 9495 return os; 9496 } 9497 9498 auto validate() const -> Result override { 9499 for( auto const &opt : m_options ) { 9500 auto result = opt.validate(); 9501 if( !result ) 9502 return result; 9503 } 9504 for( auto const &arg : m_args ) { 9505 auto result = arg.validate(); 9506 if( !result ) 9507 return result; 9508 } 9509 return Result::ok(); 9510 } 9511 9512 using ParserBase::parse; 9513 9514 auto parse( std::string const& exeName, TokenStream const &tokens ) const -> InternalParseResult override { 9515 9516 struct ParserInfo { 9517 ParserBase const* parser = nullptr; 9518 size_t count = 0; 9519 }; 9520 const size_t totalParsers = m_options.size() + m_args.size(); 9521 assert( totalParsers < 512 ); 9522 // ParserInfo parseInfos[totalParsers]; // <-- this is what we really want to do 9523 ParserInfo parseInfos[512]; 9524 9525 { 9526 size_t i = 0; 9527 for (auto const &opt : m_options) parseInfos[i++].parser = &opt; 9528 for (auto const &arg : m_args) parseInfos[i++].parser = &arg; 9529 } 9530 9531 m_exeName.set( exeName ); 9532 9533 auto result = InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) ); 9534 while( result.value().remainingTokens() ) { 9535 bool tokenParsed = false; 9536 9537 for( size_t i = 0; i < totalParsers; ++i ) { 9538 auto& parseInfo = parseInfos[i]; 9539 if( parseInfo.parser->cardinality() == 0 || parseInfo.count < parseInfo.parser->cardinality() ) { 9540 result = parseInfo.parser->parse(exeName, result.value().remainingTokens()); 9541 if (!result) 9542 return result; 9543 if (result.value().type() != ParseResultType::NoMatch) { 9544 tokenParsed = true; 9545 ++parseInfo.count; 9546 break; 9547 } 9548 } 9549 } 9550 9551 if( result.value().type() == ParseResultType::ShortCircuitAll ) 9552 return result; 9553 if( !tokenParsed ) 9554 return InternalParseResult::runtimeError( "Unrecognised token: " + result.value().remainingTokens()->token ); 9555 } 9556 // !TBD Check missing required options 9557 return result; 9558 } 9559 }; 9560 9561 template<typename DerivedT> 9562 template<typename T> 9563 auto ComposableParserImpl<DerivedT>::operator|( T const &other ) const -> Parser { 9564 return Parser() | static_cast<DerivedT const &>( *this ) | other; 9565 } 9566 } // namespace detail 9567 9568 // A Combined parser 9569 using detail::Parser; 9570 9571 // A parser for options 9572 using detail::Opt; 9573 9574 // A parser for arguments 9575 using detail::Arg; 9576 9577 // Wrapper for argc, argv from main() 9578 using detail::Args; 9579 9580 // Specifies the name of the executable 9581 using detail::ExeName; 9582 9583 // Convenience wrapper for option parser that specifies the help option 9584 using detail::Help; 9585 9586 // enum of result types from a parse 9587 using detail::ParseResultType; 9588 9589 // Result type for parser operation 9590 using detail::ParserResult; 9591 9592 }} // namespace Catch::clara 9593 9594 // end clara.hpp 9595 #ifdef __clang__ 9596 #pragma clang diagnostic pop 9597 #endif 9598 9599 // Restore Clara's value for console width, if present 9600 #ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH 9601 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH 9602 #undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH 9603 #endif 9604 9605 // end catch_clara.h 9606 namespace Catch { 9607 9608 clara::Parser makeCommandLineParser( ConfigData& config ); 9609 9610 } // end namespace Catch 9611 9612 // end catch_commandline.h 9613 #include <fstream> 9614 #include <ctime> 9615 9616 namespace Catch { 9617 9618 clara::Parser makeCommandLineParser( ConfigData& config ) { 9619 9620 using namespace clara; 9621 9622 auto const setWarning = [&]( std::string const& warning ) { 9623 auto warningSet = [&]() { 9624 if( warning == "NoAssertions" ) 9625 return WarnAbout::NoAssertions; 9626 9627 if ( warning == "NoTests" ) 9628 return WarnAbout::NoTests; 9629 9630 return WarnAbout::Nothing; 9631 }(); 9632 9633 if (warningSet == WarnAbout::Nothing) 9634 return ParserResult::runtimeError( "Unrecognised warning: '" + warning + "'" ); 9635 config.warnings = static_cast<WarnAbout::What>( config.warnings | warningSet ); 9636 return ParserResult::ok( ParseResultType::Matched ); 9637 }; 9638 auto const loadTestNamesFromFile = [&]( std::string const& filename ) { 9639 std::ifstream f( filename.c_str() ); 9640 if( !f.is_open() ) 9641 return ParserResult::runtimeError( "Unable to load input file: '" + filename + "'" ); 9642 9643 std::string line; 9644 while( std::getline( f, line ) ) { 9645 line = trim(line); 9646 if( !line.empty() && !startsWith( line, '#' ) ) { 9647 if( !startsWith( line, '"' ) ) 9648 line = '"' + line + '"'; 9649 config.testsOrTags.push_back( line ); 9650 config.testsOrTags.push_back( "," ); 9651 9652 } 9653 } 9654 //Remove comma in the end 9655 if(!config.testsOrTags.empty()) 9656 config.testsOrTags.erase( config.testsOrTags.end()-1 ); 9657 9658 return ParserResult::ok( ParseResultType::Matched ); 9659 }; 9660 auto const setTestOrder = [&]( std::string const& order ) { 9661 if( startsWith( "declared", order ) ) 9662 config.runOrder = RunTests::InDeclarationOrder; 9663 else if( startsWith( "lexical", order ) ) 9664 config.runOrder = RunTests::InLexicographicalOrder; 9665 else if( startsWith( "random", order ) ) 9666 config.runOrder = RunTests::InRandomOrder; 9667 else 9668 return clara::ParserResult::runtimeError( "Unrecognised ordering: '" + order + "'" ); 9669 return ParserResult::ok( ParseResultType::Matched ); 9670 }; 9671 auto const setRngSeed = [&]( std::string const& seed ) { 9672 if( seed != "time" ) 9673 return clara::detail::convertInto( seed, config.rngSeed ); 9674 config.rngSeed = static_cast<unsigned int>( std::time(nullptr) ); 9675 return ParserResult::ok( ParseResultType::Matched ); 9676 }; 9677 auto const setColourUsage = [&]( std::string const& useColour ) { 9678 auto mode = toLower( useColour ); 9679 9680 if( mode == "yes" ) 9681 config.useColour = UseColour::Yes; 9682 else if( mode == "no" ) 9683 config.useColour = UseColour::No; 9684 else if( mode == "auto" ) 9685 config.useColour = UseColour::Auto; 9686 else 9687 return ParserResult::runtimeError( "colour mode must be one of: auto, yes or no. '" + useColour + "' not recognised" ); 9688 return ParserResult::ok( ParseResultType::Matched ); 9689 }; 9690 auto const setWaitForKeypress = [&]( std::string const& keypress ) { 9691 auto keypressLc = toLower( keypress ); 9692 if( keypressLc == "start" ) 9693 config.waitForKeypress = WaitForKeypress::BeforeStart; 9694 else if( keypressLc == "exit" ) 9695 config.waitForKeypress = WaitForKeypress::BeforeExit; 9696 else if( keypressLc == "both" ) 9697 config.waitForKeypress = WaitForKeypress::BeforeStartAndExit; 9698 else 9699 return ParserResult::runtimeError( "keypress argument must be one of: start, exit or both. '" + keypress + "' not recognised" ); 9700 return ParserResult::ok( ParseResultType::Matched ); 9701 }; 9702 auto const setVerbosity = [&]( std::string const& verbosity ) { 9703 auto lcVerbosity = toLower( verbosity ); 9704 if( lcVerbosity == "quiet" ) 9705 config.verbosity = Verbosity::Quiet; 9706 else if( lcVerbosity == "normal" ) 9707 config.verbosity = Verbosity::Normal; 9708 else if( lcVerbosity == "high" ) 9709 config.verbosity = Verbosity::High; 9710 else 9711 return ParserResult::runtimeError( "Unrecognised verbosity, '" + verbosity + "'" ); 9712 return ParserResult::ok( ParseResultType::Matched ); 9713 }; 9714 auto const setReporter = [&]( std::string const& reporter ) { 9715 IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); 9716 9717 auto lcReporter = toLower( reporter ); 9718 auto result = factories.find( lcReporter ); 9719 9720 if( factories.end() != result ) 9721 config.reporterName = lcReporter; 9722 else 9723 return ParserResult::runtimeError( "Unrecognized reporter, '" + reporter + "'. Check available with --list-reporters" ); 9724 return ParserResult::ok( ParseResultType::Matched ); 9725 }; 9726 9727 auto cli 9728 = ExeName( config.processName ) 9729 | Help( config.showHelp ) 9730 | Opt( config.listTests ) 9731 ["-l"]["--list-tests"] 9732 ( "list all/matching test cases" ) 9733 | Opt( config.listTags ) 9734 ["-t"]["--list-tags"] 9735 ( "list all/matching tags" ) 9736 | Opt( config.showSuccessfulTests ) 9737 ["-s"]["--success"] 9738 ( "include successful tests in output" ) 9739 | Opt( config.shouldDebugBreak ) 9740 ["-b"]["--break"] 9741 ( "break into debugger on failure" ) 9742 | Opt( config.noThrow ) 9743 ["-e"]["--nothrow"] 9744 ( "skip exception tests" ) 9745 | Opt( config.showInvisibles ) 9746 ["-i"]["--invisibles"] 9747 ( "show invisibles (tabs, newlines)" ) 9748 | Opt( config.outputFilename, "filename" ) 9749 ["-o"]["--out"] 9750 ( "output filename" ) 9751 | Opt( setReporter, "name" ) 9752 ["-r"]["--reporter"] 9753 ( "reporter to use (defaults to console)" ) 9754 | Opt( config.name, "name" ) 9755 ["-n"]["--name"] 9756 ( "suite name" ) 9757 | Opt( [&]( bool ){ config.abortAfter = 1; } ) 9758 ["-a"]["--abort"] 9759 ( "abort at first failure" ) 9760 | Opt( [&]( int x ){ config.abortAfter = x; }, "no. failures" ) 9761 ["-x"]["--abortx"] 9762 ( "abort after x failures" ) 9763 | Opt( setWarning, "warning name" ) 9764 ["-w"]["--warn"] 9765 ( "enable warnings" ) 9766 | Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" ) 9767 ["-d"]["--durations"] 9768 ( "show test durations" ) 9769 | Opt( loadTestNamesFromFile, "filename" ) 9770 ["-f"]["--input-file"] 9771 ( "load test names to run from a file" ) 9772 | Opt( config.filenamesAsTags ) 9773 ["-#"]["--filenames-as-tags"] 9774 ( "adds a tag for the filename" ) 9775 | Opt( config.sectionsToRun, "section name" ) 9776 ["-c"]["--section"] 9777 ( "specify section to run" ) 9778 | Opt( setVerbosity, "quiet|normal|high" ) 9779 ["-v"]["--verbosity"] 9780 ( "set output verbosity" ) 9781 | Opt( config.listTestNamesOnly ) 9782 ["--list-test-names-only"] 9783 ( "list all/matching test cases names only" ) 9784 | Opt( config.listReporters ) 9785 ["--list-reporters"] 9786 ( "list all reporters" ) 9787 | Opt( setTestOrder, "decl|lex|rand" ) 9788 ["--order"] 9789 ( "test case order (defaults to decl)" ) 9790 | Opt( setRngSeed, "'time'|number" ) 9791 ["--rng-seed"] 9792 ( "set a specific seed for random numbers" ) 9793 | Opt( setColourUsage, "yes|no" ) 9794 ["--use-colour"] 9795 ( "should output be colourised" ) 9796 | Opt( config.libIdentify ) 9797 ["--libidentify"] 9798 ( "report name and version according to libidentify standard" ) 9799 | Opt( setWaitForKeypress, "start|exit|both" ) 9800 ["--wait-for-keypress"] 9801 ( "waits for a keypress before exiting" ) 9802 | Opt( config.benchmarkSamples, "samples" ) 9803 ["--benchmark-samples"] 9804 ( "number of samples to collect (default: 100)" ) 9805 | Opt( config.benchmarkResamples, "resamples" ) 9806 ["--benchmark-resamples"] 9807 ( "number of resamples for the bootstrap (default: 100000)" ) 9808 | Opt( config.benchmarkConfidenceInterval, "confidence interval" ) 9809 ["--benchmark-confidence-interval"] 9810 ( "confidence interval for the bootstrap (between 0 and 1, default: 0.95)" ) 9811 | Opt( config.benchmarkNoAnalysis ) 9812 ["--benchmark-no-analysis"] 9813 ( "perform only measurements; do not perform any analysis" ) 9814 | Arg( config.testsOrTags, "test name|pattern|tags" ) 9815 ( "which test or tests to use" ); 9816 9817 return cli; 9818 } 9819 9820 } // end namespace Catch 9821 // end catch_commandline.cpp 9822 // start catch_common.cpp 9823 9824 #include <cstring> 9825 #include <ostream> 9826 9827 namespace Catch { 9828 9829 bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const noexcept { 9830 return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0); 9831 } 9832 bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const noexcept { 9833 // We can assume that the same file will usually have the same pointer. 9834 // Thus, if the pointers are the same, there is no point in calling the strcmp 9835 return line < other.line || ( line == other.line && file != other.file && (std::strcmp(file, other.file) < 0)); 9836 } 9837 9838 std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { 9839 #ifndef __GNUG__ 9840 os << info.file << '(' << info.line << ')'; 9841 #else 9842 os << info.file << ':' << info.line; 9843 #endif 9844 return os; 9845 } 9846 9847 std::string StreamEndStop::operator+() const { 9848 return std::string(); 9849 } 9850 9851 NonCopyable::NonCopyable() = default; 9852 NonCopyable::~NonCopyable() = default; 9853 9854 } 9855 // end catch_common.cpp 9856 // start catch_config.cpp 9857 9858 namespace Catch { 9859 9860 Config::Config( ConfigData const& data ) 9861 : m_data( data ), 9862 m_stream( openStream() ) 9863 { 9864 // We need to trim filter specs to avoid trouble with superfluous 9865 // whitespace (esp. important for bdd macros, as those are manually 9866 // aligned with whitespace). 9867 9868 for (auto& elem : m_data.testsOrTags) { 9869 elem = trim(elem); 9870 } 9871 for (auto& elem : m_data.sectionsToRun) { 9872 elem = trim(elem); 9873 } 9874 9875 TestSpecParser parser(ITagAliasRegistry::get()); 9876 if (!m_data.testsOrTags.empty()) { 9877 m_hasTestFilters = true; 9878 for (auto const& testOrTags : m_data.testsOrTags) { 9879 parser.parse(testOrTags); 9880 } 9881 } 9882 m_testSpec = parser.testSpec(); 9883 } 9884 9885 std::string const& Config::getFilename() const { 9886 return m_data.outputFilename ; 9887 } 9888 9889 bool Config::listTests() const { return m_data.listTests; } 9890 bool Config::listTestNamesOnly() const { return m_data.listTestNamesOnly; } 9891 bool Config::listTags() const { return m_data.listTags; } 9892 bool Config::listReporters() const { return m_data.listReporters; } 9893 9894 std::string Config::getProcessName() const { return m_data.processName; } 9895 std::string const& Config::getReporterName() const { return m_data.reporterName; } 9896 9897 std::vector<std::string> const& Config::getTestsOrTags() const { return m_data.testsOrTags; } 9898 std::vector<std::string> const& Config::getSectionsToRun() const { return m_data.sectionsToRun; } 9899 9900 TestSpec const& Config::testSpec() const { return m_testSpec; } 9901 bool Config::hasTestFilters() const { return m_hasTestFilters; } 9902 9903 bool Config::showHelp() const { return m_data.showHelp; } 9904 9905 // IConfig interface 9906 bool Config::allowThrows() const { return !m_data.noThrow; } 9907 std::ostream& Config::stream() const { return m_stream->stream(); } 9908 std::string Config::name() const { return m_data.name.empty() ? m_data.processName : m_data.name; } 9909 bool Config::includeSuccessfulResults() const { return m_data.showSuccessfulTests; } 9910 bool Config::warnAboutMissingAssertions() const { return !!(m_data.warnings & WarnAbout::NoAssertions); } 9911 bool Config::warnAboutNoTests() const { return !!(m_data.warnings & WarnAbout::NoTests); } 9912 ShowDurations::OrNot Config::showDurations() const { return m_data.showDurations; } 9913 RunTests::InWhatOrder Config::runOrder() const { return m_data.runOrder; } 9914 unsigned int Config::rngSeed() const { return m_data.rngSeed; } 9915 UseColour::YesOrNo Config::useColour() const { return m_data.useColour; } 9916 bool Config::shouldDebugBreak() const { return m_data.shouldDebugBreak; } 9917 int Config::abortAfter() const { return m_data.abortAfter; } 9918 bool Config::showInvisibles() const { return m_data.showInvisibles; } 9919 Verbosity Config::verbosity() const { return m_data.verbosity; } 9920 9921 bool Config::benchmarkNoAnalysis() const { return m_data.benchmarkNoAnalysis; } 9922 int Config::benchmarkSamples() const { return m_data.benchmarkSamples; } 9923 double Config::benchmarkConfidenceInterval() const { return m_data.benchmarkConfidenceInterval; } 9924 unsigned int Config::benchmarkResamples() const { return m_data.benchmarkResamples; } 9925 9926 IStream const* Config::openStream() { 9927 return Catch::makeStream(m_data.outputFilename); 9928 } 9929 9930 } // end namespace Catch 9931 // end catch_config.cpp 9932 // start catch_console_colour.cpp 9933 9934 #if defined(__clang__) 9935 # pragma clang diagnostic push 9936 # pragma clang diagnostic ignored "-Wexit-time-destructors" 9937 #endif 9938 9939 // start catch_errno_guard.h 9940 9941 namespace Catch { 9942 9943 class ErrnoGuard { 9944 public: 9945 ErrnoGuard(); 9946 ~ErrnoGuard(); 9947 private: 9948 int m_oldErrno; 9949 }; 9950 9951 } 9952 9953 // end catch_errno_guard.h 9954 #include <sstream> 9955 9956 namespace Catch { 9957 namespace { 9958 9959 struct IColourImpl { 9960 virtual ~IColourImpl() = default; 9961 virtual void use( Colour::Code _colourCode ) = 0; 9962 }; 9963 9964 struct NoColourImpl : IColourImpl { 9965 void use( Colour::Code ) {} 9966 9967 static IColourImpl* instance() { 9968 static NoColourImpl s_instance; 9969 return &s_instance; 9970 } 9971 }; 9972 9973 } // anon namespace 9974 } // namespace Catch 9975 9976 #if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI ) 9977 # ifdef CATCH_PLATFORM_WINDOWS 9978 # define CATCH_CONFIG_COLOUR_WINDOWS 9979 # else 9980 # define CATCH_CONFIG_COLOUR_ANSI 9981 # endif 9982 #endif 9983 9984 #if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) ///////////////////////////////////////// 9985 9986 namespace Catch { 9987 namespace { 9988 9989 class Win32ColourImpl : public IColourImpl { 9990 public: 9991 Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) ) 9992 { 9993 CONSOLE_SCREEN_BUFFER_INFO csbiInfo; 9994 GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo ); 9995 originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY ); 9996 originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ); 9997 } 9998 9999 void use( Colour::Code _colourCode ) override { 10000 switch( _colourCode ) { 10001 case Colour::None: return setTextAttribute( originalForegroundAttributes ); 10002 case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); 10003 case Colour::Red: return setTextAttribute( FOREGROUND_RED ); 10004 case Colour::Green: return setTextAttribute( FOREGROUND_GREEN ); 10005 case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE ); 10006 case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN ); 10007 case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN ); 10008 case Colour::Grey: return setTextAttribute( 0 ); 10009 10010 case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY ); 10011 case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED ); 10012 case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN ); 10013 case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); 10014 case Colour::BrightYellow: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN ); 10015 10016 case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" ); 10017 10018 default: 10019 CATCH_ERROR( "Unknown colour requested" ); 10020 } 10021 } 10022 10023 private: 10024 void setTextAttribute( WORD _textAttribute ) { 10025 SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes ); 10026 } 10027 HANDLE stdoutHandle; 10028 WORD originalForegroundAttributes; 10029 WORD originalBackgroundAttributes; 10030 }; 10031 10032 IColourImpl* platformColourInstance() { 10033 static Win32ColourImpl s_instance; 10034 10035 IConfigPtr config = getCurrentContext().getConfig(); 10036 UseColour::YesOrNo colourMode = config 10037 ? config->useColour() 10038 : UseColour::Auto; 10039 if( colourMode == UseColour::Auto ) 10040 colourMode = UseColour::Yes; 10041 return colourMode == UseColour::Yes 10042 ? &s_instance 10043 : NoColourImpl::instance(); 10044 } 10045 10046 } // end anon namespace 10047 } // end namespace Catch 10048 10049 #elif defined( CATCH_CONFIG_COLOUR_ANSI ) ////////////////////////////////////// 10050 10051 #include <unistd.h> 10052 10053 namespace Catch { 10054 namespace { 10055 10056 // use POSIX/ ANSI console terminal codes 10057 // Thanks to Adam Strzelecki for original contribution 10058 // (http://github.com/nanoant) 10059 // https://github.com/philsquared/Catch/pull/131 10060 class PosixColourImpl : public IColourImpl { 10061 public: 10062 void use( Colour::Code _colourCode ) override { 10063 switch( _colourCode ) { 10064 case Colour::None: 10065 case Colour::White: return setColour( "[0m" ); 10066 case Colour::Red: return setColour( "[0;31m" ); 10067 case Colour::Green: return setColour( "[0;32m" ); 10068 case Colour::Blue: return setColour( "[0;34m" ); 10069 case Colour::Cyan: return setColour( "[0;36m" ); 10070 case Colour::Yellow: return setColour( "[0;33m" ); 10071 case Colour::Grey: return setColour( "[1;30m" ); 10072 10073 case Colour::LightGrey: return setColour( "[0;37m" ); 10074 case Colour::BrightRed: return setColour( "[1;31m" ); 10075 case Colour::BrightGreen: return setColour( "[1;32m" ); 10076 case Colour::BrightWhite: return setColour( "[1;37m" ); 10077 case Colour::BrightYellow: return setColour( "[1;33m" ); 10078 10079 case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" ); 10080 default: CATCH_INTERNAL_ERROR( "Unknown colour requested" ); 10081 } 10082 } 10083 static IColourImpl* instance() { 10084 static PosixColourImpl s_instance; 10085 return &s_instance; 10086 } 10087 10088 private: 10089 void setColour( const char* _escapeCode ) { 10090 getCurrentContext().getConfig()->stream() 10091 << '\033' << _escapeCode; 10092 } 10093 }; 10094 10095 bool useColourOnPlatform() { 10096 return 10097 #ifdef CATCH_PLATFORM_MAC 10098 !isDebuggerActive() && 10099 #endif 10100 #if !(defined(__DJGPP__) && defined(__STRICT_ANSI__)) 10101 isatty(STDOUT_FILENO) 10102 #else 10103 false 10104 #endif 10105 ; 10106 } 10107 IColourImpl* platformColourInstance() { 10108 ErrnoGuard guard; 10109 IConfigPtr config = getCurrentContext().getConfig(); 10110 UseColour::YesOrNo colourMode = config 10111 ? config->useColour() 10112 : UseColour::Auto; 10113 if( colourMode == UseColour::Auto ) 10114 colourMode = useColourOnPlatform() 10115 ? UseColour::Yes 10116 : UseColour::No; 10117 return colourMode == UseColour::Yes 10118 ? PosixColourImpl::instance() 10119 : NoColourImpl::instance(); 10120 } 10121 10122 } // end anon namespace 10123 } // end namespace Catch 10124 10125 #else // not Windows or ANSI /////////////////////////////////////////////// 10126 10127 namespace Catch { 10128 10129 static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); } 10130 10131 } // end namespace Catch 10132 10133 #endif // Windows/ ANSI/ None 10134 10135 namespace Catch { 10136 10137 Colour::Colour( Code _colourCode ) { use( _colourCode ); } 10138 Colour::Colour( Colour&& rhs ) noexcept { 10139 m_moved = rhs.m_moved; 10140 rhs.m_moved = true; 10141 } 10142 Colour& Colour::operator=( Colour&& rhs ) noexcept { 10143 m_moved = rhs.m_moved; 10144 rhs.m_moved = true; 10145 return *this; 10146 } 10147 10148 Colour::~Colour(){ if( !m_moved ) use( None ); } 10149 10150 void Colour::use( Code _colourCode ) { 10151 static IColourImpl* impl = platformColourInstance(); 10152 // Strictly speaking, this cannot possibly happen. 10153 // However, under some conditions it does happen (see #1626), 10154 // and this change is small enough that we can let practicality 10155 // triumph over purity in this case. 10156 if (impl != NULL) { 10157 impl->use( _colourCode ); 10158 } 10159 } 10160 10161 std::ostream& operator << ( std::ostream& os, Colour const& ) { 10162 return os; 10163 } 10164 10165 } // end namespace Catch 10166 10167 #if defined(__clang__) 10168 # pragma clang diagnostic pop 10169 #endif 10170 10171 // end catch_console_colour.cpp 10172 // start catch_context.cpp 10173 10174 namespace Catch { 10175 10176 class Context : public IMutableContext, NonCopyable { 10177 10178 public: // IContext 10179 IResultCapture* getResultCapture() override { 10180 return m_resultCapture; 10181 } 10182 IRunner* getRunner() override { 10183 return m_runner; 10184 } 10185 10186 IConfigPtr const& getConfig() const override { 10187 return m_config; 10188 } 10189 10190 ~Context() override; 10191 10192 public: // IMutableContext 10193 void setResultCapture( IResultCapture* resultCapture ) override { 10194 m_resultCapture = resultCapture; 10195 } 10196 void setRunner( IRunner* runner ) override { 10197 m_runner = runner; 10198 } 10199 void setConfig( IConfigPtr const& config ) override { 10200 m_config = config; 10201 } 10202 10203 friend IMutableContext& getCurrentMutableContext(); 10204 10205 private: 10206 IConfigPtr m_config; 10207 IRunner* m_runner = nullptr; 10208 IResultCapture* m_resultCapture = nullptr; 10209 }; 10210 10211 IMutableContext *IMutableContext::currentContext = nullptr; 10212 10213 void IMutableContext::createContext() 10214 { 10215 currentContext = new Context(); 10216 } 10217 10218 void cleanUpContext() { 10219 delete IMutableContext::currentContext; 10220 IMutableContext::currentContext = nullptr; 10221 } 10222 IContext::~IContext() = default; 10223 IMutableContext::~IMutableContext() = default; 10224 Context::~Context() = default; 10225 10226 SimplePcg32& rng() { 10227 static SimplePcg32 s_rng; 10228 return s_rng; 10229 } 10230 10231 } 10232 // end catch_context.cpp 10233 // start catch_debug_console.cpp 10234 10235 // start catch_debug_console.h 10236 10237 #include <string> 10238 10239 namespace Catch { 10240 void writeToDebugConsole( std::string const& text ); 10241 } 10242 10243 // end catch_debug_console.h 10244 #if defined(CATCH_CONFIG_ANDROID_LOGWRITE) 10245 #include <android/log.h> 10246 10247 namespace Catch { 10248 void writeToDebugConsole( std::string const& text ) { 10249 __android_log_write( ANDROID_LOG_DEBUG, "Catch", text.c_str() ); 10250 } 10251 } 10252 10253 #elif defined(CATCH_PLATFORM_WINDOWS) 10254 10255 namespace Catch { 10256 void writeToDebugConsole( std::string const& text ) { 10257 ::OutputDebugStringA( text.c_str() ); 10258 } 10259 } 10260 10261 #else 10262 10263 namespace Catch { 10264 void writeToDebugConsole( std::string const& text ) { 10265 // !TBD: Need a version for Mac/ XCode and other IDEs 10266 Catch::cout() << text; 10267 } 10268 } 10269 10270 #endif // Platform 10271 // end catch_debug_console.cpp 10272 // start catch_debugger.cpp 10273 10274 #ifdef CATCH_PLATFORM_MAC 10275 10276 # include <assert.h> 10277 # include <stdbool.h> 10278 # include <sys/types.h> 10279 # include <unistd.h> 10280 # include <cstddef> 10281 # include <ostream> 10282 10283 #ifdef __apple_build_version__ 10284 // These headers will only compile with AppleClang (XCode) 10285 // For other compilers (Clang, GCC, ... ) we need to exclude them 10286 # include <sys/sysctl.h> 10287 #endif 10288 10289 namespace Catch { 10290 #ifdef __apple_build_version__ 10291 // The following function is taken directly from the following technical note: 10292 // https://developer.apple.com/library/archive/qa/qa1361/_index.html 10293 10294 // Returns true if the current process is being debugged (either 10295 // running under the debugger or has a debugger attached post facto). 10296 bool isDebuggerActive(){ 10297 int mib[4]; 10298 struct kinfo_proc info; 10299 std::size_t size; 10300 10301 // Initialize the flags so that, if sysctl fails for some bizarre 10302 // reason, we get a predictable result. 10303 10304 info.kp_proc.p_flag = 0; 10305 10306 // Initialize mib, which tells sysctl the info we want, in this case 10307 // we're looking for information about a specific process ID. 10308 10309 mib[0] = CTL_KERN; 10310 mib[1] = KERN_PROC; 10311 mib[2] = KERN_PROC_PID; 10312 mib[3] = getpid(); 10313 10314 // Call sysctl. 10315 10316 size = sizeof(info); 10317 if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, nullptr, 0) != 0 ) { 10318 Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; 10319 return false; 10320 } 10321 10322 // We're being debugged if the P_TRACED flag is set. 10323 10324 return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); 10325 } 10326 #else 10327 bool isDebuggerActive() { 10328 // We need to find another way to determine this for non-appleclang compilers on macOS 10329 return false; 10330 } 10331 #endif 10332 } // namespace Catch 10333 10334 #elif defined(CATCH_PLATFORM_LINUX) 10335 #include <fstream> 10336 #include <string> 10337 10338 namespace Catch{ 10339 // The standard POSIX way of detecting a debugger is to attempt to 10340 // ptrace() the process, but this needs to be done from a child and not 10341 // this process itself to still allow attaching to this process later 10342 // if wanted, so is rather heavy. Under Linux we have the PID of the 10343 // "debugger" (which doesn't need to be gdb, of course, it could also 10344 // be strace, for example) in /proc/$PID/status, so just get it from 10345 // there instead. 10346 bool isDebuggerActive(){ 10347 // Libstdc++ has a bug, where std::ifstream sets errno to 0 10348 // This way our users can properly assert over errno values 10349 ErrnoGuard guard; 10350 std::ifstream in("/proc/self/status"); 10351 for( std::string line; std::getline(in, line); ) { 10352 static const int PREFIX_LEN = 11; 10353 if( line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0 ) { 10354 // We're traced if the PID is not 0 and no other PID starts 10355 // with 0 digit, so it's enough to check for just a single 10356 // character. 10357 return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0'; 10358 } 10359 } 10360 10361 return false; 10362 } 10363 } // namespace Catch 10364 #elif defined(_MSC_VER) 10365 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); 10366 namespace Catch { 10367 bool isDebuggerActive() { 10368 return IsDebuggerPresent() != 0; 10369 } 10370 } 10371 #elif defined(__MINGW32__) 10372 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); 10373 namespace Catch { 10374 bool isDebuggerActive() { 10375 return IsDebuggerPresent() != 0; 10376 } 10377 } 10378 #else 10379 namespace Catch { 10380 bool isDebuggerActive() { return false; } 10381 } 10382 #endif // Platform 10383 // end catch_debugger.cpp 10384 // start catch_decomposer.cpp 10385 10386 namespace Catch { 10387 10388 ITransientExpression::~ITransientExpression() = default; 10389 10390 void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ) { 10391 if( lhs.size() + rhs.size() < 40 && 10392 lhs.find('\n') == std::string::npos && 10393 rhs.find('\n') == std::string::npos ) 10394 os << lhs << " " << op << " " << rhs; 10395 else 10396 os << lhs << "\n" << op << "\n" << rhs; 10397 } 10398 } 10399 // end catch_decomposer.cpp 10400 // start catch_enforce.cpp 10401 10402 #include <stdexcept> 10403 10404 namespace Catch { 10405 #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER) 10406 [[noreturn]] 10407 void throw_exception(std::exception const& e) { 10408 Catch::cerr() << "Catch will terminate because it needed to throw an exception.\n" 10409 << "The message was: " << e.what() << '\n'; 10410 std::terminate(); 10411 } 10412 #endif 10413 10414 [[noreturn]] 10415 void throw_logic_error(std::string const& msg) { 10416 throw_exception(std::logic_error(msg)); 10417 } 10418 10419 [[noreturn]] 10420 void throw_domain_error(std::string const& msg) { 10421 throw_exception(std::domain_error(msg)); 10422 } 10423 10424 [[noreturn]] 10425 void throw_runtime_error(std::string const& msg) { 10426 throw_exception(std::runtime_error(msg)); 10427 } 10428 10429 } // namespace Catch; 10430 // end catch_enforce.cpp 10431 // start catch_enum_values_registry.cpp 10432 // start catch_enum_values_registry.h 10433 10434 #include <vector> 10435 #include <memory> 10436 10437 namespace Catch { 10438 10439 namespace Detail { 10440 10441 std::unique_ptr<EnumInfo> makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ); 10442 10443 class EnumValuesRegistry : public IMutableEnumValuesRegistry { 10444 10445 std::vector<std::unique_ptr<EnumInfo>> m_enumInfos; 10446 10447 EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::vector<int> const& values) override; 10448 }; 10449 10450 std::vector<StringRef> parseEnums( StringRef enums ); 10451 10452 } // Detail 10453 10454 } // Catch 10455 10456 // end catch_enum_values_registry.h 10457 10458 #include <map> 10459 #include <cassert> 10460 10461 namespace Catch { 10462 10463 IMutableEnumValuesRegistry::~IMutableEnumValuesRegistry() {} 10464 10465 namespace Detail { 10466 10467 namespace { 10468 // Extracts the actual name part of an enum instance 10469 // In other words, it returns the Blue part of Bikeshed::Colour::Blue 10470 StringRef extractInstanceName(StringRef enumInstance) { 10471 // Find last occurence of ":" 10472 size_t name_start = enumInstance.size(); 10473 while (name_start > 0 && enumInstance[name_start - 1] != ':') { 10474 --name_start; 10475 } 10476 return enumInstance.substr(name_start, enumInstance.size() - name_start); 10477 } 10478 } 10479 10480 std::vector<StringRef> parseEnums( StringRef enums ) { 10481 auto enumValues = splitStringRef( enums, ',' ); 10482 std::vector<StringRef> parsed; 10483 parsed.reserve( enumValues.size() ); 10484 for( auto const& enumValue : enumValues ) { 10485 parsed.push_back(trim(extractInstanceName(enumValue))); 10486 } 10487 return parsed; 10488 } 10489 10490 EnumInfo::~EnumInfo() {} 10491 10492 StringRef EnumInfo::lookup( int value ) const { 10493 for( auto const& valueToName : m_values ) { 10494 if( valueToName.first == value ) 10495 return valueToName.second; 10496 } 10497 return "{** unexpected enum value **}"_sr; 10498 } 10499 10500 std::unique_ptr<EnumInfo> makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ) { 10501 std::unique_ptr<EnumInfo> enumInfo( new EnumInfo ); 10502 enumInfo->m_name = enumName; 10503 enumInfo->m_values.reserve( values.size() ); 10504 10505 const auto valueNames = Catch::Detail::parseEnums( allValueNames ); 10506 assert( valueNames.size() == values.size() ); 10507 std::size_t i = 0; 10508 for( auto value : values ) 10509 enumInfo->m_values.push_back({ value, valueNames[i++] }); 10510 10511 return enumInfo; 10512 } 10513 10514 EnumInfo const& EnumValuesRegistry::registerEnum( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ) { 10515 m_enumInfos.push_back(makeEnumInfo(enumName, allValueNames, values)); 10516 return *m_enumInfos.back(); 10517 } 10518 10519 } // Detail 10520 } // Catch 10521 10522 // end catch_enum_values_registry.cpp 10523 // start catch_errno_guard.cpp 10524 10525 #include <cerrno> 10526 10527 namespace Catch { 10528 ErrnoGuard::ErrnoGuard():m_oldErrno(errno){} 10529 ErrnoGuard::~ErrnoGuard() { errno = m_oldErrno; } 10530 } 10531 // end catch_errno_guard.cpp 10532 // start catch_exception_translator_registry.cpp 10533 10534 // start catch_exception_translator_registry.h 10535 10536 #include <vector> 10537 #include <string> 10538 #include <memory> 10539 10540 namespace Catch { 10541 10542 class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { 10543 public: 10544 ~ExceptionTranslatorRegistry(); 10545 virtual void registerTranslator( const IExceptionTranslator* translator ); 10546 std::string translateActiveException() const override; 10547 std::string tryTranslators() const; 10548 10549 private: 10550 std::vector<std::unique_ptr<IExceptionTranslator const>> m_translators; 10551 }; 10552 } 10553 10554 // end catch_exception_translator_registry.h 10555 #ifdef __OBJC__ 10556 #import "Foundation/Foundation.h" 10557 #endif 10558 10559 namespace Catch { 10560 10561 ExceptionTranslatorRegistry::~ExceptionTranslatorRegistry() { 10562 } 10563 10564 void ExceptionTranslatorRegistry::registerTranslator( const IExceptionTranslator* translator ) { 10565 m_translators.push_back( std::unique_ptr<const IExceptionTranslator>( translator ) ); 10566 } 10567 10568 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 10569 std::string ExceptionTranslatorRegistry::translateActiveException() const { 10570 try { 10571 #ifdef __OBJC__ 10572 // In Objective-C try objective-c exceptions first 10573 @try { 10574 return tryTranslators(); 10575 } 10576 @catch (NSException *exception) { 10577 return Catch::Detail::stringify( [exception description] ); 10578 } 10579 #else 10580 // Compiling a mixed mode project with MSVC means that CLR 10581 // exceptions will be caught in (...) as well. However, these 10582 // do not fill-in std::current_exception and thus lead to crash 10583 // when attempting rethrow. 10584 // /EHa switch also causes structured exceptions to be caught 10585 // here, but they fill-in current_exception properly, so 10586 // at worst the output should be a little weird, instead of 10587 // causing a crash. 10588 if (std::current_exception() == nullptr) { 10589 return "Non C++ exception. Possibly a CLR exception."; 10590 } 10591 return tryTranslators(); 10592 #endif 10593 } 10594 catch( TestFailureException& ) { 10595 std::rethrow_exception(std::current_exception()); 10596 } 10597 catch( std::exception& ex ) { 10598 return ex.what(); 10599 } 10600 catch( std::string& msg ) { 10601 return msg; 10602 } 10603 catch( const char* msg ) { 10604 return msg; 10605 } 10606 catch(...) { 10607 return "Unknown exception"; 10608 } 10609 } 10610 10611 std::string ExceptionTranslatorRegistry::tryTranslators() const { 10612 if (m_translators.empty()) { 10613 std::rethrow_exception(std::current_exception()); 10614 } else { 10615 return m_translators[0]->translate(m_translators.begin() + 1, m_translators.end()); 10616 } 10617 } 10618 10619 #else // ^^ Exceptions are enabled // Exceptions are disabled vv 10620 std::string ExceptionTranslatorRegistry::translateActiveException() const { 10621 CATCH_INTERNAL_ERROR("Attempted to translate active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!"); 10622 } 10623 10624 std::string ExceptionTranslatorRegistry::tryTranslators() const { 10625 CATCH_INTERNAL_ERROR("Attempted to use exception translators under CATCH_CONFIG_DISABLE_EXCEPTIONS!"); 10626 } 10627 #endif 10628 10629 } 10630 // end catch_exception_translator_registry.cpp 10631 // start catch_fatal_condition.cpp 10632 10633 #if defined(__GNUC__) 10634 # pragma GCC diagnostic push 10635 # pragma GCC diagnostic ignored "-Wmissing-field-initializers" 10636 #endif 10637 10638 #if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS ) 10639 10640 namespace { 10641 // Report the error condition 10642 void reportFatal( char const * const message ) { 10643 Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message ); 10644 } 10645 } 10646 10647 #endif // signals/SEH handling 10648 10649 #if defined( CATCH_CONFIG_WINDOWS_SEH ) 10650 10651 namespace Catch { 10652 struct SignalDefs { DWORD id; const char* name; }; 10653 10654 // There is no 1-1 mapping between signals and windows exceptions. 10655 // Windows can easily distinguish between SO and SigSegV, 10656 // but SigInt, SigTerm, etc are handled differently. 10657 static SignalDefs signalDefs[] = { 10658 { static_cast<DWORD>(EXCEPTION_ILLEGAL_INSTRUCTION), "SIGILL - Illegal instruction signal" }, 10659 { static_cast<DWORD>(EXCEPTION_STACK_OVERFLOW), "SIGSEGV - Stack overflow" }, 10660 { static_cast<DWORD>(EXCEPTION_ACCESS_VIOLATION), "SIGSEGV - Segmentation violation signal" }, 10661 { static_cast<DWORD>(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error" }, 10662 }; 10663 10664 LONG CALLBACK FatalConditionHandler::handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) { 10665 for (auto const& def : signalDefs) { 10666 if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) { 10667 reportFatal(def.name); 10668 } 10669 } 10670 // If its not an exception we care about, pass it along. 10671 // This stops us from eating debugger breaks etc. 10672 return EXCEPTION_CONTINUE_SEARCH; 10673 } 10674 10675 FatalConditionHandler::FatalConditionHandler() { 10676 isSet = true; 10677 // 32k seems enough for Catch to handle stack overflow, 10678 // but the value was found experimentally, so there is no strong guarantee 10679 guaranteeSize = 32 * 1024; 10680 exceptionHandlerHandle = nullptr; 10681 // Register as first handler in current chain 10682 exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException); 10683 // Pass in guarantee size to be filled 10684 SetThreadStackGuarantee(&guaranteeSize); 10685 } 10686 10687 void FatalConditionHandler::reset() { 10688 if (isSet) { 10689 RemoveVectoredExceptionHandler(exceptionHandlerHandle); 10690 SetThreadStackGuarantee(&guaranteeSize); 10691 exceptionHandlerHandle = nullptr; 10692 isSet = false; 10693 } 10694 } 10695 10696 FatalConditionHandler::~FatalConditionHandler() { 10697 reset(); 10698 } 10699 10700 bool FatalConditionHandler::isSet = false; 10701 ULONG FatalConditionHandler::guaranteeSize = 0; 10702 PVOID FatalConditionHandler::exceptionHandlerHandle = nullptr; 10703 10704 } // namespace Catch 10705 10706 #elif defined( CATCH_CONFIG_POSIX_SIGNALS ) 10707 10708 namespace Catch { 10709 10710 struct SignalDefs { 10711 int id; 10712 const char* name; 10713 }; 10714 10715 // 32kb for the alternate stack seems to be sufficient. However, this value 10716 // is experimentally determined, so that's not guaranteed. 10717 static constexpr std::size_t sigStackSize = 32768 >= MINSIGSTKSZ ? 32768 : MINSIGSTKSZ; 10718 10719 static SignalDefs signalDefs[] = { 10720 { SIGINT, "SIGINT - Terminal interrupt signal" }, 10721 { SIGILL, "SIGILL - Illegal instruction signal" }, 10722 { SIGFPE, "SIGFPE - Floating point error signal" }, 10723 { SIGSEGV, "SIGSEGV - Segmentation violation signal" }, 10724 { SIGTERM, "SIGTERM - Termination request signal" }, 10725 { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" } 10726 }; 10727 10728 void FatalConditionHandler::handleSignal( int sig ) { 10729 char const * name = "<unknown signal>"; 10730 for (auto const& def : signalDefs) { 10731 if (sig == def.id) { 10732 name = def.name; 10733 break; 10734 } 10735 } 10736 reset(); 10737 reportFatal(name); 10738 raise( sig ); 10739 } 10740 10741 FatalConditionHandler::FatalConditionHandler() { 10742 isSet = true; 10743 stack_t sigStack; 10744 sigStack.ss_sp = altStackMem; 10745 sigStack.ss_size = sigStackSize; 10746 sigStack.ss_flags = 0; 10747 sigaltstack(&sigStack, &oldSigStack); 10748 struct sigaction sa = { }; 10749 10750 sa.sa_handler = handleSignal; 10751 sa.sa_flags = SA_ONSTACK; 10752 for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) { 10753 sigaction(signalDefs[i].id, &sa, &oldSigActions[i]); 10754 } 10755 } 10756 10757 FatalConditionHandler::~FatalConditionHandler() { 10758 reset(); 10759 } 10760 10761 void FatalConditionHandler::reset() { 10762 if( isSet ) { 10763 // Set signals back to previous values -- hopefully nobody overwrote them in the meantime 10764 for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) { 10765 sigaction(signalDefs[i].id, &oldSigActions[i], nullptr); 10766 } 10767 // Return the old stack 10768 sigaltstack(&oldSigStack, nullptr); 10769 isSet = false; 10770 } 10771 } 10772 10773 bool FatalConditionHandler::isSet = false; 10774 struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {}; 10775 stack_t FatalConditionHandler::oldSigStack = {}; 10776 char FatalConditionHandler::altStackMem[sigStackSize] = {}; 10777 10778 } // namespace Catch 10779 10780 #else 10781 10782 namespace Catch { 10783 void FatalConditionHandler::reset() {} 10784 } 10785 10786 #endif // signals/SEH handling 10787 10788 #if defined(__GNUC__) 10789 # pragma GCC diagnostic pop 10790 #endif 10791 // end catch_fatal_condition.cpp 10792 // start catch_generators.cpp 10793 10794 #include <limits> 10795 #include <set> 10796 10797 namespace Catch { 10798 10799 IGeneratorTracker::~IGeneratorTracker() {} 10800 10801 const char* GeneratorException::what() const noexcept { 10802 return m_msg; 10803 } 10804 10805 namespace Generators { 10806 10807 GeneratorUntypedBase::~GeneratorUntypedBase() {} 10808 10809 auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& { 10810 return getResultCapture().acquireGeneratorTracker( lineInfo ); 10811 } 10812 10813 } // namespace Generators 10814 } // namespace Catch 10815 // end catch_generators.cpp 10816 // start catch_interfaces_capture.cpp 10817 10818 namespace Catch { 10819 IResultCapture::~IResultCapture() = default; 10820 } 10821 // end catch_interfaces_capture.cpp 10822 // start catch_interfaces_config.cpp 10823 10824 namespace Catch { 10825 IConfig::~IConfig() = default; 10826 } 10827 // end catch_interfaces_config.cpp 10828 // start catch_interfaces_exception.cpp 10829 10830 namespace Catch { 10831 IExceptionTranslator::~IExceptionTranslator() = default; 10832 IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() = default; 10833 } 10834 // end catch_interfaces_exception.cpp 10835 // start catch_interfaces_registry_hub.cpp 10836 10837 namespace Catch { 10838 IRegistryHub::~IRegistryHub() = default; 10839 IMutableRegistryHub::~IMutableRegistryHub() = default; 10840 } 10841 // end catch_interfaces_registry_hub.cpp 10842 // start catch_interfaces_reporter.cpp 10843 10844 // start catch_reporter_listening.h 10845 10846 namespace Catch { 10847 10848 class ListeningReporter : public IStreamingReporter { 10849 using Reporters = std::vector<IStreamingReporterPtr>; 10850 Reporters m_listeners; 10851 IStreamingReporterPtr m_reporter = nullptr; 10852 ReporterPreferences m_preferences; 10853 10854 public: 10855 ListeningReporter(); 10856 10857 void addListener( IStreamingReporterPtr&& listener ); 10858 void addReporter( IStreamingReporterPtr&& reporter ); 10859 10860 public: // IStreamingReporter 10861 10862 ReporterPreferences getPreferences() const override; 10863 10864 void noMatchingTestCases( std::string const& spec ) override; 10865 10866 void reportInvalidArguments(std::string const&arg) override; 10867 10868 static std::set<Verbosity> getSupportedVerbosities(); 10869 10870 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 10871 void benchmarkPreparing(std::string const& name) override; 10872 void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) override; 10873 void benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) override; 10874 void benchmarkFailed(std::string const&) override; 10875 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 10876 10877 void testRunStarting( TestRunInfo const& testRunInfo ) override; 10878 void testGroupStarting( GroupInfo const& groupInfo ) override; 10879 void testCaseStarting( TestCaseInfo const& testInfo ) override; 10880 void sectionStarting( SectionInfo const& sectionInfo ) override; 10881 void assertionStarting( AssertionInfo const& assertionInfo ) override; 10882 10883 // The return value indicates if the messages buffer should be cleared: 10884 bool assertionEnded( AssertionStats const& assertionStats ) override; 10885 void sectionEnded( SectionStats const& sectionStats ) override; 10886 void testCaseEnded( TestCaseStats const& testCaseStats ) override; 10887 void testGroupEnded( TestGroupStats const& testGroupStats ) override; 10888 void testRunEnded( TestRunStats const& testRunStats ) override; 10889 10890 void skipTest( TestCaseInfo const& testInfo ) override; 10891 bool isMulti() const override; 10892 10893 }; 10894 10895 } // end namespace Catch 10896 10897 // end catch_reporter_listening.h 10898 namespace Catch { 10899 10900 ReporterConfig::ReporterConfig( IConfigPtr const& _fullConfig ) 10901 : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} 10902 10903 ReporterConfig::ReporterConfig( IConfigPtr const& _fullConfig, std::ostream& _stream ) 10904 : m_stream( &_stream ), m_fullConfig( _fullConfig ) {} 10905 10906 std::ostream& ReporterConfig::stream() const { return *m_stream; } 10907 IConfigPtr ReporterConfig::fullConfig() const { return m_fullConfig; } 10908 10909 TestRunInfo::TestRunInfo( std::string const& _name ) : name( _name ) {} 10910 10911 GroupInfo::GroupInfo( std::string const& _name, 10912 std::size_t _groupIndex, 10913 std::size_t _groupsCount ) 10914 : name( _name ), 10915 groupIndex( _groupIndex ), 10916 groupsCounts( _groupsCount ) 10917 {} 10918 10919 AssertionStats::AssertionStats( AssertionResult const& _assertionResult, 10920 std::vector<MessageInfo> const& _infoMessages, 10921 Totals const& _totals ) 10922 : assertionResult( _assertionResult ), 10923 infoMessages( _infoMessages ), 10924 totals( _totals ) 10925 { 10926 assertionResult.m_resultData.lazyExpression.m_transientExpression = _assertionResult.m_resultData.lazyExpression.m_transientExpression; 10927 10928 if( assertionResult.hasMessage() ) { 10929 // Copy message into messages list. 10930 // !TBD This should have been done earlier, somewhere 10931 MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); 10932 builder << assertionResult.getMessage(); 10933 builder.m_info.message = builder.m_stream.str(); 10934 10935 infoMessages.push_back( builder.m_info ); 10936 } 10937 } 10938 10939 AssertionStats::~AssertionStats() = default; 10940 10941 SectionStats::SectionStats( SectionInfo const& _sectionInfo, 10942 Counts const& _assertions, 10943 double _durationInSeconds, 10944 bool _missingAssertions ) 10945 : sectionInfo( _sectionInfo ), 10946 assertions( _assertions ), 10947 durationInSeconds( _durationInSeconds ), 10948 missingAssertions( _missingAssertions ) 10949 {} 10950 10951 SectionStats::~SectionStats() = default; 10952 10953 TestCaseStats::TestCaseStats( TestCaseInfo const& _testInfo, 10954 Totals const& _totals, 10955 std::string const& _stdOut, 10956 std::string const& _stdErr, 10957 bool _aborting ) 10958 : testInfo( _testInfo ), 10959 totals( _totals ), 10960 stdOut( _stdOut ), 10961 stdErr( _stdErr ), 10962 aborting( _aborting ) 10963 {} 10964 10965 TestCaseStats::~TestCaseStats() = default; 10966 10967 TestGroupStats::TestGroupStats( GroupInfo const& _groupInfo, 10968 Totals const& _totals, 10969 bool _aborting ) 10970 : groupInfo( _groupInfo ), 10971 totals( _totals ), 10972 aborting( _aborting ) 10973 {} 10974 10975 TestGroupStats::TestGroupStats( GroupInfo const& _groupInfo ) 10976 : groupInfo( _groupInfo ), 10977 aborting( false ) 10978 {} 10979 10980 TestGroupStats::~TestGroupStats() = default; 10981 10982 TestRunStats::TestRunStats( TestRunInfo const& _runInfo, 10983 Totals const& _totals, 10984 bool _aborting ) 10985 : runInfo( _runInfo ), 10986 totals( _totals ), 10987 aborting( _aborting ) 10988 {} 10989 10990 TestRunStats::~TestRunStats() = default; 10991 10992 void IStreamingReporter::fatalErrorEncountered( StringRef ) {} 10993 bool IStreamingReporter::isMulti() const { return false; } 10994 10995 IReporterFactory::~IReporterFactory() = default; 10996 IReporterRegistry::~IReporterRegistry() = default; 10997 10998 } // end namespace Catch 10999 // end catch_interfaces_reporter.cpp 11000 // start catch_interfaces_runner.cpp 11001 11002 namespace Catch { 11003 IRunner::~IRunner() = default; 11004 } 11005 // end catch_interfaces_runner.cpp 11006 // start catch_interfaces_testcase.cpp 11007 11008 namespace Catch { 11009 ITestInvoker::~ITestInvoker() = default; 11010 ITestCaseRegistry::~ITestCaseRegistry() = default; 11011 } 11012 // end catch_interfaces_testcase.cpp 11013 // start catch_leak_detector.cpp 11014 11015 #ifdef CATCH_CONFIG_WINDOWS_CRTDBG 11016 #include <crtdbg.h> 11017 11018 namespace Catch { 11019 11020 LeakDetector::LeakDetector() { 11021 int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); 11022 flag |= _CRTDBG_LEAK_CHECK_DF; 11023 flag |= _CRTDBG_ALLOC_MEM_DF; 11024 _CrtSetDbgFlag(flag); 11025 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); 11026 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); 11027 // Change this to leaking allocation's number to break there 11028 _CrtSetBreakAlloc(-1); 11029 } 11030 } 11031 11032 #else 11033 11034 Catch::LeakDetector::LeakDetector() {} 11035 11036 #endif 11037 11038 Catch::LeakDetector::~LeakDetector() { 11039 Catch::cleanUp(); 11040 } 11041 // end catch_leak_detector.cpp 11042 // start catch_list.cpp 11043 11044 // start catch_list.h 11045 11046 #include <set> 11047 11048 namespace Catch { 11049 11050 std::size_t listTests( Config const& config ); 11051 11052 std::size_t listTestsNamesOnly( Config const& config ); 11053 11054 struct TagInfo { 11055 void add( std::string const& spelling ); 11056 std::string all() const; 11057 11058 std::set<std::string> spellings; 11059 std::size_t count = 0; 11060 }; 11061 11062 std::size_t listTags( Config const& config ); 11063 11064 std::size_t listReporters(); 11065 11066 Option<std::size_t> list( std::shared_ptr<Config> const& config ); 11067 11068 } // end namespace Catch 11069 11070 // end catch_list.h 11071 // start catch_text.h 11072 11073 namespace Catch { 11074 using namespace clara::TextFlow; 11075 } 11076 11077 // end catch_text.h 11078 #include <limits> 11079 #include <algorithm> 11080 #include <iomanip> 11081 11082 namespace Catch { 11083 11084 std::size_t listTests( Config const& config ) { 11085 TestSpec testSpec = config.testSpec(); 11086 if( config.hasTestFilters() ) 11087 Catch::cout() << "Matching test cases:\n"; 11088 else { 11089 Catch::cout() << "All available test cases:\n"; 11090 } 11091 11092 auto matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); 11093 for( auto const& testCaseInfo : matchedTestCases ) { 11094 Colour::Code colour = testCaseInfo.isHidden() 11095 ? Colour::SecondaryText 11096 : Colour::None; 11097 Colour colourGuard( colour ); 11098 11099 Catch::cout() << Column( testCaseInfo.name ).initialIndent( 2 ).indent( 4 ) << "\n"; 11100 if( config.verbosity() >= Verbosity::High ) { 11101 Catch::cout() << Column( Catch::Detail::stringify( testCaseInfo.lineInfo ) ).indent(4) << std::endl; 11102 std::string description = testCaseInfo.description; 11103 if( description.empty() ) 11104 description = "(NO DESCRIPTION)"; 11105 Catch::cout() << Column( description ).indent(4) << std::endl; 11106 } 11107 if( !testCaseInfo.tags.empty() ) 11108 Catch::cout() << Column( testCaseInfo.tagsAsString() ).indent( 6 ) << "\n"; 11109 } 11110 11111 if( !config.hasTestFilters() ) 11112 Catch::cout() << pluralise( matchedTestCases.size(), "test case" ) << '\n' << std::endl; 11113 else 11114 Catch::cout() << pluralise( matchedTestCases.size(), "matching test case" ) << '\n' << std::endl; 11115 return matchedTestCases.size(); 11116 } 11117 11118 std::size_t listTestsNamesOnly( Config const& config ) { 11119 TestSpec testSpec = config.testSpec(); 11120 std::size_t matchedTests = 0; 11121 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); 11122 for( auto const& testCaseInfo : matchedTestCases ) { 11123 matchedTests++; 11124 if( startsWith( testCaseInfo.name, '#' ) ) 11125 Catch::cout() << '"' << testCaseInfo.name << '"'; 11126 else 11127 Catch::cout() << testCaseInfo.name; 11128 if ( config.verbosity() >= Verbosity::High ) 11129 Catch::cout() << "\t@" << testCaseInfo.lineInfo; 11130 Catch::cout() << std::endl; 11131 } 11132 return matchedTests; 11133 } 11134 11135 void TagInfo::add( std::string const& spelling ) { 11136 ++count; 11137 spellings.insert( spelling ); 11138 } 11139 11140 std::string TagInfo::all() const { 11141 size_t size = 0; 11142 for (auto const& spelling : spellings) { 11143 // Add 2 for the brackes 11144 size += spelling.size() + 2; 11145 } 11146 11147 std::string out; out.reserve(size); 11148 for (auto const& spelling : spellings) { 11149 out += '['; 11150 out += spelling; 11151 out += ']'; 11152 } 11153 return out; 11154 } 11155 11156 std::size_t listTags( Config const& config ) { 11157 TestSpec testSpec = config.testSpec(); 11158 if( config.hasTestFilters() ) 11159 Catch::cout() << "Tags for matching test cases:\n"; 11160 else { 11161 Catch::cout() << "All available tags:\n"; 11162 } 11163 11164 std::map<std::string, TagInfo> tagCounts; 11165 11166 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); 11167 for( auto const& testCase : matchedTestCases ) { 11168 for( auto const& tagName : testCase.getTestCaseInfo().tags ) { 11169 std::string lcaseTagName = toLower( tagName ); 11170 auto countIt = tagCounts.find( lcaseTagName ); 11171 if( countIt == tagCounts.end() ) 11172 countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first; 11173 countIt->second.add( tagName ); 11174 } 11175 } 11176 11177 for( auto const& tagCount : tagCounts ) { 11178 ReusableStringStream rss; 11179 rss << " " << std::setw(2) << tagCount.second.count << " "; 11180 auto str = rss.str(); 11181 auto wrapper = Column( tagCount.second.all() ) 11182 .initialIndent( 0 ) 11183 .indent( str.size() ) 11184 .width( CATCH_CONFIG_CONSOLE_WIDTH-10 ); 11185 Catch::cout() << str << wrapper << '\n'; 11186 } 11187 Catch::cout() << pluralise( tagCounts.size(), "tag" ) << '\n' << std::endl; 11188 return tagCounts.size(); 11189 } 11190 11191 std::size_t listReporters() { 11192 Catch::cout() << "Available reporters:\n"; 11193 IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); 11194 std::size_t maxNameLen = 0; 11195 for( auto const& factoryKvp : factories ) 11196 maxNameLen = (std::max)( maxNameLen, factoryKvp.first.size() ); 11197 11198 for( auto const& factoryKvp : factories ) { 11199 Catch::cout() 11200 << Column( factoryKvp.first + ":" ) 11201 .indent(2) 11202 .width( 5+maxNameLen ) 11203 + Column( factoryKvp.second->getDescription() ) 11204 .initialIndent(0) 11205 .indent(2) 11206 .width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) 11207 << "\n"; 11208 } 11209 Catch::cout() << std::endl; 11210 return factories.size(); 11211 } 11212 11213 Option<std::size_t> list( std::shared_ptr<Config> const& config ) { 11214 Option<std::size_t> listedCount; 11215 getCurrentMutableContext().setConfig( config ); 11216 if( config->listTests() ) 11217 listedCount = listedCount.valueOr(0) + listTests( *config ); 11218 if( config->listTestNamesOnly() ) 11219 listedCount = listedCount.valueOr(0) + listTestsNamesOnly( *config ); 11220 if( config->listTags() ) 11221 listedCount = listedCount.valueOr(0) + listTags( *config ); 11222 if( config->listReporters() ) 11223 listedCount = listedCount.valueOr(0) + listReporters(); 11224 return listedCount; 11225 } 11226 11227 } // end namespace Catch 11228 // end catch_list.cpp 11229 // start catch_matchers.cpp 11230 11231 namespace Catch { 11232 namespace Matchers { 11233 namespace Impl { 11234 11235 std::string MatcherUntypedBase::toString() const { 11236 if( m_cachedToString.empty() ) 11237 m_cachedToString = describe(); 11238 return m_cachedToString; 11239 } 11240 11241 MatcherUntypedBase::~MatcherUntypedBase() = default; 11242 11243 } // namespace Impl 11244 } // namespace Matchers 11245 11246 using namespace Matchers; 11247 using Matchers::Impl::MatcherBase; 11248 11249 } // namespace Catch 11250 // end catch_matchers.cpp 11251 // start catch_matchers_exception.cpp 11252 11253 namespace Catch { 11254 namespace Matchers { 11255 namespace Exception { 11256 11257 bool ExceptionMessageMatcher::match(std::exception const& ex) const { 11258 return ex.what() == m_message; 11259 } 11260 11261 std::string ExceptionMessageMatcher::describe() const { 11262 return "exception message matches \"" + m_message + "\""; 11263 } 11264 11265 } 11266 Exception::ExceptionMessageMatcher Message(std::string const& message) { 11267 return Exception::ExceptionMessageMatcher(message); 11268 } 11269 11270 // namespace Exception 11271 } // namespace Matchers 11272 } // namespace Catch 11273 // end catch_matchers_exception.cpp 11274 // start catch_matchers_floating.cpp 11275 11276 // start catch_polyfills.hpp 11277 11278 namespace Catch { 11279 bool isnan(float f); 11280 bool isnan(double d); 11281 } 11282 11283 // end catch_polyfills.hpp 11284 // start catch_to_string.hpp 11285 11286 #include <string> 11287 11288 namespace Catch { 11289 template <typename T> 11290 std::string to_string(T const& t) { 11291 #if defined(CATCH_CONFIG_CPP11_TO_STRING) 11292 return std::to_string(t); 11293 #else 11294 ReusableStringStream rss; 11295 rss << t; 11296 return rss.str(); 11297 #endif 11298 } 11299 } // end namespace Catch 11300 11301 // end catch_to_string.hpp 11302 #include <algorithm> 11303 #include <cmath> 11304 #include <cstdlib> 11305 #include <cstdint> 11306 #include <cstring> 11307 #include <sstream> 11308 #include <type_traits> 11309 #include <iomanip> 11310 #include <limits> 11311 11312 namespace Catch { 11313 namespace { 11314 11315 int32_t convert(float f) { 11316 static_assert(sizeof(float) == sizeof(int32_t), "Important ULP matcher assumption violated"); 11317 int32_t i; 11318 std::memcpy(&i, &f, sizeof(f)); 11319 return i; 11320 } 11321 11322 int64_t convert(double d) { 11323 static_assert(sizeof(double) == sizeof(int64_t), "Important ULP matcher assumption violated"); 11324 int64_t i; 11325 std::memcpy(&i, &d, sizeof(d)); 11326 return i; 11327 } 11328 11329 template <typename FP> 11330 bool almostEqualUlps(FP lhs, FP rhs, uint64_t maxUlpDiff) { 11331 // Comparison with NaN should always be false. 11332 // This way we can rule it out before getting into the ugly details 11333 if (Catch::isnan(lhs) || Catch::isnan(rhs)) { 11334 return false; 11335 } 11336 11337 auto lc = convert(lhs); 11338 auto rc = convert(rhs); 11339 11340 if ((lc < 0) != (rc < 0)) { 11341 // Potentially we can have +0 and -0 11342 return lhs == rhs; 11343 } 11344 11345 auto ulpDiff = std::abs(lc - rc); 11346 return static_cast<uint64_t>(ulpDiff) <= maxUlpDiff; 11347 } 11348 11349 } //end anonymous namespace 11350 11351 #if defined(CATCH_CONFIG_GLOBAL_NEXTAFTER) 11352 11353 #if defined(__clang__) 11354 #pragma clang diagnostic push 11355 // The long double overload is currently unused 11356 #pragma clang diagnostic ignored "-Wunused-function" 11357 #endif 11358 11359 float nextafter(float x, float y) { 11360 return ::nextafterf(x, y); 11361 } 11362 11363 double nextafter(double x, double y) { 11364 return ::nextafter(x, y); 11365 } 11366 11367 long double nextafter(long double x, long double y) { 11368 return ::nextafterl(x, y); 11369 } 11370 11371 #if defined(__clang__) 11372 #pragma clang diagnostic pop 11373 #endif 11374 11375 #endif // ^^^ CATCH_CONFIG_GLOBAL_NEXTAFTER ^^^ 11376 11377 namespace { 11378 11379 template <typename FP> 11380 FP step(FP start, FP direction, uint64_t steps) { 11381 for (uint64_t i = 0; i < steps; ++i) { 11382 #if defined(CATCH_CONFIG_GLOBAL_NEXTAFTER) 11383 start = Catch::nextafter(start, direction); 11384 #else 11385 start = std::nextafter(start, direction); 11386 #endif 11387 } 11388 return start; 11389 } 11390 11391 // Performs equivalent check of std::fabs(lhs - rhs) <= margin 11392 // But without the subtraction to allow for INFINITY in comparison 11393 bool marginComparison(double lhs, double rhs, double margin) { 11394 return (lhs + margin >= rhs) && (rhs + margin >= lhs); 11395 } 11396 11397 template <typename FloatingPoint> 11398 void write(std::ostream& out, FloatingPoint num) { 11399 out << std::scientific 11400 << std::setprecision(std::numeric_limits<FloatingPoint>::max_digits10 - 1) 11401 << num; 11402 } 11403 11404 } // end anonymous namespace 11405 11406 namespace Matchers { 11407 namespace Floating { 11408 11409 enum class FloatingPointKind : uint8_t { 11410 Float, 11411 Double 11412 }; 11413 11414 WithinAbsMatcher::WithinAbsMatcher(double target, double margin) 11415 :m_target{ target }, m_margin{ margin } { 11416 CATCH_ENFORCE(margin >= 0, "Invalid margin: " << margin << '.' 11417 << " Margin has to be non-negative."); 11418 } 11419 11420 // Performs equivalent check of std::fabs(lhs - rhs) <= margin 11421 // But without the subtraction to allow for INFINITY in comparison 11422 bool WithinAbsMatcher::match(double const& matchee) const { 11423 return (matchee + m_margin >= m_target) && (m_target + m_margin >= matchee); 11424 } 11425 11426 std::string WithinAbsMatcher::describe() const { 11427 return "is within " + ::Catch::Detail::stringify(m_margin) + " of " + ::Catch::Detail::stringify(m_target); 11428 } 11429 11430 WithinUlpsMatcher::WithinUlpsMatcher(double target, uint64_t ulps, FloatingPointKind baseType) 11431 :m_target{ target }, m_ulps{ ulps }, m_type{ baseType } { 11432 CATCH_ENFORCE(m_type == FloatingPointKind::Double 11433 || m_ulps < (std::numeric_limits<uint32_t>::max)(), 11434 "Provided ULP is impossibly large for a float comparison."); 11435 } 11436 11437 #if defined(__clang__) 11438 #pragma clang diagnostic push 11439 // Clang <3.5 reports on the default branch in the switch below 11440 #pragma clang diagnostic ignored "-Wunreachable-code" 11441 #endif 11442 11443 bool WithinUlpsMatcher::match(double const& matchee) const { 11444 switch (m_type) { 11445 case FloatingPointKind::Float: 11446 return almostEqualUlps<float>(static_cast<float>(matchee), static_cast<float>(m_target), m_ulps); 11447 case FloatingPointKind::Double: 11448 return almostEqualUlps<double>(matchee, m_target, m_ulps); 11449 default: 11450 CATCH_INTERNAL_ERROR( "Unknown FloatingPointKind value" ); 11451 } 11452 } 11453 11454 #if defined(__clang__) 11455 #pragma clang diagnostic pop 11456 #endif 11457 11458 std::string WithinUlpsMatcher::describe() const { 11459 std::stringstream ret; 11460 11461 ret << "is within " << m_ulps << " ULPs of "; 11462 11463 if (m_type == FloatingPointKind::Float) { 11464 write(ret, static_cast<float>(m_target)); 11465 ret << 'f'; 11466 } else { 11467 write(ret, m_target); 11468 } 11469 11470 ret << " (["; 11471 if (m_type == FloatingPointKind::Double) { 11472 write(ret, step(m_target, static_cast<double>(-INFINITY), m_ulps)); 11473 ret << ", "; 11474 write(ret, step(m_target, static_cast<double>( INFINITY), m_ulps)); 11475 } else { 11476 // We have to cast INFINITY to float because of MinGW, see #1782 11477 write(ret, step(static_cast<float>(m_target), static_cast<float>(-INFINITY), m_ulps)); 11478 ret << ", "; 11479 write(ret, step(static_cast<float>(m_target), static_cast<float>( INFINITY), m_ulps)); 11480 } 11481 ret << "])"; 11482 11483 return ret.str(); 11484 } 11485 11486 WithinRelMatcher::WithinRelMatcher(double target, double epsilon): 11487 m_target(target), 11488 m_epsilon(epsilon){ 11489 CATCH_ENFORCE(m_epsilon >= 0., "Relative comparison with epsilon < 0 does not make sense."); 11490 CATCH_ENFORCE(m_epsilon < 1., "Relative comparison with epsilon >= 1 does not make sense."); 11491 } 11492 11493 bool WithinRelMatcher::match(double const& matchee) const { 11494 const auto relMargin = m_epsilon * (std::max)(std::fabs(matchee), std::fabs(m_target)); 11495 return marginComparison(matchee, m_target, 11496 std::isinf(relMargin)? 0 : relMargin); 11497 } 11498 11499 std::string WithinRelMatcher::describe() const { 11500 Catch::ReusableStringStream sstr; 11501 sstr << "and " << m_target << " are within " << m_epsilon * 100. << "% of each other"; 11502 return sstr.str(); 11503 } 11504 11505 }// namespace Floating 11506 11507 Floating::WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff) { 11508 return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Double); 11509 } 11510 11511 Floating::WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff) { 11512 return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Float); 11513 } 11514 11515 Floating::WithinAbsMatcher WithinAbs(double target, double margin) { 11516 return Floating::WithinAbsMatcher(target, margin); 11517 } 11518 11519 Floating::WithinRelMatcher WithinRel(double target, double eps) { 11520 return Floating::WithinRelMatcher(target, eps); 11521 } 11522 11523 Floating::WithinRelMatcher WithinRel(double target) { 11524 return Floating::WithinRelMatcher(target, std::numeric_limits<double>::epsilon() * 100); 11525 } 11526 11527 Floating::WithinRelMatcher WithinRel(float target, float eps) { 11528 return Floating::WithinRelMatcher(target, eps); 11529 } 11530 11531 Floating::WithinRelMatcher WithinRel(float target) { 11532 return Floating::WithinRelMatcher(target, std::numeric_limits<float>::epsilon() * 100); 11533 } 11534 11535 } // namespace Matchers 11536 } // namespace Catch 11537 11538 // end catch_matchers_floating.cpp 11539 // start catch_matchers_generic.cpp 11540 11541 std::string Catch::Matchers::Generic::Detail::finalizeDescription(const std::string& desc) { 11542 if (desc.empty()) { 11543 return "matches undescribed predicate"; 11544 } else { 11545 return "matches predicate: \"" + desc + '"'; 11546 } 11547 } 11548 // end catch_matchers_generic.cpp 11549 // start catch_matchers_string.cpp 11550 11551 #include <regex> 11552 11553 namespace Catch { 11554 namespace Matchers { 11555 11556 namespace StdString { 11557 11558 CasedString::CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ) 11559 : m_caseSensitivity( caseSensitivity ), 11560 m_str( adjustString( str ) ) 11561 {} 11562 std::string CasedString::adjustString( std::string const& str ) const { 11563 return m_caseSensitivity == CaseSensitive::No 11564 ? toLower( str ) 11565 : str; 11566 } 11567 std::string CasedString::caseSensitivitySuffix() const { 11568 return m_caseSensitivity == CaseSensitive::No 11569 ? " (case insensitive)" 11570 : std::string(); 11571 } 11572 11573 StringMatcherBase::StringMatcherBase( std::string const& operation, CasedString const& comparator ) 11574 : m_comparator( comparator ), 11575 m_operation( operation ) { 11576 } 11577 11578 std::string StringMatcherBase::describe() const { 11579 std::string description; 11580 description.reserve(5 + m_operation.size() + m_comparator.m_str.size() + 11581 m_comparator.caseSensitivitySuffix().size()); 11582 description += m_operation; 11583 description += ": \""; 11584 description += m_comparator.m_str; 11585 description += "\""; 11586 description += m_comparator.caseSensitivitySuffix(); 11587 return description; 11588 } 11589 11590 EqualsMatcher::EqualsMatcher( CasedString const& comparator ) : StringMatcherBase( "equals", comparator ) {} 11591 11592 bool EqualsMatcher::match( std::string const& source ) const { 11593 return m_comparator.adjustString( source ) == m_comparator.m_str; 11594 } 11595 11596 ContainsMatcher::ContainsMatcher( CasedString const& comparator ) : StringMatcherBase( "contains", comparator ) {} 11597 11598 bool ContainsMatcher::match( std::string const& source ) const { 11599 return contains( m_comparator.adjustString( source ), m_comparator.m_str ); 11600 } 11601 11602 StartsWithMatcher::StartsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "starts with", comparator ) {} 11603 11604 bool StartsWithMatcher::match( std::string const& source ) const { 11605 return startsWith( m_comparator.adjustString( source ), m_comparator.m_str ); 11606 } 11607 11608 EndsWithMatcher::EndsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "ends with", comparator ) {} 11609 11610 bool EndsWithMatcher::match( std::string const& source ) const { 11611 return endsWith( m_comparator.adjustString( source ), m_comparator.m_str ); 11612 } 11613 11614 RegexMatcher::RegexMatcher(std::string regex, CaseSensitive::Choice caseSensitivity): m_regex(std::move(regex)), m_caseSensitivity(caseSensitivity) {} 11615 11616 bool RegexMatcher::match(std::string const& matchee) const { 11617 auto flags = std::regex::ECMAScript; // ECMAScript is the default syntax option anyway 11618 if (m_caseSensitivity == CaseSensitive::Choice::No) { 11619 flags |= std::regex::icase; 11620 } 11621 auto reg = std::regex(m_regex, flags); 11622 return std::regex_match(matchee, reg); 11623 } 11624 11625 std::string RegexMatcher::describe() const { 11626 return "matches " + ::Catch::Detail::stringify(m_regex) + ((m_caseSensitivity == CaseSensitive::Choice::Yes)? " case sensitively" : " case insensitively"); 11627 } 11628 11629 } // namespace StdString 11630 11631 StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity ) { 11632 return StdString::EqualsMatcher( StdString::CasedString( str, caseSensitivity) ); 11633 } 11634 StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity ) { 11635 return StdString::ContainsMatcher( StdString::CasedString( str, caseSensitivity) ); 11636 } 11637 StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) { 11638 return StdString::EndsWithMatcher( StdString::CasedString( str, caseSensitivity) ); 11639 } 11640 StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) { 11641 return StdString::StartsWithMatcher( StdString::CasedString( str, caseSensitivity) ); 11642 } 11643 11644 StdString::RegexMatcher Matches(std::string const& regex, CaseSensitive::Choice caseSensitivity) { 11645 return StdString::RegexMatcher(regex, caseSensitivity); 11646 } 11647 11648 } // namespace Matchers 11649 } // namespace Catch 11650 // end catch_matchers_string.cpp 11651 // start catch_message.cpp 11652 11653 // start catch_uncaught_exceptions.h 11654 11655 namespace Catch { 11656 bool uncaught_exceptions(); 11657 } // end namespace Catch 11658 11659 // end catch_uncaught_exceptions.h 11660 #include <cassert> 11661 #include <stack> 11662 11663 namespace Catch { 11664 11665 MessageInfo::MessageInfo( StringRef const& _macroName, 11666 SourceLineInfo const& _lineInfo, 11667 ResultWas::OfType _type ) 11668 : macroName( _macroName ), 11669 lineInfo( _lineInfo ), 11670 type( _type ), 11671 sequence( ++globalCount ) 11672 {} 11673 11674 bool MessageInfo::operator==( MessageInfo const& other ) const { 11675 return sequence == other.sequence; 11676 } 11677 11678 bool MessageInfo::operator<( MessageInfo const& other ) const { 11679 return sequence < other.sequence; 11680 } 11681 11682 // This may need protecting if threading support is added 11683 unsigned int MessageInfo::globalCount = 0; 11684 11685 //////////////////////////////////////////////////////////////////////////// 11686 11687 Catch::MessageBuilder::MessageBuilder( StringRef const& macroName, 11688 SourceLineInfo const& lineInfo, 11689 ResultWas::OfType type ) 11690 :m_info(macroName, lineInfo, type) {} 11691 11692 //////////////////////////////////////////////////////////////////////////// 11693 11694 ScopedMessage::ScopedMessage( MessageBuilder const& builder ) 11695 : m_info( builder.m_info ), m_moved() 11696 { 11697 m_info.message = builder.m_stream.str(); 11698 getResultCapture().pushScopedMessage( m_info ); 11699 } 11700 11701 ScopedMessage::ScopedMessage( ScopedMessage&& old ) 11702 : m_info( old.m_info ), m_moved() 11703 { 11704 old.m_moved = true; 11705 } 11706 11707 ScopedMessage::~ScopedMessage() { 11708 if ( !uncaught_exceptions() && !m_moved ){ 11709 getResultCapture().popScopedMessage(m_info); 11710 } 11711 } 11712 11713 Capturer::Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names ) { 11714 auto trimmed = [&] (size_t start, size_t end) { 11715 while (names[start] == ',' || isspace(names[start])) { 11716 ++start; 11717 } 11718 while (names[end] == ',' || isspace(names[end])) { 11719 --end; 11720 } 11721 return names.substr(start, end - start + 1); 11722 }; 11723 auto skipq = [&] (size_t start, char quote) { 11724 for (auto i = start + 1; i < names.size() ; ++i) { 11725 if (names[i] == quote) 11726 return i; 11727 if (names[i] == '\\') 11728 ++i; 11729 } 11730 CATCH_INTERNAL_ERROR("CAPTURE parsing encountered unmatched quote"); 11731 }; 11732 11733 size_t start = 0; 11734 std::stack<char> openings; 11735 for (size_t pos = 0; pos < names.size(); ++pos) { 11736 char c = names[pos]; 11737 switch (c) { 11738 case '[': 11739 case '{': 11740 case '(': 11741 // It is basically impossible to disambiguate between 11742 // comparison and start of template args in this context 11743 // case '<': 11744 openings.push(c); 11745 break; 11746 case ']': 11747 case '}': 11748 case ')': 11749 // case '>': 11750 openings.pop(); 11751 break; 11752 case '"': 11753 case '\'': 11754 pos = skipq(pos, c); 11755 break; 11756 case ',': 11757 if (start != pos && openings.size() == 0) { 11758 m_messages.emplace_back(macroName, lineInfo, resultType); 11759 m_messages.back().message = static_cast<std::string>(trimmed(start, pos)); 11760 m_messages.back().message += " := "; 11761 start = pos; 11762 } 11763 } 11764 } 11765 assert(openings.size() == 0 && "Mismatched openings"); 11766 m_messages.emplace_back(macroName, lineInfo, resultType); 11767 m_messages.back().message = static_cast<std::string>(trimmed(start, names.size() - 1)); 11768 m_messages.back().message += " := "; 11769 } 11770 Capturer::~Capturer() { 11771 if ( !uncaught_exceptions() ){ 11772 assert( m_captured == m_messages.size() ); 11773 for( size_t i = 0; i < m_captured; ++i ) 11774 m_resultCapture.popScopedMessage( m_messages[i] ); 11775 } 11776 } 11777 11778 void Capturer::captureValue( size_t index, std::string const& value ) { 11779 assert( index < m_messages.size() ); 11780 m_messages[index].message += value; 11781 m_resultCapture.pushScopedMessage( m_messages[index] ); 11782 m_captured++; 11783 } 11784 11785 } // end namespace Catch 11786 // end catch_message.cpp 11787 // start catch_output_redirect.cpp 11788 11789 // start catch_output_redirect.h 11790 #ifndef TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H 11791 #define TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H 11792 11793 #include <cstdio> 11794 #include <iosfwd> 11795 #include <string> 11796 11797 namespace Catch { 11798 11799 class RedirectedStream { 11800 std::ostream& m_originalStream; 11801 std::ostream& m_redirectionStream; 11802 std::streambuf* m_prevBuf; 11803 11804 public: 11805 RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream ); 11806 ~RedirectedStream(); 11807 }; 11808 11809 class RedirectedStdOut { 11810 ReusableStringStream m_rss; 11811 RedirectedStream m_cout; 11812 public: 11813 RedirectedStdOut(); 11814 auto str() const -> std::string; 11815 }; 11816 11817 // StdErr has two constituent streams in C++, std::cerr and std::clog 11818 // This means that we need to redirect 2 streams into 1 to keep proper 11819 // order of writes 11820 class RedirectedStdErr { 11821 ReusableStringStream m_rss; 11822 RedirectedStream m_cerr; 11823 RedirectedStream m_clog; 11824 public: 11825 RedirectedStdErr(); 11826 auto str() const -> std::string; 11827 }; 11828 11829 class RedirectedStreams { 11830 public: 11831 RedirectedStreams(RedirectedStreams const&) = delete; 11832 RedirectedStreams& operator=(RedirectedStreams const&) = delete; 11833 RedirectedStreams(RedirectedStreams&&) = delete; 11834 RedirectedStreams& operator=(RedirectedStreams&&) = delete; 11835 11836 RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr); 11837 ~RedirectedStreams(); 11838 private: 11839 std::string& m_redirectedCout; 11840 std::string& m_redirectedCerr; 11841 RedirectedStdOut m_redirectedStdOut; 11842 RedirectedStdErr m_redirectedStdErr; 11843 }; 11844 11845 #if defined(CATCH_CONFIG_NEW_CAPTURE) 11846 11847 // Windows's implementation of std::tmpfile is terrible (it tries 11848 // to create a file inside system folder, thus requiring elevated 11849 // privileges for the binary), so we have to use tmpnam(_s) and 11850 // create the file ourselves there. 11851 class TempFile { 11852 public: 11853 TempFile(TempFile const&) = delete; 11854 TempFile& operator=(TempFile const&) = delete; 11855 TempFile(TempFile&&) = delete; 11856 TempFile& operator=(TempFile&&) = delete; 11857 11858 TempFile(); 11859 ~TempFile(); 11860 11861 std::FILE* getFile(); 11862 std::string getContents(); 11863 11864 private: 11865 std::FILE* m_file = nullptr; 11866 #if defined(_MSC_VER) 11867 char m_buffer[L_tmpnam] = { 0 }; 11868 #endif 11869 }; 11870 11871 class OutputRedirect { 11872 public: 11873 OutputRedirect(OutputRedirect const&) = delete; 11874 OutputRedirect& operator=(OutputRedirect const&) = delete; 11875 OutputRedirect(OutputRedirect&&) = delete; 11876 OutputRedirect& operator=(OutputRedirect&&) = delete; 11877 11878 OutputRedirect(std::string& stdout_dest, std::string& stderr_dest); 11879 ~OutputRedirect(); 11880 11881 private: 11882 int m_originalStdout = -1; 11883 int m_originalStderr = -1; 11884 TempFile m_stdoutFile; 11885 TempFile m_stderrFile; 11886 std::string& m_stdoutDest; 11887 std::string& m_stderrDest; 11888 }; 11889 11890 #endif 11891 11892 } // end namespace Catch 11893 11894 #endif // TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H 11895 // end catch_output_redirect.h 11896 #include <cstdio> 11897 #include <cstring> 11898 #include <fstream> 11899 #include <sstream> 11900 #include <stdexcept> 11901 11902 #if defined(CATCH_CONFIG_NEW_CAPTURE) 11903 #if defined(_MSC_VER) 11904 #include <io.h> //_dup and _dup2 11905 #define dup _dup 11906 #define dup2 _dup2 11907 #define fileno _fileno 11908 #else 11909 #include <unistd.h> // dup and dup2 11910 #endif 11911 #endif 11912 11913 namespace Catch { 11914 11915 RedirectedStream::RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream ) 11916 : m_originalStream( originalStream ), 11917 m_redirectionStream( redirectionStream ), 11918 m_prevBuf( m_originalStream.rdbuf() ) 11919 { 11920 m_originalStream.rdbuf( m_redirectionStream.rdbuf() ); 11921 } 11922 11923 RedirectedStream::~RedirectedStream() { 11924 m_originalStream.rdbuf( m_prevBuf ); 11925 } 11926 11927 RedirectedStdOut::RedirectedStdOut() : m_cout( Catch::cout(), m_rss.get() ) {} 11928 auto RedirectedStdOut::str() const -> std::string { return m_rss.str(); } 11929 11930 RedirectedStdErr::RedirectedStdErr() 11931 : m_cerr( Catch::cerr(), m_rss.get() ), 11932 m_clog( Catch::clog(), m_rss.get() ) 11933 {} 11934 auto RedirectedStdErr::str() const -> std::string { return m_rss.str(); } 11935 11936 RedirectedStreams::RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr) 11937 : m_redirectedCout(redirectedCout), 11938 m_redirectedCerr(redirectedCerr) 11939 {} 11940 11941 RedirectedStreams::~RedirectedStreams() { 11942 m_redirectedCout += m_redirectedStdOut.str(); 11943 m_redirectedCerr += m_redirectedStdErr.str(); 11944 } 11945 11946 #if defined(CATCH_CONFIG_NEW_CAPTURE) 11947 11948 #if defined(_MSC_VER) 11949 TempFile::TempFile() { 11950 if (tmpnam_s(m_buffer)) { 11951 CATCH_RUNTIME_ERROR("Could not get a temp filename"); 11952 } 11953 if (fopen_s(&m_file, m_buffer, "w")) { 11954 char buffer[100]; 11955 if (strerror_s(buffer, errno)) { 11956 CATCH_RUNTIME_ERROR("Could not translate errno to a string"); 11957 } 11958 CATCH_RUNTIME_ERROR("Could not open the temp file: '" << m_buffer << "' because: " << buffer); 11959 } 11960 } 11961 #else 11962 TempFile::TempFile() { 11963 m_file = std::tmpfile(); 11964 if (!m_file) { 11965 CATCH_RUNTIME_ERROR("Could not create a temp file."); 11966 } 11967 } 11968 11969 #endif 11970 11971 TempFile::~TempFile() { 11972 // TBD: What to do about errors here? 11973 std::fclose(m_file); 11974 // We manually create the file on Windows only, on Linux 11975 // it will be autodeleted 11976 #if defined(_MSC_VER) 11977 std::remove(m_buffer); 11978 #endif 11979 } 11980 11981 FILE* TempFile::getFile() { 11982 return m_file; 11983 } 11984 11985 std::string TempFile::getContents() { 11986 std::stringstream sstr; 11987 char buffer[100] = {}; 11988 std::rewind(m_file); 11989 while (std::fgets(buffer, sizeof(buffer), m_file)) { 11990 sstr << buffer; 11991 } 11992 return sstr.str(); 11993 } 11994 11995 OutputRedirect::OutputRedirect(std::string& stdout_dest, std::string& stderr_dest) : 11996 m_originalStdout(dup(1)), 11997 m_originalStderr(dup(2)), 11998 m_stdoutDest(stdout_dest), 11999 m_stderrDest(stderr_dest) { 12000 dup2(fileno(m_stdoutFile.getFile()), 1); 12001 dup2(fileno(m_stderrFile.getFile()), 2); 12002 } 12003 12004 OutputRedirect::~OutputRedirect() { 12005 Catch::cout() << std::flush; 12006 fflush(stdout); 12007 // Since we support overriding these streams, we flush cerr 12008 // even though std::cerr is unbuffered 12009 Catch::cerr() << std::flush; 12010 Catch::clog() << std::flush; 12011 fflush(stderr); 12012 12013 dup2(m_originalStdout, 1); 12014 dup2(m_originalStderr, 2); 12015 12016 m_stdoutDest += m_stdoutFile.getContents(); 12017 m_stderrDest += m_stderrFile.getContents(); 12018 } 12019 12020 #endif // CATCH_CONFIG_NEW_CAPTURE 12021 12022 } // namespace Catch 12023 12024 #if defined(CATCH_CONFIG_NEW_CAPTURE) 12025 #if defined(_MSC_VER) 12026 #undef dup 12027 #undef dup2 12028 #undef fileno 12029 #endif 12030 #endif 12031 // end catch_output_redirect.cpp 12032 // start catch_polyfills.cpp 12033 12034 #include <cmath> 12035 12036 namespace Catch { 12037 12038 #if !defined(CATCH_CONFIG_POLYFILL_ISNAN) 12039 bool isnan(float f) { 12040 return std::isnan(f); 12041 } 12042 bool isnan(double d) { 12043 return std::isnan(d); 12044 } 12045 #else 12046 // For now we only use this for embarcadero 12047 bool isnan(float f) { 12048 return std::_isnan(f); 12049 } 12050 bool isnan(double d) { 12051 return std::_isnan(d); 12052 } 12053 #endif 12054 12055 } // end namespace Catch 12056 // end catch_polyfills.cpp 12057 // start catch_random_number_generator.cpp 12058 12059 namespace Catch { 12060 12061 namespace { 12062 12063 #if defined(_MSC_VER) 12064 #pragma warning(push) 12065 #pragma warning(disable:4146) // we negate uint32 during the rotate 12066 #endif 12067 // Safe rotr implementation thanks to John Regehr 12068 uint32_t rotate_right(uint32_t val, uint32_t count) { 12069 const uint32_t mask = 31; 12070 count &= mask; 12071 return (val >> count) | (val << (-count & mask)); 12072 } 12073 12074 #if defined(_MSC_VER) 12075 #pragma warning(pop) 12076 #endif 12077 12078 } 12079 12080 SimplePcg32::SimplePcg32(result_type seed_) { 12081 seed(seed_); 12082 } 12083 12084 void SimplePcg32::seed(result_type seed_) { 12085 m_state = 0; 12086 (*this)(); 12087 m_state += seed_; 12088 (*this)(); 12089 } 12090 12091 void SimplePcg32::discard(uint64_t skip) { 12092 // We could implement this to run in O(log n) steps, but this 12093 // should suffice for our use case. 12094 for (uint64_t s = 0; s < skip; ++s) { 12095 static_cast<void>((*this)()); 12096 } 12097 } 12098 12099 SimplePcg32::result_type SimplePcg32::operator()() { 12100 // prepare the output value 12101 const uint32_t xorshifted = static_cast<uint32_t>(((m_state >> 18u) ^ m_state) >> 27u); 12102 const auto output = rotate_right(xorshifted, m_state >> 59u); 12103 12104 // advance state 12105 m_state = m_state * 6364136223846793005ULL + s_inc; 12106 12107 return output; 12108 } 12109 12110 bool operator==(SimplePcg32 const& lhs, SimplePcg32 const& rhs) { 12111 return lhs.m_state == rhs.m_state; 12112 } 12113 12114 bool operator!=(SimplePcg32 const& lhs, SimplePcg32 const& rhs) { 12115 return lhs.m_state != rhs.m_state; 12116 } 12117 } 12118 // end catch_random_number_generator.cpp 12119 // start catch_registry_hub.cpp 12120 12121 // start catch_test_case_registry_impl.h 12122 12123 #include <vector> 12124 #include <set> 12125 #include <algorithm> 12126 #include <ios> 12127 12128 namespace Catch { 12129 12130 class TestCase; 12131 struct IConfig; 12132 12133 std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ); 12134 12135 bool isThrowSafe( TestCase const& testCase, IConfig const& config ); 12136 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); 12137 12138 void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ); 12139 12140 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ); 12141 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ); 12142 12143 class TestRegistry : public ITestCaseRegistry { 12144 public: 12145 virtual ~TestRegistry() = default; 12146 12147 virtual void registerTest( TestCase const& testCase ); 12148 12149 std::vector<TestCase> const& getAllTests() const override; 12150 std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const override; 12151 12152 private: 12153 std::vector<TestCase> m_functions; 12154 mutable RunTests::InWhatOrder m_currentSortOrder = RunTests::InDeclarationOrder; 12155 mutable std::vector<TestCase> m_sortedFunctions; 12156 std::size_t m_unnamedCount = 0; 12157 std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised 12158 }; 12159 12160 /////////////////////////////////////////////////////////////////////////// 12161 12162 class TestInvokerAsFunction : public ITestInvoker { 12163 void(*m_testAsFunction)(); 12164 public: 12165 TestInvokerAsFunction( void(*testAsFunction)() ) noexcept; 12166 12167 void invoke() const override; 12168 }; 12169 12170 std::string extractClassName( StringRef const& classOrQualifiedMethodName ); 12171 12172 /////////////////////////////////////////////////////////////////////////// 12173 12174 } // end namespace Catch 12175 12176 // end catch_test_case_registry_impl.h 12177 // start catch_reporter_registry.h 12178 12179 #include <map> 12180 12181 namespace Catch { 12182 12183 class ReporterRegistry : public IReporterRegistry { 12184 12185 public: 12186 12187 ~ReporterRegistry() override; 12188 12189 IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const override; 12190 12191 void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ); 12192 void registerListener( IReporterFactoryPtr const& factory ); 12193 12194 FactoryMap const& getFactories() const override; 12195 Listeners const& getListeners() const override; 12196 12197 private: 12198 FactoryMap m_factories; 12199 Listeners m_listeners; 12200 }; 12201 } 12202 12203 // end catch_reporter_registry.h 12204 // start catch_tag_alias_registry.h 12205 12206 // start catch_tag_alias.h 12207 12208 #include <string> 12209 12210 namespace Catch { 12211 12212 struct TagAlias { 12213 TagAlias(std::string const& _tag, SourceLineInfo _lineInfo); 12214 12215 std::string tag; 12216 SourceLineInfo lineInfo; 12217 }; 12218 12219 } // end namespace Catch 12220 12221 // end catch_tag_alias.h 12222 #include <map> 12223 12224 namespace Catch { 12225 12226 class TagAliasRegistry : public ITagAliasRegistry { 12227 public: 12228 ~TagAliasRegistry() override; 12229 TagAlias const* find( std::string const& alias ) const override; 12230 std::string expandAliases( std::string const& unexpandedTestSpec ) const override; 12231 void add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ); 12232 12233 private: 12234 std::map<std::string, TagAlias> m_registry; 12235 }; 12236 12237 } // end namespace Catch 12238 12239 // end catch_tag_alias_registry.h 12240 // start catch_startup_exception_registry.h 12241 12242 #include <vector> 12243 #include <exception> 12244 12245 namespace Catch { 12246 12247 class StartupExceptionRegistry { 12248 public: 12249 void add(std::exception_ptr const& exception) noexcept; 12250 std::vector<std::exception_ptr> const& getExceptions() const noexcept; 12251 private: 12252 std::vector<std::exception_ptr> m_exceptions; 12253 }; 12254 12255 } // end namespace Catch 12256 12257 // end catch_startup_exception_registry.h 12258 // start catch_singletons.hpp 12259 12260 namespace Catch { 12261 12262 struct ISingleton { 12263 virtual ~ISingleton(); 12264 }; 12265 12266 void addSingleton( ISingleton* singleton ); 12267 void cleanupSingletons(); 12268 12269 template<typename SingletonImplT, typename InterfaceT = SingletonImplT, typename MutableInterfaceT = InterfaceT> 12270 class Singleton : SingletonImplT, public ISingleton { 12271 12272 static auto getInternal() -> Singleton* { 12273 static Singleton* s_instance = nullptr; 12274 if( !s_instance ) { 12275 s_instance = new Singleton; 12276 addSingleton( s_instance ); 12277 } 12278 return s_instance; 12279 } 12280 12281 public: 12282 static auto get() -> InterfaceT const& { 12283 return *getInternal(); 12284 } 12285 static auto getMutable() -> MutableInterfaceT& { 12286 return *getInternal(); 12287 } 12288 }; 12289 12290 } // namespace Catch 12291 12292 // end catch_singletons.hpp 12293 namespace Catch { 12294 12295 namespace { 12296 12297 class RegistryHub : public IRegistryHub, public IMutableRegistryHub, 12298 private NonCopyable { 12299 12300 public: // IRegistryHub 12301 RegistryHub() = default; 12302 IReporterRegistry const& getReporterRegistry() const override { 12303 return m_reporterRegistry; 12304 } 12305 ITestCaseRegistry const& getTestCaseRegistry() const override { 12306 return m_testCaseRegistry; 12307 } 12308 IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const override { 12309 return m_exceptionTranslatorRegistry; 12310 } 12311 ITagAliasRegistry const& getTagAliasRegistry() const override { 12312 return m_tagAliasRegistry; 12313 } 12314 StartupExceptionRegistry const& getStartupExceptionRegistry() const override { 12315 return m_exceptionRegistry; 12316 } 12317 12318 public: // IMutableRegistryHub 12319 void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) override { 12320 m_reporterRegistry.registerReporter( name, factory ); 12321 } 12322 void registerListener( IReporterFactoryPtr const& factory ) override { 12323 m_reporterRegistry.registerListener( factory ); 12324 } 12325 void registerTest( TestCase const& testInfo ) override { 12326 m_testCaseRegistry.registerTest( testInfo ); 12327 } 12328 void registerTranslator( const IExceptionTranslator* translator ) override { 12329 m_exceptionTranslatorRegistry.registerTranslator( translator ); 12330 } 12331 void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) override { 12332 m_tagAliasRegistry.add( alias, tag, lineInfo ); 12333 } 12334 void registerStartupException() noexcept override { 12335 m_exceptionRegistry.add(std::current_exception()); 12336 } 12337 IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() override { 12338 return m_enumValuesRegistry; 12339 } 12340 12341 private: 12342 TestRegistry m_testCaseRegistry; 12343 ReporterRegistry m_reporterRegistry; 12344 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; 12345 TagAliasRegistry m_tagAliasRegistry; 12346 StartupExceptionRegistry m_exceptionRegistry; 12347 Detail::EnumValuesRegistry m_enumValuesRegistry; 12348 }; 12349 } 12350 12351 using RegistryHubSingleton = Singleton<RegistryHub, IRegistryHub, IMutableRegistryHub>; 12352 12353 IRegistryHub const& getRegistryHub() { 12354 return RegistryHubSingleton::get(); 12355 } 12356 IMutableRegistryHub& getMutableRegistryHub() { 12357 return RegistryHubSingleton::getMutable(); 12358 } 12359 void cleanUp() { 12360 cleanupSingletons(); 12361 cleanUpContext(); 12362 } 12363 std::string translateActiveException() { 12364 return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); 12365 } 12366 12367 } // end namespace Catch 12368 // end catch_registry_hub.cpp 12369 // start catch_reporter_registry.cpp 12370 12371 namespace Catch { 12372 12373 ReporterRegistry::~ReporterRegistry() = default; 12374 12375 IStreamingReporterPtr ReporterRegistry::create( std::string const& name, IConfigPtr const& config ) const { 12376 auto it = m_factories.find( name ); 12377 if( it == m_factories.end() ) 12378 return nullptr; 12379 return it->second->create( ReporterConfig( config ) ); 12380 } 12381 12382 void ReporterRegistry::registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) { 12383 m_factories.emplace(name, factory); 12384 } 12385 void ReporterRegistry::registerListener( IReporterFactoryPtr const& factory ) { 12386 m_listeners.push_back( factory ); 12387 } 12388 12389 IReporterRegistry::FactoryMap const& ReporterRegistry::getFactories() const { 12390 return m_factories; 12391 } 12392 IReporterRegistry::Listeners const& ReporterRegistry::getListeners() const { 12393 return m_listeners; 12394 } 12395 12396 } 12397 // end catch_reporter_registry.cpp 12398 // start catch_result_type.cpp 12399 12400 namespace Catch { 12401 12402 bool isOk( ResultWas::OfType resultType ) { 12403 return ( resultType & ResultWas::FailureBit ) == 0; 12404 } 12405 bool isJustInfo( int flags ) { 12406 return flags == ResultWas::Info; 12407 } 12408 12409 ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { 12410 return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( rhs ) ); 12411 } 12412 12413 bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; } 12414 bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; } 12415 12416 } // end namespace Catch 12417 // end catch_result_type.cpp 12418 // start catch_run_context.cpp 12419 12420 #include <cassert> 12421 #include <algorithm> 12422 #include <sstream> 12423 12424 namespace Catch { 12425 12426 namespace Generators { 12427 struct GeneratorTracker : TestCaseTracking::TrackerBase, IGeneratorTracker { 12428 GeneratorBasePtr m_generator; 12429 12430 GeneratorTracker( TestCaseTracking::NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) 12431 : TrackerBase( nameAndLocation, ctx, parent ) 12432 {} 12433 ~GeneratorTracker(); 12434 12435 static GeneratorTracker& acquire( TrackerContext& ctx, TestCaseTracking::NameAndLocation const& nameAndLocation ) { 12436 std::shared_ptr<GeneratorTracker> tracker; 12437 12438 ITracker& currentTracker = ctx.currentTracker(); 12439 if( TestCaseTracking::ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) { 12440 assert( childTracker ); 12441 assert( childTracker->isGeneratorTracker() ); 12442 tracker = std::static_pointer_cast<GeneratorTracker>( childTracker ); 12443 } 12444 else { 12445 tracker = std::make_shared<GeneratorTracker>( nameAndLocation, ctx, ¤tTracker ); 12446 currentTracker.addChild( tracker ); 12447 } 12448 12449 if( !ctx.completedCycle() && !tracker->isComplete() ) { 12450 tracker->open(); 12451 } 12452 12453 return *tracker; 12454 } 12455 12456 // TrackerBase interface 12457 bool isGeneratorTracker() const override { return true; } 12458 auto hasGenerator() const -> bool override { 12459 return !!m_generator; 12460 } 12461 void close() override { 12462 TrackerBase::close(); 12463 // Generator interface only finds out if it has another item on atual move 12464 if (m_runState == CompletedSuccessfully && m_generator->next()) { 12465 m_children.clear(); 12466 m_runState = Executing; 12467 } 12468 } 12469 12470 // IGeneratorTracker interface 12471 auto getGenerator() const -> GeneratorBasePtr const& override { 12472 return m_generator; 12473 } 12474 void setGenerator( GeneratorBasePtr&& generator ) override { 12475 m_generator = std::move( generator ); 12476 } 12477 }; 12478 GeneratorTracker::~GeneratorTracker() {} 12479 } 12480 12481 RunContext::RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter) 12482 : m_runInfo(_config->name()), 12483 m_context(getCurrentMutableContext()), 12484 m_config(_config), 12485 m_reporter(std::move(reporter)), 12486 m_lastAssertionInfo{ StringRef(), SourceLineInfo("",0), StringRef(), ResultDisposition::Normal }, 12487 m_includeSuccessfulResults( m_config->includeSuccessfulResults() || m_reporter->getPreferences().shouldReportAllAssertions ) 12488 { 12489 m_context.setRunner(this); 12490 m_context.setConfig(m_config); 12491 m_context.setResultCapture(this); 12492 m_reporter->testRunStarting(m_runInfo); 12493 } 12494 12495 RunContext::~RunContext() { 12496 m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, aborting())); 12497 } 12498 12499 void RunContext::testGroupStarting(std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount) { 12500 m_reporter->testGroupStarting(GroupInfo(testSpec, groupIndex, groupsCount)); 12501 } 12502 12503 void RunContext::testGroupEnded(std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount) { 12504 m_reporter->testGroupEnded(TestGroupStats(GroupInfo(testSpec, groupIndex, groupsCount), totals, aborting())); 12505 } 12506 12507 Totals RunContext::runTest(TestCase const& testCase) { 12508 Totals prevTotals = m_totals; 12509 12510 std::string redirectedCout; 12511 std::string redirectedCerr; 12512 12513 auto const& testInfo = testCase.getTestCaseInfo(); 12514 12515 m_reporter->testCaseStarting(testInfo); 12516 12517 m_activeTestCase = &testCase; 12518 12519 ITracker& rootTracker = m_trackerContext.startRun(); 12520 assert(rootTracker.isSectionTracker()); 12521 static_cast<SectionTracker&>(rootTracker).addInitialFilters(m_config->getSectionsToRun()); 12522 do { 12523 m_trackerContext.startCycle(); 12524 m_testCaseTracker = &SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(testInfo.name, testInfo.lineInfo)); 12525 runCurrentTest(redirectedCout, redirectedCerr); 12526 } while (!m_testCaseTracker->isSuccessfullyCompleted() && !aborting()); 12527 12528 Totals deltaTotals = m_totals.delta(prevTotals); 12529 if (testInfo.expectedToFail() && deltaTotals.testCases.passed > 0) { 12530 deltaTotals.assertions.failed++; 12531 deltaTotals.testCases.passed--; 12532 deltaTotals.testCases.failed++; 12533 } 12534 m_totals.testCases += deltaTotals.testCases; 12535 m_reporter->testCaseEnded(TestCaseStats(testInfo, 12536 deltaTotals, 12537 redirectedCout, 12538 redirectedCerr, 12539 aborting())); 12540 12541 m_activeTestCase = nullptr; 12542 m_testCaseTracker = nullptr; 12543 12544 return deltaTotals; 12545 } 12546 12547 IConfigPtr RunContext::config() const { 12548 return m_config; 12549 } 12550 12551 IStreamingReporter& RunContext::reporter() const { 12552 return *m_reporter; 12553 } 12554 12555 void RunContext::assertionEnded(AssertionResult const & result) { 12556 if (result.getResultType() == ResultWas::Ok) { 12557 m_totals.assertions.passed++; 12558 m_lastAssertionPassed = true; 12559 } else if (!result.isOk()) { 12560 m_lastAssertionPassed = false; 12561 if( m_activeTestCase->getTestCaseInfo().okToFail() ) 12562 m_totals.assertions.failedButOk++; 12563 else 12564 m_totals.assertions.failed++; 12565 } 12566 else { 12567 m_lastAssertionPassed = true; 12568 } 12569 12570 // We have no use for the return value (whether messages should be cleared), because messages were made scoped 12571 // and should be let to clear themselves out. 12572 static_cast<void>(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals))); 12573 12574 if (result.getResultType() != ResultWas::Warning) 12575 m_messageScopes.clear(); 12576 12577 // Reset working state 12578 resetAssertionInfo(); 12579 m_lastResult = result; 12580 } 12581 void RunContext::resetAssertionInfo() { 12582 m_lastAssertionInfo.macroName = StringRef(); 12583 m_lastAssertionInfo.capturedExpression = "{Unknown expression after the reported line}"_sr; 12584 } 12585 12586 bool RunContext::sectionStarted(SectionInfo const & sectionInfo, Counts & assertions) { 12587 ITracker& sectionTracker = SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(sectionInfo.name, sectionInfo.lineInfo)); 12588 if (!sectionTracker.isOpen()) 12589 return false; 12590 m_activeSections.push_back(§ionTracker); 12591 12592 m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; 12593 12594 m_reporter->sectionStarting(sectionInfo); 12595 12596 assertions = m_totals.assertions; 12597 12598 return true; 12599 } 12600 auto RunContext::acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& { 12601 using namespace Generators; 12602 GeneratorTracker& tracker = GeneratorTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( "generator", lineInfo ) ); 12603 assert( tracker.isOpen() ); 12604 m_lastAssertionInfo.lineInfo = lineInfo; 12605 return tracker; 12606 } 12607 12608 bool RunContext::testForMissingAssertions(Counts& assertions) { 12609 if (assertions.total() != 0) 12610 return false; 12611 if (!m_config->warnAboutMissingAssertions()) 12612 return false; 12613 if (m_trackerContext.currentTracker().hasChildren()) 12614 return false; 12615 m_totals.assertions.failed++; 12616 assertions.failed++; 12617 return true; 12618 } 12619 12620 void RunContext::sectionEnded(SectionEndInfo const & endInfo) { 12621 Counts assertions = m_totals.assertions - endInfo.prevAssertions; 12622 bool missingAssertions = testForMissingAssertions(assertions); 12623 12624 if (!m_activeSections.empty()) { 12625 m_activeSections.back()->close(); 12626 m_activeSections.pop_back(); 12627 } 12628 12629 m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions)); 12630 m_messages.clear(); 12631 m_messageScopes.clear(); 12632 } 12633 12634 void RunContext::sectionEndedEarly(SectionEndInfo const & endInfo) { 12635 if (m_unfinishedSections.empty()) 12636 m_activeSections.back()->fail(); 12637 else 12638 m_activeSections.back()->close(); 12639 m_activeSections.pop_back(); 12640 12641 m_unfinishedSections.push_back(endInfo); 12642 } 12643 12644 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 12645 void RunContext::benchmarkPreparing(std::string const& name) { 12646 m_reporter->benchmarkPreparing(name); 12647 } 12648 void RunContext::benchmarkStarting( BenchmarkInfo const& info ) { 12649 m_reporter->benchmarkStarting( info ); 12650 } 12651 void RunContext::benchmarkEnded( BenchmarkStats<> const& stats ) { 12652 m_reporter->benchmarkEnded( stats ); 12653 } 12654 void RunContext::benchmarkFailed(std::string const & error) { 12655 m_reporter->benchmarkFailed(error); 12656 } 12657 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 12658 12659 void RunContext::pushScopedMessage(MessageInfo const & message) { 12660 m_messages.push_back(message); 12661 } 12662 12663 void RunContext::popScopedMessage(MessageInfo const & message) { 12664 m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end()); 12665 } 12666 12667 void RunContext::emplaceUnscopedMessage( MessageBuilder const& builder ) { 12668 m_messageScopes.emplace_back( builder ); 12669 } 12670 12671 std::string RunContext::getCurrentTestName() const { 12672 return m_activeTestCase 12673 ? m_activeTestCase->getTestCaseInfo().name 12674 : std::string(); 12675 } 12676 12677 const AssertionResult * RunContext::getLastResult() const { 12678 return &(*m_lastResult); 12679 } 12680 12681 void RunContext::exceptionEarlyReported() { 12682 m_shouldReportUnexpected = false; 12683 } 12684 12685 void RunContext::handleFatalErrorCondition( StringRef message ) { 12686 // First notify reporter that bad things happened 12687 m_reporter->fatalErrorEncountered(message); 12688 12689 // Don't rebuild the result -- the stringification itself can cause more fatal errors 12690 // Instead, fake a result data. 12691 AssertionResultData tempResult( ResultWas::FatalErrorCondition, { false } ); 12692 tempResult.message = static_cast<std::string>(message); 12693 AssertionResult result(m_lastAssertionInfo, tempResult); 12694 12695 assertionEnded(result); 12696 12697 handleUnfinishedSections(); 12698 12699 // Recreate section for test case (as we will lose the one that was in scope) 12700 auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); 12701 SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name); 12702 12703 Counts assertions; 12704 assertions.failed = 1; 12705 SectionStats testCaseSectionStats(testCaseSection, assertions, 0, false); 12706 m_reporter->sectionEnded(testCaseSectionStats); 12707 12708 auto const& testInfo = m_activeTestCase->getTestCaseInfo(); 12709 12710 Totals deltaTotals; 12711 deltaTotals.testCases.failed = 1; 12712 deltaTotals.assertions.failed = 1; 12713 m_reporter->testCaseEnded(TestCaseStats(testInfo, 12714 deltaTotals, 12715 std::string(), 12716 std::string(), 12717 false)); 12718 m_totals.testCases.failed++; 12719 testGroupEnded(std::string(), m_totals, 1, 1); 12720 m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, false)); 12721 } 12722 12723 bool RunContext::lastAssertionPassed() { 12724 return m_lastAssertionPassed; 12725 } 12726 12727 void RunContext::assertionPassed() { 12728 m_lastAssertionPassed = true; 12729 ++m_totals.assertions.passed; 12730 resetAssertionInfo(); 12731 m_messageScopes.clear(); 12732 } 12733 12734 bool RunContext::aborting() const { 12735 return m_totals.assertions.failed >= static_cast<std::size_t>(m_config->abortAfter()); 12736 } 12737 12738 void RunContext::runCurrentTest(std::string & redirectedCout, std::string & redirectedCerr) { 12739 auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); 12740 SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name); 12741 m_reporter->sectionStarting(testCaseSection); 12742 Counts prevAssertions = m_totals.assertions; 12743 double duration = 0; 12744 m_shouldReportUnexpected = true; 12745 m_lastAssertionInfo = { "TEST_CASE"_sr, testCaseInfo.lineInfo, StringRef(), ResultDisposition::Normal }; 12746 12747 seedRng(*m_config); 12748 12749 Timer timer; 12750 CATCH_TRY { 12751 if (m_reporter->getPreferences().shouldRedirectStdOut) { 12752 #if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) 12753 RedirectedStreams redirectedStreams(redirectedCout, redirectedCerr); 12754 12755 timer.start(); 12756 invokeActiveTestCase(); 12757 #else 12758 OutputRedirect r(redirectedCout, redirectedCerr); 12759 timer.start(); 12760 invokeActiveTestCase(); 12761 #endif 12762 } else { 12763 timer.start(); 12764 invokeActiveTestCase(); 12765 } 12766 duration = timer.getElapsedSeconds(); 12767 } CATCH_CATCH_ANON (TestFailureException&) { 12768 // This just means the test was aborted due to failure 12769 } CATCH_CATCH_ALL { 12770 // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions 12771 // are reported without translation at the point of origin. 12772 if( m_shouldReportUnexpected ) { 12773 AssertionReaction dummyReaction; 12774 handleUnexpectedInflightException( m_lastAssertionInfo, translateActiveException(), dummyReaction ); 12775 } 12776 } 12777 Counts assertions = m_totals.assertions - prevAssertions; 12778 bool missingAssertions = testForMissingAssertions(assertions); 12779 12780 m_testCaseTracker->close(); 12781 handleUnfinishedSections(); 12782 m_messages.clear(); 12783 m_messageScopes.clear(); 12784 12785 SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions); 12786 m_reporter->sectionEnded(testCaseSectionStats); 12787 } 12788 12789 void RunContext::invokeActiveTestCase() { 12790 FatalConditionHandler fatalConditionHandler; // Handle signals 12791 m_activeTestCase->invoke(); 12792 fatalConditionHandler.reset(); 12793 } 12794 12795 void RunContext::handleUnfinishedSections() { 12796 // If sections ended prematurely due to an exception we stored their 12797 // infos here so we can tear them down outside the unwind process. 12798 for (auto it = m_unfinishedSections.rbegin(), 12799 itEnd = m_unfinishedSections.rend(); 12800 it != itEnd; 12801 ++it) 12802 sectionEnded(*it); 12803 m_unfinishedSections.clear(); 12804 } 12805 12806 void RunContext::handleExpr( 12807 AssertionInfo const& info, 12808 ITransientExpression const& expr, 12809 AssertionReaction& reaction 12810 ) { 12811 m_reporter->assertionStarting( info ); 12812 12813 bool negated = isFalseTest( info.resultDisposition ); 12814 bool result = expr.getResult() != negated; 12815 12816 if( result ) { 12817 if (!m_includeSuccessfulResults) { 12818 assertionPassed(); 12819 } 12820 else { 12821 reportExpr(info, ResultWas::Ok, &expr, negated); 12822 } 12823 } 12824 else { 12825 reportExpr(info, ResultWas::ExpressionFailed, &expr, negated ); 12826 populateReaction( reaction ); 12827 } 12828 } 12829 void RunContext::reportExpr( 12830 AssertionInfo const &info, 12831 ResultWas::OfType resultType, 12832 ITransientExpression const *expr, 12833 bool negated ) { 12834 12835 m_lastAssertionInfo = info; 12836 AssertionResultData data( resultType, LazyExpression( negated ) ); 12837 12838 AssertionResult assertionResult{ info, data }; 12839 assertionResult.m_resultData.lazyExpression.m_transientExpression = expr; 12840 12841 assertionEnded( assertionResult ); 12842 } 12843 12844 void RunContext::handleMessage( 12845 AssertionInfo const& info, 12846 ResultWas::OfType resultType, 12847 StringRef const& message, 12848 AssertionReaction& reaction 12849 ) { 12850 m_reporter->assertionStarting( info ); 12851 12852 m_lastAssertionInfo = info; 12853 12854 AssertionResultData data( resultType, LazyExpression( false ) ); 12855 data.message = static_cast<std::string>(message); 12856 AssertionResult assertionResult{ m_lastAssertionInfo, data }; 12857 assertionEnded( assertionResult ); 12858 if( !assertionResult.isOk() ) 12859 populateReaction( reaction ); 12860 } 12861 void RunContext::handleUnexpectedExceptionNotThrown( 12862 AssertionInfo const& info, 12863 AssertionReaction& reaction 12864 ) { 12865 handleNonExpr(info, Catch::ResultWas::DidntThrowException, reaction); 12866 } 12867 12868 void RunContext::handleUnexpectedInflightException( 12869 AssertionInfo const& info, 12870 std::string const& message, 12871 AssertionReaction& reaction 12872 ) { 12873 m_lastAssertionInfo = info; 12874 12875 AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) ); 12876 data.message = message; 12877 AssertionResult assertionResult{ info, data }; 12878 assertionEnded( assertionResult ); 12879 populateReaction( reaction ); 12880 } 12881 12882 void RunContext::populateReaction( AssertionReaction& reaction ) { 12883 reaction.shouldDebugBreak = m_config->shouldDebugBreak(); 12884 reaction.shouldThrow = aborting() || (m_lastAssertionInfo.resultDisposition & ResultDisposition::Normal); 12885 } 12886 12887 void RunContext::handleIncomplete( 12888 AssertionInfo const& info 12889 ) { 12890 m_lastAssertionInfo = info; 12891 12892 AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) ); 12893 data.message = "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE"; 12894 AssertionResult assertionResult{ info, data }; 12895 assertionEnded( assertionResult ); 12896 } 12897 void RunContext::handleNonExpr( 12898 AssertionInfo const &info, 12899 ResultWas::OfType resultType, 12900 AssertionReaction &reaction 12901 ) { 12902 m_lastAssertionInfo = info; 12903 12904 AssertionResultData data( resultType, LazyExpression( false ) ); 12905 AssertionResult assertionResult{ info, data }; 12906 assertionEnded( assertionResult ); 12907 12908 if( !assertionResult.isOk() ) 12909 populateReaction( reaction ); 12910 } 12911 12912 IResultCapture& getResultCapture() { 12913 if (auto* capture = getCurrentContext().getResultCapture()) 12914 return *capture; 12915 else 12916 CATCH_INTERNAL_ERROR("No result capture instance"); 12917 } 12918 12919 void seedRng(IConfig const& config) { 12920 if (config.rngSeed() != 0) { 12921 std::srand(config.rngSeed()); 12922 rng().seed(config.rngSeed()); 12923 } 12924 } 12925 12926 unsigned int rngSeed() { 12927 return getCurrentContext().getConfig()->rngSeed(); 12928 } 12929 12930 } 12931 // end catch_run_context.cpp 12932 // start catch_section.cpp 12933 12934 namespace Catch { 12935 12936 Section::Section( SectionInfo const& info ) 12937 : m_info( info ), 12938 m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) ) 12939 { 12940 m_timer.start(); 12941 } 12942 12943 Section::~Section() { 12944 if( m_sectionIncluded ) { 12945 SectionEndInfo endInfo{ m_info, m_assertions, m_timer.getElapsedSeconds() }; 12946 if( uncaught_exceptions() ) 12947 getResultCapture().sectionEndedEarly( endInfo ); 12948 else 12949 getResultCapture().sectionEnded( endInfo ); 12950 } 12951 } 12952 12953 // This indicates whether the section should be executed or not 12954 Section::operator bool() const { 12955 return m_sectionIncluded; 12956 } 12957 12958 } // end namespace Catch 12959 // end catch_section.cpp 12960 // start catch_section_info.cpp 12961 12962 namespace Catch { 12963 12964 SectionInfo::SectionInfo 12965 ( SourceLineInfo const& _lineInfo, 12966 std::string const& _name ) 12967 : name( _name ), 12968 lineInfo( _lineInfo ) 12969 {} 12970 12971 } // end namespace Catch 12972 // end catch_section_info.cpp 12973 // start catch_session.cpp 12974 12975 // start catch_session.h 12976 12977 #include <memory> 12978 12979 namespace Catch { 12980 12981 class Session : NonCopyable { 12982 public: 12983 12984 Session(); 12985 ~Session() override; 12986 12987 void showHelp() const; 12988 void libIdentify(); 12989 12990 int applyCommandLine( int argc, char const * const * argv ); 12991 #if defined(CATCH_CONFIG_WCHAR) && defined(_WIN32) && defined(UNICODE) 12992 int applyCommandLine( int argc, wchar_t const * const * argv ); 12993 #endif 12994 12995 void useConfigData( ConfigData const& configData ); 12996 12997 template<typename CharT> 12998 int run(int argc, CharT const * const argv[]) { 12999 if (m_startupExceptions) 13000 return 1; 13001 int returnCode = applyCommandLine(argc, argv); 13002 if (returnCode == 0) 13003 returnCode = run(); 13004 return returnCode; 13005 } 13006 13007 int run(); 13008 13009 clara::Parser const& cli() const; 13010 void cli( clara::Parser const& newParser ); 13011 ConfigData& configData(); 13012 Config& config(); 13013 private: 13014 int runInternal(); 13015 13016 clara::Parser m_cli; 13017 ConfigData m_configData; 13018 std::shared_ptr<Config> m_config; 13019 bool m_startupExceptions = false; 13020 }; 13021 13022 } // end namespace Catch 13023 13024 // end catch_session.h 13025 // start catch_version.h 13026 13027 #include <iosfwd> 13028 13029 namespace Catch { 13030 13031 // Versioning information 13032 struct Version { 13033 Version( Version const& ) = delete; 13034 Version& operator=( Version const& ) = delete; 13035 Version( unsigned int _majorVersion, 13036 unsigned int _minorVersion, 13037 unsigned int _patchNumber, 13038 char const * const _branchName, 13039 unsigned int _buildNumber ); 13040 13041 unsigned int const majorVersion; 13042 unsigned int const minorVersion; 13043 unsigned int const patchNumber; 13044 13045 // buildNumber is only used if branchName is not null 13046 char const * const branchName; 13047 unsigned int const buildNumber; 13048 13049 friend std::ostream& operator << ( std::ostream& os, Version const& version ); 13050 }; 13051 13052 Version const& libraryVersion(); 13053 } 13054 13055 // end catch_version.h 13056 #include <cstdlib> 13057 #include <iomanip> 13058 #include <set> 13059 #include <iterator> 13060 13061 namespace Catch { 13062 13063 namespace { 13064 const int MaxExitCode = 255; 13065 13066 IStreamingReporterPtr createReporter(std::string const& reporterName, IConfigPtr const& config) { 13067 auto reporter = Catch::getRegistryHub().getReporterRegistry().create(reporterName, config); 13068 CATCH_ENFORCE(reporter, "No reporter registered with name: '" << reporterName << "'"); 13069 13070 return reporter; 13071 } 13072 13073 IStreamingReporterPtr makeReporter(std::shared_ptr<Config> const& config) { 13074 if (Catch::getRegistryHub().getReporterRegistry().getListeners().empty()) { 13075 return createReporter(config->getReporterName(), config); 13076 } 13077 13078 // On older platforms, returning std::unique_ptr<ListeningReporter> 13079 // when the return type is std::unique_ptr<IStreamingReporter> 13080 // doesn't compile without a std::move call. However, this causes 13081 // a warning on newer platforms. Thus, we have to work around 13082 // it a bit and downcast the pointer manually. 13083 auto ret = std::unique_ptr<IStreamingReporter>(new ListeningReporter); 13084 auto& multi = static_cast<ListeningReporter&>(*ret); 13085 auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners(); 13086 for (auto const& listener : listeners) { 13087 multi.addListener(listener->create(Catch::ReporterConfig(config))); 13088 } 13089 multi.addReporter(createReporter(config->getReporterName(), config)); 13090 return ret; 13091 } 13092 13093 class TestGroup { 13094 public: 13095 explicit TestGroup(std::shared_ptr<Config> const& config) 13096 : m_config{config} 13097 , m_context{config, makeReporter(config)} 13098 { 13099 auto const& allTestCases = getAllTestCasesSorted(*m_config); 13100 m_matches = m_config->testSpec().matchesByFilter(allTestCases, *m_config); 13101 auto const& invalidArgs = m_config->testSpec().getInvalidArgs(); 13102 13103 if (m_matches.empty() && invalidArgs.empty()) { 13104 for (auto const& test : allTestCases) 13105 if (!test.isHidden()) 13106 m_tests.emplace(&test); 13107 } else { 13108 for (auto const& match : m_matches) 13109 m_tests.insert(match.tests.begin(), match.tests.end()); 13110 } 13111 } 13112 13113 Totals execute() { 13114 auto const& invalidArgs = m_config->testSpec().getInvalidArgs(); 13115 Totals totals; 13116 m_context.testGroupStarting(m_config->name(), 1, 1); 13117 for (auto const& testCase : m_tests) { 13118 if (!m_context.aborting()) 13119 totals += m_context.runTest(*testCase); 13120 else 13121 m_context.reporter().skipTest(*testCase); 13122 } 13123 13124 for (auto const& match : m_matches) { 13125 if (match.tests.empty()) { 13126 m_context.reporter().noMatchingTestCases(match.name); 13127 totals.error = -1; 13128 } 13129 } 13130 13131 if (!invalidArgs.empty()) { 13132 for (auto const& invalidArg: invalidArgs) 13133 m_context.reporter().reportInvalidArguments(invalidArg); 13134 } 13135 13136 m_context.testGroupEnded(m_config->name(), totals, 1, 1); 13137 return totals; 13138 } 13139 13140 private: 13141 using Tests = std::set<TestCase const*>; 13142 13143 std::shared_ptr<Config> m_config; 13144 RunContext m_context; 13145 Tests m_tests; 13146 TestSpec::Matches m_matches; 13147 }; 13148 13149 void applyFilenamesAsTags(Catch::IConfig const& config) { 13150 auto& tests = const_cast<std::vector<TestCase>&>(getAllTestCasesSorted(config)); 13151 for (auto& testCase : tests) { 13152 auto tags = testCase.tags; 13153 13154 std::string filename = testCase.lineInfo.file; 13155 auto lastSlash = filename.find_last_of("\\/"); 13156 if (lastSlash != std::string::npos) { 13157 filename.erase(0, lastSlash); 13158 filename[0] = '#'; 13159 } 13160 13161 auto lastDot = filename.find_last_of('.'); 13162 if (lastDot != std::string::npos) { 13163 filename.erase(lastDot); 13164 } 13165 13166 tags.push_back(std::move(filename)); 13167 setTags(testCase, tags); 13168 } 13169 } 13170 13171 } // anon namespace 13172 13173 Session::Session() { 13174 static bool alreadyInstantiated = false; 13175 if( alreadyInstantiated ) { 13176 CATCH_TRY { CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" ); } 13177 CATCH_CATCH_ALL { getMutableRegistryHub().registerStartupException(); } 13178 } 13179 13180 // There cannot be exceptions at startup in no-exception mode. 13181 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 13182 const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions(); 13183 if ( !exceptions.empty() ) { 13184 config(); 13185 getCurrentMutableContext().setConfig(m_config); 13186 13187 m_startupExceptions = true; 13188 Colour colourGuard( Colour::Red ); 13189 Catch::cerr() << "Errors occurred during startup!" << '\n'; 13190 // iterate over all exceptions and notify user 13191 for ( const auto& ex_ptr : exceptions ) { 13192 try { 13193 std::rethrow_exception(ex_ptr); 13194 } catch ( std::exception const& ex ) { 13195 Catch::cerr() << Column( ex.what() ).indent(2) << '\n'; 13196 } 13197 } 13198 } 13199 #endif 13200 13201 alreadyInstantiated = true; 13202 m_cli = makeCommandLineParser( m_configData ); 13203 } 13204 Session::~Session() { 13205 Catch::cleanUp(); 13206 } 13207 13208 void Session::showHelp() const { 13209 Catch::cout() 13210 << "\nCatch v" << libraryVersion() << "\n" 13211 << m_cli << std::endl 13212 << "For more detailed usage please see the project docs\n" << std::endl; 13213 } 13214 void Session::libIdentify() { 13215 Catch::cout() 13216 << std::left << std::setw(16) << "description: " << "A Catch2 test executable\n" 13217 << std::left << std::setw(16) << "category: " << "testframework\n" 13218 << std::left << std::setw(16) << "framework: " << "Catch Test\n" 13219 << std::left << std::setw(16) << "version: " << libraryVersion() << std::endl; 13220 } 13221 13222 int Session::applyCommandLine( int argc, char const * const * argv ) { 13223 if( m_startupExceptions ) 13224 return 1; 13225 13226 auto result = m_cli.parse( clara::Args( argc, argv ) ); 13227 if( !result ) { 13228 config(); 13229 getCurrentMutableContext().setConfig(m_config); 13230 Catch::cerr() 13231 << Colour( Colour::Red ) 13232 << "\nError(s) in input:\n" 13233 << Column( result.errorMessage() ).indent( 2 ) 13234 << "\n\n"; 13235 Catch::cerr() << "Run with -? for usage\n" << std::endl; 13236 return MaxExitCode; 13237 } 13238 13239 if( m_configData.showHelp ) 13240 showHelp(); 13241 if( m_configData.libIdentify ) 13242 libIdentify(); 13243 m_config.reset(); 13244 return 0; 13245 } 13246 13247 #if defined(CATCH_CONFIG_WCHAR) && defined(_WIN32) && defined(UNICODE) 13248 int Session::applyCommandLine( int argc, wchar_t const * const * argv ) { 13249 13250 char **utf8Argv = new char *[ argc ]; 13251 13252 for ( int i = 0; i < argc; ++i ) { 13253 int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL ); 13254 13255 utf8Argv[ i ] = new char[ bufSize ]; 13256 13257 WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL ); 13258 } 13259 13260 int returnCode = applyCommandLine( argc, utf8Argv ); 13261 13262 for ( int i = 0; i < argc; ++i ) 13263 delete [] utf8Argv[ i ]; 13264 13265 delete [] utf8Argv; 13266 13267 return returnCode; 13268 } 13269 #endif 13270 13271 void Session::useConfigData( ConfigData const& configData ) { 13272 m_configData = configData; 13273 m_config.reset(); 13274 } 13275 13276 int Session::run() { 13277 if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) { 13278 Catch::cout() << "...waiting for enter/ return before starting" << std::endl; 13279 static_cast<void>(std::getchar()); 13280 } 13281 int exitCode = runInternal(); 13282 if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) { 13283 Catch::cout() << "...waiting for enter/ return before exiting, with code: " << exitCode << std::endl; 13284 static_cast<void>(std::getchar()); 13285 } 13286 return exitCode; 13287 } 13288 13289 clara::Parser const& Session::cli() const { 13290 return m_cli; 13291 } 13292 void Session::cli( clara::Parser const& newParser ) { 13293 m_cli = newParser; 13294 } 13295 ConfigData& Session::configData() { 13296 return m_configData; 13297 } 13298 Config& Session::config() { 13299 if( !m_config ) 13300 m_config = std::make_shared<Config>( m_configData ); 13301 return *m_config; 13302 } 13303 13304 int Session::runInternal() { 13305 if( m_startupExceptions ) 13306 return 1; 13307 13308 if (m_configData.showHelp || m_configData.libIdentify) { 13309 return 0; 13310 } 13311 13312 CATCH_TRY { 13313 config(); // Force config to be constructed 13314 13315 seedRng( *m_config ); 13316 13317 if( m_configData.filenamesAsTags ) 13318 applyFilenamesAsTags( *m_config ); 13319 13320 // Handle list request 13321 if( Option<std::size_t> listed = list( m_config ) ) 13322 return static_cast<int>( *listed ); 13323 13324 TestGroup tests { m_config }; 13325 auto const totals = tests.execute(); 13326 13327 if( m_config->warnAboutNoTests() && totals.error == -1 ) 13328 return 2; 13329 13330 // Note that on unices only the lower 8 bits are usually used, clamping 13331 // the return value to 255 prevents false negative when some multiple 13332 // of 256 tests has failed 13333 return (std::min) (MaxExitCode, (std::max) (totals.error, static_cast<int>(totals.assertions.failed))); 13334 } 13335 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 13336 catch( std::exception& ex ) { 13337 Catch::cerr() << ex.what() << std::endl; 13338 return MaxExitCode; 13339 } 13340 #endif 13341 } 13342 13343 } // end namespace Catch 13344 // end catch_session.cpp 13345 // start catch_singletons.cpp 13346 13347 #include <vector> 13348 13349 namespace Catch { 13350 13351 namespace { 13352 static auto getSingletons() -> std::vector<ISingleton*>*& { 13353 static std::vector<ISingleton*>* g_singletons = nullptr; 13354 if( !g_singletons ) 13355 g_singletons = new std::vector<ISingleton*>(); 13356 return g_singletons; 13357 } 13358 } 13359 13360 ISingleton::~ISingleton() {} 13361 13362 void addSingleton(ISingleton* singleton ) { 13363 getSingletons()->push_back( singleton ); 13364 } 13365 void cleanupSingletons() { 13366 auto& singletons = getSingletons(); 13367 for( auto singleton : *singletons ) 13368 delete singleton; 13369 delete singletons; 13370 singletons = nullptr; 13371 } 13372 13373 } // namespace Catch 13374 // end catch_singletons.cpp 13375 // start catch_startup_exception_registry.cpp 13376 13377 namespace Catch { 13378 void StartupExceptionRegistry::add( std::exception_ptr const& exception ) noexcept { 13379 CATCH_TRY { 13380 m_exceptions.push_back(exception); 13381 } CATCH_CATCH_ALL { 13382 // If we run out of memory during start-up there's really not a lot more we can do about it 13383 std::terminate(); 13384 } 13385 } 13386 13387 std::vector<std::exception_ptr> const& StartupExceptionRegistry::getExceptions() const noexcept { 13388 return m_exceptions; 13389 } 13390 13391 } // end namespace Catch 13392 // end catch_startup_exception_registry.cpp 13393 // start catch_stream.cpp 13394 13395 #include <cstdio> 13396 #include <iostream> 13397 #include <fstream> 13398 #include <sstream> 13399 #include <vector> 13400 #include <memory> 13401 13402 namespace Catch { 13403 13404 Catch::IStream::~IStream() = default; 13405 13406 namespace Detail { namespace { 13407 template<typename WriterF, std::size_t bufferSize=256> 13408 class StreamBufImpl : public std::streambuf { 13409 char data[bufferSize]; 13410 WriterF m_writer; 13411 13412 public: 13413 StreamBufImpl() { 13414 setp( data, data + sizeof(data) ); 13415 } 13416 13417 ~StreamBufImpl() noexcept { 13418 StreamBufImpl::sync(); 13419 } 13420 13421 private: 13422 int overflow( int c ) override { 13423 sync(); 13424 13425 if( c != EOF ) { 13426 if( pbase() == epptr() ) 13427 m_writer( std::string( 1, static_cast<char>( c ) ) ); 13428 else 13429 sputc( static_cast<char>( c ) ); 13430 } 13431 return 0; 13432 } 13433 13434 int sync() override { 13435 if( pbase() != pptr() ) { 13436 m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) ); 13437 setp( pbase(), epptr() ); 13438 } 13439 return 0; 13440 } 13441 }; 13442 13443 /////////////////////////////////////////////////////////////////////////// 13444 13445 struct OutputDebugWriter { 13446 13447 void operator()( std::string const&str ) { 13448 writeToDebugConsole( str ); 13449 } 13450 }; 13451 13452 /////////////////////////////////////////////////////////////////////////// 13453 13454 class FileStream : public IStream { 13455 mutable std::ofstream m_ofs; 13456 public: 13457 FileStream( StringRef filename ) { 13458 m_ofs.open( filename.c_str() ); 13459 CATCH_ENFORCE( !m_ofs.fail(), "Unable to open file: '" << filename << "'" ); 13460 } 13461 ~FileStream() override = default; 13462 public: // IStream 13463 std::ostream& stream() const override { 13464 return m_ofs; 13465 } 13466 }; 13467 13468 /////////////////////////////////////////////////////////////////////////// 13469 13470 class CoutStream : public IStream { 13471 mutable std::ostream m_os; 13472 public: 13473 // Store the streambuf from cout up-front because 13474 // cout may get redirected when running tests 13475 CoutStream() : m_os( Catch::cout().rdbuf() ) {} 13476 ~CoutStream() override = default; 13477 13478 public: // IStream 13479 std::ostream& stream() const override { return m_os; } 13480 }; 13481 13482 /////////////////////////////////////////////////////////////////////////// 13483 13484 class DebugOutStream : public IStream { 13485 std::unique_ptr<StreamBufImpl<OutputDebugWriter>> m_streamBuf; 13486 mutable std::ostream m_os; 13487 public: 13488 DebugOutStream() 13489 : m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ), 13490 m_os( m_streamBuf.get() ) 13491 {} 13492 13493 ~DebugOutStream() override = default; 13494 13495 public: // IStream 13496 std::ostream& stream() const override { return m_os; } 13497 }; 13498 13499 }} // namespace anon::detail 13500 13501 /////////////////////////////////////////////////////////////////////////// 13502 13503 auto makeStream( StringRef const &filename ) -> IStream const* { 13504 if( filename.empty() ) 13505 return new Detail::CoutStream(); 13506 else if( filename[0] == '%' ) { 13507 if( filename == "%debug" ) 13508 return new Detail::DebugOutStream(); 13509 else 13510 CATCH_ERROR( "Unrecognised stream: '" << filename << "'" ); 13511 } 13512 else 13513 return new Detail::FileStream( filename ); 13514 } 13515 13516 // This class encapsulates the idea of a pool of ostringstreams that can be reused. 13517 struct StringStreams { 13518 std::vector<std::unique_ptr<std::ostringstream>> m_streams; 13519 std::vector<std::size_t> m_unused; 13520 std::ostringstream m_referenceStream; // Used for copy state/ flags from 13521 13522 auto add() -> std::size_t { 13523 if( m_unused.empty() ) { 13524 m_streams.push_back( std::unique_ptr<std::ostringstream>( new std::ostringstream ) ); 13525 return m_streams.size()-1; 13526 } 13527 else { 13528 auto index = m_unused.back(); 13529 m_unused.pop_back(); 13530 return index; 13531 } 13532 } 13533 13534 void release( std::size_t index ) { 13535 m_streams[index]->copyfmt( m_referenceStream ); // Restore initial flags and other state 13536 m_unused.push_back(index); 13537 } 13538 }; 13539 13540 ReusableStringStream::ReusableStringStream() 13541 : m_index( Singleton<StringStreams>::getMutable().add() ), 13542 m_oss( Singleton<StringStreams>::getMutable().m_streams[m_index].get() ) 13543 {} 13544 13545 ReusableStringStream::~ReusableStringStream() { 13546 static_cast<std::ostringstream*>( m_oss )->str(""); 13547 m_oss->clear(); 13548 Singleton<StringStreams>::getMutable().release( m_index ); 13549 } 13550 13551 auto ReusableStringStream::str() const -> std::string { 13552 return static_cast<std::ostringstream*>( m_oss )->str(); 13553 } 13554 13555 /////////////////////////////////////////////////////////////////////////// 13556 13557 #ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions 13558 std::ostream& cout() { return std::cout; } 13559 std::ostream& cerr() { return std::cerr; } 13560 std::ostream& clog() { return std::clog; } 13561 #endif 13562 } 13563 // end catch_stream.cpp 13564 // start catch_string_manip.cpp 13565 13566 #include <algorithm> 13567 #include <ostream> 13568 #include <cstring> 13569 #include <cctype> 13570 #include <vector> 13571 13572 namespace Catch { 13573 13574 namespace { 13575 char toLowerCh(char c) { 13576 return static_cast<char>( std::tolower( c ) ); 13577 } 13578 } 13579 13580 bool startsWith( std::string const& s, std::string const& prefix ) { 13581 return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin()); 13582 } 13583 bool startsWith( std::string const& s, char prefix ) { 13584 return !s.empty() && s[0] == prefix; 13585 } 13586 bool endsWith( std::string const& s, std::string const& suffix ) { 13587 return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin()); 13588 } 13589 bool endsWith( std::string const& s, char suffix ) { 13590 return !s.empty() && s[s.size()-1] == suffix; 13591 } 13592 bool contains( std::string const& s, std::string const& infix ) { 13593 return s.find( infix ) != std::string::npos; 13594 } 13595 void toLowerInPlace( std::string& s ) { 13596 std::transform( s.begin(), s.end(), s.begin(), toLowerCh ); 13597 } 13598 std::string toLower( std::string const& s ) { 13599 std::string lc = s; 13600 toLowerInPlace( lc ); 13601 return lc; 13602 } 13603 std::string trim( std::string const& str ) { 13604 static char const* whitespaceChars = "\n\r\t "; 13605 std::string::size_type start = str.find_first_not_of( whitespaceChars ); 13606 std::string::size_type end = str.find_last_not_of( whitespaceChars ); 13607 13608 return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string(); 13609 } 13610 13611 StringRef trim(StringRef ref) { 13612 const auto is_ws = [](char c) { 13613 return c == ' ' || c == '\t' || c == '\n' || c == '\r'; 13614 }; 13615 size_t real_begin = 0; 13616 while (real_begin < ref.size() && is_ws(ref[real_begin])) { ++real_begin; } 13617 size_t real_end = ref.size(); 13618 while (real_end > real_begin && is_ws(ref[real_end - 1])) { --real_end; } 13619 13620 return ref.substr(real_begin, real_end - real_begin); 13621 } 13622 13623 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) { 13624 bool replaced = false; 13625 std::size_t i = str.find( replaceThis ); 13626 while( i != std::string::npos ) { 13627 replaced = true; 13628 str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() ); 13629 if( i < str.size()-withThis.size() ) 13630 i = str.find( replaceThis, i+withThis.size() ); 13631 else 13632 i = std::string::npos; 13633 } 13634 return replaced; 13635 } 13636 13637 std::vector<StringRef> splitStringRef( StringRef str, char delimiter ) { 13638 std::vector<StringRef> subStrings; 13639 std::size_t start = 0; 13640 for(std::size_t pos = 0; pos < str.size(); ++pos ) { 13641 if( str[pos] == delimiter ) { 13642 if( pos - start > 1 ) 13643 subStrings.push_back( str.substr( start, pos-start ) ); 13644 start = pos+1; 13645 } 13646 } 13647 if( start < str.size() ) 13648 subStrings.push_back( str.substr( start, str.size()-start ) ); 13649 return subStrings; 13650 } 13651 13652 pluralise::pluralise( std::size_t count, std::string const& label ) 13653 : m_count( count ), 13654 m_label( label ) 13655 {} 13656 13657 std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { 13658 os << pluraliser.m_count << ' ' << pluraliser.m_label; 13659 if( pluraliser.m_count != 1 ) 13660 os << 's'; 13661 return os; 13662 } 13663 13664 } 13665 // end catch_string_manip.cpp 13666 // start catch_stringref.cpp 13667 13668 #include <algorithm> 13669 #include <ostream> 13670 #include <cstring> 13671 #include <cstdint> 13672 13673 namespace Catch { 13674 StringRef::StringRef( char const* rawChars ) noexcept 13675 : StringRef( rawChars, static_cast<StringRef::size_type>(std::strlen(rawChars) ) ) 13676 {} 13677 13678 auto StringRef::c_str() const -> char const* { 13679 CATCH_ENFORCE(isNullTerminated(), "Called StringRef::c_str() on a non-null-terminated instance"); 13680 return m_start; 13681 } 13682 auto StringRef::data() const noexcept -> char const* { 13683 return m_start; 13684 } 13685 13686 auto StringRef::substr( size_type start, size_type size ) const noexcept -> StringRef { 13687 if (start < m_size) { 13688 return StringRef(m_start + start, (std::min)(m_size - start, size)); 13689 } else { 13690 return StringRef(); 13691 } 13692 } 13693 auto StringRef::operator == ( StringRef const& other ) const noexcept -> bool { 13694 return m_size == other.m_size 13695 && (std::memcmp( m_start, other.m_start, m_size ) == 0); 13696 } 13697 13698 auto operator << ( std::ostream& os, StringRef const& str ) -> std::ostream& { 13699 return os.write(str.data(), str.size()); 13700 } 13701 13702 auto operator+=( std::string& lhs, StringRef const& rhs ) -> std::string& { 13703 lhs.append(rhs.data(), rhs.size()); 13704 return lhs; 13705 } 13706 13707 } // namespace Catch 13708 // end catch_stringref.cpp 13709 // start catch_tag_alias.cpp 13710 13711 namespace Catch { 13712 TagAlias::TagAlias(std::string const & _tag, SourceLineInfo _lineInfo): tag(_tag), lineInfo(_lineInfo) {} 13713 } 13714 // end catch_tag_alias.cpp 13715 // start catch_tag_alias_autoregistrar.cpp 13716 13717 namespace Catch { 13718 13719 RegistrarForTagAliases::RegistrarForTagAliases(char const* alias, char const* tag, SourceLineInfo const& lineInfo) { 13720 CATCH_TRY { 13721 getMutableRegistryHub().registerTagAlias(alias, tag, lineInfo); 13722 } CATCH_CATCH_ALL { 13723 // Do not throw when constructing global objects, instead register the exception to be processed later 13724 getMutableRegistryHub().registerStartupException(); 13725 } 13726 } 13727 13728 } 13729 // end catch_tag_alias_autoregistrar.cpp 13730 // start catch_tag_alias_registry.cpp 13731 13732 #include <sstream> 13733 13734 namespace Catch { 13735 13736 TagAliasRegistry::~TagAliasRegistry() {} 13737 13738 TagAlias const* TagAliasRegistry::find( std::string const& alias ) const { 13739 auto it = m_registry.find( alias ); 13740 if( it != m_registry.end() ) 13741 return &(it->second); 13742 else 13743 return nullptr; 13744 } 13745 13746 std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const { 13747 std::string expandedTestSpec = unexpandedTestSpec; 13748 for( auto const& registryKvp : m_registry ) { 13749 std::size_t pos = expandedTestSpec.find( registryKvp.first ); 13750 if( pos != std::string::npos ) { 13751 expandedTestSpec = expandedTestSpec.substr( 0, pos ) + 13752 registryKvp.second.tag + 13753 expandedTestSpec.substr( pos + registryKvp.first.size() ); 13754 } 13755 } 13756 return expandedTestSpec; 13757 } 13758 13759 void TagAliasRegistry::add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) { 13760 CATCH_ENFORCE( startsWith(alias, "[@") && endsWith(alias, ']'), 13761 "error: tag alias, '" << alias << "' is not of the form [@alias name].\n" << lineInfo ); 13762 13763 CATCH_ENFORCE( m_registry.insert(std::make_pair(alias, TagAlias(tag, lineInfo))).second, 13764 "error: tag alias, '" << alias << "' already registered.\n" 13765 << "\tFirst seen at: " << find(alias)->lineInfo << "\n" 13766 << "\tRedefined at: " << lineInfo ); 13767 } 13768 13769 ITagAliasRegistry::~ITagAliasRegistry() {} 13770 13771 ITagAliasRegistry const& ITagAliasRegistry::get() { 13772 return getRegistryHub().getTagAliasRegistry(); 13773 } 13774 13775 } // end namespace Catch 13776 // end catch_tag_alias_registry.cpp 13777 // start catch_test_case_info.cpp 13778 13779 #include <cctype> 13780 #include <exception> 13781 #include <algorithm> 13782 #include <sstream> 13783 13784 namespace Catch { 13785 13786 namespace { 13787 TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) { 13788 if( startsWith( tag, '.' ) || 13789 tag == "!hide" ) 13790 return TestCaseInfo::IsHidden; 13791 else if( tag == "!throws" ) 13792 return TestCaseInfo::Throws; 13793 else if( tag == "!shouldfail" ) 13794 return TestCaseInfo::ShouldFail; 13795 else if( tag == "!mayfail" ) 13796 return TestCaseInfo::MayFail; 13797 else if( tag == "!nonportable" ) 13798 return TestCaseInfo::NonPortable; 13799 else if( tag == "!benchmark" ) 13800 return static_cast<TestCaseInfo::SpecialProperties>( TestCaseInfo::Benchmark | TestCaseInfo::IsHidden ); 13801 else 13802 return TestCaseInfo::None; 13803 } 13804 bool isReservedTag( std::string const& tag ) { 13805 return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( static_cast<unsigned char>(tag[0]) ); 13806 } 13807 void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { 13808 CATCH_ENFORCE( !isReservedTag(tag), 13809 "Tag name: [" << tag << "] is not allowed.\n" 13810 << "Tag names starting with non alphanumeric characters are reserved\n" 13811 << _lineInfo ); 13812 } 13813 } 13814 13815 TestCase makeTestCase( ITestInvoker* _testCase, 13816 std::string const& _className, 13817 NameAndTags const& nameAndTags, 13818 SourceLineInfo const& _lineInfo ) 13819 { 13820 bool isHidden = false; 13821 13822 // Parse out tags 13823 std::vector<std::string> tags; 13824 std::string desc, tag; 13825 bool inTag = false; 13826 for (char c : nameAndTags.tags) { 13827 if( !inTag ) { 13828 if( c == '[' ) 13829 inTag = true; 13830 else 13831 desc += c; 13832 } 13833 else { 13834 if( c == ']' ) { 13835 TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag ); 13836 if( ( prop & TestCaseInfo::IsHidden ) != 0 ) 13837 isHidden = true; 13838 else if( prop == TestCaseInfo::None ) 13839 enforceNotReservedTag( tag, _lineInfo ); 13840 13841 // Merged hide tags like `[.approvals]` should be added as 13842 // `[.][approvals]`. The `[.]` is added at later point, so 13843 // we only strip the prefix 13844 if (startsWith(tag, '.') && tag.size() > 1) { 13845 tag.erase(0, 1); 13846 } 13847 tags.push_back( tag ); 13848 tag.clear(); 13849 inTag = false; 13850 } 13851 else 13852 tag += c; 13853 } 13854 } 13855 if( isHidden ) { 13856 tags.push_back( "." ); 13857 } 13858 13859 TestCaseInfo info( static_cast<std::string>(nameAndTags.name), _className, desc, tags, _lineInfo ); 13860 return TestCase( _testCase, std::move(info) ); 13861 } 13862 13863 void setTags( TestCaseInfo& testCaseInfo, std::vector<std::string> tags ) { 13864 std::sort(begin(tags), end(tags)); 13865 tags.erase(std::unique(begin(tags), end(tags)), end(tags)); 13866 testCaseInfo.lcaseTags.clear(); 13867 13868 for( auto const& tag : tags ) { 13869 std::string lcaseTag = toLower( tag ); 13870 testCaseInfo.properties = static_cast<TestCaseInfo::SpecialProperties>( testCaseInfo.properties | parseSpecialTag( lcaseTag ) ); 13871 testCaseInfo.lcaseTags.push_back( lcaseTag ); 13872 } 13873 testCaseInfo.tags = std::move(tags); 13874 } 13875 13876 TestCaseInfo::TestCaseInfo( std::string const& _name, 13877 std::string const& _className, 13878 std::string const& _description, 13879 std::vector<std::string> const& _tags, 13880 SourceLineInfo const& _lineInfo ) 13881 : name( _name ), 13882 className( _className ), 13883 description( _description ), 13884 lineInfo( _lineInfo ), 13885 properties( None ) 13886 { 13887 setTags( *this, _tags ); 13888 } 13889 13890 bool TestCaseInfo::isHidden() const { 13891 return ( properties & IsHidden ) != 0; 13892 } 13893 bool TestCaseInfo::throws() const { 13894 return ( properties & Throws ) != 0; 13895 } 13896 bool TestCaseInfo::okToFail() const { 13897 return ( properties & (ShouldFail | MayFail ) ) != 0; 13898 } 13899 bool TestCaseInfo::expectedToFail() const { 13900 return ( properties & (ShouldFail ) ) != 0; 13901 } 13902 13903 std::string TestCaseInfo::tagsAsString() const { 13904 std::string ret; 13905 // '[' and ']' per tag 13906 std::size_t full_size = 2 * tags.size(); 13907 for (const auto& tag : tags) { 13908 full_size += tag.size(); 13909 } 13910 ret.reserve(full_size); 13911 for (const auto& tag : tags) { 13912 ret.push_back('['); 13913 ret.append(tag); 13914 ret.push_back(']'); 13915 } 13916 13917 return ret; 13918 } 13919 13920 TestCase::TestCase( ITestInvoker* testCase, TestCaseInfo&& info ) : TestCaseInfo( std::move(info) ), test( testCase ) {} 13921 13922 TestCase TestCase::withName( std::string const& _newName ) const { 13923 TestCase other( *this ); 13924 other.name = _newName; 13925 return other; 13926 } 13927 13928 void TestCase::invoke() const { 13929 test->invoke(); 13930 } 13931 13932 bool TestCase::operator == ( TestCase const& other ) const { 13933 return test.get() == other.test.get() && 13934 name == other.name && 13935 className == other.className; 13936 } 13937 13938 bool TestCase::operator < ( TestCase const& other ) const { 13939 return name < other.name; 13940 } 13941 13942 TestCaseInfo const& TestCase::getTestCaseInfo() const 13943 { 13944 return *this; 13945 } 13946 13947 } // end namespace Catch 13948 // end catch_test_case_info.cpp 13949 // start catch_test_case_registry_impl.cpp 13950 13951 #include <sstream> 13952 13953 namespace Catch { 13954 13955 std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) { 13956 13957 std::vector<TestCase> sorted = unsortedTestCases; 13958 13959 switch( config.runOrder() ) { 13960 case RunTests::InLexicographicalOrder: 13961 std::sort( sorted.begin(), sorted.end() ); 13962 break; 13963 case RunTests::InRandomOrder: 13964 seedRng( config ); 13965 std::shuffle( sorted.begin(), sorted.end(), rng() ); 13966 break; 13967 case RunTests::InDeclarationOrder: 13968 // already in declaration order 13969 break; 13970 } 13971 return sorted; 13972 } 13973 13974 bool isThrowSafe( TestCase const& testCase, IConfig const& config ) { 13975 return !testCase.throws() || config.allowThrows(); 13976 } 13977 13978 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) { 13979 return testSpec.matches( testCase ) && isThrowSafe( testCase, config ); 13980 } 13981 13982 void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) { 13983 std::set<TestCase> seenFunctions; 13984 for( auto const& function : functions ) { 13985 auto prev = seenFunctions.insert( function ); 13986 CATCH_ENFORCE( prev.second, 13987 "error: TEST_CASE( \"" << function.name << "\" ) already defined.\n" 13988 << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n" 13989 << "\tRedefined at " << function.getTestCaseInfo().lineInfo ); 13990 } 13991 } 13992 13993 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) { 13994 std::vector<TestCase> filtered; 13995 filtered.reserve( testCases.size() ); 13996 for (auto const& testCase : testCases) { 13997 if ((!testSpec.hasFilters() && !testCase.isHidden()) || 13998 (testSpec.hasFilters() && matchTest(testCase, testSpec, config))) { 13999 filtered.push_back(testCase); 14000 } 14001 } 14002 return filtered; 14003 } 14004 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) { 14005 return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config ); 14006 } 14007 14008 void TestRegistry::registerTest( TestCase const& testCase ) { 14009 std::string name = testCase.getTestCaseInfo().name; 14010 if( name.empty() ) { 14011 ReusableStringStream rss; 14012 rss << "Anonymous test case " << ++m_unnamedCount; 14013 return registerTest( testCase.withName( rss.str() ) ); 14014 } 14015 m_functions.push_back( testCase ); 14016 } 14017 14018 std::vector<TestCase> const& TestRegistry::getAllTests() const { 14019 return m_functions; 14020 } 14021 std::vector<TestCase> const& TestRegistry::getAllTestsSorted( IConfig const& config ) const { 14022 if( m_sortedFunctions.empty() ) 14023 enforceNoDuplicateTestCases( m_functions ); 14024 14025 if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) { 14026 m_sortedFunctions = sortTests( config, m_functions ); 14027 m_currentSortOrder = config.runOrder(); 14028 } 14029 return m_sortedFunctions; 14030 } 14031 14032 /////////////////////////////////////////////////////////////////////////// 14033 TestInvokerAsFunction::TestInvokerAsFunction( void(*testAsFunction)() ) noexcept : m_testAsFunction( testAsFunction ) {} 14034 14035 void TestInvokerAsFunction::invoke() const { 14036 m_testAsFunction(); 14037 } 14038 14039 std::string extractClassName( StringRef const& classOrQualifiedMethodName ) { 14040 std::string className(classOrQualifiedMethodName); 14041 if( startsWith( className, '&' ) ) 14042 { 14043 std::size_t lastColons = className.rfind( "::" ); 14044 std::size_t penultimateColons = className.rfind( "::", lastColons-1 ); 14045 if( penultimateColons == std::string::npos ) 14046 penultimateColons = 1; 14047 className = className.substr( penultimateColons, lastColons-penultimateColons ); 14048 } 14049 return className; 14050 } 14051 14052 } // end namespace Catch 14053 // end catch_test_case_registry_impl.cpp 14054 // start catch_test_case_tracker.cpp 14055 14056 #include <algorithm> 14057 #include <cassert> 14058 #include <stdexcept> 14059 #include <memory> 14060 #include <sstream> 14061 14062 #if defined(__clang__) 14063 # pragma clang diagnostic push 14064 # pragma clang diagnostic ignored "-Wexit-time-destructors" 14065 #endif 14066 14067 namespace Catch { 14068 namespace TestCaseTracking { 14069 14070 NameAndLocation::NameAndLocation( std::string const& _name, SourceLineInfo const& _location ) 14071 : name( _name ), 14072 location( _location ) 14073 {} 14074 14075 ITracker::~ITracker() = default; 14076 14077 ITracker& TrackerContext::startRun() { 14078 m_rootTracker = std::make_shared<SectionTracker>( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, nullptr ); 14079 m_currentTracker = nullptr; 14080 m_runState = Executing; 14081 return *m_rootTracker; 14082 } 14083 14084 void TrackerContext::endRun() { 14085 m_rootTracker.reset(); 14086 m_currentTracker = nullptr; 14087 m_runState = NotStarted; 14088 } 14089 14090 void TrackerContext::startCycle() { 14091 m_currentTracker = m_rootTracker.get(); 14092 m_runState = Executing; 14093 } 14094 void TrackerContext::completeCycle() { 14095 m_runState = CompletedCycle; 14096 } 14097 14098 bool TrackerContext::completedCycle() const { 14099 return m_runState == CompletedCycle; 14100 } 14101 ITracker& TrackerContext::currentTracker() { 14102 return *m_currentTracker; 14103 } 14104 void TrackerContext::setCurrentTracker( ITracker* tracker ) { 14105 m_currentTracker = tracker; 14106 } 14107 14108 TrackerBase::TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) 14109 : m_nameAndLocation( nameAndLocation ), 14110 m_ctx( ctx ), 14111 m_parent( parent ) 14112 {} 14113 14114 NameAndLocation const& TrackerBase::nameAndLocation() const { 14115 return m_nameAndLocation; 14116 } 14117 bool TrackerBase::isComplete() const { 14118 return m_runState == CompletedSuccessfully || m_runState == Failed; 14119 } 14120 bool TrackerBase::isSuccessfullyCompleted() const { 14121 return m_runState == CompletedSuccessfully; 14122 } 14123 bool TrackerBase::isOpen() const { 14124 return m_runState != NotStarted && !isComplete(); 14125 } 14126 bool TrackerBase::hasChildren() const { 14127 return !m_children.empty(); 14128 } 14129 14130 void TrackerBase::addChild( ITrackerPtr const& child ) { 14131 m_children.push_back( child ); 14132 } 14133 14134 ITrackerPtr TrackerBase::findChild( NameAndLocation const& nameAndLocation ) { 14135 auto it = std::find_if( m_children.begin(), m_children.end(), 14136 [&nameAndLocation]( ITrackerPtr const& tracker ){ 14137 return 14138 tracker->nameAndLocation().location == nameAndLocation.location && 14139 tracker->nameAndLocation().name == nameAndLocation.name; 14140 } ); 14141 return( it != m_children.end() ) 14142 ? *it 14143 : nullptr; 14144 } 14145 ITracker& TrackerBase::parent() { 14146 assert( m_parent ); // Should always be non-null except for root 14147 return *m_parent; 14148 } 14149 14150 void TrackerBase::openChild() { 14151 if( m_runState != ExecutingChildren ) { 14152 m_runState = ExecutingChildren; 14153 if( m_parent ) 14154 m_parent->openChild(); 14155 } 14156 } 14157 14158 bool TrackerBase::isSectionTracker() const { return false; } 14159 bool TrackerBase::isGeneratorTracker() const { return false; } 14160 14161 void TrackerBase::open() { 14162 m_runState = Executing; 14163 moveToThis(); 14164 if( m_parent ) 14165 m_parent->openChild(); 14166 } 14167 14168 void TrackerBase::close() { 14169 14170 // Close any still open children (e.g. generators) 14171 while( &m_ctx.currentTracker() != this ) 14172 m_ctx.currentTracker().close(); 14173 14174 switch( m_runState ) { 14175 case NeedsAnotherRun: 14176 break; 14177 14178 case Executing: 14179 m_runState = CompletedSuccessfully; 14180 break; 14181 case ExecutingChildren: 14182 if( std::all_of(m_children.begin(), m_children.end(), [](ITrackerPtr const& t){ return t->isComplete(); }) ) 14183 m_runState = CompletedSuccessfully; 14184 break; 14185 14186 case NotStarted: 14187 case CompletedSuccessfully: 14188 case Failed: 14189 CATCH_INTERNAL_ERROR( "Illogical state: " << m_runState ); 14190 14191 default: 14192 CATCH_INTERNAL_ERROR( "Unknown state: " << m_runState ); 14193 } 14194 moveToParent(); 14195 m_ctx.completeCycle(); 14196 } 14197 void TrackerBase::fail() { 14198 m_runState = Failed; 14199 if( m_parent ) 14200 m_parent->markAsNeedingAnotherRun(); 14201 moveToParent(); 14202 m_ctx.completeCycle(); 14203 } 14204 void TrackerBase::markAsNeedingAnotherRun() { 14205 m_runState = NeedsAnotherRun; 14206 } 14207 14208 void TrackerBase::moveToParent() { 14209 assert( m_parent ); 14210 m_ctx.setCurrentTracker( m_parent ); 14211 } 14212 void TrackerBase::moveToThis() { 14213 m_ctx.setCurrentTracker( this ); 14214 } 14215 14216 SectionTracker::SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) 14217 : TrackerBase( nameAndLocation, ctx, parent ), 14218 m_trimmed_name(trim(nameAndLocation.name)) 14219 { 14220 if( parent ) { 14221 while( !parent->isSectionTracker() ) 14222 parent = &parent->parent(); 14223 14224 SectionTracker& parentSection = static_cast<SectionTracker&>( *parent ); 14225 addNextFilters( parentSection.m_filters ); 14226 } 14227 } 14228 14229 bool SectionTracker::isComplete() const { 14230 bool complete = true; 14231 14232 if ((m_filters.empty() || m_filters[0] == "") 14233 || std::find(m_filters.begin(), m_filters.end(), m_trimmed_name) != m_filters.end()) { 14234 complete = TrackerBase::isComplete(); 14235 } 14236 return complete; 14237 } 14238 14239 bool SectionTracker::isSectionTracker() const { return true; } 14240 14241 SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) { 14242 std::shared_ptr<SectionTracker> section; 14243 14244 ITracker& currentTracker = ctx.currentTracker(); 14245 if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) { 14246 assert( childTracker ); 14247 assert( childTracker->isSectionTracker() ); 14248 section = std::static_pointer_cast<SectionTracker>( childTracker ); 14249 } 14250 else { 14251 section = std::make_shared<SectionTracker>( nameAndLocation, ctx, ¤tTracker ); 14252 currentTracker.addChild( section ); 14253 } 14254 if( !ctx.completedCycle() ) 14255 section->tryOpen(); 14256 return *section; 14257 } 14258 14259 void SectionTracker::tryOpen() { 14260 if( !isComplete() ) 14261 open(); 14262 } 14263 14264 void SectionTracker::addInitialFilters( std::vector<std::string> const& filters ) { 14265 if( !filters.empty() ) { 14266 m_filters.reserve( m_filters.size() + filters.size() + 2 ); 14267 m_filters.push_back(""); // Root - should never be consulted 14268 m_filters.push_back(""); // Test Case - not a section filter 14269 m_filters.insert( m_filters.end(), filters.begin(), filters.end() ); 14270 } 14271 } 14272 void SectionTracker::addNextFilters( std::vector<std::string> const& filters ) { 14273 if( filters.size() > 1 ) 14274 m_filters.insert( m_filters.end(), filters.begin()+1, filters.end() ); 14275 } 14276 14277 } // namespace TestCaseTracking 14278 14279 using TestCaseTracking::ITracker; 14280 using TestCaseTracking::TrackerContext; 14281 using TestCaseTracking::SectionTracker; 14282 14283 } // namespace Catch 14284 14285 #if defined(__clang__) 14286 # pragma clang diagnostic pop 14287 #endif 14288 // end catch_test_case_tracker.cpp 14289 // start catch_test_registry.cpp 14290 14291 namespace Catch { 14292 14293 auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker* { 14294 return new(std::nothrow) TestInvokerAsFunction( testAsFunction ); 14295 } 14296 14297 NameAndTags::NameAndTags( StringRef const& name_ , StringRef const& tags_ ) noexcept : name( name_ ), tags( tags_ ) {} 14298 14299 AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept { 14300 CATCH_TRY { 14301 getMutableRegistryHub() 14302 .registerTest( 14303 makeTestCase( 14304 invoker, 14305 extractClassName( classOrMethod ), 14306 nameAndTags, 14307 lineInfo)); 14308 } CATCH_CATCH_ALL { 14309 // Do not throw when constructing global objects, instead register the exception to be processed later 14310 getMutableRegistryHub().registerStartupException(); 14311 } 14312 } 14313 14314 AutoReg::~AutoReg() = default; 14315 } 14316 // end catch_test_registry.cpp 14317 // start catch_test_spec.cpp 14318 14319 #include <algorithm> 14320 #include <string> 14321 #include <vector> 14322 #include <memory> 14323 14324 namespace Catch { 14325 14326 TestSpec::Pattern::Pattern( std::string const& name ) 14327 : m_name( name ) 14328 {} 14329 14330 TestSpec::Pattern::~Pattern() = default; 14331 14332 std::string const& TestSpec::Pattern::name() const { 14333 return m_name; 14334 } 14335 14336 TestSpec::NamePattern::NamePattern( std::string const& name, std::string const& filterString ) 14337 : Pattern( filterString ) 14338 , m_wildcardPattern( toLower( name ), CaseSensitive::No ) 14339 {} 14340 14341 bool TestSpec::NamePattern::matches( TestCaseInfo const& testCase ) const { 14342 return m_wildcardPattern.matches( testCase.name ); 14343 } 14344 14345 TestSpec::TagPattern::TagPattern( std::string const& tag, std::string const& filterString ) 14346 : Pattern( filterString ) 14347 , m_tag( toLower( tag ) ) 14348 {} 14349 14350 bool TestSpec::TagPattern::matches( TestCaseInfo const& testCase ) const { 14351 return std::find(begin(testCase.lcaseTags), 14352 end(testCase.lcaseTags), 14353 m_tag) != end(testCase.lcaseTags); 14354 } 14355 14356 TestSpec::ExcludedPattern::ExcludedPattern( PatternPtr const& underlyingPattern ) 14357 : Pattern( underlyingPattern->name() ) 14358 , m_underlyingPattern( underlyingPattern ) 14359 {} 14360 14361 bool TestSpec::ExcludedPattern::matches( TestCaseInfo const& testCase ) const { 14362 return !m_underlyingPattern->matches( testCase ); 14363 } 14364 14365 bool TestSpec::Filter::matches( TestCaseInfo const& testCase ) const { 14366 return std::all_of( m_patterns.begin(), m_patterns.end(), [&]( PatternPtr const& p ){ return p->matches( testCase ); } ); 14367 } 14368 14369 std::string TestSpec::Filter::name() const { 14370 std::string name; 14371 for( auto const& p : m_patterns ) 14372 name += p->name(); 14373 return name; 14374 } 14375 14376 bool TestSpec::hasFilters() const { 14377 return !m_filters.empty(); 14378 } 14379 14380 bool TestSpec::matches( TestCaseInfo const& testCase ) const { 14381 return std::any_of( m_filters.begin(), m_filters.end(), [&]( Filter const& f ){ return f.matches( testCase ); } ); 14382 } 14383 14384 TestSpec::Matches TestSpec::matchesByFilter( std::vector<TestCase> const& testCases, IConfig const& config ) const 14385 { 14386 Matches matches( m_filters.size() ); 14387 std::transform( m_filters.begin(), m_filters.end(), matches.begin(), [&]( Filter const& filter ){ 14388 std::vector<TestCase const*> currentMatches; 14389 for( auto const& test : testCases ) 14390 if( isThrowSafe( test, config ) && filter.matches( test ) ) 14391 currentMatches.emplace_back( &test ); 14392 return FilterMatch{ filter.name(), currentMatches }; 14393 } ); 14394 return matches; 14395 } 14396 14397 const TestSpec::vectorStrings& TestSpec::getInvalidArgs() const{ 14398 return (m_invalidArgs); 14399 } 14400 14401 } 14402 // end catch_test_spec.cpp 14403 // start catch_test_spec_parser.cpp 14404 14405 namespace Catch { 14406 14407 TestSpecParser::TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {} 14408 14409 TestSpecParser& TestSpecParser::parse( std::string const& arg ) { 14410 m_mode = None; 14411 m_exclusion = false; 14412 m_arg = m_tagAliases->expandAliases( arg ); 14413 m_escapeChars.clear(); 14414 m_substring.reserve(m_arg.size()); 14415 m_patternName.reserve(m_arg.size()); 14416 m_realPatternPos = 0; 14417 14418 for( m_pos = 0; m_pos < m_arg.size(); ++m_pos ) 14419 //if visitChar fails 14420 if( !visitChar( m_arg[m_pos] ) ){ 14421 m_testSpec.m_invalidArgs.push_back(arg); 14422 break; 14423 } 14424 endMode(); 14425 return *this; 14426 } 14427 TestSpec TestSpecParser::testSpec() { 14428 addFilter(); 14429 return m_testSpec; 14430 } 14431 bool TestSpecParser::visitChar( char c ) { 14432 if( (m_mode != EscapedName) && (c == '\\') ) { 14433 escape(); 14434 addCharToPattern(c); 14435 return true; 14436 }else if((m_mode != EscapedName) && (c == ',') ) { 14437 return separate(); 14438 } 14439 14440 switch( m_mode ) { 14441 case None: 14442 if( processNoneChar( c ) ) 14443 return true; 14444 break; 14445 case Name: 14446 processNameChar( c ); 14447 break; 14448 case EscapedName: 14449 endMode(); 14450 addCharToPattern(c); 14451 return true; 14452 default: 14453 case Tag: 14454 case QuotedName: 14455 if( processOtherChar( c ) ) 14456 return true; 14457 break; 14458 } 14459 14460 m_substring += c; 14461 if( !isControlChar( c ) ) { 14462 m_patternName += c; 14463 m_realPatternPos++; 14464 } 14465 return true; 14466 } 14467 // Two of the processing methods return true to signal the caller to return 14468 // without adding the given character to the current pattern strings 14469 bool TestSpecParser::processNoneChar( char c ) { 14470 switch( c ) { 14471 case ' ': 14472 return true; 14473 case '~': 14474 m_exclusion = true; 14475 return false; 14476 case '[': 14477 startNewMode( Tag ); 14478 return false; 14479 case '"': 14480 startNewMode( QuotedName ); 14481 return false; 14482 default: 14483 startNewMode( Name ); 14484 return false; 14485 } 14486 } 14487 void TestSpecParser::processNameChar( char c ) { 14488 if( c == '[' ) { 14489 if( m_substring == "exclude:" ) 14490 m_exclusion = true; 14491 else 14492 endMode(); 14493 startNewMode( Tag ); 14494 } 14495 } 14496 bool TestSpecParser::processOtherChar( char c ) { 14497 if( !isControlChar( c ) ) 14498 return false; 14499 m_substring += c; 14500 endMode(); 14501 return true; 14502 } 14503 void TestSpecParser::startNewMode( Mode mode ) { 14504 m_mode = mode; 14505 } 14506 void TestSpecParser::endMode() { 14507 switch( m_mode ) { 14508 case Name: 14509 case QuotedName: 14510 return addNamePattern(); 14511 case Tag: 14512 return addTagPattern(); 14513 case EscapedName: 14514 revertBackToLastMode(); 14515 return; 14516 case None: 14517 default: 14518 return startNewMode( None ); 14519 } 14520 } 14521 void TestSpecParser::escape() { 14522 saveLastMode(); 14523 m_mode = EscapedName; 14524 m_escapeChars.push_back(m_realPatternPos); 14525 } 14526 bool TestSpecParser::isControlChar( char c ) const { 14527 switch( m_mode ) { 14528 default: 14529 return false; 14530 case None: 14531 return c == '~'; 14532 case Name: 14533 return c == '['; 14534 case EscapedName: 14535 return true; 14536 case QuotedName: 14537 return c == '"'; 14538 case Tag: 14539 return c == '[' || c == ']'; 14540 } 14541 } 14542 14543 void TestSpecParser::addFilter() { 14544 if( !m_currentFilter.m_patterns.empty() ) { 14545 m_testSpec.m_filters.push_back( m_currentFilter ); 14546 m_currentFilter = TestSpec::Filter(); 14547 } 14548 } 14549 14550 void TestSpecParser::saveLastMode() { 14551 lastMode = m_mode; 14552 } 14553 14554 void TestSpecParser::revertBackToLastMode() { 14555 m_mode = lastMode; 14556 } 14557 14558 bool TestSpecParser::separate() { 14559 if( (m_mode==QuotedName) || (m_mode==Tag) ){ 14560 //invalid argument, signal failure to previous scope. 14561 m_mode = None; 14562 m_pos = m_arg.size(); 14563 m_substring.clear(); 14564 m_patternName.clear(); 14565 return false; 14566 } 14567 endMode(); 14568 addFilter(); 14569 return true; //success 14570 } 14571 14572 std::string TestSpecParser::preprocessPattern() { 14573 std::string token = m_patternName; 14574 for (std::size_t i = 0; i < m_escapeChars.size(); ++i) 14575 token = token.substr(0, m_escapeChars[i] - i) + token.substr(m_escapeChars[i] - i + 1); 14576 m_escapeChars.clear(); 14577 if (startsWith(token, "exclude:")) { 14578 m_exclusion = true; 14579 token = token.substr(8); 14580 } 14581 14582 m_patternName.clear(); 14583 14584 return token; 14585 } 14586 14587 void TestSpecParser::addNamePattern() { 14588 auto token = preprocessPattern(); 14589 14590 if (!token.empty()) { 14591 TestSpec::PatternPtr pattern = std::make_shared<TestSpec::NamePattern>(token, m_substring); 14592 if (m_exclusion) 14593 pattern = std::make_shared<TestSpec::ExcludedPattern>(pattern); 14594 m_currentFilter.m_patterns.push_back(pattern); 14595 } 14596 m_substring.clear(); 14597 m_exclusion = false; 14598 m_mode = None; 14599 } 14600 14601 void TestSpecParser::addTagPattern() { 14602 auto token = preprocessPattern(); 14603 14604 if (!token.empty()) { 14605 // If the tag pattern is the "hide and tag" shorthand (e.g. [.foo]) 14606 // we have to create a separate hide tag and shorten the real one 14607 if (token.size() > 1 && token[0] == '.') { 14608 token.erase(token.begin()); 14609 TestSpec::PatternPtr pattern = std::make_shared<TestSpec::TagPattern>(".", m_substring); 14610 if (m_exclusion) { 14611 pattern = std::make_shared<TestSpec::ExcludedPattern>(pattern); 14612 } 14613 m_currentFilter.m_patterns.push_back(pattern); 14614 } 14615 14616 TestSpec::PatternPtr pattern = std::make_shared<TestSpec::TagPattern>(token, m_substring); 14617 14618 if (m_exclusion) { 14619 pattern = std::make_shared<TestSpec::ExcludedPattern>(pattern); 14620 } 14621 m_currentFilter.m_patterns.push_back(pattern); 14622 } 14623 m_substring.clear(); 14624 m_exclusion = false; 14625 m_mode = None; 14626 } 14627 14628 TestSpec parseTestSpec( std::string const& arg ) { 14629 return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec(); 14630 } 14631 14632 } // namespace Catch 14633 // end catch_test_spec_parser.cpp 14634 // start catch_timer.cpp 14635 14636 #include <chrono> 14637 14638 static const uint64_t nanosecondsInSecond = 1000000000; 14639 14640 namespace Catch { 14641 14642 auto getCurrentNanosecondsSinceEpoch() -> uint64_t { 14643 return std::chrono::duration_cast<std::chrono::nanoseconds>( std::chrono::high_resolution_clock::now().time_since_epoch() ).count(); 14644 } 14645 14646 namespace { 14647 auto estimateClockResolution() -> uint64_t { 14648 uint64_t sum = 0; 14649 static const uint64_t iterations = 1000000; 14650 14651 auto startTime = getCurrentNanosecondsSinceEpoch(); 14652 14653 for( std::size_t i = 0; i < iterations; ++i ) { 14654 14655 uint64_t ticks; 14656 uint64_t baseTicks = getCurrentNanosecondsSinceEpoch(); 14657 do { 14658 ticks = getCurrentNanosecondsSinceEpoch(); 14659 } while( ticks == baseTicks ); 14660 14661 auto delta = ticks - baseTicks; 14662 sum += delta; 14663 14664 // If we have been calibrating for over 3 seconds -- the clock 14665 // is terrible and we should move on. 14666 // TBD: How to signal that the measured resolution is probably wrong? 14667 if (ticks > startTime + 3 * nanosecondsInSecond) { 14668 return sum / ( i + 1u ); 14669 } 14670 } 14671 14672 // We're just taking the mean, here. To do better we could take the std. dev and exclude outliers 14673 // - and potentially do more iterations if there's a high variance. 14674 return sum/iterations; 14675 } 14676 } 14677 auto getEstimatedClockResolution() -> uint64_t { 14678 static auto s_resolution = estimateClockResolution(); 14679 return s_resolution; 14680 } 14681 14682 void Timer::start() { 14683 m_nanoseconds = getCurrentNanosecondsSinceEpoch(); 14684 } 14685 auto Timer::getElapsedNanoseconds() const -> uint64_t { 14686 return getCurrentNanosecondsSinceEpoch() - m_nanoseconds; 14687 } 14688 auto Timer::getElapsedMicroseconds() const -> uint64_t { 14689 return getElapsedNanoseconds()/1000; 14690 } 14691 auto Timer::getElapsedMilliseconds() const -> unsigned int { 14692 return static_cast<unsigned int>(getElapsedMicroseconds()/1000); 14693 } 14694 auto Timer::getElapsedSeconds() const -> double { 14695 return getElapsedMicroseconds()/1000000.0; 14696 } 14697 14698 } // namespace Catch 14699 // end catch_timer.cpp 14700 // start catch_tostring.cpp 14701 14702 #if defined(__clang__) 14703 # pragma clang diagnostic push 14704 # pragma clang diagnostic ignored "-Wexit-time-destructors" 14705 # pragma clang diagnostic ignored "-Wglobal-constructors" 14706 #endif 14707 14708 // Enable specific decls locally 14709 #if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) 14710 #define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER 14711 #endif 14712 14713 #include <cmath> 14714 #include <iomanip> 14715 14716 namespace Catch { 14717 14718 namespace Detail { 14719 14720 const std::string unprintableString = "{?}"; 14721 14722 namespace { 14723 const int hexThreshold = 255; 14724 14725 struct Endianness { 14726 enum Arch { Big, Little }; 14727 14728 static Arch which() { 14729 int one = 1; 14730 // If the lowest byte we read is non-zero, we can assume 14731 // that little endian format is used. 14732 auto value = *reinterpret_cast<char*>(&one); 14733 return value ? Little : Big; 14734 } 14735 }; 14736 } 14737 14738 std::string rawMemoryToString( const void *object, std::size_t size ) { 14739 // Reverse order for little endian architectures 14740 int i = 0, end = static_cast<int>( size ), inc = 1; 14741 if( Endianness::which() == Endianness::Little ) { 14742 i = end-1; 14743 end = inc = -1; 14744 } 14745 14746 unsigned char const *bytes = static_cast<unsigned char const *>(object); 14747 ReusableStringStream rss; 14748 rss << "0x" << std::setfill('0') << std::hex; 14749 for( ; i != end; i += inc ) 14750 rss << std::setw(2) << static_cast<unsigned>(bytes[i]); 14751 return rss.str(); 14752 } 14753 } 14754 14755 template<typename T> 14756 std::string fpToString( T value, int precision ) { 14757 if (Catch::isnan(value)) { 14758 return "nan"; 14759 } 14760 14761 ReusableStringStream rss; 14762 rss << std::setprecision( precision ) 14763 << std::fixed 14764 << value; 14765 std::string d = rss.str(); 14766 std::size_t i = d.find_last_not_of( '0' ); 14767 if( i != std::string::npos && i != d.size()-1 ) { 14768 if( d[i] == '.' ) 14769 i++; 14770 d = d.substr( 0, i+1 ); 14771 } 14772 return d; 14773 } 14774 14775 //// ======================================================= //// 14776 // 14777 // Out-of-line defs for full specialization of StringMaker 14778 // 14779 //// ======================================================= //// 14780 14781 std::string StringMaker<std::string>::convert(const std::string& str) { 14782 if (!getCurrentContext().getConfig()->showInvisibles()) { 14783 return '"' + str + '"'; 14784 } 14785 14786 std::string s("\""); 14787 for (char c : str) { 14788 switch (c) { 14789 case '\n': 14790 s.append("\\n"); 14791 break; 14792 case '\t': 14793 s.append("\\t"); 14794 break; 14795 default: 14796 s.push_back(c); 14797 break; 14798 } 14799 } 14800 s.append("\""); 14801 return s; 14802 } 14803 14804 #ifdef CATCH_CONFIG_CPP17_STRING_VIEW 14805 std::string StringMaker<std::string_view>::convert(std::string_view str) { 14806 return ::Catch::Detail::stringify(std::string{ str }); 14807 } 14808 #endif 14809 14810 std::string StringMaker<char const*>::convert(char const* str) { 14811 if (str) { 14812 return ::Catch::Detail::stringify(std::string{ str }); 14813 } else { 14814 return{ "{null string}" }; 14815 } 14816 } 14817 std::string StringMaker<char*>::convert(char* str) { 14818 if (str) { 14819 return ::Catch::Detail::stringify(std::string{ str }); 14820 } else { 14821 return{ "{null string}" }; 14822 } 14823 } 14824 14825 #ifdef CATCH_CONFIG_WCHAR 14826 std::string StringMaker<std::wstring>::convert(const std::wstring& wstr) { 14827 std::string s; 14828 s.reserve(wstr.size()); 14829 for (auto c : wstr) { 14830 s += (c <= 0xff) ? static_cast<char>(c) : '?'; 14831 } 14832 return ::Catch::Detail::stringify(s); 14833 } 14834 14835 # ifdef CATCH_CONFIG_CPP17_STRING_VIEW 14836 std::string StringMaker<std::wstring_view>::convert(std::wstring_view str) { 14837 return StringMaker<std::wstring>::convert(std::wstring(str)); 14838 } 14839 # endif 14840 14841 std::string StringMaker<wchar_t const*>::convert(wchar_t const * str) { 14842 if (str) { 14843 return ::Catch::Detail::stringify(std::wstring{ str }); 14844 } else { 14845 return{ "{null string}" }; 14846 } 14847 } 14848 std::string StringMaker<wchar_t *>::convert(wchar_t * str) { 14849 if (str) { 14850 return ::Catch::Detail::stringify(std::wstring{ str }); 14851 } else { 14852 return{ "{null string}" }; 14853 } 14854 } 14855 #endif 14856 14857 #if defined(CATCH_CONFIG_CPP17_BYTE) 14858 #include <cstddef> 14859 std::string StringMaker<std::byte>::convert(std::byte value) { 14860 return ::Catch::Detail::stringify(std::to_integer<unsigned long long>(value)); 14861 } 14862 #endif // defined(CATCH_CONFIG_CPP17_BYTE) 14863 14864 std::string StringMaker<int>::convert(int value) { 14865 return ::Catch::Detail::stringify(static_cast<long long>(value)); 14866 } 14867 std::string StringMaker<long>::convert(long value) { 14868 return ::Catch::Detail::stringify(static_cast<long long>(value)); 14869 } 14870 std::string StringMaker<long long>::convert(long long value) { 14871 ReusableStringStream rss; 14872 rss << value; 14873 if (value > Detail::hexThreshold) { 14874 rss << " (0x" << std::hex << value << ')'; 14875 } 14876 return rss.str(); 14877 } 14878 14879 std::string StringMaker<unsigned int>::convert(unsigned int value) { 14880 return ::Catch::Detail::stringify(static_cast<unsigned long long>(value)); 14881 } 14882 std::string StringMaker<unsigned long>::convert(unsigned long value) { 14883 return ::Catch::Detail::stringify(static_cast<unsigned long long>(value)); 14884 } 14885 std::string StringMaker<unsigned long long>::convert(unsigned long long value) { 14886 ReusableStringStream rss; 14887 rss << value; 14888 if (value > Detail::hexThreshold) { 14889 rss << " (0x" << std::hex << value << ')'; 14890 } 14891 return rss.str(); 14892 } 14893 14894 std::string StringMaker<bool>::convert(bool b) { 14895 return b ? "true" : "false"; 14896 } 14897 14898 std::string StringMaker<signed char>::convert(signed char value) { 14899 if (value == '\r') { 14900 return "'\\r'"; 14901 } else if (value == '\f') { 14902 return "'\\f'"; 14903 } else if (value == '\n') { 14904 return "'\\n'"; 14905 } else if (value == '\t') { 14906 return "'\\t'"; 14907 } else if ('\0' <= value && value < ' ') { 14908 return ::Catch::Detail::stringify(static_cast<unsigned int>(value)); 14909 } else { 14910 char chstr[] = "' '"; 14911 chstr[1] = value; 14912 return chstr; 14913 } 14914 } 14915 std::string StringMaker<char>::convert(char c) { 14916 return ::Catch::Detail::stringify(static_cast<signed char>(c)); 14917 } 14918 std::string StringMaker<unsigned char>::convert(unsigned char c) { 14919 return ::Catch::Detail::stringify(static_cast<char>(c)); 14920 } 14921 14922 std::string StringMaker<std::nullptr_t>::convert(std::nullptr_t) { 14923 return "nullptr"; 14924 } 14925 14926 int StringMaker<float>::precision = 5; 14927 14928 std::string StringMaker<float>::convert(float value) { 14929 return fpToString(value, precision) + 'f'; 14930 } 14931 14932 int StringMaker<double>::precision = 10; 14933 14934 std::string StringMaker<double>::convert(double value) { 14935 return fpToString(value, precision); 14936 } 14937 14938 std::string ratio_string<std::atto>::symbol() { return "a"; } 14939 std::string ratio_string<std::femto>::symbol() { return "f"; } 14940 std::string ratio_string<std::pico>::symbol() { return "p"; } 14941 std::string ratio_string<std::nano>::symbol() { return "n"; } 14942 std::string ratio_string<std::micro>::symbol() { return "u"; } 14943 std::string ratio_string<std::milli>::symbol() { return "m"; } 14944 14945 } // end namespace Catch 14946 14947 #if defined(__clang__) 14948 # pragma clang diagnostic pop 14949 #endif 14950 14951 // end catch_tostring.cpp 14952 // start catch_totals.cpp 14953 14954 namespace Catch { 14955 14956 Counts Counts::operator - ( Counts const& other ) const { 14957 Counts diff; 14958 diff.passed = passed - other.passed; 14959 diff.failed = failed - other.failed; 14960 diff.failedButOk = failedButOk - other.failedButOk; 14961 return diff; 14962 } 14963 14964 Counts& Counts::operator += ( Counts const& other ) { 14965 passed += other.passed; 14966 failed += other.failed; 14967 failedButOk += other.failedButOk; 14968 return *this; 14969 } 14970 14971 std::size_t Counts::total() const { 14972 return passed + failed + failedButOk; 14973 } 14974 bool Counts::allPassed() const { 14975 return failed == 0 && failedButOk == 0; 14976 } 14977 bool Counts::allOk() const { 14978 return failed == 0; 14979 } 14980 14981 Totals Totals::operator - ( Totals const& other ) const { 14982 Totals diff; 14983 diff.assertions = assertions - other.assertions; 14984 diff.testCases = testCases - other.testCases; 14985 return diff; 14986 } 14987 14988 Totals& Totals::operator += ( Totals const& other ) { 14989 assertions += other.assertions; 14990 testCases += other.testCases; 14991 return *this; 14992 } 14993 14994 Totals Totals::delta( Totals const& prevTotals ) const { 14995 Totals diff = *this - prevTotals; 14996 if( diff.assertions.failed > 0 ) 14997 ++diff.testCases.failed; 14998 else if( diff.assertions.failedButOk > 0 ) 14999 ++diff.testCases.failedButOk; 15000 else 15001 ++diff.testCases.passed; 15002 return diff; 15003 } 15004 15005 } 15006 // end catch_totals.cpp 15007 // start catch_uncaught_exceptions.cpp 15008 15009 #include <exception> 15010 15011 namespace Catch { 15012 bool uncaught_exceptions() { 15013 #if defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) 15014 return std::uncaught_exceptions() > 0; 15015 #else 15016 return std::uncaught_exception(); 15017 #endif 15018 } 15019 } // end namespace Catch 15020 // end catch_uncaught_exceptions.cpp 15021 // start catch_version.cpp 15022 15023 #include <ostream> 15024 15025 namespace Catch { 15026 15027 Version::Version 15028 ( unsigned int _majorVersion, 15029 unsigned int _minorVersion, 15030 unsigned int _patchNumber, 15031 char const * const _branchName, 15032 unsigned int _buildNumber ) 15033 : majorVersion( _majorVersion ), 15034 minorVersion( _minorVersion ), 15035 patchNumber( _patchNumber ), 15036 branchName( _branchName ), 15037 buildNumber( _buildNumber ) 15038 {} 15039 15040 std::ostream& operator << ( std::ostream& os, Version const& version ) { 15041 os << version.majorVersion << '.' 15042 << version.minorVersion << '.' 15043 << version.patchNumber; 15044 // branchName is never null -> 0th char is \0 if it is empty 15045 if (version.branchName[0]) { 15046 os << '-' << version.branchName 15047 << '.' << version.buildNumber; 15048 } 15049 return os; 15050 } 15051 15052 Version const& libraryVersion() { 15053 static Version version( 2, 11, 0, "", 0 ); 15054 return version; 15055 } 15056 15057 } 15058 // end catch_version.cpp 15059 // start catch_wildcard_pattern.cpp 15060 15061 namespace Catch { 15062 15063 WildcardPattern::WildcardPattern( std::string const& pattern, 15064 CaseSensitive::Choice caseSensitivity ) 15065 : m_caseSensitivity( caseSensitivity ), 15066 m_pattern( normaliseString( pattern ) ) 15067 { 15068 if( startsWith( m_pattern, '*' ) ) { 15069 m_pattern = m_pattern.substr( 1 ); 15070 m_wildcard = WildcardAtStart; 15071 } 15072 if( endsWith( m_pattern, '*' ) ) { 15073 m_pattern = m_pattern.substr( 0, m_pattern.size()-1 ); 15074 m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd ); 15075 } 15076 } 15077 15078 bool WildcardPattern::matches( std::string const& str ) const { 15079 switch( m_wildcard ) { 15080 case NoWildcard: 15081 return m_pattern == normaliseString( str ); 15082 case WildcardAtStart: 15083 return endsWith( normaliseString( str ), m_pattern ); 15084 case WildcardAtEnd: 15085 return startsWith( normaliseString( str ), m_pattern ); 15086 case WildcardAtBothEnds: 15087 return contains( normaliseString( str ), m_pattern ); 15088 default: 15089 CATCH_INTERNAL_ERROR( "Unknown enum" ); 15090 } 15091 } 15092 15093 std::string WildcardPattern::normaliseString( std::string const& str ) const { 15094 return trim( m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str ); 15095 } 15096 } 15097 // end catch_wildcard_pattern.cpp 15098 // start catch_xmlwriter.cpp 15099 15100 #include <iomanip> 15101 #include <type_traits> 15102 15103 using uchar = unsigned char; 15104 15105 namespace Catch { 15106 15107 namespace { 15108 15109 size_t trailingBytes(unsigned char c) { 15110 if ((c & 0xE0) == 0xC0) { 15111 return 2; 15112 } 15113 if ((c & 0xF0) == 0xE0) { 15114 return 3; 15115 } 15116 if ((c & 0xF8) == 0xF0) { 15117 return 4; 15118 } 15119 CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered"); 15120 } 15121 15122 uint32_t headerValue(unsigned char c) { 15123 if ((c & 0xE0) == 0xC0) { 15124 return c & 0x1F; 15125 } 15126 if ((c & 0xF0) == 0xE0) { 15127 return c & 0x0F; 15128 } 15129 if ((c & 0xF8) == 0xF0) { 15130 return c & 0x07; 15131 } 15132 CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered"); 15133 } 15134 15135 void hexEscapeChar(std::ostream& os, unsigned char c) { 15136 std::ios_base::fmtflags f(os.flags()); 15137 os << "\\x" 15138 << std::uppercase << std::hex << std::setfill('0') << std::setw(2) 15139 << static_cast<int>(c); 15140 os.flags(f); 15141 } 15142 15143 bool shouldNewline(XmlFormatting fmt) { 15144 return !!(static_cast<std::underlying_type<XmlFormatting>::type>(fmt & XmlFormatting::Newline)); 15145 } 15146 15147 bool shouldIndent(XmlFormatting fmt) { 15148 return !!(static_cast<std::underlying_type<XmlFormatting>::type>(fmt & XmlFormatting::Indent)); 15149 } 15150 15151 } // anonymous namespace 15152 15153 XmlFormatting operator | (XmlFormatting lhs, XmlFormatting rhs) { 15154 return static_cast<XmlFormatting>( 15155 static_cast<std::underlying_type<XmlFormatting>::type>(lhs) | 15156 static_cast<std::underlying_type<XmlFormatting>::type>(rhs) 15157 ); 15158 } 15159 15160 XmlFormatting operator & (XmlFormatting lhs, XmlFormatting rhs) { 15161 return static_cast<XmlFormatting>( 15162 static_cast<std::underlying_type<XmlFormatting>::type>(lhs) & 15163 static_cast<std::underlying_type<XmlFormatting>::type>(rhs) 15164 ); 15165 } 15166 15167 XmlEncode::XmlEncode( std::string const& str, ForWhat forWhat ) 15168 : m_str( str ), 15169 m_forWhat( forWhat ) 15170 {} 15171 15172 void XmlEncode::encodeTo( std::ostream& os ) const { 15173 // Apostrophe escaping not necessary if we always use " to write attributes 15174 // (see: http://www.w3.org/TR/xml/#syntax) 15175 15176 for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) { 15177 uchar c = m_str[idx]; 15178 switch (c) { 15179 case '<': os << "<"; break; 15180 case '&': os << "&"; break; 15181 15182 case '>': 15183 // See: http://www.w3.org/TR/xml/#syntax 15184 if (idx > 2 && m_str[idx - 1] == ']' && m_str[idx - 2] == ']') 15185 os << ">"; 15186 else 15187 os << c; 15188 break; 15189 15190 case '\"': 15191 if (m_forWhat == ForAttributes) 15192 os << """; 15193 else 15194 os << c; 15195 break; 15196 15197 default: 15198 // Check for control characters and invalid utf-8 15199 15200 // Escape control characters in standard ascii 15201 // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0 15202 if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) { 15203 hexEscapeChar(os, c); 15204 break; 15205 } 15206 15207 // Plain ASCII: Write it to stream 15208 if (c < 0x7F) { 15209 os << c; 15210 break; 15211 } 15212 15213 // UTF-8 territory 15214 // Check if the encoding is valid and if it is not, hex escape bytes. 15215 // Important: We do not check the exact decoded values for validity, only the encoding format 15216 // First check that this bytes is a valid lead byte: 15217 // This means that it is not encoded as 1111 1XXX 15218 // Or as 10XX XXXX 15219 if (c < 0xC0 || 15220 c >= 0xF8) { 15221 hexEscapeChar(os, c); 15222 break; 15223 } 15224 15225 auto encBytes = trailingBytes(c); 15226 // Are there enough bytes left to avoid accessing out-of-bounds memory? 15227 if (idx + encBytes - 1 >= m_str.size()) { 15228 hexEscapeChar(os, c); 15229 break; 15230 } 15231 // The header is valid, check data 15232 // The next encBytes bytes must together be a valid utf-8 15233 // This means: bitpattern 10XX XXXX and the extracted value is sane (ish) 15234 bool valid = true; 15235 uint32_t value = headerValue(c); 15236 for (std::size_t n = 1; n < encBytes; ++n) { 15237 uchar nc = m_str[idx + n]; 15238 valid &= ((nc & 0xC0) == 0x80); 15239 value = (value << 6) | (nc & 0x3F); 15240 } 15241 15242 if ( 15243 // Wrong bit pattern of following bytes 15244 (!valid) || 15245 // Overlong encodings 15246 (value < 0x80) || 15247 (0x80 <= value && value < 0x800 && encBytes > 2) || 15248 (0x800 < value && value < 0x10000 && encBytes > 3) || 15249 // Encoded value out of range 15250 (value >= 0x110000) 15251 ) { 15252 hexEscapeChar(os, c); 15253 break; 15254 } 15255 15256 // If we got here, this is in fact a valid(ish) utf-8 sequence 15257 for (std::size_t n = 0; n < encBytes; ++n) { 15258 os << m_str[idx + n]; 15259 } 15260 idx += encBytes - 1; 15261 break; 15262 } 15263 } 15264 } 15265 15266 std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) { 15267 xmlEncode.encodeTo( os ); 15268 return os; 15269 } 15270 15271 XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer, XmlFormatting fmt ) 15272 : m_writer( writer ), 15273 m_fmt(fmt) 15274 {} 15275 15276 XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) noexcept 15277 : m_writer( other.m_writer ), 15278 m_fmt(other.m_fmt) 15279 { 15280 other.m_writer = nullptr; 15281 other.m_fmt = XmlFormatting::None; 15282 } 15283 XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) noexcept { 15284 if ( m_writer ) { 15285 m_writer->endElement(); 15286 } 15287 m_writer = other.m_writer; 15288 other.m_writer = nullptr; 15289 m_fmt = other.m_fmt; 15290 other.m_fmt = XmlFormatting::None; 15291 return *this; 15292 } 15293 15294 XmlWriter::ScopedElement::~ScopedElement() { 15295 if (m_writer) { 15296 m_writer->endElement(m_fmt); 15297 } 15298 } 15299 15300 XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText( std::string const& text, XmlFormatting fmt ) { 15301 m_writer->writeText( text, fmt ); 15302 return *this; 15303 } 15304 15305 XmlWriter::XmlWriter( std::ostream& os ) : m_os( os ) 15306 { 15307 writeDeclaration(); 15308 } 15309 15310 XmlWriter::~XmlWriter() { 15311 while (!m_tags.empty()) { 15312 endElement(); 15313 } 15314 newlineIfNecessary(); 15315 } 15316 15317 XmlWriter& XmlWriter::startElement( std::string const& name, XmlFormatting fmt ) { 15318 ensureTagClosed(); 15319 newlineIfNecessary(); 15320 if (shouldIndent(fmt)) { 15321 m_os << m_indent; 15322 m_indent += " "; 15323 } 15324 m_os << '<' << name; 15325 m_tags.push_back( name ); 15326 m_tagIsOpen = true; 15327 applyFormatting(fmt); 15328 return *this; 15329 } 15330 15331 XmlWriter::ScopedElement XmlWriter::scopedElement( std::string const& name, XmlFormatting fmt ) { 15332 ScopedElement scoped( this, fmt ); 15333 startElement( name, fmt ); 15334 return scoped; 15335 } 15336 15337 XmlWriter& XmlWriter::endElement(XmlFormatting fmt) { 15338 m_indent = m_indent.substr(0, m_indent.size() - 2); 15339 15340 if( m_tagIsOpen ) { 15341 m_os << "/>"; 15342 m_tagIsOpen = false; 15343 } else { 15344 newlineIfNecessary(); 15345 if (shouldIndent(fmt)) { 15346 m_os << m_indent; 15347 } 15348 m_os << "</" << m_tags.back() << ">"; 15349 } 15350 m_os << std::flush; 15351 applyFormatting(fmt); 15352 m_tags.pop_back(); 15353 return *this; 15354 } 15355 15356 XmlWriter& XmlWriter::writeAttribute( std::string const& name, std::string const& attribute ) { 15357 if( !name.empty() && !attribute.empty() ) 15358 m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"'; 15359 return *this; 15360 } 15361 15362 XmlWriter& XmlWriter::writeAttribute( std::string const& name, bool attribute ) { 15363 m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"'; 15364 return *this; 15365 } 15366 15367 XmlWriter& XmlWriter::writeText( std::string const& text, XmlFormatting fmt) { 15368 if( !text.empty() ){ 15369 bool tagWasOpen = m_tagIsOpen; 15370 ensureTagClosed(); 15371 if (tagWasOpen && shouldIndent(fmt)) { 15372 m_os << m_indent; 15373 } 15374 m_os << XmlEncode( text ); 15375 applyFormatting(fmt); 15376 } 15377 return *this; 15378 } 15379 15380 XmlWriter& XmlWriter::writeComment( std::string const& text, XmlFormatting fmt) { 15381 ensureTagClosed(); 15382 if (shouldIndent(fmt)) { 15383 m_os << m_indent; 15384 } 15385 m_os << "<!--" << text << "-->"; 15386 applyFormatting(fmt); 15387 return *this; 15388 } 15389 15390 void XmlWriter::writeStylesheetRef( std::string const& url ) { 15391 m_os << "<?xml-stylesheet type=\"text/xsl\" href=\"" << url << "\"?>\n"; 15392 } 15393 15394 XmlWriter& XmlWriter::writeBlankLine() { 15395 ensureTagClosed(); 15396 m_os << '\n'; 15397 return *this; 15398 } 15399 15400 void XmlWriter::ensureTagClosed() { 15401 if( m_tagIsOpen ) { 15402 m_os << '>' << std::flush; 15403 newlineIfNecessary(); 15404 m_tagIsOpen = false; 15405 } 15406 } 15407 15408 void XmlWriter::applyFormatting(XmlFormatting fmt) { 15409 m_needsNewline = shouldNewline(fmt); 15410 } 15411 15412 void XmlWriter::writeDeclaration() { 15413 m_os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; 15414 } 15415 15416 void XmlWriter::newlineIfNecessary() { 15417 if( m_needsNewline ) { 15418 m_os << std::endl; 15419 m_needsNewline = false; 15420 } 15421 } 15422 } 15423 // end catch_xmlwriter.cpp 15424 // start catch_reporter_bases.cpp 15425 15426 #include <cstring> 15427 #include <cfloat> 15428 #include <cstdio> 15429 #include <cassert> 15430 #include <memory> 15431 15432 namespace Catch { 15433 void prepareExpandedExpression(AssertionResult& result) { 15434 result.getExpandedExpression(); 15435 } 15436 15437 // Because formatting using c++ streams is stateful, drop down to C is required 15438 // Alternatively we could use stringstream, but its performance is... not good. 15439 std::string getFormattedDuration( double duration ) { 15440 // Max exponent + 1 is required to represent the whole part 15441 // + 1 for decimal point 15442 // + 3 for the 3 decimal places 15443 // + 1 for null terminator 15444 const std::size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1; 15445 char buffer[maxDoubleSize]; 15446 15447 // Save previous errno, to prevent sprintf from overwriting it 15448 ErrnoGuard guard; 15449 #ifdef _MSC_VER 15450 sprintf_s(buffer, "%.3f", duration); 15451 #else 15452 std::sprintf(buffer, "%.3f", duration); 15453 #endif 15454 return std::string(buffer); 15455 } 15456 15457 std::string serializeFilters( std::vector<std::string> const& container ) { 15458 ReusableStringStream oss; 15459 bool first = true; 15460 for (auto&& filter : container) 15461 { 15462 if (!first) 15463 oss << ' '; 15464 else 15465 first = false; 15466 15467 oss << filter; 15468 } 15469 return oss.str(); 15470 } 15471 15472 TestEventListenerBase::TestEventListenerBase(ReporterConfig const & _config) 15473 :StreamingReporterBase(_config) {} 15474 15475 std::set<Verbosity> TestEventListenerBase::getSupportedVerbosities() { 15476 return { Verbosity::Quiet, Verbosity::Normal, Verbosity::High }; 15477 } 15478 15479 void TestEventListenerBase::assertionStarting(AssertionInfo const &) {} 15480 15481 bool TestEventListenerBase::assertionEnded(AssertionStats const &) { 15482 return false; 15483 } 15484 15485 } // end namespace Catch 15486 // end catch_reporter_bases.cpp 15487 // start catch_reporter_compact.cpp 15488 15489 namespace { 15490 15491 #ifdef CATCH_PLATFORM_MAC 15492 const char* failedString() { return "FAILED"; } 15493 const char* passedString() { return "PASSED"; } 15494 #else 15495 const char* failedString() { return "failed"; } 15496 const char* passedString() { return "passed"; } 15497 #endif 15498 15499 // Colour::LightGrey 15500 Catch::Colour::Code dimColour() { return Catch::Colour::FileName; } 15501 15502 std::string bothOrAll( std::size_t count ) { 15503 return count == 1 ? std::string() : 15504 count == 2 ? "both " : "all " ; 15505 } 15506 15507 } // anon namespace 15508 15509 namespace Catch { 15510 namespace { 15511 // Colour, message variants: 15512 // - white: No tests ran. 15513 // - red: Failed [both/all] N test cases, failed [both/all] M assertions. 15514 // - white: Passed [both/all] N test cases (no assertions). 15515 // - red: Failed N tests cases, failed M assertions. 15516 // - green: Passed [both/all] N tests cases with M assertions. 15517 void printTotals(std::ostream& out, const Totals& totals) { 15518 if (totals.testCases.total() == 0) { 15519 out << "No tests ran."; 15520 } else if (totals.testCases.failed == totals.testCases.total()) { 15521 Colour colour(Colour::ResultError); 15522 const std::string qualify_assertions_failed = 15523 totals.assertions.failed == totals.assertions.total() ? 15524 bothOrAll(totals.assertions.failed) : std::string(); 15525 out << 15526 "Failed " << bothOrAll(totals.testCases.failed) 15527 << pluralise(totals.testCases.failed, "test case") << ", " 15528 "failed " << qualify_assertions_failed << 15529 pluralise(totals.assertions.failed, "assertion") << '.'; 15530 } else if (totals.assertions.total() == 0) { 15531 out << 15532 "Passed " << bothOrAll(totals.testCases.total()) 15533 << pluralise(totals.testCases.total(), "test case") 15534 << " (no assertions)."; 15535 } else if (totals.assertions.failed) { 15536 Colour colour(Colour::ResultError); 15537 out << 15538 "Failed " << pluralise(totals.testCases.failed, "test case") << ", " 15539 "failed " << pluralise(totals.assertions.failed, "assertion") << '.'; 15540 } else { 15541 Colour colour(Colour::ResultSuccess); 15542 out << 15543 "Passed " << bothOrAll(totals.testCases.passed) 15544 << pluralise(totals.testCases.passed, "test case") << 15545 " with " << pluralise(totals.assertions.passed, "assertion") << '.'; 15546 } 15547 } 15548 15549 // Implementation of CompactReporter formatting 15550 class AssertionPrinter { 15551 public: 15552 AssertionPrinter& operator= (AssertionPrinter const&) = delete; 15553 AssertionPrinter(AssertionPrinter const&) = delete; 15554 AssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages) 15555 : stream(_stream) 15556 , result(_stats.assertionResult) 15557 , messages(_stats.infoMessages) 15558 , itMessage(_stats.infoMessages.begin()) 15559 , printInfoMessages(_printInfoMessages) {} 15560 15561 void print() { 15562 printSourceInfo(); 15563 15564 itMessage = messages.begin(); 15565 15566 switch (result.getResultType()) { 15567 case ResultWas::Ok: 15568 printResultType(Colour::ResultSuccess, passedString()); 15569 printOriginalExpression(); 15570 printReconstructedExpression(); 15571 if (!result.hasExpression()) 15572 printRemainingMessages(Colour::None); 15573 else 15574 printRemainingMessages(); 15575 break; 15576 case ResultWas::ExpressionFailed: 15577 if (result.isOk()) 15578 printResultType(Colour::ResultSuccess, failedString() + std::string(" - but was ok")); 15579 else 15580 printResultType(Colour::Error, failedString()); 15581 printOriginalExpression(); 15582 printReconstructedExpression(); 15583 printRemainingMessages(); 15584 break; 15585 case ResultWas::ThrewException: 15586 printResultType(Colour::Error, failedString()); 15587 printIssue("unexpected exception with message:"); 15588 printMessage(); 15589 printExpressionWas(); 15590 printRemainingMessages(); 15591 break; 15592 case ResultWas::FatalErrorCondition: 15593 printResultType(Colour::Error, failedString()); 15594 printIssue("fatal error condition with message:"); 15595 printMessage(); 15596 printExpressionWas(); 15597 printRemainingMessages(); 15598 break; 15599 case ResultWas::DidntThrowException: 15600 printResultType(Colour::Error, failedString()); 15601 printIssue("expected exception, got none"); 15602 printExpressionWas(); 15603 printRemainingMessages(); 15604 break; 15605 case ResultWas::Info: 15606 printResultType(Colour::None, "info"); 15607 printMessage(); 15608 printRemainingMessages(); 15609 break; 15610 case ResultWas::Warning: 15611 printResultType(Colour::None, "warning"); 15612 printMessage(); 15613 printRemainingMessages(); 15614 break; 15615 case ResultWas::ExplicitFailure: 15616 printResultType(Colour::Error, failedString()); 15617 printIssue("explicitly"); 15618 printRemainingMessages(Colour::None); 15619 break; 15620 // These cases are here to prevent compiler warnings 15621 case ResultWas::Unknown: 15622 case ResultWas::FailureBit: 15623 case ResultWas::Exception: 15624 printResultType(Colour::Error, "** internal error **"); 15625 break; 15626 } 15627 } 15628 15629 private: 15630 void printSourceInfo() const { 15631 Colour colourGuard(Colour::FileName); 15632 stream << result.getSourceInfo() << ':'; 15633 } 15634 15635 void printResultType(Colour::Code colour, std::string const& passOrFail) const { 15636 if (!passOrFail.empty()) { 15637 { 15638 Colour colourGuard(colour); 15639 stream << ' ' << passOrFail; 15640 } 15641 stream << ':'; 15642 } 15643 } 15644 15645 void printIssue(std::string const& issue) const { 15646 stream << ' ' << issue; 15647 } 15648 15649 void printExpressionWas() { 15650 if (result.hasExpression()) { 15651 stream << ';'; 15652 { 15653 Colour colour(dimColour()); 15654 stream << " expression was:"; 15655 } 15656 printOriginalExpression(); 15657 } 15658 } 15659 15660 void printOriginalExpression() const { 15661 if (result.hasExpression()) { 15662 stream << ' ' << result.getExpression(); 15663 } 15664 } 15665 15666 void printReconstructedExpression() const { 15667 if (result.hasExpandedExpression()) { 15668 { 15669 Colour colour(dimColour()); 15670 stream << " for: "; 15671 } 15672 stream << result.getExpandedExpression(); 15673 } 15674 } 15675 15676 void printMessage() { 15677 if (itMessage != messages.end()) { 15678 stream << " '" << itMessage->message << '\''; 15679 ++itMessage; 15680 } 15681 } 15682 15683 void printRemainingMessages(Colour::Code colour = dimColour()) { 15684 if (itMessage == messages.end()) 15685 return; 15686 15687 const auto itEnd = messages.cend(); 15688 const auto N = static_cast<std::size_t>(std::distance(itMessage, itEnd)); 15689 15690 { 15691 Colour colourGuard(colour); 15692 stream << " with " << pluralise(N, "message") << ':'; 15693 } 15694 15695 while (itMessage != itEnd) { 15696 // If this assertion is a warning ignore any INFO messages 15697 if (printInfoMessages || itMessage->type != ResultWas::Info) { 15698 printMessage(); 15699 if (itMessage != itEnd) { 15700 Colour colourGuard(dimColour()); 15701 stream << " and"; 15702 } 15703 continue; 15704 } 15705 ++itMessage; 15706 } 15707 } 15708 15709 private: 15710 std::ostream& stream; 15711 AssertionResult const& result; 15712 std::vector<MessageInfo> messages; 15713 std::vector<MessageInfo>::const_iterator itMessage; 15714 bool printInfoMessages; 15715 }; 15716 15717 } // anon namespace 15718 15719 std::string CompactReporter::getDescription() { 15720 return "Reports test results on a single line, suitable for IDEs"; 15721 } 15722 15723 ReporterPreferences CompactReporter::getPreferences() const { 15724 return m_reporterPrefs; 15725 } 15726 15727 void CompactReporter::noMatchingTestCases( std::string const& spec ) { 15728 stream << "No test cases matched '" << spec << '\'' << std::endl; 15729 } 15730 15731 void CompactReporter::assertionStarting( AssertionInfo const& ) {} 15732 15733 bool CompactReporter::assertionEnded( AssertionStats const& _assertionStats ) { 15734 AssertionResult const& result = _assertionStats.assertionResult; 15735 15736 bool printInfoMessages = true; 15737 15738 // Drop out if result was successful and we're not printing those 15739 if( !m_config->includeSuccessfulResults() && result.isOk() ) { 15740 if( result.getResultType() != ResultWas::Warning ) 15741 return false; 15742 printInfoMessages = false; 15743 } 15744 15745 AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); 15746 printer.print(); 15747 15748 stream << std::endl; 15749 return true; 15750 } 15751 15752 void CompactReporter::sectionEnded(SectionStats const& _sectionStats) { 15753 if (m_config->showDurations() == ShowDurations::Always) { 15754 stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl; 15755 } 15756 } 15757 15758 void CompactReporter::testRunEnded( TestRunStats const& _testRunStats ) { 15759 printTotals( stream, _testRunStats.totals ); 15760 stream << '\n' << std::endl; 15761 StreamingReporterBase::testRunEnded( _testRunStats ); 15762 } 15763 15764 CompactReporter::~CompactReporter() {} 15765 15766 CATCH_REGISTER_REPORTER( "compact", CompactReporter ) 15767 15768 } // end namespace Catch 15769 // end catch_reporter_compact.cpp 15770 // start catch_reporter_console.cpp 15771 15772 #include <cfloat> 15773 #include <cstdio> 15774 15775 #if defined(_MSC_VER) 15776 #pragma warning(push) 15777 #pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch 15778 // Note that 4062 (not all labels are handled and default is missing) is enabled 15779 #endif 15780 15781 #if defined(__clang__) 15782 # pragma clang diagnostic push 15783 // For simplicity, benchmarking-only helpers are always enabled 15784 # pragma clang diagnostic ignored "-Wunused-function" 15785 #endif 15786 15787 namespace Catch { 15788 15789 namespace { 15790 15791 // Formatter impl for ConsoleReporter 15792 class ConsoleAssertionPrinter { 15793 public: 15794 ConsoleAssertionPrinter& operator= (ConsoleAssertionPrinter const&) = delete; 15795 ConsoleAssertionPrinter(ConsoleAssertionPrinter const&) = delete; 15796 ConsoleAssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages) 15797 : stream(_stream), 15798 stats(_stats), 15799 result(_stats.assertionResult), 15800 colour(Colour::None), 15801 message(result.getMessage()), 15802 messages(_stats.infoMessages), 15803 printInfoMessages(_printInfoMessages) { 15804 switch (result.getResultType()) { 15805 case ResultWas::Ok: 15806 colour = Colour::Success; 15807 passOrFail = "PASSED"; 15808 //if( result.hasMessage() ) 15809 if (_stats.infoMessages.size() == 1) 15810 messageLabel = "with message"; 15811 if (_stats.infoMessages.size() > 1) 15812 messageLabel = "with messages"; 15813 break; 15814 case ResultWas::ExpressionFailed: 15815 if (result.isOk()) { 15816 colour = Colour::Success; 15817 passOrFail = "FAILED - but was ok"; 15818 } else { 15819 colour = Colour::Error; 15820 passOrFail = "FAILED"; 15821 } 15822 if (_stats.infoMessages.size() == 1) 15823 messageLabel = "with message"; 15824 if (_stats.infoMessages.size() > 1) 15825 messageLabel = "with messages"; 15826 break; 15827 case ResultWas::ThrewException: 15828 colour = Colour::Error; 15829 passOrFail = "FAILED"; 15830 messageLabel = "due to unexpected exception with "; 15831 if (_stats.infoMessages.size() == 1) 15832 messageLabel += "message"; 15833 if (_stats.infoMessages.size() > 1) 15834 messageLabel += "messages"; 15835 break; 15836 case ResultWas::FatalErrorCondition: 15837 colour = Colour::Error; 15838 passOrFail = "FAILED"; 15839 messageLabel = "due to a fatal error condition"; 15840 break; 15841 case ResultWas::DidntThrowException: 15842 colour = Colour::Error; 15843 passOrFail = "FAILED"; 15844 messageLabel = "because no exception was thrown where one was expected"; 15845 break; 15846 case ResultWas::Info: 15847 messageLabel = "info"; 15848 break; 15849 case ResultWas::Warning: 15850 messageLabel = "warning"; 15851 break; 15852 case ResultWas::ExplicitFailure: 15853 passOrFail = "FAILED"; 15854 colour = Colour::Error; 15855 if (_stats.infoMessages.size() == 1) 15856 messageLabel = "explicitly with message"; 15857 if (_stats.infoMessages.size() > 1) 15858 messageLabel = "explicitly with messages"; 15859 break; 15860 // These cases are here to prevent compiler warnings 15861 case ResultWas::Unknown: 15862 case ResultWas::FailureBit: 15863 case ResultWas::Exception: 15864 passOrFail = "** internal error **"; 15865 colour = Colour::Error; 15866 break; 15867 } 15868 } 15869 15870 void print() const { 15871 printSourceInfo(); 15872 if (stats.totals.assertions.total() > 0) { 15873 printResultType(); 15874 printOriginalExpression(); 15875 printReconstructedExpression(); 15876 } else { 15877 stream << '\n'; 15878 } 15879 printMessage(); 15880 } 15881 15882 private: 15883 void printResultType() const { 15884 if (!passOrFail.empty()) { 15885 Colour colourGuard(colour); 15886 stream << passOrFail << ":\n"; 15887 } 15888 } 15889 void printOriginalExpression() const { 15890 if (result.hasExpression()) { 15891 Colour colourGuard(Colour::OriginalExpression); 15892 stream << " "; 15893 stream << result.getExpressionInMacro(); 15894 stream << '\n'; 15895 } 15896 } 15897 void printReconstructedExpression() const { 15898 if (result.hasExpandedExpression()) { 15899 stream << "with expansion:\n"; 15900 Colour colourGuard(Colour::ReconstructedExpression); 15901 stream << Column(result.getExpandedExpression()).indent(2) << '\n'; 15902 } 15903 } 15904 void printMessage() const { 15905 if (!messageLabel.empty()) 15906 stream << messageLabel << ':' << '\n'; 15907 for (auto const& msg : messages) { 15908 // If this assertion is a warning ignore any INFO messages 15909 if (printInfoMessages || msg.type != ResultWas::Info) 15910 stream << Column(msg.message).indent(2) << '\n'; 15911 } 15912 } 15913 void printSourceInfo() const { 15914 Colour colourGuard(Colour::FileName); 15915 stream << result.getSourceInfo() << ": "; 15916 } 15917 15918 std::ostream& stream; 15919 AssertionStats const& stats; 15920 AssertionResult const& result; 15921 Colour::Code colour; 15922 std::string passOrFail; 15923 std::string messageLabel; 15924 std::string message; 15925 std::vector<MessageInfo> messages; 15926 bool printInfoMessages; 15927 }; 15928 15929 std::size_t makeRatio(std::size_t number, std::size_t total) { 15930 std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number / total : 0; 15931 return (ratio == 0 && number > 0) ? 1 : ratio; 15932 } 15933 15934 std::size_t& findMax(std::size_t& i, std::size_t& j, std::size_t& k) { 15935 if (i > j && i > k) 15936 return i; 15937 else if (j > k) 15938 return j; 15939 else 15940 return k; 15941 } 15942 15943 struct ColumnInfo { 15944 enum Justification { Left, Right }; 15945 std::string name; 15946 int width; 15947 Justification justification; 15948 }; 15949 struct ColumnBreak {}; 15950 struct RowBreak {}; 15951 15952 class Duration { 15953 enum class Unit { 15954 Auto, 15955 Nanoseconds, 15956 Microseconds, 15957 Milliseconds, 15958 Seconds, 15959 Minutes 15960 }; 15961 static const uint64_t s_nanosecondsInAMicrosecond = 1000; 15962 static const uint64_t s_nanosecondsInAMillisecond = 1000 * s_nanosecondsInAMicrosecond; 15963 static const uint64_t s_nanosecondsInASecond = 1000 * s_nanosecondsInAMillisecond; 15964 static const uint64_t s_nanosecondsInAMinute = 60 * s_nanosecondsInASecond; 15965 15966 uint64_t m_inNanoseconds; 15967 Unit m_units; 15968 15969 public: 15970 explicit Duration(double inNanoseconds, Unit units = Unit::Auto) 15971 : Duration(static_cast<uint64_t>(inNanoseconds), units) { 15972 } 15973 15974 explicit Duration(uint64_t inNanoseconds, Unit units = Unit::Auto) 15975 : m_inNanoseconds(inNanoseconds), 15976 m_units(units) { 15977 if (m_units == Unit::Auto) { 15978 if (m_inNanoseconds < s_nanosecondsInAMicrosecond) 15979 m_units = Unit::Nanoseconds; 15980 else if (m_inNanoseconds < s_nanosecondsInAMillisecond) 15981 m_units = Unit::Microseconds; 15982 else if (m_inNanoseconds < s_nanosecondsInASecond) 15983 m_units = Unit::Milliseconds; 15984 else if (m_inNanoseconds < s_nanosecondsInAMinute) 15985 m_units = Unit::Seconds; 15986 else 15987 m_units = Unit::Minutes; 15988 } 15989 15990 } 15991 15992 auto value() const -> double { 15993 switch (m_units) { 15994 case Unit::Microseconds: 15995 return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMicrosecond); 15996 case Unit::Milliseconds: 15997 return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMillisecond); 15998 case Unit::Seconds: 15999 return m_inNanoseconds / static_cast<double>(s_nanosecondsInASecond); 16000 case Unit::Minutes: 16001 return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMinute); 16002 default: 16003 return static_cast<double>(m_inNanoseconds); 16004 } 16005 } 16006 auto unitsAsString() const -> std::string { 16007 switch (m_units) { 16008 case Unit::Nanoseconds: 16009 return "ns"; 16010 case Unit::Microseconds: 16011 return "us"; 16012 case Unit::Milliseconds: 16013 return "ms"; 16014 case Unit::Seconds: 16015 return "s"; 16016 case Unit::Minutes: 16017 return "m"; 16018 default: 16019 return "** internal error **"; 16020 } 16021 16022 } 16023 friend auto operator << (std::ostream& os, Duration const& duration) -> std::ostream& { 16024 return os << duration.value() << ' ' << duration.unitsAsString(); 16025 } 16026 }; 16027 } // end anon namespace 16028 16029 class TablePrinter { 16030 std::ostream& m_os; 16031 std::vector<ColumnInfo> m_columnInfos; 16032 std::ostringstream m_oss; 16033 int m_currentColumn = -1; 16034 bool m_isOpen = false; 16035 16036 public: 16037 TablePrinter( std::ostream& os, std::vector<ColumnInfo> columnInfos ) 16038 : m_os( os ), 16039 m_columnInfos( std::move( columnInfos ) ) {} 16040 16041 auto columnInfos() const -> std::vector<ColumnInfo> const& { 16042 return m_columnInfos; 16043 } 16044 16045 void open() { 16046 if (!m_isOpen) { 16047 m_isOpen = true; 16048 *this << RowBreak(); 16049 16050 Columns headerCols; 16051 Spacer spacer(2); 16052 for (auto const& info : m_columnInfos) { 16053 headerCols += Column(info.name).width(static_cast<std::size_t>(info.width - 2)); 16054 headerCols += spacer; 16055 } 16056 m_os << headerCols << '\n'; 16057 16058 m_os << Catch::getLineOfChars<'-'>() << '\n'; 16059 } 16060 } 16061 void close() { 16062 if (m_isOpen) { 16063 *this << RowBreak(); 16064 m_os << std::endl; 16065 m_isOpen = false; 16066 } 16067 } 16068 16069 template<typename T> 16070 friend TablePrinter& operator << (TablePrinter& tp, T const& value) { 16071 tp.m_oss << value; 16072 return tp; 16073 } 16074 16075 friend TablePrinter& operator << (TablePrinter& tp, ColumnBreak) { 16076 auto colStr = tp.m_oss.str(); 16077 const auto strSize = colStr.size(); 16078 tp.m_oss.str(""); 16079 tp.open(); 16080 if (tp.m_currentColumn == static_cast<int>(tp.m_columnInfos.size() - 1)) { 16081 tp.m_currentColumn = -1; 16082 tp.m_os << '\n'; 16083 } 16084 tp.m_currentColumn++; 16085 16086 auto colInfo = tp.m_columnInfos[tp.m_currentColumn]; 16087 auto padding = (strSize + 1 < static_cast<std::size_t>(colInfo.width)) 16088 ? std::string(colInfo.width - (strSize + 1), ' ') 16089 : std::string(); 16090 if (colInfo.justification == ColumnInfo::Left) 16091 tp.m_os << colStr << padding << ' '; 16092 else 16093 tp.m_os << padding << colStr << ' '; 16094 return tp; 16095 } 16096 16097 friend TablePrinter& operator << (TablePrinter& tp, RowBreak) { 16098 if (tp.m_currentColumn > 0) { 16099 tp.m_os << '\n'; 16100 tp.m_currentColumn = -1; 16101 } 16102 return tp; 16103 } 16104 }; 16105 16106 ConsoleReporter::ConsoleReporter(ReporterConfig const& config) 16107 : StreamingReporterBase(config), 16108 m_tablePrinter(new TablePrinter(config.stream(), 16109 [&config]() -> std::vector<ColumnInfo> { 16110 if (config.fullConfig()->benchmarkNoAnalysis()) 16111 { 16112 return{ 16113 { "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 43, ColumnInfo::Left }, 16114 { " samples", 14, ColumnInfo::Right }, 16115 { " iterations", 14, ColumnInfo::Right }, 16116 { " mean", 14, ColumnInfo::Right } 16117 }; 16118 } 16119 else 16120 { 16121 return{ 16122 { "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 32, ColumnInfo::Left }, 16123 { "samples mean std dev", 14, ColumnInfo::Right }, 16124 { "iterations low mean low std dev", 14, ColumnInfo::Right }, 16125 { "estimated high mean high std dev", 14, ColumnInfo::Right } 16126 }; 16127 } 16128 }())) {} 16129 ConsoleReporter::~ConsoleReporter() = default; 16130 16131 std::string ConsoleReporter::getDescription() { 16132 return "Reports test results as plain lines of text"; 16133 } 16134 16135 void ConsoleReporter::noMatchingTestCases(std::string const& spec) { 16136 stream << "No test cases matched '" << spec << '\'' << std::endl; 16137 } 16138 16139 void ConsoleReporter::reportInvalidArguments(std::string const&arg){ 16140 stream << "Invalid Filter: " << arg << std::endl; 16141 } 16142 16143 void ConsoleReporter::assertionStarting(AssertionInfo const&) {} 16144 16145 bool ConsoleReporter::assertionEnded(AssertionStats const& _assertionStats) { 16146 AssertionResult const& result = _assertionStats.assertionResult; 16147 16148 bool includeResults = m_config->includeSuccessfulResults() || !result.isOk(); 16149 16150 // Drop out if result was successful but we're not printing them. 16151 if (!includeResults && result.getResultType() != ResultWas::Warning) 16152 return false; 16153 16154 lazyPrint(); 16155 16156 ConsoleAssertionPrinter printer(stream, _assertionStats, includeResults); 16157 printer.print(); 16158 stream << std::endl; 16159 return true; 16160 } 16161 16162 void ConsoleReporter::sectionStarting(SectionInfo const& _sectionInfo) { 16163 m_tablePrinter->close(); 16164 m_headerPrinted = false; 16165 StreamingReporterBase::sectionStarting(_sectionInfo); 16166 } 16167 void ConsoleReporter::sectionEnded(SectionStats const& _sectionStats) { 16168 m_tablePrinter->close(); 16169 if (_sectionStats.missingAssertions) { 16170 lazyPrint(); 16171 Colour colour(Colour::ResultError); 16172 if (m_sectionStack.size() > 1) 16173 stream << "\nNo assertions in section"; 16174 else 16175 stream << "\nNo assertions in test case"; 16176 stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; 16177 } 16178 if (m_config->showDurations() == ShowDurations::Always) { 16179 stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl; 16180 } 16181 if (m_headerPrinted) { 16182 m_headerPrinted = false; 16183 } 16184 StreamingReporterBase::sectionEnded(_sectionStats); 16185 } 16186 16187 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 16188 void ConsoleReporter::benchmarkPreparing(std::string const& name) { 16189 lazyPrintWithoutClosingBenchmarkTable(); 16190 16191 auto nameCol = Column(name).width(static_cast<std::size_t>(m_tablePrinter->columnInfos()[0].width - 2)); 16192 16193 bool firstLine = true; 16194 for (auto line : nameCol) { 16195 if (!firstLine) 16196 (*m_tablePrinter) << ColumnBreak() << ColumnBreak() << ColumnBreak(); 16197 else 16198 firstLine = false; 16199 16200 (*m_tablePrinter) << line << ColumnBreak(); 16201 } 16202 } 16203 16204 void ConsoleReporter::benchmarkStarting(BenchmarkInfo const& info) { 16205 (*m_tablePrinter) << info.samples << ColumnBreak() 16206 << info.iterations << ColumnBreak(); 16207 if (!m_config->benchmarkNoAnalysis()) 16208 (*m_tablePrinter) << Duration(info.estimatedDuration) << ColumnBreak(); 16209 } 16210 void ConsoleReporter::benchmarkEnded(BenchmarkStats<> const& stats) { 16211 if (m_config->benchmarkNoAnalysis()) 16212 { 16213 (*m_tablePrinter) << Duration(stats.mean.point.count()) << ColumnBreak(); 16214 } 16215 else 16216 { 16217 (*m_tablePrinter) << ColumnBreak() 16218 << Duration(stats.mean.point.count()) << ColumnBreak() 16219 << Duration(stats.mean.lower_bound.count()) << ColumnBreak() 16220 << Duration(stats.mean.upper_bound.count()) << ColumnBreak() << ColumnBreak() 16221 << Duration(stats.standardDeviation.point.count()) << ColumnBreak() 16222 << Duration(stats.standardDeviation.lower_bound.count()) << ColumnBreak() 16223 << Duration(stats.standardDeviation.upper_bound.count()) << ColumnBreak() << ColumnBreak() << ColumnBreak() << ColumnBreak() << ColumnBreak(); 16224 } 16225 } 16226 16227 void ConsoleReporter::benchmarkFailed(std::string const& error) { 16228 Colour colour(Colour::Red); 16229 (*m_tablePrinter) 16230 << "Benchmark failed (" << error << ')' 16231 << ColumnBreak() << RowBreak(); 16232 } 16233 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 16234 16235 void ConsoleReporter::testCaseEnded(TestCaseStats const& _testCaseStats) { 16236 m_tablePrinter->close(); 16237 StreamingReporterBase::testCaseEnded(_testCaseStats); 16238 m_headerPrinted = false; 16239 } 16240 void ConsoleReporter::testGroupEnded(TestGroupStats const& _testGroupStats) { 16241 if (currentGroupInfo.used) { 16242 printSummaryDivider(); 16243 stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; 16244 printTotals(_testGroupStats.totals); 16245 stream << '\n' << std::endl; 16246 } 16247 StreamingReporterBase::testGroupEnded(_testGroupStats); 16248 } 16249 void ConsoleReporter::testRunEnded(TestRunStats const& _testRunStats) { 16250 printTotalsDivider(_testRunStats.totals); 16251 printTotals(_testRunStats.totals); 16252 stream << std::endl; 16253 StreamingReporterBase::testRunEnded(_testRunStats); 16254 } 16255 void ConsoleReporter::testRunStarting(TestRunInfo const& _testInfo) { 16256 StreamingReporterBase::testRunStarting(_testInfo); 16257 printTestFilters(); 16258 } 16259 16260 void ConsoleReporter::lazyPrint() { 16261 16262 m_tablePrinter->close(); 16263 lazyPrintWithoutClosingBenchmarkTable(); 16264 } 16265 16266 void ConsoleReporter::lazyPrintWithoutClosingBenchmarkTable() { 16267 16268 if (!currentTestRunInfo.used) 16269 lazyPrintRunInfo(); 16270 if (!currentGroupInfo.used) 16271 lazyPrintGroupInfo(); 16272 16273 if (!m_headerPrinted) { 16274 printTestCaseAndSectionHeader(); 16275 m_headerPrinted = true; 16276 } 16277 } 16278 void ConsoleReporter::lazyPrintRunInfo() { 16279 stream << '\n' << getLineOfChars<'~'>() << '\n'; 16280 Colour colour(Colour::SecondaryText); 16281 stream << currentTestRunInfo->name 16282 << " is a Catch v" << libraryVersion() << " host application.\n" 16283 << "Run with -? for options\n\n"; 16284 16285 if (m_config->rngSeed() != 0) 16286 stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n"; 16287 16288 currentTestRunInfo.used = true; 16289 } 16290 void ConsoleReporter::lazyPrintGroupInfo() { 16291 if (!currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1) { 16292 printClosedHeader("Group: " + currentGroupInfo->name); 16293 currentGroupInfo.used = true; 16294 } 16295 } 16296 void ConsoleReporter::printTestCaseAndSectionHeader() { 16297 assert(!m_sectionStack.empty()); 16298 printOpenHeader(currentTestCaseInfo->name); 16299 16300 if (m_sectionStack.size() > 1) { 16301 Colour colourGuard(Colour::Headers); 16302 16303 auto 16304 it = m_sectionStack.begin() + 1, // Skip first section (test case) 16305 itEnd = m_sectionStack.end(); 16306 for (; it != itEnd; ++it) 16307 printHeaderString(it->name, 2); 16308 } 16309 16310 SourceLineInfo lineInfo = m_sectionStack.back().lineInfo; 16311 16312 stream << getLineOfChars<'-'>() << '\n'; 16313 Colour colourGuard(Colour::FileName); 16314 stream << lineInfo << '\n'; 16315 stream << getLineOfChars<'.'>() << '\n' << std::endl; 16316 } 16317 16318 void ConsoleReporter::printClosedHeader(std::string const& _name) { 16319 printOpenHeader(_name); 16320 stream << getLineOfChars<'.'>() << '\n'; 16321 } 16322 void ConsoleReporter::printOpenHeader(std::string const& _name) { 16323 stream << getLineOfChars<'-'>() << '\n'; 16324 { 16325 Colour colourGuard(Colour::Headers); 16326 printHeaderString(_name); 16327 } 16328 } 16329 16330 // if string has a : in first line will set indent to follow it on 16331 // subsequent lines 16332 void ConsoleReporter::printHeaderString(std::string const& _string, std::size_t indent) { 16333 std::size_t i = _string.find(": "); 16334 if (i != std::string::npos) 16335 i += 2; 16336 else 16337 i = 0; 16338 stream << Column(_string).indent(indent + i).initialIndent(indent) << '\n'; 16339 } 16340 16341 struct SummaryColumn { 16342 16343 SummaryColumn( std::string _label, Colour::Code _colour ) 16344 : label( std::move( _label ) ), 16345 colour( _colour ) {} 16346 SummaryColumn addRow( std::size_t count ) { 16347 ReusableStringStream rss; 16348 rss << count; 16349 std::string row = rss.str(); 16350 for (auto& oldRow : rows) { 16351 while (oldRow.size() < row.size()) 16352 oldRow = ' ' + oldRow; 16353 while (oldRow.size() > row.size()) 16354 row = ' ' + row; 16355 } 16356 rows.push_back(row); 16357 return *this; 16358 } 16359 16360 std::string label; 16361 Colour::Code colour; 16362 std::vector<std::string> rows; 16363 16364 }; 16365 16366 void ConsoleReporter::printTotals( Totals const& totals ) { 16367 if (totals.testCases.total() == 0) { 16368 stream << Colour(Colour::Warning) << "No tests ran\n"; 16369 } else if (totals.assertions.total() > 0 && totals.testCases.allPassed()) { 16370 stream << Colour(Colour::ResultSuccess) << "All tests passed"; 16371 stream << " (" 16372 << pluralise(totals.assertions.passed, "assertion") << " in " 16373 << pluralise(totals.testCases.passed, "test case") << ')' 16374 << '\n'; 16375 } else { 16376 16377 std::vector<SummaryColumn> columns; 16378 columns.push_back(SummaryColumn("", Colour::None) 16379 .addRow(totals.testCases.total()) 16380 .addRow(totals.assertions.total())); 16381 columns.push_back(SummaryColumn("passed", Colour::Success) 16382 .addRow(totals.testCases.passed) 16383 .addRow(totals.assertions.passed)); 16384 columns.push_back(SummaryColumn("failed", Colour::ResultError) 16385 .addRow(totals.testCases.failed) 16386 .addRow(totals.assertions.failed)); 16387 columns.push_back(SummaryColumn("failed as expected", Colour::ResultExpectedFailure) 16388 .addRow(totals.testCases.failedButOk) 16389 .addRow(totals.assertions.failedButOk)); 16390 16391 printSummaryRow("test cases", columns, 0); 16392 printSummaryRow("assertions", columns, 1); 16393 } 16394 } 16395 void ConsoleReporter::printSummaryRow(std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row) { 16396 for (auto col : cols) { 16397 std::string value = col.rows[row]; 16398 if (col.label.empty()) { 16399 stream << label << ": "; 16400 if (value != "0") 16401 stream << value; 16402 else 16403 stream << Colour(Colour::Warning) << "- none -"; 16404 } else if (value != "0") { 16405 stream << Colour(Colour::LightGrey) << " | "; 16406 stream << Colour(col.colour) 16407 << value << ' ' << col.label; 16408 } 16409 } 16410 stream << '\n'; 16411 } 16412 16413 void ConsoleReporter::printTotalsDivider(Totals const& totals) { 16414 if (totals.testCases.total() > 0) { 16415 std::size_t failedRatio = makeRatio(totals.testCases.failed, totals.testCases.total()); 16416 std::size_t failedButOkRatio = makeRatio(totals.testCases.failedButOk, totals.testCases.total()); 16417 std::size_t passedRatio = makeRatio(totals.testCases.passed, totals.testCases.total()); 16418 while (failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH - 1) 16419 findMax(failedRatio, failedButOkRatio, passedRatio)++; 16420 while (failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH - 1) 16421 findMax(failedRatio, failedButOkRatio, passedRatio)--; 16422 16423 stream << Colour(Colour::Error) << std::string(failedRatio, '='); 16424 stream << Colour(Colour::ResultExpectedFailure) << std::string(failedButOkRatio, '='); 16425 if (totals.testCases.allPassed()) 16426 stream << Colour(Colour::ResultSuccess) << std::string(passedRatio, '='); 16427 else 16428 stream << Colour(Colour::Success) << std::string(passedRatio, '='); 16429 } else { 16430 stream << Colour(Colour::Warning) << std::string(CATCH_CONFIG_CONSOLE_WIDTH - 1, '='); 16431 } 16432 stream << '\n'; 16433 } 16434 void ConsoleReporter::printSummaryDivider() { 16435 stream << getLineOfChars<'-'>() << '\n'; 16436 } 16437 16438 void ConsoleReporter::printTestFilters() { 16439 if (m_config->testSpec().hasFilters()) 16440 stream << Colour(Colour::BrightYellow) << "Filters: " << serializeFilters( m_config->getTestsOrTags() ) << '\n'; 16441 } 16442 16443 CATCH_REGISTER_REPORTER("console", ConsoleReporter) 16444 16445 } // end namespace Catch 16446 16447 #if defined(_MSC_VER) 16448 #pragma warning(pop) 16449 #endif 16450 16451 #if defined(__clang__) 16452 # pragma clang diagnostic pop 16453 #endif 16454 // end catch_reporter_console.cpp 16455 // start catch_reporter_junit.cpp 16456 16457 #include <cassert> 16458 #include <sstream> 16459 #include <ctime> 16460 #include <algorithm> 16461 16462 namespace Catch { 16463 16464 namespace { 16465 std::string getCurrentTimestamp() { 16466 // Beware, this is not reentrant because of backward compatibility issues 16467 // Also, UTC only, again because of backward compatibility (%z is C++11) 16468 time_t rawtime; 16469 std::time(&rawtime); 16470 auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); 16471 16472 #ifdef _MSC_VER 16473 std::tm timeInfo = {}; 16474 gmtime_s(&timeInfo, &rawtime); 16475 #else 16476 std::tm* timeInfo; 16477 timeInfo = std::gmtime(&rawtime); 16478 #endif 16479 16480 char timeStamp[timeStampSize]; 16481 const char * const fmt = "%Y-%m-%dT%H:%M:%SZ"; 16482 16483 #ifdef _MSC_VER 16484 std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); 16485 #else 16486 std::strftime(timeStamp, timeStampSize, fmt, timeInfo); 16487 #endif 16488 return std::string(timeStamp); 16489 } 16490 16491 std::string fileNameTag(const std::vector<std::string> &tags) { 16492 auto it = std::find_if(begin(tags), 16493 end(tags), 16494 [] (std::string const& tag) {return tag.front() == '#'; }); 16495 if (it != tags.end()) 16496 return it->substr(1); 16497 return std::string(); 16498 } 16499 } // anonymous namespace 16500 16501 JunitReporter::JunitReporter( ReporterConfig const& _config ) 16502 : CumulativeReporterBase( _config ), 16503 xml( _config.stream() ) 16504 { 16505 m_reporterPrefs.shouldRedirectStdOut = true; 16506 m_reporterPrefs.shouldReportAllAssertions = true; 16507 } 16508 16509 JunitReporter::~JunitReporter() {} 16510 16511 std::string JunitReporter::getDescription() { 16512 return "Reports test results in an XML format that looks like Ant's junitreport target"; 16513 } 16514 16515 void JunitReporter::noMatchingTestCases( std::string const& /*spec*/ ) {} 16516 16517 void JunitReporter::testRunStarting( TestRunInfo const& runInfo ) { 16518 CumulativeReporterBase::testRunStarting( runInfo ); 16519 xml.startElement( "testsuites" ); 16520 } 16521 16522 void JunitReporter::testGroupStarting( GroupInfo const& groupInfo ) { 16523 suiteTimer.start(); 16524 stdOutForSuite.clear(); 16525 stdErrForSuite.clear(); 16526 unexpectedExceptions = 0; 16527 CumulativeReporterBase::testGroupStarting( groupInfo ); 16528 } 16529 16530 void JunitReporter::testCaseStarting( TestCaseInfo const& testCaseInfo ) { 16531 m_okToFail = testCaseInfo.okToFail(); 16532 } 16533 16534 bool JunitReporter::assertionEnded( AssertionStats const& assertionStats ) { 16535 if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException && !m_okToFail ) 16536 unexpectedExceptions++; 16537 return CumulativeReporterBase::assertionEnded( assertionStats ); 16538 } 16539 16540 void JunitReporter::testCaseEnded( TestCaseStats const& testCaseStats ) { 16541 stdOutForSuite += testCaseStats.stdOut; 16542 stdErrForSuite += testCaseStats.stdErr; 16543 CumulativeReporterBase::testCaseEnded( testCaseStats ); 16544 } 16545 16546 void JunitReporter::testGroupEnded( TestGroupStats const& testGroupStats ) { 16547 double suiteTime = suiteTimer.getElapsedSeconds(); 16548 CumulativeReporterBase::testGroupEnded( testGroupStats ); 16549 writeGroup( *m_testGroups.back(), suiteTime ); 16550 } 16551 16552 void JunitReporter::testRunEndedCumulative() { 16553 xml.endElement(); 16554 } 16555 16556 void JunitReporter::writeGroup( TestGroupNode const& groupNode, double suiteTime ) { 16557 XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); 16558 16559 TestGroupStats const& stats = groupNode.value; 16560 xml.writeAttribute( "name", stats.groupInfo.name ); 16561 xml.writeAttribute( "errors", unexpectedExceptions ); 16562 xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions ); 16563 xml.writeAttribute( "tests", stats.totals.assertions.total() ); 16564 xml.writeAttribute( "hostname", "tbd" ); // !TBD 16565 if( m_config->showDurations() == ShowDurations::Never ) 16566 xml.writeAttribute( "time", "" ); 16567 else 16568 xml.writeAttribute( "time", suiteTime ); 16569 xml.writeAttribute( "timestamp", getCurrentTimestamp() ); 16570 16571 // Write properties if there are any 16572 if (m_config->hasTestFilters() || m_config->rngSeed() != 0) { 16573 auto properties = xml.scopedElement("properties"); 16574 if (m_config->hasTestFilters()) { 16575 xml.scopedElement("property") 16576 .writeAttribute("name", "filters") 16577 .writeAttribute("value", serializeFilters(m_config->getTestsOrTags())); 16578 } 16579 if (m_config->rngSeed() != 0) { 16580 xml.scopedElement("property") 16581 .writeAttribute("name", "random-seed") 16582 .writeAttribute("value", m_config->rngSeed()); 16583 } 16584 } 16585 16586 // Write test cases 16587 for( auto const& child : groupNode.children ) 16588 writeTestCase( *child ); 16589 16590 xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite ), XmlFormatting::Newline ); 16591 xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite ), XmlFormatting::Newline ); 16592 } 16593 16594 void JunitReporter::writeTestCase( TestCaseNode const& testCaseNode ) { 16595 TestCaseStats const& stats = testCaseNode.value; 16596 16597 // All test cases have exactly one section - which represents the 16598 // test case itself. That section may have 0-n nested sections 16599 assert( testCaseNode.children.size() == 1 ); 16600 SectionNode const& rootSection = *testCaseNode.children.front(); 16601 16602 std::string className = stats.testInfo.className; 16603 16604 if( className.empty() ) { 16605 className = fileNameTag(stats.testInfo.tags); 16606 if ( className.empty() ) 16607 className = "global"; 16608 } 16609 16610 if ( !m_config->name().empty() ) 16611 className = m_config->name() + "." + className; 16612 16613 writeSection( className, "", rootSection ); 16614 } 16615 16616 void JunitReporter::writeSection( std::string const& className, 16617 std::string const& rootName, 16618 SectionNode const& sectionNode ) { 16619 std::string name = trim( sectionNode.stats.sectionInfo.name ); 16620 if( !rootName.empty() ) 16621 name = rootName + '/' + name; 16622 16623 if( !sectionNode.assertions.empty() || 16624 !sectionNode.stdOut.empty() || 16625 !sectionNode.stdErr.empty() ) { 16626 XmlWriter::ScopedElement e = xml.scopedElement( "testcase" ); 16627 if( className.empty() ) { 16628 xml.writeAttribute( "classname", name ); 16629 xml.writeAttribute( "name", "root" ); 16630 } 16631 else { 16632 xml.writeAttribute( "classname", className ); 16633 xml.writeAttribute( "name", name ); 16634 } 16635 xml.writeAttribute( "time", ::Catch::Detail::stringify( sectionNode.stats.durationInSeconds ) ); 16636 16637 writeAssertions( sectionNode ); 16638 16639 if( !sectionNode.stdOut.empty() ) 16640 xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), XmlFormatting::Newline ); 16641 if( !sectionNode.stdErr.empty() ) 16642 xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), XmlFormatting::Newline ); 16643 } 16644 for( auto const& childNode : sectionNode.childSections ) 16645 if( className.empty() ) 16646 writeSection( name, "", *childNode ); 16647 else 16648 writeSection( className, name, *childNode ); 16649 } 16650 16651 void JunitReporter::writeAssertions( SectionNode const& sectionNode ) { 16652 for( auto const& assertion : sectionNode.assertions ) 16653 writeAssertion( assertion ); 16654 } 16655 16656 void JunitReporter::writeAssertion( AssertionStats const& stats ) { 16657 AssertionResult const& result = stats.assertionResult; 16658 if( !result.isOk() ) { 16659 std::string elementName; 16660 switch( result.getResultType() ) { 16661 case ResultWas::ThrewException: 16662 case ResultWas::FatalErrorCondition: 16663 elementName = "error"; 16664 break; 16665 case ResultWas::ExplicitFailure: 16666 elementName = "failure"; 16667 break; 16668 case ResultWas::ExpressionFailed: 16669 elementName = "failure"; 16670 break; 16671 case ResultWas::DidntThrowException: 16672 elementName = "failure"; 16673 break; 16674 16675 // We should never see these here: 16676 case ResultWas::Info: 16677 case ResultWas::Warning: 16678 case ResultWas::Ok: 16679 case ResultWas::Unknown: 16680 case ResultWas::FailureBit: 16681 case ResultWas::Exception: 16682 elementName = "internalError"; 16683 break; 16684 } 16685 16686 XmlWriter::ScopedElement e = xml.scopedElement( elementName ); 16687 16688 xml.writeAttribute( "message", result.getExpression() ); 16689 xml.writeAttribute( "type", result.getTestMacroName() ); 16690 16691 ReusableStringStream rss; 16692 if (stats.totals.assertions.total() > 0) { 16693 rss << "FAILED" << ":\n"; 16694 if (result.hasExpression()) { 16695 rss << " "; 16696 rss << result.getExpressionInMacro(); 16697 rss << '\n'; 16698 } 16699 if (result.hasExpandedExpression()) { 16700 rss << "with expansion:\n"; 16701 rss << Column(result.getExpandedExpression()).indent(2) << '\n'; 16702 } 16703 } else { 16704 rss << '\n'; 16705 } 16706 16707 if( !result.getMessage().empty() ) 16708 rss << result.getMessage() << '\n'; 16709 for( auto const& msg : stats.infoMessages ) 16710 if( msg.type == ResultWas::Info ) 16711 rss << msg.message << '\n'; 16712 16713 rss << "at " << result.getSourceInfo(); 16714 xml.writeText( rss.str(), XmlFormatting::Newline ); 16715 } 16716 } 16717 16718 CATCH_REGISTER_REPORTER( "junit", JunitReporter ) 16719 16720 } // end namespace Catch 16721 // end catch_reporter_junit.cpp 16722 // start catch_reporter_listening.cpp 16723 16724 #include <cassert> 16725 16726 namespace Catch { 16727 16728 ListeningReporter::ListeningReporter() { 16729 // We will assume that listeners will always want all assertions 16730 m_preferences.shouldReportAllAssertions = true; 16731 } 16732 16733 void ListeningReporter::addListener( IStreamingReporterPtr&& listener ) { 16734 m_listeners.push_back( std::move( listener ) ); 16735 } 16736 16737 void ListeningReporter::addReporter(IStreamingReporterPtr&& reporter) { 16738 assert(!m_reporter && "Listening reporter can wrap only 1 real reporter"); 16739 m_reporter = std::move( reporter ); 16740 m_preferences.shouldRedirectStdOut = m_reporter->getPreferences().shouldRedirectStdOut; 16741 } 16742 16743 ReporterPreferences ListeningReporter::getPreferences() const { 16744 return m_preferences; 16745 } 16746 16747 std::set<Verbosity> ListeningReporter::getSupportedVerbosities() { 16748 return std::set<Verbosity>{ }; 16749 } 16750 16751 void ListeningReporter::noMatchingTestCases( std::string const& spec ) { 16752 for ( auto const& listener : m_listeners ) { 16753 listener->noMatchingTestCases( spec ); 16754 } 16755 m_reporter->noMatchingTestCases( spec ); 16756 } 16757 16758 void ListeningReporter::reportInvalidArguments(std::string const&arg){ 16759 for ( auto const& listener : m_listeners ) { 16760 listener->reportInvalidArguments( arg ); 16761 } 16762 m_reporter->reportInvalidArguments( arg ); 16763 } 16764 16765 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 16766 void ListeningReporter::benchmarkPreparing( std::string const& name ) { 16767 for (auto const& listener : m_listeners) { 16768 listener->benchmarkPreparing(name); 16769 } 16770 m_reporter->benchmarkPreparing(name); 16771 } 16772 void ListeningReporter::benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) { 16773 for ( auto const& listener : m_listeners ) { 16774 listener->benchmarkStarting( benchmarkInfo ); 16775 } 16776 m_reporter->benchmarkStarting( benchmarkInfo ); 16777 } 16778 void ListeningReporter::benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) { 16779 for ( auto const& listener : m_listeners ) { 16780 listener->benchmarkEnded( benchmarkStats ); 16781 } 16782 m_reporter->benchmarkEnded( benchmarkStats ); 16783 } 16784 16785 void ListeningReporter::benchmarkFailed( std::string const& error ) { 16786 for (auto const& listener : m_listeners) { 16787 listener->benchmarkFailed(error); 16788 } 16789 m_reporter->benchmarkFailed(error); 16790 } 16791 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 16792 16793 void ListeningReporter::testRunStarting( TestRunInfo const& testRunInfo ) { 16794 for ( auto const& listener : m_listeners ) { 16795 listener->testRunStarting( testRunInfo ); 16796 } 16797 m_reporter->testRunStarting( testRunInfo ); 16798 } 16799 16800 void ListeningReporter::testGroupStarting( GroupInfo const& groupInfo ) { 16801 for ( auto const& listener : m_listeners ) { 16802 listener->testGroupStarting( groupInfo ); 16803 } 16804 m_reporter->testGroupStarting( groupInfo ); 16805 } 16806 16807 void ListeningReporter::testCaseStarting( TestCaseInfo const& testInfo ) { 16808 for ( auto const& listener : m_listeners ) { 16809 listener->testCaseStarting( testInfo ); 16810 } 16811 m_reporter->testCaseStarting( testInfo ); 16812 } 16813 16814 void ListeningReporter::sectionStarting( SectionInfo const& sectionInfo ) { 16815 for ( auto const& listener : m_listeners ) { 16816 listener->sectionStarting( sectionInfo ); 16817 } 16818 m_reporter->sectionStarting( sectionInfo ); 16819 } 16820 16821 void ListeningReporter::assertionStarting( AssertionInfo const& assertionInfo ) { 16822 for ( auto const& listener : m_listeners ) { 16823 listener->assertionStarting( assertionInfo ); 16824 } 16825 m_reporter->assertionStarting( assertionInfo ); 16826 } 16827 16828 // The return value indicates if the messages buffer should be cleared: 16829 bool ListeningReporter::assertionEnded( AssertionStats const& assertionStats ) { 16830 for( auto const& listener : m_listeners ) { 16831 static_cast<void>( listener->assertionEnded( assertionStats ) ); 16832 } 16833 return m_reporter->assertionEnded( assertionStats ); 16834 } 16835 16836 void ListeningReporter::sectionEnded( SectionStats const& sectionStats ) { 16837 for ( auto const& listener : m_listeners ) { 16838 listener->sectionEnded( sectionStats ); 16839 } 16840 m_reporter->sectionEnded( sectionStats ); 16841 } 16842 16843 void ListeningReporter::testCaseEnded( TestCaseStats const& testCaseStats ) { 16844 for ( auto const& listener : m_listeners ) { 16845 listener->testCaseEnded( testCaseStats ); 16846 } 16847 m_reporter->testCaseEnded( testCaseStats ); 16848 } 16849 16850 void ListeningReporter::testGroupEnded( TestGroupStats const& testGroupStats ) { 16851 for ( auto const& listener : m_listeners ) { 16852 listener->testGroupEnded( testGroupStats ); 16853 } 16854 m_reporter->testGroupEnded( testGroupStats ); 16855 } 16856 16857 void ListeningReporter::testRunEnded( TestRunStats const& testRunStats ) { 16858 for ( auto const& listener : m_listeners ) { 16859 listener->testRunEnded( testRunStats ); 16860 } 16861 m_reporter->testRunEnded( testRunStats ); 16862 } 16863 16864 void ListeningReporter::skipTest( TestCaseInfo const& testInfo ) { 16865 for ( auto const& listener : m_listeners ) { 16866 listener->skipTest( testInfo ); 16867 } 16868 m_reporter->skipTest( testInfo ); 16869 } 16870 16871 bool ListeningReporter::isMulti() const { 16872 return true; 16873 } 16874 16875 } // end namespace Catch 16876 // end catch_reporter_listening.cpp 16877 // start catch_reporter_xml.cpp 16878 16879 #if defined(_MSC_VER) 16880 #pragma warning(push) 16881 #pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch 16882 // Note that 4062 (not all labels are handled 16883 // and default is missing) is enabled 16884 #endif 16885 16886 namespace Catch { 16887 XmlReporter::XmlReporter( ReporterConfig const& _config ) 16888 : StreamingReporterBase( _config ), 16889 m_xml(_config.stream()) 16890 { 16891 m_reporterPrefs.shouldRedirectStdOut = true; 16892 m_reporterPrefs.shouldReportAllAssertions = true; 16893 } 16894 16895 XmlReporter::~XmlReporter() = default; 16896 16897 std::string XmlReporter::getDescription() { 16898 return "Reports test results as an XML document"; 16899 } 16900 16901 std::string XmlReporter::getStylesheetRef() const { 16902 return std::string(); 16903 } 16904 16905 void XmlReporter::writeSourceInfo( SourceLineInfo const& sourceInfo ) { 16906 m_xml 16907 .writeAttribute( "filename", sourceInfo.file ) 16908 .writeAttribute( "line", sourceInfo.line ); 16909 } 16910 16911 void XmlReporter::noMatchingTestCases( std::string const& s ) { 16912 StreamingReporterBase::noMatchingTestCases( s ); 16913 } 16914 16915 void XmlReporter::testRunStarting( TestRunInfo const& testInfo ) { 16916 StreamingReporterBase::testRunStarting( testInfo ); 16917 std::string stylesheetRef = getStylesheetRef(); 16918 if( !stylesheetRef.empty() ) 16919 m_xml.writeStylesheetRef( stylesheetRef ); 16920 m_xml.startElement( "Catch" ); 16921 if( !m_config->name().empty() ) 16922 m_xml.writeAttribute( "name", m_config->name() ); 16923 if (m_config->testSpec().hasFilters()) 16924 m_xml.writeAttribute( "filters", serializeFilters( m_config->getTestsOrTags() ) ); 16925 if( m_config->rngSeed() != 0 ) 16926 m_xml.scopedElement( "Randomness" ) 16927 .writeAttribute( "seed", m_config->rngSeed() ); 16928 } 16929 16930 void XmlReporter::testGroupStarting( GroupInfo const& groupInfo ) { 16931 StreamingReporterBase::testGroupStarting( groupInfo ); 16932 m_xml.startElement( "Group" ) 16933 .writeAttribute( "name", groupInfo.name ); 16934 } 16935 16936 void XmlReporter::testCaseStarting( TestCaseInfo const& testInfo ) { 16937 StreamingReporterBase::testCaseStarting(testInfo); 16938 m_xml.startElement( "TestCase" ) 16939 .writeAttribute( "name", trim( testInfo.name ) ) 16940 .writeAttribute( "description", testInfo.description ) 16941 .writeAttribute( "tags", testInfo.tagsAsString() ); 16942 16943 writeSourceInfo( testInfo.lineInfo ); 16944 16945 if ( m_config->showDurations() == ShowDurations::Always ) 16946 m_testCaseTimer.start(); 16947 m_xml.ensureTagClosed(); 16948 } 16949 16950 void XmlReporter::sectionStarting( SectionInfo const& sectionInfo ) { 16951 StreamingReporterBase::sectionStarting( sectionInfo ); 16952 if( m_sectionDepth++ > 0 ) { 16953 m_xml.startElement( "Section" ) 16954 .writeAttribute( "name", trim( sectionInfo.name ) ); 16955 writeSourceInfo( sectionInfo.lineInfo ); 16956 m_xml.ensureTagClosed(); 16957 } 16958 } 16959 16960 void XmlReporter::assertionStarting( AssertionInfo const& ) { } 16961 16962 bool XmlReporter::assertionEnded( AssertionStats const& assertionStats ) { 16963 16964 AssertionResult const& result = assertionStats.assertionResult; 16965 16966 bool includeResults = m_config->includeSuccessfulResults() || !result.isOk(); 16967 16968 if( includeResults || result.getResultType() == ResultWas::Warning ) { 16969 // Print any info messages in <Info> tags. 16970 for( auto const& msg : assertionStats.infoMessages ) { 16971 if( msg.type == ResultWas::Info && includeResults ) { 16972 m_xml.scopedElement( "Info" ) 16973 .writeText( msg.message ); 16974 } else if ( msg.type == ResultWas::Warning ) { 16975 m_xml.scopedElement( "Warning" ) 16976 .writeText( msg.message ); 16977 } 16978 } 16979 } 16980 16981 // Drop out if result was successful but we're not printing them. 16982 if( !includeResults && result.getResultType() != ResultWas::Warning ) 16983 return true; 16984 16985 // Print the expression if there is one. 16986 if( result.hasExpression() ) { 16987 m_xml.startElement( "Expression" ) 16988 .writeAttribute( "success", result.succeeded() ) 16989 .writeAttribute( "type", result.getTestMacroName() ); 16990 16991 writeSourceInfo( result.getSourceInfo() ); 16992 16993 m_xml.scopedElement( "Original" ) 16994 .writeText( result.getExpression() ); 16995 m_xml.scopedElement( "Expanded" ) 16996 .writeText( result.getExpandedExpression() ); 16997 } 16998 16999 // And... Print a result applicable to each result type. 17000 switch( result.getResultType() ) { 17001 case ResultWas::ThrewException: 17002 m_xml.startElement( "Exception" ); 17003 writeSourceInfo( result.getSourceInfo() ); 17004 m_xml.writeText( result.getMessage() ); 17005 m_xml.endElement(); 17006 break; 17007 case ResultWas::FatalErrorCondition: 17008 m_xml.startElement( "FatalErrorCondition" ); 17009 writeSourceInfo( result.getSourceInfo() ); 17010 m_xml.writeText( result.getMessage() ); 17011 m_xml.endElement(); 17012 break; 17013 case ResultWas::Info: 17014 m_xml.scopedElement( "Info" ) 17015 .writeText( result.getMessage() ); 17016 break; 17017 case ResultWas::Warning: 17018 // Warning will already have been written 17019 break; 17020 case ResultWas::ExplicitFailure: 17021 m_xml.startElement( "Failure" ); 17022 writeSourceInfo( result.getSourceInfo() ); 17023 m_xml.writeText( result.getMessage() ); 17024 m_xml.endElement(); 17025 break; 17026 default: 17027 break; 17028 } 17029 17030 if( result.hasExpression() ) 17031 m_xml.endElement(); 17032 17033 return true; 17034 } 17035 17036 void XmlReporter::sectionEnded( SectionStats const& sectionStats ) { 17037 StreamingReporterBase::sectionEnded( sectionStats ); 17038 if( --m_sectionDepth > 0 ) { 17039 XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" ); 17040 e.writeAttribute( "successes", sectionStats.assertions.passed ); 17041 e.writeAttribute( "failures", sectionStats.assertions.failed ); 17042 e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk ); 17043 17044 if ( m_config->showDurations() == ShowDurations::Always ) 17045 e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds ); 17046 17047 m_xml.endElement(); 17048 } 17049 } 17050 17051 void XmlReporter::testCaseEnded( TestCaseStats const& testCaseStats ) { 17052 StreamingReporterBase::testCaseEnded( testCaseStats ); 17053 XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" ); 17054 e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() ); 17055 17056 if ( m_config->showDurations() == ShowDurations::Always ) 17057 e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() ); 17058 17059 if( !testCaseStats.stdOut.empty() ) 17060 m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), XmlFormatting::Newline ); 17061 if( !testCaseStats.stdErr.empty() ) 17062 m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), XmlFormatting::Newline ); 17063 17064 m_xml.endElement(); 17065 } 17066 17067 void XmlReporter::testGroupEnded( TestGroupStats const& testGroupStats ) { 17068 StreamingReporterBase::testGroupEnded( testGroupStats ); 17069 // TODO: Check testGroupStats.aborting and act accordingly. 17070 m_xml.scopedElement( "OverallResults" ) 17071 .writeAttribute( "successes", testGroupStats.totals.assertions.passed ) 17072 .writeAttribute( "failures", testGroupStats.totals.assertions.failed ) 17073 .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk ); 17074 m_xml.endElement(); 17075 } 17076 17077 void XmlReporter::testRunEnded( TestRunStats const& testRunStats ) { 17078 StreamingReporterBase::testRunEnded( testRunStats ); 17079 m_xml.scopedElement( "OverallResults" ) 17080 .writeAttribute( "successes", testRunStats.totals.assertions.passed ) 17081 .writeAttribute( "failures", testRunStats.totals.assertions.failed ) 17082 .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk ); 17083 m_xml.endElement(); 17084 } 17085 17086 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 17087 void XmlReporter::benchmarkPreparing(std::string const& name) { 17088 m_xml.startElement("BenchmarkResults") 17089 .writeAttribute("name", name); 17090 } 17091 17092 void XmlReporter::benchmarkStarting(BenchmarkInfo const &info) { 17093 m_xml.writeAttribute("samples", info.samples) 17094 .writeAttribute("resamples", info.resamples) 17095 .writeAttribute("iterations", info.iterations) 17096 .writeAttribute("clockResolution", static_cast<uint64_t>(info.clockResolution)) 17097 .writeAttribute("estimatedDuration", static_cast<uint64_t>(info.estimatedDuration)) 17098 .writeComment("All values in nano seconds"); 17099 } 17100 17101 void XmlReporter::benchmarkEnded(BenchmarkStats<> const& benchmarkStats) { 17102 m_xml.startElement("mean") 17103 .writeAttribute("value", static_cast<uint64_t>(benchmarkStats.mean.point.count())) 17104 .writeAttribute("lowerBound", static_cast<uint64_t>(benchmarkStats.mean.lower_bound.count())) 17105 .writeAttribute("upperBound", static_cast<uint64_t>(benchmarkStats.mean.upper_bound.count())) 17106 .writeAttribute("ci", benchmarkStats.mean.confidence_interval); 17107 m_xml.endElement(); 17108 m_xml.startElement("standardDeviation") 17109 .writeAttribute("value", benchmarkStats.standardDeviation.point.count()) 17110 .writeAttribute("lowerBound", benchmarkStats.standardDeviation.lower_bound.count()) 17111 .writeAttribute("upperBound", benchmarkStats.standardDeviation.upper_bound.count()) 17112 .writeAttribute("ci", benchmarkStats.standardDeviation.confidence_interval); 17113 m_xml.endElement(); 17114 m_xml.startElement("outliers") 17115 .writeAttribute("variance", benchmarkStats.outlierVariance) 17116 .writeAttribute("lowMild", benchmarkStats.outliers.low_mild) 17117 .writeAttribute("lowSevere", benchmarkStats.outliers.low_severe) 17118 .writeAttribute("highMild", benchmarkStats.outliers.high_mild) 17119 .writeAttribute("highSevere", benchmarkStats.outliers.high_severe); 17120 m_xml.endElement(); 17121 m_xml.endElement(); 17122 } 17123 17124 void XmlReporter::benchmarkFailed(std::string const &error) { 17125 m_xml.scopedElement("failed"). 17126 writeAttribute("message", error); 17127 m_xml.endElement(); 17128 } 17129 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 17130 17131 CATCH_REGISTER_REPORTER( "xml", XmlReporter ) 17132 17133 } // end namespace Catch 17134 17135 #if defined(_MSC_VER) 17136 #pragma warning(pop) 17137 #endif 17138 // end catch_reporter_xml.cpp 17139 17140 namespace Catch { 17141 LeakDetector leakDetector; 17142 } 17143 17144 #ifdef __clang__ 17145 #pragma clang diagnostic pop 17146 #endif 17147 17148 // end catch_impl.hpp 17149 #endif 17150 17151 #ifdef CATCH_CONFIG_MAIN 17152 // start catch_default_main.hpp 17153 17154 #ifndef __OBJC__ 17155 17156 #if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN) 17157 // Standard C/C++ Win32 Unicode wmain entry point 17158 extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) { 17159 #else 17160 // Standard C/C++ main entry point 17161 int main (int argc, char * argv[]) { 17162 #endif 17163 17164 return Catch::Session().run( argc, argv ); 17165 } 17166 17167 #else // __OBJC__ 17168 17169 // Objective-C entry point 17170 int main (int argc, char * const argv[]) { 17171 #if !CATCH_ARC_ENABLED 17172 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 17173 #endif 17174 17175 Catch::registerTestMethods(); 17176 int result = Catch::Session().run( argc, (char**)argv ); 17177 17178 #if !CATCH_ARC_ENABLED 17179 [pool drain]; 17180 #endif 17181 17182 return result; 17183 } 17184 17185 #endif // __OBJC__ 17186 17187 // end catch_default_main.hpp 17188 #endif 17189 17190 #if !defined(CATCH_CONFIG_IMPL_ONLY) 17191 17192 #ifdef CLARA_CONFIG_MAIN_NOT_DEFINED 17193 # undef CLARA_CONFIG_MAIN 17194 #endif 17195 17196 #if !defined(CATCH_CONFIG_DISABLE) 17197 ////// 17198 // If this config identifier is defined then all CATCH macros are prefixed with CATCH_ 17199 #ifdef CATCH_CONFIG_PREFIX_ALL 17200 17201 #define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17202 #define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 17203 17204 #define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17205 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) 17206 #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) 17207 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17208 #define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) 17209 #endif// CATCH_CONFIG_DISABLE_MATCHERS 17210 #define CATCH_REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17211 17212 #define CATCH_CHECK( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17213 #define CATCH_CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 17214 #define CATCH_CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17215 #define CATCH_CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17216 #define CATCH_CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) 17217 17218 #define CATCH_CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17219 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) 17220 #define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 17221 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17222 #define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 17223 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17224 #define CATCH_CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17225 17226 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17227 #define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) 17228 17229 #define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) 17230 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17231 17232 #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) 17233 #define CATCH_UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "CATCH_UNSCOPED_INFO", msg ) 17234 #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) 17235 #define CATCH_CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CATCH_CAPTURE",__VA_ARGS__ ) 17236 17237 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) 17238 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17239 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) 17240 #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) 17241 #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) 17242 #define CATCH_DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ ) 17243 #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17244 #define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17245 #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17246 17247 #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE() 17248 17249 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 17250 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17251 #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) 17252 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17253 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) 17254 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) 17255 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) 17256 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17257 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) 17258 #else 17259 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) ) 17260 #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) ) 17261 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) 17262 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) ) 17263 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) ) 17264 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) ) 17265 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) 17266 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) ) 17267 #endif 17268 17269 #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE) 17270 #define CATCH_STATIC_REQUIRE( ... ) static_assert( __VA_ARGS__ , #__VA_ARGS__ ); CATCH_SUCCEED( #__VA_ARGS__ ) 17271 #define CATCH_STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); CATCH_SUCCEED( #__VA_ARGS__ ) 17272 #else 17273 #define CATCH_STATIC_REQUIRE( ... ) CATCH_REQUIRE( __VA_ARGS__ ) 17274 #define CATCH_STATIC_REQUIRE_FALSE( ... ) CATCH_REQUIRE_FALSE( __VA_ARGS__ ) 17275 #endif 17276 17277 // "BDD-style" convenience wrappers 17278 #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) 17279 #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) 17280 #define CATCH_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc ) 17281 #define CATCH_AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc ) 17282 #define CATCH_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc ) 17283 #define CATCH_AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc ) 17284 #define CATCH_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc ) 17285 #define CATCH_AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc ) 17286 17287 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 17288 #define CATCH_BENCHMARK(...) \ 17289 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__,,)) 17290 #define CATCH_BENCHMARK_ADVANCED(name) \ 17291 INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), name) 17292 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 17293 17294 // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required 17295 #else 17296 17297 #define REQUIRE( ... ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17298 #define REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 17299 17300 #define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17301 #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) 17302 #define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) 17303 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17304 #define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) 17305 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17306 #define REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17307 17308 #define CHECK( ... ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17309 #define CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 17310 #define CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17311 #define CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17312 #define CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) 17313 17314 #define CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17315 #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) 17316 #define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 17317 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17318 #define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 17319 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17320 #define CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17321 17322 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17323 #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) 17324 17325 #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) 17326 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17327 17328 #define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) 17329 #define UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "UNSCOPED_INFO", msg ) 17330 #define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) 17331 #define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE",__VA_ARGS__ ) 17332 17333 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) 17334 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17335 #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) 17336 #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) 17337 #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) 17338 #define DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ ) 17339 #define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17340 #define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17341 #define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17342 #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE() 17343 17344 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 17345 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17346 #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) 17347 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17348 #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) 17349 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) 17350 #define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) 17351 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17352 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) 17353 #define TEMPLATE_LIST_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(__VA_ARGS__) 17354 #define TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17355 #else 17356 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) ) 17357 #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) ) 17358 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) 17359 #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) ) 17360 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) ) 17361 #define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) ) 17362 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) 17363 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) ) 17364 #define TEMPLATE_LIST_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE( __VA_ARGS__ ) ) 17365 #define TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) 17366 #endif 17367 17368 #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE) 17369 #define STATIC_REQUIRE( ... ) static_assert( __VA_ARGS__, #__VA_ARGS__ ); SUCCEED( #__VA_ARGS__ ) 17370 #define STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); SUCCEED( "!(" #__VA_ARGS__ ")" ) 17371 #else 17372 #define STATIC_REQUIRE( ... ) REQUIRE( __VA_ARGS__ ) 17373 #define STATIC_REQUIRE_FALSE( ... ) REQUIRE_FALSE( __VA_ARGS__ ) 17374 #endif 17375 17376 #endif 17377 17378 #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) 17379 17380 // "BDD-style" convenience wrappers 17381 #define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) 17382 #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) 17383 17384 #define GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc ) 17385 #define AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc ) 17386 #define WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc ) 17387 #define AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc ) 17388 #define THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc ) 17389 #define AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc ) 17390 17391 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) 17392 #define BENCHMARK(...) \ 17393 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__,,)) 17394 #define BENCHMARK_ADVANCED(name) \ 17395 INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), name) 17396 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING 17397 17398 using Catch::Detail::Approx; 17399 17400 #else // CATCH_CONFIG_DISABLE 17401 17402 ////// 17403 // If this config identifier is defined then all CATCH macros are prefixed with CATCH_ 17404 #ifdef CATCH_CONFIG_PREFIX_ALL 17405 17406 #define CATCH_REQUIRE( ... ) (void)(0) 17407 #define CATCH_REQUIRE_FALSE( ... ) (void)(0) 17408 17409 #define CATCH_REQUIRE_THROWS( ... ) (void)(0) 17410 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0) 17411 #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) (void)(0) 17412 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17413 #define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) 17414 #endif// CATCH_CONFIG_DISABLE_MATCHERS 17415 #define CATCH_REQUIRE_NOTHROW( ... ) (void)(0) 17416 17417 #define CATCH_CHECK( ... ) (void)(0) 17418 #define CATCH_CHECK_FALSE( ... ) (void)(0) 17419 #define CATCH_CHECKED_IF( ... ) if (__VA_ARGS__) 17420 #define CATCH_CHECKED_ELSE( ... ) if (!(__VA_ARGS__)) 17421 #define CATCH_CHECK_NOFAIL( ... ) (void)(0) 17422 17423 #define CATCH_CHECK_THROWS( ... ) (void)(0) 17424 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) (void)(0) 17425 #define CATCH_CHECK_THROWS_WITH( expr, matcher ) (void)(0) 17426 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17427 #define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) 17428 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17429 #define CATCH_CHECK_NOTHROW( ... ) (void)(0) 17430 17431 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17432 #define CATCH_CHECK_THAT( arg, matcher ) (void)(0) 17433 17434 #define CATCH_REQUIRE_THAT( arg, matcher ) (void)(0) 17435 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17436 17437 #define CATCH_INFO( msg ) (void)(0) 17438 #define CATCH_UNSCOPED_INFO( msg ) (void)(0) 17439 #define CATCH_WARN( msg ) (void)(0) 17440 #define CATCH_CAPTURE( msg ) (void)(0) 17441 17442 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 17443 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 17444 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) 17445 #define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0) 17446 #define CATCH_SECTION( ... ) 17447 #define CATCH_DYNAMIC_SECTION( ... ) 17448 #define CATCH_FAIL( ... ) (void)(0) 17449 #define CATCH_FAIL_CHECK( ... ) (void)(0) 17450 #define CATCH_SUCCEED( ... ) (void)(0) 17451 17452 #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 17453 17454 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 17455 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) 17456 #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) 17457 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__) 17458 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) 17459 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17460 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17461 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17462 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17463 #else 17464 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) ) 17465 #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) ) 17466 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__ ) ) 17467 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) ) 17468 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17469 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17470 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17471 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17472 #endif 17473 17474 // "BDD-style" convenience wrappers 17475 #define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 17476 #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 ) 17477 #define CATCH_GIVEN( desc ) 17478 #define CATCH_AND_GIVEN( desc ) 17479 #define CATCH_WHEN( desc ) 17480 #define CATCH_AND_WHEN( desc ) 17481 #define CATCH_THEN( desc ) 17482 #define CATCH_AND_THEN( desc ) 17483 17484 #define CATCH_STATIC_REQUIRE( ... ) (void)(0) 17485 #define CATCH_STATIC_REQUIRE_FALSE( ... ) (void)(0) 17486 17487 // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required 17488 #else 17489 17490 #define REQUIRE( ... ) (void)(0) 17491 #define REQUIRE_FALSE( ... ) (void)(0) 17492 17493 #define REQUIRE_THROWS( ... ) (void)(0) 17494 #define REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0) 17495 #define REQUIRE_THROWS_WITH( expr, matcher ) (void)(0) 17496 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17497 #define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) 17498 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17499 #define REQUIRE_NOTHROW( ... ) (void)(0) 17500 17501 #define CHECK( ... ) (void)(0) 17502 #define CHECK_FALSE( ... ) (void)(0) 17503 #define CHECKED_IF( ... ) if (__VA_ARGS__) 17504 #define CHECKED_ELSE( ... ) if (!(__VA_ARGS__)) 17505 #define CHECK_NOFAIL( ... ) (void)(0) 17506 17507 #define CHECK_THROWS( ... ) (void)(0) 17508 #define CHECK_THROWS_AS( expr, exceptionType ) (void)(0) 17509 #define CHECK_THROWS_WITH( expr, matcher ) (void)(0) 17510 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17511 #define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) 17512 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17513 #define CHECK_NOTHROW( ... ) (void)(0) 17514 17515 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 17516 #define CHECK_THAT( arg, matcher ) (void)(0) 17517 17518 #define REQUIRE_THAT( arg, matcher ) (void)(0) 17519 #endif // CATCH_CONFIG_DISABLE_MATCHERS 17520 17521 #define INFO( msg ) (void)(0) 17522 #define UNSCOPED_INFO( msg ) (void)(0) 17523 #define WARN( msg ) (void)(0) 17524 #define CAPTURE( msg ) (void)(0) 17525 17526 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 17527 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 17528 #define METHOD_AS_TEST_CASE( method, ... ) 17529 #define REGISTER_TEST_CASE( Function, ... ) (void)(0) 17530 #define SECTION( ... ) 17531 #define DYNAMIC_SECTION( ... ) 17532 #define FAIL( ... ) (void)(0) 17533 #define FAIL_CHECK( ... ) (void)(0) 17534 #define SUCCEED( ... ) (void)(0) 17535 #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 17536 17537 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 17538 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) 17539 #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) 17540 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__) 17541 #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) 17542 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17543 #define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17544 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17545 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17546 #else 17547 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) ) 17548 #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) ) 17549 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__ ) ) 17550 #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) ) 17551 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17552 #define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17553 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17554 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17555 #endif 17556 17557 #define STATIC_REQUIRE( ... ) (void)(0) 17558 #define STATIC_REQUIRE_FALSE( ... ) (void)(0) 17559 17560 #endif 17561 17562 #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) 17563 17564 // "BDD-style" convenience wrappers 17565 #define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) ) 17566 #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className ) 17567 17568 #define GIVEN( desc ) 17569 #define AND_GIVEN( desc ) 17570 #define WHEN( desc ) 17571 #define AND_WHEN( desc ) 17572 #define THEN( desc ) 17573 #define AND_THEN( desc ) 17574 17575 using Catch::Detail::Approx; 17576 17577 #endif 17578 17579 #endif // ! CATCH_CONFIG_IMPL_ONLY 17580 17581 // start catch_reenable_warnings.h 17582 17583 17584 #ifdef __clang__ 17585 # ifdef __ICC // icpc defines the __clang__ macro 17586 # pragma warning(pop) 17587 # else 17588 # pragma clang diagnostic pop 17589 # endif 17590 #elif defined __GNUC__ 17591 # pragma GCC diagnostic pop 17592 #endif 17593 17594 // end catch_reenable_warnings.h 17595 // end catch.hpp 17596 #endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED 17597 17598