/ unit_tests / catch.hpp
catch.hpp
1 /* 2 * Catch v2.7.2 3 * Generated: 2019-04-22 23:13:14.687465 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 7 18 #define CATCH_VERSION_PATCH 2 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 #ifdef __clang__ 140 141 # define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 142 _Pragma( "clang diagnostic push" ) \ 143 _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ 144 _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") 145 # define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ 146 _Pragma( "clang diagnostic pop" ) 147 148 # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ 149 _Pragma( "clang diagnostic push" ) \ 150 _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) 151 # define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ 152 _Pragma( "clang diagnostic pop" ) 153 154 # define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ 155 _Pragma( "clang diagnostic push" ) \ 156 _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" ) 157 # define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS \ 158 _Pragma( "clang diagnostic pop" ) 159 160 #endif // __clang__ 161 162 //////////////////////////////////////////////////////////////////////////////// 163 // Assume that non-Windows platforms support posix signals by default 164 #if !defined(CATCH_PLATFORM_WINDOWS) 165 #define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS 166 #endif 167 168 //////////////////////////////////////////////////////////////////////////////// 169 // We know some environments not to support full POSIX signals 170 #if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__) 171 #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS 172 #endif 173 174 #ifdef __OS400__ 175 # define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS 176 # define CATCH_CONFIG_COLOUR_NONE 177 #endif 178 179 //////////////////////////////////////////////////////////////////////////////// 180 // Android somehow still does not support std::to_string 181 #if defined(__ANDROID__) 182 # define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING 183 #endif 184 185 //////////////////////////////////////////////////////////////////////////////// 186 // Not all Windows environments support SEH properly 187 #if defined(__MINGW32__) 188 # define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH 189 #endif 190 191 //////////////////////////////////////////////////////////////////////////////// 192 // PS4 193 #if defined(__ORBIS__) 194 # define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE 195 #endif 196 197 //////////////////////////////////////////////////////////////////////////////// 198 // Cygwin 199 #ifdef __CYGWIN__ 200 201 // Required for some versions of Cygwin to declare gettimeofday 202 // see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin 203 # define _BSD_SOURCE 204 // some versions of cygwin (most) do not support std::to_string. Use the libstd check. 205 // https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813 206 # if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \ 207 && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF)) 208 209 # define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING 210 211 # endif 212 #endif // __CYGWIN__ 213 214 //////////////////////////////////////////////////////////////////////////////// 215 // Visual C++ 216 #ifdef _MSC_VER 217 218 # if _MSC_VER >= 1900 // Visual Studio 2015 or newer 219 # define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS 220 # endif 221 222 // Universal Windows platform does not support SEH 223 // Or console colours (or console at all...) 224 # if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) 225 # define CATCH_CONFIG_COLOUR_NONE 226 # else 227 # define CATCH_INTERNAL_CONFIG_WINDOWS_SEH 228 # endif 229 230 // MSVC traditional preprocessor needs some workaround for __VA_ARGS__ 231 // _MSVC_TRADITIONAL == 0 means new conformant preprocessor 232 // _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor 233 # if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) 234 # define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 235 # endif 236 237 #endif // _MSC_VER 238 239 //////////////////////////////////////////////////////////////////////////////// 240 // Check if we are compiled with -fno-exceptions or equivalent 241 #if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND) 242 # define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED 243 #endif 244 245 //////////////////////////////////////////////////////////////////////////////// 246 // DJGPP 247 #ifdef __DJGPP__ 248 # define CATCH_INTERNAL_CONFIG_NO_WCHAR 249 #endif // __DJGPP__ 250 251 //////////////////////////////////////////////////////////////////////////////// 252 // Embarcadero C++Build 253 #if defined(__BORLANDC__) 254 #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN 255 #endif 256 257 //////////////////////////////////////////////////////////////////////////////// 258 259 // Use of __COUNTER__ is suppressed during code analysis in 260 // CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly 261 // handled by it. 262 // Otherwise all supported compilers support COUNTER macro, 263 // but user still might want to turn it off 264 #if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L ) 265 #define CATCH_INTERNAL_CONFIG_COUNTER 266 #endif 267 268 //////////////////////////////////////////////////////////////////////////////// 269 // Check if string_view is available and usable 270 // The check is split apart to work around v140 (VS2015) preprocessor issue... 271 #if defined(__has_include) 272 #if __has_include(<string_view>) && defined(CATCH_CPP17_OR_GREATER) 273 # define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW 274 #endif 275 #endif 276 277 //////////////////////////////////////////////////////////////////////////////// 278 // Check if optional is available and usable 279 #if defined(__has_include) 280 # if __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER) 281 # define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL 282 # endif // __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER) 283 #endif // __has_include 284 285 //////////////////////////////////////////////////////////////////////////////// 286 // Check if variant is available and usable 287 #if defined(__has_include) 288 # if __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER) 289 # if defined(__clang__) && (__clang_major__ < 8) 290 // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852 291 // fix should be in clang 8, workaround in libstdc++ 8.2 292 # include <ciso646> 293 # if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) 294 # define CATCH_CONFIG_NO_CPP17_VARIANT 295 # else 296 # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT 297 # endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) 298 # else 299 # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT 300 # endif // defined(__clang__) && (__clang_major__ < 8) 301 # endif // __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER) 302 #endif // __has_include 303 304 #if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) 305 # define CATCH_CONFIG_COUNTER 306 #endif 307 #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) 308 # define CATCH_CONFIG_WINDOWS_SEH 309 #endif 310 // This is set by default, because we assume that unix compilers are posix-signal-compatible by default. 311 #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) 312 # define CATCH_CONFIG_POSIX_SIGNALS 313 #endif 314 // This is set by default, because we assume that compilers with no wchar_t support are just rare exceptions. 315 #if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR) 316 # define CATCH_CONFIG_WCHAR 317 #endif 318 319 #if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING) 320 # define CATCH_CONFIG_CPP11_TO_STRING 321 #endif 322 323 #if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL) 324 # define CATCH_CONFIG_CPP17_OPTIONAL 325 #endif 326 327 #if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) 328 # define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS 329 #endif 330 331 #if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW) 332 # define CATCH_CONFIG_CPP17_STRING_VIEW 333 #endif 334 335 #if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT) 336 # define CATCH_CONFIG_CPP17_VARIANT 337 #endif 338 339 #if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) 340 # define CATCH_INTERNAL_CONFIG_NEW_CAPTURE 341 #endif 342 343 #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) 344 # define CATCH_CONFIG_NEW_CAPTURE 345 #endif 346 347 #if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 348 # define CATCH_CONFIG_DISABLE_EXCEPTIONS 349 #endif 350 351 #if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN) 352 # define CATCH_CONFIG_POLYFILL_ISNAN 353 #endif 354 355 #if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) 356 # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS 357 # define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS 358 #endif 359 #if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS) 360 # define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS 361 # define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS 362 #endif 363 #if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS) 364 # define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS 365 # define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS 366 #endif 367 368 #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 369 #define CATCH_TRY if ((true)) 370 #define CATCH_CATCH_ALL if ((false)) 371 #define CATCH_CATCH_ANON(type) if ((false)) 372 #else 373 #define CATCH_TRY try 374 #define CATCH_CATCH_ALL catch (...) 375 #define CATCH_CATCH_ANON(type) catch (type) 376 #endif 377 378 #if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) 379 #define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 380 #endif 381 382 // end catch_compiler_capabilities.h 383 #define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line 384 #define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) 385 #ifdef CATCH_CONFIG_COUNTER 386 # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) 387 #else 388 # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) 389 #endif 390 391 #include <iosfwd> 392 #include <string> 393 #include <cstdint> 394 395 // We need a dummy global operator<< so we can bring it into Catch namespace later 396 struct Catch_global_namespace_dummy {}; 397 std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy); 398 399 namespace Catch { 400 401 struct CaseSensitive { enum Choice { 402 Yes, 403 No 404 }; }; 405 406 class NonCopyable { 407 NonCopyable( NonCopyable const& ) = delete; 408 NonCopyable( NonCopyable && ) = delete; 409 NonCopyable& operator = ( NonCopyable const& ) = delete; 410 NonCopyable& operator = ( NonCopyable && ) = delete; 411 412 protected: 413 NonCopyable(); 414 virtual ~NonCopyable(); 415 }; 416 417 struct SourceLineInfo { 418 419 SourceLineInfo() = delete; 420 SourceLineInfo( char const* _file, std::size_t _line ) noexcept 421 : file( _file ), 422 line( _line ) 423 {} 424 425 SourceLineInfo( SourceLineInfo const& other ) = default; 426 SourceLineInfo& operator = ( SourceLineInfo const& ) = default; 427 SourceLineInfo( SourceLineInfo&& ) noexcept = default; 428 SourceLineInfo& operator = ( SourceLineInfo&& ) noexcept = default; 429 430 bool empty() const noexcept; 431 bool operator == ( SourceLineInfo const& other ) const noexcept; 432 bool operator < ( SourceLineInfo const& other ) const noexcept; 433 434 char const* file; 435 std::size_t line; 436 }; 437 438 std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); 439 440 // Bring in operator<< from global namespace into Catch namespace 441 // This is necessary because the overload of operator<< above makes 442 // lookup stop at namespace Catch 443 using ::operator<<; 444 445 // Use this in variadic streaming macros to allow 446 // >> +StreamEndStop 447 // as well as 448 // >> stuff +StreamEndStop 449 struct StreamEndStop { 450 std::string operator+() const; 451 }; 452 template<typename T> 453 T const& operator + ( T const& value, StreamEndStop ) { 454 return value; 455 } 456 } 457 458 #define CATCH_INTERNAL_LINEINFO \ 459 ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) ) 460 461 // end catch_common.h 462 namespace Catch { 463 464 struct RegistrarForTagAliases { 465 RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); 466 }; 467 468 } // end namespace Catch 469 470 #define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \ 471 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 472 namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \ 473 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS 474 475 // end catch_tag_alias_autoregistrar.h 476 // start catch_test_registry.h 477 478 // start catch_interfaces_testcase.h 479 480 #include <vector> 481 482 namespace Catch { 483 484 class TestSpec; 485 486 struct ITestInvoker { 487 virtual void invoke () const = 0; 488 virtual ~ITestInvoker(); 489 }; 490 491 class TestCase; 492 struct IConfig; 493 494 struct ITestCaseRegistry { 495 virtual ~ITestCaseRegistry(); 496 virtual std::vector<TestCase> const& getAllTests() const = 0; 497 virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const = 0; 498 }; 499 500 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); 501 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ); 502 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ); 503 504 } 505 506 // end catch_interfaces_testcase.h 507 // start catch_stringref.h 508 509 #include <cstddef> 510 #include <string> 511 #include <iosfwd> 512 513 namespace Catch { 514 515 /// A non-owning string class (similar to the forthcoming std::string_view) 516 /// Note that, because a StringRef may be a substring of another string, 517 /// it may not be null terminated. c_str() must return a null terminated 518 /// string, however, and so the StringRef will internally take ownership 519 /// (taking a copy), if necessary. In theory this ownership is not externally 520 /// visible - but it does mean (substring) StringRefs should not be shared between 521 /// threads. 522 class StringRef { 523 public: 524 using size_type = std::size_t; 525 526 private: 527 friend struct StringRefTestAccess; 528 529 char const* m_start; 530 size_type m_size; 531 532 char* m_data = nullptr; 533 534 void takeOwnership(); 535 536 static constexpr char const* const s_empty = ""; 537 538 public: // construction/ assignment 539 StringRef() noexcept 540 : StringRef( s_empty, 0 ) 541 {} 542 543 StringRef( StringRef const& other ) noexcept 544 : m_start( other.m_start ), 545 m_size( other.m_size ) 546 {} 547 548 StringRef( StringRef&& other ) noexcept 549 : m_start( other.m_start ), 550 m_size( other.m_size ), 551 m_data( other.m_data ) 552 { 553 other.m_data = nullptr; 554 } 555 556 StringRef( char const* rawChars ) noexcept; 557 558 StringRef( char const* rawChars, size_type size ) noexcept 559 : m_start( rawChars ), 560 m_size( size ) 561 {} 562 563 StringRef( std::string const& stdString ) noexcept 564 : m_start( stdString.c_str() ), 565 m_size( stdString.size() ) 566 {} 567 568 ~StringRef() noexcept { 569 delete[] m_data; 570 } 571 572 auto operator = ( StringRef const &other ) noexcept -> StringRef& { 573 delete[] m_data; 574 m_data = nullptr; 575 m_start = other.m_start; 576 m_size = other.m_size; 577 return *this; 578 } 579 580 operator std::string() const; 581 582 void swap( StringRef& other ) noexcept; 583 584 public: // operators 585 auto operator == ( StringRef const& other ) const noexcept -> bool; 586 auto operator != ( StringRef const& other ) const noexcept -> bool; 587 588 auto operator[] ( size_type index ) const noexcept -> char; 589 590 public: // named queries 591 auto empty() const noexcept -> bool { 592 return m_size == 0; 593 } 594 auto size() const noexcept -> size_type { 595 return m_size; 596 } 597 598 auto numberOfCharacters() const noexcept -> size_type; 599 auto c_str() const -> char const*; 600 601 public: // substrings and searches 602 auto substr( size_type start, size_type size ) const noexcept -> StringRef; 603 604 // Returns the current start pointer. 605 // Note that the pointer can change when if the StringRef is a substring 606 auto currentData() const noexcept -> char const*; 607 608 private: // ownership queries - may not be consistent between calls 609 auto isOwned() const noexcept -> bool; 610 auto isSubstring() const noexcept -> bool; 611 }; 612 613 auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string; 614 auto operator + ( StringRef const& lhs, char const* rhs ) -> std::string; 615 auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string; 616 617 auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&; 618 auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&; 619 620 inline auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef { 621 return StringRef( rawChars, size ); 622 } 623 624 } // namespace Catch 625 626 inline auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef { 627 return Catch::StringRef( rawChars, size ); 628 } 629 630 // end catch_stringref.h 631 // start catch_type_traits.hpp 632 633 634 #include <type_traits> 635 636 namespace Catch{ 637 638 #ifdef CATCH_CPP17_OR_GREATER 639 template <typename...> 640 inline constexpr auto is_unique = std::true_type{}; 641 642 template <typename T, typename... Rest> 643 inline constexpr auto is_unique<T, Rest...> = std::bool_constant< 644 (!std::is_same_v<T, Rest> && ...) && is_unique<Rest...> 645 >{}; 646 #else 647 648 template <typename...> 649 struct is_unique : std::true_type{}; 650 651 template <typename T0, typename T1, typename... Rest> 652 struct is_unique<T0, T1, Rest...> : std::integral_constant 653 <bool, 654 !std::is_same<T0, T1>::value 655 && is_unique<T0, Rest...>::value 656 && is_unique<T1, Rest...>::value 657 >{}; 658 659 #endif 660 } 661 662 // end catch_type_traits.hpp 663 // start catch_preprocessor.hpp 664 665 666 #define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__ 667 #define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__))) 668 #define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__))) 669 #define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__))) 670 #define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__))) 671 #define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__))) 672 673 #ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 674 #define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__ 675 // MSVC needs more evaluations 676 #define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__))) 677 #define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__)) 678 #else 679 #define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL5(__VA_ARGS__) 680 #endif 681 682 #define CATCH_REC_END(...) 683 #define CATCH_REC_OUT 684 685 #define CATCH_EMPTY() 686 #define CATCH_DEFER(id) id CATCH_EMPTY() 687 688 #define CATCH_REC_GET_END2() 0, CATCH_REC_END 689 #define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2 690 #define CATCH_REC_GET_END(...) CATCH_REC_GET_END1 691 #define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT 692 #define CATCH_REC_NEXT1(test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0) 693 #define CATCH_REC_NEXT(test, next) CATCH_REC_NEXT1(CATCH_REC_GET_END test, next) 694 695 #define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) 696 #define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ ) 697 #define CATCH_REC_LIST2(f, x, peek, ...) f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) 698 699 #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__ ) 700 #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__ ) 701 #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__ ) 702 703 // Applies the function macro `f` to each of the remaining parameters, inserts commas between the results, 704 // and passes userdata as the first parameter to each invocation, 705 // e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c) 706 #define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) 707 708 #define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) 709 710 #define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param) 711 #define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__ 712 #define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__ 713 #define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF 714 #define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__) 715 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 716 #define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__ 717 #define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) 718 #else 719 // MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF 720 #define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__) 721 #define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__ 722 #define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1) 723 #endif 724 725 #define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__) 726 727 #define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME2(Name, ...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME3(Name, __VA_ARGS__) 728 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 729 #define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME3(Name,...) Name " - " #__VA_ARGS__ 730 #define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME(Name,...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME2(Name, INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)) 731 #else 732 // MSVC is adding extra space and needs more calls to properly remove () 733 #define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME3(Name,...) Name " -" #__VA_ARGS__ 734 #define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME1(Name, ...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME2(Name, __VA_ARGS__) 735 #define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME(Name, ...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME1(Name, INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))) 736 #endif 737 738 #define INTERNAL_CATCH_MAKE_TYPE_LIST(types) Catch::TypeList<INTERNAL_CATCH_REMOVE_PARENS(types)> 739 740 #define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(types)\ 741 CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,INTERNAL_CATCH_REMOVE_PARENS(types)) 742 743 // end catch_preprocessor.hpp 744 // start catch_meta.hpp 745 746 747 #include <type_traits> 748 749 namespace Catch { 750 template< typename... > 751 struct TypeList {}; 752 753 template< typename... > 754 struct append; 755 756 template< template<typename...> class L1 757 , typename...E1 758 , template<typename...> class L2 759 , typename...E2 760 > 761 struct append< L1<E1...>, L2<E2...> > { 762 using type = L1<E1..., E2...>; 763 }; 764 765 template< template<typename...> class L1 766 , typename...E1 767 , template<typename...> class L2 768 , typename...E2 769 , typename...Rest 770 > 771 struct append< L1<E1...>, L2<E2...>, Rest...> { 772 using type = typename append< L1<E1..., E2...>, Rest... >::type; 773 }; 774 775 template< template<typename...> class 776 , typename... 777 > 778 struct rewrap; 779 780 template< template<typename...> class Container 781 , template<typename...> class List 782 , typename...elems 783 > 784 struct rewrap<Container, List<elems...>> { 785 using type = TypeList< Container< elems... > >; 786 }; 787 788 template< template<typename...> class Container 789 , template<typename...> class List 790 , class...Elems 791 , typename...Elements> 792 struct rewrap<Container, List<Elems...>, Elements...> { 793 using type = typename append<TypeList<Container<Elems...>>, typename rewrap<Container, Elements...>::type>::type; 794 }; 795 796 template< template<typename...> class...Containers > 797 struct combine { 798 template< typename...Types > 799 struct with_types { 800 template< template <typename...> class Final > 801 struct into { 802 using type = typename append<Final<>, typename rewrap<Containers, Types...>::type...>::type; 803 }; 804 }; 805 }; 806 807 template<typename T> 808 struct always_false : std::false_type {}; 809 810 } // namespace Catch 811 812 // end catch_meta.hpp 813 namespace Catch { 814 815 template<typename C> 816 class TestInvokerAsMethod : public ITestInvoker { 817 void (C::*m_testAsMethod)(); 818 public: 819 TestInvokerAsMethod( void (C::*testAsMethod)() ) noexcept : m_testAsMethod( testAsMethod ) {} 820 821 void invoke() const override { 822 C obj; 823 (obj.*m_testAsMethod)(); 824 } 825 }; 826 827 auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker*; 828 829 template<typename C> 830 auto makeTestInvoker( void (C::*testAsMethod)() ) noexcept -> ITestInvoker* { 831 return new(std::nothrow) TestInvokerAsMethod<C>( testAsMethod ); 832 } 833 834 struct NameAndTags { 835 NameAndTags( StringRef const& name_ = StringRef(), StringRef const& tags_ = StringRef() ) noexcept; 836 StringRef name; 837 StringRef tags; 838 }; 839 840 struct AutoReg : NonCopyable { 841 AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept; 842 ~AutoReg(); 843 }; 844 845 } // end namespace Catch 846 847 #if defined(CATCH_CONFIG_DISABLE) 848 #define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \ 849 static void TestName() 850 #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \ 851 namespace{ \ 852 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \ 853 void test(); \ 854 }; \ 855 } \ 856 void TestName::test() 857 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION( TestName, ... ) \ 858 template<typename TestType> \ 859 static void TestName() 860 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \ 861 namespace{ \ 862 template<typename TestType> \ 863 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \ 864 void test(); \ 865 }; \ 866 } \ 867 template<typename TestType> \ 868 void TestName::test() 869 #endif 870 871 /////////////////////////////////////////////////////////////////////////////// 872 #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ 873 static void TestName(); \ 874 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 875 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \ 876 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ 877 static void TestName() 878 #define INTERNAL_CATCH_TESTCASE( ... ) \ 879 INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ ) 880 881 /////////////////////////////////////////////////////////////////////////////// 882 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ 883 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 884 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &QualifiedMethod ), CATCH_INTERNAL_LINEINFO, "&" #QualifiedMethod, Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \ 885 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS 886 887 /////////////////////////////////////////////////////////////////////////////// 888 #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ 889 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 890 namespace{ \ 891 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \ 892 void test(); \ 893 }; \ 894 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ 895 } \ 896 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ 897 void TestName::test() 898 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \ 899 INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ ) 900 901 /////////////////////////////////////////////////////////////////////////////// 902 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ 903 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 904 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ 905 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS 906 907 /////////////////////////////////////////////////////////////////////////////// 908 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_2(TestName, TestFunc, Name, Tags, ... )\ 909 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 910 template<typename TestType> \ 911 static void TestFunc();\ 912 namespace {\ 913 template<typename...Types> \ 914 struct TestName{\ 915 template<typename...Ts> \ 916 TestName(Ts...names){\ 917 CATCH_INTERNAL_CHECK_UNIQUE_TYPES(CATCH_REC_LIST(INTERNAL_CATCH_REMOVE_PARENS, __VA_ARGS__)) \ 918 using expander = int[];\ 919 (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFunc<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ names, Tags } ), 0)... };/* NOLINT */ \ 920 }\ 921 };\ 922 INTERNAL_CATCH_TEMPLATE_REGISTRY_INITIATE(TestName, Name, __VA_ARGS__) \ 923 }\ 924 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ 925 template<typename TestType> \ 926 static void TestFunc() 927 928 #if defined(CATCH_CPP17_OR_GREATER) 929 #define CATCH_INTERNAL_CHECK_UNIQUE_TYPES(...) static_assert(Catch::is_unique<__VA_ARGS__>,"Duplicate type detected in declaration of template test case"); 930 #else 931 #define CATCH_INTERNAL_CHECK_UNIQUE_TYPES(...) static_assert(Catch::is_unique<__VA_ARGS__>::value,"Duplicate type detected in declaration of template test case"); 932 #endif 933 934 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 935 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \ 936 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, __VA_ARGS__ ) 937 #else 938 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \ 939 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, __VA_ARGS__ ) ) 940 #endif 941 942 #define INTERNAL_CATCH_TEMPLATE_REGISTRY_INITIATE(TestName, Name, ...)\ 943 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ 944 TestName<CATCH_REC_LIST(INTERNAL_CATCH_REMOVE_PARENS, __VA_ARGS__)>(CATCH_REC_LIST_UD(INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME,Name, __VA_ARGS__));\ 945 return 0;\ 946 }(); 947 948 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(TestName, TestFuncName, Name, Tags, TmplTypes, TypesList) \ 949 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 950 template<typename TestType> static void TestFuncName(); \ 951 namespace { \ 952 template<typename... Types> \ 953 struct TestName { \ 954 TestName() { \ 955 CATCH_INTERNAL_CHECK_UNIQUE_TYPES(Types...) \ 956 int index = 0; \ 957 using expander = int[]; \ 958 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\ 959 constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\ 960 constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\ 961 (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 */\ 962 } \ 963 }; \ 964 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \ 965 using TestInit = Catch::combine<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)> \ 966 ::with_types<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(TypesList)>::into<TestName>::type; \ 967 TestInit(); \ 968 return 0; \ 969 }(); \ 970 } \ 971 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ 972 template<typename TestType> \ 973 static void TestFuncName() 974 975 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 976 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\ 977 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,__VA_ARGS__) 978 #else 979 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\ 980 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, __VA_ARGS__ ) ) 981 #endif 982 983 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, ... ) \ 984 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 985 namespace{ \ 986 template<typename TestType> \ 987 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \ 988 void test();\ 989 };\ 990 template<typename...Types> \ 991 struct TestNameClass{\ 992 template<typename...Ts> \ 993 TestNameClass(Ts...names){\ 994 CATCH_INTERNAL_CHECK_UNIQUE_TYPES(CATCH_REC_LIST(INTERNAL_CATCH_REMOVE_PARENS, __VA_ARGS__)) \ 995 using expander = int[];\ 996 (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ names, Tags } ), 0)... };/* NOLINT */ \ 997 }\ 998 };\ 999 INTERNAL_CATCH_TEMPLATE_REGISTRY_INITIATE(TestNameClass, Name, __VA_ARGS__)\ 1000 }\ 1001 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS\ 1002 template<typename TestType> \ 1003 void TestName<TestType>::test() 1004 1005 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1006 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \ 1007 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, __VA_ARGS__ ) 1008 #else 1009 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \ 1010 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, __VA_ARGS__ ) ) 1011 #endif 1012 1013 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2(TestNameClass, TestName, ClassName, Name, Tags, TmplTypes, TypesList)\ 1014 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1015 template<typename TestType> \ 1016 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \ 1017 void test();\ 1018 };\ 1019 namespace {\ 1020 template<typename...Types>\ 1021 struct TestNameClass{\ 1022 TestNameClass(){\ 1023 CATCH_INTERNAL_CHECK_UNIQUE_TYPES(Types...)\ 1024 int index = 0;\ 1025 using expander = int[];\ 1026 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\ 1027 constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\ 1028 constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\ 1029 (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 */ \ 1030 }\ 1031 };\ 1032 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ 1033 using TestInit = Catch::combine<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>\ 1034 ::with_types<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(TypesList)>::into<TestNameClass>::type;\ 1035 TestInit();\ 1036 return 0;\ 1037 }(); \ 1038 }\ 1039 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ 1040 template<typename TestType> \ 1041 void TestName<TestType>::test() 1042 1043 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1044 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\ 1045 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, __VA_ARGS__ ) 1046 #else 1047 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\ 1048 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, __VA_ARGS__ ) ) 1049 #endif 1050 1051 // end catch_test_registry.h 1052 // start catch_capture.hpp 1053 1054 // start catch_assertionhandler.h 1055 1056 // start catch_assertioninfo.h 1057 1058 // start catch_result_type.h 1059 1060 namespace Catch { 1061 1062 // ResultWas::OfType enum 1063 struct ResultWas { enum OfType { 1064 Unknown = -1, 1065 Ok = 0, 1066 Info = 1, 1067 Warning = 2, 1068 1069 FailureBit = 0x10, 1070 1071 ExpressionFailed = FailureBit | 1, 1072 ExplicitFailure = FailureBit | 2, 1073 1074 Exception = 0x100 | FailureBit, 1075 1076 ThrewException = Exception | 1, 1077 DidntThrowException = Exception | 2, 1078 1079 FatalErrorCondition = 0x200 | FailureBit 1080 1081 }; }; 1082 1083 bool isOk( ResultWas::OfType resultType ); 1084 bool isJustInfo( int flags ); 1085 1086 // ResultDisposition::Flags enum 1087 struct ResultDisposition { enum Flags { 1088 Normal = 0x01, 1089 1090 ContinueOnFailure = 0x02, // Failures fail test, but execution continues 1091 FalseTest = 0x04, // Prefix expression with ! 1092 SuppressFail = 0x08 // Failures are reported but do not fail the test 1093 }; }; 1094 1095 ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ); 1096 1097 bool shouldContinueOnFailure( int flags ); 1098 inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; } 1099 bool shouldSuppressFailure( int flags ); 1100 1101 } // end namespace Catch 1102 1103 // end catch_result_type.h 1104 namespace Catch { 1105 1106 struct AssertionInfo 1107 { 1108 StringRef macroName; 1109 SourceLineInfo lineInfo; 1110 StringRef capturedExpression; 1111 ResultDisposition::Flags resultDisposition; 1112 1113 // We want to delete this constructor but a compiler bug in 4.8 means 1114 // the struct is then treated as non-aggregate 1115 //AssertionInfo() = delete; 1116 }; 1117 1118 } // end namespace Catch 1119 1120 // end catch_assertioninfo.h 1121 // start catch_decomposer.h 1122 1123 // start catch_tostring.h 1124 1125 #include <vector> 1126 #include <cstddef> 1127 #include <type_traits> 1128 #include <string> 1129 // start catch_stream.h 1130 1131 #include <iosfwd> 1132 #include <cstddef> 1133 #include <ostream> 1134 1135 namespace Catch { 1136 1137 std::ostream& cout(); 1138 std::ostream& cerr(); 1139 std::ostream& clog(); 1140 1141 class StringRef; 1142 1143 struct IStream { 1144 virtual ~IStream(); 1145 virtual std::ostream& stream() const = 0; 1146 }; 1147 1148 auto makeStream( StringRef const &filename ) -> IStream const*; 1149 1150 class ReusableStringStream { 1151 std::size_t m_index; 1152 std::ostream* m_oss; 1153 public: 1154 ReusableStringStream(); 1155 ~ReusableStringStream(); 1156 1157 auto str() const -> std::string; 1158 1159 template<typename T> 1160 auto operator << ( T const& value ) -> ReusableStringStream& { 1161 *m_oss << value; 1162 return *this; 1163 } 1164 auto get() -> std::ostream& { return *m_oss; } 1165 }; 1166 } 1167 1168 // end catch_stream.h 1169 1170 #ifdef CATCH_CONFIG_CPP17_STRING_VIEW 1171 #include <string_view> 1172 #endif 1173 1174 #ifdef __OBJC__ 1175 // start catch_objc_arc.hpp 1176 1177 #import <Foundation/Foundation.h> 1178 1179 #ifdef __has_feature 1180 #define CATCH_ARC_ENABLED __has_feature(objc_arc) 1181 #else 1182 #define CATCH_ARC_ENABLED 0 1183 #endif 1184 1185 void arcSafeRelease( NSObject* obj ); 1186 id performOptionalSelector( id obj, SEL sel ); 1187 1188 #if !CATCH_ARC_ENABLED 1189 inline void arcSafeRelease( NSObject* obj ) { 1190 [obj release]; 1191 } 1192 inline id performOptionalSelector( id obj, SEL sel ) { 1193 if( [obj respondsToSelector: sel] ) 1194 return [obj performSelector: sel]; 1195 return nil; 1196 } 1197 #define CATCH_UNSAFE_UNRETAINED 1198 #define CATCH_ARC_STRONG 1199 #else 1200 inline void arcSafeRelease( NSObject* ){} 1201 inline id performOptionalSelector( id obj, SEL sel ) { 1202 #ifdef __clang__ 1203 #pragma clang diagnostic push 1204 #pragma clang diagnostic ignored "-Warc-performSelector-leaks" 1205 #endif 1206 if( [obj respondsToSelector: sel] ) 1207 return [obj performSelector: sel]; 1208 #ifdef __clang__ 1209 #pragma clang diagnostic pop 1210 #endif 1211 return nil; 1212 } 1213 #define CATCH_UNSAFE_UNRETAINED __unsafe_unretained 1214 #define CATCH_ARC_STRONG __strong 1215 #endif 1216 1217 // end catch_objc_arc.hpp 1218 #endif 1219 1220 #ifdef _MSC_VER 1221 #pragma warning(push) 1222 #pragma warning(disable:4180) // We attempt to stream a function (address) by const&, which MSVC complains about but is harmless 1223 #endif 1224 1225 namespace Catch { 1226 namespace Detail { 1227 1228 extern const std::string unprintableString; 1229 1230 std::string rawMemoryToString( const void *object, std::size_t size ); 1231 1232 template<typename T> 1233 std::string rawMemoryToString( const T& object ) { 1234 return rawMemoryToString( &object, sizeof(object) ); 1235 } 1236 1237 template<typename T> 1238 class IsStreamInsertable { 1239 template<typename SS, typename TT> 1240 static auto test(int) 1241 -> decltype(std::declval<SS&>() << std::declval<TT>(), std::true_type()); 1242 1243 template<typename, typename> 1244 static auto test(...)->std::false_type; 1245 1246 public: 1247 static const bool value = decltype(test<std::ostream, const T&>(0))::value; 1248 }; 1249 1250 template<typename E> 1251 std::string convertUnknownEnumToString( E e ); 1252 1253 template<typename T> 1254 typename std::enable_if< 1255 !std::is_enum<T>::value && !std::is_base_of<std::exception, T>::value, 1256 std::string>::type convertUnstreamable( T const& ) { 1257 return Detail::unprintableString; 1258 } 1259 template<typename T> 1260 typename std::enable_if< 1261 !std::is_enum<T>::value && std::is_base_of<std::exception, T>::value, 1262 std::string>::type convertUnstreamable(T const& ex) { 1263 return ex.what(); 1264 } 1265 1266 template<typename T> 1267 typename std::enable_if< 1268 std::is_enum<T>::value 1269 , std::string>::type convertUnstreamable( T const& value ) { 1270 return convertUnknownEnumToString( value ); 1271 } 1272 1273 #if defined(_MANAGED) 1274 //! Convert a CLR string to a utf8 std::string 1275 template<typename T> 1276 std::string clrReferenceToString( T^ ref ) { 1277 if (ref == nullptr) 1278 return std::string("null"); 1279 auto bytes = System::Text::Encoding::UTF8->GetBytes(ref->ToString()); 1280 cli::pin_ptr<System::Byte> p = &bytes[0]; 1281 return std::string(reinterpret_cast<char const *>(p), bytes->Length); 1282 } 1283 #endif 1284 1285 } // namespace Detail 1286 1287 // If we decide for C++14, change these to enable_if_ts 1288 template <typename T, typename = void> 1289 struct StringMaker { 1290 template <typename Fake = T> 1291 static 1292 typename std::enable_if<::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type 1293 convert(const Fake& value) { 1294 ReusableStringStream rss; 1295 // NB: call using the function-like syntax to avoid ambiguity with 1296 // user-defined templated operator<< under clang. 1297 rss.operator<<(value); 1298 return rss.str(); 1299 } 1300 1301 template <typename Fake = T> 1302 static 1303 typename std::enable_if<!::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type 1304 convert( const Fake& value ) { 1305 #if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER) 1306 return Detail::convertUnstreamable(value); 1307 #else 1308 return CATCH_CONFIG_FALLBACK_STRINGIFIER(value); 1309 #endif 1310 } 1311 }; 1312 1313 namespace Detail { 1314 1315 // This function dispatches all stringification requests inside of Catch. 1316 // Should be preferably called fully qualified, like ::Catch::Detail::stringify 1317 template <typename T> 1318 std::string stringify(const T& e) { 1319 return ::Catch::StringMaker<typename std::remove_cv<typename std::remove_reference<T>::type>::type>::convert(e); 1320 } 1321 1322 template<typename E> 1323 std::string convertUnknownEnumToString( E e ) { 1324 return ::Catch::Detail::stringify(static_cast<typename std::underlying_type<E>::type>(e)); 1325 } 1326 1327 #if defined(_MANAGED) 1328 template <typename T> 1329 std::string stringify( T^ e ) { 1330 return ::Catch::StringMaker<T^>::convert(e); 1331 } 1332 #endif 1333 1334 } // namespace Detail 1335 1336 // Some predefined specializations 1337 1338 template<> 1339 struct StringMaker<std::string> { 1340 static std::string convert(const std::string& str); 1341 }; 1342 1343 #ifdef CATCH_CONFIG_CPP17_STRING_VIEW 1344 template<> 1345 struct StringMaker<std::string_view> { 1346 static std::string convert(std::string_view str); 1347 }; 1348 #endif 1349 1350 template<> 1351 struct StringMaker<char const *> { 1352 static std::string convert(char const * str); 1353 }; 1354 template<> 1355 struct StringMaker<char *> { 1356 static std::string convert(char * str); 1357 }; 1358 1359 #ifdef CATCH_CONFIG_WCHAR 1360 template<> 1361 struct StringMaker<std::wstring> { 1362 static std::string convert(const std::wstring& wstr); 1363 }; 1364 1365 # ifdef CATCH_CONFIG_CPP17_STRING_VIEW 1366 template<> 1367 struct StringMaker<std::wstring_view> { 1368 static std::string convert(std::wstring_view str); 1369 }; 1370 # endif 1371 1372 template<> 1373 struct StringMaker<wchar_t const *> { 1374 static std::string convert(wchar_t const * str); 1375 }; 1376 template<> 1377 struct StringMaker<wchar_t *> { 1378 static std::string convert(wchar_t * str); 1379 }; 1380 #endif 1381 1382 // TBD: Should we use `strnlen` to ensure that we don't go out of the buffer, 1383 // while keeping string semantics? 1384 template<int SZ> 1385 struct StringMaker<char[SZ]> { 1386 static std::string convert(char const* str) { 1387 return ::Catch::Detail::stringify(std::string{ str }); 1388 } 1389 }; 1390 template<int SZ> 1391 struct StringMaker<signed char[SZ]> { 1392 static std::string convert(signed char const* str) { 1393 return ::Catch::Detail::stringify(std::string{ reinterpret_cast<char const *>(str) }); 1394 } 1395 }; 1396 template<int SZ> 1397 struct StringMaker<unsigned char[SZ]> { 1398 static std::string convert(unsigned char const* str) { 1399 return ::Catch::Detail::stringify(std::string{ reinterpret_cast<char const *>(str) }); 1400 } 1401 }; 1402 1403 template<> 1404 struct StringMaker<int> { 1405 static std::string convert(int value); 1406 }; 1407 template<> 1408 struct StringMaker<long> { 1409 static std::string convert(long value); 1410 }; 1411 template<> 1412 struct StringMaker<long long> { 1413 static std::string convert(long long value); 1414 }; 1415 template<> 1416 struct StringMaker<unsigned int> { 1417 static std::string convert(unsigned int value); 1418 }; 1419 template<> 1420 struct StringMaker<unsigned long> { 1421 static std::string convert(unsigned long value); 1422 }; 1423 template<> 1424 struct StringMaker<unsigned long long> { 1425 static std::string convert(unsigned long long value); 1426 }; 1427 1428 template<> 1429 struct StringMaker<bool> { 1430 static std::string convert(bool b); 1431 }; 1432 1433 template<> 1434 struct StringMaker<char> { 1435 static std::string convert(char c); 1436 }; 1437 template<> 1438 struct StringMaker<signed char> { 1439 static std::string convert(signed char c); 1440 }; 1441 template<> 1442 struct StringMaker<unsigned char> { 1443 static std::string convert(unsigned char c); 1444 }; 1445 1446 template<> 1447 struct StringMaker<std::nullptr_t> { 1448 static std::string convert(std::nullptr_t); 1449 }; 1450 1451 template<> 1452 struct StringMaker<float> { 1453 static std::string convert(float value); 1454 }; 1455 template<> 1456 struct StringMaker<double> { 1457 static std::string convert(double value); 1458 }; 1459 1460 template <typename T> 1461 struct StringMaker<T*> { 1462 template <typename U> 1463 static std::string convert(U* p) { 1464 if (p) { 1465 return ::Catch::Detail::rawMemoryToString(p); 1466 } else { 1467 return "nullptr"; 1468 } 1469 } 1470 }; 1471 1472 template <typename R, typename C> 1473 struct StringMaker<R C::*> { 1474 static std::string convert(R C::* p) { 1475 if (p) { 1476 return ::Catch::Detail::rawMemoryToString(p); 1477 } else { 1478 return "nullptr"; 1479 } 1480 } 1481 }; 1482 1483 #if defined(_MANAGED) 1484 template <typename T> 1485 struct StringMaker<T^> { 1486 static std::string convert( T^ ref ) { 1487 return ::Catch::Detail::clrReferenceToString(ref); 1488 } 1489 }; 1490 #endif 1491 1492 namespace Detail { 1493 template<typename InputIterator> 1494 std::string rangeToString(InputIterator first, InputIterator last) { 1495 ReusableStringStream rss; 1496 rss << "{ "; 1497 if (first != last) { 1498 rss << ::Catch::Detail::stringify(*first); 1499 for (++first; first != last; ++first) 1500 rss << ", " << ::Catch::Detail::stringify(*first); 1501 } 1502 rss << " }"; 1503 return rss.str(); 1504 } 1505 } 1506 1507 #ifdef __OBJC__ 1508 template<> 1509 struct StringMaker<NSString*> { 1510 static std::string convert(NSString * nsstring) { 1511 if (!nsstring) 1512 return "nil"; 1513 return std::string("@") + [nsstring UTF8String]; 1514 } 1515 }; 1516 template<> 1517 struct StringMaker<NSObject*> { 1518 static std::string convert(NSObject* nsObject) { 1519 return ::Catch::Detail::stringify([nsObject description]); 1520 } 1521 1522 }; 1523 namespace Detail { 1524 inline std::string stringify( NSString* nsstring ) { 1525 return StringMaker<NSString*>::convert( nsstring ); 1526 } 1527 1528 } // namespace Detail 1529 #endif // __OBJC__ 1530 1531 } // namespace Catch 1532 1533 ////////////////////////////////////////////////////// 1534 // Separate std-lib types stringification, so it can be selectively enabled 1535 // This means that we do not bring in 1536 1537 #if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS) 1538 # define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER 1539 # define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER 1540 # define CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER 1541 # define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER 1542 # define CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER 1543 #endif 1544 1545 // Separate std::pair specialization 1546 #if defined(CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER) 1547 #include <utility> 1548 namespace Catch { 1549 template<typename T1, typename T2> 1550 struct StringMaker<std::pair<T1, T2> > { 1551 static std::string convert(const std::pair<T1, T2>& pair) { 1552 ReusableStringStream rss; 1553 rss << "{ " 1554 << ::Catch::Detail::stringify(pair.first) 1555 << ", " 1556 << ::Catch::Detail::stringify(pair.second) 1557 << " }"; 1558 return rss.str(); 1559 } 1560 }; 1561 } 1562 #endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER 1563 1564 #if defined(CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_OPTIONAL) 1565 #include <optional> 1566 namespace Catch { 1567 template<typename T> 1568 struct StringMaker<std::optional<T> > { 1569 static std::string convert(const std::optional<T>& optional) { 1570 ReusableStringStream rss; 1571 if (optional.has_value()) { 1572 rss << ::Catch::Detail::stringify(*optional); 1573 } else { 1574 rss << "{ }"; 1575 } 1576 return rss.str(); 1577 } 1578 }; 1579 } 1580 #endif // CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER 1581 1582 // Separate std::tuple specialization 1583 #if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER) 1584 #include <tuple> 1585 namespace Catch { 1586 namespace Detail { 1587 template< 1588 typename Tuple, 1589 std::size_t N = 0, 1590 bool = (N < std::tuple_size<Tuple>::value) 1591 > 1592 struct TupleElementPrinter { 1593 static void print(const Tuple& tuple, std::ostream& os) { 1594 os << (N ? ", " : " ") 1595 << ::Catch::Detail::stringify(std::get<N>(tuple)); 1596 TupleElementPrinter<Tuple, N + 1>::print(tuple, os); 1597 } 1598 }; 1599 1600 template< 1601 typename Tuple, 1602 std::size_t N 1603 > 1604 struct TupleElementPrinter<Tuple, N, false> { 1605 static void print(const Tuple&, std::ostream&) {} 1606 }; 1607 1608 } 1609 1610 template<typename ...Types> 1611 struct StringMaker<std::tuple<Types...>> { 1612 static std::string convert(const std::tuple<Types...>& tuple) { 1613 ReusableStringStream rss; 1614 rss << '{'; 1615 Detail::TupleElementPrinter<std::tuple<Types...>>::print(tuple, rss.get()); 1616 rss << " }"; 1617 return rss.str(); 1618 } 1619 }; 1620 } 1621 #endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER 1622 1623 #if defined(CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_VARIANT) 1624 #include <variant> 1625 namespace Catch { 1626 template<> 1627 struct StringMaker<std::monostate> { 1628 static std::string convert(const std::monostate&) { 1629 return "{ }"; 1630 } 1631 }; 1632 1633 template<typename... Elements> 1634 struct StringMaker<std::variant<Elements...>> { 1635 static std::string convert(const std::variant<Elements...>& variant) { 1636 if (variant.valueless_by_exception()) { 1637 return "{valueless variant}"; 1638 } else { 1639 return std::visit( 1640 [](const auto& value) { 1641 return ::Catch::Detail::stringify(value); 1642 }, 1643 variant 1644 ); 1645 } 1646 } 1647 }; 1648 } 1649 #endif // CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER 1650 1651 namespace Catch { 1652 struct not_this_one {}; // Tag type for detecting which begin/ end are being selected 1653 1654 // Import begin/ end from std here so they are considered alongside the fallback (...) overloads in this namespace 1655 using std::begin; 1656 using std::end; 1657 1658 not_this_one begin( ... ); 1659 not_this_one end( ... ); 1660 1661 template <typename T> 1662 struct is_range { 1663 static const bool value = 1664 !std::is_same<decltype(begin(std::declval<T>())), not_this_one>::value && 1665 !std::is_same<decltype(end(std::declval<T>())), not_this_one>::value; 1666 }; 1667 1668 #if defined(_MANAGED) // Managed types are never ranges 1669 template <typename T> 1670 struct is_range<T^> { 1671 static const bool value = false; 1672 }; 1673 #endif 1674 1675 template<typename Range> 1676 std::string rangeToString( Range const& range ) { 1677 return ::Catch::Detail::rangeToString( begin( range ), end( range ) ); 1678 } 1679 1680 // Handle vector<bool> specially 1681 template<typename Allocator> 1682 std::string rangeToString( std::vector<bool, Allocator> const& v ) { 1683 ReusableStringStream rss; 1684 rss << "{ "; 1685 bool first = true; 1686 for( bool b : v ) { 1687 if( first ) 1688 first = false; 1689 else 1690 rss << ", "; 1691 rss << ::Catch::Detail::stringify( b ); 1692 } 1693 rss << " }"; 1694 return rss.str(); 1695 } 1696 1697 template<typename R> 1698 struct StringMaker<R, typename std::enable_if<is_range<R>::value && !::Catch::Detail::IsStreamInsertable<R>::value>::type> { 1699 static std::string convert( R const& range ) { 1700 return rangeToString( range ); 1701 } 1702 }; 1703 1704 template <typename T, int SZ> 1705 struct StringMaker<T[SZ]> { 1706 static std::string convert(T const(&arr)[SZ]) { 1707 return rangeToString(arr); 1708 } 1709 }; 1710 1711 } // namespace Catch 1712 1713 // Separate std::chrono::duration specialization 1714 #if defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) 1715 #include <ctime> 1716 #include <ratio> 1717 #include <chrono> 1718 1719 namespace Catch { 1720 1721 template <class Ratio> 1722 struct ratio_string { 1723 static std::string symbol(); 1724 }; 1725 1726 template <class Ratio> 1727 std::string ratio_string<Ratio>::symbol() { 1728 Catch::ReusableStringStream rss; 1729 rss << '[' << Ratio::num << '/' 1730 << Ratio::den << ']'; 1731 return rss.str(); 1732 } 1733 template <> 1734 struct ratio_string<std::atto> { 1735 static std::string symbol(); 1736 }; 1737 template <> 1738 struct ratio_string<std::femto> { 1739 static std::string symbol(); 1740 }; 1741 template <> 1742 struct ratio_string<std::pico> { 1743 static std::string symbol(); 1744 }; 1745 template <> 1746 struct ratio_string<std::nano> { 1747 static std::string symbol(); 1748 }; 1749 template <> 1750 struct ratio_string<std::micro> { 1751 static std::string symbol(); 1752 }; 1753 template <> 1754 struct ratio_string<std::milli> { 1755 static std::string symbol(); 1756 }; 1757 1758 //////////// 1759 // std::chrono::duration specializations 1760 template<typename Value, typename Ratio> 1761 struct StringMaker<std::chrono::duration<Value, Ratio>> { 1762 static std::string convert(std::chrono::duration<Value, Ratio> const& duration) { 1763 ReusableStringStream rss; 1764 rss << duration.count() << ' ' << ratio_string<Ratio>::symbol() << 's'; 1765 return rss.str(); 1766 } 1767 }; 1768 template<typename Value> 1769 struct StringMaker<std::chrono::duration<Value, std::ratio<1>>> { 1770 static std::string convert(std::chrono::duration<Value, std::ratio<1>> const& duration) { 1771 ReusableStringStream rss; 1772 rss << duration.count() << " s"; 1773 return rss.str(); 1774 } 1775 }; 1776 template<typename Value> 1777 struct StringMaker<std::chrono::duration<Value, std::ratio<60>>> { 1778 static std::string convert(std::chrono::duration<Value, std::ratio<60>> const& duration) { 1779 ReusableStringStream rss; 1780 rss << duration.count() << " m"; 1781 return rss.str(); 1782 } 1783 }; 1784 template<typename Value> 1785 struct StringMaker<std::chrono::duration<Value, std::ratio<3600>>> { 1786 static std::string convert(std::chrono::duration<Value, std::ratio<3600>> const& duration) { 1787 ReusableStringStream rss; 1788 rss << duration.count() << " h"; 1789 return rss.str(); 1790 } 1791 }; 1792 1793 //////////// 1794 // std::chrono::time_point specialization 1795 // Generic time_point cannot be specialized, only std::chrono::time_point<system_clock> 1796 template<typename Clock, typename Duration> 1797 struct StringMaker<std::chrono::time_point<Clock, Duration>> { 1798 static std::string convert(std::chrono::time_point<Clock, Duration> const& time_point) { 1799 return ::Catch::Detail::stringify(time_point.time_since_epoch()) + " since epoch"; 1800 } 1801 }; 1802 // std::chrono::time_point<system_clock> specialization 1803 template<typename Duration> 1804 struct StringMaker<std::chrono::time_point<std::chrono::system_clock, Duration>> { 1805 static std::string convert(std::chrono::time_point<std::chrono::system_clock, Duration> const& time_point) { 1806 auto converted = std::chrono::system_clock::to_time_t(time_point); 1807 1808 #ifdef _MSC_VER 1809 std::tm timeInfo = {}; 1810 gmtime_s(&timeInfo, &converted); 1811 #else 1812 std::tm* timeInfo = std::gmtime(&converted); 1813 #endif 1814 1815 auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); 1816 char timeStamp[timeStampSize]; 1817 const char * const fmt = "%Y-%m-%dT%H:%M:%SZ"; 1818 1819 #ifdef _MSC_VER 1820 std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); 1821 #else 1822 std::strftime(timeStamp, timeStampSize, fmt, timeInfo); 1823 #endif 1824 return std::string(timeStamp); 1825 } 1826 }; 1827 } 1828 #endif // CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER 1829 1830 #ifdef _MSC_VER 1831 #pragma warning(pop) 1832 #endif 1833 1834 // end catch_tostring.h 1835 #include <iosfwd> 1836 1837 #ifdef _MSC_VER 1838 #pragma warning(push) 1839 #pragma warning(disable:4389) // '==' : signed/unsigned mismatch 1840 #pragma warning(disable:4018) // more "signed/unsigned mismatch" 1841 #pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform) 1842 #pragma warning(disable:4180) // qualifier applied to function type has no meaning 1843 #pragma warning(disable:4800) // Forcing result to true or false 1844 #endif 1845 1846 namespace Catch { 1847 1848 struct ITransientExpression { 1849 auto isBinaryExpression() const -> bool { return m_isBinaryExpression; } 1850 auto getResult() const -> bool { return m_result; } 1851 virtual void streamReconstructedExpression( std::ostream &os ) const = 0; 1852 1853 ITransientExpression( bool isBinaryExpression, bool result ) 1854 : m_isBinaryExpression( isBinaryExpression ), 1855 m_result( result ) 1856 {} 1857 1858 // We don't actually need a virtual destructor, but many static analysers 1859 // complain if it's not here :-( 1860 virtual ~ITransientExpression(); 1861 1862 bool m_isBinaryExpression; 1863 bool m_result; 1864 1865 }; 1866 1867 void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ); 1868 1869 template<typename LhsT, typename RhsT> 1870 class BinaryExpr : public ITransientExpression { 1871 LhsT m_lhs; 1872 StringRef m_op; 1873 RhsT m_rhs; 1874 1875 void streamReconstructedExpression( std::ostream &os ) const override { 1876 formatReconstructedExpression 1877 ( os, Catch::Detail::stringify( m_lhs ), m_op, Catch::Detail::stringify( m_rhs ) ); 1878 } 1879 1880 public: 1881 BinaryExpr( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs ) 1882 : ITransientExpression{ true, comparisonResult }, 1883 m_lhs( lhs ), 1884 m_op( op ), 1885 m_rhs( rhs ) 1886 {} 1887 1888 template<typename T> 1889 auto operator && ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 1890 static_assert(always_false<T>::value, 1891 "chained comparisons are not supported inside assertions, " 1892 "wrap the expression inside parentheses, or decompose it"); 1893 } 1894 1895 template<typename T> 1896 auto operator || ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 1897 static_assert(always_false<T>::value, 1898 "chained comparisons are not supported inside assertions, " 1899 "wrap the expression inside parentheses, or decompose it"); 1900 } 1901 1902 template<typename T> 1903 auto operator == ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 1904 static_assert(always_false<T>::value, 1905 "chained comparisons are not supported inside assertions, " 1906 "wrap the expression inside parentheses, or decompose it"); 1907 } 1908 1909 template<typename T> 1910 auto operator != ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 1911 static_assert(always_false<T>::value, 1912 "chained comparisons are not supported inside assertions, " 1913 "wrap the expression inside parentheses, or decompose it"); 1914 } 1915 1916 template<typename T> 1917 auto operator > ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 1918 static_assert(always_false<T>::value, 1919 "chained comparisons are not supported inside assertions, " 1920 "wrap the expression inside parentheses, or decompose it"); 1921 } 1922 1923 template<typename T> 1924 auto operator < ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 1925 static_assert(always_false<T>::value, 1926 "chained comparisons are not supported inside assertions, " 1927 "wrap the expression inside parentheses, or decompose it"); 1928 } 1929 1930 template<typename T> 1931 auto operator >= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 1932 static_assert(always_false<T>::value, 1933 "chained comparisons are not supported inside assertions, " 1934 "wrap the expression inside parentheses, or decompose it"); 1935 } 1936 1937 template<typename T> 1938 auto operator <= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 1939 static_assert(always_false<T>::value, 1940 "chained comparisons are not supported inside assertions, " 1941 "wrap the expression inside parentheses, or decompose it"); 1942 } 1943 }; 1944 1945 template<typename LhsT> 1946 class UnaryExpr : public ITransientExpression { 1947 LhsT m_lhs; 1948 1949 void streamReconstructedExpression( std::ostream &os ) const override { 1950 os << Catch::Detail::stringify( m_lhs ); 1951 } 1952 1953 public: 1954 explicit UnaryExpr( LhsT lhs ) 1955 : ITransientExpression{ false, static_cast<bool>(lhs) }, 1956 m_lhs( lhs ) 1957 {} 1958 }; 1959 1960 // Specialised comparison functions to handle equality comparisons between ints and pointers (NULL deduces as an int) 1961 template<typename LhsT, typename RhsT> 1962 auto compareEqual( LhsT const& lhs, RhsT const& rhs ) -> bool { return static_cast<bool>(lhs == rhs); } 1963 template<typename T> 1964 auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); } 1965 template<typename T> 1966 auto compareEqual( T* const& lhs, long rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); } 1967 template<typename T> 1968 auto compareEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; } 1969 template<typename T> 1970 auto compareEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; } 1971 1972 template<typename LhsT, typename RhsT> 1973 auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return static_cast<bool>(lhs != rhs); } 1974 template<typename T> 1975 auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); } 1976 template<typename T> 1977 auto compareNotEqual( T* const& lhs, long rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); } 1978 template<typename T> 1979 auto compareNotEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) != rhs; } 1980 template<typename T> 1981 auto compareNotEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) != rhs; } 1982 1983 template<typename LhsT> 1984 class ExprLhs { 1985 LhsT m_lhs; 1986 public: 1987 explicit ExprLhs( LhsT lhs ) : m_lhs( lhs ) {} 1988 1989 template<typename RhsT> 1990 auto operator == ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const { 1991 return { compareEqual( m_lhs, rhs ), m_lhs, "==", rhs }; 1992 } 1993 auto operator == ( bool rhs ) -> BinaryExpr<LhsT, bool> const { 1994 return { m_lhs == rhs, m_lhs, "==", rhs }; 1995 } 1996 1997 template<typename RhsT> 1998 auto operator != ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const { 1999 return { compareNotEqual( m_lhs, rhs ), m_lhs, "!=", rhs }; 2000 } 2001 auto operator != ( bool rhs ) -> BinaryExpr<LhsT, bool> const { 2002 return { m_lhs != rhs, m_lhs, "!=", rhs }; 2003 } 2004 2005 template<typename RhsT> 2006 auto operator > ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const { 2007 return { static_cast<bool>(m_lhs > rhs), m_lhs, ">", rhs }; 2008 } 2009 template<typename RhsT> 2010 auto operator < ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const { 2011 return { static_cast<bool>(m_lhs < rhs), m_lhs, "<", rhs }; 2012 } 2013 template<typename RhsT> 2014 auto operator >= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const { 2015 return { static_cast<bool>(m_lhs >= rhs), m_lhs, ">=", rhs }; 2016 } 2017 template<typename RhsT> 2018 auto operator <= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const { 2019 return { static_cast<bool>(m_lhs <= rhs), m_lhs, "<=", rhs }; 2020 } 2021 2022 template<typename RhsT> 2023 auto operator && ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const { 2024 static_assert(always_false<RhsT>::value, 2025 "operator&& is not supported inside assertions, " 2026 "wrap the expression inside parentheses, or decompose it"); 2027 } 2028 2029 template<typename RhsT> 2030 auto operator || ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const { 2031 static_assert(always_false<RhsT>::value, 2032 "operator|| is not supported inside assertions, " 2033 "wrap the expression inside parentheses, or decompose it"); 2034 } 2035 2036 auto makeUnaryExpr() const -> UnaryExpr<LhsT> { 2037 return UnaryExpr<LhsT>{ m_lhs }; 2038 } 2039 }; 2040 2041 void handleExpression( ITransientExpression const& expr ); 2042 2043 template<typename T> 2044 void handleExpression( ExprLhs<T> const& expr ) { 2045 handleExpression( expr.makeUnaryExpr() ); 2046 } 2047 2048 struct Decomposer { 2049 template<typename T> 2050 auto operator <= ( T const& lhs ) -> ExprLhs<T const&> { 2051 return ExprLhs<T const&>{ lhs }; 2052 } 2053 2054 auto operator <=( bool value ) -> ExprLhs<bool> { 2055 return ExprLhs<bool>{ value }; 2056 } 2057 }; 2058 2059 } // end namespace Catch 2060 2061 #ifdef _MSC_VER 2062 #pragma warning(pop) 2063 #endif 2064 2065 // end catch_decomposer.h 2066 // start catch_interfaces_capture.h 2067 2068 #include <string> 2069 2070 namespace Catch { 2071 2072 class AssertionResult; 2073 struct AssertionInfo; 2074 struct SectionInfo; 2075 struct SectionEndInfo; 2076 struct MessageInfo; 2077 struct MessageBuilder; 2078 struct Counts; 2079 struct BenchmarkInfo; 2080 struct BenchmarkStats; 2081 struct AssertionReaction; 2082 struct SourceLineInfo; 2083 2084 struct ITransientExpression; 2085 struct IGeneratorTracker; 2086 2087 struct IResultCapture { 2088 2089 virtual ~IResultCapture(); 2090 2091 virtual bool sectionStarted( SectionInfo const& sectionInfo, 2092 Counts& assertions ) = 0; 2093 virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; 2094 virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; 2095 2096 virtual auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& = 0; 2097 2098 virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0; 2099 virtual void benchmarkEnded( BenchmarkStats const& stats ) = 0; 2100 2101 virtual void pushScopedMessage( MessageInfo const& message ) = 0; 2102 virtual void popScopedMessage( MessageInfo const& message ) = 0; 2103 2104 virtual void emplaceUnscopedMessage( MessageBuilder const& builder ) = 0; 2105 2106 virtual void handleFatalErrorCondition( StringRef message ) = 0; 2107 2108 virtual void handleExpr 2109 ( AssertionInfo const& info, 2110 ITransientExpression const& expr, 2111 AssertionReaction& reaction ) = 0; 2112 virtual void handleMessage 2113 ( AssertionInfo const& info, 2114 ResultWas::OfType resultType, 2115 StringRef const& message, 2116 AssertionReaction& reaction ) = 0; 2117 virtual void handleUnexpectedExceptionNotThrown 2118 ( AssertionInfo const& info, 2119 AssertionReaction& reaction ) = 0; 2120 virtual void handleUnexpectedInflightException 2121 ( AssertionInfo const& info, 2122 std::string const& message, 2123 AssertionReaction& reaction ) = 0; 2124 virtual void handleIncomplete 2125 ( AssertionInfo const& info ) = 0; 2126 virtual void handleNonExpr 2127 ( AssertionInfo const &info, 2128 ResultWas::OfType resultType, 2129 AssertionReaction &reaction ) = 0; 2130 2131 virtual bool lastAssertionPassed() = 0; 2132 virtual void assertionPassed() = 0; 2133 2134 // Deprecated, do not use: 2135 virtual std::string getCurrentTestName() const = 0; 2136 virtual const AssertionResult* getLastResult() const = 0; 2137 virtual void exceptionEarlyReported() = 0; 2138 }; 2139 2140 IResultCapture& getResultCapture(); 2141 } 2142 2143 // end catch_interfaces_capture.h 2144 namespace Catch { 2145 2146 struct TestFailureException{}; 2147 struct AssertionResultData; 2148 struct IResultCapture; 2149 class RunContext; 2150 2151 class LazyExpression { 2152 friend class AssertionHandler; 2153 friend struct AssertionStats; 2154 friend class RunContext; 2155 2156 ITransientExpression const* m_transientExpression = nullptr; 2157 bool m_isNegated; 2158 public: 2159 LazyExpression( bool isNegated ); 2160 LazyExpression( LazyExpression const& other ); 2161 LazyExpression& operator = ( LazyExpression const& ) = delete; 2162 2163 explicit operator bool() const; 2164 2165 friend auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream&; 2166 }; 2167 2168 struct AssertionReaction { 2169 bool shouldDebugBreak = false; 2170 bool shouldThrow = false; 2171 }; 2172 2173 class AssertionHandler { 2174 AssertionInfo m_assertionInfo; 2175 AssertionReaction m_reaction; 2176 bool m_completed = false; 2177 IResultCapture& m_resultCapture; 2178 2179 public: 2180 AssertionHandler 2181 ( StringRef const& macroName, 2182 SourceLineInfo const& lineInfo, 2183 StringRef capturedExpression, 2184 ResultDisposition::Flags resultDisposition ); 2185 ~AssertionHandler() { 2186 if ( !m_completed ) { 2187 m_resultCapture.handleIncomplete( m_assertionInfo ); 2188 } 2189 } 2190 2191 template<typename T> 2192 void handleExpr( ExprLhs<T> const& expr ) { 2193 handleExpr( expr.makeUnaryExpr() ); 2194 } 2195 void handleExpr( ITransientExpression const& expr ); 2196 2197 void handleMessage(ResultWas::OfType resultType, StringRef const& message); 2198 2199 void handleExceptionThrownAsExpected(); 2200 void handleUnexpectedExceptionNotThrown(); 2201 void handleExceptionNotThrownAsExpected(); 2202 void handleThrowingCallSkipped(); 2203 void handleUnexpectedInflightException(); 2204 2205 void complete(); 2206 void setCompleted(); 2207 2208 // query 2209 auto allowThrows() const -> bool; 2210 }; 2211 2212 void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef const& matcherString ); 2213 2214 } // namespace Catch 2215 2216 // end catch_assertionhandler.h 2217 // start catch_message.h 2218 2219 #include <string> 2220 #include <vector> 2221 2222 namespace Catch { 2223 2224 struct MessageInfo { 2225 MessageInfo( StringRef const& _macroName, 2226 SourceLineInfo const& _lineInfo, 2227 ResultWas::OfType _type ); 2228 2229 StringRef macroName; 2230 std::string message; 2231 SourceLineInfo lineInfo; 2232 ResultWas::OfType type; 2233 unsigned int sequence; 2234 2235 bool operator == ( MessageInfo const& other ) const; 2236 bool operator < ( MessageInfo const& other ) const; 2237 private: 2238 static unsigned int globalCount; 2239 }; 2240 2241 struct MessageStream { 2242 2243 template<typename T> 2244 MessageStream& operator << ( T const& value ) { 2245 m_stream << value; 2246 return *this; 2247 } 2248 2249 ReusableStringStream m_stream; 2250 }; 2251 2252 struct MessageBuilder : MessageStream { 2253 MessageBuilder( StringRef const& macroName, 2254 SourceLineInfo const& lineInfo, 2255 ResultWas::OfType type ); 2256 2257 template<typename T> 2258 MessageBuilder& operator << ( T const& value ) { 2259 m_stream << value; 2260 return *this; 2261 } 2262 2263 MessageInfo m_info; 2264 }; 2265 2266 class ScopedMessage { 2267 public: 2268 explicit ScopedMessage( MessageBuilder const& builder ); 2269 ScopedMessage( ScopedMessage& duplicate ) = delete; 2270 ScopedMessage( ScopedMessage&& old ); 2271 ~ScopedMessage(); 2272 2273 MessageInfo m_info; 2274 bool m_moved; 2275 }; 2276 2277 class Capturer { 2278 std::vector<MessageInfo> m_messages; 2279 IResultCapture& m_resultCapture = getResultCapture(); 2280 size_t m_captured = 0; 2281 public: 2282 Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names ); 2283 ~Capturer(); 2284 2285 void captureValue( size_t index, std::string const& value ); 2286 2287 template<typename T> 2288 void captureValues( size_t index, T const& value ) { 2289 captureValue( index, Catch::Detail::stringify( value ) ); 2290 } 2291 2292 template<typename T, typename... Ts> 2293 void captureValues( size_t index, T const& value, Ts const&... values ) { 2294 captureValue( index, Catch::Detail::stringify(value) ); 2295 captureValues( index+1, values... ); 2296 } 2297 }; 2298 2299 } // end namespace Catch 2300 2301 // end catch_message.h 2302 #if !defined(CATCH_CONFIG_DISABLE) 2303 2304 #if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION) 2305 #define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__ 2306 #else 2307 #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION" 2308 #endif 2309 2310 #if defined(CATCH_CONFIG_FAST_COMPILE) || defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 2311 2312 /////////////////////////////////////////////////////////////////////////////// 2313 // Another way to speed-up compilation is to omit local try-catch for REQUIRE* 2314 // macros. 2315 #define INTERNAL_CATCH_TRY 2316 #define INTERNAL_CATCH_CATCH( capturer ) 2317 2318 #else // CATCH_CONFIG_FAST_COMPILE 2319 2320 #define INTERNAL_CATCH_TRY try 2321 #define INTERNAL_CATCH_CATCH( handler ) catch(...) { handler.handleUnexpectedInflightException(); } 2322 2323 #endif 2324 2325 #define INTERNAL_CATCH_REACT( handler ) handler.complete(); 2326 2327 /////////////////////////////////////////////////////////////////////////////// 2328 #define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \ 2329 do { \ 2330 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ 2331 INTERNAL_CATCH_TRY { \ 2332 CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ 2333 catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); \ 2334 CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ 2335 } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ 2336 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2337 } 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 2338 // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. 2339 2340 /////////////////////////////////////////////////////////////////////////////// 2341 #define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \ 2342 INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \ 2343 if( Catch::getResultCapture().lastAssertionPassed() ) 2344 2345 /////////////////////////////////////////////////////////////////////////////// 2346 #define INTERNAL_CATCH_ELSE( macroName, resultDisposition, ... ) \ 2347 INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \ 2348 if( !Catch::getResultCapture().lastAssertionPassed() ) 2349 2350 /////////////////////////////////////////////////////////////////////////////// 2351 #define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \ 2352 do { \ 2353 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ 2354 try { \ 2355 static_cast<void>(__VA_ARGS__); \ 2356 catchAssertionHandler.handleExceptionNotThrownAsExpected(); \ 2357 } \ 2358 catch( ... ) { \ 2359 catchAssertionHandler.handleUnexpectedInflightException(); \ 2360 } \ 2361 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2362 } while( false ) 2363 2364 /////////////////////////////////////////////////////////////////////////////// 2365 #define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \ 2366 do { \ 2367 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \ 2368 if( catchAssertionHandler.allowThrows() ) \ 2369 try { \ 2370 static_cast<void>(__VA_ARGS__); \ 2371 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 2372 } \ 2373 catch( ... ) { \ 2374 catchAssertionHandler.handleExceptionThrownAsExpected(); \ 2375 } \ 2376 else \ 2377 catchAssertionHandler.handleThrowingCallSkipped(); \ 2378 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2379 } while( false ) 2380 2381 /////////////////////////////////////////////////////////////////////////////// 2382 #define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \ 2383 do { \ 2384 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \ 2385 if( catchAssertionHandler.allowThrows() ) \ 2386 try { \ 2387 static_cast<void>(expr); \ 2388 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 2389 } \ 2390 catch( exceptionType const& ) { \ 2391 catchAssertionHandler.handleExceptionThrownAsExpected(); \ 2392 } \ 2393 catch( ... ) { \ 2394 catchAssertionHandler.handleUnexpectedInflightException(); \ 2395 } \ 2396 else \ 2397 catchAssertionHandler.handleThrowingCallSkipped(); \ 2398 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2399 } while( false ) 2400 2401 /////////////////////////////////////////////////////////////////////////////// 2402 #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \ 2403 do { \ 2404 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::StringRef(), resultDisposition ); \ 2405 catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \ 2406 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2407 } while( false ) 2408 2409 /////////////////////////////////////////////////////////////////////////////// 2410 #define INTERNAL_CATCH_CAPTURE( varName, macroName, ... ) \ 2411 auto varName = Catch::Capturer( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info, #__VA_ARGS__ ); \ 2412 varName.captureValues( 0, __VA_ARGS__ ) 2413 2414 /////////////////////////////////////////////////////////////////////////////// 2415 #define INTERNAL_CATCH_INFO( macroName, log ) \ 2416 Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log ); 2417 2418 /////////////////////////////////////////////////////////////////////////////// 2419 #define INTERNAL_CATCH_UNSCOPED_INFO( macroName, log ) \ 2420 Catch::getResultCapture().emplaceUnscopedMessage( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log ) 2421 2422 /////////////////////////////////////////////////////////////////////////////// 2423 // Although this is matcher-based, it can be used with just a string 2424 #define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \ 2425 do { \ 2426 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ 2427 if( catchAssertionHandler.allowThrows() ) \ 2428 try { \ 2429 static_cast<void>(__VA_ARGS__); \ 2430 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 2431 } \ 2432 catch( ... ) { \ 2433 Catch::handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher##_catch_sr ); \ 2434 } \ 2435 else \ 2436 catchAssertionHandler.handleThrowingCallSkipped(); \ 2437 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2438 } while( false ) 2439 2440 #endif // CATCH_CONFIG_DISABLE 2441 2442 // end catch_capture.hpp 2443 // start catch_section.h 2444 2445 // start catch_section_info.h 2446 2447 // start catch_totals.h 2448 2449 #include <cstddef> 2450 2451 namespace Catch { 2452 2453 struct Counts { 2454 Counts operator - ( Counts const& other ) const; 2455 Counts& operator += ( Counts const& other ); 2456 2457 std::size_t total() const; 2458 bool allPassed() const; 2459 bool allOk() const; 2460 2461 std::size_t passed = 0; 2462 std::size_t failed = 0; 2463 std::size_t failedButOk = 0; 2464 }; 2465 2466 struct Totals { 2467 2468 Totals operator - ( Totals const& other ) const; 2469 Totals& operator += ( Totals const& other ); 2470 2471 Totals delta( Totals const& prevTotals ) const; 2472 2473 int error = 0; 2474 Counts assertions; 2475 Counts testCases; 2476 }; 2477 } 2478 2479 // end catch_totals.h 2480 #include <string> 2481 2482 namespace Catch { 2483 2484 struct SectionInfo { 2485 SectionInfo 2486 ( SourceLineInfo const& _lineInfo, 2487 std::string const& _name ); 2488 2489 // Deprecated 2490 SectionInfo 2491 ( SourceLineInfo const& _lineInfo, 2492 std::string const& _name, 2493 std::string const& ) : SectionInfo( _lineInfo, _name ) {} 2494 2495 std::string name; 2496 std::string description; // !Deprecated: this will always be empty 2497 SourceLineInfo lineInfo; 2498 }; 2499 2500 struct SectionEndInfo { 2501 SectionInfo sectionInfo; 2502 Counts prevAssertions; 2503 double durationInSeconds; 2504 }; 2505 2506 } // end namespace Catch 2507 2508 // end catch_section_info.h 2509 // start catch_timer.h 2510 2511 #include <cstdint> 2512 2513 namespace Catch { 2514 2515 auto getCurrentNanosecondsSinceEpoch() -> uint64_t; 2516 auto getEstimatedClockResolution() -> uint64_t; 2517 2518 class Timer { 2519 uint64_t m_nanoseconds = 0; 2520 public: 2521 void start(); 2522 auto getElapsedNanoseconds() const -> uint64_t; 2523 auto getElapsedMicroseconds() const -> uint64_t; 2524 auto getElapsedMilliseconds() const -> unsigned int; 2525 auto getElapsedSeconds() const -> double; 2526 }; 2527 2528 } // namespace Catch 2529 2530 // end catch_timer.h 2531 #include <string> 2532 2533 namespace Catch { 2534 2535 class Section : NonCopyable { 2536 public: 2537 Section( SectionInfo const& info ); 2538 ~Section(); 2539 2540 // This indicates whether the section should be executed or not 2541 explicit operator bool() const; 2542 2543 private: 2544 SectionInfo m_info; 2545 2546 std::string m_name; 2547 Counts m_assertions; 2548 bool m_sectionIncluded; 2549 Timer m_timer; 2550 }; 2551 2552 } // end namespace Catch 2553 2554 #define INTERNAL_CATCH_SECTION( ... ) \ 2555 CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ 2556 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \ 2557 CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS 2558 2559 #define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \ 2560 CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ 2561 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, (Catch::ReusableStringStream() << __VA_ARGS__).str() ) ) \ 2562 CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS 2563 2564 // end catch_section.h 2565 // start catch_benchmark.h 2566 2567 #include <cstdint> 2568 #include <string> 2569 2570 namespace Catch { 2571 2572 class BenchmarkLooper { 2573 2574 std::string m_name; 2575 std::size_t m_count = 0; 2576 std::size_t m_iterationsToRun = 1; 2577 uint64_t m_resolution; 2578 Timer m_timer; 2579 2580 static auto getResolution() -> uint64_t; 2581 public: 2582 // Keep most of this inline as it's on the code path that is being timed 2583 BenchmarkLooper( StringRef name ) 2584 : m_name( name ), 2585 m_resolution( getResolution() ) 2586 { 2587 reportStart(); 2588 m_timer.start(); 2589 } 2590 2591 explicit operator bool() { 2592 if( m_count < m_iterationsToRun ) 2593 return true; 2594 return needsMoreIterations(); 2595 } 2596 2597 void increment() { 2598 ++m_count; 2599 } 2600 2601 void reportStart(); 2602 auto needsMoreIterations() -> bool; 2603 }; 2604 2605 } // end namespace Catch 2606 2607 #define BENCHMARK( name ) \ 2608 for( Catch::BenchmarkLooper looper( name ); looper; looper.increment() ) 2609 2610 // end catch_benchmark.h 2611 // start catch_interfaces_exception.h 2612 2613 // start catch_interfaces_registry_hub.h 2614 2615 #include <string> 2616 #include <memory> 2617 2618 namespace Catch { 2619 2620 class TestCase; 2621 struct ITestCaseRegistry; 2622 struct IExceptionTranslatorRegistry; 2623 struct IExceptionTranslator; 2624 struct IReporterRegistry; 2625 struct IReporterFactory; 2626 struct ITagAliasRegistry; 2627 class StartupExceptionRegistry; 2628 2629 using IReporterFactoryPtr = std::shared_ptr<IReporterFactory>; 2630 2631 struct IRegistryHub { 2632 virtual ~IRegistryHub(); 2633 2634 virtual IReporterRegistry const& getReporterRegistry() const = 0; 2635 virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; 2636 virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0; 2637 2638 virtual IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const = 0; 2639 2640 virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0; 2641 }; 2642 2643 struct IMutableRegistryHub { 2644 virtual ~IMutableRegistryHub(); 2645 virtual void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) = 0; 2646 virtual void registerListener( IReporterFactoryPtr const& factory ) = 0; 2647 virtual void registerTest( TestCase const& testInfo ) = 0; 2648 virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; 2649 virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0; 2650 virtual void registerStartupException() noexcept = 0; 2651 }; 2652 2653 IRegistryHub const& getRegistryHub(); 2654 IMutableRegistryHub& getMutableRegistryHub(); 2655 void cleanUp(); 2656 std::string translateActiveException(); 2657 2658 } 2659 2660 // end catch_interfaces_registry_hub.h 2661 #if defined(CATCH_CONFIG_DISABLE) 2662 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( translatorName, signature) \ 2663 static std::string translatorName( signature ) 2664 #endif 2665 2666 #include <exception> 2667 #include <string> 2668 #include <vector> 2669 2670 namespace Catch { 2671 using exceptionTranslateFunction = std::string(*)(); 2672 2673 struct IExceptionTranslator; 2674 using ExceptionTranslators = std::vector<std::unique_ptr<IExceptionTranslator const>>; 2675 2676 struct IExceptionTranslator { 2677 virtual ~IExceptionTranslator(); 2678 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0; 2679 }; 2680 2681 struct IExceptionTranslatorRegistry { 2682 virtual ~IExceptionTranslatorRegistry(); 2683 2684 virtual std::string translateActiveException() const = 0; 2685 }; 2686 2687 class ExceptionTranslatorRegistrar { 2688 template<typename T> 2689 class ExceptionTranslator : public IExceptionTranslator { 2690 public: 2691 2692 ExceptionTranslator( std::string(*translateFunction)( T& ) ) 2693 : m_translateFunction( translateFunction ) 2694 {} 2695 2696 std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override { 2697 try { 2698 if( it == itEnd ) 2699 std::rethrow_exception(std::current_exception()); 2700 else 2701 return (*it)->translate( it+1, itEnd ); 2702 } 2703 catch( T& ex ) { 2704 return m_translateFunction( ex ); 2705 } 2706 } 2707 2708 protected: 2709 std::string(*m_translateFunction)( T& ); 2710 }; 2711 2712 public: 2713 template<typename T> 2714 ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) { 2715 getMutableRegistryHub().registerTranslator 2716 ( new ExceptionTranslator<T>( translateFunction ) ); 2717 } 2718 }; 2719 } 2720 2721 /////////////////////////////////////////////////////////////////////////////// 2722 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \ 2723 static std::string translatorName( signature ); \ 2724 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 2725 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); } \ 2726 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ 2727 static std::string translatorName( signature ) 2728 2729 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) 2730 2731 // end catch_interfaces_exception.h 2732 // start catch_approx.h 2733 2734 #include <type_traits> 2735 2736 namespace Catch { 2737 namespace Detail { 2738 2739 class Approx { 2740 private: 2741 bool equalityComparisonImpl(double other) const; 2742 // Validates the new margin (margin >= 0) 2743 // out-of-line to avoid including stdexcept in the header 2744 void setMargin(double margin); 2745 // Validates the new epsilon (0 < epsilon < 1) 2746 // out-of-line to avoid including stdexcept in the header 2747 void setEpsilon(double epsilon); 2748 2749 public: 2750 explicit Approx ( double value ); 2751 2752 static Approx custom(); 2753 2754 Approx operator-() const; 2755 2756 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 2757 Approx operator()( T const& value ) { 2758 Approx approx( static_cast<double>(value) ); 2759 approx.m_epsilon = m_epsilon; 2760 approx.m_margin = m_margin; 2761 approx.m_scale = m_scale; 2762 return approx; 2763 } 2764 2765 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 2766 explicit Approx( T const& value ): Approx(static_cast<double>(value)) 2767 {} 2768 2769 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 2770 friend bool operator == ( const T& lhs, Approx const& rhs ) { 2771 auto lhs_v = static_cast<double>(lhs); 2772 return rhs.equalityComparisonImpl(lhs_v); 2773 } 2774 2775 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 2776 friend bool operator == ( Approx const& lhs, const T& rhs ) { 2777 return operator==( rhs, lhs ); 2778 } 2779 2780 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 2781 friend bool operator != ( T const& lhs, Approx const& rhs ) { 2782 return !operator==( lhs, rhs ); 2783 } 2784 2785 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 2786 friend bool operator != ( Approx const& lhs, T const& rhs ) { 2787 return !operator==( rhs, lhs ); 2788 } 2789 2790 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 2791 friend bool operator <= ( T const& lhs, Approx const& rhs ) { 2792 return static_cast<double>(lhs) < rhs.m_value || lhs == rhs; 2793 } 2794 2795 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 2796 friend bool operator <= ( Approx const& lhs, T const& rhs ) { 2797 return lhs.m_value < static_cast<double>(rhs) || lhs == rhs; 2798 } 2799 2800 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 2801 friend bool operator >= ( T const& lhs, Approx const& rhs ) { 2802 return static_cast<double>(lhs) > rhs.m_value || lhs == rhs; 2803 } 2804 2805 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 2806 friend bool operator >= ( Approx const& lhs, T const& rhs ) { 2807 return lhs.m_value > static_cast<double>(rhs) || lhs == rhs; 2808 } 2809 2810 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 2811 Approx& epsilon( T const& newEpsilon ) { 2812 double epsilonAsDouble = static_cast<double>(newEpsilon); 2813 setEpsilon(epsilonAsDouble); 2814 return *this; 2815 } 2816 2817 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 2818 Approx& margin( T const& newMargin ) { 2819 double marginAsDouble = static_cast<double>(newMargin); 2820 setMargin(marginAsDouble); 2821 return *this; 2822 } 2823 2824 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 2825 Approx& scale( T const& newScale ) { 2826 m_scale = static_cast<double>(newScale); 2827 return *this; 2828 } 2829 2830 std::string toString() const; 2831 2832 private: 2833 double m_epsilon; 2834 double m_margin; 2835 double m_scale; 2836 double m_value; 2837 }; 2838 } // end namespace Detail 2839 2840 namespace literals { 2841 Detail::Approx operator "" _a(long double val); 2842 Detail::Approx operator "" _a(unsigned long long val); 2843 } // end namespace literals 2844 2845 template<> 2846 struct StringMaker<Catch::Detail::Approx> { 2847 static std::string convert(Catch::Detail::Approx const& value); 2848 }; 2849 2850 } // end namespace Catch 2851 2852 // end catch_approx.h 2853 // start catch_string_manip.h 2854 2855 #include <string> 2856 #include <iosfwd> 2857 2858 namespace Catch { 2859 2860 bool startsWith( std::string const& s, std::string const& prefix ); 2861 bool startsWith( std::string const& s, char prefix ); 2862 bool endsWith( std::string const& s, std::string const& suffix ); 2863 bool endsWith( std::string const& s, char suffix ); 2864 bool contains( std::string const& s, std::string const& infix ); 2865 void toLowerInPlace( std::string& s ); 2866 std::string toLower( std::string const& s ); 2867 std::string trim( std::string const& str ); 2868 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ); 2869 2870 struct pluralise { 2871 pluralise( std::size_t count, std::string const& label ); 2872 2873 friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); 2874 2875 std::size_t m_count; 2876 std::string m_label; 2877 }; 2878 } 2879 2880 // end catch_string_manip.h 2881 #ifndef CATCH_CONFIG_DISABLE_MATCHERS 2882 // start catch_capture_matchers.h 2883 2884 // start catch_matchers.h 2885 2886 #include <string> 2887 #include <vector> 2888 2889 namespace Catch { 2890 namespace Matchers { 2891 namespace Impl { 2892 2893 template<typename ArgT> struct MatchAllOf; 2894 template<typename ArgT> struct MatchAnyOf; 2895 template<typename ArgT> struct MatchNotOf; 2896 2897 class MatcherUntypedBase { 2898 public: 2899 MatcherUntypedBase() = default; 2900 MatcherUntypedBase ( MatcherUntypedBase const& ) = default; 2901 MatcherUntypedBase& operator = ( MatcherUntypedBase const& ) = delete; 2902 std::string toString() const; 2903 2904 protected: 2905 virtual ~MatcherUntypedBase(); 2906 virtual std::string describe() const = 0; 2907 mutable std::string m_cachedToString; 2908 }; 2909 2910 #ifdef __clang__ 2911 # pragma clang diagnostic push 2912 # pragma clang diagnostic ignored "-Wnon-virtual-dtor" 2913 #endif 2914 2915 template<typename ObjectT> 2916 struct MatcherMethod { 2917 virtual bool match( ObjectT const& arg ) const = 0; 2918 }; 2919 2920 #ifdef __clang__ 2921 # pragma clang diagnostic pop 2922 #endif 2923 2924 template<typename T> 2925 struct MatcherBase : MatcherUntypedBase, MatcherMethod<T> { 2926 2927 MatchAllOf<T> operator && ( MatcherBase const& other ) const; 2928 MatchAnyOf<T> operator || ( MatcherBase const& other ) const; 2929 MatchNotOf<T> operator ! () const; 2930 }; 2931 2932 template<typename ArgT> 2933 struct MatchAllOf : MatcherBase<ArgT> { 2934 bool match( ArgT const& arg ) const override { 2935 for( auto matcher : m_matchers ) { 2936 if (!matcher->match(arg)) 2937 return false; 2938 } 2939 return true; 2940 } 2941 std::string describe() const override { 2942 std::string description; 2943 description.reserve( 4 + m_matchers.size()*32 ); 2944 description += "( "; 2945 bool first = true; 2946 for( auto matcher : m_matchers ) { 2947 if( first ) 2948 first = false; 2949 else 2950 description += " and "; 2951 description += matcher->toString(); 2952 } 2953 description += " )"; 2954 return description; 2955 } 2956 2957 MatchAllOf<ArgT>& operator && ( MatcherBase<ArgT> const& other ) { 2958 m_matchers.push_back( &other ); 2959 return *this; 2960 } 2961 2962 std::vector<MatcherBase<ArgT> const*> m_matchers; 2963 }; 2964 template<typename ArgT> 2965 struct MatchAnyOf : MatcherBase<ArgT> { 2966 2967 bool match( ArgT const& arg ) const override { 2968 for( auto matcher : m_matchers ) { 2969 if (matcher->match(arg)) 2970 return true; 2971 } 2972 return false; 2973 } 2974 std::string describe() const override { 2975 std::string description; 2976 description.reserve( 4 + m_matchers.size()*32 ); 2977 description += "( "; 2978 bool first = true; 2979 for( auto matcher : m_matchers ) { 2980 if( first ) 2981 first = false; 2982 else 2983 description += " or "; 2984 description += matcher->toString(); 2985 } 2986 description += " )"; 2987 return description; 2988 } 2989 2990 MatchAnyOf<ArgT>& operator || ( MatcherBase<ArgT> const& other ) { 2991 m_matchers.push_back( &other ); 2992 return *this; 2993 } 2994 2995 std::vector<MatcherBase<ArgT> const*> m_matchers; 2996 }; 2997 2998 template<typename ArgT> 2999 struct MatchNotOf : MatcherBase<ArgT> { 3000 3001 MatchNotOf( MatcherBase<ArgT> const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {} 3002 3003 bool match( ArgT const& arg ) const override { 3004 return !m_underlyingMatcher.match( arg ); 3005 } 3006 3007 std::string describe() const override { 3008 return "not " + m_underlyingMatcher.toString(); 3009 } 3010 MatcherBase<ArgT> const& m_underlyingMatcher; 3011 }; 3012 3013 template<typename T> 3014 MatchAllOf<T> MatcherBase<T>::operator && ( MatcherBase const& other ) const { 3015 return MatchAllOf<T>() && *this && other; 3016 } 3017 template<typename T> 3018 MatchAnyOf<T> MatcherBase<T>::operator || ( MatcherBase const& other ) const { 3019 return MatchAnyOf<T>() || *this || other; 3020 } 3021 template<typename T> 3022 MatchNotOf<T> MatcherBase<T>::operator ! () const { 3023 return MatchNotOf<T>( *this ); 3024 } 3025 3026 } // namespace Impl 3027 3028 } // namespace Matchers 3029 3030 using namespace Matchers; 3031 using Matchers::Impl::MatcherBase; 3032 3033 } // namespace Catch 3034 3035 // end catch_matchers.h 3036 // start catch_matchers_floating.h 3037 3038 #include <type_traits> 3039 #include <cmath> 3040 3041 namespace Catch { 3042 namespace Matchers { 3043 3044 namespace Floating { 3045 3046 enum class FloatingPointKind : uint8_t; 3047 3048 struct WithinAbsMatcher : MatcherBase<double> { 3049 WithinAbsMatcher(double target, double margin); 3050 bool match(double const& matchee) const override; 3051 std::string describe() const override; 3052 private: 3053 double m_target; 3054 double m_margin; 3055 }; 3056 3057 struct WithinUlpsMatcher : MatcherBase<double> { 3058 WithinUlpsMatcher(double target, int ulps, FloatingPointKind baseType); 3059 bool match(double const& matchee) const override; 3060 std::string describe() const override; 3061 private: 3062 double m_target; 3063 int m_ulps; 3064 FloatingPointKind m_type; 3065 }; 3066 3067 } // namespace Floating 3068 3069 // The following functions create the actual matcher objects. 3070 // This allows the types to be inferred 3071 Floating::WithinUlpsMatcher WithinULP(double target, int maxUlpDiff); 3072 Floating::WithinUlpsMatcher WithinULP(float target, int maxUlpDiff); 3073 Floating::WithinAbsMatcher WithinAbs(double target, double margin); 3074 3075 } // namespace Matchers 3076 } // namespace Catch 3077 3078 // end catch_matchers_floating.h 3079 // start catch_matchers_generic.hpp 3080 3081 #include <functional> 3082 #include <string> 3083 3084 namespace Catch { 3085 namespace Matchers { 3086 namespace Generic { 3087 3088 namespace Detail { 3089 std::string finalizeDescription(const std::string& desc); 3090 } 3091 3092 template <typename T> 3093 class PredicateMatcher : public MatcherBase<T> { 3094 std::function<bool(T const&)> m_predicate; 3095 std::string m_description; 3096 public: 3097 3098 PredicateMatcher(std::function<bool(T const&)> const& elem, std::string const& descr) 3099 :m_predicate(std::move(elem)), 3100 m_description(Detail::finalizeDescription(descr)) 3101 {} 3102 3103 bool match( T const& item ) const override { 3104 return m_predicate(item); 3105 } 3106 3107 std::string describe() const override { 3108 return m_description; 3109 } 3110 }; 3111 3112 } // namespace Generic 3113 3114 // The following functions create the actual matcher objects. 3115 // The user has to explicitly specify type to the function, because 3116 // inferring std::function<bool(T const&)> is hard (but possible) and 3117 // requires a lot of TMP. 3118 template<typename T> 3119 Generic::PredicateMatcher<T> Predicate(std::function<bool(T const&)> const& predicate, std::string const& description = "") { 3120 return Generic::PredicateMatcher<T>(predicate, description); 3121 } 3122 3123 } // namespace Matchers 3124 } // namespace Catch 3125 3126 // end catch_matchers_generic.hpp 3127 // start catch_matchers_string.h 3128 3129 #include <string> 3130 3131 namespace Catch { 3132 namespace Matchers { 3133 3134 namespace StdString { 3135 3136 struct CasedString 3137 { 3138 CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ); 3139 std::string adjustString( std::string const& str ) const; 3140 std::string caseSensitivitySuffix() const; 3141 3142 CaseSensitive::Choice m_caseSensitivity; 3143 std::string m_str; 3144 }; 3145 3146 struct StringMatcherBase : MatcherBase<std::string> { 3147 StringMatcherBase( std::string const& operation, CasedString const& comparator ); 3148 std::string describe() const override; 3149 3150 CasedString m_comparator; 3151 std::string m_operation; 3152 }; 3153 3154 struct EqualsMatcher : StringMatcherBase { 3155 EqualsMatcher( CasedString const& comparator ); 3156 bool match( std::string const& source ) const override; 3157 }; 3158 struct ContainsMatcher : StringMatcherBase { 3159 ContainsMatcher( CasedString const& comparator ); 3160 bool match( std::string const& source ) const override; 3161 }; 3162 struct StartsWithMatcher : StringMatcherBase { 3163 StartsWithMatcher( CasedString const& comparator ); 3164 bool match( std::string const& source ) const override; 3165 }; 3166 struct EndsWithMatcher : StringMatcherBase { 3167 EndsWithMatcher( CasedString const& comparator ); 3168 bool match( std::string const& source ) const override; 3169 }; 3170 3171 struct RegexMatcher : MatcherBase<std::string> { 3172 RegexMatcher( std::string regex, CaseSensitive::Choice caseSensitivity ); 3173 bool match( std::string const& matchee ) const override; 3174 std::string describe() const override; 3175 3176 private: 3177 std::string m_regex; 3178 CaseSensitive::Choice m_caseSensitivity; 3179 }; 3180 3181 } // namespace StdString 3182 3183 // The following functions create the actual matcher objects. 3184 // This allows the types to be inferred 3185 3186 StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); 3187 StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); 3188 StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); 3189 StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); 3190 StdString::RegexMatcher Matches( std::string const& regex, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); 3191 3192 } // namespace Matchers 3193 } // namespace Catch 3194 3195 // end catch_matchers_string.h 3196 // start catch_matchers_vector.h 3197 3198 #include <algorithm> 3199 3200 namespace Catch { 3201 namespace Matchers { 3202 3203 namespace Vector { 3204 template<typename T> 3205 struct ContainsElementMatcher : MatcherBase<std::vector<T>> { 3206 3207 ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {} 3208 3209 bool match(std::vector<T> const &v) const override { 3210 for (auto const& el : v) { 3211 if (el == m_comparator) { 3212 return true; 3213 } 3214 } 3215 return false; 3216 } 3217 3218 std::string describe() const override { 3219 return "Contains: " + ::Catch::Detail::stringify( m_comparator ); 3220 } 3221 3222 T const& m_comparator; 3223 }; 3224 3225 template<typename T> 3226 struct ContainsMatcher : MatcherBase<std::vector<T>> { 3227 3228 ContainsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {} 3229 3230 bool match(std::vector<T> const &v) const override { 3231 // !TBD: see note in EqualsMatcher 3232 if (m_comparator.size() > v.size()) 3233 return false; 3234 for (auto const& comparator : m_comparator) { 3235 auto present = false; 3236 for (const auto& el : v) { 3237 if (el == comparator) { 3238 present = true; 3239 break; 3240 } 3241 } 3242 if (!present) { 3243 return false; 3244 } 3245 } 3246 return true; 3247 } 3248 std::string describe() const override { 3249 return "Contains: " + ::Catch::Detail::stringify( m_comparator ); 3250 } 3251 3252 std::vector<T> const& m_comparator; 3253 }; 3254 3255 template<typename T> 3256 struct EqualsMatcher : MatcherBase<std::vector<T>> { 3257 3258 EqualsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {} 3259 3260 bool match(std::vector<T> const &v) const override { 3261 // !TBD: This currently works if all elements can be compared using != 3262 // - a more general approach would be via a compare template that defaults 3263 // to using !=. but could be specialised for, e.g. std::vector<T> etc 3264 // - then just call that directly 3265 if (m_comparator.size() != v.size()) 3266 return false; 3267 for (std::size_t i = 0; i < v.size(); ++i) 3268 if (m_comparator[i] != v[i]) 3269 return false; 3270 return true; 3271 } 3272 std::string describe() const override { 3273 return "Equals: " + ::Catch::Detail::stringify( m_comparator ); 3274 } 3275 std::vector<T> const& m_comparator; 3276 }; 3277 3278 template<typename T> 3279 struct ApproxMatcher : MatcherBase<std::vector<T>> { 3280 3281 ApproxMatcher(std::vector<T> const& comparator) : m_comparator( comparator ) {} 3282 3283 bool match(std::vector<T> const &v) const override { 3284 if (m_comparator.size() != v.size()) 3285 return false; 3286 for (std::size_t i = 0; i < v.size(); ++i) 3287 if (m_comparator[i] != approx(v[i])) 3288 return false; 3289 return true; 3290 } 3291 std::string describe() const override { 3292 return "is approx: " + ::Catch::Detail::stringify( m_comparator ); 3293 } 3294 template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3295 ApproxMatcher& epsilon( T const& newEpsilon ) { 3296 approx.epsilon(newEpsilon); 3297 return *this; 3298 } 3299 template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3300 ApproxMatcher& margin( T const& newMargin ) { 3301 approx.margin(newMargin); 3302 return *this; 3303 } 3304 template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 3305 ApproxMatcher& scale( T const& newScale ) { 3306 approx.scale(newScale); 3307 return *this; 3308 } 3309 3310 std::vector<T> const& m_comparator; 3311 mutable Catch::Detail::Approx approx = Catch::Detail::Approx::custom(); 3312 }; 3313 3314 template<typename T> 3315 struct UnorderedEqualsMatcher : MatcherBase<std::vector<T>> { 3316 UnorderedEqualsMatcher(std::vector<T> const& target) : m_target(target) {} 3317 bool match(std::vector<T> const& vec) const override { 3318 // Note: This is a reimplementation of std::is_permutation, 3319 // because I don't want to include <algorithm> inside the common path 3320 if (m_target.size() != vec.size()) { 3321 return false; 3322 } 3323 return std::is_permutation(m_target.begin(), m_target.end(), vec.begin()); 3324 } 3325 3326 std::string describe() const override { 3327 return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target); 3328 } 3329 private: 3330 std::vector<T> const& m_target; 3331 }; 3332 3333 } // namespace Vector 3334 3335 // The following functions create the actual matcher objects. 3336 // This allows the types to be inferred 3337 3338 template<typename T> 3339 Vector::ContainsMatcher<T> Contains( std::vector<T> const& comparator ) { 3340 return Vector::ContainsMatcher<T>( comparator ); 3341 } 3342 3343 template<typename T> 3344 Vector::ContainsElementMatcher<T> VectorContains( T const& comparator ) { 3345 return Vector::ContainsElementMatcher<T>( comparator ); 3346 } 3347 3348 template<typename T> 3349 Vector::EqualsMatcher<T> Equals( std::vector<T> const& comparator ) { 3350 return Vector::EqualsMatcher<T>( comparator ); 3351 } 3352 3353 template<typename T> 3354 Vector::ApproxMatcher<T> Approx( std::vector<T> const& comparator ) { 3355 return Vector::ApproxMatcher<T>( comparator ); 3356 } 3357 3358 template<typename T> 3359 Vector::UnorderedEqualsMatcher<T> UnorderedEquals(std::vector<T> const& target) { 3360 return Vector::UnorderedEqualsMatcher<T>(target); 3361 } 3362 3363 } // namespace Matchers 3364 } // namespace Catch 3365 3366 // end catch_matchers_vector.h 3367 namespace Catch { 3368 3369 template<typename ArgT, typename MatcherT> 3370 class MatchExpr : public ITransientExpression { 3371 ArgT const& m_arg; 3372 MatcherT m_matcher; 3373 StringRef m_matcherString; 3374 public: 3375 MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString ) 3376 : ITransientExpression{ true, matcher.match( arg ) }, 3377 m_arg( arg ), 3378 m_matcher( matcher ), 3379 m_matcherString( matcherString ) 3380 {} 3381 3382 void streamReconstructedExpression( std::ostream &os ) const override { 3383 auto matcherAsString = m_matcher.toString(); 3384 os << Catch::Detail::stringify( m_arg ) << ' '; 3385 if( matcherAsString == Detail::unprintableString ) 3386 os << m_matcherString; 3387 else 3388 os << matcherAsString; 3389 } 3390 }; 3391 3392 using StringMatcher = Matchers::Impl::MatcherBase<std::string>; 3393 3394 void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString ); 3395 3396 template<typename ArgT, typename MatcherT> 3397 auto makeMatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString ) -> MatchExpr<ArgT, MatcherT> { 3398 return MatchExpr<ArgT, MatcherT>( arg, matcher, matcherString ); 3399 } 3400 3401 } // namespace Catch 3402 3403 /////////////////////////////////////////////////////////////////////////////// 3404 #define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ 3405 do { \ 3406 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ 3407 INTERNAL_CATCH_TRY { \ 3408 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher, #matcher##_catch_sr ) ); \ 3409 } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ 3410 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 3411 } while( false ) 3412 3413 /////////////////////////////////////////////////////////////////////////////// 3414 #define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \ 3415 do { \ 3416 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ 3417 if( catchAssertionHandler.allowThrows() ) \ 3418 try { \ 3419 static_cast<void>(__VA_ARGS__ ); \ 3420 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 3421 } \ 3422 catch( exceptionType const& ex ) { \ 3423 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( ex, matcher, #matcher##_catch_sr ) ); \ 3424 } \ 3425 catch( ... ) { \ 3426 catchAssertionHandler.handleUnexpectedInflightException(); \ 3427 } \ 3428 else \ 3429 catchAssertionHandler.handleThrowingCallSkipped(); \ 3430 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 3431 } while( false ) 3432 3433 // end catch_capture_matchers.h 3434 #endif 3435 // start catch_generators.hpp 3436 3437 // start catch_interfaces_generatortracker.h 3438 3439 3440 #include <memory> 3441 3442 namespace Catch { 3443 3444 namespace Generators { 3445 class GeneratorUntypedBase { 3446 public: 3447 GeneratorUntypedBase() = default; 3448 virtual ~GeneratorUntypedBase(); 3449 // Attempts to move the generator to the next element 3450 // 3451 // Returns true iff the move succeeded (and a valid element 3452 // can be retrieved). 3453 virtual bool next() = 0; 3454 }; 3455 using GeneratorBasePtr = std::unique_ptr<GeneratorUntypedBase>; 3456 3457 } // namespace Generators 3458 3459 struct IGeneratorTracker { 3460 virtual ~IGeneratorTracker(); 3461 virtual auto hasGenerator() const -> bool = 0; 3462 virtual auto getGenerator() const -> Generators::GeneratorBasePtr const& = 0; 3463 virtual void setGenerator( Generators::GeneratorBasePtr&& generator ) = 0; 3464 }; 3465 3466 } // namespace Catch 3467 3468 // end catch_interfaces_generatortracker.h 3469 // start catch_enforce.h 3470 3471 #include <stdexcept> 3472 3473 namespace Catch { 3474 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 3475 template <typename Ex> 3476 [[noreturn]] 3477 void throw_exception(Ex const& e) { 3478 throw e; 3479 } 3480 #else // ^^ Exceptions are enabled // Exceptions are disabled vv 3481 [[noreturn]] 3482 void throw_exception(std::exception const& e); 3483 #endif 3484 } // namespace Catch; 3485 3486 #define CATCH_PREPARE_EXCEPTION( type, msg ) \ 3487 type( ( Catch::ReusableStringStream() << msg ).str() ) 3488 #define CATCH_INTERNAL_ERROR( msg ) \ 3489 Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::logic_error, CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg)) 3490 #define CATCH_ERROR( msg ) \ 3491 Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::domain_error, msg )) 3492 #define CATCH_RUNTIME_ERROR( msg ) \ 3493 Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::runtime_error, msg )) 3494 #define CATCH_ENFORCE( condition, msg ) \ 3495 do{ if( !(condition) ) CATCH_ERROR( msg ); } while(false) 3496 3497 // end catch_enforce.h 3498 #include <memory> 3499 #include <vector> 3500 #include <cassert> 3501 3502 #include <utility> 3503 #include <exception> 3504 3505 namespace Catch { 3506 3507 class GeneratorException : public std::exception { 3508 const char* const m_msg = ""; 3509 3510 public: 3511 GeneratorException(const char* msg): 3512 m_msg(msg) 3513 {} 3514 3515 const char* what() const noexcept override final; 3516 }; 3517 3518 namespace Generators { 3519 3520 // !TBD move this into its own location? 3521 namespace pf{ 3522 template<typename T, typename... Args> 3523 std::unique_ptr<T> make_unique( Args&&... args ) { 3524 return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); 3525 } 3526 } 3527 3528 template<typename T> 3529 struct IGenerator : GeneratorUntypedBase { 3530 virtual ~IGenerator() = default; 3531 3532 // Returns the current element of the generator 3533 // 3534 // \Precondition The generator is either freshly constructed, 3535 // or the last call to `next()` returned true 3536 virtual T const& get() const = 0; 3537 using type = T; 3538 }; 3539 3540 template<typename T> 3541 class SingleValueGenerator final : public IGenerator<T> { 3542 T m_value; 3543 public: 3544 SingleValueGenerator(T const& value) : m_value( value ) {} 3545 SingleValueGenerator(T&& value) : m_value(std::move(value)) {} 3546 3547 T const& get() const override { 3548 return m_value; 3549 } 3550 bool next() override { 3551 return false; 3552 } 3553 }; 3554 3555 template<typename T> 3556 class FixedValuesGenerator final : public IGenerator<T> { 3557 std::vector<T> m_values; 3558 size_t m_idx = 0; 3559 public: 3560 FixedValuesGenerator( std::initializer_list<T> values ) : m_values( values ) {} 3561 3562 T const& get() const override { 3563 return m_values[m_idx]; 3564 } 3565 bool next() override { 3566 ++m_idx; 3567 return m_idx < m_values.size(); 3568 } 3569 }; 3570 3571 template <typename T> 3572 class GeneratorWrapper final { 3573 std::unique_ptr<IGenerator<T>> m_generator; 3574 public: 3575 GeneratorWrapper(std::unique_ptr<IGenerator<T>> generator): 3576 m_generator(std::move(generator)) 3577 {} 3578 T const& get() const { 3579 return m_generator->get(); 3580 } 3581 bool next() { 3582 return m_generator->next(); 3583 } 3584 }; 3585 3586 template <typename T> 3587 GeneratorWrapper<T> value(T&& value) { 3588 return GeneratorWrapper<T>(pf::make_unique<SingleValueGenerator<T>>(std::forward<T>(value))); 3589 } 3590 template <typename T> 3591 GeneratorWrapper<T> values(std::initializer_list<T> values) { 3592 return GeneratorWrapper<T>(pf::make_unique<FixedValuesGenerator<T>>(values)); 3593 } 3594 3595 template<typename T> 3596 class Generators : public IGenerator<T> { 3597 std::vector<GeneratorWrapper<T>> m_generators; 3598 size_t m_current = 0; 3599 3600 void populate(GeneratorWrapper<T>&& generator) { 3601 m_generators.emplace_back(std::move(generator)); 3602 } 3603 void populate(T&& val) { 3604 m_generators.emplace_back(value(std::move(val))); 3605 } 3606 template<typename U> 3607 void populate(U&& val) { 3608 populate(T(std::move(val))); 3609 } 3610 template<typename U, typename... Gs> 3611 void populate(U&& valueOrGenerator, Gs... moreGenerators) { 3612 populate(std::forward<U>(valueOrGenerator)); 3613 populate(std::forward<Gs>(moreGenerators)...); 3614 } 3615 3616 public: 3617 template <typename... Gs> 3618 Generators(Gs... moreGenerators) { 3619 m_generators.reserve(sizeof...(Gs)); 3620 populate(std::forward<Gs>(moreGenerators)...); 3621 } 3622 3623 T const& get() const override { 3624 return m_generators[m_current].get(); 3625 } 3626 3627 bool next() override { 3628 if (m_current >= m_generators.size()) { 3629 return false; 3630 } 3631 const bool current_status = m_generators[m_current].next(); 3632 if (!current_status) { 3633 ++m_current; 3634 } 3635 return m_current < m_generators.size(); 3636 } 3637 }; 3638 3639 template<typename... Ts> 3640 GeneratorWrapper<std::tuple<Ts...>> table( std::initializer_list<std::tuple<typename std::decay<Ts>::type...>> tuples ) { 3641 return values<std::tuple<Ts...>>( tuples ); 3642 } 3643 3644 // Tag type to signal that a generator sequence should convert arguments to a specific type 3645 template <typename T> 3646 struct as {}; 3647 3648 template<typename T, typename... Gs> 3649 auto makeGenerators( GeneratorWrapper<T>&& generator, Gs... moreGenerators ) -> Generators<T> { 3650 return Generators<T>(std::move(generator), std::forward<Gs>(moreGenerators)...); 3651 } 3652 template<typename T> 3653 auto makeGenerators( GeneratorWrapper<T>&& generator ) -> Generators<T> { 3654 return Generators<T>(std::move(generator)); 3655 } 3656 template<typename T, typename... Gs> 3657 auto makeGenerators( T&& val, Gs... moreGenerators ) -> Generators<T> { 3658 return makeGenerators( value( std::forward<T>( val ) ), std::forward<Gs>( moreGenerators )... ); 3659 } 3660 template<typename T, typename U, typename... Gs> 3661 auto makeGenerators( as<T>, U&& val, Gs... moreGenerators ) -> Generators<T> { 3662 return makeGenerators( value( T( std::forward<U>( val ) ) ), std::forward<Gs>( moreGenerators )... ); 3663 } 3664 3665 auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker&; 3666 3667 template<typename L> 3668 // Note: The type after -> is weird, because VS2015 cannot parse 3669 // the expression used in the typedef inside, when it is in 3670 // return type. Yeah. 3671 auto generate( SourceLineInfo const& lineInfo, L const& generatorExpression ) -> decltype(std::declval<decltype(generatorExpression())>().get()) { 3672 using UnderlyingType = typename decltype(generatorExpression())::type; 3673 3674 IGeneratorTracker& tracker = acquireGeneratorTracker( lineInfo ); 3675 if (!tracker.hasGenerator()) { 3676 tracker.setGenerator(pf::make_unique<Generators<UnderlyingType>>(generatorExpression())); 3677 } 3678 3679 auto const& generator = static_cast<IGenerator<UnderlyingType> const&>( *tracker.getGenerator() ); 3680 return generator.get(); 3681 } 3682 3683 } // namespace Generators 3684 } // namespace Catch 3685 3686 #define GENERATE( ... ) \ 3687 Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) 3688 #define GENERATE_COPY( ... ) \ 3689 Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) 3690 #define GENERATE_REF( ... ) \ 3691 Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) 3692 3693 // end catch_generators.hpp 3694 // start catch_generators_generic.hpp 3695 3696 namespace Catch { 3697 namespace Generators { 3698 3699 template <typename T> 3700 class TakeGenerator : public IGenerator<T> { 3701 GeneratorWrapper<T> m_generator; 3702 size_t m_returned = 0; 3703 size_t m_target; 3704 public: 3705 TakeGenerator(size_t target, GeneratorWrapper<T>&& generator): 3706 m_generator(std::move(generator)), 3707 m_target(target) 3708 { 3709 assert(target != 0 && "Empty generators are not allowed"); 3710 } 3711 T const& get() const override { 3712 return m_generator.get(); 3713 } 3714 bool next() override { 3715 ++m_returned; 3716 if (m_returned >= m_target) { 3717 return false; 3718 } 3719 3720 const auto success = m_generator.next(); 3721 // If the underlying generator does not contain enough values 3722 // then we cut short as well 3723 if (!success) { 3724 m_returned = m_target; 3725 } 3726 return success; 3727 } 3728 }; 3729 3730 template <typename T> 3731 GeneratorWrapper<T> take(size_t target, GeneratorWrapper<T>&& generator) { 3732 return GeneratorWrapper<T>(pf::make_unique<TakeGenerator<T>>(target, std::move(generator))); 3733 } 3734 3735 template <typename T, typename Predicate> 3736 class FilterGenerator : public IGenerator<T> { 3737 GeneratorWrapper<T> m_generator; 3738 Predicate m_predicate; 3739 public: 3740 template <typename P = Predicate> 3741 FilterGenerator(P&& pred, GeneratorWrapper<T>&& generator): 3742 m_generator(std::move(generator)), 3743 m_predicate(std::forward<P>(pred)) 3744 { 3745 if (!m_predicate(m_generator.get())) { 3746 // It might happen that there are no values that pass the 3747 // filter. In that case we throw an exception. 3748 auto has_initial_value = next(); 3749 if (!has_initial_value) { 3750 Catch::throw_exception(GeneratorException("No valid value found in filtered generator")); 3751 } 3752 } 3753 } 3754 3755 T const& get() const override { 3756 return m_generator.get(); 3757 } 3758 3759 bool next() override { 3760 bool success = m_generator.next(); 3761 if (!success) { 3762 return false; 3763 } 3764 while (!m_predicate(m_generator.get()) && (success = m_generator.next()) == true); 3765 return success; 3766 } 3767 }; 3768 3769 template <typename T, typename Predicate> 3770 GeneratorWrapper<T> filter(Predicate&& pred, GeneratorWrapper<T>&& generator) { 3771 return GeneratorWrapper<T>(std::unique_ptr<IGenerator<T>>(pf::make_unique<FilterGenerator<T, Predicate>>(std::forward<Predicate>(pred), std::move(generator)))); 3772 } 3773 3774 template <typename T> 3775 class RepeatGenerator : public IGenerator<T> { 3776 GeneratorWrapper<T> m_generator; 3777 mutable std::vector<T> m_returned; 3778 size_t m_target_repeats; 3779 size_t m_current_repeat = 0; 3780 size_t m_repeat_index = 0; 3781 public: 3782 RepeatGenerator(size_t repeats, GeneratorWrapper<T>&& generator): 3783 m_generator(std::move(generator)), 3784 m_target_repeats(repeats) 3785 { 3786 assert(m_target_repeats > 0 && "Repeat generator must repeat at least once"); 3787 } 3788 3789 T const& get() const override { 3790 if (m_current_repeat == 0) { 3791 m_returned.push_back(m_generator.get()); 3792 return m_returned.back(); 3793 } 3794 return m_returned[m_repeat_index]; 3795 } 3796 3797 bool next() override { 3798 // There are 2 basic cases: 3799 // 1) We are still reading the generator 3800 // 2) We are reading our own cache 3801 3802 // In the first case, we need to poke the underlying generator. 3803 // If it happily moves, we are left in that state, otherwise it is time to start reading from our cache 3804 if (m_current_repeat == 0) { 3805 const auto success = m_generator.next(); 3806 if (!success) { 3807 ++m_current_repeat; 3808 } 3809 return m_current_repeat < m_target_repeats; 3810 } 3811 3812 // In the second case, we need to move indices forward and check that we haven't run up against the end 3813 ++m_repeat_index; 3814 if (m_repeat_index == m_returned.size()) { 3815 m_repeat_index = 0; 3816 ++m_current_repeat; 3817 } 3818 return m_current_repeat < m_target_repeats; 3819 } 3820 }; 3821 3822 template <typename T> 3823 GeneratorWrapper<T> repeat(size_t repeats, GeneratorWrapper<T>&& generator) { 3824 return GeneratorWrapper<T>(pf::make_unique<RepeatGenerator<T>>(repeats, std::move(generator))); 3825 } 3826 3827 template <typename T, typename U, typename Func> 3828 class MapGenerator : public IGenerator<T> { 3829 // TBD: provide static assert for mapping function, for friendly error message 3830 GeneratorWrapper<U> m_generator; 3831 Func m_function; 3832 // To avoid returning dangling reference, we have to save the values 3833 T m_cache; 3834 public: 3835 template <typename F2 = Func> 3836 MapGenerator(F2&& function, GeneratorWrapper<U>&& generator) : 3837 m_generator(std::move(generator)), 3838 m_function(std::forward<F2>(function)), 3839 m_cache(m_function(m_generator.get())) 3840 {} 3841 3842 T const& get() const override { 3843 return m_cache; 3844 } 3845 bool next() override { 3846 const auto success = m_generator.next(); 3847 if (success) { 3848 m_cache = m_function(m_generator.get()); 3849 } 3850 return success; 3851 } 3852 }; 3853 3854 #if defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703 3855 // std::result_of is deprecated in C++17 and removed in C++20. Hence, it is 3856 // replaced with std::invoke_result here. Also *_t format is preferred over 3857 // typename *::type format. 3858 template <typename Func, typename U> 3859 using MapFunctionReturnType = std::remove_reference_t<std::remove_cv_t<std::invoke_result_t<Func, U>>>; 3860 #else 3861 template <typename Func, typename U> 3862 using MapFunctionReturnType = typename std::remove_reference<typename std::remove_cv<typename std::result_of<Func(U)>::type>::type>::type; 3863 #endif 3864 3865 template <typename Func, typename U, typename T = MapFunctionReturnType<Func, U>> 3866 GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) { 3867 return GeneratorWrapper<T>( 3868 pf::make_unique<MapGenerator<T, U, Func>>(std::forward<Func>(function), std::move(generator)) 3869 ); 3870 } 3871 3872 template <typename T, typename U, typename Func> 3873 GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) { 3874 return GeneratorWrapper<T>( 3875 pf::make_unique<MapGenerator<T, U, Func>>(std::forward<Func>(function), std::move(generator)) 3876 ); 3877 } 3878 3879 template <typename T> 3880 class ChunkGenerator final : public IGenerator<std::vector<T>> { 3881 std::vector<T> m_chunk; 3882 size_t m_chunk_size; 3883 GeneratorWrapper<T> m_generator; 3884 bool m_used_up = false; 3885 public: 3886 ChunkGenerator(size_t size, GeneratorWrapper<T> generator) : 3887 m_chunk_size(size), m_generator(std::move(generator)) 3888 { 3889 m_chunk.reserve(m_chunk_size); 3890 m_chunk.push_back(m_generator.get()); 3891 for (size_t i = 1; i < m_chunk_size; ++i) { 3892 if (!m_generator.next()) { 3893 Catch::throw_exception(GeneratorException("Not enough values to initialize the first chunk")); 3894 } 3895 m_chunk.push_back(m_generator.get()); 3896 } 3897 } 3898 std::vector<T> const& get() const override { 3899 return m_chunk; 3900 } 3901 bool next() override { 3902 m_chunk.clear(); 3903 for (size_t idx = 0; idx < m_chunk_size; ++idx) { 3904 if (!m_generator.next()) { 3905 return false; 3906 } 3907 m_chunk.push_back(m_generator.get()); 3908 } 3909 return true; 3910 } 3911 }; 3912 3913 template <typename T> 3914 GeneratorWrapper<std::vector<T>> chunk(size_t size, GeneratorWrapper<T>&& generator) { 3915 return GeneratorWrapper<std::vector<T>>( 3916 pf::make_unique<ChunkGenerator<T>>(size, std::move(generator)) 3917 ); 3918 } 3919 3920 } // namespace Generators 3921 } // namespace Catch 3922 3923 // end catch_generators_generic.hpp 3924 // start catch_generators_specific.hpp 3925 3926 // start catch_context.h 3927 3928 #include <memory> 3929 3930 namespace Catch { 3931 3932 struct IResultCapture; 3933 struct IRunner; 3934 struct IConfig; 3935 struct IMutableContext; 3936 3937 using IConfigPtr = std::shared_ptr<IConfig const>; 3938 3939 struct IContext 3940 { 3941 virtual ~IContext(); 3942 3943 virtual IResultCapture* getResultCapture() = 0; 3944 virtual IRunner* getRunner() = 0; 3945 virtual IConfigPtr const& getConfig() const = 0; 3946 }; 3947 3948 struct IMutableContext : IContext 3949 { 3950 virtual ~IMutableContext(); 3951 virtual void setResultCapture( IResultCapture* resultCapture ) = 0; 3952 virtual void setRunner( IRunner* runner ) = 0; 3953 virtual void setConfig( IConfigPtr const& config ) = 0; 3954 3955 private: 3956 static IMutableContext *currentContext; 3957 friend IMutableContext& getCurrentMutableContext(); 3958 friend void cleanUpContext(); 3959 static void createContext(); 3960 }; 3961 3962 inline IMutableContext& getCurrentMutableContext() 3963 { 3964 if( !IMutableContext::currentContext ) 3965 IMutableContext::createContext(); 3966 return *IMutableContext::currentContext; 3967 } 3968 3969 inline IContext& getCurrentContext() 3970 { 3971 return getCurrentMutableContext(); 3972 } 3973 3974 void cleanUpContext(); 3975 } 3976 3977 // end catch_context.h 3978 // start catch_interfaces_config.h 3979 3980 #include <iosfwd> 3981 #include <string> 3982 #include <vector> 3983 #include <memory> 3984 3985 namespace Catch { 3986 3987 enum class Verbosity { 3988 Quiet = 0, 3989 Normal, 3990 High 3991 }; 3992 3993 struct WarnAbout { enum What { 3994 Nothing = 0x00, 3995 NoAssertions = 0x01, 3996 NoTests = 0x02 3997 }; }; 3998 3999 struct ShowDurations { enum OrNot { 4000 DefaultForReporter, 4001 Always, 4002 Never 4003 }; }; 4004 struct RunTests { enum InWhatOrder { 4005 InDeclarationOrder, 4006 InLexicographicalOrder, 4007 InRandomOrder 4008 }; }; 4009 struct UseColour { enum YesOrNo { 4010 Auto, 4011 Yes, 4012 No 4013 }; }; 4014 struct WaitForKeypress { enum When { 4015 Never, 4016 BeforeStart = 1, 4017 BeforeExit = 2, 4018 BeforeStartAndExit = BeforeStart | BeforeExit 4019 }; }; 4020 4021 class TestSpec; 4022 4023 struct IConfig : NonCopyable { 4024 4025 virtual ~IConfig(); 4026 4027 virtual bool allowThrows() const = 0; 4028 virtual std::ostream& stream() const = 0; 4029 virtual std::string name() const = 0; 4030 virtual bool includeSuccessfulResults() const = 0; 4031 virtual bool shouldDebugBreak() const = 0; 4032 virtual bool warnAboutMissingAssertions() const = 0; 4033 virtual bool warnAboutNoTests() const = 0; 4034 virtual int abortAfter() const = 0; 4035 virtual bool showInvisibles() const = 0; 4036 virtual ShowDurations::OrNot showDurations() const = 0; 4037 virtual TestSpec const& testSpec() const = 0; 4038 virtual bool hasTestFilters() const = 0; 4039 virtual std::vector<std::string> const& getTestsOrTags() const = 0; 4040 virtual RunTests::InWhatOrder runOrder() const = 0; 4041 virtual unsigned int rngSeed() const = 0; 4042 virtual int benchmarkResolutionMultiple() const = 0; 4043 virtual UseColour::YesOrNo useColour() const = 0; 4044 virtual std::vector<std::string> const& getSectionsToRun() const = 0; 4045 virtual Verbosity verbosity() const = 0; 4046 }; 4047 4048 using IConfigPtr = std::shared_ptr<IConfig const>; 4049 } 4050 4051 // end catch_interfaces_config.h 4052 #include <random> 4053 4054 namespace Catch { 4055 namespace Generators { 4056 4057 template <typename Float> 4058 class RandomFloatingGenerator final : public IGenerator<Float> { 4059 // FIXME: What is the right seed? 4060 std::minstd_rand m_rand; 4061 std::uniform_real_distribution<Float> m_dist; 4062 Float m_current_number; 4063 public: 4064 4065 RandomFloatingGenerator(Float a, Float b): 4066 m_rand(getCurrentContext().getConfig()->rngSeed()), 4067 m_dist(a, b) { 4068 static_cast<void>(next()); 4069 } 4070 4071 Float const& get() const override { 4072 return m_current_number; 4073 } 4074 bool next() override { 4075 m_current_number = m_dist(m_rand); 4076 return true; 4077 } 4078 }; 4079 4080 template <typename Integer> 4081 class RandomIntegerGenerator final : public IGenerator<Integer> { 4082 std::minstd_rand m_rand; 4083 std::uniform_int_distribution<Integer> m_dist; 4084 Integer m_current_number; 4085 public: 4086 4087 RandomIntegerGenerator(Integer a, Integer b): 4088 m_rand(getCurrentContext().getConfig()->rngSeed()), 4089 m_dist(a, b) { 4090 static_cast<void>(next()); 4091 } 4092 4093 Integer const& get() const override { 4094 return m_current_number; 4095 } 4096 bool next() override { 4097 m_current_number = m_dist(m_rand); 4098 return true; 4099 } 4100 }; 4101 4102 // TODO: Ideally this would be also constrained against the various char types, 4103 // but I don't expect users to run into that in practice. 4104 template <typename T> 4105 typename std::enable_if<std::is_integral<T>::value && !std::is_same<T, bool>::value, 4106 GeneratorWrapper<T>>::type 4107 random(T a, T b) { 4108 return GeneratorWrapper<T>( 4109 pf::make_unique<RandomIntegerGenerator<T>>(a, b) 4110 ); 4111 } 4112 4113 template <typename T> 4114 typename std::enable_if<std::is_floating_point<T>::value, 4115 GeneratorWrapper<T>>::type 4116 random(T a, T b) { 4117 return GeneratorWrapper<T>( 4118 pf::make_unique<RandomFloatingGenerator<T>>(a, b) 4119 ); 4120 } 4121 4122 template <typename T> 4123 class RangeGenerator final : public IGenerator<T> { 4124 T m_current; 4125 T m_end; 4126 T m_step; 4127 bool m_positive; 4128 4129 public: 4130 RangeGenerator(T const& start, T const& end, T const& step): 4131 m_current(start), 4132 m_end(end), 4133 m_step(step), 4134 m_positive(m_step > T(0)) 4135 { 4136 assert(m_current != m_end && "Range start and end cannot be equal"); 4137 assert(m_step != T(0) && "Step size cannot be zero"); 4138 assert(((m_positive && m_current <= m_end) || (!m_positive && m_current >= m_end)) && "Step moves away from end"); 4139 } 4140 4141 RangeGenerator(T const& start, T const& end): 4142 RangeGenerator(start, end, (start < end) ? T(1) : T(-1)) 4143 {} 4144 4145 T const& get() const override { 4146 return m_current; 4147 } 4148 4149 bool next() override { 4150 m_current += m_step; 4151 return (m_positive) ? (m_current < m_end) : (m_current > m_end); 4152 } 4153 }; 4154 4155 template <typename T> 4156 GeneratorWrapper<T> range(T const& start, T const& end, T const& step) { 4157 static_assert(std::is_integral<T>::value && !std::is_same<T, bool>::value, "Type must be an integer"); 4158 return GeneratorWrapper<T>(pf::make_unique<RangeGenerator<T>>(start, end, step)); 4159 } 4160 4161 template <typename T> 4162 GeneratorWrapper<T> range(T const& start, T const& end) { 4163 static_assert(std::is_integral<T>::value && !std::is_same<T, bool>::value, "Type must be an integer"); 4164 return GeneratorWrapper<T>(pf::make_unique<RangeGenerator<T>>(start, end)); 4165 } 4166 4167 } // namespace Generators 4168 } // namespace Catch 4169 4170 // end catch_generators_specific.hpp 4171 4172 // These files are included here so the single_include script doesn't put them 4173 // in the conditionally compiled sections 4174 // start catch_test_case_info.h 4175 4176 #include <string> 4177 #include <vector> 4178 #include <memory> 4179 4180 #ifdef __clang__ 4181 #pragma clang diagnostic push 4182 #pragma clang diagnostic ignored "-Wpadded" 4183 #endif 4184 4185 namespace Catch { 4186 4187 struct ITestInvoker; 4188 4189 struct TestCaseInfo { 4190 enum SpecialProperties{ 4191 None = 0, 4192 IsHidden = 1 << 1, 4193 ShouldFail = 1 << 2, 4194 MayFail = 1 << 3, 4195 Throws = 1 << 4, 4196 NonPortable = 1 << 5, 4197 Benchmark = 1 << 6 4198 }; 4199 4200 TestCaseInfo( std::string const& _name, 4201 std::string const& _className, 4202 std::string const& _description, 4203 std::vector<std::string> const& _tags, 4204 SourceLineInfo const& _lineInfo ); 4205 4206 friend void setTags( TestCaseInfo& testCaseInfo, std::vector<std::string> tags ); 4207 4208 bool isHidden() const; 4209 bool throws() const; 4210 bool okToFail() const; 4211 bool expectedToFail() const; 4212 4213 std::string tagsAsString() const; 4214 4215 std::string name; 4216 std::string className; 4217 std::string description; 4218 std::vector<std::string> tags; 4219 std::vector<std::string> lcaseTags; 4220 SourceLineInfo lineInfo; 4221 SpecialProperties properties; 4222 }; 4223 4224 class TestCase : public TestCaseInfo { 4225 public: 4226 4227 TestCase( ITestInvoker* testCase, TestCaseInfo&& info ); 4228 4229 TestCase withName( std::string const& _newName ) const; 4230 4231 void invoke() const; 4232 4233 TestCaseInfo const& getTestCaseInfo() const; 4234 4235 bool operator == ( TestCase const& other ) const; 4236 bool operator < ( TestCase const& other ) const; 4237 4238 private: 4239 std::shared_ptr<ITestInvoker> test; 4240 }; 4241 4242 TestCase makeTestCase( ITestInvoker* testCase, 4243 std::string const& className, 4244 NameAndTags const& nameAndTags, 4245 SourceLineInfo const& lineInfo ); 4246 } 4247 4248 #ifdef __clang__ 4249 #pragma clang diagnostic pop 4250 #endif 4251 4252 // end catch_test_case_info.h 4253 // start catch_interfaces_runner.h 4254 4255 namespace Catch { 4256 4257 struct IRunner { 4258 virtual ~IRunner(); 4259 virtual bool aborting() const = 0; 4260 }; 4261 } 4262 4263 // end catch_interfaces_runner.h 4264 4265 #ifdef __OBJC__ 4266 // start catch_objc.hpp 4267 4268 #import <objc/runtime.h> 4269 4270 #include <string> 4271 4272 // NB. Any general catch headers included here must be included 4273 // in catch.hpp first to make sure they are included by the single 4274 // header for non obj-usage 4275 4276 /////////////////////////////////////////////////////////////////////////////// 4277 // This protocol is really only here for (self) documenting purposes, since 4278 // all its methods are optional. 4279 @protocol OcFixture 4280 4281 @optional 4282 4283 -(void) setUp; 4284 -(void) tearDown; 4285 4286 @end 4287 4288 namespace Catch { 4289 4290 class OcMethod : public ITestInvoker { 4291 4292 public: 4293 OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} 4294 4295 virtual void invoke() const { 4296 id obj = [[m_cls alloc] init]; 4297 4298 performOptionalSelector( obj, @selector(setUp) ); 4299 performOptionalSelector( obj, m_sel ); 4300 performOptionalSelector( obj, @selector(tearDown) ); 4301 4302 arcSafeRelease( obj ); 4303 } 4304 private: 4305 virtual ~OcMethod() {} 4306 4307 Class m_cls; 4308 SEL m_sel; 4309 }; 4310 4311 namespace Detail{ 4312 4313 inline std::string getAnnotation( Class cls, 4314 std::string const& annotationName, 4315 std::string const& testCaseName ) { 4316 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()]; 4317 SEL sel = NSSelectorFromString( selStr ); 4318 arcSafeRelease( selStr ); 4319 id value = performOptionalSelector( cls, sel ); 4320 if( value ) 4321 return [(NSString*)value UTF8String]; 4322 return ""; 4323 } 4324 } 4325 4326 inline std::size_t registerTestMethods() { 4327 std::size_t noTestMethods = 0; 4328 int noClasses = objc_getClassList( nullptr, 0 ); 4329 4330 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); 4331 objc_getClassList( classes, noClasses ); 4332 4333 for( int c = 0; c < noClasses; c++ ) { 4334 Class cls = classes[c]; 4335 { 4336 u_int count; 4337 Method* methods = class_copyMethodList( cls, &count ); 4338 for( u_int m = 0; m < count ; m++ ) { 4339 SEL selector = method_getName(methods[m]); 4340 std::string methodName = sel_getName(selector); 4341 if( startsWith( methodName, "Catch_TestCase_" ) ) { 4342 std::string testCaseName = methodName.substr( 15 ); 4343 std::string name = Detail::getAnnotation( cls, "Name", testCaseName ); 4344 std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); 4345 const char* className = class_getName( cls ); 4346 4347 getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, NameAndTags( name.c_str(), desc.c_str() ), SourceLineInfo("",0) ) ); 4348 noTestMethods++; 4349 } 4350 } 4351 free(methods); 4352 } 4353 } 4354 return noTestMethods; 4355 } 4356 4357 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 4358 4359 namespace Matchers { 4360 namespace Impl { 4361 namespace NSStringMatchers { 4362 4363 struct StringHolder : MatcherBase<NSString*>{ 4364 StringHolder( NSString* substr ) : m_substr( [substr copy] ){} 4365 StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){} 4366 StringHolder() { 4367 arcSafeRelease( m_substr ); 4368 } 4369 4370 bool match( NSString* const& str ) const override { 4371 return false; 4372 } 4373 4374 NSString* CATCH_ARC_STRONG m_substr; 4375 }; 4376 4377 struct Equals : StringHolder { 4378 Equals( NSString* substr ) : StringHolder( substr ){} 4379 4380 bool match( NSString* const& str ) const override { 4381 return (str != nil || m_substr == nil ) && 4382 [str isEqualToString:m_substr]; 4383 } 4384 4385 std::string describe() const override { 4386 return "equals string: " + Catch::Detail::stringify( m_substr ); 4387 } 4388 }; 4389 4390 struct Contains : StringHolder { 4391 Contains( NSString* substr ) : StringHolder( substr ){} 4392 4393 bool match( NSString* const& str ) const override { 4394 return (str != nil || m_substr == nil ) && 4395 [str rangeOfString:m_substr].location != NSNotFound; 4396 } 4397 4398 std::string describe() const override { 4399 return "contains string: " + Catch::Detail::stringify( m_substr ); 4400 } 4401 }; 4402 4403 struct StartsWith : StringHolder { 4404 StartsWith( NSString* substr ) : StringHolder( substr ){} 4405 4406 bool match( NSString* const& str ) const override { 4407 return (str != nil || m_substr == nil ) && 4408 [str rangeOfString:m_substr].location == 0; 4409 } 4410 4411 std::string describe() const override { 4412 return "starts with: " + Catch::Detail::stringify( m_substr ); 4413 } 4414 }; 4415 struct EndsWith : StringHolder { 4416 EndsWith( NSString* substr ) : StringHolder( substr ){} 4417 4418 bool match( NSString* const& str ) const override { 4419 return (str != nil || m_substr == nil ) && 4420 [str rangeOfString:m_substr].location == [str length] - [m_substr length]; 4421 } 4422 4423 std::string describe() const override { 4424 return "ends with: " + Catch::Detail::stringify( m_substr ); 4425 } 4426 }; 4427 4428 } // namespace NSStringMatchers 4429 } // namespace Impl 4430 4431 inline Impl::NSStringMatchers::Equals 4432 Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); } 4433 4434 inline Impl::NSStringMatchers::Contains 4435 Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); } 4436 4437 inline Impl::NSStringMatchers::StartsWith 4438 StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); } 4439 4440 inline Impl::NSStringMatchers::EndsWith 4441 EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); } 4442 4443 } // namespace Matchers 4444 4445 using namespace Matchers; 4446 4447 #endif // CATCH_CONFIG_DISABLE_MATCHERS 4448 4449 } // namespace Catch 4450 4451 /////////////////////////////////////////////////////////////////////////////// 4452 #define OC_MAKE_UNIQUE_NAME( root, uniqueSuffix ) root##uniqueSuffix 4453 #define OC_TEST_CASE2( name, desc, uniqueSuffix ) \ 4454 +(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Name_test_, uniqueSuffix ) \ 4455 { \ 4456 return @ name; \ 4457 } \ 4458 +(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Description_test_, uniqueSuffix ) \ 4459 { \ 4460 return @ desc; \ 4461 } \ 4462 -(void) OC_MAKE_UNIQUE_NAME( Catch_TestCase_test_, uniqueSuffix ) 4463 4464 #define OC_TEST_CASE( name, desc ) OC_TEST_CASE2( name, desc, __LINE__ ) 4465 4466 // end catch_objc.hpp 4467 #endif 4468 4469 #ifdef CATCH_CONFIG_EXTERNAL_INTERFACES 4470 // start catch_external_interfaces.h 4471 4472 // start catch_reporter_bases.hpp 4473 4474 // start catch_interfaces_reporter.h 4475 4476 // start catch_config.hpp 4477 4478 // start catch_test_spec_parser.h 4479 4480 #ifdef __clang__ 4481 #pragma clang diagnostic push 4482 #pragma clang diagnostic ignored "-Wpadded" 4483 #endif 4484 4485 // start catch_test_spec.h 4486 4487 #ifdef __clang__ 4488 #pragma clang diagnostic push 4489 #pragma clang diagnostic ignored "-Wpadded" 4490 #endif 4491 4492 // start catch_wildcard_pattern.h 4493 4494 namespace Catch 4495 { 4496 class WildcardPattern { 4497 enum WildcardPosition { 4498 NoWildcard = 0, 4499 WildcardAtStart = 1, 4500 WildcardAtEnd = 2, 4501 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd 4502 }; 4503 4504 public: 4505 4506 WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity ); 4507 virtual ~WildcardPattern() = default; 4508 virtual bool matches( std::string const& str ) const; 4509 4510 private: 4511 std::string adjustCase( std::string const& str ) const; 4512 CaseSensitive::Choice m_caseSensitivity; 4513 WildcardPosition m_wildcard = NoWildcard; 4514 std::string m_pattern; 4515 }; 4516 } 4517 4518 // end catch_wildcard_pattern.h 4519 #include <string> 4520 #include <vector> 4521 #include <memory> 4522 4523 namespace Catch { 4524 4525 class TestSpec { 4526 struct Pattern { 4527 virtual ~Pattern(); 4528 virtual bool matches( TestCaseInfo const& testCase ) const = 0; 4529 }; 4530 using PatternPtr = std::shared_ptr<Pattern>; 4531 4532 class NamePattern : public Pattern { 4533 public: 4534 NamePattern( std::string const& name ); 4535 virtual ~NamePattern(); 4536 bool matches( TestCaseInfo const& testCase ) const override; 4537 private: 4538 WildcardPattern m_wildcardPattern; 4539 }; 4540 4541 class TagPattern : public Pattern { 4542 public: 4543 TagPattern( std::string const& tag ); 4544 virtual ~TagPattern(); 4545 bool matches( TestCaseInfo const& testCase ) const override; 4546 private: 4547 std::string m_tag; 4548 }; 4549 4550 class ExcludedPattern : public Pattern { 4551 public: 4552 ExcludedPattern( PatternPtr const& underlyingPattern ); 4553 virtual ~ExcludedPattern(); 4554 bool matches( TestCaseInfo const& testCase ) const override; 4555 private: 4556 PatternPtr m_underlyingPattern; 4557 }; 4558 4559 struct Filter { 4560 std::vector<PatternPtr> m_patterns; 4561 4562 bool matches( TestCaseInfo const& testCase ) const; 4563 }; 4564 4565 public: 4566 bool hasFilters() const; 4567 bool matches( TestCaseInfo const& testCase ) const; 4568 4569 private: 4570 std::vector<Filter> m_filters; 4571 4572 friend class TestSpecParser; 4573 }; 4574 } 4575 4576 #ifdef __clang__ 4577 #pragma clang diagnostic pop 4578 #endif 4579 4580 // end catch_test_spec.h 4581 // start catch_interfaces_tag_alias_registry.h 4582 4583 #include <string> 4584 4585 namespace Catch { 4586 4587 struct TagAlias; 4588 4589 struct ITagAliasRegistry { 4590 virtual ~ITagAliasRegistry(); 4591 // Nullptr if not present 4592 virtual TagAlias const* find( std::string const& alias ) const = 0; 4593 virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; 4594 4595 static ITagAliasRegistry const& get(); 4596 }; 4597 4598 } // end namespace Catch 4599 4600 // end catch_interfaces_tag_alias_registry.h 4601 namespace Catch { 4602 4603 class TestSpecParser { 4604 enum Mode{ None, Name, QuotedName, Tag, EscapedName }; 4605 Mode m_mode = None; 4606 bool m_exclusion = false; 4607 std::size_t m_start = std::string::npos, m_pos = 0; 4608 std::string m_arg; 4609 std::vector<std::size_t> m_escapeChars; 4610 TestSpec::Filter m_currentFilter; 4611 TestSpec m_testSpec; 4612 ITagAliasRegistry const* m_tagAliases = nullptr; 4613 4614 public: 4615 TestSpecParser( ITagAliasRegistry const& tagAliases ); 4616 4617 TestSpecParser& parse( std::string const& arg ); 4618 TestSpec testSpec(); 4619 4620 private: 4621 void visitChar( char c ); 4622 void startNewMode( Mode mode, std::size_t start ); 4623 void escape(); 4624 std::string subString() const; 4625 4626 template<typename T> 4627 void addPattern() { 4628 std::string token = subString(); 4629 for( std::size_t i = 0; i < m_escapeChars.size(); ++i ) 4630 token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 ); 4631 m_escapeChars.clear(); 4632 if( startsWith( token, "exclude:" ) ) { 4633 m_exclusion = true; 4634 token = token.substr( 8 ); 4635 } 4636 if( !token.empty() ) { 4637 TestSpec::PatternPtr pattern = std::make_shared<T>( token ); 4638 if( m_exclusion ) 4639 pattern = std::make_shared<TestSpec::ExcludedPattern>( pattern ); 4640 m_currentFilter.m_patterns.push_back( pattern ); 4641 } 4642 m_exclusion = false; 4643 m_mode = None; 4644 } 4645 4646 void addFilter(); 4647 }; 4648 TestSpec parseTestSpec( std::string const& arg ); 4649 4650 } // namespace Catch 4651 4652 #ifdef __clang__ 4653 #pragma clang diagnostic pop 4654 #endif 4655 4656 // end catch_test_spec_parser.h 4657 // Libstdc++ doesn't like incomplete classes for unique_ptr 4658 4659 #include <memory> 4660 #include <vector> 4661 #include <string> 4662 4663 #ifndef CATCH_CONFIG_CONSOLE_WIDTH 4664 #define CATCH_CONFIG_CONSOLE_WIDTH 80 4665 #endif 4666 4667 namespace Catch { 4668 4669 struct IStream; 4670 4671 struct ConfigData { 4672 bool listTests = false; 4673 bool listTags = false; 4674 bool listReporters = false; 4675 bool listTestNamesOnly = false; 4676 4677 bool showSuccessfulTests = false; 4678 bool shouldDebugBreak = false; 4679 bool noThrow = false; 4680 bool showHelp = false; 4681 bool showInvisibles = false; 4682 bool filenamesAsTags = false; 4683 bool libIdentify = false; 4684 4685 int abortAfter = -1; 4686 unsigned int rngSeed = 0; 4687 int benchmarkResolutionMultiple = 100; 4688 4689 Verbosity verbosity = Verbosity::Normal; 4690 WarnAbout::What warnings = WarnAbout::Nothing; 4691 ShowDurations::OrNot showDurations = ShowDurations::DefaultForReporter; 4692 RunTests::InWhatOrder runOrder = RunTests::InDeclarationOrder; 4693 UseColour::YesOrNo useColour = UseColour::Auto; 4694 WaitForKeypress::When waitForKeypress = WaitForKeypress::Never; 4695 4696 std::string outputFilename; 4697 std::string name; 4698 std::string processName; 4699 #ifndef CATCH_CONFIG_DEFAULT_REPORTER 4700 #define CATCH_CONFIG_DEFAULT_REPORTER "console" 4701 #endif 4702 std::string reporterName = CATCH_CONFIG_DEFAULT_REPORTER; 4703 #undef CATCH_CONFIG_DEFAULT_REPORTER 4704 4705 std::vector<std::string> testsOrTags; 4706 std::vector<std::string> sectionsToRun; 4707 }; 4708 4709 class Config : public IConfig { 4710 public: 4711 4712 Config() = default; 4713 Config( ConfigData const& data ); 4714 virtual ~Config() = default; 4715 4716 std::string const& getFilename() const; 4717 4718 bool listTests() const; 4719 bool listTestNamesOnly() const; 4720 bool listTags() const; 4721 bool listReporters() const; 4722 4723 std::string getProcessName() const; 4724 std::string const& getReporterName() const; 4725 4726 std::vector<std::string> const& getTestsOrTags() const override; 4727 std::vector<std::string> const& getSectionsToRun() const override; 4728 4729 TestSpec const& testSpec() const override; 4730 bool hasTestFilters() const override; 4731 4732 bool showHelp() const; 4733 4734 // IConfig interface 4735 bool allowThrows() const override; 4736 std::ostream& stream() const override; 4737 std::string name() const override; 4738 bool includeSuccessfulResults() const override; 4739 bool warnAboutMissingAssertions() const override; 4740 bool warnAboutNoTests() const override; 4741 ShowDurations::OrNot showDurations() const override; 4742 RunTests::InWhatOrder runOrder() const override; 4743 unsigned int rngSeed() const override; 4744 int benchmarkResolutionMultiple() const override; 4745 UseColour::YesOrNo useColour() const override; 4746 bool shouldDebugBreak() const override; 4747 int abortAfter() const override; 4748 bool showInvisibles() const override; 4749 Verbosity verbosity() const override; 4750 4751 private: 4752 4753 IStream const* openStream(); 4754 ConfigData m_data; 4755 4756 std::unique_ptr<IStream const> m_stream; 4757 TestSpec m_testSpec; 4758 bool m_hasTestFilters = false; 4759 }; 4760 4761 } // end namespace Catch 4762 4763 // end catch_config.hpp 4764 // start catch_assertionresult.h 4765 4766 #include <string> 4767 4768 namespace Catch { 4769 4770 struct AssertionResultData 4771 { 4772 AssertionResultData() = delete; 4773 4774 AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression ); 4775 4776 std::string message; 4777 mutable std::string reconstructedExpression; 4778 LazyExpression lazyExpression; 4779 ResultWas::OfType resultType; 4780 4781 std::string reconstructExpression() const; 4782 }; 4783 4784 class AssertionResult { 4785 public: 4786 AssertionResult() = delete; 4787 AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); 4788 4789 bool isOk() const; 4790 bool succeeded() const; 4791 ResultWas::OfType getResultType() const; 4792 bool hasExpression() const; 4793 bool hasMessage() const; 4794 std::string getExpression() const; 4795 std::string getExpressionInMacro() const; 4796 bool hasExpandedExpression() const; 4797 std::string getExpandedExpression() const; 4798 std::string getMessage() const; 4799 SourceLineInfo getSourceInfo() const; 4800 StringRef getTestMacroName() const; 4801 4802 //protected: 4803 AssertionInfo m_info; 4804 AssertionResultData m_resultData; 4805 }; 4806 4807 } // end namespace Catch 4808 4809 // end catch_assertionresult.h 4810 // start catch_option.hpp 4811 4812 namespace Catch { 4813 4814 // An optional type 4815 template<typename T> 4816 class Option { 4817 public: 4818 Option() : nullableValue( nullptr ) {} 4819 Option( T const& _value ) 4820 : nullableValue( new( storage ) T( _value ) ) 4821 {} 4822 Option( Option const& _other ) 4823 : nullableValue( _other ? new( storage ) T( *_other ) : nullptr ) 4824 {} 4825 4826 ~Option() { 4827 reset(); 4828 } 4829 4830 Option& operator= ( Option const& _other ) { 4831 if( &_other != this ) { 4832 reset(); 4833 if( _other ) 4834 nullableValue = new( storage ) T( *_other ); 4835 } 4836 return *this; 4837 } 4838 Option& operator = ( T const& _value ) { 4839 reset(); 4840 nullableValue = new( storage ) T( _value ); 4841 return *this; 4842 } 4843 4844 void reset() { 4845 if( nullableValue ) 4846 nullableValue->~T(); 4847 nullableValue = nullptr; 4848 } 4849 4850 T& operator*() { return *nullableValue; } 4851 T const& operator*() const { return *nullableValue; } 4852 T* operator->() { return nullableValue; } 4853 const T* operator->() const { return nullableValue; } 4854 4855 T valueOr( T const& defaultValue ) const { 4856 return nullableValue ? *nullableValue : defaultValue; 4857 } 4858 4859 bool some() const { return nullableValue != nullptr; } 4860 bool none() const { return nullableValue == nullptr; } 4861 4862 bool operator !() const { return nullableValue == nullptr; } 4863 explicit operator bool() const { 4864 return some(); 4865 } 4866 4867 private: 4868 T *nullableValue; 4869 alignas(alignof(T)) char storage[sizeof(T)]; 4870 }; 4871 4872 } // end namespace Catch 4873 4874 // end catch_option.hpp 4875 #include <string> 4876 #include <iosfwd> 4877 #include <map> 4878 #include <set> 4879 #include <memory> 4880 4881 namespace Catch { 4882 4883 struct ReporterConfig { 4884 explicit ReporterConfig( IConfigPtr const& _fullConfig ); 4885 4886 ReporterConfig( IConfigPtr const& _fullConfig, std::ostream& _stream ); 4887 4888 std::ostream& stream() const; 4889 IConfigPtr fullConfig() const; 4890 4891 private: 4892 std::ostream* m_stream; 4893 IConfigPtr m_fullConfig; 4894 }; 4895 4896 struct ReporterPreferences { 4897 bool shouldRedirectStdOut = false; 4898 bool shouldReportAllAssertions = false; 4899 }; 4900 4901 template<typename T> 4902 struct LazyStat : Option<T> { 4903 LazyStat& operator=( T const& _value ) { 4904 Option<T>::operator=( _value ); 4905 used = false; 4906 return *this; 4907 } 4908 void reset() { 4909 Option<T>::reset(); 4910 used = false; 4911 } 4912 bool used = false; 4913 }; 4914 4915 struct TestRunInfo { 4916 TestRunInfo( std::string const& _name ); 4917 std::string name; 4918 }; 4919 struct GroupInfo { 4920 GroupInfo( std::string const& _name, 4921 std::size_t _groupIndex, 4922 std::size_t _groupsCount ); 4923 4924 std::string name; 4925 std::size_t groupIndex; 4926 std::size_t groupsCounts; 4927 }; 4928 4929 struct AssertionStats { 4930 AssertionStats( AssertionResult const& _assertionResult, 4931 std::vector<MessageInfo> const& _infoMessages, 4932 Totals const& _totals ); 4933 4934 AssertionStats( AssertionStats const& ) = default; 4935 AssertionStats( AssertionStats && ) = default; 4936 AssertionStats& operator = ( AssertionStats const& ) = delete; 4937 AssertionStats& operator = ( AssertionStats && ) = delete; 4938 virtual ~AssertionStats(); 4939 4940 AssertionResult assertionResult; 4941 std::vector<MessageInfo> infoMessages; 4942 Totals totals; 4943 }; 4944 4945 struct SectionStats { 4946 SectionStats( SectionInfo const& _sectionInfo, 4947 Counts const& _assertions, 4948 double _durationInSeconds, 4949 bool _missingAssertions ); 4950 SectionStats( SectionStats const& ) = default; 4951 SectionStats( SectionStats && ) = default; 4952 SectionStats& operator = ( SectionStats const& ) = default; 4953 SectionStats& operator = ( SectionStats && ) = default; 4954 virtual ~SectionStats(); 4955 4956 SectionInfo sectionInfo; 4957 Counts assertions; 4958 double durationInSeconds; 4959 bool missingAssertions; 4960 }; 4961 4962 struct TestCaseStats { 4963 TestCaseStats( TestCaseInfo const& _testInfo, 4964 Totals const& _totals, 4965 std::string const& _stdOut, 4966 std::string const& _stdErr, 4967 bool _aborting ); 4968 4969 TestCaseStats( TestCaseStats const& ) = default; 4970 TestCaseStats( TestCaseStats && ) = default; 4971 TestCaseStats& operator = ( TestCaseStats const& ) = default; 4972 TestCaseStats& operator = ( TestCaseStats && ) = default; 4973 virtual ~TestCaseStats(); 4974 4975 TestCaseInfo testInfo; 4976 Totals totals; 4977 std::string stdOut; 4978 std::string stdErr; 4979 bool aborting; 4980 }; 4981 4982 struct TestGroupStats { 4983 TestGroupStats( GroupInfo const& _groupInfo, 4984 Totals const& _totals, 4985 bool _aborting ); 4986 TestGroupStats( GroupInfo const& _groupInfo ); 4987 4988 TestGroupStats( TestGroupStats const& ) = default; 4989 TestGroupStats( TestGroupStats && ) = default; 4990 TestGroupStats& operator = ( TestGroupStats const& ) = default; 4991 TestGroupStats& operator = ( TestGroupStats && ) = default; 4992 virtual ~TestGroupStats(); 4993 4994 GroupInfo groupInfo; 4995 Totals totals; 4996 bool aborting; 4997 }; 4998 4999 struct TestRunStats { 5000 TestRunStats( TestRunInfo const& _runInfo, 5001 Totals const& _totals, 5002 bool _aborting ); 5003 5004 TestRunStats( TestRunStats const& ) = default; 5005 TestRunStats( TestRunStats && ) = default; 5006 TestRunStats& operator = ( TestRunStats const& ) = default; 5007 TestRunStats& operator = ( TestRunStats && ) = default; 5008 virtual ~TestRunStats(); 5009 5010 TestRunInfo runInfo; 5011 Totals totals; 5012 bool aborting; 5013 }; 5014 5015 struct BenchmarkInfo { 5016 std::string name; 5017 }; 5018 struct BenchmarkStats { 5019 BenchmarkInfo info; 5020 std::size_t iterations; 5021 uint64_t elapsedTimeInNanoseconds; 5022 }; 5023 5024 struct IStreamingReporter { 5025 virtual ~IStreamingReporter() = default; 5026 5027 // Implementing class must also provide the following static methods: 5028 // static std::string getDescription(); 5029 // static std::set<Verbosity> getSupportedVerbosities() 5030 5031 virtual ReporterPreferences getPreferences() const = 0; 5032 5033 virtual void noMatchingTestCases( std::string const& spec ) = 0; 5034 5035 virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; 5036 virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0; 5037 5038 virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; 5039 virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; 5040 5041 // *** experimental *** 5042 virtual void benchmarkStarting( BenchmarkInfo const& ) {} 5043 5044 virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; 5045 5046 // The return value indicates if the messages buffer should be cleared: 5047 virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; 5048 5049 // *** experimental *** 5050 virtual void benchmarkEnded( BenchmarkStats const& ) {} 5051 5052 virtual void sectionEnded( SectionStats const& sectionStats ) = 0; 5053 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; 5054 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; 5055 virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; 5056 5057 virtual void skipTest( TestCaseInfo const& testInfo ) = 0; 5058 5059 // Default empty implementation provided 5060 virtual void fatalErrorEncountered( StringRef name ); 5061 5062 virtual bool isMulti() const; 5063 }; 5064 using IStreamingReporterPtr = std::unique_ptr<IStreamingReporter>; 5065 5066 struct IReporterFactory { 5067 virtual ~IReporterFactory(); 5068 virtual IStreamingReporterPtr create( ReporterConfig const& config ) const = 0; 5069 virtual std::string getDescription() const = 0; 5070 }; 5071 using IReporterFactoryPtr = std::shared_ptr<IReporterFactory>; 5072 5073 struct IReporterRegistry { 5074 using FactoryMap = std::map<std::string, IReporterFactoryPtr>; 5075 using Listeners = std::vector<IReporterFactoryPtr>; 5076 5077 virtual ~IReporterRegistry(); 5078 virtual IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const = 0; 5079 virtual FactoryMap const& getFactories() const = 0; 5080 virtual Listeners const& getListeners() const = 0; 5081 }; 5082 5083 } // end namespace Catch 5084 5085 // end catch_interfaces_reporter.h 5086 #include <algorithm> 5087 #include <cstring> 5088 #include <cfloat> 5089 #include <cstdio> 5090 #include <cassert> 5091 #include <memory> 5092 #include <ostream> 5093 5094 namespace Catch { 5095 void prepareExpandedExpression(AssertionResult& result); 5096 5097 // Returns double formatted as %.3f (format expected on output) 5098 std::string getFormattedDuration( double duration ); 5099 5100 std::string serializeFilters( std::vector<std::string> const& container ); 5101 5102 template<typename DerivedT> 5103 struct StreamingReporterBase : IStreamingReporter { 5104 5105 StreamingReporterBase( ReporterConfig const& _config ) 5106 : m_config( _config.fullConfig() ), 5107 stream( _config.stream() ) 5108 { 5109 m_reporterPrefs.shouldRedirectStdOut = false; 5110 if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) ) 5111 CATCH_ERROR( "Verbosity level not supported by this reporter" ); 5112 } 5113 5114 ReporterPreferences getPreferences() const override { 5115 return m_reporterPrefs; 5116 } 5117 5118 static std::set<Verbosity> getSupportedVerbosities() { 5119 return { Verbosity::Normal }; 5120 } 5121 5122 ~StreamingReporterBase() override = default; 5123 5124 void noMatchingTestCases(std::string const&) override {} 5125 5126 void testRunStarting(TestRunInfo const& _testRunInfo) override { 5127 currentTestRunInfo = _testRunInfo; 5128 } 5129 5130 void testGroupStarting(GroupInfo const& _groupInfo) override { 5131 currentGroupInfo = _groupInfo; 5132 } 5133 5134 void testCaseStarting(TestCaseInfo const& _testInfo) override { 5135 currentTestCaseInfo = _testInfo; 5136 } 5137 void sectionStarting(SectionInfo const& _sectionInfo) override { 5138 m_sectionStack.push_back(_sectionInfo); 5139 } 5140 5141 void sectionEnded(SectionStats const& /* _sectionStats */) override { 5142 m_sectionStack.pop_back(); 5143 } 5144 void testCaseEnded(TestCaseStats const& /* _testCaseStats */) override { 5145 currentTestCaseInfo.reset(); 5146 } 5147 void testGroupEnded(TestGroupStats const& /* _testGroupStats */) override { 5148 currentGroupInfo.reset(); 5149 } 5150 void testRunEnded(TestRunStats const& /* _testRunStats */) override { 5151 currentTestCaseInfo.reset(); 5152 currentGroupInfo.reset(); 5153 currentTestRunInfo.reset(); 5154 } 5155 5156 void skipTest(TestCaseInfo const&) override { 5157 // Don't do anything with this by default. 5158 // It can optionally be overridden in the derived class. 5159 } 5160 5161 IConfigPtr m_config; 5162 std::ostream& stream; 5163 5164 LazyStat<TestRunInfo> currentTestRunInfo; 5165 LazyStat<GroupInfo> currentGroupInfo; 5166 LazyStat<TestCaseInfo> currentTestCaseInfo; 5167 5168 std::vector<SectionInfo> m_sectionStack; 5169 ReporterPreferences m_reporterPrefs; 5170 }; 5171 5172 template<typename DerivedT> 5173 struct CumulativeReporterBase : IStreamingReporter { 5174 template<typename T, typename ChildNodeT> 5175 struct Node { 5176 explicit Node( T const& _value ) : value( _value ) {} 5177 virtual ~Node() {} 5178 5179 using ChildNodes = std::vector<std::shared_ptr<ChildNodeT>>; 5180 T value; 5181 ChildNodes children; 5182 }; 5183 struct SectionNode { 5184 explicit SectionNode(SectionStats const& _stats) : stats(_stats) {} 5185 virtual ~SectionNode() = default; 5186 5187 bool operator == (SectionNode const& other) const { 5188 return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; 5189 } 5190 bool operator == (std::shared_ptr<SectionNode> const& other) const { 5191 return operator==(*other); 5192 } 5193 5194 SectionStats stats; 5195 using ChildSections = std::vector<std::shared_ptr<SectionNode>>; 5196 using Assertions = std::vector<AssertionStats>; 5197 ChildSections childSections; 5198 Assertions assertions; 5199 std::string stdOut; 5200 std::string stdErr; 5201 }; 5202 5203 struct BySectionInfo { 5204 BySectionInfo( SectionInfo const& other ) : m_other( other ) {} 5205 BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {} 5206 bool operator() (std::shared_ptr<SectionNode> const& node) const { 5207 return ((node->stats.sectionInfo.name == m_other.name) && 5208 (node->stats.sectionInfo.lineInfo == m_other.lineInfo)); 5209 } 5210 void operator=(BySectionInfo const&) = delete; 5211 5212 private: 5213 SectionInfo const& m_other; 5214 }; 5215 5216 using TestCaseNode = Node<TestCaseStats, SectionNode>; 5217 using TestGroupNode = Node<TestGroupStats, TestCaseNode>; 5218 using TestRunNode = Node<TestRunStats, TestGroupNode>; 5219 5220 CumulativeReporterBase( ReporterConfig const& _config ) 5221 : m_config( _config.fullConfig() ), 5222 stream( _config.stream() ) 5223 { 5224 m_reporterPrefs.shouldRedirectStdOut = false; 5225 if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) ) 5226 CATCH_ERROR( "Verbosity level not supported by this reporter" ); 5227 } 5228 ~CumulativeReporterBase() override = default; 5229 5230 ReporterPreferences getPreferences() const override { 5231 return m_reporterPrefs; 5232 } 5233 5234 static std::set<Verbosity> getSupportedVerbosities() { 5235 return { Verbosity::Normal }; 5236 } 5237 5238 void testRunStarting( TestRunInfo const& ) override {} 5239 void testGroupStarting( GroupInfo const& ) override {} 5240 5241 void testCaseStarting( TestCaseInfo const& ) override {} 5242 5243 void sectionStarting( SectionInfo const& sectionInfo ) override { 5244 SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); 5245 std::shared_ptr<SectionNode> node; 5246 if( m_sectionStack.empty() ) { 5247 if( !m_rootSection ) 5248 m_rootSection = std::make_shared<SectionNode>( incompleteStats ); 5249 node = m_rootSection; 5250 } 5251 else { 5252 SectionNode& parentNode = *m_sectionStack.back(); 5253 auto it = 5254 std::find_if( parentNode.childSections.begin(), 5255 parentNode.childSections.end(), 5256 BySectionInfo( sectionInfo ) ); 5257 if( it == parentNode.childSections.end() ) { 5258 node = std::make_shared<SectionNode>( incompleteStats ); 5259 parentNode.childSections.push_back( node ); 5260 } 5261 else 5262 node = *it; 5263 } 5264 m_sectionStack.push_back( node ); 5265 m_deepestSection = std::move(node); 5266 } 5267 5268 void assertionStarting(AssertionInfo const&) override {} 5269 5270 bool assertionEnded(AssertionStats const& assertionStats) override { 5271 assert(!m_sectionStack.empty()); 5272 // AssertionResult holds a pointer to a temporary DecomposedExpression, 5273 // which getExpandedExpression() calls to build the expression string. 5274 // Our section stack copy of the assertionResult will likely outlive the 5275 // temporary, so it must be expanded or discarded now to avoid calling 5276 // a destroyed object later. 5277 prepareExpandedExpression(const_cast<AssertionResult&>( assertionStats.assertionResult ) ); 5278 SectionNode& sectionNode = *m_sectionStack.back(); 5279 sectionNode.assertions.push_back(assertionStats); 5280 return true; 5281 } 5282 void sectionEnded(SectionStats const& sectionStats) override { 5283 assert(!m_sectionStack.empty()); 5284 SectionNode& node = *m_sectionStack.back(); 5285 node.stats = sectionStats; 5286 m_sectionStack.pop_back(); 5287 } 5288 void testCaseEnded(TestCaseStats const& testCaseStats) override { 5289 auto node = std::make_shared<TestCaseNode>(testCaseStats); 5290 assert(m_sectionStack.size() == 0); 5291 node->children.push_back(m_rootSection); 5292 m_testCases.push_back(node); 5293 m_rootSection.reset(); 5294 5295 assert(m_deepestSection); 5296 m_deepestSection->stdOut = testCaseStats.stdOut; 5297 m_deepestSection->stdErr = testCaseStats.stdErr; 5298 } 5299 void testGroupEnded(TestGroupStats const& testGroupStats) override { 5300 auto node = std::make_shared<TestGroupNode>(testGroupStats); 5301 node->children.swap(m_testCases); 5302 m_testGroups.push_back(node); 5303 } 5304 void testRunEnded(TestRunStats const& testRunStats) override { 5305 auto node = std::make_shared<TestRunNode>(testRunStats); 5306 node->children.swap(m_testGroups); 5307 m_testRuns.push_back(node); 5308 testRunEndedCumulative(); 5309 } 5310 virtual void testRunEndedCumulative() = 0; 5311 5312 void skipTest(TestCaseInfo const&) override {} 5313 5314 IConfigPtr m_config; 5315 std::ostream& stream; 5316 std::vector<AssertionStats> m_assertions; 5317 std::vector<std::vector<std::shared_ptr<SectionNode>>> m_sections; 5318 std::vector<std::shared_ptr<TestCaseNode>> m_testCases; 5319 std::vector<std::shared_ptr<TestGroupNode>> m_testGroups; 5320 5321 std::vector<std::shared_ptr<TestRunNode>> m_testRuns; 5322 5323 std::shared_ptr<SectionNode> m_rootSection; 5324 std::shared_ptr<SectionNode> m_deepestSection; 5325 std::vector<std::shared_ptr<SectionNode>> m_sectionStack; 5326 ReporterPreferences m_reporterPrefs; 5327 }; 5328 5329 template<char C> 5330 char const* getLineOfChars() { 5331 static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0}; 5332 if( !*line ) { 5333 std::memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 ); 5334 line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0; 5335 } 5336 return line; 5337 } 5338 5339 struct TestEventListenerBase : StreamingReporterBase<TestEventListenerBase> { 5340 TestEventListenerBase( ReporterConfig const& _config ); 5341 5342 static std::set<Verbosity> getSupportedVerbosities(); 5343 5344 void assertionStarting(AssertionInfo const&) override; 5345 bool assertionEnded(AssertionStats const&) override; 5346 }; 5347 5348 } // end namespace Catch 5349 5350 // end catch_reporter_bases.hpp 5351 // start catch_console_colour.h 5352 5353 namespace Catch { 5354 5355 struct Colour { 5356 enum Code { 5357 None = 0, 5358 5359 White, 5360 Red, 5361 Green, 5362 Blue, 5363 Cyan, 5364 Yellow, 5365 Grey, 5366 5367 Bright = 0x10, 5368 5369 BrightRed = Bright | Red, 5370 BrightGreen = Bright | Green, 5371 LightGrey = Bright | Grey, 5372 BrightWhite = Bright | White, 5373 BrightYellow = Bright | Yellow, 5374 5375 // By intention 5376 FileName = LightGrey, 5377 Warning = BrightYellow, 5378 ResultError = BrightRed, 5379 ResultSuccess = BrightGreen, 5380 ResultExpectedFailure = Warning, 5381 5382 Error = BrightRed, 5383 Success = Green, 5384 5385 OriginalExpression = Cyan, 5386 ReconstructedExpression = BrightYellow, 5387 5388 SecondaryText = LightGrey, 5389 Headers = White 5390 }; 5391 5392 // Use constructed object for RAII guard 5393 Colour( Code _colourCode ); 5394 Colour( Colour&& other ) noexcept; 5395 Colour& operator=( Colour&& other ) noexcept; 5396 ~Colour(); 5397 5398 // Use static method for one-shot changes 5399 static void use( Code _colourCode ); 5400 5401 private: 5402 bool m_moved = false; 5403 }; 5404 5405 std::ostream& operator << ( std::ostream& os, Colour const& ); 5406 5407 } // end namespace Catch 5408 5409 // end catch_console_colour.h 5410 // start catch_reporter_registrars.hpp 5411 5412 5413 namespace Catch { 5414 5415 template<typename T> 5416 class ReporterRegistrar { 5417 5418 class ReporterFactory : public IReporterFactory { 5419 5420 IStreamingReporterPtr create( ReporterConfig const& config ) const override { 5421 return std::unique_ptr<T>( new T( config ) ); 5422 } 5423 5424 std::string getDescription() const override { 5425 return T::getDescription(); 5426 } 5427 }; 5428 5429 public: 5430 5431 explicit ReporterRegistrar( std::string const& name ) { 5432 getMutableRegistryHub().registerReporter( name, std::make_shared<ReporterFactory>() ); 5433 } 5434 }; 5435 5436 template<typename T> 5437 class ListenerRegistrar { 5438 5439 class ListenerFactory : public IReporterFactory { 5440 5441 IStreamingReporterPtr create( ReporterConfig const& config ) const override { 5442 return std::unique_ptr<T>( new T( config ) ); 5443 } 5444 std::string getDescription() const override { 5445 return std::string(); 5446 } 5447 }; 5448 5449 public: 5450 5451 ListenerRegistrar() { 5452 getMutableRegistryHub().registerListener( std::make_shared<ListenerFactory>() ); 5453 } 5454 }; 5455 } 5456 5457 #if !defined(CATCH_CONFIG_DISABLE) 5458 5459 #define CATCH_REGISTER_REPORTER( name, reporterType ) \ 5460 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 5461 namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); } \ 5462 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS 5463 5464 #define CATCH_REGISTER_LISTENER( listenerType ) \ 5465 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 5466 namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; } \ 5467 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS 5468 #else // CATCH_CONFIG_DISABLE 5469 5470 #define CATCH_REGISTER_REPORTER(name, reporterType) 5471 #define CATCH_REGISTER_LISTENER(listenerType) 5472 5473 #endif // CATCH_CONFIG_DISABLE 5474 5475 // end catch_reporter_registrars.hpp 5476 // Allow users to base their work off existing reporters 5477 // start catch_reporter_compact.h 5478 5479 namespace Catch { 5480 5481 struct CompactReporter : StreamingReporterBase<CompactReporter> { 5482 5483 using StreamingReporterBase::StreamingReporterBase; 5484 5485 ~CompactReporter() override; 5486 5487 static std::string getDescription(); 5488 5489 ReporterPreferences getPreferences() const override; 5490 5491 void noMatchingTestCases(std::string const& spec) override; 5492 5493 void assertionStarting(AssertionInfo const&) override; 5494 5495 bool assertionEnded(AssertionStats const& _assertionStats) override; 5496 5497 void sectionEnded(SectionStats const& _sectionStats) override; 5498 5499 void testRunEnded(TestRunStats const& _testRunStats) override; 5500 5501 }; 5502 5503 } // end namespace Catch 5504 5505 // end catch_reporter_compact.h 5506 // start catch_reporter_console.h 5507 5508 #if defined(_MSC_VER) 5509 #pragma warning(push) 5510 #pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch 5511 // Note that 4062 (not all labels are handled 5512 // and default is missing) is enabled 5513 #endif 5514 5515 namespace Catch { 5516 // Fwd decls 5517 struct SummaryColumn; 5518 class TablePrinter; 5519 5520 struct ConsoleReporter : StreamingReporterBase<ConsoleReporter> { 5521 std::unique_ptr<TablePrinter> m_tablePrinter; 5522 5523 ConsoleReporter(ReporterConfig const& config); 5524 ~ConsoleReporter() override; 5525 static std::string getDescription(); 5526 5527 void noMatchingTestCases(std::string const& spec) override; 5528 5529 void assertionStarting(AssertionInfo const&) override; 5530 5531 bool assertionEnded(AssertionStats const& _assertionStats) override; 5532 5533 void sectionStarting(SectionInfo const& _sectionInfo) override; 5534 void sectionEnded(SectionStats const& _sectionStats) override; 5535 5536 void benchmarkStarting(BenchmarkInfo const& info) override; 5537 void benchmarkEnded(BenchmarkStats const& stats) override; 5538 5539 void testCaseEnded(TestCaseStats const& _testCaseStats) override; 5540 void testGroupEnded(TestGroupStats const& _testGroupStats) override; 5541 void testRunEnded(TestRunStats const& _testRunStats) override; 5542 void testRunStarting(TestRunInfo const& _testRunInfo) override; 5543 private: 5544 5545 void lazyPrint(); 5546 5547 void lazyPrintWithoutClosingBenchmarkTable(); 5548 void lazyPrintRunInfo(); 5549 void lazyPrintGroupInfo(); 5550 void printTestCaseAndSectionHeader(); 5551 5552 void printClosedHeader(std::string const& _name); 5553 void printOpenHeader(std::string const& _name); 5554 5555 // if string has a : in first line will set indent to follow it on 5556 // subsequent lines 5557 void printHeaderString(std::string const& _string, std::size_t indent = 0); 5558 5559 void printTotals(Totals const& totals); 5560 void printSummaryRow(std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row); 5561 5562 void printTotalsDivider(Totals const& totals); 5563 void printSummaryDivider(); 5564 void printTestFilters(); 5565 5566 private: 5567 bool m_headerPrinted = false; 5568 }; 5569 5570 } // end namespace Catch 5571 5572 #if defined(_MSC_VER) 5573 #pragma warning(pop) 5574 #endif 5575 5576 // end catch_reporter_console.h 5577 // start catch_reporter_junit.h 5578 5579 // start catch_xmlwriter.h 5580 5581 #include <vector> 5582 5583 namespace Catch { 5584 5585 class XmlEncode { 5586 public: 5587 enum ForWhat { ForTextNodes, ForAttributes }; 5588 5589 XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes ); 5590 5591 void encodeTo( std::ostream& os ) const; 5592 5593 friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ); 5594 5595 private: 5596 std::string m_str; 5597 ForWhat m_forWhat; 5598 }; 5599 5600 class XmlWriter { 5601 public: 5602 5603 class ScopedElement { 5604 public: 5605 ScopedElement( XmlWriter* writer ); 5606 5607 ScopedElement( ScopedElement&& other ) noexcept; 5608 ScopedElement& operator=( ScopedElement&& other ) noexcept; 5609 5610 ~ScopedElement(); 5611 5612 ScopedElement& writeText( std::string const& text, bool indent = true ); 5613 5614 template<typename T> 5615 ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { 5616 m_writer->writeAttribute( name, attribute ); 5617 return *this; 5618 } 5619 5620 private: 5621 mutable XmlWriter* m_writer = nullptr; 5622 }; 5623 5624 XmlWriter( std::ostream& os = Catch::cout() ); 5625 ~XmlWriter(); 5626 5627 XmlWriter( XmlWriter const& ) = delete; 5628 XmlWriter& operator=( XmlWriter const& ) = delete; 5629 5630 XmlWriter& startElement( std::string const& name ); 5631 5632 ScopedElement scopedElement( std::string const& name ); 5633 5634 XmlWriter& endElement(); 5635 5636 XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ); 5637 5638 XmlWriter& writeAttribute( std::string const& name, bool attribute ); 5639 5640 template<typename T> 5641 XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { 5642 ReusableStringStream rss; 5643 rss << attribute; 5644 return writeAttribute( name, rss.str() ); 5645 } 5646 5647 XmlWriter& writeText( std::string const& text, bool indent = true ); 5648 5649 XmlWriter& writeComment( std::string const& text ); 5650 5651 void writeStylesheetRef( std::string const& url ); 5652 5653 XmlWriter& writeBlankLine(); 5654 5655 void ensureTagClosed(); 5656 5657 private: 5658 5659 void writeDeclaration(); 5660 5661 void newlineIfNecessary(); 5662 5663 bool m_tagIsOpen = false; 5664 bool m_needsNewline = false; 5665 std::vector<std::string> m_tags; 5666 std::string m_indent; 5667 std::ostream& m_os; 5668 }; 5669 5670 } 5671 5672 // end catch_xmlwriter.h 5673 namespace Catch { 5674 5675 class JunitReporter : public CumulativeReporterBase<JunitReporter> { 5676 public: 5677 JunitReporter(ReporterConfig const& _config); 5678 5679 ~JunitReporter() override; 5680 5681 static std::string getDescription(); 5682 5683 void noMatchingTestCases(std::string const& /*spec*/) override; 5684 5685 void testRunStarting(TestRunInfo const& runInfo) override; 5686 5687 void testGroupStarting(GroupInfo const& groupInfo) override; 5688 5689 void testCaseStarting(TestCaseInfo const& testCaseInfo) override; 5690 bool assertionEnded(AssertionStats const& assertionStats) override; 5691 5692 void testCaseEnded(TestCaseStats const& testCaseStats) override; 5693 5694 void testGroupEnded(TestGroupStats const& testGroupStats) override; 5695 5696 void testRunEndedCumulative() override; 5697 5698 void writeGroup(TestGroupNode const& groupNode, double suiteTime); 5699 5700 void writeTestCase(TestCaseNode const& testCaseNode); 5701 5702 void writeSection(std::string const& className, 5703 std::string const& rootName, 5704 SectionNode const& sectionNode); 5705 5706 void writeAssertions(SectionNode const& sectionNode); 5707 void writeAssertion(AssertionStats const& stats); 5708 5709 XmlWriter xml; 5710 Timer suiteTimer; 5711 std::string stdOutForSuite; 5712 std::string stdErrForSuite; 5713 unsigned int unexpectedExceptions = 0; 5714 bool m_okToFail = false; 5715 }; 5716 5717 } // end namespace Catch 5718 5719 // end catch_reporter_junit.h 5720 // start catch_reporter_xml.h 5721 5722 namespace Catch { 5723 class XmlReporter : public StreamingReporterBase<XmlReporter> { 5724 public: 5725 XmlReporter(ReporterConfig const& _config); 5726 5727 ~XmlReporter() override; 5728 5729 static std::string getDescription(); 5730 5731 virtual std::string getStylesheetRef() const; 5732 5733 void writeSourceInfo(SourceLineInfo const& sourceInfo); 5734 5735 public: // StreamingReporterBase 5736 5737 void noMatchingTestCases(std::string const& s) override; 5738 5739 void testRunStarting(TestRunInfo const& testInfo) override; 5740 5741 void testGroupStarting(GroupInfo const& groupInfo) override; 5742 5743 void testCaseStarting(TestCaseInfo const& testInfo) override; 5744 5745 void sectionStarting(SectionInfo const& sectionInfo) override; 5746 5747 void assertionStarting(AssertionInfo const&) override; 5748 5749 bool assertionEnded(AssertionStats const& assertionStats) override; 5750 5751 void sectionEnded(SectionStats const& sectionStats) override; 5752 5753 void testCaseEnded(TestCaseStats const& testCaseStats) override; 5754 5755 void testGroupEnded(TestGroupStats const& testGroupStats) override; 5756 5757 void testRunEnded(TestRunStats const& testRunStats) override; 5758 5759 private: 5760 Timer m_testCaseTimer; 5761 XmlWriter m_xml; 5762 int m_sectionDepth = 0; 5763 }; 5764 5765 } // end namespace Catch 5766 5767 // end catch_reporter_xml.h 5768 5769 // end catch_external_interfaces.h 5770 #endif 5771 5772 #endif // ! CATCH_CONFIG_IMPL_ONLY 5773 5774 #ifdef CATCH_IMPL 5775 // start catch_impl.hpp 5776 5777 #ifdef __clang__ 5778 #pragma clang diagnostic push 5779 #pragma clang diagnostic ignored "-Wweak-vtables" 5780 #endif 5781 5782 // Keep these here for external reporters 5783 // start catch_test_case_tracker.h 5784 5785 #include <string> 5786 #include <vector> 5787 #include <memory> 5788 5789 namespace Catch { 5790 namespace TestCaseTracking { 5791 5792 struct NameAndLocation { 5793 std::string name; 5794 SourceLineInfo location; 5795 5796 NameAndLocation( std::string const& _name, SourceLineInfo const& _location ); 5797 }; 5798 5799 struct ITracker; 5800 5801 using ITrackerPtr = std::shared_ptr<ITracker>; 5802 5803 struct ITracker { 5804 virtual ~ITracker(); 5805 5806 // static queries 5807 virtual NameAndLocation const& nameAndLocation() const = 0; 5808 5809 // dynamic queries 5810 virtual bool isComplete() const = 0; // Successfully completed or failed 5811 virtual bool isSuccessfullyCompleted() const = 0; 5812 virtual bool isOpen() const = 0; // Started but not complete 5813 virtual bool hasChildren() const = 0; 5814 5815 virtual ITracker& parent() = 0; 5816 5817 // actions 5818 virtual void close() = 0; // Successfully complete 5819 virtual void fail() = 0; 5820 virtual void markAsNeedingAnotherRun() = 0; 5821 5822 virtual void addChild( ITrackerPtr const& child ) = 0; 5823 virtual ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) = 0; 5824 virtual void openChild() = 0; 5825 5826 // Debug/ checking 5827 virtual bool isSectionTracker() const = 0; 5828 virtual bool isGeneratorTracker() const = 0; 5829 }; 5830 5831 class TrackerContext { 5832 5833 enum RunState { 5834 NotStarted, 5835 Executing, 5836 CompletedCycle 5837 }; 5838 5839 ITrackerPtr m_rootTracker; 5840 ITracker* m_currentTracker = nullptr; 5841 RunState m_runState = NotStarted; 5842 5843 public: 5844 5845 ITracker& startRun(); 5846 void endRun(); 5847 5848 void startCycle(); 5849 void completeCycle(); 5850 5851 bool completedCycle() const; 5852 ITracker& currentTracker(); 5853 void setCurrentTracker( ITracker* tracker ); 5854 }; 5855 5856 class TrackerBase : public ITracker { 5857 protected: 5858 enum CycleState { 5859 NotStarted, 5860 Executing, 5861 ExecutingChildren, 5862 NeedsAnotherRun, 5863 CompletedSuccessfully, 5864 Failed 5865 }; 5866 5867 using Children = std::vector<ITrackerPtr>; 5868 NameAndLocation m_nameAndLocation; 5869 TrackerContext& m_ctx; 5870 ITracker* m_parent; 5871 Children m_children; 5872 CycleState m_runState = NotStarted; 5873 5874 public: 5875 TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ); 5876 5877 NameAndLocation const& nameAndLocation() const override; 5878 bool isComplete() const override; 5879 bool isSuccessfullyCompleted() const override; 5880 bool isOpen() const override; 5881 bool hasChildren() const override; 5882 5883 void addChild( ITrackerPtr const& child ) override; 5884 5885 ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) override; 5886 ITracker& parent() override; 5887 5888 void openChild() override; 5889 5890 bool isSectionTracker() const override; 5891 bool isGeneratorTracker() const override; 5892 5893 void open(); 5894 5895 void close() override; 5896 void fail() override; 5897 void markAsNeedingAnotherRun() override; 5898 5899 private: 5900 void moveToParent(); 5901 void moveToThis(); 5902 }; 5903 5904 class SectionTracker : public TrackerBase { 5905 std::vector<std::string> m_filters; 5906 public: 5907 SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ); 5908 5909 bool isSectionTracker() const override; 5910 5911 bool isComplete() const override; 5912 5913 static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ); 5914 5915 void tryOpen(); 5916 5917 void addInitialFilters( std::vector<std::string> const& filters ); 5918 void addNextFilters( std::vector<std::string> const& filters ); 5919 }; 5920 5921 } // namespace TestCaseTracking 5922 5923 using TestCaseTracking::ITracker; 5924 using TestCaseTracking::TrackerContext; 5925 using TestCaseTracking::SectionTracker; 5926 5927 } // namespace Catch 5928 5929 // end catch_test_case_tracker.h 5930 5931 // start catch_leak_detector.h 5932 5933 namespace Catch { 5934 5935 struct LeakDetector { 5936 LeakDetector(); 5937 ~LeakDetector(); 5938 }; 5939 5940 } 5941 // end catch_leak_detector.h 5942 // Cpp files will be included in the single-header file here 5943 // start catch_approx.cpp 5944 5945 #include <cmath> 5946 #include <limits> 5947 5948 namespace { 5949 5950 // Performs equivalent check of std::fabs(lhs - rhs) <= margin 5951 // But without the subtraction to allow for INFINITY in comparison 5952 bool marginComparison(double lhs, double rhs, double margin) { 5953 return (lhs + margin >= rhs) && (rhs + margin >= lhs); 5954 } 5955 5956 } 5957 5958 namespace Catch { 5959 namespace Detail { 5960 5961 Approx::Approx ( double value ) 5962 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ), 5963 m_margin( 0.0 ), 5964 m_scale( 0.0 ), 5965 m_value( value ) 5966 {} 5967 5968 Approx Approx::custom() { 5969 return Approx( 0 ); 5970 } 5971 5972 Approx Approx::operator-() const { 5973 auto temp(*this); 5974 temp.m_value = -temp.m_value; 5975 return temp; 5976 } 5977 5978 std::string Approx::toString() const { 5979 ReusableStringStream rss; 5980 rss << "Approx( " << ::Catch::Detail::stringify( m_value ) << " )"; 5981 return rss.str(); 5982 } 5983 5984 bool Approx::equalityComparisonImpl(const double other) const { 5985 // First try with fixed margin, then compute margin based on epsilon, scale and Approx's value 5986 // Thanks to Richard Harris for his help refining the scaled margin value 5987 return marginComparison(m_value, other, m_margin) || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(m_value))); 5988 } 5989 5990 void Approx::setMargin(double newMargin) { 5991 CATCH_ENFORCE(newMargin >= 0, 5992 "Invalid Approx::margin: " << newMargin << '.' 5993 << " Approx::Margin has to be non-negative."); 5994 m_margin = newMargin; 5995 } 5996 5997 void Approx::setEpsilon(double newEpsilon) { 5998 CATCH_ENFORCE(newEpsilon >= 0 && newEpsilon <= 1.0, 5999 "Invalid Approx::epsilon: " << newEpsilon << '.' 6000 << " Approx::epsilon has to be in [0, 1]"); 6001 m_epsilon = newEpsilon; 6002 } 6003 6004 } // end namespace Detail 6005 6006 namespace literals { 6007 Detail::Approx operator "" _a(long double val) { 6008 return Detail::Approx(val); 6009 } 6010 Detail::Approx operator "" _a(unsigned long long val) { 6011 return Detail::Approx(val); 6012 } 6013 } // end namespace literals 6014 6015 std::string StringMaker<Catch::Detail::Approx>::convert(Catch::Detail::Approx const& value) { 6016 return value.toString(); 6017 } 6018 6019 } // end namespace Catch 6020 // end catch_approx.cpp 6021 // start catch_assertionhandler.cpp 6022 6023 // start catch_debugger.h 6024 6025 namespace Catch { 6026 bool isDebuggerActive(); 6027 } 6028 6029 #ifdef CATCH_PLATFORM_MAC 6030 6031 #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */ 6032 6033 #elif defined(CATCH_PLATFORM_LINUX) 6034 // If we can use inline assembler, do it because this allows us to break 6035 // directly at the location of the failing check instead of breaking inside 6036 // raise() called from it, i.e. one stack frame below. 6037 #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64)) 6038 #define CATCH_TRAP() asm volatile ("int $3") /* NOLINT */ 6039 #else // Fall back to the generic way. 6040 #include <signal.h> 6041 6042 #define CATCH_TRAP() raise(SIGTRAP) 6043 #endif 6044 #elif defined(_MSC_VER) 6045 #define CATCH_TRAP() __debugbreak() 6046 #elif defined(__MINGW32__) 6047 extern "C" __declspec(dllimport) void __stdcall DebugBreak(); 6048 #define CATCH_TRAP() DebugBreak() 6049 #endif 6050 6051 #ifdef CATCH_TRAP 6052 #define CATCH_BREAK_INTO_DEBUGGER() []{ if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } }() 6053 #else 6054 #define CATCH_BREAK_INTO_DEBUGGER() []{}() 6055 #endif 6056 6057 // end catch_debugger.h 6058 // start catch_run_context.h 6059 6060 // start catch_fatal_condition.h 6061 6062 // start catch_windows_h_proxy.h 6063 6064 6065 #if defined(CATCH_PLATFORM_WINDOWS) 6066 6067 #if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX) 6068 # define CATCH_DEFINED_NOMINMAX 6069 # define NOMINMAX 6070 #endif 6071 #if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN) 6072 # define CATCH_DEFINED_WIN32_LEAN_AND_MEAN 6073 # define WIN32_LEAN_AND_MEAN 6074 #endif 6075 6076 #ifdef __AFXDLL 6077 #include <AfxWin.h> 6078 #else 6079 #include <windows.h> 6080 #endif 6081 6082 #ifdef CATCH_DEFINED_NOMINMAX 6083 # undef NOMINMAX 6084 #endif 6085 #ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN 6086 # undef WIN32_LEAN_AND_MEAN 6087 #endif 6088 6089 #endif // defined(CATCH_PLATFORM_WINDOWS) 6090 6091 // end catch_windows_h_proxy.h 6092 #if defined( CATCH_CONFIG_WINDOWS_SEH ) 6093 6094 namespace Catch { 6095 6096 struct FatalConditionHandler { 6097 6098 static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo); 6099 FatalConditionHandler(); 6100 static void reset(); 6101 ~FatalConditionHandler(); 6102 6103 private: 6104 static bool isSet; 6105 static ULONG guaranteeSize; 6106 static PVOID exceptionHandlerHandle; 6107 }; 6108 6109 } // namespace Catch 6110 6111 #elif defined ( CATCH_CONFIG_POSIX_SIGNALS ) 6112 6113 #include <signal.h> 6114 6115 namespace Catch { 6116 6117 struct FatalConditionHandler { 6118 6119 static bool isSet; 6120 static struct sigaction oldSigActions[]; 6121 static stack_t oldSigStack; 6122 static char altStackMem[]; 6123 6124 static void handleSignal( int sig ); 6125 6126 FatalConditionHandler(); 6127 ~FatalConditionHandler(); 6128 static void reset(); 6129 }; 6130 6131 } // namespace Catch 6132 6133 #else 6134 6135 namespace Catch { 6136 struct FatalConditionHandler { 6137 void reset(); 6138 }; 6139 } 6140 6141 #endif 6142 6143 // end catch_fatal_condition.h 6144 #include <string> 6145 6146 namespace Catch { 6147 6148 struct IMutableContext; 6149 6150 /////////////////////////////////////////////////////////////////////////// 6151 6152 class RunContext : public IResultCapture, public IRunner { 6153 6154 public: 6155 RunContext( RunContext const& ) = delete; 6156 RunContext& operator =( RunContext const& ) = delete; 6157 6158 explicit RunContext( IConfigPtr const& _config, IStreamingReporterPtr&& reporter ); 6159 6160 ~RunContext() override; 6161 6162 void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ); 6163 void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ); 6164 6165 Totals runTest(TestCase const& testCase); 6166 6167 IConfigPtr config() const; 6168 IStreamingReporter& reporter() const; 6169 6170 public: // IResultCapture 6171 6172 // Assertion handlers 6173 void handleExpr 6174 ( AssertionInfo const& info, 6175 ITransientExpression const& expr, 6176 AssertionReaction& reaction ) override; 6177 void handleMessage 6178 ( AssertionInfo const& info, 6179 ResultWas::OfType resultType, 6180 StringRef const& message, 6181 AssertionReaction& reaction ) override; 6182 void handleUnexpectedExceptionNotThrown 6183 ( AssertionInfo const& info, 6184 AssertionReaction& reaction ) override; 6185 void handleUnexpectedInflightException 6186 ( AssertionInfo const& info, 6187 std::string const& message, 6188 AssertionReaction& reaction ) override; 6189 void handleIncomplete 6190 ( AssertionInfo const& info ) override; 6191 void handleNonExpr 6192 ( AssertionInfo const &info, 6193 ResultWas::OfType resultType, 6194 AssertionReaction &reaction ) override; 6195 6196 bool sectionStarted( SectionInfo const& sectionInfo, Counts& assertions ) override; 6197 6198 void sectionEnded( SectionEndInfo const& endInfo ) override; 6199 void sectionEndedEarly( SectionEndInfo const& endInfo ) override; 6200 6201 auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& override; 6202 6203 void benchmarkStarting( BenchmarkInfo const& info ) override; 6204 void benchmarkEnded( BenchmarkStats const& stats ) override; 6205 6206 void pushScopedMessage( MessageInfo const& message ) override; 6207 void popScopedMessage( MessageInfo const& message ) override; 6208 6209 void emplaceUnscopedMessage( MessageBuilder const& builder ) override; 6210 6211 std::string getCurrentTestName() const override; 6212 6213 const AssertionResult* getLastResult() const override; 6214 6215 void exceptionEarlyReported() override; 6216 6217 void handleFatalErrorCondition( StringRef message ) override; 6218 6219 bool lastAssertionPassed() override; 6220 6221 void assertionPassed() override; 6222 6223 public: 6224 // !TBD We need to do this another way! 6225 bool aborting() const final; 6226 6227 private: 6228 6229 void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ); 6230 void invokeActiveTestCase(); 6231 6232 void resetAssertionInfo(); 6233 bool testForMissingAssertions( Counts& assertions ); 6234 6235 void assertionEnded( AssertionResult const& result ); 6236 void reportExpr 6237 ( AssertionInfo const &info, 6238 ResultWas::OfType resultType, 6239 ITransientExpression const *expr, 6240 bool negated ); 6241 6242 void populateReaction( AssertionReaction& reaction ); 6243 6244 private: 6245 6246 void handleUnfinishedSections(); 6247 6248 TestRunInfo m_runInfo; 6249 IMutableContext& m_context; 6250 TestCase const* m_activeTestCase = nullptr; 6251 ITracker* m_testCaseTracker = nullptr; 6252 Option<AssertionResult> m_lastResult; 6253 6254 IConfigPtr m_config; 6255 Totals m_totals; 6256 IStreamingReporterPtr m_reporter; 6257 std::vector<MessageInfo> m_messages; 6258 std::vector<ScopedMessage> m_messageScopes; /* Keeps owners of so-called unscoped messages. */ 6259 AssertionInfo m_lastAssertionInfo; 6260 std::vector<SectionEndInfo> m_unfinishedSections; 6261 std::vector<ITracker*> m_activeSections; 6262 TrackerContext m_trackerContext; 6263 bool m_lastAssertionPassed = false; 6264 bool m_shouldReportUnexpected = true; 6265 bool m_includeSuccessfulResults; 6266 }; 6267 6268 } // end namespace Catch 6269 6270 // end catch_run_context.h 6271 namespace Catch { 6272 6273 namespace { 6274 auto operator <<( std::ostream& os, ITransientExpression const& expr ) -> std::ostream& { 6275 expr.streamReconstructedExpression( os ); 6276 return os; 6277 } 6278 } 6279 6280 LazyExpression::LazyExpression( bool isNegated ) 6281 : m_isNegated( isNegated ) 6282 {} 6283 6284 LazyExpression::LazyExpression( LazyExpression const& other ) : m_isNegated( other.m_isNegated ) {} 6285 6286 LazyExpression::operator bool() const { 6287 return m_transientExpression != nullptr; 6288 } 6289 6290 auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream& { 6291 if( lazyExpr.m_isNegated ) 6292 os << "!"; 6293 6294 if( lazyExpr ) { 6295 if( lazyExpr.m_isNegated && lazyExpr.m_transientExpression->isBinaryExpression() ) 6296 os << "(" << *lazyExpr.m_transientExpression << ")"; 6297 else 6298 os << *lazyExpr.m_transientExpression; 6299 } 6300 else { 6301 os << "{** error - unchecked empty expression requested **}"; 6302 } 6303 return os; 6304 } 6305 6306 AssertionHandler::AssertionHandler 6307 ( StringRef const& macroName, 6308 SourceLineInfo const& lineInfo, 6309 StringRef capturedExpression, 6310 ResultDisposition::Flags resultDisposition ) 6311 : m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition }, 6312 m_resultCapture( getResultCapture() ) 6313 {} 6314 6315 void AssertionHandler::handleExpr( ITransientExpression const& expr ) { 6316 m_resultCapture.handleExpr( m_assertionInfo, expr, m_reaction ); 6317 } 6318 void AssertionHandler::handleMessage(ResultWas::OfType resultType, StringRef const& message) { 6319 m_resultCapture.handleMessage( m_assertionInfo, resultType, message, m_reaction ); 6320 } 6321 6322 auto AssertionHandler::allowThrows() const -> bool { 6323 return getCurrentContext().getConfig()->allowThrows(); 6324 } 6325 6326 void AssertionHandler::complete() { 6327 setCompleted(); 6328 if( m_reaction.shouldDebugBreak ) { 6329 6330 // If you find your debugger stopping you here then go one level up on the 6331 // call-stack for the code that caused it (typically a failed assertion) 6332 6333 // (To go back to the test and change execution, jump over the throw, next) 6334 CATCH_BREAK_INTO_DEBUGGER(); 6335 } 6336 if (m_reaction.shouldThrow) { 6337 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 6338 throw Catch::TestFailureException(); 6339 #else 6340 CATCH_ERROR( "Test failure requires aborting test!" ); 6341 #endif 6342 } 6343 } 6344 void AssertionHandler::setCompleted() { 6345 m_completed = true; 6346 } 6347 6348 void AssertionHandler::handleUnexpectedInflightException() { 6349 m_resultCapture.handleUnexpectedInflightException( m_assertionInfo, Catch::translateActiveException(), m_reaction ); 6350 } 6351 6352 void AssertionHandler::handleExceptionThrownAsExpected() { 6353 m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction); 6354 } 6355 void AssertionHandler::handleExceptionNotThrownAsExpected() { 6356 m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction); 6357 } 6358 6359 void AssertionHandler::handleUnexpectedExceptionNotThrown() { 6360 m_resultCapture.handleUnexpectedExceptionNotThrown( m_assertionInfo, m_reaction ); 6361 } 6362 6363 void AssertionHandler::handleThrowingCallSkipped() { 6364 m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction); 6365 } 6366 6367 // This is the overload that takes a string and infers the Equals matcher from it 6368 // The more general overload, that takes any string matcher, is in catch_capture_matchers.cpp 6369 void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef const& matcherString ) { 6370 handleExceptionMatchExpr( handler, Matchers::Equals( str ), matcherString ); 6371 } 6372 6373 } // namespace Catch 6374 // end catch_assertionhandler.cpp 6375 // start catch_assertionresult.cpp 6376 6377 namespace Catch { 6378 AssertionResultData::AssertionResultData(ResultWas::OfType _resultType, LazyExpression const & _lazyExpression): 6379 lazyExpression(_lazyExpression), 6380 resultType(_resultType) {} 6381 6382 std::string AssertionResultData::reconstructExpression() const { 6383 6384 if( reconstructedExpression.empty() ) { 6385 if( lazyExpression ) { 6386 ReusableStringStream rss; 6387 rss << lazyExpression; 6388 reconstructedExpression = rss.str(); 6389 } 6390 } 6391 return reconstructedExpression; 6392 } 6393 6394 AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) 6395 : m_info( info ), 6396 m_resultData( data ) 6397 {} 6398 6399 // Result was a success 6400 bool AssertionResult::succeeded() const { 6401 return Catch::isOk( m_resultData.resultType ); 6402 } 6403 6404 // Result was a success, or failure is suppressed 6405 bool AssertionResult::isOk() const { 6406 return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition ); 6407 } 6408 6409 ResultWas::OfType AssertionResult::getResultType() const { 6410 return m_resultData.resultType; 6411 } 6412 6413 bool AssertionResult::hasExpression() const { 6414 return m_info.capturedExpression[0] != 0; 6415 } 6416 6417 bool AssertionResult::hasMessage() const { 6418 return !m_resultData.message.empty(); 6419 } 6420 6421 std::string AssertionResult::getExpression() const { 6422 if( isFalseTest( m_info.resultDisposition ) ) 6423 return "!(" + m_info.capturedExpression + ")"; 6424 else 6425 return m_info.capturedExpression; 6426 } 6427 6428 std::string AssertionResult::getExpressionInMacro() const { 6429 std::string expr; 6430 if( m_info.macroName[0] == 0 ) 6431 expr = m_info.capturedExpression; 6432 else { 6433 expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 ); 6434 expr += m_info.macroName; 6435 expr += "( "; 6436 expr += m_info.capturedExpression; 6437 expr += " )"; 6438 } 6439 return expr; 6440 } 6441 6442 bool AssertionResult::hasExpandedExpression() const { 6443 return hasExpression() && getExpandedExpression() != getExpression(); 6444 } 6445 6446 std::string AssertionResult::getExpandedExpression() const { 6447 std::string expr = m_resultData.reconstructExpression(); 6448 return expr.empty() 6449 ? getExpression() 6450 : expr; 6451 } 6452 6453 std::string AssertionResult::getMessage() const { 6454 return m_resultData.message; 6455 } 6456 SourceLineInfo AssertionResult::getSourceInfo() const { 6457 return m_info.lineInfo; 6458 } 6459 6460 StringRef AssertionResult::getTestMacroName() const { 6461 return m_info.macroName; 6462 } 6463 6464 } // end namespace Catch 6465 // end catch_assertionresult.cpp 6466 // start catch_benchmark.cpp 6467 6468 namespace Catch { 6469 6470 auto BenchmarkLooper::getResolution() -> uint64_t { 6471 return getEstimatedClockResolution() * getCurrentContext().getConfig()->benchmarkResolutionMultiple(); 6472 } 6473 6474 void BenchmarkLooper::reportStart() { 6475 getResultCapture().benchmarkStarting( { m_name } ); 6476 } 6477 auto BenchmarkLooper::needsMoreIterations() -> bool { 6478 auto elapsed = m_timer.getElapsedNanoseconds(); 6479 6480 // Exponentially increasing iterations until we're confident in our timer resolution 6481 if( elapsed < m_resolution ) { 6482 m_iterationsToRun *= 10; 6483 return true; 6484 } 6485 6486 getResultCapture().benchmarkEnded( { { m_name }, m_count, elapsed } ); 6487 return false; 6488 } 6489 6490 } // end namespace Catch 6491 // end catch_benchmark.cpp 6492 // start catch_capture_matchers.cpp 6493 6494 namespace Catch { 6495 6496 using StringMatcher = Matchers::Impl::MatcherBase<std::string>; 6497 6498 // This is the general overload that takes a any string matcher 6499 // There is another overload, in catch_assertionhandler.h/.cpp, that only takes a string and infers 6500 // the Equals matcher (so the header does not mention matchers) 6501 void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString ) { 6502 std::string exceptionMessage = Catch::translateActiveException(); 6503 MatchExpr<std::string, StringMatcher const&> expr( exceptionMessage, matcher, matcherString ); 6504 handler.handleExpr( expr ); 6505 } 6506 6507 } // namespace Catch 6508 // end catch_capture_matchers.cpp 6509 // start catch_commandline.cpp 6510 6511 // start catch_commandline.h 6512 6513 // start catch_clara.h 6514 6515 // Use Catch's value for console width (store Clara's off to the side, if present) 6516 #ifdef CLARA_CONFIG_CONSOLE_WIDTH 6517 #define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 6518 #undef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 6519 #endif 6520 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH-1 6521 6522 #ifdef __clang__ 6523 #pragma clang diagnostic push 6524 #pragma clang diagnostic ignored "-Wweak-vtables" 6525 #pragma clang diagnostic ignored "-Wexit-time-destructors" 6526 #pragma clang diagnostic ignored "-Wshadow" 6527 #endif 6528 6529 // start clara.hpp 6530 // Copyright 2017 Two Blue Cubes Ltd. All rights reserved. 6531 // 6532 // Distributed under the Boost Software License, Version 1.0. (See accompanying 6533 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6534 // 6535 // See https://github.com/philsquared/Clara for more details 6536 6537 // Clara v1.1.5 6538 6539 6540 #ifndef CATCH_CLARA_CONFIG_CONSOLE_WIDTH 6541 #define CATCH_CLARA_CONFIG_CONSOLE_WIDTH 80 6542 #endif 6543 6544 #ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 6545 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CLARA_CONFIG_CONSOLE_WIDTH 6546 #endif 6547 6548 #ifndef CLARA_CONFIG_OPTIONAL_TYPE 6549 #ifdef __has_include 6550 #if __has_include(<optional>) && __cplusplus >= 201703L 6551 #include <optional> 6552 #define CLARA_CONFIG_OPTIONAL_TYPE std::optional 6553 #endif 6554 #endif 6555 #endif 6556 6557 // ----------- #included from clara_textflow.hpp ----------- 6558 6559 // TextFlowCpp 6560 // 6561 // A single-header library for wrapping and laying out basic text, by Phil Nash 6562 // 6563 // Distributed under the Boost Software License, Version 1.0. (See accompanying 6564 // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6565 // 6566 // This project is hosted at https://github.com/philsquared/textflowcpp 6567 6568 6569 #include <cassert> 6570 #include <ostream> 6571 #include <sstream> 6572 #include <vector> 6573 6574 #ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 6575 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 80 6576 #endif 6577 6578 namespace Catch { 6579 namespace clara { 6580 namespace TextFlow { 6581 6582 inline auto isWhitespace(char c) -> bool { 6583 static std::string chars = " \t\n\r"; 6584 return chars.find(c) != std::string::npos; 6585 } 6586 inline auto isBreakableBefore(char c) -> bool { 6587 static std::string chars = "[({<|"; 6588 return chars.find(c) != std::string::npos; 6589 } 6590 inline auto isBreakableAfter(char c) -> bool { 6591 static std::string chars = "])}>.,:;*+-=&/\\"; 6592 return chars.find(c) != std::string::npos; 6593 } 6594 6595 class Columns; 6596 6597 class Column { 6598 std::vector<std::string> m_strings; 6599 size_t m_width = CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH; 6600 size_t m_indent = 0; 6601 size_t m_initialIndent = std::string::npos; 6602 6603 public: 6604 class iterator { 6605 friend Column; 6606 6607 Column const& m_column; 6608 size_t m_stringIndex = 0; 6609 size_t m_pos = 0; 6610 6611 size_t m_len = 0; 6612 size_t m_end = 0; 6613 bool m_suffix = false; 6614 6615 iterator(Column const& column, size_t stringIndex) 6616 : m_column(column), 6617 m_stringIndex(stringIndex) {} 6618 6619 auto line() const -> std::string const& { return m_column.m_strings[m_stringIndex]; } 6620 6621 auto isBoundary(size_t at) const -> bool { 6622 assert(at > 0); 6623 assert(at <= line().size()); 6624 6625 return at == line().size() || 6626 (isWhitespace(line()[at]) && !isWhitespace(line()[at - 1])) || 6627 isBreakableBefore(line()[at]) || 6628 isBreakableAfter(line()[at - 1]); 6629 } 6630 6631 void calcLength() { 6632 assert(m_stringIndex < m_column.m_strings.size()); 6633 6634 m_suffix = false; 6635 auto width = m_column.m_width - indent(); 6636 m_end = m_pos; 6637 if (line()[m_pos] == '\n') { 6638 ++m_end; 6639 } 6640 while (m_end < line().size() && line()[m_end] != '\n') 6641 ++m_end; 6642 6643 if (m_end < m_pos + width) { 6644 m_len = m_end - m_pos; 6645 } else { 6646 size_t len = width; 6647 while (len > 0 && !isBoundary(m_pos + len)) 6648 --len; 6649 while (len > 0 && isWhitespace(line()[m_pos + len - 1])) 6650 --len; 6651 6652 if (len > 0) { 6653 m_len = len; 6654 } else { 6655 m_suffix = true; 6656 m_len = width - 1; 6657 } 6658 } 6659 } 6660 6661 auto indent() const -> size_t { 6662 auto initial = m_pos == 0 && m_stringIndex == 0 ? m_column.m_initialIndent : std::string::npos; 6663 return initial == std::string::npos ? m_column.m_indent : initial; 6664 } 6665 6666 auto addIndentAndSuffix(std::string const &plain) const -> std::string { 6667 return std::string(indent(), ' ') + (m_suffix ? plain + "-" : plain); 6668 } 6669 6670 public: 6671 using difference_type = std::ptrdiff_t; 6672 using value_type = std::string; 6673 using pointer = value_type * ; 6674 using reference = value_type & ; 6675 using iterator_category = std::forward_iterator_tag; 6676 6677 explicit iterator(Column const& column) : m_column(column) { 6678 assert(m_column.m_width > m_column.m_indent); 6679 assert(m_column.m_initialIndent == std::string::npos || m_column.m_width > m_column.m_initialIndent); 6680 calcLength(); 6681 if (m_len == 0) 6682 m_stringIndex++; // Empty string 6683 } 6684 6685 auto operator *() const -> std::string { 6686 assert(m_stringIndex < m_column.m_strings.size()); 6687 assert(m_pos <= m_end); 6688 return addIndentAndSuffix(line().substr(m_pos, m_len)); 6689 } 6690 6691 auto operator ++() -> iterator& { 6692 m_pos += m_len; 6693 if (m_pos < line().size() && line()[m_pos] == '\n') 6694 m_pos += 1; 6695 else 6696 while (m_pos < line().size() && isWhitespace(line()[m_pos])) 6697 ++m_pos; 6698 6699 if (m_pos == line().size()) { 6700 m_pos = 0; 6701 ++m_stringIndex; 6702 } 6703 if (m_stringIndex < m_column.m_strings.size()) 6704 calcLength(); 6705 return *this; 6706 } 6707 auto operator ++(int) -> iterator { 6708 iterator prev(*this); 6709 operator++(); 6710 return prev; 6711 } 6712 6713 auto operator ==(iterator const& other) const -> bool { 6714 return 6715 m_pos == other.m_pos && 6716 m_stringIndex == other.m_stringIndex && 6717 &m_column == &other.m_column; 6718 } 6719 auto operator !=(iterator const& other) const -> bool { 6720 return !operator==(other); 6721 } 6722 }; 6723 using const_iterator = iterator; 6724 6725 explicit Column(std::string const& text) { m_strings.push_back(text); } 6726 6727 auto width(size_t newWidth) -> Column& { 6728 assert(newWidth > 0); 6729 m_width = newWidth; 6730 return *this; 6731 } 6732 auto indent(size_t newIndent) -> Column& { 6733 m_indent = newIndent; 6734 return *this; 6735 } 6736 auto initialIndent(size_t newIndent) -> Column& { 6737 m_initialIndent = newIndent; 6738 return *this; 6739 } 6740 6741 auto width() const -> size_t { return m_width; } 6742 auto begin() const -> iterator { return iterator(*this); } 6743 auto end() const -> iterator { return { *this, m_strings.size() }; } 6744 6745 inline friend std::ostream& operator << (std::ostream& os, Column const& col) { 6746 bool first = true; 6747 for (auto line : col) { 6748 if (first) 6749 first = false; 6750 else 6751 os << "\n"; 6752 os << line; 6753 } 6754 return os; 6755 } 6756 6757 auto operator + (Column const& other)->Columns; 6758 6759 auto toString() const -> std::string { 6760 std::ostringstream oss; 6761 oss << *this; 6762 return oss.str(); 6763 } 6764 }; 6765 6766 class Spacer : public Column { 6767 6768 public: 6769 explicit Spacer(size_t spaceWidth) : Column("") { 6770 width(spaceWidth); 6771 } 6772 }; 6773 6774 class Columns { 6775 std::vector<Column> m_columns; 6776 6777 public: 6778 6779 class iterator { 6780 friend Columns; 6781 struct EndTag {}; 6782 6783 std::vector<Column> const& m_columns; 6784 std::vector<Column::iterator> m_iterators; 6785 size_t m_activeIterators; 6786 6787 iterator(Columns const& columns, EndTag) 6788 : m_columns(columns.m_columns), 6789 m_activeIterators(0) { 6790 m_iterators.reserve(m_columns.size()); 6791 6792 for (auto const& col : m_columns) 6793 m_iterators.push_back(col.end()); 6794 } 6795 6796 public: 6797 using difference_type = std::ptrdiff_t; 6798 using value_type = std::string; 6799 using pointer = value_type * ; 6800 using reference = value_type & ; 6801 using iterator_category = std::forward_iterator_tag; 6802 6803 explicit iterator(Columns const& columns) 6804 : m_columns(columns.m_columns), 6805 m_activeIterators(m_columns.size()) { 6806 m_iterators.reserve(m_columns.size()); 6807 6808 for (auto const& col : m_columns) 6809 m_iterators.push_back(col.begin()); 6810 } 6811 6812 auto operator ==(iterator const& other) const -> bool { 6813 return m_iterators == other.m_iterators; 6814 } 6815 auto operator !=(iterator const& other) const -> bool { 6816 return m_iterators != other.m_iterators; 6817 } 6818 auto operator *() const -> std::string { 6819 std::string row, padding; 6820 6821 for (size_t i = 0; i < m_columns.size(); ++i) { 6822 auto width = m_columns[i].width(); 6823 if (m_iterators[i] != m_columns[i].end()) { 6824 std::string col = *m_iterators[i]; 6825 row += padding + col; 6826 if (col.size() < width) 6827 padding = std::string(width - col.size(), ' '); 6828 else 6829 padding = ""; 6830 } else { 6831 padding += std::string(width, ' '); 6832 } 6833 } 6834 return row; 6835 } 6836 auto operator ++() -> iterator& { 6837 for (size_t i = 0; i < m_columns.size(); ++i) { 6838 if (m_iterators[i] != m_columns[i].end()) 6839 ++m_iterators[i]; 6840 } 6841 return *this; 6842 } 6843 auto operator ++(int) -> iterator { 6844 iterator prev(*this); 6845 operator++(); 6846 return prev; 6847 } 6848 }; 6849 using const_iterator = iterator; 6850 6851 auto begin() const -> iterator { return iterator(*this); } 6852 auto end() const -> iterator { return { *this, iterator::EndTag() }; } 6853 6854 auto operator += (Column const& col) -> Columns& { 6855 m_columns.push_back(col); 6856 return *this; 6857 } 6858 auto operator + (Column const& col) -> Columns { 6859 Columns combined = *this; 6860 combined += col; 6861 return combined; 6862 } 6863 6864 inline friend std::ostream& operator << (std::ostream& os, Columns const& cols) { 6865 6866 bool first = true; 6867 for (auto line : cols) { 6868 if (first) 6869 first = false; 6870 else 6871 os << "\n"; 6872 os << line; 6873 } 6874 return os; 6875 } 6876 6877 auto toString() const -> std::string { 6878 std::ostringstream oss; 6879 oss << *this; 6880 return oss.str(); 6881 } 6882 }; 6883 6884 inline auto Column::operator + (Column const& other) -> Columns { 6885 Columns cols; 6886 cols += *this; 6887 cols += other; 6888 return cols; 6889 } 6890 } 6891 6892 } 6893 } 6894 6895 // ----------- end of #include from clara_textflow.hpp ----------- 6896 // ........... back in clara.hpp 6897 6898 #include <cctype> 6899 #include <string> 6900 #include <memory> 6901 #include <set> 6902 #include <algorithm> 6903 6904 #if !defined(CATCH_PLATFORM_WINDOWS) && ( defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) ) 6905 #define CATCH_PLATFORM_WINDOWS 6906 #endif 6907 6908 namespace Catch { namespace clara { 6909 namespace detail { 6910 6911 // Traits for extracting arg and return type of lambdas (for single argument lambdas) 6912 template<typename L> 6913 struct UnaryLambdaTraits : UnaryLambdaTraits<decltype( &L::operator() )> {}; 6914 6915 template<typename ClassT, typename ReturnT, typename... Args> 6916 struct UnaryLambdaTraits<ReturnT( ClassT::* )( Args... ) const> { 6917 static const bool isValid = false; 6918 }; 6919 6920 template<typename ClassT, typename ReturnT, typename ArgT> 6921 struct UnaryLambdaTraits<ReturnT( ClassT::* )( ArgT ) const> { 6922 static const bool isValid = true; 6923 using ArgType = typename std::remove_const<typename std::remove_reference<ArgT>::type>::type; 6924 using ReturnType = ReturnT; 6925 }; 6926 6927 class TokenStream; 6928 6929 // Transport for raw args (copied from main args, or supplied via init list for testing) 6930 class Args { 6931 friend TokenStream; 6932 std::string m_exeName; 6933 std::vector<std::string> m_args; 6934 6935 public: 6936 Args( int argc, char const* const* argv ) 6937 : m_exeName(argv[0]), 6938 m_args(argv + 1, argv + argc) {} 6939 6940 Args( std::initializer_list<std::string> args ) 6941 : m_exeName( *args.begin() ), 6942 m_args( args.begin()+1, args.end() ) 6943 {} 6944 6945 auto exeName() const -> std::string { 6946 return m_exeName; 6947 } 6948 }; 6949 6950 // Wraps a token coming from a token stream. These may not directly correspond to strings as a single string 6951 // may encode an option + its argument if the : or = form is used 6952 enum class TokenType { 6953 Option, Argument 6954 }; 6955 struct Token { 6956 TokenType type; 6957 std::string token; 6958 }; 6959 6960 inline auto isOptPrefix( char c ) -> bool { 6961 return c == '-' 6962 #ifdef CATCH_PLATFORM_WINDOWS 6963 || c == '/' 6964 #endif 6965 ; 6966 } 6967 6968 // Abstracts iterators into args as a stream of tokens, with option arguments uniformly handled 6969 class TokenStream { 6970 using Iterator = std::vector<std::string>::const_iterator; 6971 Iterator it; 6972 Iterator itEnd; 6973 std::vector<Token> m_tokenBuffer; 6974 6975 void loadBuffer() { 6976 m_tokenBuffer.resize( 0 ); 6977 6978 // Skip any empty strings 6979 while( it != itEnd && it->empty() ) 6980 ++it; 6981 6982 if( it != itEnd ) { 6983 auto const &next = *it; 6984 if( isOptPrefix( next[0] ) ) { 6985 auto delimiterPos = next.find_first_of( " :=" ); 6986 if( delimiterPos != std::string::npos ) { 6987 m_tokenBuffer.push_back( { TokenType::Option, next.substr( 0, delimiterPos ) } ); 6988 m_tokenBuffer.push_back( { TokenType::Argument, next.substr( delimiterPos + 1 ) } ); 6989 } else { 6990 if( next[1] != '-' && next.size() > 2 ) { 6991 std::string opt = "- "; 6992 for( size_t i = 1; i < next.size(); ++i ) { 6993 opt[1] = next[i]; 6994 m_tokenBuffer.push_back( { TokenType::Option, opt } ); 6995 } 6996 } else { 6997 m_tokenBuffer.push_back( { TokenType::Option, next } ); 6998 } 6999 } 7000 } else { 7001 m_tokenBuffer.push_back( { TokenType::Argument, next } ); 7002 } 7003 } 7004 } 7005 7006 public: 7007 explicit TokenStream( Args const &args ) : TokenStream( args.m_args.begin(), args.m_args.end() ) {} 7008 7009 TokenStream( Iterator it, Iterator itEnd ) : it( it ), itEnd( itEnd ) { 7010 loadBuffer(); 7011 } 7012 7013 explicit operator bool() const { 7014 return !m_tokenBuffer.empty() || it != itEnd; 7015 } 7016 7017 auto count() const -> size_t { return m_tokenBuffer.size() + (itEnd - it); } 7018 7019 auto operator*() const -> Token { 7020 assert( !m_tokenBuffer.empty() ); 7021 return m_tokenBuffer.front(); 7022 } 7023 7024 auto operator->() const -> Token const * { 7025 assert( !m_tokenBuffer.empty() ); 7026 return &m_tokenBuffer.front(); 7027 } 7028 7029 auto operator++() -> TokenStream & { 7030 if( m_tokenBuffer.size() >= 2 ) { 7031 m_tokenBuffer.erase( m_tokenBuffer.begin() ); 7032 } else { 7033 if( it != itEnd ) 7034 ++it; 7035 loadBuffer(); 7036 } 7037 return *this; 7038 } 7039 }; 7040 7041 class ResultBase { 7042 public: 7043 enum Type { 7044 Ok, LogicError, RuntimeError 7045 }; 7046 7047 protected: 7048 ResultBase( Type type ) : m_type( type ) {} 7049 virtual ~ResultBase() = default; 7050 7051 virtual void enforceOk() const = 0; 7052 7053 Type m_type; 7054 }; 7055 7056 template<typename T> 7057 class ResultValueBase : public ResultBase { 7058 public: 7059 auto value() const -> T const & { 7060 enforceOk(); 7061 return m_value; 7062 } 7063 7064 protected: 7065 ResultValueBase( Type type ) : ResultBase( type ) {} 7066 7067 ResultValueBase( ResultValueBase const &other ) : ResultBase( other ) { 7068 if( m_type == ResultBase::Ok ) 7069 new( &m_value ) T( other.m_value ); 7070 } 7071 7072 ResultValueBase( Type, T const &value ) : ResultBase( Ok ) { 7073 new( &m_value ) T( value ); 7074 } 7075 7076 auto operator=( ResultValueBase const &other ) -> ResultValueBase & { 7077 if( m_type == ResultBase::Ok ) 7078 m_value.~T(); 7079 ResultBase::operator=(other); 7080 if( m_type == ResultBase::Ok ) 7081 new( &m_value ) T( other.m_value ); 7082 return *this; 7083 } 7084 7085 ~ResultValueBase() override { 7086 if( m_type == Ok ) 7087 m_value.~T(); 7088 } 7089 7090 union { 7091 T m_value; 7092 }; 7093 }; 7094 7095 template<> 7096 class ResultValueBase<void> : public ResultBase { 7097 protected: 7098 using ResultBase::ResultBase; 7099 }; 7100 7101 template<typename T = void> 7102 class BasicResult : public ResultValueBase<T> { 7103 public: 7104 template<typename U> 7105 explicit BasicResult( BasicResult<U> const &other ) 7106 : ResultValueBase<T>( other.type() ), 7107 m_errorMessage( other.errorMessage() ) 7108 { 7109 assert( type() != ResultBase::Ok ); 7110 } 7111 7112 template<typename U> 7113 static auto ok( U const &value ) -> BasicResult { return { ResultBase::Ok, value }; } 7114 static auto ok() -> BasicResult { return { ResultBase::Ok }; } 7115 static auto logicError( std::string const &message ) -> BasicResult { return { ResultBase::LogicError, message }; } 7116 static auto runtimeError( std::string const &message ) -> BasicResult { return { ResultBase::RuntimeError, message }; } 7117 7118 explicit operator bool() const { return m_type == ResultBase::Ok; } 7119 auto type() const -> ResultBase::Type { return m_type; } 7120 auto errorMessage() const -> std::string { return m_errorMessage; } 7121 7122 protected: 7123 void enforceOk() const override { 7124 7125 // Errors shouldn't reach this point, but if they do 7126 // the actual error message will be in m_errorMessage 7127 assert( m_type != ResultBase::LogicError ); 7128 assert( m_type != ResultBase::RuntimeError ); 7129 if( m_type != ResultBase::Ok ) 7130 std::abort(); 7131 } 7132 7133 std::string m_errorMessage; // Only populated if resultType is an error 7134 7135 BasicResult( ResultBase::Type type, std::string const &message ) 7136 : ResultValueBase<T>(type), 7137 m_errorMessage(message) 7138 { 7139 assert( m_type != ResultBase::Ok ); 7140 } 7141 7142 using ResultValueBase<T>::ResultValueBase; 7143 using ResultBase::m_type; 7144 }; 7145 7146 enum class ParseResultType { 7147 Matched, NoMatch, ShortCircuitAll, ShortCircuitSame 7148 }; 7149 7150 class ParseState { 7151 public: 7152 7153 ParseState( ParseResultType type, TokenStream const &remainingTokens ) 7154 : m_type(type), 7155 m_remainingTokens( remainingTokens ) 7156 {} 7157 7158 auto type() const -> ParseResultType { return m_type; } 7159 auto remainingTokens() const -> TokenStream { return m_remainingTokens; } 7160 7161 private: 7162 ParseResultType m_type; 7163 TokenStream m_remainingTokens; 7164 }; 7165 7166 using Result = BasicResult<void>; 7167 using ParserResult = BasicResult<ParseResultType>; 7168 using InternalParseResult = BasicResult<ParseState>; 7169 7170 struct HelpColumns { 7171 std::string left; 7172 std::string right; 7173 }; 7174 7175 template<typename T> 7176 inline auto convertInto( std::string const &source, T& target ) -> ParserResult { 7177 std::stringstream ss; 7178 ss << source; 7179 ss >> target; 7180 if( ss.fail() ) 7181 return ParserResult::runtimeError( "Unable to convert '" + source + "' to destination type" ); 7182 else 7183 return ParserResult::ok( ParseResultType::Matched ); 7184 } 7185 inline auto convertInto( std::string const &source, std::string& target ) -> ParserResult { 7186 target = source; 7187 return ParserResult::ok( ParseResultType::Matched ); 7188 } 7189 inline auto convertInto( std::string const &source, bool &target ) -> ParserResult { 7190 std::string srcLC = source; 7191 std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( char c ) { return static_cast<char>( std::tolower(c) ); } ); 7192 if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on") 7193 target = true; 7194 else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off") 7195 target = false; 7196 else 7197 return ParserResult::runtimeError( "Expected a boolean value but did not recognise: '" + source + "'" ); 7198 return ParserResult::ok( ParseResultType::Matched ); 7199 } 7200 #ifdef CLARA_CONFIG_OPTIONAL_TYPE 7201 template<typename T> 7202 inline auto convertInto( std::string const &source, CLARA_CONFIG_OPTIONAL_TYPE<T>& target ) -> ParserResult { 7203 T temp; 7204 auto result = convertInto( source, temp ); 7205 if( result ) 7206 target = std::move(temp); 7207 return result; 7208 } 7209 #endif // CLARA_CONFIG_OPTIONAL_TYPE 7210 7211 struct NonCopyable { 7212 NonCopyable() = default; 7213 NonCopyable( NonCopyable const & ) = delete; 7214 NonCopyable( NonCopyable && ) = delete; 7215 NonCopyable &operator=( NonCopyable const & ) = delete; 7216 NonCopyable &operator=( NonCopyable && ) = delete; 7217 }; 7218 7219 struct BoundRef : NonCopyable { 7220 virtual ~BoundRef() = default; 7221 virtual auto isContainer() const -> bool { return false; } 7222 virtual auto isFlag() const -> bool { return false; } 7223 }; 7224 struct BoundValueRefBase : BoundRef { 7225 virtual auto setValue( std::string const &arg ) -> ParserResult = 0; 7226 }; 7227 struct BoundFlagRefBase : BoundRef { 7228 virtual auto setFlag( bool flag ) -> ParserResult = 0; 7229 virtual auto isFlag() const -> bool { return true; } 7230 }; 7231 7232 template<typename T> 7233 struct BoundValueRef : BoundValueRefBase { 7234 T &m_ref; 7235 7236 explicit BoundValueRef( T &ref ) : m_ref( ref ) {} 7237 7238 auto setValue( std::string const &arg ) -> ParserResult override { 7239 return convertInto( arg, m_ref ); 7240 } 7241 }; 7242 7243 template<typename T> 7244 struct BoundValueRef<std::vector<T>> : BoundValueRefBase { 7245 std::vector<T> &m_ref; 7246 7247 explicit BoundValueRef( std::vector<T> &ref ) : m_ref( ref ) {} 7248 7249 auto isContainer() const -> bool override { return true; } 7250 7251 auto setValue( std::string const &arg ) -> ParserResult override { 7252 T temp; 7253 auto result = convertInto( arg, temp ); 7254 if( result ) 7255 m_ref.push_back( temp ); 7256 return result; 7257 } 7258 }; 7259 7260 struct BoundFlagRef : BoundFlagRefBase { 7261 bool &m_ref; 7262 7263 explicit BoundFlagRef( bool &ref ) : m_ref( ref ) {} 7264 7265 auto setFlag( bool flag ) -> ParserResult override { 7266 m_ref = flag; 7267 return ParserResult::ok( ParseResultType::Matched ); 7268 } 7269 }; 7270 7271 template<typename ReturnType> 7272 struct LambdaInvoker { 7273 static_assert( std::is_same<ReturnType, ParserResult>::value, "Lambda must return void or clara::ParserResult" ); 7274 7275 template<typename L, typename ArgType> 7276 static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult { 7277 return lambda( arg ); 7278 } 7279 }; 7280 7281 template<> 7282 struct LambdaInvoker<void> { 7283 template<typename L, typename ArgType> 7284 static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult { 7285 lambda( arg ); 7286 return ParserResult::ok( ParseResultType::Matched ); 7287 } 7288 }; 7289 7290 template<typename ArgType, typename L> 7291 inline auto invokeLambda( L const &lambda, std::string const &arg ) -> ParserResult { 7292 ArgType temp{}; 7293 auto result = convertInto( arg, temp ); 7294 return !result 7295 ? result 7296 : LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( lambda, temp ); 7297 } 7298 7299 template<typename L> 7300 struct BoundLambda : BoundValueRefBase { 7301 L m_lambda; 7302 7303 static_assert( UnaryLambdaTraits<L>::isValid, "Supplied lambda must take exactly one argument" ); 7304 explicit BoundLambda( L const &lambda ) : m_lambda( lambda ) {} 7305 7306 auto setValue( std::string const &arg ) -> ParserResult override { 7307 return invokeLambda<typename UnaryLambdaTraits<L>::ArgType>( m_lambda, arg ); 7308 } 7309 }; 7310 7311 template<typename L> 7312 struct BoundFlagLambda : BoundFlagRefBase { 7313 L m_lambda; 7314 7315 static_assert( UnaryLambdaTraits<L>::isValid, "Supplied lambda must take exactly one argument" ); 7316 static_assert( std::is_same<typename UnaryLambdaTraits<L>::ArgType, bool>::value, "flags must be boolean" ); 7317 7318 explicit BoundFlagLambda( L const &lambda ) : m_lambda( lambda ) {} 7319 7320 auto setFlag( bool flag ) -> ParserResult override { 7321 return LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( m_lambda, flag ); 7322 } 7323 }; 7324 7325 enum class Optionality { Optional, Required }; 7326 7327 struct Parser; 7328 7329 class ParserBase { 7330 public: 7331 virtual ~ParserBase() = default; 7332 virtual auto validate() const -> Result { return Result::ok(); } 7333 virtual auto parse( std::string const& exeName, TokenStream const &tokens) const -> InternalParseResult = 0; 7334 virtual auto cardinality() const -> size_t { return 1; } 7335 7336 auto parse( Args const &args ) const -> InternalParseResult { 7337 return parse( args.exeName(), TokenStream( args ) ); 7338 } 7339 }; 7340 7341 template<typename DerivedT> 7342 class ComposableParserImpl : public ParserBase { 7343 public: 7344 template<typename T> 7345 auto operator|( T const &other ) const -> Parser; 7346 7347 template<typename T> 7348 auto operator+( T const &other ) const -> Parser; 7349 }; 7350 7351 // Common code and state for Args and Opts 7352 template<typename DerivedT> 7353 class ParserRefImpl : public ComposableParserImpl<DerivedT> { 7354 protected: 7355 Optionality m_optionality = Optionality::Optional; 7356 std::shared_ptr<BoundRef> m_ref; 7357 std::string m_hint; 7358 std::string m_description; 7359 7360 explicit ParserRefImpl( std::shared_ptr<BoundRef> const &ref ) : m_ref( ref ) {} 7361 7362 public: 7363 template<typename T> 7364 ParserRefImpl( T &ref, std::string const &hint ) 7365 : m_ref( std::make_shared<BoundValueRef<T>>( ref ) ), 7366 m_hint( hint ) 7367 {} 7368 7369 template<typename LambdaT> 7370 ParserRefImpl( LambdaT const &ref, std::string const &hint ) 7371 : m_ref( std::make_shared<BoundLambda<LambdaT>>( ref ) ), 7372 m_hint(hint) 7373 {} 7374 7375 auto operator()( std::string const &description ) -> DerivedT & { 7376 m_description = description; 7377 return static_cast<DerivedT &>( *this ); 7378 } 7379 7380 auto optional() -> DerivedT & { 7381 m_optionality = Optionality::Optional; 7382 return static_cast<DerivedT &>( *this ); 7383 }; 7384 7385 auto required() -> DerivedT & { 7386 m_optionality = Optionality::Required; 7387 return static_cast<DerivedT &>( *this ); 7388 }; 7389 7390 auto isOptional() const -> bool { 7391 return m_optionality == Optionality::Optional; 7392 } 7393 7394 auto cardinality() const -> size_t override { 7395 if( m_ref->isContainer() ) 7396 return 0; 7397 else 7398 return 1; 7399 } 7400 7401 auto hint() const -> std::string { return m_hint; } 7402 }; 7403 7404 class ExeName : public ComposableParserImpl<ExeName> { 7405 std::shared_ptr<std::string> m_name; 7406 std::shared_ptr<BoundValueRefBase> m_ref; 7407 7408 template<typename LambdaT> 7409 static auto makeRef(LambdaT const &lambda) -> std::shared_ptr<BoundValueRefBase> { 7410 return std::make_shared<BoundLambda<LambdaT>>( lambda) ; 7411 } 7412 7413 public: 7414 ExeName() : m_name( std::make_shared<std::string>( "<executable>" ) ) {} 7415 7416 explicit ExeName( std::string &ref ) : ExeName() { 7417 m_ref = std::make_shared<BoundValueRef<std::string>>( ref ); 7418 } 7419 7420 template<typename LambdaT> 7421 explicit ExeName( LambdaT const& lambda ) : ExeName() { 7422 m_ref = std::make_shared<BoundLambda<LambdaT>>( lambda ); 7423 } 7424 7425 // The exe name is not parsed out of the normal tokens, but is handled specially 7426 auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override { 7427 return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) ); 7428 } 7429 7430 auto name() const -> std::string { return *m_name; } 7431 auto set( std::string const& newName ) -> ParserResult { 7432 7433 auto lastSlash = newName.find_last_of( "\\/" ); 7434 auto filename = ( lastSlash == std::string::npos ) 7435 ? newName 7436 : newName.substr( lastSlash+1 ); 7437 7438 *m_name = filename; 7439 if( m_ref ) 7440 return m_ref->setValue( filename ); 7441 else 7442 return ParserResult::ok( ParseResultType::Matched ); 7443 } 7444 }; 7445 7446 class Arg : public ParserRefImpl<Arg> { 7447 public: 7448 using ParserRefImpl::ParserRefImpl; 7449 7450 auto parse( std::string const &, TokenStream const &tokens ) const -> InternalParseResult override { 7451 auto validationResult = validate(); 7452 if( !validationResult ) 7453 return InternalParseResult( validationResult ); 7454 7455 auto remainingTokens = tokens; 7456 auto const &token = *remainingTokens; 7457 if( token.type != TokenType::Argument ) 7458 return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) ); 7459 7460 assert( !m_ref->isFlag() ); 7461 auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() ); 7462 7463 auto result = valueRef->setValue( remainingTokens->token ); 7464 if( !result ) 7465 return InternalParseResult( result ); 7466 else 7467 return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) ); 7468 } 7469 }; 7470 7471 inline auto normaliseOpt( std::string const &optName ) -> std::string { 7472 #ifdef CATCH_PLATFORM_WINDOWS 7473 if( optName[0] == '/' ) 7474 return "-" + optName.substr( 1 ); 7475 else 7476 #endif 7477 return optName; 7478 } 7479 7480 class Opt : public ParserRefImpl<Opt> { 7481 protected: 7482 std::vector<std::string> m_optNames; 7483 7484 public: 7485 template<typename LambdaT> 7486 explicit Opt( LambdaT const &ref ) : ParserRefImpl( std::make_shared<BoundFlagLambda<LambdaT>>( ref ) ) {} 7487 7488 explicit Opt( bool &ref ) : ParserRefImpl( std::make_shared<BoundFlagRef>( ref ) ) {} 7489 7490 template<typename LambdaT> 7491 Opt( LambdaT const &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {} 7492 7493 template<typename T> 7494 Opt( T &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {} 7495 7496 auto operator[]( std::string const &optName ) -> Opt & { 7497 m_optNames.push_back( optName ); 7498 return *this; 7499 } 7500 7501 auto getHelpColumns() const -> std::vector<HelpColumns> { 7502 std::ostringstream oss; 7503 bool first = true; 7504 for( auto const &opt : m_optNames ) { 7505 if (first) 7506 first = false; 7507 else 7508 oss << ", "; 7509 oss << opt; 7510 } 7511 if( !m_hint.empty() ) 7512 oss << " <" << m_hint << ">"; 7513 return { { oss.str(), m_description } }; 7514 } 7515 7516 auto isMatch( std::string const &optToken ) const -> bool { 7517 auto normalisedToken = normaliseOpt( optToken ); 7518 for( auto const &name : m_optNames ) { 7519 if( normaliseOpt( name ) == normalisedToken ) 7520 return true; 7521 } 7522 return false; 7523 } 7524 7525 using ParserBase::parse; 7526 7527 auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override { 7528 auto validationResult = validate(); 7529 if( !validationResult ) 7530 return InternalParseResult( validationResult ); 7531 7532 auto remainingTokens = tokens; 7533 if( remainingTokens && remainingTokens->type == TokenType::Option ) { 7534 auto const &token = *remainingTokens; 7535 if( isMatch(token.token ) ) { 7536 if( m_ref->isFlag() ) { 7537 auto flagRef = static_cast<detail::BoundFlagRefBase*>( m_ref.get() ); 7538 auto result = flagRef->setFlag( true ); 7539 if( !result ) 7540 return InternalParseResult( result ); 7541 if( result.value() == ParseResultType::ShortCircuitAll ) 7542 return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) ); 7543 } else { 7544 auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() ); 7545 ++remainingTokens; 7546 if( !remainingTokens ) 7547 return InternalParseResult::runtimeError( "Expected argument following " + token.token ); 7548 auto const &argToken = *remainingTokens; 7549 if( argToken.type != TokenType::Argument ) 7550 return InternalParseResult::runtimeError( "Expected argument following " + token.token ); 7551 auto result = valueRef->setValue( argToken.token ); 7552 if( !result ) 7553 return InternalParseResult( result ); 7554 if( result.value() == ParseResultType::ShortCircuitAll ) 7555 return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) ); 7556 } 7557 return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) ); 7558 } 7559 } 7560 return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) ); 7561 } 7562 7563 auto validate() const -> Result override { 7564 if( m_optNames.empty() ) 7565 return Result::logicError( "No options supplied to Opt" ); 7566 for( auto const &name : m_optNames ) { 7567 if( name.empty() ) 7568 return Result::logicError( "Option name cannot be empty" ); 7569 #ifdef CATCH_PLATFORM_WINDOWS 7570 if( name[0] != '-' && name[0] != '/' ) 7571 return Result::logicError( "Option name must begin with '-' or '/'" ); 7572 #else 7573 if( name[0] != '-' ) 7574 return Result::logicError( "Option name must begin with '-'" ); 7575 #endif 7576 } 7577 return ParserRefImpl::validate(); 7578 } 7579 }; 7580 7581 struct Help : Opt { 7582 Help( bool &showHelpFlag ) 7583 : Opt([&]( bool flag ) { 7584 showHelpFlag = flag; 7585 return ParserResult::ok( ParseResultType::ShortCircuitAll ); 7586 }) 7587 { 7588 static_cast<Opt &>( *this ) 7589 ("display usage information") 7590 ["-?"]["-h"]["--help"] 7591 .optional(); 7592 } 7593 }; 7594 7595 struct Parser : ParserBase { 7596 7597 mutable ExeName m_exeName; 7598 std::vector<Opt> m_options; 7599 std::vector<Arg> m_args; 7600 7601 auto operator|=( ExeName const &exeName ) -> Parser & { 7602 m_exeName = exeName; 7603 return *this; 7604 } 7605 7606 auto operator|=( Arg const &arg ) -> Parser & { 7607 m_args.push_back(arg); 7608 return *this; 7609 } 7610 7611 auto operator|=( Opt const &opt ) -> Parser & { 7612 m_options.push_back(opt); 7613 return *this; 7614 } 7615 7616 auto operator|=( Parser const &other ) -> Parser & { 7617 m_options.insert(m_options.end(), other.m_options.begin(), other.m_options.end()); 7618 m_args.insert(m_args.end(), other.m_args.begin(), other.m_args.end()); 7619 return *this; 7620 } 7621 7622 template<typename T> 7623 auto operator|( T const &other ) const -> Parser { 7624 return Parser( *this ) |= other; 7625 } 7626 7627 // Forward deprecated interface with '+' instead of '|' 7628 template<typename T> 7629 auto operator+=( T const &other ) -> Parser & { return operator|=( other ); } 7630 template<typename T> 7631 auto operator+( T const &other ) const -> Parser { return operator|( other ); } 7632 7633 auto getHelpColumns() const -> std::vector<HelpColumns> { 7634 std::vector<HelpColumns> cols; 7635 for (auto const &o : m_options) { 7636 auto childCols = o.getHelpColumns(); 7637 cols.insert( cols.end(), childCols.begin(), childCols.end() ); 7638 } 7639 return cols; 7640 } 7641 7642 void writeToStream( std::ostream &os ) const { 7643 if (!m_exeName.name().empty()) { 7644 os << "usage:\n" << " " << m_exeName.name() << " "; 7645 bool required = true, first = true; 7646 for( auto const &arg : m_args ) { 7647 if (first) 7648 first = false; 7649 else 7650 os << " "; 7651 if( arg.isOptional() && required ) { 7652 os << "["; 7653 required = false; 7654 } 7655 os << "<" << arg.hint() << ">"; 7656 if( arg.cardinality() == 0 ) 7657 os << " ... "; 7658 } 7659 if( !required ) 7660 os << "]"; 7661 if( !m_options.empty() ) 7662 os << " options"; 7663 os << "\n\nwhere options are:" << std::endl; 7664 } 7665 7666 auto rows = getHelpColumns(); 7667 size_t consoleWidth = CATCH_CLARA_CONFIG_CONSOLE_WIDTH; 7668 size_t optWidth = 0; 7669 for( auto const &cols : rows ) 7670 optWidth = (std::max)(optWidth, cols.left.size() + 2); 7671 7672 optWidth = (std::min)(optWidth, consoleWidth/2); 7673 7674 for( auto const &cols : rows ) { 7675 auto row = 7676 TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) + 7677 TextFlow::Spacer(4) + 7678 TextFlow::Column( cols.right ).width( consoleWidth - 7 - optWidth ); 7679 os << row << std::endl; 7680 } 7681 } 7682 7683 friend auto operator<<( std::ostream &os, Parser const &parser ) -> std::ostream& { 7684 parser.writeToStream( os ); 7685 return os; 7686 } 7687 7688 auto validate() const -> Result override { 7689 for( auto const &opt : m_options ) { 7690 auto result = opt.validate(); 7691 if( !result ) 7692 return result; 7693 } 7694 for( auto const &arg : m_args ) { 7695 auto result = arg.validate(); 7696 if( !result ) 7697 return result; 7698 } 7699 return Result::ok(); 7700 } 7701 7702 using ParserBase::parse; 7703 7704 auto parse( std::string const& exeName, TokenStream const &tokens ) const -> InternalParseResult override { 7705 7706 struct ParserInfo { 7707 ParserBase const* parser = nullptr; 7708 size_t count = 0; 7709 }; 7710 const size_t totalParsers = m_options.size() + m_args.size(); 7711 assert( totalParsers < 512 ); 7712 // ParserInfo parseInfos[totalParsers]; // <-- this is what we really want to do 7713 ParserInfo parseInfos[512]; 7714 7715 { 7716 size_t i = 0; 7717 for (auto const &opt : m_options) parseInfos[i++].parser = &opt; 7718 for (auto const &arg : m_args) parseInfos[i++].parser = &arg; 7719 } 7720 7721 m_exeName.set( exeName ); 7722 7723 auto result = InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) ); 7724 while( result.value().remainingTokens() ) { 7725 bool tokenParsed = false; 7726 7727 for( size_t i = 0; i < totalParsers; ++i ) { 7728 auto& parseInfo = parseInfos[i]; 7729 if( parseInfo.parser->cardinality() == 0 || parseInfo.count < parseInfo.parser->cardinality() ) { 7730 result = parseInfo.parser->parse(exeName, result.value().remainingTokens()); 7731 if (!result) 7732 return result; 7733 if (result.value().type() != ParseResultType::NoMatch) { 7734 tokenParsed = true; 7735 ++parseInfo.count; 7736 break; 7737 } 7738 } 7739 } 7740 7741 if( result.value().type() == ParseResultType::ShortCircuitAll ) 7742 return result; 7743 if( !tokenParsed ) 7744 return InternalParseResult::runtimeError( "Unrecognised token: " + result.value().remainingTokens()->token ); 7745 } 7746 // !TBD Check missing required options 7747 return result; 7748 } 7749 }; 7750 7751 template<typename DerivedT> 7752 template<typename T> 7753 auto ComposableParserImpl<DerivedT>::operator|( T const &other ) const -> Parser { 7754 return Parser() | static_cast<DerivedT const &>( *this ) | other; 7755 } 7756 } // namespace detail 7757 7758 // A Combined parser 7759 using detail::Parser; 7760 7761 // A parser for options 7762 using detail::Opt; 7763 7764 // A parser for arguments 7765 using detail::Arg; 7766 7767 // Wrapper for argc, argv from main() 7768 using detail::Args; 7769 7770 // Specifies the name of the executable 7771 using detail::ExeName; 7772 7773 // Convenience wrapper for option parser that specifies the help option 7774 using detail::Help; 7775 7776 // enum of result types from a parse 7777 using detail::ParseResultType; 7778 7779 // Result type for parser operation 7780 using detail::ParserResult; 7781 7782 }} // namespace Catch::clara 7783 7784 // end clara.hpp 7785 #ifdef __clang__ 7786 #pragma clang diagnostic pop 7787 #endif 7788 7789 // Restore Clara's value for console width, if present 7790 #ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH 7791 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH 7792 #undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH 7793 #endif 7794 7795 // end catch_clara.h 7796 namespace Catch { 7797 7798 clara::Parser makeCommandLineParser( ConfigData& config ); 7799 7800 } // end namespace Catch 7801 7802 // end catch_commandline.h 7803 #include <fstream> 7804 #include <ctime> 7805 7806 namespace Catch { 7807 7808 clara::Parser makeCommandLineParser( ConfigData& config ) { 7809 7810 using namespace clara; 7811 7812 auto const setWarning = [&]( std::string const& warning ) { 7813 auto warningSet = [&]() { 7814 if( warning == "NoAssertions" ) 7815 return WarnAbout::NoAssertions; 7816 7817 if ( warning == "NoTests" ) 7818 return WarnAbout::NoTests; 7819 7820 return WarnAbout::Nothing; 7821 }(); 7822 7823 if (warningSet == WarnAbout::Nothing) 7824 return ParserResult::runtimeError( "Unrecognised warning: '" + warning + "'" ); 7825 config.warnings = static_cast<WarnAbout::What>( config.warnings | warningSet ); 7826 return ParserResult::ok( ParseResultType::Matched ); 7827 }; 7828 auto const loadTestNamesFromFile = [&]( std::string const& filename ) { 7829 std::ifstream f( filename.c_str() ); 7830 if( !f.is_open() ) 7831 return ParserResult::runtimeError( "Unable to load input file: '" + filename + "'" ); 7832 7833 std::string line; 7834 while( std::getline( f, line ) ) { 7835 line = trim(line); 7836 if( !line.empty() && !startsWith( line, '#' ) ) { 7837 if( !startsWith( line, '"' ) ) 7838 line = '"' + line + '"'; 7839 config.testsOrTags.push_back( line + ',' ); 7840 } 7841 } 7842 return ParserResult::ok( ParseResultType::Matched ); 7843 }; 7844 auto const setTestOrder = [&]( std::string const& order ) { 7845 if( startsWith( "declared", order ) ) 7846 config.runOrder = RunTests::InDeclarationOrder; 7847 else if( startsWith( "lexical", order ) ) 7848 config.runOrder = RunTests::InLexicographicalOrder; 7849 else if( startsWith( "random", order ) ) 7850 config.runOrder = RunTests::InRandomOrder; 7851 else 7852 return clara::ParserResult::runtimeError( "Unrecognised ordering: '" + order + "'" ); 7853 return ParserResult::ok( ParseResultType::Matched ); 7854 }; 7855 auto const setRngSeed = [&]( std::string const& seed ) { 7856 if( seed != "time" ) 7857 return clara::detail::convertInto( seed, config.rngSeed ); 7858 config.rngSeed = static_cast<unsigned int>( std::time(nullptr) ); 7859 return ParserResult::ok( ParseResultType::Matched ); 7860 }; 7861 auto const setColourUsage = [&]( std::string const& useColour ) { 7862 auto mode = toLower( useColour ); 7863 7864 if( mode == "yes" ) 7865 config.useColour = UseColour::Yes; 7866 else if( mode == "no" ) 7867 config.useColour = UseColour::No; 7868 else if( mode == "auto" ) 7869 config.useColour = UseColour::Auto; 7870 else 7871 return ParserResult::runtimeError( "colour mode must be one of: auto, yes or no. '" + useColour + "' not recognised" ); 7872 return ParserResult::ok( ParseResultType::Matched ); 7873 }; 7874 auto const setWaitForKeypress = [&]( std::string const& keypress ) { 7875 auto keypressLc = toLower( keypress ); 7876 if( keypressLc == "start" ) 7877 config.waitForKeypress = WaitForKeypress::BeforeStart; 7878 else if( keypressLc == "exit" ) 7879 config.waitForKeypress = WaitForKeypress::BeforeExit; 7880 else if( keypressLc == "both" ) 7881 config.waitForKeypress = WaitForKeypress::BeforeStartAndExit; 7882 else 7883 return ParserResult::runtimeError( "keypress argument must be one of: start, exit or both. '" + keypress + "' not recognised" ); 7884 return ParserResult::ok( ParseResultType::Matched ); 7885 }; 7886 auto const setVerbosity = [&]( std::string const& verbosity ) { 7887 auto lcVerbosity = toLower( verbosity ); 7888 if( lcVerbosity == "quiet" ) 7889 config.verbosity = Verbosity::Quiet; 7890 else if( lcVerbosity == "normal" ) 7891 config.verbosity = Verbosity::Normal; 7892 else if( lcVerbosity == "high" ) 7893 config.verbosity = Verbosity::High; 7894 else 7895 return ParserResult::runtimeError( "Unrecognised verbosity, '" + verbosity + "'" ); 7896 return ParserResult::ok( ParseResultType::Matched ); 7897 }; 7898 auto const setReporter = [&]( std::string const& reporter ) { 7899 IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); 7900 7901 auto lcReporter = toLower( reporter ); 7902 auto result = factories.find( lcReporter ); 7903 7904 if( factories.end() != result ) 7905 config.reporterName = lcReporter; 7906 else 7907 return ParserResult::runtimeError( "Unrecognized reporter, '" + reporter + "'. Check available with --list-reporters" ); 7908 return ParserResult::ok( ParseResultType::Matched ); 7909 }; 7910 7911 auto cli 7912 = ExeName( config.processName ) 7913 | Help( config.showHelp ) 7914 | Opt( config.listTests ) 7915 ["-l"]["--list-tests"] 7916 ( "list all/matching test cases" ) 7917 | Opt( config.listTags ) 7918 ["-t"]["--list-tags"] 7919 ( "list all/matching tags" ) 7920 | Opt( config.showSuccessfulTests ) 7921 ["-s"]["--success"] 7922 ( "include successful tests in output" ) 7923 | Opt( config.shouldDebugBreak ) 7924 ["-b"]["--break"] 7925 ( "break into debugger on failure" ) 7926 | Opt( config.noThrow ) 7927 ["-e"]["--nothrow"] 7928 ( "skip exception tests" ) 7929 | Opt( config.showInvisibles ) 7930 ["-i"]["--invisibles"] 7931 ( "show invisibles (tabs, newlines)" ) 7932 | Opt( config.outputFilename, "filename" ) 7933 ["-o"]["--out"] 7934 ( "output filename" ) 7935 | Opt( setReporter, "name" ) 7936 ["-r"]["--reporter"] 7937 ( "reporter to use (defaults to console)" ) 7938 | Opt( config.name, "name" ) 7939 ["-n"]["--name"] 7940 ( "suite name" ) 7941 | Opt( [&]( bool ){ config.abortAfter = 1; } ) 7942 ["-a"]["--abort"] 7943 ( "abort at first failure" ) 7944 | Opt( [&]( int x ){ config.abortAfter = x; }, "no. failures" ) 7945 ["-x"]["--abortx"] 7946 ( "abort after x failures" ) 7947 | Opt( setWarning, "warning name" ) 7948 ["-w"]["--warn"] 7949 ( "enable warnings" ) 7950 | Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" ) 7951 ["-d"]["--durations"] 7952 ( "show test durations" ) 7953 | Opt( loadTestNamesFromFile, "filename" ) 7954 ["-f"]["--input-file"] 7955 ( "load test names to run from a file" ) 7956 | Opt( config.filenamesAsTags ) 7957 ["-#"]["--filenames-as-tags"] 7958 ( "adds a tag for the filename" ) 7959 | Opt( config.sectionsToRun, "section name" ) 7960 ["-c"]["--section"] 7961 ( "specify section to run" ) 7962 | Opt( setVerbosity, "quiet|normal|high" ) 7963 ["-v"]["--verbosity"] 7964 ( "set output verbosity" ) 7965 | Opt( config.listTestNamesOnly ) 7966 ["--list-test-names-only"] 7967 ( "list all/matching test cases names only" ) 7968 | Opt( config.listReporters ) 7969 ["--list-reporters"] 7970 ( "list all reporters" ) 7971 | Opt( setTestOrder, "decl|lex|rand" ) 7972 ["--order"] 7973 ( "test case order (defaults to decl)" ) 7974 | Opt( setRngSeed, "'time'|number" ) 7975 ["--rng-seed"] 7976 ( "set a specific seed for random numbers" ) 7977 | Opt( setColourUsage, "yes|no" ) 7978 ["--use-colour"] 7979 ( "should output be colourised" ) 7980 | Opt( config.libIdentify ) 7981 ["--libidentify"] 7982 ( "report name and version according to libidentify standard" ) 7983 | Opt( setWaitForKeypress, "start|exit|both" ) 7984 ["--wait-for-keypress"] 7985 ( "waits for a keypress before exiting" ) 7986 | Opt( config.benchmarkResolutionMultiple, "multiplier" ) 7987 ["--benchmark-resolution-multiple"] 7988 ( "multiple of clock resolution to run benchmarks" ) 7989 7990 | Arg( config.testsOrTags, "test name|pattern|tags" ) 7991 ( "which test or tests to use" ); 7992 7993 return cli; 7994 } 7995 7996 } // end namespace Catch 7997 // end catch_commandline.cpp 7998 // start catch_common.cpp 7999 8000 #include <cstring> 8001 #include <ostream> 8002 8003 namespace Catch { 8004 8005 bool SourceLineInfo::empty() const noexcept { 8006 return file[0] == '\0'; 8007 } 8008 bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const noexcept { 8009 return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0); 8010 } 8011 bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const noexcept { 8012 // We can assume that the same file will usually have the same pointer. 8013 // Thus, if the pointers are the same, there is no point in calling the strcmp 8014 return line < other.line || ( line == other.line && file != other.file && (std::strcmp(file, other.file) < 0)); 8015 } 8016 8017 std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { 8018 #ifndef __GNUG__ 8019 os << info.file << '(' << info.line << ')'; 8020 #else 8021 os << info.file << ':' << info.line; 8022 #endif 8023 return os; 8024 } 8025 8026 std::string StreamEndStop::operator+() const { 8027 return std::string(); 8028 } 8029 8030 NonCopyable::NonCopyable() = default; 8031 NonCopyable::~NonCopyable() = default; 8032 8033 } 8034 // end catch_common.cpp 8035 // start catch_config.cpp 8036 8037 namespace Catch { 8038 8039 Config::Config( ConfigData const& data ) 8040 : m_data( data ), 8041 m_stream( openStream() ) 8042 { 8043 TestSpecParser parser(ITagAliasRegistry::get()); 8044 if (!data.testsOrTags.empty()) { 8045 m_hasTestFilters = true; 8046 for( auto const& testOrTags : data.testsOrTags ) 8047 parser.parse( testOrTags ); 8048 } 8049 m_testSpec = parser.testSpec(); 8050 } 8051 8052 std::string const& Config::getFilename() const { 8053 return m_data.outputFilename ; 8054 } 8055 8056 bool Config::listTests() const { return m_data.listTests; } 8057 bool Config::listTestNamesOnly() const { return m_data.listTestNamesOnly; } 8058 bool Config::listTags() const { return m_data.listTags; } 8059 bool Config::listReporters() const { return m_data.listReporters; } 8060 8061 std::string Config::getProcessName() const { return m_data.processName; } 8062 std::string const& Config::getReporterName() const { return m_data.reporterName; } 8063 8064 std::vector<std::string> const& Config::getTestsOrTags() const { return m_data.testsOrTags; } 8065 std::vector<std::string> const& Config::getSectionsToRun() const { return m_data.sectionsToRun; } 8066 8067 TestSpec const& Config::testSpec() const { return m_testSpec; } 8068 bool Config::hasTestFilters() const { return m_hasTestFilters; } 8069 8070 bool Config::showHelp() const { return m_data.showHelp; } 8071 8072 // IConfig interface 8073 bool Config::allowThrows() const { return !m_data.noThrow; } 8074 std::ostream& Config::stream() const { return m_stream->stream(); } 8075 std::string Config::name() const { return m_data.name.empty() ? m_data.processName : m_data.name; } 8076 bool Config::includeSuccessfulResults() const { return m_data.showSuccessfulTests; } 8077 bool Config::warnAboutMissingAssertions() const { return !!(m_data.warnings & WarnAbout::NoAssertions); } 8078 bool Config::warnAboutNoTests() const { return !!(m_data.warnings & WarnAbout::NoTests); } 8079 ShowDurations::OrNot Config::showDurations() const { return m_data.showDurations; } 8080 RunTests::InWhatOrder Config::runOrder() const { return m_data.runOrder; } 8081 unsigned int Config::rngSeed() const { return m_data.rngSeed; } 8082 int Config::benchmarkResolutionMultiple() const { return m_data.benchmarkResolutionMultiple; } 8083 UseColour::YesOrNo Config::useColour() const { return m_data.useColour; } 8084 bool Config::shouldDebugBreak() const { return m_data.shouldDebugBreak; } 8085 int Config::abortAfter() const { return m_data.abortAfter; } 8086 bool Config::showInvisibles() const { return m_data.showInvisibles; } 8087 Verbosity Config::verbosity() const { return m_data.verbosity; } 8088 8089 IStream const* Config::openStream() { 8090 return Catch::makeStream(m_data.outputFilename); 8091 } 8092 8093 } // end namespace Catch 8094 // end catch_config.cpp 8095 // start catch_console_colour.cpp 8096 8097 #if defined(__clang__) 8098 # pragma clang diagnostic push 8099 # pragma clang diagnostic ignored "-Wexit-time-destructors" 8100 #endif 8101 8102 // start catch_errno_guard.h 8103 8104 namespace Catch { 8105 8106 class ErrnoGuard { 8107 public: 8108 ErrnoGuard(); 8109 ~ErrnoGuard(); 8110 private: 8111 int m_oldErrno; 8112 }; 8113 8114 } 8115 8116 // end catch_errno_guard.h 8117 #include <sstream> 8118 8119 namespace Catch { 8120 namespace { 8121 8122 struct IColourImpl { 8123 virtual ~IColourImpl() = default; 8124 virtual void use( Colour::Code _colourCode ) = 0; 8125 }; 8126 8127 struct NoColourImpl : IColourImpl { 8128 void use( Colour::Code ) {} 8129 8130 static IColourImpl* instance() { 8131 static NoColourImpl s_instance; 8132 return &s_instance; 8133 } 8134 }; 8135 8136 } // anon namespace 8137 } // namespace Catch 8138 8139 #if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI ) 8140 # ifdef CATCH_PLATFORM_WINDOWS 8141 # define CATCH_CONFIG_COLOUR_WINDOWS 8142 # else 8143 # define CATCH_CONFIG_COLOUR_ANSI 8144 # endif 8145 #endif 8146 8147 #if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) ///////////////////////////////////////// 8148 8149 namespace Catch { 8150 namespace { 8151 8152 class Win32ColourImpl : public IColourImpl { 8153 public: 8154 Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) ) 8155 { 8156 CONSOLE_SCREEN_BUFFER_INFO csbiInfo; 8157 GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo ); 8158 originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY ); 8159 originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ); 8160 } 8161 8162 void use( Colour::Code _colourCode ) override { 8163 switch( _colourCode ) { 8164 case Colour::None: return setTextAttribute( originalForegroundAttributes ); 8165 case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); 8166 case Colour::Red: return setTextAttribute( FOREGROUND_RED ); 8167 case Colour::Green: return setTextAttribute( FOREGROUND_GREEN ); 8168 case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE ); 8169 case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN ); 8170 case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN ); 8171 case Colour::Grey: return setTextAttribute( 0 ); 8172 8173 case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY ); 8174 case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED ); 8175 case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN ); 8176 case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); 8177 case Colour::BrightYellow: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN ); 8178 8179 case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" ); 8180 8181 default: 8182 CATCH_ERROR( "Unknown colour requested" ); 8183 } 8184 } 8185 8186 private: 8187 void setTextAttribute( WORD _textAttribute ) { 8188 SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes ); 8189 } 8190 HANDLE stdoutHandle; 8191 WORD originalForegroundAttributes; 8192 WORD originalBackgroundAttributes; 8193 }; 8194 8195 IColourImpl* platformColourInstance() { 8196 static Win32ColourImpl s_instance; 8197 8198 IConfigPtr config = getCurrentContext().getConfig(); 8199 UseColour::YesOrNo colourMode = config 8200 ? config->useColour() 8201 : UseColour::Auto; 8202 if( colourMode == UseColour::Auto ) 8203 colourMode = UseColour::Yes; 8204 return colourMode == UseColour::Yes 8205 ? &s_instance 8206 : NoColourImpl::instance(); 8207 } 8208 8209 } // end anon namespace 8210 } // end namespace Catch 8211 8212 #elif defined( CATCH_CONFIG_COLOUR_ANSI ) ////////////////////////////////////// 8213 8214 #include <unistd.h> 8215 8216 namespace Catch { 8217 namespace { 8218 8219 // use POSIX/ ANSI console terminal codes 8220 // Thanks to Adam Strzelecki for original contribution 8221 // (http://github.com/nanoant) 8222 // https://github.com/philsquared/Catch/pull/131 8223 class PosixColourImpl : public IColourImpl { 8224 public: 8225 void use( Colour::Code _colourCode ) override { 8226 switch( _colourCode ) { 8227 case Colour::None: 8228 case Colour::White: return setColour( "[0m" ); 8229 case Colour::Red: return setColour( "[0;31m" ); 8230 case Colour::Green: return setColour( "[0;32m" ); 8231 case Colour::Blue: return setColour( "[0;34m" ); 8232 case Colour::Cyan: return setColour( "[0;36m" ); 8233 case Colour::Yellow: return setColour( "[0;33m" ); 8234 case Colour::Grey: return setColour( "[1;30m" ); 8235 8236 case Colour::LightGrey: return setColour( "[0;37m" ); 8237 case Colour::BrightRed: return setColour( "[1;31m" ); 8238 case Colour::BrightGreen: return setColour( "[1;32m" ); 8239 case Colour::BrightWhite: return setColour( "[1;37m" ); 8240 case Colour::BrightYellow: return setColour( "[1;33m" ); 8241 8242 case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" ); 8243 default: CATCH_INTERNAL_ERROR( "Unknown colour requested" ); 8244 } 8245 } 8246 static IColourImpl* instance() { 8247 static PosixColourImpl s_instance; 8248 return &s_instance; 8249 } 8250 8251 private: 8252 void setColour( const char* _escapeCode ) { 8253 getCurrentContext().getConfig()->stream() 8254 << '\033' << _escapeCode; 8255 } 8256 }; 8257 8258 bool useColourOnPlatform() { 8259 return 8260 #ifdef CATCH_PLATFORM_MAC 8261 !isDebuggerActive() && 8262 #endif 8263 #if !(defined(__DJGPP__) && defined(__STRICT_ANSI__)) 8264 isatty(STDOUT_FILENO) 8265 #else 8266 false 8267 #endif 8268 ; 8269 } 8270 IColourImpl* platformColourInstance() { 8271 ErrnoGuard guard; 8272 IConfigPtr config = getCurrentContext().getConfig(); 8273 UseColour::YesOrNo colourMode = config 8274 ? config->useColour() 8275 : UseColour::Auto; 8276 if( colourMode == UseColour::Auto ) 8277 colourMode = useColourOnPlatform() 8278 ? UseColour::Yes 8279 : UseColour::No; 8280 return colourMode == UseColour::Yes 8281 ? PosixColourImpl::instance() 8282 : NoColourImpl::instance(); 8283 } 8284 8285 } // end anon namespace 8286 } // end namespace Catch 8287 8288 #else // not Windows or ANSI /////////////////////////////////////////////// 8289 8290 namespace Catch { 8291 8292 static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); } 8293 8294 } // end namespace Catch 8295 8296 #endif // Windows/ ANSI/ None 8297 8298 namespace Catch { 8299 8300 Colour::Colour( Code _colourCode ) { use( _colourCode ); } 8301 Colour::Colour( Colour&& rhs ) noexcept { 8302 m_moved = rhs.m_moved; 8303 rhs.m_moved = true; 8304 } 8305 Colour& Colour::operator=( Colour&& rhs ) noexcept { 8306 m_moved = rhs.m_moved; 8307 rhs.m_moved = true; 8308 return *this; 8309 } 8310 8311 Colour::~Colour(){ if( !m_moved ) use( None ); } 8312 8313 void Colour::use( Code _colourCode ) { 8314 static IColourImpl* impl = platformColourInstance(); 8315 impl->use( _colourCode ); 8316 } 8317 8318 std::ostream& operator << ( std::ostream& os, Colour const& ) { 8319 return os; 8320 } 8321 8322 } // end namespace Catch 8323 8324 #if defined(__clang__) 8325 # pragma clang diagnostic pop 8326 #endif 8327 8328 // end catch_console_colour.cpp 8329 // start catch_context.cpp 8330 8331 namespace Catch { 8332 8333 class Context : public IMutableContext, NonCopyable { 8334 8335 public: // IContext 8336 IResultCapture* getResultCapture() override { 8337 return m_resultCapture; 8338 } 8339 IRunner* getRunner() override { 8340 return m_runner; 8341 } 8342 8343 IConfigPtr const& getConfig() const override { 8344 return m_config; 8345 } 8346 8347 ~Context() override; 8348 8349 public: // IMutableContext 8350 void setResultCapture( IResultCapture* resultCapture ) override { 8351 m_resultCapture = resultCapture; 8352 } 8353 void setRunner( IRunner* runner ) override { 8354 m_runner = runner; 8355 } 8356 void setConfig( IConfigPtr const& config ) override { 8357 m_config = config; 8358 } 8359 8360 friend IMutableContext& getCurrentMutableContext(); 8361 8362 private: 8363 IConfigPtr m_config; 8364 IRunner* m_runner = nullptr; 8365 IResultCapture* m_resultCapture = nullptr; 8366 }; 8367 8368 IMutableContext *IMutableContext::currentContext = nullptr; 8369 8370 void IMutableContext::createContext() 8371 { 8372 currentContext = new Context(); 8373 } 8374 8375 void cleanUpContext() { 8376 delete IMutableContext::currentContext; 8377 IMutableContext::currentContext = nullptr; 8378 } 8379 IContext::~IContext() = default; 8380 IMutableContext::~IMutableContext() = default; 8381 Context::~Context() = default; 8382 } 8383 // end catch_context.cpp 8384 // start catch_debug_console.cpp 8385 8386 // start catch_debug_console.h 8387 8388 #include <string> 8389 8390 namespace Catch { 8391 void writeToDebugConsole( std::string const& text ); 8392 } 8393 8394 // end catch_debug_console.h 8395 #ifdef CATCH_PLATFORM_WINDOWS 8396 8397 namespace Catch { 8398 void writeToDebugConsole( std::string const& text ) { 8399 ::OutputDebugStringA( text.c_str() ); 8400 } 8401 } 8402 8403 #else 8404 8405 namespace Catch { 8406 void writeToDebugConsole( std::string const& text ) { 8407 // !TBD: Need a version for Mac/ XCode and other IDEs 8408 Catch::cout() << text; 8409 } 8410 } 8411 8412 #endif // Platform 8413 // end catch_debug_console.cpp 8414 // start catch_debugger.cpp 8415 8416 #ifdef CATCH_PLATFORM_MAC 8417 8418 # include <assert.h> 8419 # include <stdbool.h> 8420 # include <sys/types.h> 8421 # include <unistd.h> 8422 # include <cstddef> 8423 # include <ostream> 8424 8425 #ifdef __apple_build_version__ 8426 // These headers will only compile with AppleClang (XCode) 8427 // For other compilers (Clang, GCC, ... ) we need to exclude them 8428 # include <sys/sysctl.h> 8429 #endif 8430 8431 namespace Catch { 8432 #ifdef __apple_build_version__ 8433 // The following function is taken directly from the following technical note: 8434 // https://developer.apple.com/library/archive/qa/qa1361/_index.html 8435 8436 // Returns true if the current process is being debugged (either 8437 // running under the debugger or has a debugger attached post facto). 8438 bool isDebuggerActive(){ 8439 int mib[4]; 8440 struct kinfo_proc info; 8441 std::size_t size; 8442 8443 // Initialize the flags so that, if sysctl fails for some bizarre 8444 // reason, we get a predictable result. 8445 8446 info.kp_proc.p_flag = 0; 8447 8448 // Initialize mib, which tells sysctl the info we want, in this case 8449 // we're looking for information about a specific process ID. 8450 8451 mib[0] = CTL_KERN; 8452 mib[1] = KERN_PROC; 8453 mib[2] = KERN_PROC_PID; 8454 mib[3] = getpid(); 8455 8456 // Call sysctl. 8457 8458 size = sizeof(info); 8459 if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, nullptr, 0) != 0 ) { 8460 Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; 8461 return false; 8462 } 8463 8464 // We're being debugged if the P_TRACED flag is set. 8465 8466 return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); 8467 } 8468 #else 8469 bool isDebuggerActive() { 8470 // We need to find another way to determine this for non-appleclang compilers on macOS 8471 return false; 8472 } 8473 #endif 8474 } // namespace Catch 8475 8476 #elif defined(CATCH_PLATFORM_LINUX) 8477 #include <fstream> 8478 #include <string> 8479 8480 namespace Catch{ 8481 // The standard POSIX way of detecting a debugger is to attempt to 8482 // ptrace() the process, but this needs to be done from a child and not 8483 // this process itself to still allow attaching to this process later 8484 // if wanted, so is rather heavy. Under Linux we have the PID of the 8485 // "debugger" (which doesn't need to be gdb, of course, it could also 8486 // be strace, for example) in /proc/$PID/status, so just get it from 8487 // there instead. 8488 bool isDebuggerActive(){ 8489 // Libstdc++ has a bug, where std::ifstream sets errno to 0 8490 // This way our users can properly assert over errno values 8491 ErrnoGuard guard; 8492 std::ifstream in("/proc/self/status"); 8493 for( std::string line; std::getline(in, line); ) { 8494 static const int PREFIX_LEN = 11; 8495 if( line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0 ) { 8496 // We're traced if the PID is not 0 and no other PID starts 8497 // with 0 digit, so it's enough to check for just a single 8498 // character. 8499 return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0'; 8500 } 8501 } 8502 8503 return false; 8504 } 8505 } // namespace Catch 8506 #elif defined(_MSC_VER) 8507 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); 8508 namespace Catch { 8509 bool isDebuggerActive() { 8510 return IsDebuggerPresent() != 0; 8511 } 8512 } 8513 #elif defined(__MINGW32__) 8514 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); 8515 namespace Catch { 8516 bool isDebuggerActive() { 8517 return IsDebuggerPresent() != 0; 8518 } 8519 } 8520 #else 8521 namespace Catch { 8522 bool isDebuggerActive() { return false; } 8523 } 8524 #endif // Platform 8525 // end catch_debugger.cpp 8526 // start catch_decomposer.cpp 8527 8528 namespace Catch { 8529 8530 ITransientExpression::~ITransientExpression() = default; 8531 8532 void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ) { 8533 if( lhs.size() + rhs.size() < 40 && 8534 lhs.find('\n') == std::string::npos && 8535 rhs.find('\n') == std::string::npos ) 8536 os << lhs << " " << op << " " << rhs; 8537 else 8538 os << lhs << "\n" << op << "\n" << rhs; 8539 } 8540 } 8541 // end catch_decomposer.cpp 8542 // start catch_enforce.cpp 8543 8544 namespace Catch { 8545 #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER) 8546 [[noreturn]] 8547 void throw_exception(std::exception const& e) { 8548 Catch::cerr() << "Catch will terminate because it needed to throw an exception.\n" 8549 << "The message was: " << e.what() << '\n'; 8550 std::terminate(); 8551 } 8552 #endif 8553 } // namespace Catch; 8554 // end catch_enforce.cpp 8555 // start catch_errno_guard.cpp 8556 8557 #include <cerrno> 8558 8559 namespace Catch { 8560 ErrnoGuard::ErrnoGuard():m_oldErrno(errno){} 8561 ErrnoGuard::~ErrnoGuard() { errno = m_oldErrno; } 8562 } 8563 // end catch_errno_guard.cpp 8564 // start catch_exception_translator_registry.cpp 8565 8566 // start catch_exception_translator_registry.h 8567 8568 #include <vector> 8569 #include <string> 8570 #include <memory> 8571 8572 namespace Catch { 8573 8574 class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { 8575 public: 8576 ~ExceptionTranslatorRegistry(); 8577 virtual void registerTranslator( const IExceptionTranslator* translator ); 8578 std::string translateActiveException() const override; 8579 std::string tryTranslators() const; 8580 8581 private: 8582 std::vector<std::unique_ptr<IExceptionTranslator const>> m_translators; 8583 }; 8584 } 8585 8586 // end catch_exception_translator_registry.h 8587 #ifdef __OBJC__ 8588 #import "Foundation/Foundation.h" 8589 #endif 8590 8591 namespace Catch { 8592 8593 ExceptionTranslatorRegistry::~ExceptionTranslatorRegistry() { 8594 } 8595 8596 void ExceptionTranslatorRegistry::registerTranslator( const IExceptionTranslator* translator ) { 8597 m_translators.push_back( std::unique_ptr<const IExceptionTranslator>( translator ) ); 8598 } 8599 8600 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 8601 std::string ExceptionTranslatorRegistry::translateActiveException() const { 8602 try { 8603 #ifdef __OBJC__ 8604 // In Objective-C try objective-c exceptions first 8605 @try { 8606 return tryTranslators(); 8607 } 8608 @catch (NSException *exception) { 8609 return Catch::Detail::stringify( [exception description] ); 8610 } 8611 #else 8612 // Compiling a mixed mode project with MSVC means that CLR 8613 // exceptions will be caught in (...) as well. However, these 8614 // do not fill-in std::current_exception and thus lead to crash 8615 // when attempting rethrow. 8616 // /EHa switch also causes structured exceptions to be caught 8617 // here, but they fill-in current_exception properly, so 8618 // at worst the output should be a little weird, instead of 8619 // causing a crash. 8620 if (std::current_exception() == nullptr) { 8621 return "Non C++ exception. Possibly a CLR exception."; 8622 } 8623 return tryTranslators(); 8624 #endif 8625 } 8626 catch( TestFailureException& ) { 8627 std::rethrow_exception(std::current_exception()); 8628 } 8629 catch( std::exception& ex ) { 8630 return ex.what(); 8631 } 8632 catch( std::string& msg ) { 8633 return msg; 8634 } 8635 catch( const char* msg ) { 8636 return msg; 8637 } 8638 catch(...) { 8639 return "Unknown exception"; 8640 } 8641 } 8642 8643 std::string ExceptionTranslatorRegistry::tryTranslators() const { 8644 if (m_translators.empty()) { 8645 std::rethrow_exception(std::current_exception()); 8646 } else { 8647 return m_translators[0]->translate(m_translators.begin() + 1, m_translators.end()); 8648 } 8649 } 8650 8651 #else // ^^ Exceptions are enabled // Exceptions are disabled vv 8652 std::string ExceptionTranslatorRegistry::translateActiveException() const { 8653 CATCH_INTERNAL_ERROR("Attempted to translate active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!"); 8654 } 8655 8656 std::string ExceptionTranslatorRegistry::tryTranslators() const { 8657 CATCH_INTERNAL_ERROR("Attempted to use exception translators under CATCH_CONFIG_DISABLE_EXCEPTIONS!"); 8658 } 8659 #endif 8660 8661 } 8662 // end catch_exception_translator_registry.cpp 8663 // start catch_fatal_condition.cpp 8664 8665 #if defined(__GNUC__) 8666 # pragma GCC diagnostic push 8667 # pragma GCC diagnostic ignored "-Wmissing-field-initializers" 8668 #endif 8669 8670 #if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS ) 8671 8672 namespace { 8673 // Report the error condition 8674 void reportFatal( char const * const message ) { 8675 Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message ); 8676 } 8677 } 8678 8679 #endif // signals/SEH handling 8680 8681 #if defined( CATCH_CONFIG_WINDOWS_SEH ) 8682 8683 namespace Catch { 8684 struct SignalDefs { DWORD id; const char* name; }; 8685 8686 // There is no 1-1 mapping between signals and windows exceptions. 8687 // Windows can easily distinguish between SO and SigSegV, 8688 // but SigInt, SigTerm, etc are handled differently. 8689 static SignalDefs signalDefs[] = { 8690 { static_cast<DWORD>(EXCEPTION_ILLEGAL_INSTRUCTION), "SIGILL - Illegal instruction signal" }, 8691 { static_cast<DWORD>(EXCEPTION_STACK_OVERFLOW), "SIGSEGV - Stack overflow" }, 8692 { static_cast<DWORD>(EXCEPTION_ACCESS_VIOLATION), "SIGSEGV - Segmentation violation signal" }, 8693 { static_cast<DWORD>(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error" }, 8694 }; 8695 8696 LONG CALLBACK FatalConditionHandler::handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) { 8697 for (auto const& def : signalDefs) { 8698 if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) { 8699 reportFatal(def.name); 8700 } 8701 } 8702 // If its not an exception we care about, pass it along. 8703 // This stops us from eating debugger breaks etc. 8704 return EXCEPTION_CONTINUE_SEARCH; 8705 } 8706 8707 FatalConditionHandler::FatalConditionHandler() { 8708 isSet = true; 8709 // 32k seems enough for Catch to handle stack overflow, 8710 // but the value was found experimentally, so there is no strong guarantee 8711 guaranteeSize = 32 * 1024; 8712 exceptionHandlerHandle = nullptr; 8713 // Register as first handler in current chain 8714 exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException); 8715 // Pass in guarantee size to be filled 8716 SetThreadStackGuarantee(&guaranteeSize); 8717 } 8718 8719 void FatalConditionHandler::reset() { 8720 if (isSet) { 8721 RemoveVectoredExceptionHandler(exceptionHandlerHandle); 8722 SetThreadStackGuarantee(&guaranteeSize); 8723 exceptionHandlerHandle = nullptr; 8724 isSet = false; 8725 } 8726 } 8727 8728 FatalConditionHandler::~FatalConditionHandler() { 8729 reset(); 8730 } 8731 8732 bool FatalConditionHandler::isSet = false; 8733 ULONG FatalConditionHandler::guaranteeSize = 0; 8734 PVOID FatalConditionHandler::exceptionHandlerHandle = nullptr; 8735 8736 } // namespace Catch 8737 8738 #elif defined( CATCH_CONFIG_POSIX_SIGNALS ) 8739 8740 namespace Catch { 8741 8742 struct SignalDefs { 8743 int id; 8744 const char* name; 8745 }; 8746 8747 // 32kb for the alternate stack seems to be sufficient. However, this value 8748 // is experimentally determined, so that's not guaranteed. 8749 constexpr static std::size_t sigStackSize = 32768 >= MINSIGSTKSZ ? 32768 : MINSIGSTKSZ; 8750 8751 static SignalDefs signalDefs[] = { 8752 { SIGINT, "SIGINT - Terminal interrupt signal" }, 8753 { SIGILL, "SIGILL - Illegal instruction signal" }, 8754 { SIGFPE, "SIGFPE - Floating point error signal" }, 8755 { SIGSEGV, "SIGSEGV - Segmentation violation signal" }, 8756 { SIGTERM, "SIGTERM - Termination request signal" }, 8757 { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" } 8758 }; 8759 8760 void FatalConditionHandler::handleSignal( int sig ) { 8761 char const * name = "<unknown signal>"; 8762 for (auto const& def : signalDefs) { 8763 if (sig == def.id) { 8764 name = def.name; 8765 break; 8766 } 8767 } 8768 reset(); 8769 reportFatal(name); 8770 raise( sig ); 8771 } 8772 8773 FatalConditionHandler::FatalConditionHandler() { 8774 isSet = true; 8775 stack_t sigStack; 8776 sigStack.ss_sp = altStackMem; 8777 sigStack.ss_size = sigStackSize; 8778 sigStack.ss_flags = 0; 8779 sigaltstack(&sigStack, &oldSigStack); 8780 struct sigaction sa = { }; 8781 8782 sa.sa_handler = handleSignal; 8783 sa.sa_flags = SA_ONSTACK; 8784 for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) { 8785 sigaction(signalDefs[i].id, &sa, &oldSigActions[i]); 8786 } 8787 } 8788 8789 FatalConditionHandler::~FatalConditionHandler() { 8790 reset(); 8791 } 8792 8793 void FatalConditionHandler::reset() { 8794 if( isSet ) { 8795 // Set signals back to previous values -- hopefully nobody overwrote them in the meantime 8796 for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) { 8797 sigaction(signalDefs[i].id, &oldSigActions[i], nullptr); 8798 } 8799 // Return the old stack 8800 sigaltstack(&oldSigStack, nullptr); 8801 isSet = false; 8802 } 8803 } 8804 8805 bool FatalConditionHandler::isSet = false; 8806 struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {}; 8807 stack_t FatalConditionHandler::oldSigStack = {}; 8808 char FatalConditionHandler::altStackMem[sigStackSize] = {}; 8809 8810 } // namespace Catch 8811 8812 #else 8813 8814 namespace Catch { 8815 void FatalConditionHandler::reset() {} 8816 } 8817 8818 #endif // signals/SEH handling 8819 8820 #if defined(__GNUC__) 8821 # pragma GCC diagnostic pop 8822 #endif 8823 // end catch_fatal_condition.cpp 8824 // start catch_generators.cpp 8825 8826 // start catch_random_number_generator.h 8827 8828 #include <algorithm> 8829 #include <random> 8830 8831 namespace Catch { 8832 8833 struct IConfig; 8834 8835 std::mt19937& rng(); 8836 void seedRng( IConfig const& config ); 8837 unsigned int rngSeed(); 8838 8839 } 8840 8841 // end catch_random_number_generator.h 8842 #include <limits> 8843 #include <set> 8844 8845 namespace Catch { 8846 8847 IGeneratorTracker::~IGeneratorTracker() {} 8848 8849 const char* GeneratorException::what() const noexcept { 8850 return m_msg; 8851 } 8852 8853 namespace Generators { 8854 8855 GeneratorUntypedBase::~GeneratorUntypedBase() {} 8856 8857 auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& { 8858 return getResultCapture().acquireGeneratorTracker( lineInfo ); 8859 } 8860 8861 } // namespace Generators 8862 } // namespace Catch 8863 // end catch_generators.cpp 8864 // start catch_interfaces_capture.cpp 8865 8866 namespace Catch { 8867 IResultCapture::~IResultCapture() = default; 8868 } 8869 // end catch_interfaces_capture.cpp 8870 // start catch_interfaces_config.cpp 8871 8872 namespace Catch { 8873 IConfig::~IConfig() = default; 8874 } 8875 // end catch_interfaces_config.cpp 8876 // start catch_interfaces_exception.cpp 8877 8878 namespace Catch { 8879 IExceptionTranslator::~IExceptionTranslator() = default; 8880 IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() = default; 8881 } 8882 // end catch_interfaces_exception.cpp 8883 // start catch_interfaces_registry_hub.cpp 8884 8885 namespace Catch { 8886 IRegistryHub::~IRegistryHub() = default; 8887 IMutableRegistryHub::~IMutableRegistryHub() = default; 8888 } 8889 // end catch_interfaces_registry_hub.cpp 8890 // start catch_interfaces_reporter.cpp 8891 8892 // start catch_reporter_listening.h 8893 8894 namespace Catch { 8895 8896 class ListeningReporter : public IStreamingReporter { 8897 using Reporters = std::vector<IStreamingReporterPtr>; 8898 Reporters m_listeners; 8899 IStreamingReporterPtr m_reporter = nullptr; 8900 ReporterPreferences m_preferences; 8901 8902 public: 8903 ListeningReporter(); 8904 8905 void addListener( IStreamingReporterPtr&& listener ); 8906 void addReporter( IStreamingReporterPtr&& reporter ); 8907 8908 public: // IStreamingReporter 8909 8910 ReporterPreferences getPreferences() const override; 8911 8912 void noMatchingTestCases( std::string const& spec ) override; 8913 8914 static std::set<Verbosity> getSupportedVerbosities(); 8915 8916 void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) override; 8917 void benchmarkEnded( BenchmarkStats const& benchmarkStats ) override; 8918 8919 void testRunStarting( TestRunInfo const& testRunInfo ) override; 8920 void testGroupStarting( GroupInfo const& groupInfo ) override; 8921 void testCaseStarting( TestCaseInfo const& testInfo ) override; 8922 void sectionStarting( SectionInfo const& sectionInfo ) override; 8923 void assertionStarting( AssertionInfo const& assertionInfo ) override; 8924 8925 // The return value indicates if the messages buffer should be cleared: 8926 bool assertionEnded( AssertionStats const& assertionStats ) override; 8927 void sectionEnded( SectionStats const& sectionStats ) override; 8928 void testCaseEnded( TestCaseStats const& testCaseStats ) override; 8929 void testGroupEnded( TestGroupStats const& testGroupStats ) override; 8930 void testRunEnded( TestRunStats const& testRunStats ) override; 8931 8932 void skipTest( TestCaseInfo const& testInfo ) override; 8933 bool isMulti() const override; 8934 8935 }; 8936 8937 } // end namespace Catch 8938 8939 // end catch_reporter_listening.h 8940 namespace Catch { 8941 8942 ReporterConfig::ReporterConfig( IConfigPtr const& _fullConfig ) 8943 : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} 8944 8945 ReporterConfig::ReporterConfig( IConfigPtr const& _fullConfig, std::ostream& _stream ) 8946 : m_stream( &_stream ), m_fullConfig( _fullConfig ) {} 8947 8948 std::ostream& ReporterConfig::stream() const { return *m_stream; } 8949 IConfigPtr ReporterConfig::fullConfig() const { return m_fullConfig; } 8950 8951 TestRunInfo::TestRunInfo( std::string const& _name ) : name( _name ) {} 8952 8953 GroupInfo::GroupInfo( std::string const& _name, 8954 std::size_t _groupIndex, 8955 std::size_t _groupsCount ) 8956 : name( _name ), 8957 groupIndex( _groupIndex ), 8958 groupsCounts( _groupsCount ) 8959 {} 8960 8961 AssertionStats::AssertionStats( AssertionResult const& _assertionResult, 8962 std::vector<MessageInfo> const& _infoMessages, 8963 Totals const& _totals ) 8964 : assertionResult( _assertionResult ), 8965 infoMessages( _infoMessages ), 8966 totals( _totals ) 8967 { 8968 assertionResult.m_resultData.lazyExpression.m_transientExpression = _assertionResult.m_resultData.lazyExpression.m_transientExpression; 8969 8970 if( assertionResult.hasMessage() ) { 8971 // Copy message into messages list. 8972 // !TBD This should have been done earlier, somewhere 8973 MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); 8974 builder << assertionResult.getMessage(); 8975 builder.m_info.message = builder.m_stream.str(); 8976 8977 infoMessages.push_back( builder.m_info ); 8978 } 8979 } 8980 8981 AssertionStats::~AssertionStats() = default; 8982 8983 SectionStats::SectionStats( SectionInfo const& _sectionInfo, 8984 Counts const& _assertions, 8985 double _durationInSeconds, 8986 bool _missingAssertions ) 8987 : sectionInfo( _sectionInfo ), 8988 assertions( _assertions ), 8989 durationInSeconds( _durationInSeconds ), 8990 missingAssertions( _missingAssertions ) 8991 {} 8992 8993 SectionStats::~SectionStats() = default; 8994 8995 TestCaseStats::TestCaseStats( TestCaseInfo const& _testInfo, 8996 Totals const& _totals, 8997 std::string const& _stdOut, 8998 std::string const& _stdErr, 8999 bool _aborting ) 9000 : testInfo( _testInfo ), 9001 totals( _totals ), 9002 stdOut( _stdOut ), 9003 stdErr( _stdErr ), 9004 aborting( _aborting ) 9005 {} 9006 9007 TestCaseStats::~TestCaseStats() = default; 9008 9009 TestGroupStats::TestGroupStats( GroupInfo const& _groupInfo, 9010 Totals const& _totals, 9011 bool _aborting ) 9012 : groupInfo( _groupInfo ), 9013 totals( _totals ), 9014 aborting( _aborting ) 9015 {} 9016 9017 TestGroupStats::TestGroupStats( GroupInfo const& _groupInfo ) 9018 : groupInfo( _groupInfo ), 9019 aborting( false ) 9020 {} 9021 9022 TestGroupStats::~TestGroupStats() = default; 9023 9024 TestRunStats::TestRunStats( TestRunInfo const& _runInfo, 9025 Totals const& _totals, 9026 bool _aborting ) 9027 : runInfo( _runInfo ), 9028 totals( _totals ), 9029 aborting( _aborting ) 9030 {} 9031 9032 TestRunStats::~TestRunStats() = default; 9033 9034 void IStreamingReporter::fatalErrorEncountered( StringRef ) {} 9035 bool IStreamingReporter::isMulti() const { return false; } 9036 9037 IReporterFactory::~IReporterFactory() = default; 9038 IReporterRegistry::~IReporterRegistry() = default; 9039 9040 } // end namespace Catch 9041 // end catch_interfaces_reporter.cpp 9042 // start catch_interfaces_runner.cpp 9043 9044 namespace Catch { 9045 IRunner::~IRunner() = default; 9046 } 9047 // end catch_interfaces_runner.cpp 9048 // start catch_interfaces_testcase.cpp 9049 9050 namespace Catch { 9051 ITestInvoker::~ITestInvoker() = default; 9052 ITestCaseRegistry::~ITestCaseRegistry() = default; 9053 } 9054 // end catch_interfaces_testcase.cpp 9055 // start catch_leak_detector.cpp 9056 9057 #ifdef CATCH_CONFIG_WINDOWS_CRTDBG 9058 #include <crtdbg.h> 9059 9060 namespace Catch { 9061 9062 LeakDetector::LeakDetector() { 9063 int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); 9064 flag |= _CRTDBG_LEAK_CHECK_DF; 9065 flag |= _CRTDBG_ALLOC_MEM_DF; 9066 _CrtSetDbgFlag(flag); 9067 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); 9068 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); 9069 // Change this to leaking allocation's number to break there 9070 _CrtSetBreakAlloc(-1); 9071 } 9072 } 9073 9074 #else 9075 9076 Catch::LeakDetector::LeakDetector() {} 9077 9078 #endif 9079 9080 Catch::LeakDetector::~LeakDetector() { 9081 Catch::cleanUp(); 9082 } 9083 // end catch_leak_detector.cpp 9084 // start catch_list.cpp 9085 9086 // start catch_list.h 9087 9088 #include <set> 9089 9090 namespace Catch { 9091 9092 std::size_t listTests( Config const& config ); 9093 9094 std::size_t listTestsNamesOnly( Config const& config ); 9095 9096 struct TagInfo { 9097 void add( std::string const& spelling ); 9098 std::string all() const; 9099 9100 std::set<std::string> spellings; 9101 std::size_t count = 0; 9102 }; 9103 9104 std::size_t listTags( Config const& config ); 9105 9106 std::size_t listReporters(); 9107 9108 Option<std::size_t> list( std::shared_ptr<Config> const& config ); 9109 9110 } // end namespace Catch 9111 9112 // end catch_list.h 9113 // start catch_text.h 9114 9115 namespace Catch { 9116 using namespace clara::TextFlow; 9117 } 9118 9119 // end catch_text.h 9120 #include <limits> 9121 #include <algorithm> 9122 #include <iomanip> 9123 9124 namespace Catch { 9125 9126 std::size_t listTests( Config const& config ) { 9127 TestSpec testSpec = config.testSpec(); 9128 if( config.hasTestFilters() ) 9129 Catch::cout() << "Matching test cases:\n"; 9130 else { 9131 Catch::cout() << "All available test cases:\n"; 9132 } 9133 9134 auto matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); 9135 for( auto const& testCaseInfo : matchedTestCases ) { 9136 Colour::Code colour = testCaseInfo.isHidden() 9137 ? Colour::SecondaryText 9138 : Colour::None; 9139 Colour colourGuard( colour ); 9140 9141 Catch::cout() << Column( testCaseInfo.name ).initialIndent( 2 ).indent( 4 ) << "\n"; 9142 if( config.verbosity() >= Verbosity::High ) { 9143 Catch::cout() << Column( Catch::Detail::stringify( testCaseInfo.lineInfo ) ).indent(4) << std::endl; 9144 std::string description = testCaseInfo.description; 9145 if( description.empty() ) 9146 description = "(NO DESCRIPTION)"; 9147 Catch::cout() << Column( description ).indent(4) << std::endl; 9148 } 9149 if( !testCaseInfo.tags.empty() ) 9150 Catch::cout() << Column( testCaseInfo.tagsAsString() ).indent( 6 ) << "\n"; 9151 } 9152 9153 if( !config.hasTestFilters() ) 9154 Catch::cout() << pluralise( matchedTestCases.size(), "test case" ) << '\n' << std::endl; 9155 else 9156 Catch::cout() << pluralise( matchedTestCases.size(), "matching test case" ) << '\n' << std::endl; 9157 return matchedTestCases.size(); 9158 } 9159 9160 std::size_t listTestsNamesOnly( Config const& config ) { 9161 TestSpec testSpec = config.testSpec(); 9162 std::size_t matchedTests = 0; 9163 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); 9164 for( auto const& testCaseInfo : matchedTestCases ) { 9165 matchedTests++; 9166 if( startsWith( testCaseInfo.name, '#' ) ) 9167 Catch::cout() << '"' << testCaseInfo.name << '"'; 9168 else 9169 Catch::cout() << testCaseInfo.name; 9170 if ( config.verbosity() >= Verbosity::High ) 9171 Catch::cout() << "\t@" << testCaseInfo.lineInfo; 9172 Catch::cout() << std::endl; 9173 } 9174 return matchedTests; 9175 } 9176 9177 void TagInfo::add( std::string const& spelling ) { 9178 ++count; 9179 spellings.insert( spelling ); 9180 } 9181 9182 std::string TagInfo::all() const { 9183 std::string out; 9184 for( auto const& spelling : spellings ) 9185 out += "[" + spelling + "]"; 9186 return out; 9187 } 9188 9189 std::size_t listTags( Config const& config ) { 9190 TestSpec testSpec = config.testSpec(); 9191 if( config.hasTestFilters() ) 9192 Catch::cout() << "Tags for matching test cases:\n"; 9193 else { 9194 Catch::cout() << "All available tags:\n"; 9195 } 9196 9197 std::map<std::string, TagInfo> tagCounts; 9198 9199 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); 9200 for( auto const& testCase : matchedTestCases ) { 9201 for( auto const& tagName : testCase.getTestCaseInfo().tags ) { 9202 std::string lcaseTagName = toLower( tagName ); 9203 auto countIt = tagCounts.find( lcaseTagName ); 9204 if( countIt == tagCounts.end() ) 9205 countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first; 9206 countIt->second.add( tagName ); 9207 } 9208 } 9209 9210 for( auto const& tagCount : tagCounts ) { 9211 ReusableStringStream rss; 9212 rss << " " << std::setw(2) << tagCount.second.count << " "; 9213 auto str = rss.str(); 9214 auto wrapper = Column( tagCount.second.all() ) 9215 .initialIndent( 0 ) 9216 .indent( str.size() ) 9217 .width( CATCH_CONFIG_CONSOLE_WIDTH-10 ); 9218 Catch::cout() << str << wrapper << '\n'; 9219 } 9220 Catch::cout() << pluralise( tagCounts.size(), "tag" ) << '\n' << std::endl; 9221 return tagCounts.size(); 9222 } 9223 9224 std::size_t listReporters() { 9225 Catch::cout() << "Available reporters:\n"; 9226 IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); 9227 std::size_t maxNameLen = 0; 9228 for( auto const& factoryKvp : factories ) 9229 maxNameLen = (std::max)( maxNameLen, factoryKvp.first.size() ); 9230 9231 for( auto const& factoryKvp : factories ) { 9232 Catch::cout() 9233 << Column( factoryKvp.first + ":" ) 9234 .indent(2) 9235 .width( 5+maxNameLen ) 9236 + Column( factoryKvp.second->getDescription() ) 9237 .initialIndent(0) 9238 .indent(2) 9239 .width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) 9240 << "\n"; 9241 } 9242 Catch::cout() << std::endl; 9243 return factories.size(); 9244 } 9245 9246 Option<std::size_t> list( std::shared_ptr<Config> const& config ) { 9247 Option<std::size_t> listedCount; 9248 getCurrentMutableContext().setConfig( config ); 9249 if( config->listTests() ) 9250 listedCount = listedCount.valueOr(0) + listTests( *config ); 9251 if( config->listTestNamesOnly() ) 9252 listedCount = listedCount.valueOr(0) + listTestsNamesOnly( *config ); 9253 if( config->listTags() ) 9254 listedCount = listedCount.valueOr(0) + listTags( *config ); 9255 if( config->listReporters() ) 9256 listedCount = listedCount.valueOr(0) + listReporters(); 9257 return listedCount; 9258 } 9259 9260 } // end namespace Catch 9261 // end catch_list.cpp 9262 // start catch_matchers.cpp 9263 9264 namespace Catch { 9265 namespace Matchers { 9266 namespace Impl { 9267 9268 std::string MatcherUntypedBase::toString() const { 9269 if( m_cachedToString.empty() ) 9270 m_cachedToString = describe(); 9271 return m_cachedToString; 9272 } 9273 9274 MatcherUntypedBase::~MatcherUntypedBase() = default; 9275 9276 } // namespace Impl 9277 } // namespace Matchers 9278 9279 using namespace Matchers; 9280 using Matchers::Impl::MatcherBase; 9281 9282 } // namespace Catch 9283 // end catch_matchers.cpp 9284 // start catch_matchers_floating.cpp 9285 9286 // start catch_polyfills.hpp 9287 9288 namespace Catch { 9289 bool isnan(float f); 9290 bool isnan(double d); 9291 } 9292 9293 // end catch_polyfills.hpp 9294 // start catch_to_string.hpp 9295 9296 #include <string> 9297 9298 namespace Catch { 9299 template <typename T> 9300 std::string to_string(T const& t) { 9301 #if defined(CATCH_CONFIG_CPP11_TO_STRING) 9302 return std::to_string(t); 9303 #else 9304 ReusableStringStream rss; 9305 rss << t; 9306 return rss.str(); 9307 #endif 9308 } 9309 } // end namespace Catch 9310 9311 // end catch_to_string.hpp 9312 #include <cstdlib> 9313 #include <cstdint> 9314 #include <cstring> 9315 9316 namespace Catch { 9317 namespace Matchers { 9318 namespace Floating { 9319 enum class FloatingPointKind : uint8_t { 9320 Float, 9321 Double 9322 }; 9323 } 9324 } 9325 } 9326 9327 namespace { 9328 9329 template <typename T> 9330 struct Converter; 9331 9332 template <> 9333 struct Converter<float> { 9334 static_assert(sizeof(float) == sizeof(int32_t), "Important ULP matcher assumption violated"); 9335 Converter(float f) { 9336 std::memcpy(&i, &f, sizeof(f)); 9337 } 9338 int32_t i; 9339 }; 9340 9341 template <> 9342 struct Converter<double> { 9343 static_assert(sizeof(double) == sizeof(int64_t), "Important ULP matcher assumption violated"); 9344 Converter(double d) { 9345 std::memcpy(&i, &d, sizeof(d)); 9346 } 9347 int64_t i; 9348 }; 9349 9350 template <typename T> 9351 auto convert(T t) -> Converter<T> { 9352 return Converter<T>(t); 9353 } 9354 9355 template <typename FP> 9356 bool almostEqualUlps(FP lhs, FP rhs, int maxUlpDiff) { 9357 // Comparison with NaN should always be false. 9358 // This way we can rule it out before getting into the ugly details 9359 if (Catch::isnan(lhs) || Catch::isnan(rhs)) { 9360 return false; 9361 } 9362 9363 auto lc = convert(lhs); 9364 auto rc = convert(rhs); 9365 9366 if ((lc.i < 0) != (rc.i < 0)) { 9367 // Potentially we can have +0 and -0 9368 return lhs == rhs; 9369 } 9370 9371 auto ulpDiff = std::abs(lc.i - rc.i); 9372 return ulpDiff <= maxUlpDiff; 9373 } 9374 9375 } 9376 9377 namespace Catch { 9378 namespace Matchers { 9379 namespace Floating { 9380 WithinAbsMatcher::WithinAbsMatcher(double target, double margin) 9381 :m_target{ target }, m_margin{ margin } { 9382 CATCH_ENFORCE(margin >= 0, "Invalid margin: " << margin << '.' 9383 << " Margin has to be non-negative."); 9384 } 9385 9386 // Performs equivalent check of std::fabs(lhs - rhs) <= margin 9387 // But without the subtraction to allow for INFINITY in comparison 9388 bool WithinAbsMatcher::match(double const& matchee) const { 9389 return (matchee + m_margin >= m_target) && (m_target + m_margin >= matchee); 9390 } 9391 9392 std::string WithinAbsMatcher::describe() const { 9393 return "is within " + ::Catch::Detail::stringify(m_margin) + " of " + ::Catch::Detail::stringify(m_target); 9394 } 9395 9396 WithinUlpsMatcher::WithinUlpsMatcher(double target, int ulps, FloatingPointKind baseType) 9397 :m_target{ target }, m_ulps{ ulps }, m_type{ baseType } { 9398 CATCH_ENFORCE(ulps >= 0, "Invalid ULP setting: " << ulps << '.' 9399 << " ULPs have to be non-negative."); 9400 } 9401 9402 #if defined(__clang__) 9403 #pragma clang diagnostic push 9404 // Clang <3.5 reports on the default branch in the switch below 9405 #pragma clang diagnostic ignored "-Wunreachable-code" 9406 #endif 9407 9408 bool WithinUlpsMatcher::match(double const& matchee) const { 9409 switch (m_type) { 9410 case FloatingPointKind::Float: 9411 return almostEqualUlps<float>(static_cast<float>(matchee), static_cast<float>(m_target), m_ulps); 9412 case FloatingPointKind::Double: 9413 return almostEqualUlps<double>(matchee, m_target, m_ulps); 9414 default: 9415 CATCH_INTERNAL_ERROR( "Unknown FloatingPointKind value" ); 9416 } 9417 } 9418 9419 #if defined(__clang__) 9420 #pragma clang diagnostic pop 9421 #endif 9422 9423 std::string WithinUlpsMatcher::describe() const { 9424 return "is within " + Catch::to_string(m_ulps) + " ULPs of " + ::Catch::Detail::stringify(m_target) + ((m_type == FloatingPointKind::Float)? "f" : ""); 9425 } 9426 9427 }// namespace Floating 9428 9429 Floating::WithinUlpsMatcher WithinULP(double target, int maxUlpDiff) { 9430 return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Double); 9431 } 9432 9433 Floating::WithinUlpsMatcher WithinULP(float target, int maxUlpDiff) { 9434 return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Float); 9435 } 9436 9437 Floating::WithinAbsMatcher WithinAbs(double target, double margin) { 9438 return Floating::WithinAbsMatcher(target, margin); 9439 } 9440 9441 } // namespace Matchers 9442 } // namespace Catch 9443 9444 // end catch_matchers_floating.cpp 9445 // start catch_matchers_generic.cpp 9446 9447 std::string Catch::Matchers::Generic::Detail::finalizeDescription(const std::string& desc) { 9448 if (desc.empty()) { 9449 return "matches undescribed predicate"; 9450 } else { 9451 return "matches predicate: \"" + desc + '"'; 9452 } 9453 } 9454 // end catch_matchers_generic.cpp 9455 // start catch_matchers_string.cpp 9456 9457 #include <regex> 9458 9459 namespace Catch { 9460 namespace Matchers { 9461 9462 namespace StdString { 9463 9464 CasedString::CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ) 9465 : m_caseSensitivity( caseSensitivity ), 9466 m_str( adjustString( str ) ) 9467 {} 9468 std::string CasedString::adjustString( std::string const& str ) const { 9469 return m_caseSensitivity == CaseSensitive::No 9470 ? toLower( str ) 9471 : str; 9472 } 9473 std::string CasedString::caseSensitivitySuffix() const { 9474 return m_caseSensitivity == CaseSensitive::No 9475 ? " (case insensitive)" 9476 : std::string(); 9477 } 9478 9479 StringMatcherBase::StringMatcherBase( std::string const& operation, CasedString const& comparator ) 9480 : m_comparator( comparator ), 9481 m_operation( operation ) { 9482 } 9483 9484 std::string StringMatcherBase::describe() const { 9485 std::string description; 9486 description.reserve(5 + m_operation.size() + m_comparator.m_str.size() + 9487 m_comparator.caseSensitivitySuffix().size()); 9488 description += m_operation; 9489 description += ": \""; 9490 description += m_comparator.m_str; 9491 description += "\""; 9492 description += m_comparator.caseSensitivitySuffix(); 9493 return description; 9494 } 9495 9496 EqualsMatcher::EqualsMatcher( CasedString const& comparator ) : StringMatcherBase( "equals", comparator ) {} 9497 9498 bool EqualsMatcher::match( std::string const& source ) const { 9499 return m_comparator.adjustString( source ) == m_comparator.m_str; 9500 } 9501 9502 ContainsMatcher::ContainsMatcher( CasedString const& comparator ) : StringMatcherBase( "contains", comparator ) {} 9503 9504 bool ContainsMatcher::match( std::string const& source ) const { 9505 return contains( m_comparator.adjustString( source ), m_comparator.m_str ); 9506 } 9507 9508 StartsWithMatcher::StartsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "starts with", comparator ) {} 9509 9510 bool StartsWithMatcher::match( std::string const& source ) const { 9511 return startsWith( m_comparator.adjustString( source ), m_comparator.m_str ); 9512 } 9513 9514 EndsWithMatcher::EndsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "ends with", comparator ) {} 9515 9516 bool EndsWithMatcher::match( std::string const& source ) const { 9517 return endsWith( m_comparator.adjustString( source ), m_comparator.m_str ); 9518 } 9519 9520 RegexMatcher::RegexMatcher(std::string regex, CaseSensitive::Choice caseSensitivity): m_regex(std::move(regex)), m_caseSensitivity(caseSensitivity) {} 9521 9522 bool RegexMatcher::match(std::string const& matchee) const { 9523 auto flags = std::regex::ECMAScript; // ECMAScript is the default syntax option anyway 9524 if (m_caseSensitivity == CaseSensitive::Choice::No) { 9525 flags |= std::regex::icase; 9526 } 9527 auto reg = std::regex(m_regex, flags); 9528 return std::regex_match(matchee, reg); 9529 } 9530 9531 std::string RegexMatcher::describe() const { 9532 return "matches " + ::Catch::Detail::stringify(m_regex) + ((m_caseSensitivity == CaseSensitive::Choice::Yes)? " case sensitively" : " case insensitively"); 9533 } 9534 9535 } // namespace StdString 9536 9537 StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity ) { 9538 return StdString::EqualsMatcher( StdString::CasedString( str, caseSensitivity) ); 9539 } 9540 StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity ) { 9541 return StdString::ContainsMatcher( StdString::CasedString( str, caseSensitivity) ); 9542 } 9543 StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) { 9544 return StdString::EndsWithMatcher( StdString::CasedString( str, caseSensitivity) ); 9545 } 9546 StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) { 9547 return StdString::StartsWithMatcher( StdString::CasedString( str, caseSensitivity) ); 9548 } 9549 9550 StdString::RegexMatcher Matches(std::string const& regex, CaseSensitive::Choice caseSensitivity) { 9551 return StdString::RegexMatcher(regex, caseSensitivity); 9552 } 9553 9554 } // namespace Matchers 9555 } // namespace Catch 9556 // end catch_matchers_string.cpp 9557 // start catch_message.cpp 9558 9559 // start catch_uncaught_exceptions.h 9560 9561 namespace Catch { 9562 bool uncaught_exceptions(); 9563 } // end namespace Catch 9564 9565 // end catch_uncaught_exceptions.h 9566 #include <cassert> 9567 #include <stack> 9568 9569 namespace Catch { 9570 9571 MessageInfo::MessageInfo( StringRef const& _macroName, 9572 SourceLineInfo const& _lineInfo, 9573 ResultWas::OfType _type ) 9574 : macroName( _macroName ), 9575 lineInfo( _lineInfo ), 9576 type( _type ), 9577 sequence( ++globalCount ) 9578 {} 9579 9580 bool MessageInfo::operator==( MessageInfo const& other ) const { 9581 return sequence == other.sequence; 9582 } 9583 9584 bool MessageInfo::operator<( MessageInfo const& other ) const { 9585 return sequence < other.sequence; 9586 } 9587 9588 // This may need protecting if threading support is added 9589 unsigned int MessageInfo::globalCount = 0; 9590 9591 //////////////////////////////////////////////////////////////////////////// 9592 9593 Catch::MessageBuilder::MessageBuilder( StringRef const& macroName, 9594 SourceLineInfo const& lineInfo, 9595 ResultWas::OfType type ) 9596 :m_info(macroName, lineInfo, type) {} 9597 9598 //////////////////////////////////////////////////////////////////////////// 9599 9600 ScopedMessage::ScopedMessage( MessageBuilder const& builder ) 9601 : m_info( builder.m_info ), m_moved() 9602 { 9603 m_info.message = builder.m_stream.str(); 9604 getResultCapture().pushScopedMessage( m_info ); 9605 } 9606 9607 ScopedMessage::ScopedMessage( ScopedMessage&& old ) 9608 : m_info( old.m_info ), m_moved() 9609 { 9610 old.m_moved = true; 9611 } 9612 9613 ScopedMessage::~ScopedMessage() { 9614 if ( !uncaught_exceptions() && !m_moved ){ 9615 getResultCapture().popScopedMessage(m_info); 9616 } 9617 } 9618 9619 Capturer::Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names ) { 9620 auto trimmed = [&] (size_t start, size_t end) { 9621 while (names[start] == ',' || isspace(names[start])) { 9622 ++start; 9623 } 9624 while (names[end] == ',' || isspace(names[end])) { 9625 --end; 9626 } 9627 return names.substr(start, end - start + 1); 9628 }; 9629 9630 size_t start = 0; 9631 std::stack<char> openings; 9632 for (size_t pos = 0; pos < names.size(); ++pos) { 9633 char c = names[pos]; 9634 switch (c) { 9635 case '[': 9636 case '{': 9637 case '(': 9638 // It is basically impossible to disambiguate between 9639 // comparison and start of template args in this context 9640 // case '<': 9641 openings.push(c); 9642 break; 9643 case ']': 9644 case '}': 9645 case ')': 9646 // case '>': 9647 openings.pop(); 9648 break; 9649 case ',': 9650 if (start != pos && openings.size() == 0) { 9651 m_messages.emplace_back(macroName, lineInfo, resultType); 9652 m_messages.back().message = trimmed(start, pos); 9653 m_messages.back().message += " := "; 9654 start = pos; 9655 } 9656 } 9657 } 9658 assert(openings.size() == 0 && "Mismatched openings"); 9659 m_messages.emplace_back(macroName, lineInfo, resultType); 9660 m_messages.back().message = trimmed(start, names.size() - 1); 9661 m_messages.back().message += " := "; 9662 } 9663 Capturer::~Capturer() { 9664 if ( !uncaught_exceptions() ){ 9665 assert( m_captured == m_messages.size() ); 9666 for( size_t i = 0; i < m_captured; ++i ) 9667 m_resultCapture.popScopedMessage( m_messages[i] ); 9668 } 9669 } 9670 9671 void Capturer::captureValue( size_t index, std::string const& value ) { 9672 assert( index < m_messages.size() ); 9673 m_messages[index].message += value; 9674 m_resultCapture.pushScopedMessage( m_messages[index] ); 9675 m_captured++; 9676 } 9677 9678 } // end namespace Catch 9679 // end catch_message.cpp 9680 // start catch_output_redirect.cpp 9681 9682 // start catch_output_redirect.h 9683 #ifndef TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H 9684 #define TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H 9685 9686 #include <cstdio> 9687 #include <iosfwd> 9688 #include <string> 9689 9690 namespace Catch { 9691 9692 class RedirectedStream { 9693 std::ostream& m_originalStream; 9694 std::ostream& m_redirectionStream; 9695 std::streambuf* m_prevBuf; 9696 9697 public: 9698 RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream ); 9699 ~RedirectedStream(); 9700 }; 9701 9702 class RedirectedStdOut { 9703 ReusableStringStream m_rss; 9704 RedirectedStream m_cout; 9705 public: 9706 RedirectedStdOut(); 9707 auto str() const -> std::string; 9708 }; 9709 9710 // StdErr has two constituent streams in C++, std::cerr and std::clog 9711 // This means that we need to redirect 2 streams into 1 to keep proper 9712 // order of writes 9713 class RedirectedStdErr { 9714 ReusableStringStream m_rss; 9715 RedirectedStream m_cerr; 9716 RedirectedStream m_clog; 9717 public: 9718 RedirectedStdErr(); 9719 auto str() const -> std::string; 9720 }; 9721 9722 class RedirectedStreams { 9723 public: 9724 RedirectedStreams(RedirectedStreams const&) = delete; 9725 RedirectedStreams& operator=(RedirectedStreams const&) = delete; 9726 RedirectedStreams(RedirectedStreams&&) = delete; 9727 RedirectedStreams& operator=(RedirectedStreams&&) = delete; 9728 9729 RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr); 9730 ~RedirectedStreams(); 9731 private: 9732 std::string& m_redirectedCout; 9733 std::string& m_redirectedCerr; 9734 RedirectedStdOut m_redirectedStdOut; 9735 RedirectedStdErr m_redirectedStdErr; 9736 }; 9737 9738 #if defined(CATCH_CONFIG_NEW_CAPTURE) 9739 9740 // Windows's implementation of std::tmpfile is terrible (it tries 9741 // to create a file inside system folder, thus requiring elevated 9742 // privileges for the binary), so we have to use tmpnam(_s) and 9743 // create the file ourselves there. 9744 class TempFile { 9745 public: 9746 TempFile(TempFile const&) = delete; 9747 TempFile& operator=(TempFile const&) = delete; 9748 TempFile(TempFile&&) = delete; 9749 TempFile& operator=(TempFile&&) = delete; 9750 9751 TempFile(); 9752 ~TempFile(); 9753 9754 std::FILE* getFile(); 9755 std::string getContents(); 9756 9757 private: 9758 std::FILE* m_file = nullptr; 9759 #if defined(_MSC_VER) 9760 char m_buffer[L_tmpnam] = { 0 }; 9761 #endif 9762 }; 9763 9764 class OutputRedirect { 9765 public: 9766 OutputRedirect(OutputRedirect const&) = delete; 9767 OutputRedirect& operator=(OutputRedirect const&) = delete; 9768 OutputRedirect(OutputRedirect&&) = delete; 9769 OutputRedirect& operator=(OutputRedirect&&) = delete; 9770 9771 OutputRedirect(std::string& stdout_dest, std::string& stderr_dest); 9772 ~OutputRedirect(); 9773 9774 private: 9775 int m_originalStdout = -1; 9776 int m_originalStderr = -1; 9777 TempFile m_stdoutFile; 9778 TempFile m_stderrFile; 9779 std::string& m_stdoutDest; 9780 std::string& m_stderrDest; 9781 }; 9782 9783 #endif 9784 9785 } // end namespace Catch 9786 9787 #endif // TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H 9788 // end catch_output_redirect.h 9789 #include <cstdio> 9790 #include <cstring> 9791 #include <fstream> 9792 #include <sstream> 9793 #include <stdexcept> 9794 9795 #if defined(CATCH_CONFIG_NEW_CAPTURE) 9796 #if defined(_MSC_VER) 9797 #include <io.h> //_dup and _dup2 9798 #define dup _dup 9799 #define dup2 _dup2 9800 #define fileno _fileno 9801 #else 9802 #include <unistd.h> // dup and dup2 9803 #endif 9804 #endif 9805 9806 namespace Catch { 9807 9808 RedirectedStream::RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream ) 9809 : m_originalStream( originalStream ), 9810 m_redirectionStream( redirectionStream ), 9811 m_prevBuf( m_originalStream.rdbuf() ) 9812 { 9813 m_originalStream.rdbuf( m_redirectionStream.rdbuf() ); 9814 } 9815 9816 RedirectedStream::~RedirectedStream() { 9817 m_originalStream.rdbuf( m_prevBuf ); 9818 } 9819 9820 RedirectedStdOut::RedirectedStdOut() : m_cout( Catch::cout(), m_rss.get() ) {} 9821 auto RedirectedStdOut::str() const -> std::string { return m_rss.str(); } 9822 9823 RedirectedStdErr::RedirectedStdErr() 9824 : m_cerr( Catch::cerr(), m_rss.get() ), 9825 m_clog( Catch::clog(), m_rss.get() ) 9826 {} 9827 auto RedirectedStdErr::str() const -> std::string { return m_rss.str(); } 9828 9829 RedirectedStreams::RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr) 9830 : m_redirectedCout(redirectedCout), 9831 m_redirectedCerr(redirectedCerr) 9832 {} 9833 9834 RedirectedStreams::~RedirectedStreams() { 9835 m_redirectedCout += m_redirectedStdOut.str(); 9836 m_redirectedCerr += m_redirectedStdErr.str(); 9837 } 9838 9839 #if defined(CATCH_CONFIG_NEW_CAPTURE) 9840 9841 #if defined(_MSC_VER) 9842 TempFile::TempFile() { 9843 if (tmpnam_s(m_buffer)) { 9844 CATCH_RUNTIME_ERROR("Could not get a temp filename"); 9845 } 9846 if (fopen_s(&m_file, m_buffer, "w")) { 9847 char buffer[100]; 9848 if (strerror_s(buffer, errno)) { 9849 CATCH_RUNTIME_ERROR("Could not translate errno to a string"); 9850 } 9851 CATCH_RUNTIME_ERROR("Could not open the temp file: '" << m_buffer << "' because: " << buffer); 9852 } 9853 } 9854 #else 9855 TempFile::TempFile() { 9856 m_file = std::tmpfile(); 9857 if (!m_file) { 9858 CATCH_RUNTIME_ERROR("Could not create a temp file."); 9859 } 9860 } 9861 9862 #endif 9863 9864 TempFile::~TempFile() { 9865 // TBD: What to do about errors here? 9866 std::fclose(m_file); 9867 // We manually create the file on Windows only, on Linux 9868 // it will be autodeleted 9869 #if defined(_MSC_VER) 9870 std::remove(m_buffer); 9871 #endif 9872 } 9873 9874 FILE* TempFile::getFile() { 9875 return m_file; 9876 } 9877 9878 std::string TempFile::getContents() { 9879 std::stringstream sstr; 9880 char buffer[100] = {}; 9881 std::rewind(m_file); 9882 while (std::fgets(buffer, sizeof(buffer), m_file)) { 9883 sstr << buffer; 9884 } 9885 return sstr.str(); 9886 } 9887 9888 OutputRedirect::OutputRedirect(std::string& stdout_dest, std::string& stderr_dest) : 9889 m_originalStdout(dup(1)), 9890 m_originalStderr(dup(2)), 9891 m_stdoutDest(stdout_dest), 9892 m_stderrDest(stderr_dest) { 9893 dup2(fileno(m_stdoutFile.getFile()), 1); 9894 dup2(fileno(m_stderrFile.getFile()), 2); 9895 } 9896 9897 OutputRedirect::~OutputRedirect() { 9898 Catch::cout() << std::flush; 9899 fflush(stdout); 9900 // Since we support overriding these streams, we flush cerr 9901 // even though std::cerr is unbuffered 9902 Catch::cerr() << std::flush; 9903 Catch::clog() << std::flush; 9904 fflush(stderr); 9905 9906 dup2(m_originalStdout, 1); 9907 dup2(m_originalStderr, 2); 9908 9909 m_stdoutDest += m_stdoutFile.getContents(); 9910 m_stderrDest += m_stderrFile.getContents(); 9911 } 9912 9913 #endif // CATCH_CONFIG_NEW_CAPTURE 9914 9915 } // namespace Catch 9916 9917 #if defined(CATCH_CONFIG_NEW_CAPTURE) 9918 #if defined(_MSC_VER) 9919 #undef dup 9920 #undef dup2 9921 #undef fileno 9922 #endif 9923 #endif 9924 // end catch_output_redirect.cpp 9925 // start catch_polyfills.cpp 9926 9927 #include <cmath> 9928 9929 namespace Catch { 9930 9931 #if !defined(CATCH_CONFIG_POLYFILL_ISNAN) 9932 bool isnan(float f) { 9933 return std::isnan(f); 9934 } 9935 bool isnan(double d) { 9936 return std::isnan(d); 9937 } 9938 #else 9939 // For now we only use this for embarcadero 9940 bool isnan(float f) { 9941 return std::_isnan(f); 9942 } 9943 bool isnan(double d) { 9944 return std::_isnan(d); 9945 } 9946 #endif 9947 9948 } // end namespace Catch 9949 // end catch_polyfills.cpp 9950 // start catch_random_number_generator.cpp 9951 9952 namespace Catch { 9953 9954 std::mt19937& rng() { 9955 static std::mt19937 s_rng; 9956 return s_rng; 9957 } 9958 9959 void seedRng( IConfig const& config ) { 9960 if( config.rngSeed() != 0 ) { 9961 std::srand( config.rngSeed() ); 9962 rng().seed( config.rngSeed() ); 9963 } 9964 } 9965 9966 unsigned int rngSeed() { 9967 return getCurrentContext().getConfig()->rngSeed(); 9968 } 9969 } 9970 // end catch_random_number_generator.cpp 9971 // start catch_registry_hub.cpp 9972 9973 // start catch_test_case_registry_impl.h 9974 9975 #include <vector> 9976 #include <set> 9977 #include <algorithm> 9978 #include <ios> 9979 9980 namespace Catch { 9981 9982 class TestCase; 9983 struct IConfig; 9984 9985 std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ); 9986 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); 9987 9988 void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ); 9989 9990 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ); 9991 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ); 9992 9993 class TestRegistry : public ITestCaseRegistry { 9994 public: 9995 virtual ~TestRegistry() = default; 9996 9997 virtual void registerTest( TestCase const& testCase ); 9998 9999 std::vector<TestCase> const& getAllTests() const override; 10000 std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const override; 10001 10002 private: 10003 std::vector<TestCase> m_functions; 10004 mutable RunTests::InWhatOrder m_currentSortOrder = RunTests::InDeclarationOrder; 10005 mutable std::vector<TestCase> m_sortedFunctions; 10006 std::size_t m_unnamedCount = 0; 10007 std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised 10008 }; 10009 10010 /////////////////////////////////////////////////////////////////////////// 10011 10012 class TestInvokerAsFunction : public ITestInvoker { 10013 void(*m_testAsFunction)(); 10014 public: 10015 TestInvokerAsFunction( void(*testAsFunction)() ) noexcept; 10016 10017 void invoke() const override; 10018 }; 10019 10020 std::string extractClassName( StringRef const& classOrQualifiedMethodName ); 10021 10022 /////////////////////////////////////////////////////////////////////////// 10023 10024 } // end namespace Catch 10025 10026 // end catch_test_case_registry_impl.h 10027 // start catch_reporter_registry.h 10028 10029 #include <map> 10030 10031 namespace Catch { 10032 10033 class ReporterRegistry : public IReporterRegistry { 10034 10035 public: 10036 10037 ~ReporterRegistry() override; 10038 10039 IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const override; 10040 10041 void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ); 10042 void registerListener( IReporterFactoryPtr const& factory ); 10043 10044 FactoryMap const& getFactories() const override; 10045 Listeners const& getListeners() const override; 10046 10047 private: 10048 FactoryMap m_factories; 10049 Listeners m_listeners; 10050 }; 10051 } 10052 10053 // end catch_reporter_registry.h 10054 // start catch_tag_alias_registry.h 10055 10056 // start catch_tag_alias.h 10057 10058 #include <string> 10059 10060 namespace Catch { 10061 10062 struct TagAlias { 10063 TagAlias(std::string const& _tag, SourceLineInfo _lineInfo); 10064 10065 std::string tag; 10066 SourceLineInfo lineInfo; 10067 }; 10068 10069 } // end namespace Catch 10070 10071 // end catch_tag_alias.h 10072 #include <map> 10073 10074 namespace Catch { 10075 10076 class TagAliasRegistry : public ITagAliasRegistry { 10077 public: 10078 ~TagAliasRegistry() override; 10079 TagAlias const* find( std::string const& alias ) const override; 10080 std::string expandAliases( std::string const& unexpandedTestSpec ) const override; 10081 void add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ); 10082 10083 private: 10084 std::map<std::string, TagAlias> m_registry; 10085 }; 10086 10087 } // end namespace Catch 10088 10089 // end catch_tag_alias_registry.h 10090 // start catch_startup_exception_registry.h 10091 10092 #include <vector> 10093 #include <exception> 10094 10095 namespace Catch { 10096 10097 class StartupExceptionRegistry { 10098 public: 10099 void add(std::exception_ptr const& exception) noexcept; 10100 std::vector<std::exception_ptr> const& getExceptions() const noexcept; 10101 private: 10102 std::vector<std::exception_ptr> m_exceptions; 10103 }; 10104 10105 } // end namespace Catch 10106 10107 // end catch_startup_exception_registry.h 10108 // start catch_singletons.hpp 10109 10110 namespace Catch { 10111 10112 struct ISingleton { 10113 virtual ~ISingleton(); 10114 }; 10115 10116 void addSingleton( ISingleton* singleton ); 10117 void cleanupSingletons(); 10118 10119 template<typename SingletonImplT, typename InterfaceT = SingletonImplT, typename MutableInterfaceT = InterfaceT> 10120 class Singleton : SingletonImplT, public ISingleton { 10121 10122 static auto getInternal() -> Singleton* { 10123 static Singleton* s_instance = nullptr; 10124 if( !s_instance ) { 10125 s_instance = new Singleton; 10126 addSingleton( s_instance ); 10127 } 10128 return s_instance; 10129 } 10130 10131 public: 10132 static auto get() -> InterfaceT const& { 10133 return *getInternal(); 10134 } 10135 static auto getMutable() -> MutableInterfaceT& { 10136 return *getInternal(); 10137 } 10138 }; 10139 10140 } // namespace Catch 10141 10142 // end catch_singletons.hpp 10143 namespace Catch { 10144 10145 namespace { 10146 10147 class RegistryHub : public IRegistryHub, public IMutableRegistryHub, 10148 private NonCopyable { 10149 10150 public: // IRegistryHub 10151 RegistryHub() = default; 10152 IReporterRegistry const& getReporterRegistry() const override { 10153 return m_reporterRegistry; 10154 } 10155 ITestCaseRegistry const& getTestCaseRegistry() const override { 10156 return m_testCaseRegistry; 10157 } 10158 IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const override { 10159 return m_exceptionTranslatorRegistry; 10160 } 10161 ITagAliasRegistry const& getTagAliasRegistry() const override { 10162 return m_tagAliasRegistry; 10163 } 10164 StartupExceptionRegistry const& getStartupExceptionRegistry() const override { 10165 return m_exceptionRegistry; 10166 } 10167 10168 public: // IMutableRegistryHub 10169 void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) override { 10170 m_reporterRegistry.registerReporter( name, factory ); 10171 } 10172 void registerListener( IReporterFactoryPtr const& factory ) override { 10173 m_reporterRegistry.registerListener( factory ); 10174 } 10175 void registerTest( TestCase const& testInfo ) override { 10176 m_testCaseRegistry.registerTest( testInfo ); 10177 } 10178 void registerTranslator( const IExceptionTranslator* translator ) override { 10179 m_exceptionTranslatorRegistry.registerTranslator( translator ); 10180 } 10181 void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) override { 10182 m_tagAliasRegistry.add( alias, tag, lineInfo ); 10183 } 10184 void registerStartupException() noexcept override { 10185 m_exceptionRegistry.add(std::current_exception()); 10186 } 10187 10188 private: 10189 TestRegistry m_testCaseRegistry; 10190 ReporterRegistry m_reporterRegistry; 10191 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; 10192 TagAliasRegistry m_tagAliasRegistry; 10193 StartupExceptionRegistry m_exceptionRegistry; 10194 }; 10195 } 10196 10197 using RegistryHubSingleton = Singleton<RegistryHub, IRegistryHub, IMutableRegistryHub>; 10198 10199 IRegistryHub const& getRegistryHub() { 10200 return RegistryHubSingleton::get(); 10201 } 10202 IMutableRegistryHub& getMutableRegistryHub() { 10203 return RegistryHubSingleton::getMutable(); 10204 } 10205 void cleanUp() { 10206 cleanupSingletons(); 10207 cleanUpContext(); 10208 } 10209 std::string translateActiveException() { 10210 return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); 10211 } 10212 10213 } // end namespace Catch 10214 // end catch_registry_hub.cpp 10215 // start catch_reporter_registry.cpp 10216 10217 namespace Catch { 10218 10219 ReporterRegistry::~ReporterRegistry() = default; 10220 10221 IStreamingReporterPtr ReporterRegistry::create( std::string const& name, IConfigPtr const& config ) const { 10222 auto it = m_factories.find( name ); 10223 if( it == m_factories.end() ) 10224 return nullptr; 10225 return it->second->create( ReporterConfig( config ) ); 10226 } 10227 10228 void ReporterRegistry::registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) { 10229 m_factories.emplace(name, factory); 10230 } 10231 void ReporterRegistry::registerListener( IReporterFactoryPtr const& factory ) { 10232 m_listeners.push_back( factory ); 10233 } 10234 10235 IReporterRegistry::FactoryMap const& ReporterRegistry::getFactories() const { 10236 return m_factories; 10237 } 10238 IReporterRegistry::Listeners const& ReporterRegistry::getListeners() const { 10239 return m_listeners; 10240 } 10241 10242 } 10243 // end catch_reporter_registry.cpp 10244 // start catch_result_type.cpp 10245 10246 namespace Catch { 10247 10248 bool isOk( ResultWas::OfType resultType ) { 10249 return ( resultType & ResultWas::FailureBit ) == 0; 10250 } 10251 bool isJustInfo( int flags ) { 10252 return flags == ResultWas::Info; 10253 } 10254 10255 ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { 10256 return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( rhs ) ); 10257 } 10258 10259 bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; } 10260 bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; } 10261 10262 } // end namespace Catch 10263 // end catch_result_type.cpp 10264 // start catch_run_context.cpp 10265 10266 #include <cassert> 10267 #include <algorithm> 10268 #include <sstream> 10269 10270 namespace Catch { 10271 10272 namespace Generators { 10273 struct GeneratorTracker : TestCaseTracking::TrackerBase, IGeneratorTracker { 10274 GeneratorBasePtr m_generator; 10275 10276 GeneratorTracker( TestCaseTracking::NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) 10277 : TrackerBase( nameAndLocation, ctx, parent ) 10278 {} 10279 ~GeneratorTracker(); 10280 10281 static GeneratorTracker& acquire( TrackerContext& ctx, TestCaseTracking::NameAndLocation const& nameAndLocation ) { 10282 std::shared_ptr<GeneratorTracker> tracker; 10283 10284 ITracker& currentTracker = ctx.currentTracker(); 10285 if( TestCaseTracking::ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) { 10286 assert( childTracker ); 10287 assert( childTracker->isGeneratorTracker() ); 10288 tracker = std::static_pointer_cast<GeneratorTracker>( childTracker ); 10289 } 10290 else { 10291 tracker = std::make_shared<GeneratorTracker>( nameAndLocation, ctx, ¤tTracker ); 10292 currentTracker.addChild( tracker ); 10293 } 10294 10295 if( !ctx.completedCycle() && !tracker->isComplete() ) { 10296 tracker->open(); 10297 } 10298 10299 return *tracker; 10300 } 10301 10302 // TrackerBase interface 10303 bool isGeneratorTracker() const override { return true; } 10304 auto hasGenerator() const -> bool override { 10305 return !!m_generator; 10306 } 10307 void close() override { 10308 TrackerBase::close(); 10309 // Generator interface only finds out if it has another item on atual move 10310 if (m_runState == CompletedSuccessfully && m_generator->next()) { 10311 m_children.clear(); 10312 m_runState = Executing; 10313 } 10314 } 10315 10316 // IGeneratorTracker interface 10317 auto getGenerator() const -> GeneratorBasePtr const& override { 10318 return m_generator; 10319 } 10320 void setGenerator( GeneratorBasePtr&& generator ) override { 10321 m_generator = std::move( generator ); 10322 } 10323 }; 10324 GeneratorTracker::~GeneratorTracker() {} 10325 } 10326 10327 RunContext::RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter) 10328 : m_runInfo(_config->name()), 10329 m_context(getCurrentMutableContext()), 10330 m_config(_config), 10331 m_reporter(std::move(reporter)), 10332 m_lastAssertionInfo{ StringRef(), SourceLineInfo("",0), StringRef(), ResultDisposition::Normal }, 10333 m_includeSuccessfulResults( m_config->includeSuccessfulResults() || m_reporter->getPreferences().shouldReportAllAssertions ) 10334 { 10335 m_context.setRunner(this); 10336 m_context.setConfig(m_config); 10337 m_context.setResultCapture(this); 10338 m_reporter->testRunStarting(m_runInfo); 10339 } 10340 10341 RunContext::~RunContext() { 10342 m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, aborting())); 10343 } 10344 10345 void RunContext::testGroupStarting(std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount) { 10346 m_reporter->testGroupStarting(GroupInfo(testSpec, groupIndex, groupsCount)); 10347 } 10348 10349 void RunContext::testGroupEnded(std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount) { 10350 m_reporter->testGroupEnded(TestGroupStats(GroupInfo(testSpec, groupIndex, groupsCount), totals, aborting())); 10351 } 10352 10353 Totals RunContext::runTest(TestCase const& testCase) { 10354 Totals prevTotals = m_totals; 10355 10356 std::string redirectedCout; 10357 std::string redirectedCerr; 10358 10359 auto const& testInfo = testCase.getTestCaseInfo(); 10360 10361 m_reporter->testCaseStarting(testInfo); 10362 10363 m_activeTestCase = &testCase; 10364 10365 ITracker& rootTracker = m_trackerContext.startRun(); 10366 assert(rootTracker.isSectionTracker()); 10367 static_cast<SectionTracker&>(rootTracker).addInitialFilters(m_config->getSectionsToRun()); 10368 do { 10369 m_trackerContext.startCycle(); 10370 m_testCaseTracker = &SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(testInfo.name, testInfo.lineInfo)); 10371 runCurrentTest(redirectedCout, redirectedCerr); 10372 } while (!m_testCaseTracker->isSuccessfullyCompleted() && !aborting()); 10373 10374 Totals deltaTotals = m_totals.delta(prevTotals); 10375 if (testInfo.expectedToFail() && deltaTotals.testCases.passed > 0) { 10376 deltaTotals.assertions.failed++; 10377 deltaTotals.testCases.passed--; 10378 deltaTotals.testCases.failed++; 10379 } 10380 m_totals.testCases += deltaTotals.testCases; 10381 m_reporter->testCaseEnded(TestCaseStats(testInfo, 10382 deltaTotals, 10383 redirectedCout, 10384 redirectedCerr, 10385 aborting())); 10386 10387 m_activeTestCase = nullptr; 10388 m_testCaseTracker = nullptr; 10389 10390 return deltaTotals; 10391 } 10392 10393 IConfigPtr RunContext::config() const { 10394 return m_config; 10395 } 10396 10397 IStreamingReporter& RunContext::reporter() const { 10398 return *m_reporter; 10399 } 10400 10401 void RunContext::assertionEnded(AssertionResult const & result) { 10402 if (result.getResultType() == ResultWas::Ok) { 10403 m_totals.assertions.passed++; 10404 m_lastAssertionPassed = true; 10405 } else if (!result.isOk()) { 10406 m_lastAssertionPassed = false; 10407 if( m_activeTestCase->getTestCaseInfo().okToFail() ) 10408 m_totals.assertions.failedButOk++; 10409 else 10410 m_totals.assertions.failed++; 10411 } 10412 else { 10413 m_lastAssertionPassed = true; 10414 } 10415 10416 // We have no use for the return value (whether messages should be cleared), because messages were made scoped 10417 // and should be let to clear themselves out. 10418 static_cast<void>(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals))); 10419 10420 if (result.getResultType() != ResultWas::Warning) 10421 m_messageScopes.clear(); 10422 10423 // Reset working state 10424 resetAssertionInfo(); 10425 m_lastResult = result; 10426 } 10427 void RunContext::resetAssertionInfo() { 10428 m_lastAssertionInfo.macroName = StringRef(); 10429 m_lastAssertionInfo.capturedExpression = "{Unknown expression after the reported line}"_sr; 10430 } 10431 10432 bool RunContext::sectionStarted(SectionInfo const & sectionInfo, Counts & assertions) { 10433 ITracker& sectionTracker = SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(sectionInfo.name, sectionInfo.lineInfo)); 10434 if (!sectionTracker.isOpen()) 10435 return false; 10436 m_activeSections.push_back(§ionTracker); 10437 10438 m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; 10439 10440 m_reporter->sectionStarting(sectionInfo); 10441 10442 assertions = m_totals.assertions; 10443 10444 return true; 10445 } 10446 auto RunContext::acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& { 10447 using namespace Generators; 10448 GeneratorTracker& tracker = GeneratorTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( "generator", lineInfo ) ); 10449 assert( tracker.isOpen() ); 10450 m_lastAssertionInfo.lineInfo = lineInfo; 10451 return tracker; 10452 } 10453 10454 bool RunContext::testForMissingAssertions(Counts& assertions) { 10455 if (assertions.total() != 0) 10456 return false; 10457 if (!m_config->warnAboutMissingAssertions()) 10458 return false; 10459 if (m_trackerContext.currentTracker().hasChildren()) 10460 return false; 10461 m_totals.assertions.failed++; 10462 assertions.failed++; 10463 return true; 10464 } 10465 10466 void RunContext::sectionEnded(SectionEndInfo const & endInfo) { 10467 Counts assertions = m_totals.assertions - endInfo.prevAssertions; 10468 bool missingAssertions = testForMissingAssertions(assertions); 10469 10470 if (!m_activeSections.empty()) { 10471 m_activeSections.back()->close(); 10472 m_activeSections.pop_back(); 10473 } 10474 10475 m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions)); 10476 m_messages.clear(); 10477 m_messageScopes.clear(); 10478 } 10479 10480 void RunContext::sectionEndedEarly(SectionEndInfo const & endInfo) { 10481 if (m_unfinishedSections.empty()) 10482 m_activeSections.back()->fail(); 10483 else 10484 m_activeSections.back()->close(); 10485 m_activeSections.pop_back(); 10486 10487 m_unfinishedSections.push_back(endInfo); 10488 } 10489 void RunContext::benchmarkStarting( BenchmarkInfo const& info ) { 10490 m_reporter->benchmarkStarting( info ); 10491 } 10492 void RunContext::benchmarkEnded( BenchmarkStats const& stats ) { 10493 m_reporter->benchmarkEnded( stats ); 10494 } 10495 10496 void RunContext::pushScopedMessage(MessageInfo const & message) { 10497 m_messages.push_back(message); 10498 } 10499 10500 void RunContext::popScopedMessage(MessageInfo const & message) { 10501 m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end()); 10502 } 10503 10504 void RunContext::emplaceUnscopedMessage( MessageBuilder const& builder ) { 10505 m_messageScopes.emplace_back( builder ); 10506 } 10507 10508 std::string RunContext::getCurrentTestName() const { 10509 return m_activeTestCase 10510 ? m_activeTestCase->getTestCaseInfo().name 10511 : std::string(); 10512 } 10513 10514 const AssertionResult * RunContext::getLastResult() const { 10515 return &(*m_lastResult); 10516 } 10517 10518 void RunContext::exceptionEarlyReported() { 10519 m_shouldReportUnexpected = false; 10520 } 10521 10522 void RunContext::handleFatalErrorCondition( StringRef message ) { 10523 // First notify reporter that bad things happened 10524 m_reporter->fatalErrorEncountered(message); 10525 10526 // Don't rebuild the result -- the stringification itself can cause more fatal errors 10527 // Instead, fake a result data. 10528 AssertionResultData tempResult( ResultWas::FatalErrorCondition, { false } ); 10529 tempResult.message = message; 10530 AssertionResult result(m_lastAssertionInfo, tempResult); 10531 10532 assertionEnded(result); 10533 10534 handleUnfinishedSections(); 10535 10536 // Recreate section for test case (as we will lose the one that was in scope) 10537 auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); 10538 SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name); 10539 10540 Counts assertions; 10541 assertions.failed = 1; 10542 SectionStats testCaseSectionStats(testCaseSection, assertions, 0, false); 10543 m_reporter->sectionEnded(testCaseSectionStats); 10544 10545 auto const& testInfo = m_activeTestCase->getTestCaseInfo(); 10546 10547 Totals deltaTotals; 10548 deltaTotals.testCases.failed = 1; 10549 deltaTotals.assertions.failed = 1; 10550 m_reporter->testCaseEnded(TestCaseStats(testInfo, 10551 deltaTotals, 10552 std::string(), 10553 std::string(), 10554 false)); 10555 m_totals.testCases.failed++; 10556 testGroupEnded(std::string(), m_totals, 1, 1); 10557 m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, false)); 10558 } 10559 10560 bool RunContext::lastAssertionPassed() { 10561 return m_lastAssertionPassed; 10562 } 10563 10564 void RunContext::assertionPassed() { 10565 m_lastAssertionPassed = true; 10566 ++m_totals.assertions.passed; 10567 resetAssertionInfo(); 10568 m_messageScopes.clear(); 10569 } 10570 10571 bool RunContext::aborting() const { 10572 return m_totals.assertions.failed >= static_cast<std::size_t>(m_config->abortAfter()); 10573 } 10574 10575 void RunContext::runCurrentTest(std::string & redirectedCout, std::string & redirectedCerr) { 10576 auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); 10577 SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name); 10578 m_reporter->sectionStarting(testCaseSection); 10579 Counts prevAssertions = m_totals.assertions; 10580 double duration = 0; 10581 m_shouldReportUnexpected = true; 10582 m_lastAssertionInfo = { "TEST_CASE"_sr, testCaseInfo.lineInfo, StringRef(), ResultDisposition::Normal }; 10583 10584 seedRng(*m_config); 10585 10586 Timer timer; 10587 CATCH_TRY { 10588 if (m_reporter->getPreferences().shouldRedirectStdOut) { 10589 #if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) 10590 RedirectedStreams redirectedStreams(redirectedCout, redirectedCerr); 10591 10592 timer.start(); 10593 invokeActiveTestCase(); 10594 #else 10595 OutputRedirect r(redirectedCout, redirectedCerr); 10596 timer.start(); 10597 invokeActiveTestCase(); 10598 #endif 10599 } else { 10600 timer.start(); 10601 invokeActiveTestCase(); 10602 } 10603 duration = timer.getElapsedSeconds(); 10604 } CATCH_CATCH_ANON (TestFailureException&) { 10605 // This just means the test was aborted due to failure 10606 } CATCH_CATCH_ALL { 10607 // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions 10608 // are reported without translation at the point of origin. 10609 if( m_shouldReportUnexpected ) { 10610 AssertionReaction dummyReaction; 10611 handleUnexpectedInflightException( m_lastAssertionInfo, translateActiveException(), dummyReaction ); 10612 } 10613 } 10614 Counts assertions = m_totals.assertions - prevAssertions; 10615 bool missingAssertions = testForMissingAssertions(assertions); 10616 10617 m_testCaseTracker->close(); 10618 handleUnfinishedSections(); 10619 m_messages.clear(); 10620 m_messageScopes.clear(); 10621 10622 SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions); 10623 m_reporter->sectionEnded(testCaseSectionStats); 10624 } 10625 10626 void RunContext::invokeActiveTestCase() { 10627 FatalConditionHandler fatalConditionHandler; // Handle signals 10628 m_activeTestCase->invoke(); 10629 fatalConditionHandler.reset(); 10630 } 10631 10632 void RunContext::handleUnfinishedSections() { 10633 // If sections ended prematurely due to an exception we stored their 10634 // infos here so we can tear them down outside the unwind process. 10635 for (auto it = m_unfinishedSections.rbegin(), 10636 itEnd = m_unfinishedSections.rend(); 10637 it != itEnd; 10638 ++it) 10639 sectionEnded(*it); 10640 m_unfinishedSections.clear(); 10641 } 10642 10643 void RunContext::handleExpr( 10644 AssertionInfo const& info, 10645 ITransientExpression const& expr, 10646 AssertionReaction& reaction 10647 ) { 10648 m_reporter->assertionStarting( info ); 10649 10650 bool negated = isFalseTest( info.resultDisposition ); 10651 bool result = expr.getResult() != negated; 10652 10653 if( result ) { 10654 if (!m_includeSuccessfulResults) { 10655 assertionPassed(); 10656 } 10657 else { 10658 reportExpr(info, ResultWas::Ok, &expr, negated); 10659 } 10660 } 10661 else { 10662 reportExpr(info, ResultWas::ExpressionFailed, &expr, negated ); 10663 populateReaction( reaction ); 10664 } 10665 } 10666 void RunContext::reportExpr( 10667 AssertionInfo const &info, 10668 ResultWas::OfType resultType, 10669 ITransientExpression const *expr, 10670 bool negated ) { 10671 10672 m_lastAssertionInfo = info; 10673 AssertionResultData data( resultType, LazyExpression( negated ) ); 10674 10675 AssertionResult assertionResult{ info, data }; 10676 assertionResult.m_resultData.lazyExpression.m_transientExpression = expr; 10677 10678 assertionEnded( assertionResult ); 10679 } 10680 10681 void RunContext::handleMessage( 10682 AssertionInfo const& info, 10683 ResultWas::OfType resultType, 10684 StringRef const& message, 10685 AssertionReaction& reaction 10686 ) { 10687 m_reporter->assertionStarting( info ); 10688 10689 m_lastAssertionInfo = info; 10690 10691 AssertionResultData data( resultType, LazyExpression( false ) ); 10692 data.message = message; 10693 AssertionResult assertionResult{ m_lastAssertionInfo, data }; 10694 assertionEnded( assertionResult ); 10695 if( !assertionResult.isOk() ) 10696 populateReaction( reaction ); 10697 } 10698 void RunContext::handleUnexpectedExceptionNotThrown( 10699 AssertionInfo const& info, 10700 AssertionReaction& reaction 10701 ) { 10702 handleNonExpr(info, Catch::ResultWas::DidntThrowException, reaction); 10703 } 10704 10705 void RunContext::handleUnexpectedInflightException( 10706 AssertionInfo const& info, 10707 std::string const& message, 10708 AssertionReaction& reaction 10709 ) { 10710 m_lastAssertionInfo = info; 10711 10712 AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) ); 10713 data.message = message; 10714 AssertionResult assertionResult{ info, data }; 10715 assertionEnded( assertionResult ); 10716 populateReaction( reaction ); 10717 } 10718 10719 void RunContext::populateReaction( AssertionReaction& reaction ) { 10720 reaction.shouldDebugBreak = m_config->shouldDebugBreak(); 10721 reaction.shouldThrow = aborting() || (m_lastAssertionInfo.resultDisposition & ResultDisposition::Normal); 10722 } 10723 10724 void RunContext::handleIncomplete( 10725 AssertionInfo const& info 10726 ) { 10727 m_lastAssertionInfo = info; 10728 10729 AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) ); 10730 data.message = "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE"; 10731 AssertionResult assertionResult{ info, data }; 10732 assertionEnded( assertionResult ); 10733 } 10734 void RunContext::handleNonExpr( 10735 AssertionInfo const &info, 10736 ResultWas::OfType resultType, 10737 AssertionReaction &reaction 10738 ) { 10739 m_lastAssertionInfo = info; 10740 10741 AssertionResultData data( resultType, LazyExpression( false ) ); 10742 AssertionResult assertionResult{ info, data }; 10743 assertionEnded( assertionResult ); 10744 10745 if( !assertionResult.isOk() ) 10746 populateReaction( reaction ); 10747 } 10748 10749 IResultCapture& getResultCapture() { 10750 if (auto* capture = getCurrentContext().getResultCapture()) 10751 return *capture; 10752 else 10753 CATCH_INTERNAL_ERROR("No result capture instance"); 10754 } 10755 } 10756 // end catch_run_context.cpp 10757 // start catch_section.cpp 10758 10759 namespace Catch { 10760 10761 Section::Section( SectionInfo const& info ) 10762 : m_info( info ), 10763 m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) ) 10764 { 10765 m_timer.start(); 10766 } 10767 10768 Section::~Section() { 10769 if( m_sectionIncluded ) { 10770 SectionEndInfo endInfo{ m_info, m_assertions, m_timer.getElapsedSeconds() }; 10771 if( uncaught_exceptions() ) 10772 getResultCapture().sectionEndedEarly( endInfo ); 10773 else 10774 getResultCapture().sectionEnded( endInfo ); 10775 } 10776 } 10777 10778 // This indicates whether the section should be executed or not 10779 Section::operator bool() const { 10780 return m_sectionIncluded; 10781 } 10782 10783 } // end namespace Catch 10784 // end catch_section.cpp 10785 // start catch_section_info.cpp 10786 10787 namespace Catch { 10788 10789 SectionInfo::SectionInfo 10790 ( SourceLineInfo const& _lineInfo, 10791 std::string const& _name ) 10792 : name( _name ), 10793 lineInfo( _lineInfo ) 10794 {} 10795 10796 } // end namespace Catch 10797 // end catch_section_info.cpp 10798 // start catch_session.cpp 10799 10800 // start catch_session.h 10801 10802 #include <memory> 10803 10804 namespace Catch { 10805 10806 class Session : NonCopyable { 10807 public: 10808 10809 Session(); 10810 ~Session() override; 10811 10812 void showHelp() const; 10813 void libIdentify(); 10814 10815 int applyCommandLine( int argc, char const * const * argv ); 10816 #if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE) 10817 int applyCommandLine( int argc, wchar_t const * const * argv ); 10818 #endif 10819 10820 void useConfigData( ConfigData const& configData ); 10821 10822 template<typename CharT> 10823 int run(int argc, CharT const * const argv[]) { 10824 if (m_startupExceptions) 10825 return 1; 10826 int returnCode = applyCommandLine(argc, argv); 10827 if (returnCode == 0) 10828 returnCode = run(); 10829 return returnCode; 10830 } 10831 10832 int run(); 10833 10834 clara::Parser const& cli() const; 10835 void cli( clara::Parser const& newParser ); 10836 ConfigData& configData(); 10837 Config& config(); 10838 private: 10839 int runInternal(); 10840 10841 clara::Parser m_cli; 10842 ConfigData m_configData; 10843 std::shared_ptr<Config> m_config; 10844 bool m_startupExceptions = false; 10845 }; 10846 10847 } // end namespace Catch 10848 10849 // end catch_session.h 10850 // start catch_version.h 10851 10852 #include <iosfwd> 10853 10854 namespace Catch { 10855 10856 // Versioning information 10857 struct Version { 10858 Version( Version const& ) = delete; 10859 Version& operator=( Version const& ) = delete; 10860 Version( unsigned int _majorVersion, 10861 unsigned int _minorVersion, 10862 unsigned int _patchNumber, 10863 char const * const _branchName, 10864 unsigned int _buildNumber ); 10865 10866 unsigned int const majorVersion; 10867 unsigned int const minorVersion; 10868 unsigned int const patchNumber; 10869 10870 // buildNumber is only used if branchName is not null 10871 char const * const branchName; 10872 unsigned int const buildNumber; 10873 10874 friend std::ostream& operator << ( std::ostream& os, Version const& version ); 10875 }; 10876 10877 Version const& libraryVersion(); 10878 } 10879 10880 // end catch_version.h 10881 #include <cstdlib> 10882 #include <iomanip> 10883 10884 namespace Catch { 10885 10886 namespace { 10887 const int MaxExitCode = 255; 10888 10889 IStreamingReporterPtr createReporter(std::string const& reporterName, IConfigPtr const& config) { 10890 auto reporter = Catch::getRegistryHub().getReporterRegistry().create(reporterName, config); 10891 CATCH_ENFORCE(reporter, "No reporter registered with name: '" << reporterName << "'"); 10892 10893 return reporter; 10894 } 10895 10896 IStreamingReporterPtr makeReporter(std::shared_ptr<Config> const& config) { 10897 if (Catch::getRegistryHub().getReporterRegistry().getListeners().empty()) { 10898 return createReporter(config->getReporterName(), config); 10899 } 10900 10901 // On older platforms, returning std::unique_ptr<ListeningReporter> 10902 // when the return type is std::unique_ptr<IStreamingReporter> 10903 // doesn't compile without a std::move call. However, this causes 10904 // a warning on newer platforms. Thus, we have to work around 10905 // it a bit and downcast the pointer manually. 10906 auto ret = std::unique_ptr<IStreamingReporter>(new ListeningReporter); 10907 auto& multi = static_cast<ListeningReporter&>(*ret); 10908 auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners(); 10909 for (auto const& listener : listeners) { 10910 multi.addListener(listener->create(Catch::ReporterConfig(config))); 10911 } 10912 multi.addReporter(createReporter(config->getReporterName(), config)); 10913 return ret; 10914 } 10915 10916 Catch::Totals runTests(std::shared_ptr<Config> const& config) { 10917 auto reporter = makeReporter(config); 10918 10919 RunContext context(config, std::move(reporter)); 10920 10921 Totals totals; 10922 10923 context.testGroupStarting(config->name(), 1, 1); 10924 10925 TestSpec testSpec = config->testSpec(); 10926 10927 auto const& allTestCases = getAllTestCasesSorted(*config); 10928 for (auto const& testCase : allTestCases) { 10929 bool matching = (!testSpec.hasFilters() && !testCase.isHidden()) || 10930 (testSpec.hasFilters() && matchTest(testCase, testSpec, *config)); 10931 10932 if (!context.aborting() && matching) 10933 totals += context.runTest(testCase); 10934 else 10935 context.reporter().skipTest(testCase); 10936 } 10937 10938 if (config->warnAboutNoTests() && totals.testCases.total() == 0) { 10939 ReusableStringStream testConfig; 10940 10941 bool first = true; 10942 for (const auto& input : config->getTestsOrTags()) { 10943 if (!first) { testConfig << ' '; } 10944 first = false; 10945 testConfig << input; 10946 } 10947 10948 context.reporter().noMatchingTestCases(testConfig.str()); 10949 totals.error = -1; 10950 } 10951 10952 context.testGroupEnded(config->name(), totals, 1, 1); 10953 return totals; 10954 } 10955 10956 void applyFilenamesAsTags(Catch::IConfig const& config) { 10957 auto& tests = const_cast<std::vector<TestCase>&>(getAllTestCasesSorted(config)); 10958 for (auto& testCase : tests) { 10959 auto tags = testCase.tags; 10960 10961 std::string filename = testCase.lineInfo.file; 10962 auto lastSlash = filename.find_last_of("\\/"); 10963 if (lastSlash != std::string::npos) { 10964 filename.erase(0, lastSlash); 10965 filename[0] = '#'; 10966 } 10967 10968 auto lastDot = filename.find_last_of('.'); 10969 if (lastDot != std::string::npos) { 10970 filename.erase(lastDot); 10971 } 10972 10973 tags.push_back(std::move(filename)); 10974 setTags(testCase, tags); 10975 } 10976 } 10977 10978 } // anon namespace 10979 10980 Session::Session() { 10981 static bool alreadyInstantiated = false; 10982 if( alreadyInstantiated ) { 10983 CATCH_TRY { CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" ); } 10984 CATCH_CATCH_ALL { getMutableRegistryHub().registerStartupException(); } 10985 } 10986 10987 // There cannot be exceptions at startup in no-exception mode. 10988 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 10989 const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions(); 10990 if ( !exceptions.empty() ) { 10991 m_startupExceptions = true; 10992 Colour colourGuard( Colour::Red ); 10993 Catch::cerr() << "Errors occurred during startup!" << '\n'; 10994 // iterate over all exceptions and notify user 10995 for ( const auto& ex_ptr : exceptions ) { 10996 try { 10997 std::rethrow_exception(ex_ptr); 10998 } catch ( std::exception const& ex ) { 10999 Catch::cerr() << Column( ex.what() ).indent(2) << '\n'; 11000 } 11001 } 11002 } 11003 #endif 11004 11005 alreadyInstantiated = true; 11006 m_cli = makeCommandLineParser( m_configData ); 11007 } 11008 Session::~Session() { 11009 Catch::cleanUp(); 11010 } 11011 11012 void Session::showHelp() const { 11013 Catch::cout() 11014 << "\nCatch v" << libraryVersion() << "\n" 11015 << m_cli << std::endl 11016 << "For more detailed usage please see the project docs\n" << std::endl; 11017 } 11018 void Session::libIdentify() { 11019 Catch::cout() 11020 << std::left << std::setw(16) << "description: " << "A Catch test executable\n" 11021 << std::left << std::setw(16) << "category: " << "testframework\n" 11022 << std::left << std::setw(16) << "framework: " << "Catch Test\n" 11023 << std::left << std::setw(16) << "version: " << libraryVersion() << std::endl; 11024 } 11025 11026 int Session::applyCommandLine( int argc, char const * const * argv ) { 11027 if( m_startupExceptions ) 11028 return 1; 11029 11030 auto result = m_cli.parse( clara::Args( argc, argv ) ); 11031 if( !result ) { 11032 config(); 11033 getCurrentMutableContext().setConfig(m_config); 11034 Catch::cerr() 11035 << Colour( Colour::Red ) 11036 << "\nError(s) in input:\n" 11037 << Column( result.errorMessage() ).indent( 2 ) 11038 << "\n\n"; 11039 Catch::cerr() << "Run with -? for usage\n" << std::endl; 11040 return MaxExitCode; 11041 } 11042 11043 if( m_configData.showHelp ) 11044 showHelp(); 11045 if( m_configData.libIdentify ) 11046 libIdentify(); 11047 m_config.reset(); 11048 return 0; 11049 } 11050 11051 #if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE) 11052 int Session::applyCommandLine( int argc, wchar_t const * const * argv ) { 11053 11054 char **utf8Argv = new char *[ argc ]; 11055 11056 for ( int i = 0; i < argc; ++i ) { 11057 int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL ); 11058 11059 utf8Argv[ i ] = new char[ bufSize ]; 11060 11061 WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL ); 11062 } 11063 11064 int returnCode = applyCommandLine( argc, utf8Argv ); 11065 11066 for ( int i = 0; i < argc; ++i ) 11067 delete [] utf8Argv[ i ]; 11068 11069 delete [] utf8Argv; 11070 11071 return returnCode; 11072 } 11073 #endif 11074 11075 void Session::useConfigData( ConfigData const& configData ) { 11076 m_configData = configData; 11077 m_config.reset(); 11078 } 11079 11080 int Session::run() { 11081 if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) { 11082 Catch::cout() << "...waiting for enter/ return before starting" << std::endl; 11083 static_cast<void>(std::getchar()); 11084 } 11085 int exitCode = runInternal(); 11086 if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) { 11087 Catch::cout() << "...waiting for enter/ return before exiting, with code: " << exitCode << std::endl; 11088 static_cast<void>(std::getchar()); 11089 } 11090 return exitCode; 11091 } 11092 11093 clara::Parser const& Session::cli() const { 11094 return m_cli; 11095 } 11096 void Session::cli( clara::Parser const& newParser ) { 11097 m_cli = newParser; 11098 } 11099 ConfigData& Session::configData() { 11100 return m_configData; 11101 } 11102 Config& Session::config() { 11103 if( !m_config ) 11104 m_config = std::make_shared<Config>( m_configData ); 11105 return *m_config; 11106 } 11107 11108 int Session::runInternal() { 11109 if( m_startupExceptions ) 11110 return 1; 11111 11112 if (m_configData.showHelp || m_configData.libIdentify) { 11113 return 0; 11114 } 11115 11116 CATCH_TRY { 11117 config(); // Force config to be constructed 11118 11119 seedRng( *m_config ); 11120 11121 if( m_configData.filenamesAsTags ) 11122 applyFilenamesAsTags( *m_config ); 11123 11124 // Handle list request 11125 if( Option<std::size_t> listed = list( m_config ) ) 11126 return static_cast<int>( *listed ); 11127 11128 auto totals = runTests( m_config ); 11129 // Note that on unices only the lower 8 bits are usually used, clamping 11130 // the return value to 255 prevents false negative when some multiple 11131 // of 256 tests has failed 11132 return (std::min) (MaxExitCode, (std::max) (totals.error, static_cast<int>(totals.assertions.failed))); 11133 } 11134 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 11135 catch( std::exception& ex ) { 11136 Catch::cerr() << ex.what() << std::endl; 11137 return MaxExitCode; 11138 } 11139 #endif 11140 } 11141 11142 } // end namespace Catch 11143 // end catch_session.cpp 11144 // start catch_singletons.cpp 11145 11146 #include <vector> 11147 11148 namespace Catch { 11149 11150 namespace { 11151 static auto getSingletons() -> std::vector<ISingleton*>*& { 11152 static std::vector<ISingleton*>* g_singletons = nullptr; 11153 if( !g_singletons ) 11154 g_singletons = new std::vector<ISingleton*>(); 11155 return g_singletons; 11156 } 11157 } 11158 11159 ISingleton::~ISingleton() {} 11160 11161 void addSingleton(ISingleton* singleton ) { 11162 getSingletons()->push_back( singleton ); 11163 } 11164 void cleanupSingletons() { 11165 auto& singletons = getSingletons(); 11166 for( auto singleton : *singletons ) 11167 delete singleton; 11168 delete singletons; 11169 singletons = nullptr; 11170 } 11171 11172 } // namespace Catch 11173 // end catch_singletons.cpp 11174 // start catch_startup_exception_registry.cpp 11175 11176 namespace Catch { 11177 void StartupExceptionRegistry::add( std::exception_ptr const& exception ) noexcept { 11178 CATCH_TRY { 11179 m_exceptions.push_back(exception); 11180 } CATCH_CATCH_ALL { 11181 // If we run out of memory during start-up there's really not a lot more we can do about it 11182 std::terminate(); 11183 } 11184 } 11185 11186 std::vector<std::exception_ptr> const& StartupExceptionRegistry::getExceptions() const noexcept { 11187 return m_exceptions; 11188 } 11189 11190 } // end namespace Catch 11191 // end catch_startup_exception_registry.cpp 11192 // start catch_stream.cpp 11193 11194 #include <cstdio> 11195 #include <iostream> 11196 #include <fstream> 11197 #include <sstream> 11198 #include <vector> 11199 #include <memory> 11200 11201 namespace Catch { 11202 11203 Catch::IStream::~IStream() = default; 11204 11205 namespace detail { namespace { 11206 template<typename WriterF, std::size_t bufferSize=256> 11207 class StreamBufImpl : public std::streambuf { 11208 char data[bufferSize]; 11209 WriterF m_writer; 11210 11211 public: 11212 StreamBufImpl() { 11213 setp( data, data + sizeof(data) ); 11214 } 11215 11216 ~StreamBufImpl() noexcept { 11217 StreamBufImpl::sync(); 11218 } 11219 11220 private: 11221 int overflow( int c ) override { 11222 sync(); 11223 11224 if( c != EOF ) { 11225 if( pbase() == epptr() ) 11226 m_writer( std::string( 1, static_cast<char>( c ) ) ); 11227 else 11228 sputc( static_cast<char>( c ) ); 11229 } 11230 return 0; 11231 } 11232 11233 int sync() override { 11234 if( pbase() != pptr() ) { 11235 m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) ); 11236 setp( pbase(), epptr() ); 11237 } 11238 return 0; 11239 } 11240 }; 11241 11242 /////////////////////////////////////////////////////////////////////////// 11243 11244 struct OutputDebugWriter { 11245 11246 void operator()( std::string const&str ) { 11247 writeToDebugConsole( str ); 11248 } 11249 }; 11250 11251 /////////////////////////////////////////////////////////////////////////// 11252 11253 class FileStream : public IStream { 11254 mutable std::ofstream m_ofs; 11255 public: 11256 FileStream( StringRef filename ) { 11257 m_ofs.open( filename.c_str() ); 11258 CATCH_ENFORCE( !m_ofs.fail(), "Unable to open file: '" << filename << "'" ); 11259 } 11260 ~FileStream() override = default; 11261 public: // IStream 11262 std::ostream& stream() const override { 11263 return m_ofs; 11264 } 11265 }; 11266 11267 /////////////////////////////////////////////////////////////////////////// 11268 11269 class CoutStream : public IStream { 11270 mutable std::ostream m_os; 11271 public: 11272 // Store the streambuf from cout up-front because 11273 // cout may get redirected when running tests 11274 CoutStream() : m_os( Catch::cout().rdbuf() ) {} 11275 ~CoutStream() override = default; 11276 11277 public: // IStream 11278 std::ostream& stream() const override { return m_os; } 11279 }; 11280 11281 /////////////////////////////////////////////////////////////////////////// 11282 11283 class DebugOutStream : public IStream { 11284 std::unique_ptr<StreamBufImpl<OutputDebugWriter>> m_streamBuf; 11285 mutable std::ostream m_os; 11286 public: 11287 DebugOutStream() 11288 : m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ), 11289 m_os( m_streamBuf.get() ) 11290 {} 11291 11292 ~DebugOutStream() override = default; 11293 11294 public: // IStream 11295 std::ostream& stream() const override { return m_os; } 11296 }; 11297 11298 }} // namespace anon::detail 11299 11300 /////////////////////////////////////////////////////////////////////////// 11301 11302 auto makeStream( StringRef const &filename ) -> IStream const* { 11303 if( filename.empty() ) 11304 return new detail::CoutStream(); 11305 else if( filename[0] == '%' ) { 11306 if( filename == "%debug" ) 11307 return new detail::DebugOutStream(); 11308 else 11309 CATCH_ERROR( "Unrecognised stream: '" << filename << "'" ); 11310 } 11311 else 11312 return new detail::FileStream( filename ); 11313 } 11314 11315 // This class encapsulates the idea of a pool of ostringstreams that can be reused. 11316 struct StringStreams { 11317 std::vector<std::unique_ptr<std::ostringstream>> m_streams; 11318 std::vector<std::size_t> m_unused; 11319 std::ostringstream m_referenceStream; // Used for copy state/ flags from 11320 11321 auto add() -> std::size_t { 11322 if( m_unused.empty() ) { 11323 m_streams.push_back( std::unique_ptr<std::ostringstream>( new std::ostringstream ) ); 11324 return m_streams.size()-1; 11325 } 11326 else { 11327 auto index = m_unused.back(); 11328 m_unused.pop_back(); 11329 return index; 11330 } 11331 } 11332 11333 void release( std::size_t index ) { 11334 m_streams[index]->copyfmt( m_referenceStream ); // Restore initial flags and other state 11335 m_unused.push_back(index); 11336 } 11337 }; 11338 11339 ReusableStringStream::ReusableStringStream() 11340 : m_index( Singleton<StringStreams>::getMutable().add() ), 11341 m_oss( Singleton<StringStreams>::getMutable().m_streams[m_index].get() ) 11342 {} 11343 11344 ReusableStringStream::~ReusableStringStream() { 11345 static_cast<std::ostringstream*>( m_oss )->str(""); 11346 m_oss->clear(); 11347 Singleton<StringStreams>::getMutable().release( m_index ); 11348 } 11349 11350 auto ReusableStringStream::str() const -> std::string { 11351 return static_cast<std::ostringstream*>( m_oss )->str(); 11352 } 11353 11354 /////////////////////////////////////////////////////////////////////////// 11355 11356 #ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions 11357 std::ostream& cout() { return std::cout; } 11358 std::ostream& cerr() { return std::cerr; } 11359 std::ostream& clog() { return std::clog; } 11360 #endif 11361 } 11362 // end catch_stream.cpp 11363 // start catch_string_manip.cpp 11364 11365 #include <algorithm> 11366 #include <ostream> 11367 #include <cstring> 11368 #include <cctype> 11369 11370 namespace Catch { 11371 11372 namespace { 11373 char toLowerCh(char c) { 11374 return static_cast<char>( std::tolower( c ) ); 11375 } 11376 } 11377 11378 bool startsWith( std::string const& s, std::string const& prefix ) { 11379 return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin()); 11380 } 11381 bool startsWith( std::string const& s, char prefix ) { 11382 return !s.empty() && s[0] == prefix; 11383 } 11384 bool endsWith( std::string const& s, std::string const& suffix ) { 11385 return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin()); 11386 } 11387 bool endsWith( std::string const& s, char suffix ) { 11388 return !s.empty() && s[s.size()-1] == suffix; 11389 } 11390 bool contains( std::string const& s, std::string const& infix ) { 11391 return s.find( infix ) != std::string::npos; 11392 } 11393 void toLowerInPlace( std::string& s ) { 11394 std::transform( s.begin(), s.end(), s.begin(), toLowerCh ); 11395 } 11396 std::string toLower( std::string const& s ) { 11397 std::string lc = s; 11398 toLowerInPlace( lc ); 11399 return lc; 11400 } 11401 std::string trim( std::string const& str ) { 11402 static char const* whitespaceChars = "\n\r\t "; 11403 std::string::size_type start = str.find_first_not_of( whitespaceChars ); 11404 std::string::size_type end = str.find_last_not_of( whitespaceChars ); 11405 11406 return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string(); 11407 } 11408 11409 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) { 11410 bool replaced = false; 11411 std::size_t i = str.find( replaceThis ); 11412 while( i != std::string::npos ) { 11413 replaced = true; 11414 str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() ); 11415 if( i < str.size()-withThis.size() ) 11416 i = str.find( replaceThis, i+withThis.size() ); 11417 else 11418 i = std::string::npos; 11419 } 11420 return replaced; 11421 } 11422 11423 pluralise::pluralise( std::size_t count, std::string const& label ) 11424 : m_count( count ), 11425 m_label( label ) 11426 {} 11427 11428 std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { 11429 os << pluraliser.m_count << ' ' << pluraliser.m_label; 11430 if( pluraliser.m_count != 1 ) 11431 os << 's'; 11432 return os; 11433 } 11434 11435 } 11436 // end catch_string_manip.cpp 11437 // start catch_stringref.cpp 11438 11439 #if defined(__clang__) 11440 # pragma clang diagnostic push 11441 # pragma clang diagnostic ignored "-Wexit-time-destructors" 11442 #endif 11443 11444 #include <ostream> 11445 #include <cstring> 11446 #include <cstdint> 11447 11448 namespace { 11449 const uint32_t byte_2_lead = 0xC0; 11450 const uint32_t byte_3_lead = 0xE0; 11451 const uint32_t byte_4_lead = 0xF0; 11452 } 11453 11454 namespace Catch { 11455 StringRef::StringRef( char const* rawChars ) noexcept 11456 : StringRef( rawChars, static_cast<StringRef::size_type>(std::strlen(rawChars) ) ) 11457 {} 11458 11459 StringRef::operator std::string() const { 11460 return std::string( m_start, m_size ); 11461 } 11462 11463 void StringRef::swap( StringRef& other ) noexcept { 11464 std::swap( m_start, other.m_start ); 11465 std::swap( m_size, other.m_size ); 11466 std::swap( m_data, other.m_data ); 11467 } 11468 11469 auto StringRef::c_str() const -> char const* { 11470 if( isSubstring() ) 11471 const_cast<StringRef*>( this )->takeOwnership(); 11472 return m_start; 11473 } 11474 auto StringRef::currentData() const noexcept -> char const* { 11475 return m_start; 11476 } 11477 11478 auto StringRef::isOwned() const noexcept -> bool { 11479 return m_data != nullptr; 11480 } 11481 auto StringRef::isSubstring() const noexcept -> bool { 11482 return m_start[m_size] != '\0'; 11483 } 11484 11485 void StringRef::takeOwnership() { 11486 if( !isOwned() ) { 11487 m_data = new char[m_size+1]; 11488 memcpy( m_data, m_start, m_size ); 11489 m_data[m_size] = '\0'; 11490 m_start = m_data; 11491 } 11492 } 11493 auto StringRef::substr( size_type start, size_type size ) const noexcept -> StringRef { 11494 if( start < m_size ) 11495 return StringRef( m_start+start, size ); 11496 else 11497 return StringRef(); 11498 } 11499 auto StringRef::operator == ( StringRef const& other ) const noexcept -> bool { 11500 return 11501 size() == other.size() && 11502 (std::strncmp( m_start, other.m_start, size() ) == 0); 11503 } 11504 auto StringRef::operator != ( StringRef const& other ) const noexcept -> bool { 11505 return !operator==( other ); 11506 } 11507 11508 auto StringRef::operator[](size_type index) const noexcept -> char { 11509 return m_start[index]; 11510 } 11511 11512 auto StringRef::numberOfCharacters() const noexcept -> size_type { 11513 size_type noChars = m_size; 11514 // Make adjustments for uft encodings 11515 for( size_type i=0; i < m_size; ++i ) { 11516 char c = m_start[i]; 11517 if( ( c & byte_2_lead ) == byte_2_lead ) { 11518 noChars--; 11519 if (( c & byte_3_lead ) == byte_3_lead ) 11520 noChars--; 11521 if( ( c & byte_4_lead ) == byte_4_lead ) 11522 noChars--; 11523 } 11524 } 11525 return noChars; 11526 } 11527 11528 auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string { 11529 std::string str; 11530 str.reserve( lhs.size() + rhs.size() ); 11531 str += lhs; 11532 str += rhs; 11533 return str; 11534 } 11535 auto operator + ( StringRef const& lhs, const char* rhs ) -> std::string { 11536 return std::string( lhs ) + std::string( rhs ); 11537 } 11538 auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string { 11539 return std::string( lhs ) + std::string( rhs ); 11540 } 11541 11542 auto operator << ( std::ostream& os, StringRef const& str ) -> std::ostream& { 11543 return os.write(str.currentData(), str.size()); 11544 } 11545 11546 auto operator+=( std::string& lhs, StringRef const& rhs ) -> std::string& { 11547 lhs.append(rhs.currentData(), rhs.size()); 11548 return lhs; 11549 } 11550 11551 } // namespace Catch 11552 11553 #if defined(__clang__) 11554 # pragma clang diagnostic pop 11555 #endif 11556 // end catch_stringref.cpp 11557 // start catch_tag_alias.cpp 11558 11559 namespace Catch { 11560 TagAlias::TagAlias(std::string const & _tag, SourceLineInfo _lineInfo): tag(_tag), lineInfo(_lineInfo) {} 11561 } 11562 // end catch_tag_alias.cpp 11563 // start catch_tag_alias_autoregistrar.cpp 11564 11565 namespace Catch { 11566 11567 RegistrarForTagAliases::RegistrarForTagAliases(char const* alias, char const* tag, SourceLineInfo const& lineInfo) { 11568 CATCH_TRY { 11569 getMutableRegistryHub().registerTagAlias(alias, tag, lineInfo); 11570 } CATCH_CATCH_ALL { 11571 // Do not throw when constructing global objects, instead register the exception to be processed later 11572 getMutableRegistryHub().registerStartupException(); 11573 } 11574 } 11575 11576 } 11577 // end catch_tag_alias_autoregistrar.cpp 11578 // start catch_tag_alias_registry.cpp 11579 11580 #include <sstream> 11581 11582 namespace Catch { 11583 11584 TagAliasRegistry::~TagAliasRegistry() {} 11585 11586 TagAlias const* TagAliasRegistry::find( std::string const& alias ) const { 11587 auto it = m_registry.find( alias ); 11588 if( it != m_registry.end() ) 11589 return &(it->second); 11590 else 11591 return nullptr; 11592 } 11593 11594 std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const { 11595 std::string expandedTestSpec = unexpandedTestSpec; 11596 for( auto const& registryKvp : m_registry ) { 11597 std::size_t pos = expandedTestSpec.find( registryKvp.first ); 11598 if( pos != std::string::npos ) { 11599 expandedTestSpec = expandedTestSpec.substr( 0, pos ) + 11600 registryKvp.second.tag + 11601 expandedTestSpec.substr( pos + registryKvp.first.size() ); 11602 } 11603 } 11604 return expandedTestSpec; 11605 } 11606 11607 void TagAliasRegistry::add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) { 11608 CATCH_ENFORCE( startsWith(alias, "[@") && endsWith(alias, ']'), 11609 "error: tag alias, '" << alias << "' is not of the form [@alias name].\n" << lineInfo ); 11610 11611 CATCH_ENFORCE( m_registry.insert(std::make_pair(alias, TagAlias(tag, lineInfo))).second, 11612 "error: tag alias, '" << alias << "' already registered.\n" 11613 << "\tFirst seen at: " << find(alias)->lineInfo << "\n" 11614 << "\tRedefined at: " << lineInfo ); 11615 } 11616 11617 ITagAliasRegistry::~ITagAliasRegistry() {} 11618 11619 ITagAliasRegistry const& ITagAliasRegistry::get() { 11620 return getRegistryHub().getTagAliasRegistry(); 11621 } 11622 11623 } // end namespace Catch 11624 // end catch_tag_alias_registry.cpp 11625 // start catch_test_case_info.cpp 11626 11627 #include <cctype> 11628 #include <exception> 11629 #include <algorithm> 11630 #include <sstream> 11631 11632 namespace Catch { 11633 11634 namespace { 11635 TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) { 11636 if( startsWith( tag, '.' ) || 11637 tag == "!hide" ) 11638 return TestCaseInfo::IsHidden; 11639 else if( tag == "!throws" ) 11640 return TestCaseInfo::Throws; 11641 else if( tag == "!shouldfail" ) 11642 return TestCaseInfo::ShouldFail; 11643 else if( tag == "!mayfail" ) 11644 return TestCaseInfo::MayFail; 11645 else if( tag == "!nonportable" ) 11646 return TestCaseInfo::NonPortable; 11647 else if( tag == "!benchmark" ) 11648 return static_cast<TestCaseInfo::SpecialProperties>( TestCaseInfo::Benchmark | TestCaseInfo::IsHidden ); 11649 else 11650 return TestCaseInfo::None; 11651 } 11652 bool isReservedTag( std::string const& tag ) { 11653 return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( static_cast<unsigned char>(tag[0]) ); 11654 } 11655 void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { 11656 CATCH_ENFORCE( !isReservedTag(tag), 11657 "Tag name: [" << tag << "] is not allowed.\n" 11658 << "Tag names starting with non alphanumeric characters are reserved\n" 11659 << _lineInfo ); 11660 } 11661 } 11662 11663 TestCase makeTestCase( ITestInvoker* _testCase, 11664 std::string const& _className, 11665 NameAndTags const& nameAndTags, 11666 SourceLineInfo const& _lineInfo ) 11667 { 11668 bool isHidden = false; 11669 11670 // Parse out tags 11671 std::vector<std::string> tags; 11672 std::string desc, tag; 11673 bool inTag = false; 11674 std::string _descOrTags = nameAndTags.tags; 11675 for (char c : _descOrTags) { 11676 if( !inTag ) { 11677 if( c == '[' ) 11678 inTag = true; 11679 else 11680 desc += c; 11681 } 11682 else { 11683 if( c == ']' ) { 11684 TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag ); 11685 if( ( prop & TestCaseInfo::IsHidden ) != 0 ) 11686 isHidden = true; 11687 else if( prop == TestCaseInfo::None ) 11688 enforceNotReservedTag( tag, _lineInfo ); 11689 11690 // Merged hide tags like `[.approvals]` should be added as 11691 // `[.][approvals]`. The `[.]` is added at later point, so 11692 // we only strip the prefix 11693 if (startsWith(tag, '.') && tag.size() > 1) { 11694 tag.erase(0, 1); 11695 } 11696 tags.push_back( tag ); 11697 tag.clear(); 11698 inTag = false; 11699 } 11700 else 11701 tag += c; 11702 } 11703 } 11704 if( isHidden ) { 11705 tags.push_back( "." ); 11706 } 11707 11708 TestCaseInfo info( nameAndTags.name, _className, desc, tags, _lineInfo ); 11709 return TestCase( _testCase, std::move(info) ); 11710 } 11711 11712 void setTags( TestCaseInfo& testCaseInfo, std::vector<std::string> tags ) { 11713 std::sort(begin(tags), end(tags)); 11714 tags.erase(std::unique(begin(tags), end(tags)), end(tags)); 11715 testCaseInfo.lcaseTags.clear(); 11716 11717 for( auto const& tag : tags ) { 11718 std::string lcaseTag = toLower( tag ); 11719 testCaseInfo.properties = static_cast<TestCaseInfo::SpecialProperties>( testCaseInfo.properties | parseSpecialTag( lcaseTag ) ); 11720 testCaseInfo.lcaseTags.push_back( lcaseTag ); 11721 } 11722 testCaseInfo.tags = std::move(tags); 11723 } 11724 11725 TestCaseInfo::TestCaseInfo( std::string const& _name, 11726 std::string const& _className, 11727 std::string const& _description, 11728 std::vector<std::string> const& _tags, 11729 SourceLineInfo const& _lineInfo ) 11730 : name( _name ), 11731 className( _className ), 11732 description( _description ), 11733 lineInfo( _lineInfo ), 11734 properties( None ) 11735 { 11736 setTags( *this, _tags ); 11737 } 11738 11739 bool TestCaseInfo::isHidden() const { 11740 return ( properties & IsHidden ) != 0; 11741 } 11742 bool TestCaseInfo::throws() const { 11743 return ( properties & Throws ) != 0; 11744 } 11745 bool TestCaseInfo::okToFail() const { 11746 return ( properties & (ShouldFail | MayFail ) ) != 0; 11747 } 11748 bool TestCaseInfo::expectedToFail() const { 11749 return ( properties & (ShouldFail ) ) != 0; 11750 } 11751 11752 std::string TestCaseInfo::tagsAsString() const { 11753 std::string ret; 11754 // '[' and ']' per tag 11755 std::size_t full_size = 2 * tags.size(); 11756 for (const auto& tag : tags) { 11757 full_size += tag.size(); 11758 } 11759 ret.reserve(full_size); 11760 for (const auto& tag : tags) { 11761 ret.push_back('['); 11762 ret.append(tag); 11763 ret.push_back(']'); 11764 } 11765 11766 return ret; 11767 } 11768 11769 TestCase::TestCase( ITestInvoker* testCase, TestCaseInfo&& info ) : TestCaseInfo( std::move(info) ), test( testCase ) {} 11770 11771 TestCase TestCase::withName( std::string const& _newName ) const { 11772 TestCase other( *this ); 11773 other.name = _newName; 11774 return other; 11775 } 11776 11777 void TestCase::invoke() const { 11778 test->invoke(); 11779 } 11780 11781 bool TestCase::operator == ( TestCase const& other ) const { 11782 return test.get() == other.test.get() && 11783 name == other.name && 11784 className == other.className; 11785 } 11786 11787 bool TestCase::operator < ( TestCase const& other ) const { 11788 return name < other.name; 11789 } 11790 11791 TestCaseInfo const& TestCase::getTestCaseInfo() const 11792 { 11793 return *this; 11794 } 11795 11796 } // end namespace Catch 11797 // end catch_test_case_info.cpp 11798 // start catch_test_case_registry_impl.cpp 11799 11800 #include <sstream> 11801 11802 namespace Catch { 11803 11804 std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) { 11805 11806 std::vector<TestCase> sorted = unsortedTestCases; 11807 11808 switch( config.runOrder() ) { 11809 case RunTests::InLexicographicalOrder: 11810 std::sort( sorted.begin(), sorted.end() ); 11811 break; 11812 case RunTests::InRandomOrder: 11813 seedRng( config ); 11814 std::shuffle( sorted.begin(), sorted.end(), rng() ); 11815 break; 11816 case RunTests::InDeclarationOrder: 11817 // already in declaration order 11818 break; 11819 } 11820 return sorted; 11821 } 11822 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) { 11823 return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() ); 11824 } 11825 11826 void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) { 11827 std::set<TestCase> seenFunctions; 11828 for( auto const& function : functions ) { 11829 auto prev = seenFunctions.insert( function ); 11830 CATCH_ENFORCE( prev.second, 11831 "error: TEST_CASE( \"" << function.name << "\" ) already defined.\n" 11832 << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n" 11833 << "\tRedefined at " << function.getTestCaseInfo().lineInfo ); 11834 } 11835 } 11836 11837 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) { 11838 std::vector<TestCase> filtered; 11839 filtered.reserve( testCases.size() ); 11840 for (auto const& testCase : testCases) { 11841 if ((!testSpec.hasFilters() && !testCase.isHidden()) || 11842 (testSpec.hasFilters() && matchTest(testCase, testSpec, config))) { 11843 filtered.push_back(testCase); 11844 } 11845 } 11846 return filtered; 11847 } 11848 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) { 11849 return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config ); 11850 } 11851 11852 void TestRegistry::registerTest( TestCase const& testCase ) { 11853 std::string name = testCase.getTestCaseInfo().name; 11854 if( name.empty() ) { 11855 ReusableStringStream rss; 11856 rss << "Anonymous test case " << ++m_unnamedCount; 11857 return registerTest( testCase.withName( rss.str() ) ); 11858 } 11859 m_functions.push_back( testCase ); 11860 } 11861 11862 std::vector<TestCase> const& TestRegistry::getAllTests() const { 11863 return m_functions; 11864 } 11865 std::vector<TestCase> const& TestRegistry::getAllTestsSorted( IConfig const& config ) const { 11866 if( m_sortedFunctions.empty() ) 11867 enforceNoDuplicateTestCases( m_functions ); 11868 11869 if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) { 11870 m_sortedFunctions = sortTests( config, m_functions ); 11871 m_currentSortOrder = config.runOrder(); 11872 } 11873 return m_sortedFunctions; 11874 } 11875 11876 /////////////////////////////////////////////////////////////////////////// 11877 TestInvokerAsFunction::TestInvokerAsFunction( void(*testAsFunction)() ) noexcept : m_testAsFunction( testAsFunction ) {} 11878 11879 void TestInvokerAsFunction::invoke() const { 11880 m_testAsFunction(); 11881 } 11882 11883 std::string extractClassName( StringRef const& classOrQualifiedMethodName ) { 11884 std::string className = classOrQualifiedMethodName; 11885 if( startsWith( className, '&' ) ) 11886 { 11887 std::size_t lastColons = className.rfind( "::" ); 11888 std::size_t penultimateColons = className.rfind( "::", lastColons-1 ); 11889 if( penultimateColons == std::string::npos ) 11890 penultimateColons = 1; 11891 className = className.substr( penultimateColons, lastColons-penultimateColons ); 11892 } 11893 return className; 11894 } 11895 11896 } // end namespace Catch 11897 // end catch_test_case_registry_impl.cpp 11898 // start catch_test_case_tracker.cpp 11899 11900 #include <algorithm> 11901 #include <cassert> 11902 #include <stdexcept> 11903 #include <memory> 11904 #include <sstream> 11905 11906 #if defined(__clang__) 11907 # pragma clang diagnostic push 11908 # pragma clang diagnostic ignored "-Wexit-time-destructors" 11909 #endif 11910 11911 namespace Catch { 11912 namespace TestCaseTracking { 11913 11914 NameAndLocation::NameAndLocation( std::string const& _name, SourceLineInfo const& _location ) 11915 : name( _name ), 11916 location( _location ) 11917 {} 11918 11919 ITracker::~ITracker() = default; 11920 11921 ITracker& TrackerContext::startRun() { 11922 m_rootTracker = std::make_shared<SectionTracker>( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, nullptr ); 11923 m_currentTracker = nullptr; 11924 m_runState = Executing; 11925 return *m_rootTracker; 11926 } 11927 11928 void TrackerContext::endRun() { 11929 m_rootTracker.reset(); 11930 m_currentTracker = nullptr; 11931 m_runState = NotStarted; 11932 } 11933 11934 void TrackerContext::startCycle() { 11935 m_currentTracker = m_rootTracker.get(); 11936 m_runState = Executing; 11937 } 11938 void TrackerContext::completeCycle() { 11939 m_runState = CompletedCycle; 11940 } 11941 11942 bool TrackerContext::completedCycle() const { 11943 return m_runState == CompletedCycle; 11944 } 11945 ITracker& TrackerContext::currentTracker() { 11946 return *m_currentTracker; 11947 } 11948 void TrackerContext::setCurrentTracker( ITracker* tracker ) { 11949 m_currentTracker = tracker; 11950 } 11951 11952 TrackerBase::TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) 11953 : m_nameAndLocation( nameAndLocation ), 11954 m_ctx( ctx ), 11955 m_parent( parent ) 11956 {} 11957 11958 NameAndLocation const& TrackerBase::nameAndLocation() const { 11959 return m_nameAndLocation; 11960 } 11961 bool TrackerBase::isComplete() const { 11962 return m_runState == CompletedSuccessfully || m_runState == Failed; 11963 } 11964 bool TrackerBase::isSuccessfullyCompleted() const { 11965 return m_runState == CompletedSuccessfully; 11966 } 11967 bool TrackerBase::isOpen() const { 11968 return m_runState != NotStarted && !isComplete(); 11969 } 11970 bool TrackerBase::hasChildren() const { 11971 return !m_children.empty(); 11972 } 11973 11974 void TrackerBase::addChild( ITrackerPtr const& child ) { 11975 m_children.push_back( child ); 11976 } 11977 11978 ITrackerPtr TrackerBase::findChild( NameAndLocation const& nameAndLocation ) { 11979 auto it = std::find_if( m_children.begin(), m_children.end(), 11980 [&nameAndLocation]( ITrackerPtr const& tracker ){ 11981 return 11982 tracker->nameAndLocation().location == nameAndLocation.location && 11983 tracker->nameAndLocation().name == nameAndLocation.name; 11984 } ); 11985 return( it != m_children.end() ) 11986 ? *it 11987 : nullptr; 11988 } 11989 ITracker& TrackerBase::parent() { 11990 assert( m_parent ); // Should always be non-null except for root 11991 return *m_parent; 11992 } 11993 11994 void TrackerBase::openChild() { 11995 if( m_runState != ExecutingChildren ) { 11996 m_runState = ExecutingChildren; 11997 if( m_parent ) 11998 m_parent->openChild(); 11999 } 12000 } 12001 12002 bool TrackerBase::isSectionTracker() const { return false; } 12003 bool TrackerBase::isGeneratorTracker() const { return false; } 12004 12005 void TrackerBase::open() { 12006 m_runState = Executing; 12007 moveToThis(); 12008 if( m_parent ) 12009 m_parent->openChild(); 12010 } 12011 12012 void TrackerBase::close() { 12013 12014 // Close any still open children (e.g. generators) 12015 while( &m_ctx.currentTracker() != this ) 12016 m_ctx.currentTracker().close(); 12017 12018 switch( m_runState ) { 12019 case NeedsAnotherRun: 12020 break; 12021 12022 case Executing: 12023 m_runState = CompletedSuccessfully; 12024 break; 12025 case ExecutingChildren: 12026 if( m_children.empty() || m_children.back()->isComplete() ) 12027 m_runState = CompletedSuccessfully; 12028 break; 12029 12030 case NotStarted: 12031 case CompletedSuccessfully: 12032 case Failed: 12033 CATCH_INTERNAL_ERROR( "Illogical state: " << m_runState ); 12034 12035 default: 12036 CATCH_INTERNAL_ERROR( "Unknown state: " << m_runState ); 12037 } 12038 moveToParent(); 12039 m_ctx.completeCycle(); 12040 } 12041 void TrackerBase::fail() { 12042 m_runState = Failed; 12043 if( m_parent ) 12044 m_parent->markAsNeedingAnotherRun(); 12045 moveToParent(); 12046 m_ctx.completeCycle(); 12047 } 12048 void TrackerBase::markAsNeedingAnotherRun() { 12049 m_runState = NeedsAnotherRun; 12050 } 12051 12052 void TrackerBase::moveToParent() { 12053 assert( m_parent ); 12054 m_ctx.setCurrentTracker( m_parent ); 12055 } 12056 void TrackerBase::moveToThis() { 12057 m_ctx.setCurrentTracker( this ); 12058 } 12059 12060 SectionTracker::SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) 12061 : TrackerBase( nameAndLocation, ctx, parent ) 12062 { 12063 if( parent ) { 12064 while( !parent->isSectionTracker() ) 12065 parent = &parent->parent(); 12066 12067 SectionTracker& parentSection = static_cast<SectionTracker&>( *parent ); 12068 addNextFilters( parentSection.m_filters ); 12069 } 12070 } 12071 12072 bool SectionTracker::isComplete() const { 12073 bool complete = true; 12074 12075 if ((m_filters.empty() || m_filters[0] == "") || 12076 std::find(m_filters.begin(), m_filters.end(), 12077 m_nameAndLocation.name) != m_filters.end()) 12078 complete = TrackerBase::isComplete(); 12079 return complete; 12080 12081 } 12082 12083 bool SectionTracker::isSectionTracker() const { return true; } 12084 12085 SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) { 12086 std::shared_ptr<SectionTracker> section; 12087 12088 ITracker& currentTracker = ctx.currentTracker(); 12089 if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) { 12090 assert( childTracker ); 12091 assert( childTracker->isSectionTracker() ); 12092 section = std::static_pointer_cast<SectionTracker>( childTracker ); 12093 } 12094 else { 12095 section = std::make_shared<SectionTracker>( nameAndLocation, ctx, ¤tTracker ); 12096 currentTracker.addChild( section ); 12097 } 12098 if( !ctx.completedCycle() ) 12099 section->tryOpen(); 12100 return *section; 12101 } 12102 12103 void SectionTracker::tryOpen() { 12104 if( !isComplete() && (m_filters.empty() || m_filters[0].empty() || m_filters[0] == m_nameAndLocation.name ) ) 12105 open(); 12106 } 12107 12108 void SectionTracker::addInitialFilters( std::vector<std::string> const& filters ) { 12109 if( !filters.empty() ) { 12110 m_filters.push_back(""); // Root - should never be consulted 12111 m_filters.push_back(""); // Test Case - not a section filter 12112 m_filters.insert( m_filters.end(), filters.begin(), filters.end() ); 12113 } 12114 } 12115 void SectionTracker::addNextFilters( std::vector<std::string> const& filters ) { 12116 if( filters.size() > 1 ) 12117 m_filters.insert( m_filters.end(), ++filters.begin(), filters.end() ); 12118 } 12119 12120 } // namespace TestCaseTracking 12121 12122 using TestCaseTracking::ITracker; 12123 using TestCaseTracking::TrackerContext; 12124 using TestCaseTracking::SectionTracker; 12125 12126 } // namespace Catch 12127 12128 #if defined(__clang__) 12129 # pragma clang diagnostic pop 12130 #endif 12131 // end catch_test_case_tracker.cpp 12132 // start catch_test_registry.cpp 12133 12134 namespace Catch { 12135 12136 auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker* { 12137 return new(std::nothrow) TestInvokerAsFunction( testAsFunction ); 12138 } 12139 12140 NameAndTags::NameAndTags( StringRef const& name_ , StringRef const& tags_ ) noexcept : name( name_ ), tags( tags_ ) {} 12141 12142 AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept { 12143 CATCH_TRY { 12144 getMutableRegistryHub() 12145 .registerTest( 12146 makeTestCase( 12147 invoker, 12148 extractClassName( classOrMethod ), 12149 nameAndTags, 12150 lineInfo)); 12151 } CATCH_CATCH_ALL { 12152 // Do not throw when constructing global objects, instead register the exception to be processed later 12153 getMutableRegistryHub().registerStartupException(); 12154 } 12155 } 12156 12157 AutoReg::~AutoReg() = default; 12158 } 12159 // end catch_test_registry.cpp 12160 // start catch_test_spec.cpp 12161 12162 #include <algorithm> 12163 #include <string> 12164 #include <vector> 12165 #include <memory> 12166 12167 namespace Catch { 12168 12169 TestSpec::Pattern::~Pattern() = default; 12170 TestSpec::NamePattern::~NamePattern() = default; 12171 TestSpec::TagPattern::~TagPattern() = default; 12172 TestSpec::ExcludedPattern::~ExcludedPattern() = default; 12173 12174 TestSpec::NamePattern::NamePattern( std::string const& name ) 12175 : m_wildcardPattern( toLower( name ), CaseSensitive::No ) 12176 {} 12177 bool TestSpec::NamePattern::matches( TestCaseInfo const& testCase ) const { 12178 return m_wildcardPattern.matches( toLower( testCase.name ) ); 12179 } 12180 12181 TestSpec::TagPattern::TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} 12182 bool TestSpec::TagPattern::matches( TestCaseInfo const& testCase ) const { 12183 return std::find(begin(testCase.lcaseTags), 12184 end(testCase.lcaseTags), 12185 m_tag) != end(testCase.lcaseTags); 12186 } 12187 12188 TestSpec::ExcludedPattern::ExcludedPattern( PatternPtr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} 12189 bool TestSpec::ExcludedPattern::matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } 12190 12191 bool TestSpec::Filter::matches( TestCaseInfo const& testCase ) const { 12192 // All patterns in a filter must match for the filter to be a match 12193 for( auto const& pattern : m_patterns ) { 12194 if( !pattern->matches( testCase ) ) 12195 return false; 12196 } 12197 return true; 12198 } 12199 12200 bool TestSpec::hasFilters() const { 12201 return !m_filters.empty(); 12202 } 12203 bool TestSpec::matches( TestCaseInfo const& testCase ) const { 12204 // A TestSpec matches if any filter matches 12205 for( auto const& filter : m_filters ) 12206 if( filter.matches( testCase ) ) 12207 return true; 12208 return false; 12209 } 12210 } 12211 // end catch_test_spec.cpp 12212 // start catch_test_spec_parser.cpp 12213 12214 namespace Catch { 12215 12216 TestSpecParser::TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {} 12217 12218 TestSpecParser& TestSpecParser::parse( std::string const& arg ) { 12219 m_mode = None; 12220 m_exclusion = false; 12221 m_start = std::string::npos; 12222 m_arg = m_tagAliases->expandAliases( arg ); 12223 m_escapeChars.clear(); 12224 for( m_pos = 0; m_pos < m_arg.size(); ++m_pos ) 12225 visitChar( m_arg[m_pos] ); 12226 if( m_mode == Name ) 12227 addPattern<TestSpec::NamePattern>(); 12228 return *this; 12229 } 12230 TestSpec TestSpecParser::testSpec() { 12231 addFilter(); 12232 return m_testSpec; 12233 } 12234 12235 void TestSpecParser::visitChar( char c ) { 12236 if( m_mode == None ) { 12237 switch( c ) { 12238 case ' ': return; 12239 case '~': m_exclusion = true; return; 12240 case '[': return startNewMode( Tag, ++m_pos ); 12241 case '"': return startNewMode( QuotedName, ++m_pos ); 12242 case '\\': return escape(); 12243 default: startNewMode( Name, m_pos ); break; 12244 } 12245 } 12246 if( m_mode == Name ) { 12247 if( c == ',' ) { 12248 addPattern<TestSpec::NamePattern>(); 12249 addFilter(); 12250 } 12251 else if( c == '[' ) { 12252 if( subString() == "exclude:" ) 12253 m_exclusion = true; 12254 else 12255 addPattern<TestSpec::NamePattern>(); 12256 startNewMode( Tag, ++m_pos ); 12257 } 12258 else if( c == '\\' ) 12259 escape(); 12260 } 12261 else if( m_mode == EscapedName ) 12262 m_mode = Name; 12263 else if( m_mode == QuotedName && c == '"' ) 12264 addPattern<TestSpec::NamePattern>(); 12265 else if( m_mode == Tag && c == ']' ) 12266 addPattern<TestSpec::TagPattern>(); 12267 } 12268 void TestSpecParser::startNewMode( Mode mode, std::size_t start ) { 12269 m_mode = mode; 12270 m_start = start; 12271 } 12272 void TestSpecParser::escape() { 12273 if( m_mode == None ) 12274 m_start = m_pos; 12275 m_mode = EscapedName; 12276 m_escapeChars.push_back( m_pos ); 12277 } 12278 std::string TestSpecParser::subString() const { return m_arg.substr( m_start, m_pos - m_start ); } 12279 12280 void TestSpecParser::addFilter() { 12281 if( !m_currentFilter.m_patterns.empty() ) { 12282 m_testSpec.m_filters.push_back( m_currentFilter ); 12283 m_currentFilter = TestSpec::Filter(); 12284 } 12285 } 12286 12287 TestSpec parseTestSpec( std::string const& arg ) { 12288 return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec(); 12289 } 12290 12291 } // namespace Catch 12292 // end catch_test_spec_parser.cpp 12293 // start catch_timer.cpp 12294 12295 #include <chrono> 12296 12297 static const uint64_t nanosecondsInSecond = 1000000000; 12298 12299 namespace Catch { 12300 12301 auto getCurrentNanosecondsSinceEpoch() -> uint64_t { 12302 return std::chrono::duration_cast<std::chrono::nanoseconds>( std::chrono::high_resolution_clock::now().time_since_epoch() ).count(); 12303 } 12304 12305 namespace { 12306 auto estimateClockResolution() -> uint64_t { 12307 uint64_t sum = 0; 12308 static const uint64_t iterations = 1000000; 12309 12310 auto startTime = getCurrentNanosecondsSinceEpoch(); 12311 12312 for( std::size_t i = 0; i < iterations; ++i ) { 12313 12314 uint64_t ticks; 12315 uint64_t baseTicks = getCurrentNanosecondsSinceEpoch(); 12316 do { 12317 ticks = getCurrentNanosecondsSinceEpoch(); 12318 } while( ticks == baseTicks ); 12319 12320 auto delta = ticks - baseTicks; 12321 sum += delta; 12322 12323 // If we have been calibrating for over 3 seconds -- the clock 12324 // is terrible and we should move on. 12325 // TBD: How to signal that the measured resolution is probably wrong? 12326 if (ticks > startTime + 3 * nanosecondsInSecond) { 12327 return sum / ( i + 1u ); 12328 } 12329 } 12330 12331 // We're just taking the mean, here. To do better we could take the std. dev and exclude outliers 12332 // - and potentially do more iterations if there's a high variance. 12333 return sum/iterations; 12334 } 12335 } 12336 auto getEstimatedClockResolution() -> uint64_t { 12337 static auto s_resolution = estimateClockResolution(); 12338 return s_resolution; 12339 } 12340 12341 void Timer::start() { 12342 m_nanoseconds = getCurrentNanosecondsSinceEpoch(); 12343 } 12344 auto Timer::getElapsedNanoseconds() const -> uint64_t { 12345 return getCurrentNanosecondsSinceEpoch() - m_nanoseconds; 12346 } 12347 auto Timer::getElapsedMicroseconds() const -> uint64_t { 12348 return getElapsedNanoseconds()/1000; 12349 } 12350 auto Timer::getElapsedMilliseconds() const -> unsigned int { 12351 return static_cast<unsigned int>(getElapsedMicroseconds()/1000); 12352 } 12353 auto Timer::getElapsedSeconds() const -> double { 12354 return getElapsedMicroseconds()/1000000.0; 12355 } 12356 12357 } // namespace Catch 12358 // end catch_timer.cpp 12359 // start catch_tostring.cpp 12360 12361 #if defined(__clang__) 12362 # pragma clang diagnostic push 12363 # pragma clang diagnostic ignored "-Wexit-time-destructors" 12364 # pragma clang diagnostic ignored "-Wglobal-constructors" 12365 #endif 12366 12367 // Enable specific decls locally 12368 #if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) 12369 #define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER 12370 #endif 12371 12372 #include <cmath> 12373 #include <iomanip> 12374 12375 namespace Catch { 12376 12377 namespace Detail { 12378 12379 const std::string unprintableString = "{?}"; 12380 12381 namespace { 12382 const int hexThreshold = 255; 12383 12384 struct Endianness { 12385 enum Arch { Big, Little }; 12386 12387 static Arch which() { 12388 union _{ 12389 int asInt; 12390 char asChar[sizeof (int)]; 12391 } u; 12392 12393 u.asInt = 1; 12394 return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little; 12395 } 12396 }; 12397 } 12398 12399 std::string rawMemoryToString( const void *object, std::size_t size ) { 12400 // Reverse order for little endian architectures 12401 int i = 0, end = static_cast<int>( size ), inc = 1; 12402 if( Endianness::which() == Endianness::Little ) { 12403 i = end-1; 12404 end = inc = -1; 12405 } 12406 12407 unsigned char const *bytes = static_cast<unsigned char const *>(object); 12408 ReusableStringStream rss; 12409 rss << "0x" << std::setfill('0') << std::hex; 12410 for( ; i != end; i += inc ) 12411 rss << std::setw(2) << static_cast<unsigned>(bytes[i]); 12412 return rss.str(); 12413 } 12414 } 12415 12416 template<typename T> 12417 std::string fpToString( T value, int precision ) { 12418 if (Catch::isnan(value)) { 12419 return "nan"; 12420 } 12421 12422 ReusableStringStream rss; 12423 rss << std::setprecision( precision ) 12424 << std::fixed 12425 << value; 12426 std::string d = rss.str(); 12427 std::size_t i = d.find_last_not_of( '0' ); 12428 if( i != std::string::npos && i != d.size()-1 ) { 12429 if( d[i] == '.' ) 12430 i++; 12431 d = d.substr( 0, i+1 ); 12432 } 12433 return d; 12434 } 12435 12436 //// ======================================================= //// 12437 // 12438 // Out-of-line defs for full specialization of StringMaker 12439 // 12440 //// ======================================================= //// 12441 12442 std::string StringMaker<std::string>::convert(const std::string& str) { 12443 if (!getCurrentContext().getConfig()->showInvisibles()) { 12444 return '"' + str + '"'; 12445 } 12446 12447 std::string s("\""); 12448 for (char c : str) { 12449 switch (c) { 12450 case '\n': 12451 s.append("\\n"); 12452 break; 12453 case '\t': 12454 s.append("\\t"); 12455 break; 12456 default: 12457 s.push_back(c); 12458 break; 12459 } 12460 } 12461 s.append("\""); 12462 return s; 12463 } 12464 12465 #ifdef CATCH_CONFIG_CPP17_STRING_VIEW 12466 std::string StringMaker<std::string_view>::convert(std::string_view str) { 12467 return ::Catch::Detail::stringify(std::string{ str }); 12468 } 12469 #endif 12470 12471 std::string StringMaker<char const*>::convert(char const* str) { 12472 if (str) { 12473 return ::Catch::Detail::stringify(std::string{ str }); 12474 } else { 12475 return{ "{null string}" }; 12476 } 12477 } 12478 std::string StringMaker<char*>::convert(char* str) { 12479 if (str) { 12480 return ::Catch::Detail::stringify(std::string{ str }); 12481 } else { 12482 return{ "{null string}" }; 12483 } 12484 } 12485 12486 #ifdef CATCH_CONFIG_WCHAR 12487 std::string StringMaker<std::wstring>::convert(const std::wstring& wstr) { 12488 std::string s; 12489 s.reserve(wstr.size()); 12490 for (auto c : wstr) { 12491 s += (c <= 0xff) ? static_cast<char>(c) : '?'; 12492 } 12493 return ::Catch::Detail::stringify(s); 12494 } 12495 12496 # ifdef CATCH_CONFIG_CPP17_STRING_VIEW 12497 std::string StringMaker<std::wstring_view>::convert(std::wstring_view str) { 12498 return StringMaker<std::wstring>::convert(std::wstring(str)); 12499 } 12500 # endif 12501 12502 std::string StringMaker<wchar_t const*>::convert(wchar_t const * str) { 12503 if (str) { 12504 return ::Catch::Detail::stringify(std::wstring{ str }); 12505 } else { 12506 return{ "{null string}" }; 12507 } 12508 } 12509 std::string StringMaker<wchar_t *>::convert(wchar_t * str) { 12510 if (str) { 12511 return ::Catch::Detail::stringify(std::wstring{ str }); 12512 } else { 12513 return{ "{null string}" }; 12514 } 12515 } 12516 #endif 12517 12518 std::string StringMaker<int>::convert(int value) { 12519 return ::Catch::Detail::stringify(static_cast<long long>(value)); 12520 } 12521 std::string StringMaker<long>::convert(long value) { 12522 return ::Catch::Detail::stringify(static_cast<long long>(value)); 12523 } 12524 std::string StringMaker<long long>::convert(long long value) { 12525 ReusableStringStream rss; 12526 rss << value; 12527 if (value > Detail::hexThreshold) { 12528 rss << " (0x" << std::hex << value << ')'; 12529 } 12530 return rss.str(); 12531 } 12532 12533 std::string StringMaker<unsigned int>::convert(unsigned int value) { 12534 return ::Catch::Detail::stringify(static_cast<unsigned long long>(value)); 12535 } 12536 std::string StringMaker<unsigned long>::convert(unsigned long value) { 12537 return ::Catch::Detail::stringify(static_cast<unsigned long long>(value)); 12538 } 12539 std::string StringMaker<unsigned long long>::convert(unsigned long long value) { 12540 ReusableStringStream rss; 12541 rss << value; 12542 if (value > Detail::hexThreshold) { 12543 rss << " (0x" << std::hex << value << ')'; 12544 } 12545 return rss.str(); 12546 } 12547 12548 std::string StringMaker<bool>::convert(bool b) { 12549 return b ? "true" : "false"; 12550 } 12551 12552 std::string StringMaker<signed char>::convert(signed char value) { 12553 if (value == '\r') { 12554 return "'\\r'"; 12555 } else if (value == '\f') { 12556 return "'\\f'"; 12557 } else if (value == '\n') { 12558 return "'\\n'"; 12559 } else if (value == '\t') { 12560 return "'\\t'"; 12561 } else if ('\0' <= value && value < ' ') { 12562 return ::Catch::Detail::stringify(static_cast<unsigned int>(value)); 12563 } else { 12564 char chstr[] = "' '"; 12565 chstr[1] = value; 12566 return chstr; 12567 } 12568 } 12569 std::string StringMaker<char>::convert(char c) { 12570 return ::Catch::Detail::stringify(static_cast<signed char>(c)); 12571 } 12572 std::string StringMaker<unsigned char>::convert(unsigned char c) { 12573 return ::Catch::Detail::stringify(static_cast<char>(c)); 12574 } 12575 12576 std::string StringMaker<std::nullptr_t>::convert(std::nullptr_t) { 12577 return "nullptr"; 12578 } 12579 12580 std::string StringMaker<float>::convert(float value) { 12581 return fpToString(value, 5) + 'f'; 12582 } 12583 std::string StringMaker<double>::convert(double value) { 12584 return fpToString(value, 10); 12585 } 12586 12587 std::string ratio_string<std::atto>::symbol() { return "a"; } 12588 std::string ratio_string<std::femto>::symbol() { return "f"; } 12589 std::string ratio_string<std::pico>::symbol() { return "p"; } 12590 std::string ratio_string<std::nano>::symbol() { return "n"; } 12591 std::string ratio_string<std::micro>::symbol() { return "u"; } 12592 std::string ratio_string<std::milli>::symbol() { return "m"; } 12593 12594 } // end namespace Catch 12595 12596 #if defined(__clang__) 12597 # pragma clang diagnostic pop 12598 #endif 12599 12600 // end catch_tostring.cpp 12601 // start catch_totals.cpp 12602 12603 namespace Catch { 12604 12605 Counts Counts::operator - ( Counts const& other ) const { 12606 Counts diff; 12607 diff.passed = passed - other.passed; 12608 diff.failed = failed - other.failed; 12609 diff.failedButOk = failedButOk - other.failedButOk; 12610 return diff; 12611 } 12612 12613 Counts& Counts::operator += ( Counts const& other ) { 12614 passed += other.passed; 12615 failed += other.failed; 12616 failedButOk += other.failedButOk; 12617 return *this; 12618 } 12619 12620 std::size_t Counts::total() const { 12621 return passed + failed + failedButOk; 12622 } 12623 bool Counts::allPassed() const { 12624 return failed == 0 && failedButOk == 0; 12625 } 12626 bool Counts::allOk() const { 12627 return failed == 0; 12628 } 12629 12630 Totals Totals::operator - ( Totals const& other ) const { 12631 Totals diff; 12632 diff.assertions = assertions - other.assertions; 12633 diff.testCases = testCases - other.testCases; 12634 return diff; 12635 } 12636 12637 Totals& Totals::operator += ( Totals const& other ) { 12638 assertions += other.assertions; 12639 testCases += other.testCases; 12640 return *this; 12641 } 12642 12643 Totals Totals::delta( Totals const& prevTotals ) const { 12644 Totals diff = *this - prevTotals; 12645 if( diff.assertions.failed > 0 ) 12646 ++diff.testCases.failed; 12647 else if( diff.assertions.failedButOk > 0 ) 12648 ++diff.testCases.failedButOk; 12649 else 12650 ++diff.testCases.passed; 12651 return diff; 12652 } 12653 12654 } 12655 // end catch_totals.cpp 12656 // start catch_uncaught_exceptions.cpp 12657 12658 #include <exception> 12659 12660 namespace Catch { 12661 bool uncaught_exceptions() { 12662 #if defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) 12663 return std::uncaught_exceptions() > 0; 12664 #else 12665 return std::uncaught_exception(); 12666 #endif 12667 } 12668 } // end namespace Catch 12669 // end catch_uncaught_exceptions.cpp 12670 // start catch_version.cpp 12671 12672 #include <ostream> 12673 12674 namespace Catch { 12675 12676 Version::Version 12677 ( unsigned int _majorVersion, 12678 unsigned int _minorVersion, 12679 unsigned int _patchNumber, 12680 char const * const _branchName, 12681 unsigned int _buildNumber ) 12682 : majorVersion( _majorVersion ), 12683 minorVersion( _minorVersion ), 12684 patchNumber( _patchNumber ), 12685 branchName( _branchName ), 12686 buildNumber( _buildNumber ) 12687 {} 12688 12689 std::ostream& operator << ( std::ostream& os, Version const& version ) { 12690 os << version.majorVersion << '.' 12691 << version.minorVersion << '.' 12692 << version.patchNumber; 12693 // branchName is never null -> 0th char is \0 if it is empty 12694 if (version.branchName[0]) { 12695 os << '-' << version.branchName 12696 << '.' << version.buildNumber; 12697 } 12698 return os; 12699 } 12700 12701 Version const& libraryVersion() { 12702 static Version version( 2, 7, 2, "", 0 ); 12703 return version; 12704 } 12705 12706 } 12707 // end catch_version.cpp 12708 // start catch_wildcard_pattern.cpp 12709 12710 #include <sstream> 12711 12712 namespace Catch { 12713 12714 WildcardPattern::WildcardPattern( std::string const& pattern, 12715 CaseSensitive::Choice caseSensitivity ) 12716 : m_caseSensitivity( caseSensitivity ), 12717 m_pattern( adjustCase( pattern ) ) 12718 { 12719 if( startsWith( m_pattern, '*' ) ) { 12720 m_pattern = m_pattern.substr( 1 ); 12721 m_wildcard = WildcardAtStart; 12722 } 12723 if( endsWith( m_pattern, '*' ) ) { 12724 m_pattern = m_pattern.substr( 0, m_pattern.size()-1 ); 12725 m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd ); 12726 } 12727 } 12728 12729 bool WildcardPattern::matches( std::string const& str ) const { 12730 switch( m_wildcard ) { 12731 case NoWildcard: 12732 return m_pattern == adjustCase( str ); 12733 case WildcardAtStart: 12734 return endsWith( adjustCase( str ), m_pattern ); 12735 case WildcardAtEnd: 12736 return startsWith( adjustCase( str ), m_pattern ); 12737 case WildcardAtBothEnds: 12738 return contains( adjustCase( str ), m_pattern ); 12739 default: 12740 CATCH_INTERNAL_ERROR( "Unknown enum" ); 12741 } 12742 } 12743 12744 std::string WildcardPattern::adjustCase( std::string const& str ) const { 12745 return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str; 12746 } 12747 } 12748 // end catch_wildcard_pattern.cpp 12749 // start catch_xmlwriter.cpp 12750 12751 #include <iomanip> 12752 12753 using uchar = unsigned char; 12754 12755 namespace Catch { 12756 12757 namespace { 12758 12759 size_t trailingBytes(unsigned char c) { 12760 if ((c & 0xE0) == 0xC0) { 12761 return 2; 12762 } 12763 if ((c & 0xF0) == 0xE0) { 12764 return 3; 12765 } 12766 if ((c & 0xF8) == 0xF0) { 12767 return 4; 12768 } 12769 CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered"); 12770 } 12771 12772 uint32_t headerValue(unsigned char c) { 12773 if ((c & 0xE0) == 0xC0) { 12774 return c & 0x1F; 12775 } 12776 if ((c & 0xF0) == 0xE0) { 12777 return c & 0x0F; 12778 } 12779 if ((c & 0xF8) == 0xF0) { 12780 return c & 0x07; 12781 } 12782 CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered"); 12783 } 12784 12785 void hexEscapeChar(std::ostream& os, unsigned char c) { 12786 std::ios_base::fmtflags f(os.flags()); 12787 os << "\\x" 12788 << std::uppercase << std::hex << std::setfill('0') << std::setw(2) 12789 << static_cast<int>(c); 12790 os.flags(f); 12791 } 12792 12793 } // anonymous namespace 12794 12795 XmlEncode::XmlEncode( std::string const& str, ForWhat forWhat ) 12796 : m_str( str ), 12797 m_forWhat( forWhat ) 12798 {} 12799 12800 void XmlEncode::encodeTo( std::ostream& os ) const { 12801 // Apostrophe escaping not necessary if we always use " to write attributes 12802 // (see: http://www.w3.org/TR/xml/#syntax) 12803 12804 for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) { 12805 uchar c = m_str[idx]; 12806 switch (c) { 12807 case '<': os << "<"; break; 12808 case '&': os << "&"; break; 12809 12810 case '>': 12811 // See: http://www.w3.org/TR/xml/#syntax 12812 if (idx > 2 && m_str[idx - 1] == ']' && m_str[idx - 2] == ']') 12813 os << ">"; 12814 else 12815 os << c; 12816 break; 12817 12818 case '\"': 12819 if (m_forWhat == ForAttributes) 12820 os << """; 12821 else 12822 os << c; 12823 break; 12824 12825 default: 12826 // Check for control characters and invalid utf-8 12827 12828 // Escape control characters in standard ascii 12829 // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0 12830 if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) { 12831 hexEscapeChar(os, c); 12832 break; 12833 } 12834 12835 // Plain ASCII: Write it to stream 12836 if (c < 0x7F) { 12837 os << c; 12838 break; 12839 } 12840 12841 // UTF-8 territory 12842 // Check if the encoding is valid and if it is not, hex escape bytes. 12843 // Important: We do not check the exact decoded values for validity, only the encoding format 12844 // First check that this bytes is a valid lead byte: 12845 // This means that it is not encoded as 1111 1XXX 12846 // Or as 10XX XXXX 12847 if (c < 0xC0 || 12848 c >= 0xF8) { 12849 hexEscapeChar(os, c); 12850 break; 12851 } 12852 12853 auto encBytes = trailingBytes(c); 12854 // Are there enough bytes left to avoid accessing out-of-bounds memory? 12855 if (idx + encBytes - 1 >= m_str.size()) { 12856 hexEscapeChar(os, c); 12857 break; 12858 } 12859 // The header is valid, check data 12860 // The next encBytes bytes must together be a valid utf-8 12861 // This means: bitpattern 10XX XXXX and the extracted value is sane (ish) 12862 bool valid = true; 12863 uint32_t value = headerValue(c); 12864 for (std::size_t n = 1; n < encBytes; ++n) { 12865 uchar nc = m_str[idx + n]; 12866 valid &= ((nc & 0xC0) == 0x80); 12867 value = (value << 6) | (nc & 0x3F); 12868 } 12869 12870 if ( 12871 // Wrong bit pattern of following bytes 12872 (!valid) || 12873 // Overlong encodings 12874 (value < 0x80) || 12875 (0x80 <= value && value < 0x800 && encBytes > 2) || 12876 (0x800 < value && value < 0x10000 && encBytes > 3) || 12877 // Encoded value out of range 12878 (value >= 0x110000) 12879 ) { 12880 hexEscapeChar(os, c); 12881 break; 12882 } 12883 12884 // If we got here, this is in fact a valid(ish) utf-8 sequence 12885 for (std::size_t n = 0; n < encBytes; ++n) { 12886 os << m_str[idx + n]; 12887 } 12888 idx += encBytes - 1; 12889 break; 12890 } 12891 } 12892 } 12893 12894 std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) { 12895 xmlEncode.encodeTo( os ); 12896 return os; 12897 } 12898 12899 XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer ) 12900 : m_writer( writer ) 12901 {} 12902 12903 XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) noexcept 12904 : m_writer( other.m_writer ){ 12905 other.m_writer = nullptr; 12906 } 12907 XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) noexcept { 12908 if ( m_writer ) { 12909 m_writer->endElement(); 12910 } 12911 m_writer = other.m_writer; 12912 other.m_writer = nullptr; 12913 return *this; 12914 } 12915 12916 XmlWriter::ScopedElement::~ScopedElement() { 12917 if( m_writer ) 12918 m_writer->endElement(); 12919 } 12920 12921 XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText( std::string const& text, bool indent ) { 12922 m_writer->writeText( text, indent ); 12923 return *this; 12924 } 12925 12926 XmlWriter::XmlWriter( std::ostream& os ) : m_os( os ) 12927 { 12928 writeDeclaration(); 12929 } 12930 12931 XmlWriter::~XmlWriter() { 12932 while( !m_tags.empty() ) 12933 endElement(); 12934 } 12935 12936 XmlWriter& XmlWriter::startElement( std::string const& name ) { 12937 ensureTagClosed(); 12938 newlineIfNecessary(); 12939 m_os << m_indent << '<' << name; 12940 m_tags.push_back( name ); 12941 m_indent += " "; 12942 m_tagIsOpen = true; 12943 return *this; 12944 } 12945 12946 XmlWriter::ScopedElement XmlWriter::scopedElement( std::string const& name ) { 12947 ScopedElement scoped( this ); 12948 startElement( name ); 12949 return scoped; 12950 } 12951 12952 XmlWriter& XmlWriter::endElement() { 12953 newlineIfNecessary(); 12954 m_indent = m_indent.substr( 0, m_indent.size()-2 ); 12955 if( m_tagIsOpen ) { 12956 m_os << "/>"; 12957 m_tagIsOpen = false; 12958 } 12959 else { 12960 m_os << m_indent << "</" << m_tags.back() << ">"; 12961 } 12962 m_os << std::endl; 12963 m_tags.pop_back(); 12964 return *this; 12965 } 12966 12967 XmlWriter& XmlWriter::writeAttribute( std::string const& name, std::string const& attribute ) { 12968 if( !name.empty() && !attribute.empty() ) 12969 m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"'; 12970 return *this; 12971 } 12972 12973 XmlWriter& XmlWriter::writeAttribute( std::string const& name, bool attribute ) { 12974 m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"'; 12975 return *this; 12976 } 12977 12978 XmlWriter& XmlWriter::writeText( std::string const& text, bool indent ) { 12979 if( !text.empty() ){ 12980 bool tagWasOpen = m_tagIsOpen; 12981 ensureTagClosed(); 12982 if( tagWasOpen && indent ) 12983 m_os << m_indent; 12984 m_os << XmlEncode( text ); 12985 m_needsNewline = true; 12986 } 12987 return *this; 12988 } 12989 12990 XmlWriter& XmlWriter::writeComment( std::string const& text ) { 12991 ensureTagClosed(); 12992 m_os << m_indent << "<!--" << text << "-->"; 12993 m_needsNewline = true; 12994 return *this; 12995 } 12996 12997 void XmlWriter::writeStylesheetRef( std::string const& url ) { 12998 m_os << "<?xml-stylesheet type=\"text/xsl\" href=\"" << url << "\"?>\n"; 12999 } 13000 13001 XmlWriter& XmlWriter::writeBlankLine() { 13002 ensureTagClosed(); 13003 m_os << '\n'; 13004 return *this; 13005 } 13006 13007 void XmlWriter::ensureTagClosed() { 13008 if( m_tagIsOpen ) { 13009 m_os << ">" << std::endl; 13010 m_tagIsOpen = false; 13011 } 13012 } 13013 13014 void XmlWriter::writeDeclaration() { 13015 m_os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; 13016 } 13017 13018 void XmlWriter::newlineIfNecessary() { 13019 if( m_needsNewline ) { 13020 m_os << std::endl; 13021 m_needsNewline = false; 13022 } 13023 } 13024 } 13025 // end catch_xmlwriter.cpp 13026 // start catch_reporter_bases.cpp 13027 13028 #include <cstring> 13029 #include <cfloat> 13030 #include <cstdio> 13031 #include <cassert> 13032 #include <memory> 13033 13034 namespace Catch { 13035 void prepareExpandedExpression(AssertionResult& result) { 13036 result.getExpandedExpression(); 13037 } 13038 13039 // Because formatting using c++ streams is stateful, drop down to C is required 13040 // Alternatively we could use stringstream, but its performance is... not good. 13041 std::string getFormattedDuration( double duration ) { 13042 // Max exponent + 1 is required to represent the whole part 13043 // + 1 for decimal point 13044 // + 3 for the 3 decimal places 13045 // + 1 for null terminator 13046 const std::size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1; 13047 char buffer[maxDoubleSize]; 13048 13049 // Save previous errno, to prevent sprintf from overwriting it 13050 ErrnoGuard guard; 13051 #ifdef _MSC_VER 13052 sprintf_s(buffer, "%.3f", duration); 13053 #else 13054 std::sprintf(buffer, "%.3f", duration); 13055 #endif 13056 return std::string(buffer); 13057 } 13058 13059 std::string serializeFilters( std::vector<std::string> const& container ) { 13060 ReusableStringStream oss; 13061 bool first = true; 13062 for (auto&& filter : container) 13063 { 13064 if (!first) 13065 oss << ' '; 13066 else 13067 first = false; 13068 13069 oss << filter; 13070 } 13071 return oss.str(); 13072 } 13073 13074 TestEventListenerBase::TestEventListenerBase(ReporterConfig const & _config) 13075 :StreamingReporterBase(_config) {} 13076 13077 std::set<Verbosity> TestEventListenerBase::getSupportedVerbosities() { 13078 return { Verbosity::Quiet, Verbosity::Normal, Verbosity::High }; 13079 } 13080 13081 void TestEventListenerBase::assertionStarting(AssertionInfo const &) {} 13082 13083 bool TestEventListenerBase::assertionEnded(AssertionStats const &) { 13084 return false; 13085 } 13086 13087 } // end namespace Catch 13088 // end catch_reporter_bases.cpp 13089 // start catch_reporter_compact.cpp 13090 13091 namespace { 13092 13093 #ifdef CATCH_PLATFORM_MAC 13094 const char* failedString() { return "FAILED"; } 13095 const char* passedString() { return "PASSED"; } 13096 #else 13097 const char* failedString() { return "failed"; } 13098 const char* passedString() { return "passed"; } 13099 #endif 13100 13101 // Colour::LightGrey 13102 Catch::Colour::Code dimColour() { return Catch::Colour::FileName; } 13103 13104 std::string bothOrAll( std::size_t count ) { 13105 return count == 1 ? std::string() : 13106 count == 2 ? "both " : "all " ; 13107 } 13108 13109 } // anon namespace 13110 13111 namespace Catch { 13112 namespace { 13113 // Colour, message variants: 13114 // - white: No tests ran. 13115 // - red: Failed [both/all] N test cases, failed [both/all] M assertions. 13116 // - white: Passed [both/all] N test cases (no assertions). 13117 // - red: Failed N tests cases, failed M assertions. 13118 // - green: Passed [both/all] N tests cases with M assertions. 13119 void printTotals(std::ostream& out, const Totals& totals) { 13120 if (totals.testCases.total() == 0) { 13121 out << "No tests ran."; 13122 } else if (totals.testCases.failed == totals.testCases.total()) { 13123 Colour colour(Colour::ResultError); 13124 const std::string qualify_assertions_failed = 13125 totals.assertions.failed == totals.assertions.total() ? 13126 bothOrAll(totals.assertions.failed) : std::string(); 13127 out << 13128 "Failed " << bothOrAll(totals.testCases.failed) 13129 << pluralise(totals.testCases.failed, "test case") << ", " 13130 "failed " << qualify_assertions_failed << 13131 pluralise(totals.assertions.failed, "assertion") << '.'; 13132 } else if (totals.assertions.total() == 0) { 13133 out << 13134 "Passed " << bothOrAll(totals.testCases.total()) 13135 << pluralise(totals.testCases.total(), "test case") 13136 << " (no assertions)."; 13137 } else if (totals.assertions.failed) { 13138 Colour colour(Colour::ResultError); 13139 out << 13140 "Failed " << pluralise(totals.testCases.failed, "test case") << ", " 13141 "failed " << pluralise(totals.assertions.failed, "assertion") << '.'; 13142 } else { 13143 Colour colour(Colour::ResultSuccess); 13144 out << 13145 "Passed " << bothOrAll(totals.testCases.passed) 13146 << pluralise(totals.testCases.passed, "test case") << 13147 " with " << pluralise(totals.assertions.passed, "assertion") << '.'; 13148 } 13149 } 13150 13151 // Implementation of CompactReporter formatting 13152 class AssertionPrinter { 13153 public: 13154 AssertionPrinter& operator= (AssertionPrinter const&) = delete; 13155 AssertionPrinter(AssertionPrinter const&) = delete; 13156 AssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages) 13157 : stream(_stream) 13158 , result(_stats.assertionResult) 13159 , messages(_stats.infoMessages) 13160 , itMessage(_stats.infoMessages.begin()) 13161 , printInfoMessages(_printInfoMessages) {} 13162 13163 void print() { 13164 printSourceInfo(); 13165 13166 itMessage = messages.begin(); 13167 13168 switch (result.getResultType()) { 13169 case ResultWas::Ok: 13170 printResultType(Colour::ResultSuccess, passedString()); 13171 printOriginalExpression(); 13172 printReconstructedExpression(); 13173 if (!result.hasExpression()) 13174 printRemainingMessages(Colour::None); 13175 else 13176 printRemainingMessages(); 13177 break; 13178 case ResultWas::ExpressionFailed: 13179 if (result.isOk()) 13180 printResultType(Colour::ResultSuccess, failedString() + std::string(" - but was ok")); 13181 else 13182 printResultType(Colour::Error, failedString()); 13183 printOriginalExpression(); 13184 printReconstructedExpression(); 13185 printRemainingMessages(); 13186 break; 13187 case ResultWas::ThrewException: 13188 printResultType(Colour::Error, failedString()); 13189 printIssue("unexpected exception with message:"); 13190 printMessage(); 13191 printExpressionWas(); 13192 printRemainingMessages(); 13193 break; 13194 case ResultWas::FatalErrorCondition: 13195 printResultType(Colour::Error, failedString()); 13196 printIssue("fatal error condition with message:"); 13197 printMessage(); 13198 printExpressionWas(); 13199 printRemainingMessages(); 13200 break; 13201 case ResultWas::DidntThrowException: 13202 printResultType(Colour::Error, failedString()); 13203 printIssue("expected exception, got none"); 13204 printExpressionWas(); 13205 printRemainingMessages(); 13206 break; 13207 case ResultWas::Info: 13208 printResultType(Colour::None, "info"); 13209 printMessage(); 13210 printRemainingMessages(); 13211 break; 13212 case ResultWas::Warning: 13213 printResultType(Colour::None, "warning"); 13214 printMessage(); 13215 printRemainingMessages(); 13216 break; 13217 case ResultWas::ExplicitFailure: 13218 printResultType(Colour::Error, failedString()); 13219 printIssue("explicitly"); 13220 printRemainingMessages(Colour::None); 13221 break; 13222 // These cases are here to prevent compiler warnings 13223 case ResultWas::Unknown: 13224 case ResultWas::FailureBit: 13225 case ResultWas::Exception: 13226 printResultType(Colour::Error, "** internal error **"); 13227 break; 13228 } 13229 } 13230 13231 private: 13232 void printSourceInfo() const { 13233 Colour colourGuard(Colour::FileName); 13234 stream << result.getSourceInfo() << ':'; 13235 } 13236 13237 void printResultType(Colour::Code colour, std::string const& passOrFail) const { 13238 if (!passOrFail.empty()) { 13239 { 13240 Colour colourGuard(colour); 13241 stream << ' ' << passOrFail; 13242 } 13243 stream << ':'; 13244 } 13245 } 13246 13247 void printIssue(std::string const& issue) const { 13248 stream << ' ' << issue; 13249 } 13250 13251 void printExpressionWas() { 13252 if (result.hasExpression()) { 13253 stream << ';'; 13254 { 13255 Colour colour(dimColour()); 13256 stream << " expression was:"; 13257 } 13258 printOriginalExpression(); 13259 } 13260 } 13261 13262 void printOriginalExpression() const { 13263 if (result.hasExpression()) { 13264 stream << ' ' << result.getExpression(); 13265 } 13266 } 13267 13268 void printReconstructedExpression() const { 13269 if (result.hasExpandedExpression()) { 13270 { 13271 Colour colour(dimColour()); 13272 stream << " for: "; 13273 } 13274 stream << result.getExpandedExpression(); 13275 } 13276 } 13277 13278 void printMessage() { 13279 if (itMessage != messages.end()) { 13280 stream << " '" << itMessage->message << '\''; 13281 ++itMessage; 13282 } 13283 } 13284 13285 void printRemainingMessages(Colour::Code colour = dimColour()) { 13286 if (itMessage == messages.end()) 13287 return; 13288 13289 // using messages.end() directly yields (or auto) compilation error: 13290 std::vector<MessageInfo>::const_iterator itEnd = messages.end(); 13291 const std::size_t N = static_cast<std::size_t>(std::distance(itMessage, itEnd)); 13292 13293 { 13294 Colour colourGuard(colour); 13295 stream << " with " << pluralise(N, "message") << ':'; 13296 } 13297 13298 for (; itMessage != itEnd; ) { 13299 // If this assertion is a warning ignore any INFO messages 13300 if (printInfoMessages || itMessage->type != ResultWas::Info) { 13301 stream << " '" << itMessage->message << '\''; 13302 if (++itMessage != itEnd) { 13303 Colour colourGuard(dimColour()); 13304 stream << " and"; 13305 } 13306 } 13307 } 13308 } 13309 13310 private: 13311 std::ostream& stream; 13312 AssertionResult const& result; 13313 std::vector<MessageInfo> messages; 13314 std::vector<MessageInfo>::const_iterator itMessage; 13315 bool printInfoMessages; 13316 }; 13317 13318 } // anon namespace 13319 13320 std::string CompactReporter::getDescription() { 13321 return "Reports test results on a single line, suitable for IDEs"; 13322 } 13323 13324 ReporterPreferences CompactReporter::getPreferences() const { 13325 return m_reporterPrefs; 13326 } 13327 13328 void CompactReporter::noMatchingTestCases( std::string const& spec ) { 13329 stream << "No test cases matched '" << spec << '\'' << std::endl; 13330 } 13331 13332 void CompactReporter::assertionStarting( AssertionInfo const& ) {} 13333 13334 bool CompactReporter::assertionEnded( AssertionStats const& _assertionStats ) { 13335 AssertionResult const& result = _assertionStats.assertionResult; 13336 13337 bool printInfoMessages = true; 13338 13339 // Drop out if result was successful and we're not printing those 13340 if( !m_config->includeSuccessfulResults() && result.isOk() ) { 13341 if( result.getResultType() != ResultWas::Warning ) 13342 return false; 13343 printInfoMessages = false; 13344 } 13345 13346 AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); 13347 printer.print(); 13348 13349 stream << std::endl; 13350 return true; 13351 } 13352 13353 void CompactReporter::sectionEnded(SectionStats const& _sectionStats) { 13354 if (m_config->showDurations() == ShowDurations::Always) { 13355 stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl; 13356 } 13357 } 13358 13359 void CompactReporter::testRunEnded( TestRunStats const& _testRunStats ) { 13360 printTotals( stream, _testRunStats.totals ); 13361 stream << '\n' << std::endl; 13362 StreamingReporterBase::testRunEnded( _testRunStats ); 13363 } 13364 13365 CompactReporter::~CompactReporter() {} 13366 13367 CATCH_REGISTER_REPORTER( "compact", CompactReporter ) 13368 13369 } // end namespace Catch 13370 // end catch_reporter_compact.cpp 13371 // start catch_reporter_console.cpp 13372 13373 #include <cfloat> 13374 #include <cstdio> 13375 13376 #if defined(_MSC_VER) 13377 #pragma warning(push) 13378 #pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch 13379 // Note that 4062 (not all labels are handled 13380 // and default is missing) is enabled 13381 #endif 13382 13383 namespace Catch { 13384 13385 namespace { 13386 13387 // Formatter impl for ConsoleReporter 13388 class ConsoleAssertionPrinter { 13389 public: 13390 ConsoleAssertionPrinter& operator= (ConsoleAssertionPrinter const&) = delete; 13391 ConsoleAssertionPrinter(ConsoleAssertionPrinter const&) = delete; 13392 ConsoleAssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages) 13393 : stream(_stream), 13394 stats(_stats), 13395 result(_stats.assertionResult), 13396 colour(Colour::None), 13397 message(result.getMessage()), 13398 messages(_stats.infoMessages), 13399 printInfoMessages(_printInfoMessages) { 13400 switch (result.getResultType()) { 13401 case ResultWas::Ok: 13402 colour = Colour::Success; 13403 passOrFail = "PASSED"; 13404 //if( result.hasMessage() ) 13405 if (_stats.infoMessages.size() == 1) 13406 messageLabel = "with message"; 13407 if (_stats.infoMessages.size() > 1) 13408 messageLabel = "with messages"; 13409 break; 13410 case ResultWas::ExpressionFailed: 13411 if (result.isOk()) { 13412 colour = Colour::Success; 13413 passOrFail = "FAILED - but was ok"; 13414 } else { 13415 colour = Colour::Error; 13416 passOrFail = "error: FAILED"; 13417 } 13418 if (_stats.infoMessages.size() == 1) 13419 messageLabel = "with message"; 13420 if (_stats.infoMessages.size() > 1) 13421 messageLabel = "with messages"; 13422 break; 13423 case ResultWas::ThrewException: 13424 colour = Colour::Error; 13425 passOrFail = "error: FAILED"; 13426 messageLabel = "due to unexpected exception with "; 13427 if (_stats.infoMessages.size() == 1) 13428 messageLabel += "message"; 13429 if (_stats.infoMessages.size() > 1) 13430 messageLabel += "messages"; 13431 break; 13432 case ResultWas::FatalErrorCondition: 13433 colour = Colour::Error; 13434 passOrFail = "error: FAILED"; 13435 messageLabel = "due to a fatal error condition"; 13436 break; 13437 case ResultWas::DidntThrowException: 13438 colour = Colour::Error; 13439 passOrFail = "error: FAILED"; 13440 messageLabel = "because no exception was thrown where one was expected"; 13441 break; 13442 case ResultWas::Info: 13443 messageLabel = "info"; 13444 break; 13445 case ResultWas::Warning: 13446 messageLabel = "warning"; 13447 break; 13448 case ResultWas::ExplicitFailure: 13449 passOrFail = "FAILED"; 13450 colour = Colour::Error; 13451 if (_stats.infoMessages.size() == 1) 13452 messageLabel = "explicitly with message"; 13453 if (_stats.infoMessages.size() > 1) 13454 messageLabel = "explicitly with messages"; 13455 break; 13456 // These cases are here to prevent compiler warnings 13457 case ResultWas::Unknown: 13458 case ResultWas::FailureBit: 13459 case ResultWas::Exception: 13460 passOrFail = "** internal error **"; 13461 colour = Colour::Error; 13462 break; 13463 } 13464 } 13465 13466 void print() const { 13467 printSourceInfo(); 13468 if (stats.totals.assertions.total() > 0) { 13469 printResultType(); 13470 printOriginalExpression(); 13471 printReconstructedExpression(); 13472 } else { 13473 stream << '\n'; 13474 } 13475 printMessage(); 13476 } 13477 13478 private: 13479 void printResultType() const { 13480 if (!passOrFail.empty()) { 13481 Colour colourGuard(colour); 13482 stream << passOrFail << ": "; 13483 } 13484 } 13485 void printOriginalExpression() const { 13486 if (result.hasExpression()) { 13487 Colour colourGuard(Colour::OriginalExpression); 13488 stream << " "; 13489 stream << result.getExpressionInMacro(); 13490 stream << ' '; 13491 } 13492 } 13493 void printReconstructedExpression() const { 13494 if (result.hasExpandedExpression()) { 13495 stream << "with expansion: "; 13496 Colour colourGuard(Colour::ReconstructedExpression); 13497 stream << result.getExpandedExpression() << '\n'; 13498 } 13499 } 13500 void printMessage() const { 13501 if (!messageLabel.empty()) 13502 stream << messageLabel << ':' << '\n'; 13503 for (auto const& msg : messages) { 13504 // If this assertion is a warning ignore any INFO messages 13505 if (printInfoMessages || msg.type != ResultWas::Info) 13506 stream << Column(msg.message).indent(2) << '\n'; 13507 } 13508 } 13509 void printSourceInfo() const { 13510 Colour colourGuard(Colour::FileName); 13511 stream << result.getSourceInfo() << ": "; 13512 } 13513 13514 std::ostream& stream; 13515 AssertionStats const& stats; 13516 AssertionResult const& result; 13517 Colour::Code colour; 13518 std::string passOrFail; 13519 std::string messageLabel; 13520 std::string message; 13521 std::vector<MessageInfo> messages; 13522 bool printInfoMessages; 13523 }; 13524 13525 std::size_t makeRatio(std::size_t number, std::size_t total) { 13526 std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number / total : 0; 13527 return (ratio == 0 && number > 0) ? 1 : ratio; 13528 } 13529 13530 std::size_t& findMax(std::size_t& i, std::size_t& j, std::size_t& k) { 13531 if (i > j && i > k) 13532 return i; 13533 else if (j > k) 13534 return j; 13535 else 13536 return k; 13537 } 13538 13539 struct ColumnInfo { 13540 enum Justification { Left, Right }; 13541 std::string name; 13542 int width; 13543 Justification justification; 13544 }; 13545 struct ColumnBreak {}; 13546 struct RowBreak {}; 13547 13548 class Duration { 13549 enum class Unit { 13550 Auto, 13551 Nanoseconds, 13552 Microseconds, 13553 Milliseconds, 13554 Seconds, 13555 Minutes 13556 }; 13557 static const uint64_t s_nanosecondsInAMicrosecond = 1000; 13558 static const uint64_t s_nanosecondsInAMillisecond = 1000 * s_nanosecondsInAMicrosecond; 13559 static const uint64_t s_nanosecondsInASecond = 1000 * s_nanosecondsInAMillisecond; 13560 static const uint64_t s_nanosecondsInAMinute = 60 * s_nanosecondsInASecond; 13561 13562 uint64_t m_inNanoseconds; 13563 Unit m_units; 13564 13565 public: 13566 explicit Duration(uint64_t inNanoseconds, Unit units = Unit::Auto) 13567 : m_inNanoseconds(inNanoseconds), 13568 m_units(units) { 13569 if (m_units == Unit::Auto) { 13570 if (m_inNanoseconds < s_nanosecondsInAMicrosecond) 13571 m_units = Unit::Nanoseconds; 13572 else if (m_inNanoseconds < s_nanosecondsInAMillisecond) 13573 m_units = Unit::Microseconds; 13574 else if (m_inNanoseconds < s_nanosecondsInASecond) 13575 m_units = Unit::Milliseconds; 13576 else if (m_inNanoseconds < s_nanosecondsInAMinute) 13577 m_units = Unit::Seconds; 13578 else 13579 m_units = Unit::Minutes; 13580 } 13581 13582 } 13583 13584 auto value() const -> double { 13585 switch (m_units) { 13586 case Unit::Microseconds: 13587 return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMicrosecond); 13588 case Unit::Milliseconds: 13589 return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMillisecond); 13590 case Unit::Seconds: 13591 return m_inNanoseconds / static_cast<double>(s_nanosecondsInASecond); 13592 case Unit::Minutes: 13593 return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMinute); 13594 default: 13595 return static_cast<double>(m_inNanoseconds); 13596 } 13597 } 13598 auto unitsAsString() const -> std::string { 13599 switch (m_units) { 13600 case Unit::Nanoseconds: 13601 return "ns"; 13602 case Unit::Microseconds: 13603 return "us"; 13604 case Unit::Milliseconds: 13605 return "ms"; 13606 case Unit::Seconds: 13607 return "s"; 13608 case Unit::Minutes: 13609 return "m"; 13610 default: 13611 return "** internal error **"; 13612 } 13613 13614 } 13615 friend auto operator << (std::ostream& os, Duration const& duration) -> std::ostream& { 13616 return os << duration.value() << " " << duration.unitsAsString(); 13617 } 13618 }; 13619 } // end anon namespace 13620 13621 class TablePrinter { 13622 std::ostream& m_os; 13623 std::vector<ColumnInfo> m_columnInfos; 13624 std::ostringstream m_oss; 13625 int m_currentColumn = -1; 13626 bool m_isOpen = false; 13627 13628 public: 13629 TablePrinter( std::ostream& os, std::vector<ColumnInfo> columnInfos ) 13630 : m_os( os ), 13631 m_columnInfos( std::move( columnInfos ) ) {} 13632 13633 auto columnInfos() const -> std::vector<ColumnInfo> const& { 13634 return m_columnInfos; 13635 } 13636 13637 void open() { 13638 if (!m_isOpen) { 13639 m_isOpen = true; 13640 *this << RowBreak(); 13641 for (auto const& info : m_columnInfos) 13642 *this << info.name << ColumnBreak(); 13643 *this << RowBreak(); 13644 m_os << Catch::getLineOfChars<'-'>() << "\n"; 13645 } 13646 } 13647 void close() { 13648 if (m_isOpen) { 13649 *this << RowBreak(); 13650 m_os << std::endl; 13651 m_isOpen = false; 13652 } 13653 } 13654 13655 template<typename T> 13656 friend TablePrinter& operator << (TablePrinter& tp, T const& value) { 13657 tp.m_oss << value; 13658 return tp; 13659 } 13660 13661 friend TablePrinter& operator << (TablePrinter& tp, ColumnBreak) { 13662 auto colStr = tp.m_oss.str(); 13663 // This takes account of utf8 encodings 13664 auto strSize = Catch::StringRef(colStr).numberOfCharacters(); 13665 tp.m_oss.str(""); 13666 tp.open(); 13667 if (tp.m_currentColumn == static_cast<int>(tp.m_columnInfos.size() - 1)) { 13668 tp.m_currentColumn = -1; 13669 tp.m_os << "\n"; 13670 } 13671 tp.m_currentColumn++; 13672 13673 auto colInfo = tp.m_columnInfos[tp.m_currentColumn]; 13674 auto padding = (strSize + 2 < static_cast<std::size_t>(colInfo.width)) 13675 ? std::string(colInfo.width - (strSize + 2), ' ') 13676 : std::string(); 13677 if (colInfo.justification == ColumnInfo::Left) 13678 tp.m_os << colStr << padding << " "; 13679 else 13680 tp.m_os << padding << colStr << " "; 13681 return tp; 13682 } 13683 13684 friend TablePrinter& operator << (TablePrinter& tp, RowBreak) { 13685 if (tp.m_currentColumn > 0) { 13686 tp.m_os << "\n"; 13687 tp.m_currentColumn = -1; 13688 } 13689 return tp; 13690 } 13691 }; 13692 13693 ConsoleReporter::ConsoleReporter(ReporterConfig const& config) 13694 : StreamingReporterBase(config), 13695 m_tablePrinter(new TablePrinter(config.stream(), 13696 { 13697 { "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 32, ColumnInfo::Left }, 13698 { "iters", 8, ColumnInfo::Right }, 13699 { "elapsed ns", 14, ColumnInfo::Right }, 13700 { "average", 14, ColumnInfo::Right } 13701 })) {} 13702 ConsoleReporter::~ConsoleReporter() = default; 13703 13704 std::string ConsoleReporter::getDescription() { 13705 return "Reports test results as plain lines of text"; 13706 } 13707 13708 void ConsoleReporter::noMatchingTestCases(std::string const& spec) { 13709 stream << "No test cases matched '" << spec << '\'' << std::endl; 13710 } 13711 13712 void ConsoleReporter::assertionStarting(AssertionInfo const&) {} 13713 13714 bool ConsoleReporter::assertionEnded(AssertionStats const& _assertionStats) { 13715 AssertionResult const& result = _assertionStats.assertionResult; 13716 13717 bool includeResults = m_config->includeSuccessfulResults() || !result.isOk(); 13718 13719 // Drop out if result was successful but we're not printing them. 13720 if (!includeResults && result.getResultType() != ResultWas::Warning) 13721 return false; 13722 13723 lazyPrint(); 13724 13725 ConsoleAssertionPrinter printer(stream, _assertionStats, includeResults); 13726 printer.print(); 13727 stream << std::endl; 13728 return true; 13729 } 13730 13731 void ConsoleReporter::sectionStarting(SectionInfo const& _sectionInfo) { 13732 m_headerPrinted = false; 13733 StreamingReporterBase::sectionStarting(_sectionInfo); 13734 } 13735 void ConsoleReporter::sectionEnded(SectionStats const& _sectionStats) { 13736 m_tablePrinter->close(); 13737 if (_sectionStats.missingAssertions) { 13738 lazyPrint(); 13739 Colour colour(Colour::ResultError); 13740 if (m_sectionStack.size() > 1) 13741 stream << "\nNo assertions in section"; 13742 else 13743 stream << "\nNo assertions in test case"; 13744 stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; 13745 } 13746 if (m_config->showDurations() == ShowDurations::Always) { 13747 stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl; 13748 } 13749 if (m_headerPrinted) { 13750 m_headerPrinted = false; 13751 } 13752 StreamingReporterBase::sectionEnded(_sectionStats); 13753 } 13754 13755 void ConsoleReporter::benchmarkStarting(BenchmarkInfo const& info) { 13756 lazyPrintWithoutClosingBenchmarkTable(); 13757 13758 auto nameCol = Column( info.name ).width( static_cast<std::size_t>( m_tablePrinter->columnInfos()[0].width - 2 ) ); 13759 13760 bool firstLine = true; 13761 for (auto line : nameCol) { 13762 if (!firstLine) 13763 (*m_tablePrinter) << ColumnBreak() << ColumnBreak() << ColumnBreak(); 13764 else 13765 firstLine = false; 13766 13767 (*m_tablePrinter) << line << ColumnBreak(); 13768 } 13769 } 13770 void ConsoleReporter::benchmarkEnded(BenchmarkStats const& stats) { 13771 Duration average(stats.elapsedTimeInNanoseconds / stats.iterations); 13772 (*m_tablePrinter) 13773 << stats.iterations << ColumnBreak() 13774 << stats.elapsedTimeInNanoseconds << ColumnBreak() 13775 << average << ColumnBreak(); 13776 } 13777 13778 void ConsoleReporter::testCaseEnded(TestCaseStats const& _testCaseStats) { 13779 m_tablePrinter->close(); 13780 StreamingReporterBase::testCaseEnded(_testCaseStats); 13781 m_headerPrinted = false; 13782 } 13783 void ConsoleReporter::testGroupEnded(TestGroupStats const& _testGroupStats) { 13784 if (currentGroupInfo.used) { 13785 printSummaryDivider(); 13786 stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; 13787 printTotals(_testGroupStats.totals); 13788 stream << '\n' << std::endl; 13789 } 13790 StreamingReporterBase::testGroupEnded(_testGroupStats); 13791 } 13792 void ConsoleReporter::testRunEnded(TestRunStats const& _testRunStats) { 13793 printTotalsDivider(_testRunStats.totals); 13794 printTotals(_testRunStats.totals); 13795 stream << std::endl; 13796 StreamingReporterBase::testRunEnded(_testRunStats); 13797 } 13798 void ConsoleReporter::testRunStarting(TestRunInfo const& _testInfo) { 13799 StreamingReporterBase::testRunStarting(_testInfo); 13800 printTestFilters(); 13801 } 13802 13803 void ConsoleReporter::lazyPrint() { 13804 13805 m_tablePrinter->close(); 13806 lazyPrintWithoutClosingBenchmarkTable(); 13807 } 13808 13809 void ConsoleReporter::lazyPrintWithoutClosingBenchmarkTable() { 13810 13811 if (!currentTestRunInfo.used) 13812 lazyPrintRunInfo(); 13813 if (!currentGroupInfo.used) 13814 lazyPrintGroupInfo(); 13815 13816 if (!m_headerPrinted) { 13817 printTestCaseAndSectionHeader(); 13818 m_headerPrinted = true; 13819 } 13820 } 13821 void ConsoleReporter::lazyPrintRunInfo() { 13822 stream << '\n' << getLineOfChars<'~'>() << '\n'; 13823 Colour colour(Colour::SecondaryText); 13824 stream << currentTestRunInfo->name 13825 << " is a Catch v" << libraryVersion() << " host application.\n" 13826 << "Run with -? for options\n\n"; 13827 13828 if (m_config->rngSeed() != 0) 13829 stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n"; 13830 13831 currentTestRunInfo.used = true; 13832 } 13833 void ConsoleReporter::lazyPrintGroupInfo() { 13834 if (!currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1) { 13835 printClosedHeader("Group: " + currentGroupInfo->name); 13836 currentGroupInfo.used = true; 13837 } 13838 } 13839 void ConsoleReporter::printTestCaseAndSectionHeader() { 13840 assert(!m_sectionStack.empty()); 13841 printOpenHeader(currentTestCaseInfo->name); 13842 13843 if (m_sectionStack.size() > 1) { 13844 Colour colourGuard(Colour::Headers); 13845 13846 auto 13847 it = m_sectionStack.begin() + 1, // Skip first section (test case) 13848 itEnd = m_sectionStack.end(); 13849 for (; it != itEnd; ++it) 13850 printHeaderString(it->name, 2); 13851 } 13852 13853 SourceLineInfo lineInfo = m_sectionStack.back().lineInfo; 13854 13855 if (!lineInfo.empty()) { 13856 stream << getLineOfChars<'-'>() << '\n'; 13857 Colour colourGuard(Colour::FileName); 13858 stream << lineInfo << ": in test " << m_sectionStack.back().name << ":"; 13859 } 13860 stream << std::endl; 13861 } 13862 13863 void ConsoleReporter::printClosedHeader(std::string const& _name) { 13864 printOpenHeader(_name); 13865 stream << getLineOfChars<'.'>() << '\n'; 13866 } 13867 void ConsoleReporter::printOpenHeader(std::string const& _name) { 13868 stream << getLineOfChars<'-'>() << '\n'; 13869 { 13870 Colour colourGuard(Colour::Headers); 13871 printHeaderString(_name); 13872 } 13873 } 13874 13875 // if string has a : in first line will set indent to follow it on 13876 // subsequent lines 13877 void ConsoleReporter::printHeaderString(std::string const& _string, std::size_t indent) { 13878 std::size_t i = _string.find(": "); 13879 if (i != std::string::npos) 13880 i += 2; 13881 else 13882 i = 0; 13883 stream << Column(_string).indent(indent + i).initialIndent(indent) << '\n'; 13884 } 13885 13886 struct SummaryColumn { 13887 13888 SummaryColumn( std::string _label, Colour::Code _colour ) 13889 : label( std::move( _label ) ), 13890 colour( _colour ) {} 13891 SummaryColumn addRow( std::size_t count ) { 13892 ReusableStringStream rss; 13893 rss << count; 13894 std::string row = rss.str(); 13895 for (auto& oldRow : rows) { 13896 while (oldRow.size() < row.size()) 13897 oldRow = ' ' + oldRow; 13898 while (oldRow.size() > row.size()) 13899 row = ' ' + row; 13900 } 13901 rows.push_back(row); 13902 return *this; 13903 } 13904 13905 std::string label; 13906 Colour::Code colour; 13907 std::vector<std::string> rows; 13908 13909 }; 13910 13911 void ConsoleReporter::printTotals( Totals const& totals ) { 13912 if (totals.testCases.total() == 0) { 13913 stream << Colour(Colour::Warning) << "No tests ran\n"; 13914 } else if (totals.assertions.total() > 0 && totals.testCases.allPassed()) { 13915 stream << Colour(Colour::ResultSuccess) << "All tests passed"; 13916 stream << " (" 13917 << pluralise(totals.assertions.passed, "assertion") << " in " 13918 << pluralise(totals.testCases.passed, "test case") << ')' 13919 << '\n'; 13920 } else { 13921 13922 std::vector<SummaryColumn> columns; 13923 columns.push_back(SummaryColumn("", Colour::None) 13924 .addRow(totals.testCases.total()) 13925 .addRow(totals.assertions.total())); 13926 columns.push_back(SummaryColumn("passed", Colour::Success) 13927 .addRow(totals.testCases.passed) 13928 .addRow(totals.assertions.passed)); 13929 columns.push_back(SummaryColumn("failed", Colour::ResultError) 13930 .addRow(totals.testCases.failed) 13931 .addRow(totals.assertions.failed)); 13932 columns.push_back(SummaryColumn("failed as expected", Colour::ResultExpectedFailure) 13933 .addRow(totals.testCases.failedButOk) 13934 .addRow(totals.assertions.failedButOk)); 13935 13936 printSummaryRow("test cases", columns, 0); 13937 printSummaryRow("assertions", columns, 1); 13938 } 13939 } 13940 void ConsoleReporter::printSummaryRow(std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row) { 13941 for (auto col : cols) { 13942 std::string value = col.rows[row]; 13943 if (col.label.empty()) { 13944 stream << label << ": "; 13945 if (value != "0") 13946 stream << value; 13947 else 13948 stream << Colour(Colour::Warning) << "- none -"; 13949 } else if (value != "0") { 13950 stream << Colour(Colour::LightGrey) << " | "; 13951 stream << Colour(col.colour) 13952 << value << ' ' << col.label; 13953 } 13954 } 13955 stream << '\n'; 13956 } 13957 13958 void ConsoleReporter::printTotalsDivider(Totals const& totals) { 13959 if (totals.testCases.total() > 0) { 13960 std::size_t failedRatio = makeRatio(totals.testCases.failed, totals.testCases.total()); 13961 std::size_t failedButOkRatio = makeRatio(totals.testCases.failedButOk, totals.testCases.total()); 13962 std::size_t passedRatio = makeRatio(totals.testCases.passed, totals.testCases.total()); 13963 while (failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH - 1) 13964 findMax(failedRatio, failedButOkRatio, passedRatio)++; 13965 while (failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH - 1) 13966 findMax(failedRatio, failedButOkRatio, passedRatio)--; 13967 13968 stream << Colour(Colour::Error) << std::string(failedRatio, '='); 13969 stream << Colour(Colour::ResultExpectedFailure) << std::string(failedButOkRatio, '='); 13970 if (totals.testCases.allPassed()) 13971 stream << Colour(Colour::ResultSuccess) << std::string(passedRatio, '='); 13972 else 13973 stream << Colour(Colour::Success) << std::string(passedRatio, '='); 13974 } else { 13975 stream << Colour(Colour::Warning) << std::string(CATCH_CONFIG_CONSOLE_WIDTH - 1, '='); 13976 } 13977 stream << '\n'; 13978 } 13979 void ConsoleReporter::printSummaryDivider() { 13980 stream << getLineOfChars<'-'>() << '\n'; 13981 } 13982 13983 void ConsoleReporter::printTestFilters() { 13984 if (m_config->testSpec().hasFilters()) 13985 stream << Colour(Colour::BrightYellow) << "Filters: " << serializeFilters( m_config->getTestsOrTags() ) << '\n'; 13986 } 13987 13988 CATCH_REGISTER_REPORTER("console", ConsoleReporter) 13989 13990 } // end namespace Catch 13991 13992 #if defined(_MSC_VER) 13993 #pragma warning(pop) 13994 #endif 13995 // end catch_reporter_console.cpp 13996 // start catch_reporter_junit.cpp 13997 13998 #include <cassert> 13999 #include <sstream> 14000 #include <ctime> 14001 #include <algorithm> 14002 14003 namespace Catch { 14004 14005 namespace { 14006 std::string getCurrentTimestamp() { 14007 // Beware, this is not reentrant because of backward compatibility issues 14008 // Also, UTC only, again because of backward compatibility (%z is C++11) 14009 time_t rawtime; 14010 std::time(&rawtime); 14011 auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); 14012 14013 #ifdef _MSC_VER 14014 std::tm timeInfo = {}; 14015 gmtime_s(&timeInfo, &rawtime); 14016 #else 14017 std::tm* timeInfo; 14018 timeInfo = std::gmtime(&rawtime); 14019 #endif 14020 14021 char timeStamp[timeStampSize]; 14022 const char * const fmt = "%Y-%m-%dT%H:%M:%SZ"; 14023 14024 #ifdef _MSC_VER 14025 std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); 14026 #else 14027 std::strftime(timeStamp, timeStampSize, fmt, timeInfo); 14028 #endif 14029 return std::string(timeStamp); 14030 } 14031 14032 std::string fileNameTag(const std::vector<std::string> &tags) { 14033 auto it = std::find_if(begin(tags), 14034 end(tags), 14035 [] (std::string const& tag) {return tag.front() == '#'; }); 14036 if (it != tags.end()) 14037 return it->substr(1); 14038 return std::string(); 14039 } 14040 } // anonymous namespace 14041 14042 JunitReporter::JunitReporter( ReporterConfig const& _config ) 14043 : CumulativeReporterBase( _config ), 14044 xml( _config.stream() ) 14045 { 14046 m_reporterPrefs.shouldRedirectStdOut = true; 14047 m_reporterPrefs.shouldReportAllAssertions = true; 14048 } 14049 14050 JunitReporter::~JunitReporter() {} 14051 14052 std::string JunitReporter::getDescription() { 14053 return "Reports test results in an XML format that looks like Ant's junitreport target"; 14054 } 14055 14056 void JunitReporter::noMatchingTestCases( std::string const& /*spec*/ ) {} 14057 14058 void JunitReporter::testRunStarting( TestRunInfo const& runInfo ) { 14059 CumulativeReporterBase::testRunStarting( runInfo ); 14060 xml.startElement( "testsuites" ); 14061 } 14062 14063 void JunitReporter::testGroupStarting( GroupInfo const& groupInfo ) { 14064 suiteTimer.start(); 14065 stdOutForSuite.clear(); 14066 stdErrForSuite.clear(); 14067 unexpectedExceptions = 0; 14068 CumulativeReporterBase::testGroupStarting( groupInfo ); 14069 } 14070 14071 void JunitReporter::testCaseStarting( TestCaseInfo const& testCaseInfo ) { 14072 m_okToFail = testCaseInfo.okToFail(); 14073 } 14074 14075 bool JunitReporter::assertionEnded( AssertionStats const& assertionStats ) { 14076 if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException && !m_okToFail ) 14077 unexpectedExceptions++; 14078 return CumulativeReporterBase::assertionEnded( assertionStats ); 14079 } 14080 14081 void JunitReporter::testCaseEnded( TestCaseStats const& testCaseStats ) { 14082 stdOutForSuite += testCaseStats.stdOut; 14083 stdErrForSuite += testCaseStats.stdErr; 14084 CumulativeReporterBase::testCaseEnded( testCaseStats ); 14085 } 14086 14087 void JunitReporter::testGroupEnded( TestGroupStats const& testGroupStats ) { 14088 double suiteTime = suiteTimer.getElapsedSeconds(); 14089 CumulativeReporterBase::testGroupEnded( testGroupStats ); 14090 writeGroup( *m_testGroups.back(), suiteTime ); 14091 } 14092 14093 void JunitReporter::testRunEndedCumulative() { 14094 xml.endElement(); 14095 } 14096 14097 void JunitReporter::writeGroup( TestGroupNode const& groupNode, double suiteTime ) { 14098 XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); 14099 14100 TestGroupStats const& stats = groupNode.value; 14101 xml.writeAttribute( "name", stats.groupInfo.name ); 14102 xml.writeAttribute( "errors", unexpectedExceptions ); 14103 xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions ); 14104 xml.writeAttribute( "tests", stats.totals.assertions.total() ); 14105 xml.writeAttribute( "hostname", "tbd" ); // !TBD 14106 if( m_config->showDurations() == ShowDurations::Never ) 14107 xml.writeAttribute( "time", "" ); 14108 else 14109 xml.writeAttribute( "time", suiteTime ); 14110 xml.writeAttribute( "timestamp", getCurrentTimestamp() ); 14111 14112 // Write properties if there are any 14113 if (m_config->hasTestFilters() || m_config->rngSeed() != 0) { 14114 auto properties = xml.scopedElement("properties"); 14115 if (m_config->hasTestFilters()) { 14116 xml.scopedElement("property") 14117 .writeAttribute("name", "filters") 14118 .writeAttribute("value", serializeFilters(m_config->getTestsOrTags())); 14119 } 14120 if (m_config->rngSeed() != 0) { 14121 xml.scopedElement("property") 14122 .writeAttribute("name", "random-seed") 14123 .writeAttribute("value", m_config->rngSeed()); 14124 } 14125 } 14126 14127 // Write test cases 14128 for( auto const& child : groupNode.children ) 14129 writeTestCase( *child ); 14130 14131 xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite ), false ); 14132 xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite ), false ); 14133 } 14134 14135 void JunitReporter::writeTestCase( TestCaseNode const& testCaseNode ) { 14136 TestCaseStats const& stats = testCaseNode.value; 14137 14138 // All test cases have exactly one section - which represents the 14139 // test case itself. That section may have 0-n nested sections 14140 assert( testCaseNode.children.size() == 1 ); 14141 SectionNode const& rootSection = *testCaseNode.children.front(); 14142 14143 std::string className = stats.testInfo.className; 14144 14145 if( className.empty() ) { 14146 className = fileNameTag(stats.testInfo.tags); 14147 if ( className.empty() ) 14148 className = "global"; 14149 } 14150 14151 if ( !m_config->name().empty() ) 14152 className = m_config->name() + "." + className; 14153 14154 writeSection( className, "", rootSection ); 14155 } 14156 14157 void JunitReporter::writeSection( std::string const& className, 14158 std::string const& rootName, 14159 SectionNode const& sectionNode ) { 14160 std::string name = trim( sectionNode.stats.sectionInfo.name ); 14161 if( !rootName.empty() ) 14162 name = rootName + '/' + name; 14163 14164 if( !sectionNode.assertions.empty() || 14165 !sectionNode.stdOut.empty() || 14166 !sectionNode.stdErr.empty() ) { 14167 XmlWriter::ScopedElement e = xml.scopedElement( "testcase" ); 14168 if( className.empty() ) { 14169 xml.writeAttribute( "classname", name ); 14170 xml.writeAttribute( "name", "root" ); 14171 } 14172 else { 14173 xml.writeAttribute( "classname", className ); 14174 xml.writeAttribute( "name", name ); 14175 } 14176 xml.writeAttribute( "time", ::Catch::Detail::stringify( sectionNode.stats.durationInSeconds ) ); 14177 14178 writeAssertions( sectionNode ); 14179 14180 if( !sectionNode.stdOut.empty() ) 14181 xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false ); 14182 if( !sectionNode.stdErr.empty() ) 14183 xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false ); 14184 } 14185 for( auto const& childNode : sectionNode.childSections ) 14186 if( className.empty() ) 14187 writeSection( name, "", *childNode ); 14188 else 14189 writeSection( className, name, *childNode ); 14190 } 14191 14192 void JunitReporter::writeAssertions( SectionNode const& sectionNode ) { 14193 for( auto const& assertion : sectionNode.assertions ) 14194 writeAssertion( assertion ); 14195 } 14196 14197 void JunitReporter::writeAssertion( AssertionStats const& stats ) { 14198 AssertionResult const& result = stats.assertionResult; 14199 if( !result.isOk() ) { 14200 std::string elementName; 14201 switch( result.getResultType() ) { 14202 case ResultWas::ThrewException: 14203 case ResultWas::FatalErrorCondition: 14204 elementName = "error"; 14205 break; 14206 case ResultWas::ExplicitFailure: 14207 elementName = "failure"; 14208 break; 14209 case ResultWas::ExpressionFailed: 14210 elementName = "failure"; 14211 break; 14212 case ResultWas::DidntThrowException: 14213 elementName = "failure"; 14214 break; 14215 14216 // We should never see these here: 14217 case ResultWas::Info: 14218 case ResultWas::Warning: 14219 case ResultWas::Ok: 14220 case ResultWas::Unknown: 14221 case ResultWas::FailureBit: 14222 case ResultWas::Exception: 14223 elementName = "internalError"; 14224 break; 14225 } 14226 14227 XmlWriter::ScopedElement e = xml.scopedElement( elementName ); 14228 14229 xml.writeAttribute( "message", result.getExpandedExpression() ); 14230 xml.writeAttribute( "type", result.getTestMacroName() ); 14231 14232 ReusableStringStream rss; 14233 if( !result.getMessage().empty() ) 14234 rss << result.getMessage() << '\n'; 14235 for( auto const& msg : stats.infoMessages ) 14236 if( msg.type == ResultWas::Info ) 14237 rss << msg.message << '\n'; 14238 14239 rss << "at " << result.getSourceInfo(); 14240 xml.writeText( rss.str(), false ); 14241 } 14242 } 14243 14244 CATCH_REGISTER_REPORTER( "junit", JunitReporter ) 14245 14246 } // end namespace Catch 14247 // end catch_reporter_junit.cpp 14248 // start catch_reporter_listening.cpp 14249 14250 #include <cassert> 14251 14252 namespace Catch { 14253 14254 ListeningReporter::ListeningReporter() { 14255 // We will assume that listeners will always want all assertions 14256 m_preferences.shouldReportAllAssertions = true; 14257 } 14258 14259 void ListeningReporter::addListener( IStreamingReporterPtr&& listener ) { 14260 m_listeners.push_back( std::move( listener ) ); 14261 } 14262 14263 void ListeningReporter::addReporter(IStreamingReporterPtr&& reporter) { 14264 assert(!m_reporter && "Listening reporter can wrap only 1 real reporter"); 14265 m_reporter = std::move( reporter ); 14266 m_preferences.shouldRedirectStdOut = m_reporter->getPreferences().shouldRedirectStdOut; 14267 } 14268 14269 ReporterPreferences ListeningReporter::getPreferences() const { 14270 return m_preferences; 14271 } 14272 14273 std::set<Verbosity> ListeningReporter::getSupportedVerbosities() { 14274 return std::set<Verbosity>{ }; 14275 } 14276 14277 void ListeningReporter::noMatchingTestCases( std::string const& spec ) { 14278 for ( auto const& listener : m_listeners ) { 14279 listener->noMatchingTestCases( spec ); 14280 } 14281 m_reporter->noMatchingTestCases( spec ); 14282 } 14283 14284 void ListeningReporter::benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) { 14285 for ( auto const& listener : m_listeners ) { 14286 listener->benchmarkStarting( benchmarkInfo ); 14287 } 14288 m_reporter->benchmarkStarting( benchmarkInfo ); 14289 } 14290 void ListeningReporter::benchmarkEnded( BenchmarkStats const& benchmarkStats ) { 14291 for ( auto const& listener : m_listeners ) { 14292 listener->benchmarkEnded( benchmarkStats ); 14293 } 14294 m_reporter->benchmarkEnded( benchmarkStats ); 14295 } 14296 14297 void ListeningReporter::testRunStarting( TestRunInfo const& testRunInfo ) { 14298 for ( auto const& listener : m_listeners ) { 14299 listener->testRunStarting( testRunInfo ); 14300 } 14301 m_reporter->testRunStarting( testRunInfo ); 14302 } 14303 14304 void ListeningReporter::testGroupStarting( GroupInfo const& groupInfo ) { 14305 for ( auto const& listener : m_listeners ) { 14306 listener->testGroupStarting( groupInfo ); 14307 } 14308 m_reporter->testGroupStarting( groupInfo ); 14309 } 14310 14311 void ListeningReporter::testCaseStarting( TestCaseInfo const& testInfo ) { 14312 for ( auto const& listener : m_listeners ) { 14313 listener->testCaseStarting( testInfo ); 14314 } 14315 m_reporter->testCaseStarting( testInfo ); 14316 } 14317 14318 void ListeningReporter::sectionStarting( SectionInfo const& sectionInfo ) { 14319 for ( auto const& listener : m_listeners ) { 14320 listener->sectionStarting( sectionInfo ); 14321 } 14322 m_reporter->sectionStarting( sectionInfo ); 14323 } 14324 14325 void ListeningReporter::assertionStarting( AssertionInfo const& assertionInfo ) { 14326 for ( auto const& listener : m_listeners ) { 14327 listener->assertionStarting( assertionInfo ); 14328 } 14329 m_reporter->assertionStarting( assertionInfo ); 14330 } 14331 14332 // The return value indicates if the messages buffer should be cleared: 14333 bool ListeningReporter::assertionEnded( AssertionStats const& assertionStats ) { 14334 for( auto const& listener : m_listeners ) { 14335 static_cast<void>( listener->assertionEnded( assertionStats ) ); 14336 } 14337 return m_reporter->assertionEnded( assertionStats ); 14338 } 14339 14340 void ListeningReporter::sectionEnded( SectionStats const& sectionStats ) { 14341 for ( auto const& listener : m_listeners ) { 14342 listener->sectionEnded( sectionStats ); 14343 } 14344 m_reporter->sectionEnded( sectionStats ); 14345 } 14346 14347 void ListeningReporter::testCaseEnded( TestCaseStats const& testCaseStats ) { 14348 for ( auto const& listener : m_listeners ) { 14349 listener->testCaseEnded( testCaseStats ); 14350 } 14351 m_reporter->testCaseEnded( testCaseStats ); 14352 } 14353 14354 void ListeningReporter::testGroupEnded( TestGroupStats const& testGroupStats ) { 14355 for ( auto const& listener : m_listeners ) { 14356 listener->testGroupEnded( testGroupStats ); 14357 } 14358 m_reporter->testGroupEnded( testGroupStats ); 14359 } 14360 14361 void ListeningReporter::testRunEnded( TestRunStats const& testRunStats ) { 14362 for ( auto const& listener : m_listeners ) { 14363 listener->testRunEnded( testRunStats ); 14364 } 14365 m_reporter->testRunEnded( testRunStats ); 14366 } 14367 14368 void ListeningReporter::skipTest( TestCaseInfo const& testInfo ) { 14369 for ( auto const& listener : m_listeners ) { 14370 listener->skipTest( testInfo ); 14371 } 14372 m_reporter->skipTest( testInfo ); 14373 } 14374 14375 bool ListeningReporter::isMulti() const { 14376 return true; 14377 } 14378 14379 } // end namespace Catch 14380 // end catch_reporter_listening.cpp 14381 // start catch_reporter_xml.cpp 14382 14383 #if defined(_MSC_VER) 14384 #pragma warning(push) 14385 #pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch 14386 // Note that 4062 (not all labels are handled 14387 // and default is missing) is enabled 14388 #endif 14389 14390 namespace Catch { 14391 XmlReporter::XmlReporter( ReporterConfig const& _config ) 14392 : StreamingReporterBase( _config ), 14393 m_xml(_config.stream()) 14394 { 14395 m_reporterPrefs.shouldRedirectStdOut = true; 14396 m_reporterPrefs.shouldReportAllAssertions = true; 14397 } 14398 14399 XmlReporter::~XmlReporter() = default; 14400 14401 std::string XmlReporter::getDescription() { 14402 return "Reports test results as an XML document"; 14403 } 14404 14405 std::string XmlReporter::getStylesheetRef() const { 14406 return std::string(); 14407 } 14408 14409 void XmlReporter::writeSourceInfo( SourceLineInfo const& sourceInfo ) { 14410 m_xml 14411 .writeAttribute( "filename", sourceInfo.file ) 14412 .writeAttribute( "line", sourceInfo.line ); 14413 } 14414 14415 void XmlReporter::noMatchingTestCases( std::string const& s ) { 14416 StreamingReporterBase::noMatchingTestCases( s ); 14417 } 14418 14419 void XmlReporter::testRunStarting( TestRunInfo const& testInfo ) { 14420 StreamingReporterBase::testRunStarting( testInfo ); 14421 std::string stylesheetRef = getStylesheetRef(); 14422 if( !stylesheetRef.empty() ) 14423 m_xml.writeStylesheetRef( stylesheetRef ); 14424 m_xml.startElement( "Catch" ); 14425 if( !m_config->name().empty() ) 14426 m_xml.writeAttribute( "name", m_config->name() ); 14427 if (m_config->testSpec().hasFilters()) 14428 m_xml.writeAttribute( "filters", serializeFilters( m_config->getTestsOrTags() ) ); 14429 if( m_config->rngSeed() != 0 ) 14430 m_xml.scopedElement( "Randomness" ) 14431 .writeAttribute( "seed", m_config->rngSeed() ); 14432 } 14433 14434 void XmlReporter::testGroupStarting( GroupInfo const& groupInfo ) { 14435 StreamingReporterBase::testGroupStarting( groupInfo ); 14436 m_xml.startElement( "Group" ) 14437 .writeAttribute( "name", groupInfo.name ); 14438 } 14439 14440 void XmlReporter::testCaseStarting( TestCaseInfo const& testInfo ) { 14441 StreamingReporterBase::testCaseStarting(testInfo); 14442 m_xml.startElement( "TestCase" ) 14443 .writeAttribute( "name", trim( testInfo.name ) ) 14444 .writeAttribute( "description", testInfo.description ) 14445 .writeAttribute( "tags", testInfo.tagsAsString() ); 14446 14447 writeSourceInfo( testInfo.lineInfo ); 14448 14449 if ( m_config->showDurations() == ShowDurations::Always ) 14450 m_testCaseTimer.start(); 14451 m_xml.ensureTagClosed(); 14452 } 14453 14454 void XmlReporter::sectionStarting( SectionInfo const& sectionInfo ) { 14455 StreamingReporterBase::sectionStarting( sectionInfo ); 14456 if( m_sectionDepth++ > 0 ) { 14457 m_xml.startElement( "Section" ) 14458 .writeAttribute( "name", trim( sectionInfo.name ) ); 14459 writeSourceInfo( sectionInfo.lineInfo ); 14460 m_xml.ensureTagClosed(); 14461 } 14462 } 14463 14464 void XmlReporter::assertionStarting( AssertionInfo const& ) { } 14465 14466 bool XmlReporter::assertionEnded( AssertionStats const& assertionStats ) { 14467 14468 AssertionResult const& result = assertionStats.assertionResult; 14469 14470 bool includeResults = m_config->includeSuccessfulResults() || !result.isOk(); 14471 14472 if( includeResults || result.getResultType() == ResultWas::Warning ) { 14473 // Print any info messages in <Info> tags. 14474 for( auto const& msg : assertionStats.infoMessages ) { 14475 if( msg.type == ResultWas::Info && includeResults ) { 14476 m_xml.scopedElement( "Info" ) 14477 .writeText( msg.message ); 14478 } else if ( msg.type == ResultWas::Warning ) { 14479 m_xml.scopedElement( "Warning" ) 14480 .writeText( msg.message ); 14481 } 14482 } 14483 } 14484 14485 // Drop out if result was successful but we're not printing them. 14486 if( !includeResults && result.getResultType() != ResultWas::Warning ) 14487 return true; 14488 14489 // Print the expression if there is one. 14490 if( result.hasExpression() ) { 14491 m_xml.startElement( "Expression" ) 14492 .writeAttribute( "success", result.succeeded() ) 14493 .writeAttribute( "type", result.getTestMacroName() ); 14494 14495 writeSourceInfo( result.getSourceInfo() ); 14496 14497 m_xml.scopedElement( "Original" ) 14498 .writeText( result.getExpression() ); 14499 m_xml.scopedElement( "Expanded" ) 14500 .writeText( result.getExpandedExpression() ); 14501 } 14502 14503 // And... Print a result applicable to each result type. 14504 switch( result.getResultType() ) { 14505 case ResultWas::ThrewException: 14506 m_xml.startElement( "Exception" ); 14507 writeSourceInfo( result.getSourceInfo() ); 14508 m_xml.writeText( result.getMessage() ); 14509 m_xml.endElement(); 14510 break; 14511 case ResultWas::FatalErrorCondition: 14512 m_xml.startElement( "FatalErrorCondition" ); 14513 writeSourceInfo( result.getSourceInfo() ); 14514 m_xml.writeText( result.getMessage() ); 14515 m_xml.endElement(); 14516 break; 14517 case ResultWas::Info: 14518 m_xml.scopedElement( "Info" ) 14519 .writeText( result.getMessage() ); 14520 break; 14521 case ResultWas::Warning: 14522 // Warning will already have been written 14523 break; 14524 case ResultWas::ExplicitFailure: 14525 m_xml.startElement( "Failure" ); 14526 writeSourceInfo( result.getSourceInfo() ); 14527 m_xml.writeText( result.getMessage() ); 14528 m_xml.endElement(); 14529 break; 14530 default: 14531 break; 14532 } 14533 14534 if( result.hasExpression() ) 14535 m_xml.endElement(); 14536 14537 return true; 14538 } 14539 14540 void XmlReporter::sectionEnded( SectionStats const& sectionStats ) { 14541 StreamingReporterBase::sectionEnded( sectionStats ); 14542 if( --m_sectionDepth > 0 ) { 14543 XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" ); 14544 e.writeAttribute( "successes", sectionStats.assertions.passed ); 14545 e.writeAttribute( "failures", sectionStats.assertions.failed ); 14546 e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk ); 14547 14548 if ( m_config->showDurations() == ShowDurations::Always ) 14549 e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds ); 14550 14551 m_xml.endElement(); 14552 } 14553 } 14554 14555 void XmlReporter::testCaseEnded( TestCaseStats const& testCaseStats ) { 14556 StreamingReporterBase::testCaseEnded( testCaseStats ); 14557 XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" ); 14558 e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() ); 14559 14560 if ( m_config->showDurations() == ShowDurations::Always ) 14561 e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() ); 14562 14563 if( !testCaseStats.stdOut.empty() ) 14564 m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), false ); 14565 if( !testCaseStats.stdErr.empty() ) 14566 m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), false ); 14567 14568 m_xml.endElement(); 14569 } 14570 14571 void XmlReporter::testGroupEnded( TestGroupStats const& testGroupStats ) { 14572 StreamingReporterBase::testGroupEnded( testGroupStats ); 14573 // TODO: Check testGroupStats.aborting and act accordingly. 14574 m_xml.scopedElement( "OverallResults" ) 14575 .writeAttribute( "successes", testGroupStats.totals.assertions.passed ) 14576 .writeAttribute( "failures", testGroupStats.totals.assertions.failed ) 14577 .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk ); 14578 m_xml.endElement(); 14579 } 14580 14581 void XmlReporter::testRunEnded( TestRunStats const& testRunStats ) { 14582 StreamingReporterBase::testRunEnded( testRunStats ); 14583 m_xml.scopedElement( "OverallResults" ) 14584 .writeAttribute( "successes", testRunStats.totals.assertions.passed ) 14585 .writeAttribute( "failures", testRunStats.totals.assertions.failed ) 14586 .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk ); 14587 m_xml.endElement(); 14588 } 14589 14590 CATCH_REGISTER_REPORTER( "xml", XmlReporter ) 14591 14592 } // end namespace Catch 14593 14594 #if defined(_MSC_VER) 14595 #pragma warning(pop) 14596 #endif 14597 // end catch_reporter_xml.cpp 14598 14599 namespace Catch { 14600 LeakDetector leakDetector; 14601 } 14602 14603 #ifdef __clang__ 14604 #pragma clang diagnostic pop 14605 #endif 14606 14607 // end catch_impl.hpp 14608 #endif 14609 14610 #ifdef CATCH_CONFIG_MAIN 14611 // start catch_default_main.hpp 14612 14613 #ifndef __OBJC__ 14614 14615 #if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN) 14616 // Standard C/C++ Win32 Unicode wmain entry point 14617 extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) { 14618 #else 14619 // Standard C/C++ main entry point 14620 int main (int argc, char * argv[]) { 14621 #endif 14622 14623 return Catch::Session().run( argc, argv ); 14624 } 14625 14626 #else // __OBJC__ 14627 14628 // Objective-C entry point 14629 int main (int argc, char * const argv[]) { 14630 #if !CATCH_ARC_ENABLED 14631 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 14632 #endif 14633 14634 Catch::registerTestMethods(); 14635 int result = Catch::Session().run( argc, (char**)argv ); 14636 14637 #if !CATCH_ARC_ENABLED 14638 [pool drain]; 14639 #endif 14640 14641 return result; 14642 } 14643 14644 #endif // __OBJC__ 14645 14646 // end catch_default_main.hpp 14647 #endif 14648 14649 #if !defined(CATCH_CONFIG_IMPL_ONLY) 14650 14651 #ifdef CLARA_CONFIG_MAIN_NOT_DEFINED 14652 # undef CLARA_CONFIG_MAIN 14653 #endif 14654 14655 #if !defined(CATCH_CONFIG_DISABLE) 14656 ////// 14657 // If this config identifier is defined then all CATCH macros are prefixed with CATCH_ 14658 #ifdef CATCH_CONFIG_PREFIX_ALL 14659 14660 #define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 14661 #define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 14662 14663 #define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 14664 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) 14665 #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) 14666 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 14667 #define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) 14668 #endif// CATCH_CONFIG_DISABLE_MATCHERS 14669 #define CATCH_REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 14670 14671 #define CATCH_CHECK( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 14672 #define CATCH_CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 14673 #define CATCH_CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 14674 #define CATCH_CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 14675 #define CATCH_CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) 14676 14677 #define CATCH_CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 14678 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) 14679 #define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 14680 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 14681 #define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 14682 #endif // CATCH_CONFIG_DISABLE_MATCHERS 14683 #define CATCH_CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 14684 14685 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 14686 #define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) 14687 14688 #define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) 14689 #endif // CATCH_CONFIG_DISABLE_MATCHERS 14690 14691 #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) 14692 #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) 14693 #define CATCH_CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CATCH_CAPTURE",__VA_ARGS__ ) 14694 14695 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) 14696 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) 14697 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) 14698 #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) 14699 #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) 14700 #define CATCH_DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ ) 14701 #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) 14702 #define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 14703 #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 14704 14705 #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE() 14706 14707 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 14708 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 14709 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 14710 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) 14711 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) 14712 #else 14713 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) ) 14714 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) 14715 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) ) 14716 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) 14717 #endif 14718 14719 #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE) 14720 #define CATCH_STATIC_REQUIRE( ... ) static_assert( __VA_ARGS__ , #__VA_ARGS__ ); CATCH_SUCCEED( #__VA_ARGS__ ) 14721 #define CATCH_STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); CATCH_SUCCEED( #__VA_ARGS__ ) 14722 #else 14723 #define CATCH_STATIC_REQUIRE( ... ) CATCH_REQUIRE( __VA_ARGS__ ) 14724 #define CATCH_STATIC_REQUIRE_FALSE( ... ) CATCH_REQUIRE_FALSE( __VA_ARGS__ ) 14725 #endif 14726 14727 // "BDD-style" convenience wrappers 14728 #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) 14729 #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) 14730 #define CATCH_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc ) 14731 #define CATCH_AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc ) 14732 #define CATCH_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc ) 14733 #define CATCH_AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc ) 14734 #define CATCH_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc ) 14735 #define CATCH_AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc ) 14736 14737 // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required 14738 #else 14739 14740 #define REQUIRE( ... ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 14741 #define REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 14742 14743 #define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 14744 #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) 14745 #define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) 14746 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 14747 #define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) 14748 #endif // CATCH_CONFIG_DISABLE_MATCHERS 14749 #define REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 14750 14751 #define CHECK( ... ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 14752 #define CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 14753 #define CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 14754 #define CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 14755 #define CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) 14756 14757 #define CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 14758 #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) 14759 #define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 14760 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 14761 #define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 14762 #endif // CATCH_CONFIG_DISABLE_MATCHERS 14763 #define CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 14764 14765 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 14766 #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) 14767 14768 #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) 14769 #endif // CATCH_CONFIG_DISABLE_MATCHERS 14770 14771 #define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) 14772 #define UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "UNSCOPED_INFO", msg ) 14773 #define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) 14774 #define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE",__VA_ARGS__ ) 14775 14776 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) 14777 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) 14778 #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) 14779 #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) 14780 #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) 14781 #define DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ ) 14782 #define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) 14783 #define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 14784 #define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 14785 #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE() 14786 14787 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 14788 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 14789 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 14790 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) 14791 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) 14792 #else 14793 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) ) 14794 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) 14795 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) ) 14796 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) 14797 #endif 14798 14799 #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE) 14800 #define STATIC_REQUIRE( ... ) static_assert( __VA_ARGS__, #__VA_ARGS__ ); SUCCEED( #__VA_ARGS__ ) 14801 #define STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); SUCCEED( "!(" #__VA_ARGS__ ")" ) 14802 #else 14803 #define STATIC_REQUIRE( ... ) REQUIRE( __VA_ARGS__ ) 14804 #define STATIC_REQUIRE_FALSE( ... ) REQUIRE_FALSE( __VA_ARGS__ ) 14805 #endif 14806 14807 #endif 14808 14809 #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) 14810 14811 // "BDD-style" convenience wrappers 14812 #define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) 14813 #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) 14814 14815 #define GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc ) 14816 #define AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc ) 14817 #define WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc ) 14818 #define AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc ) 14819 #define THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc ) 14820 #define AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc ) 14821 14822 using Catch::Detail::Approx; 14823 14824 #else // CATCH_CONFIG_DISABLE 14825 14826 ////// 14827 // If this config identifier is defined then all CATCH macros are prefixed with CATCH_ 14828 #ifdef CATCH_CONFIG_PREFIX_ALL 14829 14830 #define CATCH_REQUIRE( ... ) (void)(0) 14831 #define CATCH_REQUIRE_FALSE( ... ) (void)(0) 14832 14833 #define CATCH_REQUIRE_THROWS( ... ) (void)(0) 14834 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0) 14835 #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) (void)(0) 14836 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 14837 #define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) 14838 #endif// CATCH_CONFIG_DISABLE_MATCHERS 14839 #define CATCH_REQUIRE_NOTHROW( ... ) (void)(0) 14840 14841 #define CATCH_CHECK( ... ) (void)(0) 14842 #define CATCH_CHECK_FALSE( ... ) (void)(0) 14843 #define CATCH_CHECKED_IF( ... ) if (__VA_ARGS__) 14844 #define CATCH_CHECKED_ELSE( ... ) if (!(__VA_ARGS__)) 14845 #define CATCH_CHECK_NOFAIL( ... ) (void)(0) 14846 14847 #define CATCH_CHECK_THROWS( ... ) (void)(0) 14848 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) (void)(0) 14849 #define CATCH_CHECK_THROWS_WITH( expr, matcher ) (void)(0) 14850 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 14851 #define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) 14852 #endif // CATCH_CONFIG_DISABLE_MATCHERS 14853 #define CATCH_CHECK_NOTHROW( ... ) (void)(0) 14854 14855 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 14856 #define CATCH_CHECK_THAT( arg, matcher ) (void)(0) 14857 14858 #define CATCH_REQUIRE_THAT( arg, matcher ) (void)(0) 14859 #endif // CATCH_CONFIG_DISABLE_MATCHERS 14860 14861 #define CATCH_INFO( msg ) (void)(0) 14862 #define CATCH_WARN( msg ) (void)(0) 14863 #define CATCH_CAPTURE( msg ) (void)(0) 14864 14865 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 14866 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 14867 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) 14868 #define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0) 14869 #define CATCH_SECTION( ... ) 14870 #define CATCH_DYNAMIC_SECTION( ... ) 14871 #define CATCH_FAIL( ... ) (void)(0) 14872 #define CATCH_FAIL_CHECK( ... ) (void)(0) 14873 #define CATCH_SUCCEED( ... ) (void)(0) 14874 14875 #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 14876 14877 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 14878 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) ) 14879 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className ) 14880 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 14881 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 14882 #else 14883 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) ) ) 14884 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className ) ) 14885 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 14886 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 14887 #endif 14888 14889 // "BDD-style" convenience wrappers 14890 #define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 14891 #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 ) 14892 #define CATCH_GIVEN( desc ) 14893 #define CATCH_AND_GIVEN( desc ) 14894 #define CATCH_WHEN( desc ) 14895 #define CATCH_AND_WHEN( desc ) 14896 #define CATCH_THEN( desc ) 14897 #define CATCH_AND_THEN( desc ) 14898 14899 #define CATCH_STATIC_REQUIRE( ... ) (void)(0) 14900 #define CATCH_STATIC_REQUIRE_FALSE( ... ) (void)(0) 14901 14902 // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required 14903 #else 14904 14905 #define REQUIRE( ... ) (void)(0) 14906 #define REQUIRE_FALSE( ... ) (void)(0) 14907 14908 #define REQUIRE_THROWS( ... ) (void)(0) 14909 #define REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0) 14910 #define REQUIRE_THROWS_WITH( expr, matcher ) (void)(0) 14911 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 14912 #define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) 14913 #endif // CATCH_CONFIG_DISABLE_MATCHERS 14914 #define REQUIRE_NOTHROW( ... ) (void)(0) 14915 14916 #define CHECK( ... ) (void)(0) 14917 #define CHECK_FALSE( ... ) (void)(0) 14918 #define CHECKED_IF( ... ) if (__VA_ARGS__) 14919 #define CHECKED_ELSE( ... ) if (!(__VA_ARGS__)) 14920 #define CHECK_NOFAIL( ... ) (void)(0) 14921 14922 #define CHECK_THROWS( ... ) (void)(0) 14923 #define CHECK_THROWS_AS( expr, exceptionType ) (void)(0) 14924 #define CHECK_THROWS_WITH( expr, matcher ) (void)(0) 14925 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 14926 #define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) 14927 #endif // CATCH_CONFIG_DISABLE_MATCHERS 14928 #define CHECK_NOTHROW( ... ) (void)(0) 14929 14930 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 14931 #define CHECK_THAT( arg, matcher ) (void)(0) 14932 14933 #define REQUIRE_THAT( arg, matcher ) (void)(0) 14934 #endif // CATCH_CONFIG_DISABLE_MATCHERS 14935 14936 #define INFO( msg ) (void)(0) 14937 #define WARN( msg ) (void)(0) 14938 #define CAPTURE( msg ) (void)(0) 14939 14940 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 14941 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 14942 #define METHOD_AS_TEST_CASE( method, ... ) 14943 #define REGISTER_TEST_CASE( Function, ... ) (void)(0) 14944 #define SECTION( ... ) 14945 #define DYNAMIC_SECTION( ... ) 14946 #define FAIL( ... ) (void)(0) 14947 #define FAIL_CHECK( ... ) (void)(0) 14948 #define SUCCEED( ... ) (void)(0) 14949 #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 14950 14951 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 14952 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) ) 14953 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className ) 14954 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ ) 14955 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 14956 #else 14957 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) ) ) 14958 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className ) ) 14959 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ ) 14960 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 14961 #endif 14962 14963 #define STATIC_REQUIRE( ... ) (void)(0) 14964 #define STATIC_REQUIRE_FALSE( ... ) (void)(0) 14965 14966 #endif 14967 14968 #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) 14969 14970 // "BDD-style" convenience wrappers 14971 #define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) ) 14972 #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className ) 14973 14974 #define GIVEN( desc ) 14975 #define AND_GIVEN( desc ) 14976 #define WHEN( desc ) 14977 #define AND_WHEN( desc ) 14978 #define THEN( desc ) 14979 #define AND_THEN( desc ) 14980 14981 using Catch::Detail::Approx; 14982 14983 #endif 14984 14985 #endif // ! CATCH_CONFIG_IMPL_ONLY 14986 14987 // start catch_reenable_warnings.h 14988 14989 14990 #ifdef __clang__ 14991 # ifdef __ICC // icpc defines the __clang__ macro 14992 # pragma warning(pop) 14993 # else 14994 # pragma clang diagnostic pop 14995 # endif 14996 #elif defined __GNUC__ 14997 # pragma GCC diagnostic pop 14998 #endif 14999 15000 // end catch_reenable_warnings.h 15001 // end catch.hpp 15002 #endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED 15003