yum-mirror/UwwwuPP
A rehost of leonetienne's UwwwuPP, a simple text filter to uwu-ify English text.
git clone https://git.yummers.dev/yum-mirror/UwwwuPP
c6ed235
master
1/* 2* Catch v2.13.8 3* Generated: 2022-01-03 21:20:09.589503 4* ---------------------------------------------------------- 5* This file has been merged from multiple headers. Please don't edit it directly 6* Copyright (c) 2022 Two Blue Cubes Ltd. All rights reserved. 7* 8* Distributed under the Boost Software License, Version 1.0. (See accompanying 9* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 10*/ 11#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED 12#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED 13// start catch.hpp 14 15 16#define CATCH_VERSION_MAJOR 2 17#define CATCH_VERSION_MINOR 13 18#define CATCH_VERSION_PATCH 8 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// See e.g.: 70// https://opensource.apple.com/source/CarbonHeaders/CarbonHeaders-18.1/TargetConditionals.h.auto.html 71#ifdef __APPLE__ 72# include <TargetConditionals.h> 73# if (defined(TARGET_OS_OSX )&& TARGET_OS_OSX == 1 )|| \ 74 (defined(TARGET_OS_MAC )&& TARGET_OS_MAC == 1 ) 75# define CATCH_PLATFORM_MAC 76# elif (defined(TARGET_OS_IPHONE )&& TARGET_OS_IPHONE == 1 ) 77# define CATCH_PLATFORM_IPHONE 78# endif 79 80#elif defined(linux )|| defined(__linux )|| defined(__linux__ ) 81# define CATCH_PLATFORM_LINUX 82 83#elif defined(WIN32 )|| defined(__WIN32__ )|| defined(_WIN32 )|| defined(_MSC_VER )|| defined(__MINGW32__ ) 84# define CATCH_PLATFORM_WINDOWS 85#endif 86 87// end catch_platform.h 88 89#ifdef CATCH_IMPL 90# ifndef CLARA_CONFIG_MAIN 91# define CLARA_CONFIG_MAIN_NOT_DEFINED 92# define CLARA_CONFIG_MAIN 93# endif 94#endif 95 96// start catch_user_interfaces.h 97 98namespace Catch { 99unsigned int rngSeed (); 100} 101 102// end catch_user_interfaces.h 103// start catch_tag_alias_autoregistrar.h 104 105// start catch_common.h 106 107// start catch_compiler_capabilities.h 108 109// Detect a number of compiler features - by compiler 110// The following features are defined: 111// 112// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? 113// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported? 114// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported? 115// CATCH_CONFIG_DISABLE_EXCEPTIONS : Are exceptions enabled? 116// **************** 117// Note to maintainers: if new toggles are added please document them 118// in configuration.md, too 119// **************** 120 121// In general each macro has a _NO_<feature name> form 122// (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature. 123// Many features, at point of detection, define an _INTERNAL_ macro, so they 124// can be combined, en-mass, with the _NO_ forms later. 125 126#ifdef __cplusplus 127 128# if (__cplusplus >=201402L )|| (defined(_MSVC_LANG )&& _MSVC_LANG >=201402L ) 129# define CATCH_CPP14_OR_GREATER 130# endif 131 132# if (__cplusplus >=201703L )|| (defined(_MSVC_LANG )&& _MSVC_LANG >=201703L ) 133# define CATCH_CPP17_OR_GREATER 134# endif 135 136#endif 137 138// Only GCC compiler should be used in this block, so other compilers trying to 139// mask themselves as GCC should be ignored. 140#if defined(__GNUC__ )&& !defined(__clang__ )&& !defined(__ICC )&& !defined(__CUDACC__ )&& !defined(__LCC__ ) 141# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" ) 142# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" ) 143 144# define CATCH_INTERNAL_IGNORE_BUT_WARN (...) (void)__builtin_constant_p(__VA_ARGS__) 145 146#endif 147 148#if defined(__clang__ ) 149 150# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" ) 151# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic pop" ) 152 153// As of this writing, IBM XL's implementation of __builtin_constant_p has a bug 154// which results in calls to destructors being emitted for each temporary, 155// without a matching initialization. In practice, this can result in something 156// like `std::string::~string` being called on an uninitialized value. 157// 158// For example, this code will likely segfault under IBM XL: 159// ``` 160// REQUIRE(std::string("12") + "34" == "1234") 161// ``` 162// 163// Therefore, `CATCH_INTERNAL_IGNORE_BUT_WARN` is not implemented. 164# if !defined(__ibmxl__ )&& !defined(__CUDACC__ ) 165# define CATCH_INTERNAL_IGNORE_BUT_WARN (...) (void)__builtin_constant_p(__VA_ARGS__)/* NOLINT(cppcoreguidelines-pro-type-vararg, hicpp-vararg) */ 166# endif 167 168# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 169 _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ 170 _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") 171 172# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ 173 _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) 174 175# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ 176 _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" ) 177 178# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ 179 _Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" ) 180 181# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 182 _Pragma( "clang diagnostic ignored \"-Wunused-template\"" ) 183 184#endif // __clang__ 185 186//////////////////////////////////////////////////////////////////////////////// 187// Assume that non-Windows platforms support posix signals by default 188#if !defined(CATCH_PLATFORM_WINDOWS ) 189#define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS 190#endif 191 192//////////////////////////////////////////////////////////////////////////////// 193// We know some environments not to support full POSIX signals 194#if defined(__CYGWIN__ )|| defined(__QNX__ )|| defined(__EMSCRIPTEN__ )|| defined(__DJGPP__ ) 195#define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS 196#endif 197 198#ifdef __OS400__ 199# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS 200# define CATCH_CONFIG_COLOUR_NONE 201#endif 202 203//////////////////////////////////////////////////////////////////////////////// 204// Android somehow still does not support std::to_string 205#if defined(__ANDROID__ ) 206# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING 207# define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE 208#endif 209 210//////////////////////////////////////////////////////////////////////////////// 211// Not all Windows environments support SEH properly 212#if defined(__MINGW32__ ) 213# define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH 214#endif 215 216//////////////////////////////////////////////////////////////////////////////// 217// PS4 218#if defined(__ORBIS__ ) 219# define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE 220#endif 221 222//////////////////////////////////////////////////////////////////////////////// 223// Cygwin 224#ifdef __CYGWIN__ 225 226// Required for some versions of Cygwin to declare gettimeofday 227// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin 228# define _BSD_SOURCE 229// some versions of cygwin (most) do not support std::to_string. Use the libstd check. 230// https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813 231# if !((__cplusplus >=201103L )&& defined(_GLIBCXX_USE_C99 ) \ 232&& !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF )) 233 234# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING 235 236# endif 237#endif // __CYGWIN__ 238 239//////////////////////////////////////////////////////////////////////////////// 240// Visual C++ 241#if defined(_MSC_VER ) 242 243// Universal Windows platform does not support SEH 244// Or console colours (or console at all...) 245# if defined(WINAPI_FAMILY )&& (WINAPI_FAMILY == WINAPI_FAMILY_APP ) 246# define CATCH_CONFIG_COLOUR_NONE 247# else 248# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH 249# endif 250 251# if !defined(__clang__ )// Handle Clang masquerading for msvc 252 253// MSVC traditional preprocessor needs some workaround for __VA_ARGS__ 254// _MSVC_TRADITIONAL == 0 means new conformant preprocessor 255// _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor 256# if !defined(_MSVC_TRADITIONAL )|| (defined(_MSVC_TRADITIONAL )&& _MSVC_TRADITIONAL ) 257# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 258# endif // MSVC_TRADITIONAL 259 260// Only do this if we're not using clang on Windows, which uses `diagnostic push` & `diagnostic pop` 261# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) ) 262# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) ) 263# endif // __clang__ 264 265#endif // _MSC_VER 266 267#if defined(_REENTRANT )|| defined(_MSC_VER ) 268// Enable async processing, as -pthread is specified or no additional linking is required 269# define CATCH_INTERNAL_CONFIG_USE_ASYNC 270#endif // _MSC_VER 271 272//////////////////////////////////////////////////////////////////////////////// 273// Check if we are compiled with -fno-exceptions or equivalent 274#if defined(__EXCEPTIONS )|| defined(__cpp_exceptions )|| defined(_CPPUNWIND ) 275# define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED 276#endif 277 278//////////////////////////////////////////////////////////////////////////////// 279// DJGPP 280#ifdef __DJGPP__ 281# define CATCH_INTERNAL_CONFIG_NO_WCHAR 282#endif // __DJGPP__ 283 284//////////////////////////////////////////////////////////////////////////////// 285// Embarcadero C++Build 286#if defined(__BORLANDC__ ) 287#define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN 288#endif 289 290//////////////////////////////////////////////////////////////////////////////// 291 292// Use of __COUNTER__ is suppressed during code analysis in 293// CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly 294// handled by it. 295// Otherwise all supported compilers support COUNTER macro, 296// but user still might want to turn it off 297#if ( !defined(__JETBRAINS_IDE__ )|| __JETBRAINS_IDE__ >=20170300L ) 298#define CATCH_INTERNAL_CONFIG_COUNTER 299#endif 300 301//////////////////////////////////////////////////////////////////////////////// 302 303// RTX is a special version of Windows that is real time. 304// This means that it is detected as Windows, but does not provide 305// the same set of capabilities as real Windows does. 306#if defined(UNDER_RTSS )|| defined(RTX64_BUILD ) 307#define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH 308#define CATCH_INTERNAL_CONFIG_NO_ASYNC 309#define CATCH_CONFIG_COLOUR_NONE 310#endif 311 312#if !defined(_GLIBCXX_USE_C99_MATH_TR1 ) 313#define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER 314#endif 315 316// Various stdlib support checks that require __has_include 317#if defined(__has_include ) 318// Check if string_view is available and usable 319#if __has_include (< string_view > )&& defined(CATCH_CPP17_OR_GREATER ) 320# define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW 321#endif 322 323// Check if optional is available and usable 324# if __has_include (< optional > )&& defined(CATCH_CPP17_OR_GREATER ) 325# define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL 326# endif // __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER) 327 328// Check if byte is available and usable 329# if __has_include (< cstddef > )&& defined(CATCH_CPP17_OR_GREATER ) 330# include <cstddef> 331# if defined(__cpp_lib_byte )&& (__cpp_lib_byte > 0 ) 332# define CATCH_INTERNAL_CONFIG_CPP17_BYTE 333# endif 334# endif // __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER) 335 336// Check if variant is available and usable 337# if __has_include (< variant > )&& defined(CATCH_CPP17_OR_GREATER ) 338# if defined(__clang__ )&& (__clang_major__ < 8 ) 339// work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852 340// fix should be in clang 8, workaround in libstdc++ 8.2 341# include <ciso646> 342# if defined(__GLIBCXX__ )&& defined(_GLIBCXX_RELEASE )&& (_GLIBCXX_RELEASE < 9 ) 343# define CATCH_CONFIG_NO_CPP17_VARIANT 344# else 345# define CATCH_INTERNAL_CONFIG_CPP17_VARIANT 346# endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) 347# else 348# define CATCH_INTERNAL_CONFIG_CPP17_VARIANT 349# endif // defined(__clang__) && (__clang_major__ < 8) 350# endif // __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER) 351#endif // defined(__has_include) 352 353#if defined(CATCH_INTERNAL_CONFIG_COUNTER )&& !defined(CATCH_CONFIG_NO_COUNTER )&& !defined(CATCH_CONFIG_COUNTER ) 354# define CATCH_CONFIG_COUNTER 355#endif 356#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH )&& !defined(CATCH_CONFIG_NO_WINDOWS_SEH )&& !defined(CATCH_CONFIG_WINDOWS_SEH )&& !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH ) 357# define CATCH_CONFIG_WINDOWS_SEH 358#endif 359// This is set by default, because we assume that unix compilers are posix-signal-compatible by default. 360#if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS )&& !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS )&& !defined(CATCH_CONFIG_NO_POSIX_SIGNALS )&& !defined(CATCH_CONFIG_POSIX_SIGNALS ) 361# define CATCH_CONFIG_POSIX_SIGNALS 362#endif 363// This is set by default, because we assume that compilers with no wchar_t support are just rare exceptions. 364#if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR )&& !defined(CATCH_CONFIG_NO_WCHAR )&& !defined(CATCH_CONFIG_WCHAR ) 365# define CATCH_CONFIG_WCHAR 366#endif 367 368#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING )&& !defined(CATCH_CONFIG_NO_CPP11_TO_STRING )&& !defined(CATCH_CONFIG_CPP11_TO_STRING ) 369# define CATCH_CONFIG_CPP11_TO_STRING 370#endif 371 372#if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL )&& !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL )&& !defined(CATCH_CONFIG_CPP17_OPTIONAL ) 373# define CATCH_CONFIG_CPP17_OPTIONAL 374#endif 375 376#if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW )&& !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW )&& !defined(CATCH_CONFIG_CPP17_STRING_VIEW ) 377# define CATCH_CONFIG_CPP17_STRING_VIEW 378#endif 379 380#if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT )&& !defined(CATCH_CONFIG_NO_CPP17_VARIANT )&& !defined(CATCH_CONFIG_CPP17_VARIANT ) 381# define CATCH_CONFIG_CPP17_VARIANT 382#endif 383 384#if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE )&& !defined(CATCH_CONFIG_NO_CPP17_BYTE )&& !defined(CATCH_CONFIG_CPP17_BYTE ) 385# define CATCH_CONFIG_CPP17_BYTE 386#endif 387 388#if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT ) 389# define CATCH_INTERNAL_CONFIG_NEW_CAPTURE 390#endif 391 392#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 ) 393# define CATCH_CONFIG_NEW_CAPTURE 394#endif 395 396#if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED )&& !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS ) 397# define CATCH_CONFIG_DISABLE_EXCEPTIONS 398#endif 399 400#if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN )&& !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN )&& !defined(CATCH_CONFIG_POLYFILL_ISNAN ) 401# define CATCH_CONFIG_POLYFILL_ISNAN 402#endif 403 404#if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC )&& !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC )&& !defined(CATCH_CONFIG_NO_USE_ASYNC )&& !defined(CATCH_CONFIG_USE_ASYNC ) 405# define CATCH_CONFIG_USE_ASYNC 406#endif 407 408#if defined(CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE )&& !defined(CATCH_CONFIG_NO_ANDROID_LOGWRITE )&& !defined(CATCH_CONFIG_ANDROID_LOGWRITE ) 409# define CATCH_CONFIG_ANDROID_LOGWRITE 410#endif 411 412#if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER )&& !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER )&& !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER ) 413# define CATCH_CONFIG_GLOBAL_NEXTAFTER 414#endif 415 416// Even if we do not think the compiler has that warning, we still have 417// to provide a macro that can be used by the code. 418#if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION ) 419# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION 420#endif 421#if !defined(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION ) 422# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 423#endif 424#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS ) 425# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS 426#endif 427#if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS ) 428# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS 429#endif 430#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS ) 431# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS 432#endif 433#if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS ) 434# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS 435#endif 436 437// The goal of this macro is to avoid evaluation of the arguments, but 438// still have the compiler warn on problems inside... 439#if !defined(CATCH_INTERNAL_IGNORE_BUT_WARN ) 440# define CATCH_INTERNAL_IGNORE_BUT_WARN (...) 441#endif 442 443#if defined(__APPLE__ )&& defined(__apple_build_version__ )&& (__clang_major__ < 10 ) 444# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS 445#elif defined(__clang__ )&& (__clang_major__ < 5 ) 446# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS 447#endif 448 449#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS ) 450# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS 451#endif 452 453#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS ) 454#define CATCH_TRY if ((true)) 455#define CATCH_CATCH_ALL if ((false)) 456#define CATCH_CATCH_ANON (type ) if ((false)) 457#else 458#define CATCH_TRY try 459#define CATCH_CATCH_ALL catch (...) 460#define CATCH_CATCH_ANON (type ) catch (type) 461#endif 462 463#if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR )&& !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR )&& !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR ) 464#define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 465#endif 466 467// end catch_compiler_capabilities.h 468#define INTERNAL_CATCH_UNIQUE_NAME_LINE2 (name ,line ) name##line 469#define INTERNAL_CATCH_UNIQUE_NAME_LINE (name ,line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) 470#ifdef CATCH_CONFIG_COUNTER 471# define INTERNAL_CATCH_UNIQUE_NAME (name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) 472#else 473# define INTERNAL_CATCH_UNIQUE_NAME (name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) 474#endif 475 476#include <iosfwd> 477#include <string> 478#include <cstdint> 479 480// We need a dummy global operator<< so we can bring it into Catch namespace later 481struct Catch_global_namespace_dummy {}; 482std ::ostream & operator <<(std ::ostream & ,Catch_global_namespace_dummy ); 483 484namespace Catch { 485 486struct CaseSensitive {enum Choice { 487Yes , 488No 489}; }; 490 491class NonCopyable { 492NonCopyable (NonCopyable const & )= delete ; 493NonCopyable (NonCopyable && ) = delete; 494NonCopyable & operator = ( NonCopyable const & ) = delete; 495NonCopyable & operator = ( NonCopyable && ) = delete; 496 497protected : 498NonCopyable (); 499virtual ~ NonCopyable (); 500}; 501 502struct SourceLineInfo { 503 504SourceLineInfo() = delete ; 505SourceLineInfo ( char const * _file, std :: size_t _line ) noexcept 506: file ( _file ), 507line ( _line ) 508{} 509 510SourceLineInfo ( SourceLineInfo const & other ) = default ; 511SourceLineInfo & operator = ( SourceLineInfo const & ) = default ; 512SourceLineInfo( SourceLineInfo && ) noexcept = default ; 513SourceLineInfo & operator = ( SourceLineInfo && ) noexcept = default ; 514 515bool empty () const noexcept { return file [ 0 ] == '\0' ; } 516bool operator == ( SourceLineInfo const & other ) const noexcept; 517bool operator < ( SourceLineInfo const & other ) const noexcept; 518 519char const * file; 520std :: size_t line; 521}; 522 523std ::ostream & operator << ( std::ostream & os, SourceLineInfo const & info ); 524 525// Bring in operator<< from global namespace into Catch namespace 526// This is necessary because the overload of operator<< above makes 527// lookup stop at namespace Catch 528using ::operator<<; 529 530// Use this in variadic streaming macros to allow 531// >> +StreamEndStop 532// as well as 533// >> stuff +StreamEndStop 534struct StreamEndStop { 535std :: string operator + () const ; 536}; 537template < typename T > 538T const & operator + ( T const & value, StreamEndStop ) { 539return value; 540} 541} 542 543#define CATCH_INTERNAL_LINEINFO \ 544::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) ) 545 546// end catch_common.h 547namespace Catch { 548 549struct RegistrarForTagAliases { 550RegistrarForTagAliases( char const * alias , char const * tag , SourceLineInfo const & lineInfo ); 551}; 552 553} // end namespace Catch 554 555#define CATCH_REGISTER_TAG_ALIAS ( alias, spec ) \ 556CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 557CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 558namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \ 559CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 560 561// end catch_tag_alias_autoregistrar.h 562// start catch_test_registry.h 563 564// start catch_interfaces_testcase.h 565 566#include <vector> 567 568namespace Catch { 569 570class TestSpec; 571 572struct ITestInvoker { 573virtual void invoke () const = 0 ; 574virtual ~ ITestInvoker (); 575}; 576 577class TestCase; 578struct IConfig ; 579 580struct ITestCaseRegistry { 581virtual ~ ITestCaseRegistry (); 582virtual std ::vector < TestCase > const & getAllTests () const = 0 ; 583virtual std ::vector < TestCase > const & getAllTestsSorted ( IConfig const & config ) const = 0 ; 584}; 585 586bool isThrowSafe ( TestCase const & testCase, IConfig const & config ); 587bool matchTest ( TestCase const & testCase, TestSpec const & testSpec, IConfig const & config ); 588std ::vector < TestCase > filterTests ( std::vector < TestCase > const & testCases, TestSpec const & testSpec, IConfig const & config ); 589std ::vector < TestCase > const & getAllTestCasesSorted ( IConfig const & config ); 590 591} 592 593// end catch_interfaces_testcase.h 594// start catch_stringref.h 595 596#include <cstddef> 597#include <string> 598#include <iosfwd> 599#include <cassert> 600 601namespace Catch { 602 603/// A non-owning string class (similar to the forthcoming std::string_view) 604/// Note that, because a StringRef may be a substring of another string, 605/// it may not be null terminated. 606class StringRef { 607public : 608using size_type = std:: size_t ; 609using const_iterator = const char * ; 610 611private : 612static constexpr char const * const s_empty = "" ; 613 614char const * m_start = s_empty; 615size_type m_size = 0 ; 616 617public : // construction 618constexpr StringRef( ) noexcept = default ; 619 620StringRef ( char const * rawChars ) noexcept ; 621 622constexpr StringRef ( char const * rawChars , size_type size ) noexcept 623: m_start ( rawChars ), 624m_size ( size ) 625{} 626 627StringRef ( std:: string const & stdString ) noexcept 628: m_start ( stdString . c_str () ), 629m_size ( stdString. size () ) 630{} 631 632explicit operator std :: string () const { 633return std :: string (m_start, m_size); 634} 635 636public : // operators 637auto operator == ( StringRef const & other ) const noexcept -> bool; 638auto operator != (StringRef const & other ) const noexcept -> bool { 639return !( * this == other ); 640} 641 642auto operator [] ( size_type index ) const noexcept -> char { 643assert (index < m_size); 644return m_start[index]; 645} 646 647public : // named queries 648constexpr auto empty() const noexcept -> bool { 649return m_size == 0 ; 650} 651constexpr auto size() const noexcept -> size_type { 652return m_size; 653} 654 655// Returns the current start pointer. If the StringRef is not 656// null-terminated, throws std::domain_exception 657auto c_str () const -> char const * ; 658 659public : // substrings and searches 660// Returns a substring of [start, start + length). 661// If start + length > size(), then the substring is [start, size()). 662// If start > size(), then the substring is empty. 663auto substr ( size_type start, size_type length ) const noexcept -> StringRef; 664 665// Returns the current start pointer. May not be null-terminated. 666auto data () const noexcept -> char const * ; 667 668constexpr auto isNullTerminated() const noexcept -> bool { 669return m_start[m_size] == '\0' ; 670} 671 672public : // iterators 673constexpr const_iterator begin () const { return m_start; } 674constexpr const_iterator end () const { return m_start + m_size; } 675}; 676 677auto operator += ( std :: string & lhs, StringRef const & sr ) -> std::string & ; 678auto operator << ( std :: ostream & os, StringRef const & sr ) -> std::ostream & ; 679 680constexpr auto operator "" _sr( char const * rawChars, std:: size_t size ) noexcept -> StringRef { 681return StringRef ( rawChars, size ); 682} 683} // namespace Catch 684 685constexpr auto operator "" _catch_sr( char const * rawChars, std:: size_t size ) noexcept -> Catch::StringRef { 686return Catch:: StringRef ( rawChars, size ); 687} 688 689// end catch_stringref.h 690// start catch_preprocessor.hpp 691 692 693#define CATCH_RECURSION_LEVEL0 (...) __VA_ARGS__ 694#define CATCH_RECURSION_LEVEL1 (...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__))) 695#define CATCH_RECURSION_LEVEL2 (...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__))) 696#define CATCH_RECURSION_LEVEL3 (...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__))) 697#define CATCH_RECURSION_LEVEL4 (...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__))) 698#define CATCH_RECURSION_LEVEL5 (...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__))) 699 700#ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 701#define INTERNAL_CATCH_EXPAND_VARGS (...) __VA_ARGS__ 702// MSVC needs more evaluations 703#define CATCH_RECURSION_LEVEL6 (...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__))) 704#define CATCH_RECURSE (...) CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__)) 705#else 706#define CATCH_RECURSE (...) CATCH_RECURSION_LEVEL5(__VA_ARGS__) 707#endif 708 709#define CATCH_REC_END (...) 710#define CATCH_REC_OUT 711 712#define CATCH_EMPTY () 713#define CATCH_DEFER (id) id CATCH_EMPTY() 714 715#define CATCH_REC_GET_END2 () 0, CATCH_REC_END 716#define CATCH_REC_GET_END1 (...) CATCH_REC_GET_END2 717#define CATCH_REC_GET_END (...) CATCH_REC_GET_END1 718#define CATCH_REC_NEXT0 (test, next, ...) next CATCH_REC_OUT 719#define CATCH_REC_NEXT1 (test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0) 720#define CATCH_REC_NEXT (test, next) CATCH_REC_NEXT1(CATCH_REC_GET_END test, next) 721 722#define CATCH_REC_LIST0 (f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) 723#define CATCH_REC_LIST1 (f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ ) 724#define CATCH_REC_LIST2 (f, x, peek, ...) f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) 725 726#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__ ) 727#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__ ) 728#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__ ) 729 730// Applies the function macro `f` to each of the remaining parameters, inserts commas between the results, 731// and passes userdata as the first parameter to each invocation, 732// e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c) 733#define CATCH_REC_LIST_UD (f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) 734 735#define CATCH_REC_LIST (f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) 736 737#define INTERNAL_CATCH_EXPAND1 (param) INTERNAL_CATCH_EXPAND2(param) 738#define INTERNAL_CATCH_EXPAND2 (...) INTERNAL_CATCH_NO## __VA_ARGS__ 739#define INTERNAL_CATCH_DEF (...) INTERNAL_CATCH_DEF __VA_ARGS__ 740#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF 741#define INTERNAL_CATCH_STRINGIZE (...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__) 742#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 743#define INTERNAL_CATCH_STRINGIZE2 (...) #__VA_ARGS__ 744#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS (param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) 745#else 746// MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF 747#define INTERNAL_CATCH_STRINGIZE2 (...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__) 748#define INTERNAL_CATCH_STRINGIZE3 (...) #__VA_ARGS__ 749#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS (param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1) 750#endif 751 752#define INTERNAL_CATCH_MAKE_NAMESPACE2 (...) ns_##__VA_ARGS__ 753#define INTERNAL_CATCH_MAKE_NAMESPACE (name) INTERNAL_CATCH_MAKE_NAMESPACE2(name) 754 755#define INTERNAL_CATCH_REMOVE_PARENS (...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__) 756 757#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 758#define INTERNAL_CATCH_MAKE_TYPE_LIST2 (...) decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS_GEN(__VA_ARGS__)>()) 759#define INTERNAL_CATCH_MAKE_TYPE_LIST (...) INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)) 760#else 761#define INTERNAL_CATCH_MAKE_TYPE_LIST2 (...) INTERNAL_CATCH_EXPAND_VARGS(decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS_GEN(__VA_ARGS__)>())) 762#define INTERNAL_CATCH_MAKE_TYPE_LIST (...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))) 763#endif 764 765#define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES (...)\ 766CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,__VA_ARGS__) 767 768#define INTERNAL_CATCH_REMOVE_PARENS_1_ARG (_0) INTERNAL_CATCH_REMOVE_PARENS(_0) 769#define INTERNAL_CATCH_REMOVE_PARENS_2_ARG (_0, _1) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_1) 770#define INTERNAL_CATCH_REMOVE_PARENS_3_ARG (_0, _1, _2) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_1, _2) 771#define INTERNAL_CATCH_REMOVE_PARENS_4_ARG (_0, _1, _2, _3) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_1, _2, _3) 772#define INTERNAL_CATCH_REMOVE_PARENS_5_ARG (_0, _1, _2, _3, _4) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_1, _2, _3, _4) 773#define INTERNAL_CATCH_REMOVE_PARENS_6_ARG (_0, _1, _2, _3, _4, _5) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_1, _2, _3, _4, _5) 774#define INTERNAL_CATCH_REMOVE_PARENS_7_ARG (_0, _1, _2, _3, _4, _5, _6) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_1, _2, _3, _4, _5, _6) 775#define INTERNAL_CATCH_REMOVE_PARENS_8_ARG (_0, _1, _2, _3, _4, _5, _6, _7) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_1, _2, _3, _4, _5, _6, _7) 776#define INTERNAL_CATCH_REMOVE_PARENS_9_ARG (_0, _1, _2, _3, _4, _5, _6, _7, _8) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_1, _2, _3, _4, _5, _6, _7, _8) 777#define INTERNAL_CATCH_REMOVE_PARENS_10_ARG (_0, _1, _2, _3, _4, _5, _6, _7, _8, _9) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9) 778#define INTERNAL_CATCH_REMOVE_PARENS_11_ARG (_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10) 779 780#define INTERNAL_CATCH_VA_NARGS_IMPL (_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N , ...) N 781 782#define INTERNAL_CATCH_TYPE_GEN \ 783template<typename...> struct TypeList {};\ 784template<typename...Ts>\ 785constexpr auto get_wrapper() noexcept -> TypeList<Ts...> { return {}; }\ 786template<template<typename...> class...> struct TemplateTypeList{};\ 787template<template<typename...> class...Cs>\ 788constexpr auto get_wrapper() noexcept -> TemplateTypeList<Cs...> { return {}; }\ 789template<typename...>\ 790struct append;\ 791template<typename...>\ 792struct rewrap;\ 793template<template<typename...> class, typename...>\ 794struct create;\ 795template<template<typename...> class, typename>\ 796struct convert;\ 797\ 798template<typename T> \ 799struct append<T> { using type = T; };\ 800template< template<typename...> class L1, typename...E1, template<typename...> class L2, typename...E2, typename...Rest>\ 801struct append<L1<E1...>, L2<E2...>, Rest...> { using type = typename append<L1<E1...,E2...>, Rest...>::type; };\ 802template< template<typename...> class L1, typename...E1, typename...Rest>\ 803struct append<L1<E1...>, TypeList<mpl_::na>, Rest...> { using type = L1<E1...>; };\ 804\ 805template< template<typename...> class Container, template<typename...> class List, typename...elems>\ 806struct rewrap<TemplateTypeList<Container>, List<elems...>> { using type = TypeList<Container<elems...>>; };\ 807template< template<typename...> class Container, template<typename...> class List, class...Elems, typename...Elements>\ 808struct rewrap<TemplateTypeList<Container>, List<Elems...>, Elements...> { using type = typename append<TypeList<Container<Elems...>>, typename rewrap<TemplateTypeList<Container>, Elements...>::type>::type; };\ 809\ 810template<template <typename...> class Final, template< typename...> class...Containers, typename...Types>\ 811struct create<Final, TemplateTypeList<Containers...>, TypeList<Types...>> { using type = typename append<Final<>, typename rewrap<TemplateTypeList<Containers>, Types...>::type...>::type; };\ 812template<template <typename...> class Final, template <typename...> class List, typename...Ts>\ 813struct convert<Final, List<Ts...>> { using type = typename append<Final<>,TypeList<Ts>...>::type; }; 814 815#define INTERNAL_CATCH_NTTP_1 (signature, ...)\ 816template<INTERNAL_CATCH_REMOVE_PARENS(signature)> struct Nttp{};\ 817template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 818constexpr auto get_wrapper() noexcept -> Nttp<__VA_ARGS__> { return {}; } \ 819template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...> struct NttpTemplateTypeList{};\ 820template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...Cs>\ 821constexpr auto get_wrapper() noexcept -> NttpTemplateTypeList<Cs...> { return {}; } \ 822\ 823template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 824struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>> { using type = TypeList<Container<__VA_ARGS__>>; };\ 825template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature), typename...Elements>\ 826struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>, Elements...> { using type = typename append<TypeList<Container<__VA_ARGS__>>, typename rewrap<NttpTemplateTypeList<Container>, Elements...>::type>::type; };\ 827template<template <typename...> class Final, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...Containers, typename...Types>\ 828struct create<Final, NttpTemplateTypeList<Containers...>, TypeList<Types...>> { using type = typename append<Final<>, typename rewrap<NttpTemplateTypeList<Containers>, Types...>::type...>::type; }; 829 830#define INTERNAL_CATCH_DECLARE_SIG_TEST0 (TestName) 831#define INTERNAL_CATCH_DECLARE_SIG_TEST1 (TestName, signature)\ 832template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 833static void TestName() 834#define INTERNAL_CATCH_DECLARE_SIG_TEST_X (TestName, signature, ...)\ 835template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 836static void TestName() 837 838#define INTERNAL_CATCH_DEFINE_SIG_TEST0 (TestName) 839#define INTERNAL_CATCH_DEFINE_SIG_TEST1 (TestName, signature)\ 840template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 841static void TestName() 842#define INTERNAL_CATCH_DEFINE_SIG_TEST_X (TestName, signature,...)\ 843template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 844static void TestName() 845 846#define INTERNAL_CATCH_NTTP_REGISTER0 (TestFunc, signature)\ 847template<typename Type>\ 848void reg_test(TypeList<Type>, Catch::NameAndTags nameAndTags)\ 849{\ 850Catch::AutoReg( Catch::makeTestInvoker(&TestFunc<Type>), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), nameAndTags);\ 851} 852 853#define INTERNAL_CATCH_NTTP_REGISTER (TestFunc, signature, ...)\ 854template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 855void reg_test(Nttp<__VA_ARGS__>, Catch::NameAndTags nameAndTags)\ 856{\ 857Catch::AutoReg( Catch::makeTestInvoker(&TestFunc<__VA_ARGS__>), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), nameAndTags);\ 858} 859 860#define INTERNAL_CATCH_NTTP_REGISTER_METHOD0 (TestName, signature, ...)\ 861template<typename Type>\ 862void reg_test(TypeList<Type>, Catch::StringRef className, Catch::NameAndTags nameAndTags)\ 863{\ 864Catch::AutoReg( Catch::makeTestInvoker(&TestName<Type>::test), CATCH_INTERNAL_LINEINFO, className, nameAndTags);\ 865} 866 867#define INTERNAL_CATCH_NTTP_REGISTER_METHOD (TestName, signature, ...)\ 868template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 869void reg_test(Nttp<__VA_ARGS__>, Catch::StringRef className, Catch::NameAndTags nameAndTags)\ 870{\ 871Catch::AutoReg( Catch::makeTestInvoker(&TestName<__VA_ARGS__>::test), CATCH_INTERNAL_LINEINFO, className, nameAndTags);\ 872} 873 874#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0 (TestName, ClassName) 875#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1 (TestName, ClassName, signature)\ 876template<typename TestType> \ 877struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName)<TestType> { \ 878void test();\ 879} 880 881#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X (TestName, ClassName, signature, ...)\ 882template<INTERNAL_CATCH_REMOVE_PARENS(signature)> \ 883struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName)<__VA_ARGS__> { \ 884void test();\ 885} 886 887#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0 (TestName) 888#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1 (TestName, signature)\ 889template<typename TestType> \ 890void INTERNAL_CATCH_MAKE_NAMESPACE(TestName)::TestName<TestType>::test() 891#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X (TestName, signature, ...)\ 892template<INTERNAL_CATCH_REMOVE_PARENS(signature)> \ 893void INTERNAL_CATCH_MAKE_NAMESPACE(TestName)::TestName<__VA_ARGS__>::test() 894 895#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 896#define INTERNAL_CATCH_NTTP_0 897#define INTERNAL_CATCH_NTTP_GEN (...) INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1( __VA_ARGS__), INTERNAL_CATCH_NTTP_1( __VA_ARGS__), INTERNAL_CATCH_NTTP_1( __VA_ARGS__), INTERNAL_CATCH_NTTP_1( __VA_ARGS__),INTERNAL_CATCH_NTTP_1( __VA_ARGS__), INTERNAL_CATCH_NTTP_0) 898#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD (TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0)(TestName, __VA_ARGS__) 899#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD (TestName, ClassName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0)(TestName, ClassName, __VA_ARGS__) 900#define INTERNAL_CATCH_NTTP_REG_METHOD_GEN (TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD0, INTERNAL_CATCH_NTTP_REGISTER_METHOD0)(TestName, __VA_ARGS__) 901#define INTERNAL_CATCH_NTTP_REG_GEN (TestFunc, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER0, INTERNAL_CATCH_NTTP_REGISTER0)(TestFunc, __VA_ARGS__) 902#define INTERNAL_CATCH_DEFINE_SIG_TEST (TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST1, INTERNAL_CATCH_DEFINE_SIG_TEST0)(TestName, __VA_ARGS__) 903#define INTERNAL_CATCH_DECLARE_SIG_TEST (TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST1, INTERNAL_CATCH_DECLARE_SIG_TEST0)(TestName, __VA_ARGS__) 904#define INTERNAL_CATCH_REMOVE_PARENS_GEN (...) INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_REMOVE_PARENS_11_ARG,INTERNAL_CATCH_REMOVE_PARENS_10_ARG,INTERNAL_CATCH_REMOVE_PARENS_9_ARG,INTERNAL_CATCH_REMOVE_PARENS_8_ARG,INTERNAL_CATCH_REMOVE_PARENS_7_ARG,INTERNAL_CATCH_REMOVE_PARENS_6_ARG,INTERNAL_CATCH_REMOVE_PARENS_5_ARG,INTERNAL_CATCH_REMOVE_PARENS_4_ARG,INTERNAL_CATCH_REMOVE_PARENS_3_ARG,INTERNAL_CATCH_REMOVE_PARENS_2_ARG,INTERNAL_CATCH_REMOVE_PARENS_1_ARG)(__VA_ARGS__) 905#else 906#define INTERNAL_CATCH_NTTP_0 (signature) 907#define INTERNAL_CATCH_NTTP_GEN (...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1,INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_0)( __VA_ARGS__)) 908#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD (TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0)(TestName, __VA_ARGS__)) 909#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD (TestName, ClassName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0)(TestName, ClassName, __VA_ARGS__)) 910#define INTERNAL_CATCH_NTTP_REG_METHOD_GEN (TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD0, INTERNAL_CATCH_NTTP_REGISTER_METHOD0)(TestName, __VA_ARGS__)) 911#define INTERNAL_CATCH_NTTP_REG_GEN (TestFunc, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER0, INTERNAL_CATCH_NTTP_REGISTER0)(TestFunc, __VA_ARGS__)) 912#define INTERNAL_CATCH_DEFINE_SIG_TEST (TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST1, INTERNAL_CATCH_DEFINE_SIG_TEST0)(TestName, __VA_ARGS__)) 913#define INTERNAL_CATCH_DECLARE_SIG_TEST (TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST1, INTERNAL_CATCH_DECLARE_SIG_TEST0)(TestName, __VA_ARGS__)) 914#define INTERNAL_CATCH_REMOVE_PARENS_GEN (...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_REMOVE_PARENS_11_ARG,INTERNAL_CATCH_REMOVE_PARENS_10_ARG,INTERNAL_CATCH_REMOVE_PARENS_9_ARG,INTERNAL_CATCH_REMOVE_PARENS_8_ARG,INTERNAL_CATCH_REMOVE_PARENS_7_ARG,INTERNAL_CATCH_REMOVE_PARENS_6_ARG,INTERNAL_CATCH_REMOVE_PARENS_5_ARG,INTERNAL_CATCH_REMOVE_PARENS_4_ARG,INTERNAL_CATCH_REMOVE_PARENS_3_ARG,INTERNAL_CATCH_REMOVE_PARENS_2_ARG,INTERNAL_CATCH_REMOVE_PARENS_1_ARG)(__VA_ARGS__)) 915#endif 916 917// end catch_preprocessor.hpp 918// start catch_meta.hpp 919 920 921#include <type_traits> 922 923namespace Catch { 924template < typename T > 925struct always_false : std ::false_type {}; 926 927template < typename > struct true_given : std ::true_type {}; 928struct is_callable_tester { 929template < typename Fun , typename ... Args > 930true_given < decltype ( std ::declval < Fun > ()(std::declval < Args > ()...)) > static test (int); 931template < typename ... > 932std ::false_type static test (...); 933}; 934 935template < typename T > 936struct is_callable; 937 938template < typename Fun, typename... Args > 939struct is_callable < Fun (Args...) > : decltype (is_callable_tester::test < Fun, Args... > ( 0 )) {}; 940 941#if defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703 942// std::result_of is deprecated in C++17 and removed in C++20. Hence, it is 943// replaced with std::invoke_result here. 944template < typename Func, typename... U > 945using FunctionReturnType = std::remove_reference_t < std::remove_cv_t < std::invoke_result_t < Func, U ...>> > ; 946#else 947// Keep ::type here because we still support C++11 948template < typename Func, typename... U > 949using FunctionReturnType = typename std ::remove_reference < typename std ::remove_cv < typename std ::result_of < Func ( U ...) > ::type > ::type > ::type; 950#endif 951 952} // namespace Catch 953 954namespace mpl_{ 955struct na ; 956} 957 958// end catch_meta.hpp 959namespace Catch { 960 961template < typename C > 962class TestInvokerAsMethod : public ITestInvoker { 963void ( C :: * m_testAsMethod)(); 964public : 965TestInvokerAsMethod( void ( C :: * testAsMethod)() ) noexcept : m_testAsMethod ( testAsMethod ) {} 966 967void invoke () const override { 968C obj; 969(obj. * m_testAsMethod )(); 970} 971}; 972 973auto makeTestInvoker( void ( * testAsFunction )() ) noexcept -> ITestInvoker * ; 974 975template < typename C > 976auto makeTestInvoker ( void ( C :: * testAsMethod)() ) noexcept -> ITestInvoker * { 977return new (std::nothrow) TestInvokerAsMethod < C > ( testAsMethod ); 978} 979 980struct NameAndTags { 981NameAndTags( StringRef const & name_ = StringRef (), StringRef const & tags_ = StringRef() ) noexcept ; 982StringRef name ; 983StringRef tags ; 984}; 985 986struct AutoReg : NonCopyable { 987AutoReg ( ITestInvoker * invoker, SourceLineInfo const & lineInfo, StringRef const & classOrMethod, NameAndTags const & nameAndTags ) noexcept; 988~ AutoReg (); 989}; 990 991} // end namespace Catch 992 993#if defined( CATCH_CONFIG_DISABLE ) 994#define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION ( TestName, ... ) \ 995static void TestName() 996#define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION ( TestName, ClassName, ... ) \ 997namespace{ \ 998struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \ 999void test(); \ 1000}; \ 1001} \ 1002void TestName::test() 1003#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2 ( TestName, TestFunc, Name, Tags, Signature, ... ) \ 1004INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature)) 1005#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2 ( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \ 1006namespace{ \ 1007namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) { \ 1008INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, INTERNAL_CATCH_REMOVE_PARENS(Signature));\ 1009} \ 1010} \ 1011INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature)) 1012 1013#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1014#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION (Name, Tags, ...) \ 1015INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename TestType, __VA_ARGS__ ) 1016#else 1017#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION (Name, Tags, ...) \ 1018INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename TestType, __VA_ARGS__ ) ) 1019#endif 1020 1021#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1022#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION (Name, Tags, Signature, ...) \ 1023INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ ) 1024#else 1025#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION (Name, Tags, Signature, ...) \ 1026INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ ) ) 1027#endif 1028 1029#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1030#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION ( ClassName, Name, Tags,... ) \ 1031INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) 1032#else 1033#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION ( ClassName, Name, Tags,... ) \ 1034INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) ) 1035#endif 1036 1037#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1038#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION ( ClassName, Name, Tags, Signature, ... ) \ 1039INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) 1040#else 1041#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION ( ClassName, Name, Tags, Signature, ... ) \ 1042INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) ) 1043#endif 1044#endif 1045 1046/////////////////////////////////////////////////////////////////////////////// 1047#define INTERNAL_CATCH_TESTCASE2 ( TestName, ... ) \ 1048static void TestName(); \ 1049CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1050CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1051namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \ 1052CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1053static void TestName() 1054#define INTERNAL_CATCH_TESTCASE ( ... ) \ 1055INTERNAL_CATCH_TESTCASE2 ( INTERNAL_CATCH_UNIQUE_NAME ( C_A_T_C_H_T_E_S_T_ ), __VA_ARGS__ ) 1056 1057/////////////////////////////////////////////////////////////////////////////// 1058#define INTERNAL_CATCH_METHOD_AS_TEST_CASE ( QualifiedMethod, ... ) \ 1059CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1060CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1061namespace{ Catch :: AutoReg INTERNAL_CATCH_UNIQUE_NAME ( autoRegistrar )( Catch :: makeTestInvoker ( & QualifiedMethod ), CATCH_INTERNAL_LINEINFO , "&" #QualifiedMethod , Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \ 1062CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 1063 1064/////////////////////////////////////////////////////////////////////////////// 1065#define INTERNAL_CATCH_TEST_CASE_METHOD2 ( TestName, ClassName, ... )\ 1066CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1067CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1068namespace{ \ 1069struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \ 1070void test(); \ 1071}; \ 1072Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ 1073} \ 1074CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1075void TestName :: test () 1076#define INTERNAL_CATCH_TEST_CASE_METHOD ( ClassName, ... ) \ 1077INTERNAL_CATCH_TEST_CASE_METHOD2 ( INTERNAL_CATCH_UNIQUE_NAME ( C_A_T_C_H_T_E_S_T_ ), ClassName, __VA_ARGS__ ) 1078 1079/////////////////////////////////////////////////////////////////////////////// 1080#define INTERNAL_CATCH_REGISTER_TESTCASE ( Function, ... ) \ 1081CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1082CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1083Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME ( autoRegistrar )( Catch:: makeTestInvoker ( Function ), CATCH_INTERNAL_LINEINFO , Catch:: StringRef (), Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ 1084CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 1085 1086/////////////////////////////////////////////////////////////////////////////// 1087#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_2 (TestName, TestFunc, Name, Tags, Signature, ... )\ 1088CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1089CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1090CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ 1091CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 1092INTERNAL_CATCH_DECLARE_SIG_TEST (TestFunc, INTERNAL_CATCH_REMOVE_PARENS (Signature));\ 1093namespace {\ 1094namespace INTERNAL_CATCH_MAKE_NAMESPACE ( TestName ){\ 1095INTERNAL_CATCH_TYPE_GEN \ 1096INTERNAL_CATCH_NTTP_GEN ( INTERNAL_CATCH_REMOVE_PARENS ( Signature ))\ 1097INTERNAL_CATCH_NTTP_REG_GEN (TestFunc, INTERNAL_CATCH_REMOVE_PARENS (Signature))\ 1098template < typename...Types > \ 1099struct TestName{\ 1100TestName (){\ 1101int index = 0 ; \ 1102constexpr char const * tmpl_types[] = { CATCH_REC_LIST ( INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS , __VA_ARGS__)};\ 1103using expander = int[];\ 1104( void )expander{(reg_test(Types{}, Catch::NameAndTags{ Name " - " + std:: string (tmpl_types[index]), Tags } ), index ++ )... }; /* NOLINT */ \ 1105}\ 1106};\ 1107static int INTERNAL_CATCH_UNIQUE_NAME ( globalRegistrar ) = [](){\ 1108TestName < INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES (__VA_ARGS__) > ();\ 1109return 0 ;\ 1110}();\ 1111}\ 1112}\ 1113CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1114INTERNAL_CATCH_DEFINE_SIG_TEST (TestFunc, INTERNAL_CATCH_REMOVE_PARENS (Signature)) 1115 1116#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1117#define INTERNAL_CATCH_TEMPLATE_TEST_CASE (Name, Tags, ...) \ 1118INTERNAL_CATCH_TEMPLATE_TEST_CASE_2 ( INTERNAL_CATCH_UNIQUE_NAME ( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME ( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename TestType, __VA_ARGS__ ) 1119#else 1120#define INTERNAL_CATCH_TEMPLATE_TEST_CASE (Name, Tags, ...) \ 1121INTERNAL_CATCH_EXPAND_VARGS ( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2 ( INTERNAL_CATCH_UNIQUE_NAME ( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME ( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename TestType, __VA_ARGS__ ) ) 1122#endif 1123 1124#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1125#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG (Name, Tags, Signature, ...) \ 1126INTERNAL_CATCH_TEMPLATE_TEST_CASE_2 ( INTERNAL_CATCH_UNIQUE_NAME ( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME ( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ ) 1127#else 1128#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG (Name, Tags, Signature, ...) \ 1129INTERNAL_CATCH_EXPAND_VARGS ( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2 ( INTERNAL_CATCH_UNIQUE_NAME ( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME ( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ ) ) 1130#endif 1131 1132#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2 (TestName, TestFuncName, Name, Tags, Signature, TmplTypes, TypesList) \ 1133CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1134CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1135CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ 1136CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 1137template < typename TestType > static void TestFuncName (); \ 1138namespace {\ 1139namespace INTERNAL_CATCH_MAKE_NAMESPACE ( TestName ) { \ 1140INTERNAL_CATCH_TYPE_GEN \ 1141INTERNAL_CATCH_NTTP_GEN ( INTERNAL_CATCH_REMOVE_PARENS ( Signature )) \ 1142template < typename... Types > \ 1143struct TestName { \ 1144void reg_tests () { \ 1145int index = 0 ; \ 1146using expander = int[]; \ 1147constexpr char const * tmpl_types[] = { CATCH_REC_LIST ( INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS , INTERNAL_CATCH_REMOVE_PARENS (TmplTypes))};\ 1148constexpr char const * types_list[] = { CATCH_REC_LIST ( INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS , INTERNAL_CATCH_REMOVE_PARENS (TypesList))};\ 1149constexpr auto num_types = sizeof (types_list) / sizeof (types_list[ 0 ]);\ 1150( void )expander{(Catch::AutoReg( Catch ::makeTestInvoker( & TestFuncName < Types > ), CATCH_INTERNAL_LINEINFO , Catch :: StringRef (), Catch ::NameAndTags{ Name " - " + std:: string (tmpl_types[index / num_types]) + "<" + std:: string (types_list[index % num_types]) + ">" , Tags } ), index ++ )... }; /* NOLINT */ \ 1151} \ 1152}; \ 1153static int INTERNAL_CATCH_UNIQUE_NAME ( globalRegistrar ) = [](){ \ 1154using TestInit = typename create < TestName, decltype (get_wrapper < INTERNAL_CATCH_REMOVE_PARENS (TmplTypes) > ()), TypeList < INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES ( INTERNAL_CATCH_REMOVE_PARENS (TypesList))>>::type; \ 1155TestInit t; \ 1156t. reg_tests (); \ 1157return 0 ; \ 1158}(); \ 1159} \ 1160} \ 1161CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1162template < typename TestType > \ 1163static void TestFuncName() 1164 1165#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1166#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE (Name, Tags, ...)\ 1167INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2 ( INTERNAL_CATCH_UNIQUE_NAME ( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME ( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename T ,__VA_ARGS__) 1168#else 1169#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE (Name, Tags, ...)\ 1170INTERNAL_CATCH_EXPAND_VARGS ( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2 ( INTERNAL_CATCH_UNIQUE_NAME ( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME ( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename T , __VA_ARGS__ ) ) 1171#endif 1172 1173#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1174#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG (Name, Tags, Signature, ...)\ 1175INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2 ( INTERNAL_CATCH_UNIQUE_NAME ( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME ( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__) 1176#else 1177#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG (Name, Tags, Signature, ...)\ 1178INTERNAL_CATCH_EXPAND_VARGS ( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2 ( INTERNAL_CATCH_UNIQUE_NAME ( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME ( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ ) ) 1179#endif 1180 1181#define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2 (TestName, TestFunc, Name, Tags, TmplList)\ 1182CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1183CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1184CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 1185template < typename TestType > static void TestFunc (); \ 1186namespace {\ 1187namespace INTERNAL_CATCH_MAKE_NAMESPACE ( TestName ){\ 1188INTERNAL_CATCH_TYPE_GEN \ 1189template < typename... Types > \ 1190struct TestName { \ 1191void reg_tests () { \ 1192int index = 0 ; \ 1193using expander = int[]; \ 1194( void )expander{(Catch::AutoReg( Catch ::makeTestInvoker( & TestFunc < Types > ), CATCH_INTERNAL_LINEINFO , Catch :: StringRef (), Catch ::NameAndTags{ Name " - " + std:: string ( INTERNAL_CATCH_STRINGIZE (TmplList)) + " - " + std:: to_string (index), Tags } ), index ++ )... }; /* NOLINT */ \ 1195} \ 1196};\ 1197static int INTERNAL_CATCH_UNIQUE_NAME ( globalRegistrar ) = [](){ \ 1198using TestInit = typename convert < TestName, TmplList > ::type; \ 1199TestInit t; \ 1200t. reg_tests (); \ 1201return 0 ; \ 1202}(); \ 1203}}\ 1204CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1205template < typename TestType > \ 1206static void TestFunc () 1207 1208#define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE (Name, Tags, TmplList) \ 1209INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2 ( INTERNAL_CATCH_UNIQUE_NAME ( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME ( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, TmplList ) 1210 1211#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2 ( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \ 1212CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1213CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1214CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ 1215CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 1216namespace {\ 1217namespace INTERNAL_CATCH_MAKE_NAMESPACE ( TestName ){ \ 1218INTERNAL_CATCH_TYPE_GEN \ 1219INTERNAL_CATCH_NTTP_GEN ( INTERNAL_CATCH_REMOVE_PARENS ( Signature ))\ 1220INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD (TestName, ClassName, INTERNAL_CATCH_REMOVE_PARENS (Signature));\ 1221INTERNAL_CATCH_NTTP_REG_METHOD_GEN ( TestName , INTERNAL_CATCH_REMOVE_PARENS ( Signature ))\ 1222template < typename...Types > \ 1223struct TestNameClass{\ 1224TestNameClass (){\ 1225int index = 0 ; \ 1226constexpr char const * tmpl_types[] = { CATCH_REC_LIST ( INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS , __VA_ARGS__)};\ 1227using expander = int[];\ 1228( void )expander{(reg_test(Types{}, #ClassName , Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... }; /* NOLINT */ \ 1229}\ 1230};\ 1231static int INTERNAL_CATCH_UNIQUE_NAME ( globalRegistrar ) = [](){\ 1232TestNameClass < INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES (__VA_ARGS__) > ();\ 1233return 0 ;\ 1234}();\ 1235}\ 1236}\ 1237CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1238INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD ( TestName , INTERNAL_CATCH_REMOVE_PARENS ( Signature )) 1239 1240#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1241#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD ( ClassName, Name, Tags,... ) \ 1242INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) 1243#else 1244#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD ( ClassName, Name, Tags,... ) \ 1245INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) ) 1246#endif 1247 1248#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1249#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG ( ClassName, Name, Tags, Signature, ... ) \ 1250INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) 1251#else 1252#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG ( ClassName, Name, Tags, Signature, ... ) \ 1253INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) ) 1254#endif 1255 1256#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2 (TestNameClass, TestName, ClassName, Name, Tags, Signature, TmplTypes, TypesList)\ 1257CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1258CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1259CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ 1260CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 1261template<typename TestType> \ 1262struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \ 1263void test();\ 1264};\ 1265namespace {\ 1266namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestNameClass) {\ 1267INTERNAL_CATCH_TYPE_GEN \ 1268INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\ 1269template<typename...Types>\ 1270struct TestNameClass{\ 1271void reg_tests(){\ 1272int index = 0;\ 1273using expander = int[];\ 1274constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\ 1275constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\ 1276constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\ 1277(void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++)... }; /* NOLINT */ \ 1278}\ 1279};\ 1280static int INTERNAL_CATCH_UNIQUE_NAME ( globalRegistrar ) = [](){\ 1281using TestInit = typename create<TestNameClass, decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>()), TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(INTERNAL_CATCH_REMOVE_PARENS(TypesList))>>::type;\ 1282TestInit t;\ 1283t.reg_tests();\ 1284return 0;\ 1285}(); \ 1286}\ 1287}\ 1288CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1289template<typename TestType> \ 1290void TestName<TestType>::test() 1291 1292#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1293#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD ( ClassName, Name, Tags, ... )\ 1294INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, typename T, __VA_ARGS__ ) 1295#else 1296#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD ( ClassName, Name, Tags, ... )\ 1297INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, typename T,__VA_ARGS__ ) ) 1298#endif 1299 1300#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1301#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG ( ClassName, Name, Tags, Signature, ... )\ 1302INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, Signature, __VA_ARGS__ ) 1303#else 1304#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG ( ClassName, Name, Tags, Signature, ... )\ 1305INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, Signature,__VA_ARGS__ ) ) 1306#endif 1307 1308#define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2 ( TestNameClass, TestName, ClassName, Name, Tags, TmplList) \ 1309CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 1310CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1311CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 1312template<typename TestType> \ 1313struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \ 1314void test();\ 1315};\ 1316namespace {\ 1317namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \ 1318INTERNAL_CATCH_TYPE_GEN\ 1319template<typename...Types>\ 1320struct TestNameClass{\ 1321void reg_tests(){\ 1322int index = 0;\ 1323using expander = int[];\ 1324(void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + std::to_string(index), Tags } ), index++)... }; /* NOLINT */ \ 1325}\ 1326};\ 1327static int INTERNAL_CATCH_UNIQUE_NAME ( globalRegistrar ) = [](){\ 1328using TestInit = typename convert<TestNameClass, TmplList>::type;\ 1329TestInit t;\ 1330t.reg_tests();\ 1331return 0;\ 1332}(); \ 1333}}\ 1334CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 1335template<typename TestType> \ 1336void TestName<TestType>::test() 1337 1338#define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD (ClassName, Name, Tags, TmplList) \ 1339INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, TmplList ) 1340 1341// end catch_test_registry.h 1342// start catch_capture.hpp 1343 1344// start catch_assertionhandler.h 1345 1346// start catch_assertioninfo.h 1347 1348// start catch_result_type.h 1349 1350namespace Catch { 1351 1352// ResultWas::OfType enum 1353struct ResultWas { enum OfType { 1354Unknown = -1 , 1355Ok = 0 , 1356Info = 1 , 1357Warning = 2 , 1358 1359FailureBit = 0x10 , 1360 1361ExpressionFailed = FailureBit | 1 , 1362ExplicitFailure = FailureBit | 2 , 1363 1364Exception = 0x100 | FailureBit, 1365 1366ThrewException = Exception | 1 , 1367DidntThrowException = Exception | 2 , 1368 1369FatalErrorCondition = 0x200 | FailureBit 1370 1371}; }; 1372 1373bool isOk ( ResultWas ::OfType resultType ); 1374bool isJustInfo ( int flags ); 1375 1376// ResultDisposition::Flags enum 1377struct ResultDisposition { enum Flags { 1378Normal = 0x01 , 1379 1380ContinueOnFailure = 0x02 , // Failures fail test, but execution continues 1381FalseTest = 0x04 , // Prefix expression with ! 1382SuppressFail = 0x08 // Failures are reported but do not fail the test 1383}; }; 1384 1385ResultDisposition:: Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ); 1386 1387bool shouldContinueOnFailure ( int flags ); 1388inline bool isFalseTest ( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0 ; } 1389bool shouldSuppressFailure ( int flags ); 1390 1391} // end namespace Catch 1392 1393// end catch_result_type.h 1394namespace Catch { 1395 1396struct AssertionInfo 1397{ 1398StringRef macroName ; 1399SourceLineInfo lineInfo ; 1400StringRef capturedExpression ; 1401ResultDisposition :: Flags resultDisposition ; 1402 1403// We want to delete this constructor but a compiler bug in 4.8 means 1404// the struct is then treated as non-aggregate 1405//AssertionInfo() = delete; 1406}; 1407 1408} // end namespace Catch 1409 1410// end catch_assertioninfo.h 1411// start catch_decomposer.h 1412 1413// start catch_tostring.h 1414 1415#include <vector> 1416#include <cstddef> 1417#include <type_traits> 1418#include <string> 1419// start catch_stream.h 1420 1421#include <iosfwd> 1422#include <cstddef> 1423#include <ostream> 1424 1425namespace Catch { 1426 1427std ::ostream & cout (); 1428std ::ostream & cerr (); 1429std ::ostream & clog (); 1430 1431class StringRef; 1432 1433struct IStream { 1434virtual ~ IStream (); 1435virtual std ::ostream & stream () const = 0 ; 1436}; 1437 1438auto makeStream( StringRef const & filename ) -> IStream const * ; 1439 1440class ReusableStringStream : NonCopyable { 1441std :: size_t m_index; 1442std :: ostream * m_oss; 1443public : 1444ReusableStringStream (); 1445~ ReusableStringStream (); 1446 1447auto str() const -> std :: string ; 1448 1449template < typename T > 1450auto operator << ( T const & value ) -> ReusableStringStream & { 1451* m_oss << value ; 1452return * this; 1453} 1454auto get() -> std ::ostream & { return * m_oss; } 1455}; 1456} 1457 1458// end catch_stream.h 1459// start catch_interfaces_enum_values_registry.h 1460 1461#include < vector > 1462 1463namespace Catch { 1464 1465namespace Detail { 1466struct EnumInfo { 1467StringRef m_name; 1468std::vector < std::pair < int , StringRef>> m_values; 1469 1470~ EnumInfo (); 1471 1472StringRef lookup ( int value ) const; 1473}; 1474} // namespace Detail 1475 1476struct IMutableEnumValuesRegistry { 1477virtual ~ IMutableEnumValuesRegistry (); 1478 1479virtual Detail::EnumInfo const & registerEnum ( StringRef enumName, StringRef allEnums, std ::vector < int > const & values ) = 0 ; 1480 1481template < typename E > 1482Detail:: EnumInfo const & registerEnum ( StringRef enumName, StringRef allEnums, std::initializer_list < E > values ) { 1483static_assert ( sizeof ( int ) >= sizeof ( E ), "Cannot serialize enum to int" ); 1484std ::vector < int > intValues; 1485intValues. reserve ( values. size () ); 1486for ( auto enumValue : values ) 1487intValues. push_back ( static_cast < int > ( enumValue ) ); 1488return registerEnum ( enumName, allEnums, intValues ); 1489} 1490}; 1491 1492} // Catch 1493 1494// end catch_interfaces_enum_values_registry.h 1495 1496#ifdef CATCH_CONFIG_CPP17_STRING_VIEW 1497#include < string_view > 1498#endif 1499 1500#ifdef __OBJC__ 1501// start catch_objc_arc.hpp 1502 1503#import < Foundation/Foundation. h > 1504 1505#ifdef __has_feature 1506#define CATCH_ARC_ENABLED __has_feature (objc_arc) 1507#else 1508#define CATCH_ARC_ENABLED 0 1509#endif 1510 1511void arcSafeRelease ( NSObject * obj ); 1512id performOptionalSelector( id obj, SEL sel ); 1513 1514#if ! CATCH_ARC_ENABLED 1515inline void arcSafeRelease ( NSObject * obj ) { 1516[ obj release]; 1517} 1518inline id performOptionalSelector ( id obj, SEL sel ) { 1519if ( [obj respondsToSelector : sel] ) 1520return [obj performSelector : sel]; 1521return nil; 1522} 1523#define CATCH_UNSAFE_UNRETAINED 1524#define CATCH_ARC_STRONG 1525#else 1526inline void arcSafeRelease ( NSObject * ){} 1527inline id performOptionalSelector ( id obj, SEL sel ) { 1528#ifdef __clang__ 1529#pragma clang diagnostic push 1530#pragma clang diagnostic ignored "-Warc-performSelector-leaks" 1531#endif 1532if ( [obj respondsToSelector : sel] ) 1533return [obj performSelector : sel]; 1534#ifdef __clang__ 1535#pragma clang diagnostic pop 1536#endif 1537return nil; 1538} 1539#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained 1540#define CATCH_ARC_STRONG __strong 1541#endif 1542 1543// end catch_objc_arc.hpp 1544#endif 1545 1546#ifdef _MSC_VER 1547#pragma warning(push) 1548#pragma warning(disable:4180) // We attempt to stream a function (address) by const&, which MSVC complains about but is harmless 1549#endif 1550 1551namespace Catch { 1552namespace Detail { 1553 1554extern const std ::string unprintableString; 1555 1556std :: string rawMemoryToString ( const void * object, std :: size_t size ); 1557 1558template < typename T > 1559std:: string rawMemoryToString ( const T & object ) { 1560return rawMemoryToString ( & object, sizeof (object) ); 1561} 1562 1563template < typename T > 1564class IsStreamInsertable { 1565template < typename Stream, typename U > 1566static auto test (int) 1567-> decltype (std::declval < Stream &> () << std::declval < U > (), std:: true_type ()); 1568 1569template < typename, typename > 1570static auto test(...) -> std :: false_type ; 1571 1572public : 1573static const bool value = decltype (test < std::ostream, const T &> ( 0 ))::value; 1574}; 1575 1576template < typename E > 1577std:: string convertUnknownEnumToString ( E e ); 1578 1579template < typename T > 1580typename std ::enable_if < 1581!std::is_enum < T > ::value && !std::is_base_of < std::exception, T > ::value, 1582std::string > :: type convertUnstreamable ( T const & ) { 1583return Detail::unprintableString; 1584} 1585template < typename T > 1586typename std ::enable_if < 1587!std::is_enum < T > ::value && std::is_base_of < std::exception, T > ::value, 1588std::string > :: type convertUnstreamable ( T const & ex) { 1589return ex. what (); 1590} 1591 1592template < typename T > 1593typename std ::enable_if < 1594std::is_enum < T > ::value 1595, std::string > :: type convertUnstreamable ( T const & value ) { 1596return convertUnknownEnumToString ( value ); 1597} 1598 1599#if defined(_MANAGED) 1600//! Convert a CLR string to a utf8 std::string 1601template < typename T > 1602std::string clrReferenceToString ( T ^ ref ) { 1603if (ref == nullptr ) 1604return std:: string ( "null" ); 1605auto bytes = System::Text::Encoding:: UTF8 -> GetBytes ( ref -> ToString ()); 1606cli ::pin_ptr < System::Byte > p = & bytes[ 0 ]; 1607return std:: string (reinterpret_cast < char const *> (p), bytes -> Length ); 1608} 1609#endif 1610 1611} // namespace Detail 1612 1613// If we decide for C++14, change these to enable_if_ts 1614template < typename T , typename = void > 1615struct StringMaker { 1616template < typename Fake = T > 1617static 1618typename std::enable_if < :: Catch :: Detail ::IsStreamInsertable < Fake > ::value, std::string > :: type 1619convert ( const Fake & value) { 1620ReusableStringStream rss; 1621// NB: call using the function-like syntax to avoid ambiguity with 1622// user-defined templated operator<< under clang. 1623rss. operator <<(value); 1624return rss. str (); 1625} 1626 1627template < typename Fake = T > 1628static 1629typename std::enable_if < !::Catch::Detail::IsStreamInsertable < Fake > ::value, std::string > :: type 1630convert ( const Fake & value ) { 1631#if !defined( CATCH_CONFIG_FALLBACK_STRINGIFIER ) 1632return Detail:: convertUnstreamable (value); 1633#else 1634return CATCH_CONFIG_FALLBACK_STRINGIFIER (value); 1635#endif 1636} 1637}; 1638 1639namespace Detail { 1640 1641// This function dispatches all stringification requests inside of Catch. 1642// Should be preferably called fully qualified, like ::Catch::Detail::stringify 1643template < typename T > 1644std:: string stringify ( const T & e) { 1645return ::Catch::StringMaker < typename std ::remove_cv < typename std ::remove_reference < T > ::type > ::type > :: convert (e); 1646} 1647 1648template < typename E > 1649std:: string convertUnknownEnumToString ( E e ) { 1650return ::Catch::Detail:: stringify (static_cast < typename std::underlying_type < E > ::type > (e)); 1651} 1652 1653#if defined(_MANAGED) 1654template < typename T > 1655std::string stringify ( T ^ e ) { 1656return ::Catch::StringMaker < T ^ > :: convert (e); 1657} 1658#endif 1659 1660} // namespace Detail 1661 1662// Some predefined specializations 1663 1664template <> 1665struct StringMaker < std::string > { 1666static std ::string convert ( const std ::string & str); 1667}; 1668 1669#ifdef CATCH_CONFIG_CPP17_STRING_VIEW 1670template <> 1671struct StringMaker < std::string_view > { 1672static std ::string convert ( std ::string_view str); 1673}; 1674#endif 1675 1676template <> 1677struct StringMaker < char const *> { 1678static std ::string convert ( char const * str); 1679}; 1680template <> 1681struct StringMaker < char *> { 1682static std ::string convert ( char * str); 1683}; 1684 1685#ifdef CATCH_CONFIG_WCHAR 1686template <> 1687struct StringMaker < std::wstring > { 1688static std ::string convert ( const std ::wstring & wstr); 1689}; 1690 1691# ifdef CATCH_CONFIG_CPP17_STRING_VIEW 1692template <> 1693struct StringMaker < std::wstring_view > { 1694static std ::string convert ( std ::wstring_view str); 1695}; 1696# endif 1697 1698template <> 1699struct StringMaker < wchar_t const *> { 1700static std ::string convert ( wchar_t const * str); 1701}; 1702template <> 1703struct StringMaker < wchar_t *> { 1704static std ::string convert ( wchar_t * str); 1705}; 1706#endif 1707 1708// TBD: Should we use `strnlen` to ensure that we don't go out of the buffer, 1709// while keeping string semantics? 1710template < int SZ > 1711struct StringMaker < char[ SZ ] > { 1712static std:: string convert ( char const * str) { 1713return ::Catch::Detail:: stringify (std::string{ str }); 1714} 1715}; 1716template < int SZ > 1717struct StringMaker < signed char[ SZ ] > { 1718static std:: string convert ( signed char const * str) { 1719return ::Catch::Detail:: stringify (std::string{ reinterpret_cast < char const *> (str) }); 1720} 1721}; 1722template < int SZ > 1723struct StringMaker < unsigned char [ SZ ] > { 1724static std::string convert(unsigned char const * str) { 1725return ::Catch::Detail::stringify(std::string{ reinterpret_cast < char const *> (str) }); 1726} 1727}; 1728 1729#if defined( CATCH_CONFIG_CPP17_BYTE ) 1730template < > 1731struct StringMaker < std::byte > { 1732static std::string convert(std::byte value); 1733}; 1734#endif // defined(CATCH_CONFIG_CPP17_BYTE) 1735template < > 1736struct StringMaker < int > { 1737static std::string convert( int value); 1738}; 1739template < > 1740struct StringMaker < long > { 1741static std::string convert(long value); 1742}; 1743template <> 1744struct StringMaker < long long > { 1745static std ::string convert ( long long value); 1746}; 1747template <> 1748struct StringMaker < unsigned int > { 1749static std ::string convert ( unsigned int value); 1750}; 1751template <> 1752struct StringMaker < unsigned long > { 1753static std ::string convert ( unsigned long value); 1754}; 1755template <> 1756struct StringMaker < unsigned long long > { 1757static std ::string convert ( unsigned long long value); 1758}; 1759 1760template <> 1761struct StringMaker < bool > { 1762static std ::string convert ( bool b); 1763}; 1764 1765template <> 1766struct StringMaker < char > { 1767static std ::string convert ( char c); 1768}; 1769template <> 1770struct StringMaker < signed char > { 1771static std ::string convert ( signed char c); 1772}; 1773template <> 1774struct StringMaker < unsigned char > { 1775static std ::string convert ( unsigned char c); 1776}; 1777 1778template <> 1779struct StringMaker < std:: nullptr_t > { 1780static std ::string convert (std:: nullptr_t ); 1781}; 1782 1783template <> 1784struct StringMaker < float > { 1785static std ::string convert ( float value); 1786static int precision; 1787}; 1788 1789template <> 1790struct StringMaker < double > { 1791static std ::string convert ( double value); 1792static int precision; 1793}; 1794 1795template < typename T > 1796struct StringMaker < T *> { 1797template < typename U > 1798static std :: string convert ( U * p) { 1799if (p) { 1800return ::Catch::Detail:: rawMemoryToString (p); 1801} else { 1802return "nullptr" ; 1803} 1804} 1805}; 1806 1807template < typename R , typename C > 1808struct StringMaker < R C :: *> { 1809static std :: string convert( R C :: * p) { 1810if (p) { 1811return :: Catch :: Detail :: rawMemoryToString (p); 1812} else { 1813return "nullptr" ; 1814} 1815} 1816}; 1817 1818#if defined(_MANAGED) 1819template < typename T > 1820struct StringMaker < T ^ > { 1821static std::string convert ( T ^ ref ) { 1822return ::Catch::Detail:: clrReferenceToString (ref); 1823} 1824}; 1825#endif 1826 1827namespace Detail { 1828template < typename InputIterator, typename Sentinel = InputIterator > 1829std:: string rangeToString ( InputIterator first, Sentinel last) { 1830ReusableStringStream rss; 1831rss << "{ " ; 1832if (first != last) { 1833rss << ::Catch:: Detail :: stringify ( * first); 1834for ( ++ first; first != last; ++ first) 1835rss << ", " << ::Catch:: Detail :: stringify ( * first); 1836} 1837rss << " }" ; 1838return rss. str (); 1839} 1840} 1841 1842#ifdef __OBJC__ 1843template <> 1844struct StringMaker < NSString *> { 1845static std ::string convert ( NSString * nsstring) { 1846if (!nsstring) 1847return "nil" ; 1848return std:: string ( "@" ) + [nsstring UTF8String]; 1849} 1850}; 1851template <> 1852struct StringMaker < NSObject *> { 1853static std ::string convert ( NSObject * nsObject) { 1854return ::Catch::Detail::stringify([nsObject description]); 1855} 1856 1857}; 1858namespace Detail { 1859inline std ::string stringify ( NSString * nsstring ) { 1860return StringMaker < NSString *> :: convert ( nsstring ); 1861} 1862 1863} // namespace Detail 1864#endif // __OBJC__ 1865 1866} // namespace Catch 1867 1868////////////////////////////////////////////////////// 1869// Separate std-lib types stringification, so it can be selectively enabled 1870// This means that we do not bring in 1871 1872#if defined( CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS ) 1873# define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER 1874# define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER 1875# define CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER 1876# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER 1877# define CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER 1878#endif 1879 1880// Separate std::pair specialization 1881#if defined( CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER ) 1882#include <utility> 1883namespace Catch { 1884template < typename T1 , typename T2 > 1885struct StringMaker < std::pair < T1 , T2 > > { 1886static std ::string convert ( const std ::pair < T1 , T2 >& pair) { 1887ReusableStringStream rss; 1888rss << "{ " 1889<< ::Catch:: Detail :: stringify (pair. first ) 1890<< ", " 1891<< :: Catch :: Detail :: stringify (pair. second ) 1892<< " }" ; 1893return rss. str (); 1894} 1895}; 1896} 1897#endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER 1898 1899#if defined( CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER ) && defined( CATCH_CONFIG_CPP17_OPTIONAL ) 1900#include <optional> 1901namespace Catch { 1902template < typename T > 1903struct StringMaker < std::optional < T > > { 1904static std:: string convert( const std ::optional < T >& optional) { 1905ReusableStringStream rss; 1906if (optional. has_value ()) { 1907rss << ::Catch:: Detail :: stringify ( * optional); 1908} else { 1909rss << "{ }" ; 1910} 1911return rss. str (); 1912} 1913}; 1914} 1915#endif // CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER 1916 1917// Separate std::tuple specialization 1918#if defined( CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER ) 1919#include <tuple> 1920namespace Catch { 1921namespace Detail { 1922template < 1923typename Tuple, 1924std:: size_t N = 0 , 1925bool = ( N < std::tuple_size < Tuple > ::value) 1926> 1927struct TupleElementPrinter { 1928static void (const Tuple & tuple, std::ostream & os) { 1929os << ( N ? ", " : " " ) 1930<< ::Catch:: Detail ::stringify(std::get < N > (tuple)); 1931TupleElementPrinter < Tuple, N + 1 > :: (tuple, os); 1932} 1933}; 1934 1935template < 1936typename Tuple, 1937std:: size_t N 1938> 1939struct TupleElementPrinter < Tuple, N , false > { 1940static void ( const Tuple & , std ::ostream & ) {} 1941}; 1942 1943} 1944 1945template < typename ...Types > 1946struct StringMaker < std::tuple < Types...>> { 1947static std:: string convert( const std ::tuple < Types... >& tuple) { 1948ReusableStringStream rss; 1949rss << '{' ; 1950Detail ::TupleElementPrinter < std::tuple < Types...>>:: (tuple, rss. get ()); 1951rss << " }" ; 1952return rss. str (); 1953} 1954}; 1955} 1956#endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER 1957 1958#if defined( CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER ) && defined( CATCH_CONFIG_CPP17_VARIANT ) 1959#include <variant> 1960namespace Catch { 1961template <> 1962struct StringMaker < std::monostate > { 1963static std ::string convert ( const std ::monostate & ) { 1964return "{ }" ; 1965} 1966}; 1967 1968template < typename... Elements > 1969struct StringMaker < std::variant < Elements...>> { 1970static std:: string convert( const std ::variant < Elements... >& variant) { 1971if (variant. valueless_by_exception ()) { 1972return "{valueless variant}" ; 1973} else { 1974return std:: visit ( 1975[]( const auto & value) { 1976return ::Catch::Detail:: stringify (value); 1977}, 1978variant 1979); 1980} 1981} 1982}; 1983} 1984#endif // CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER 1985 1986namespace Catch { 1987// Import begin/ end from std here 1988using std::begin; 1989using std::end; 1990 1991namespace detail { 1992template < typename... > 1993struct void_type { 1994using type = void; 1995}; 1996 1997template < typename T , typename = void > 1998struct is_range_impl : std ::false_type { 1999}; 2000 2001template < typename T > 2002struct is_range_impl < T , typename void_type < decltype ( begin (std::declval < T > ())) > ::type > : std::true_type { 2003}; 2004} // namespace detail 2005 2006template < typename T > 2007struct is_range : detail ::is_range_impl < T > { 2008}; 2009 2010#if defined(_MANAGED) // Managed types are never ranges 2011template < typename T > 2012struct is_range < T ^ > { 2013static const bool value = false; 2014}; 2015#endif 2016 2017template < typename Range > 2018std:: string rangeToString ( Range const & range ) { 2019return ::Catch::Detail:: rangeToString ( begin ( range ), end ( range ) ); 2020} 2021 2022// Handle vector<bool> specially 2023template < typename Allocator > 2024std:: string rangeToString ( std ::vector < bool , Allocator > const & v ) { 2025ReusableStringStream rss; 2026rss << "{ " ; 2027bool first = true; 2028for ( bool b : v ) { 2029if ( first ) 2030first = false; 2031else 2032rss << ", " ; 2033rss << ::Catch:: Detail :: stringify ( b ); 2034} 2035rss << " }" ; 2036return rss. str (); 2037} 2038 2039template < typename R > 2040struct StringMaker < R , typename std ::enable_if < is_range < R > ::value && !:: Catch :: Detail ::IsStreamInsertable < R > ::value > ::type > { 2041static std :: string convert ( R const & range ) { 2042return rangeToString ( range ); 2043} 2044}; 2045 2046template < typename T , int SZ > 2047struct StringMaker < T [ SZ ] > { 2048static std:: string convert ( T const ( & arr )[ SZ ]) { 2049return rangeToString (arr); 2050} 2051}; 2052 2053} // namespace Catch 2054 2055// Separate std::chrono::duration specialization 2056#if defined( CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER ) 2057#include <ctime> 2058#include <ratio> 2059#include <chrono> 2060 2061namespace Catch { 2062 2063template < class Ratio > 2064struct ratio_string { 2065static std ::string symbol (); 2066}; 2067 2068template < class Ratio > 2069std::string ratio_string < Ratio > :: symbol () { 2070Catch :: ReusableStringStream rss; 2071rss << '[' << Ratio::num << '/' 2072<< Ratio::den << ']' ; 2073return rss. str (); 2074} 2075template <> 2076struct ratio_string < std::atto > { 2077static std ::string symbol (); 2078}; 2079template <> 2080struct ratio_string < std::femto > { 2081static std ::string symbol (); 2082}; 2083template <> 2084struct ratio_string < std::pico > { 2085static std ::string symbol (); 2086}; 2087template <> 2088struct ratio_string < std::nano > { 2089static std ::string symbol (); 2090}; 2091template <> 2092struct ratio_string < std::micro > { 2093static std ::string symbol (); 2094}; 2095template <> 2096struct ratio_string < std::milli > { 2097static std ::string symbol (); 2098}; 2099 2100//////////// 2101// std::chrono::duration specializations 2102template < typename Value, typename Ratio > 2103struct StringMaker < std:: chrono ::duration < Value, Ratio>> { 2104static std ::string convert ( std ::chrono::duration < Value, Ratio > const & duration) { 2105ReusableStringStream rss; 2106rss << duration. count () << ' ' << ratio_string < Ratio > :: symbol () << 's' ; 2107return rss. str (); 2108} 2109}; 2110template < typename Value > 2111struct StringMaker < std:: chrono ::duration < Value, std::ratio < 1 >> > { 2112static std:: string convert( std :: chrono ::duration < Value, std::ratio < 1 >> const & duration) { 2113ReusableStringStream rss; 2114rss << duration. count () << " s" ; 2115return rss. str (); 2116} 2117}; 2118template < typename Value > 2119struct StringMaker < std:: chrono ::duration < Value, std::ratio < 60 >> > { 2120static std:: string convert( std :: chrono ::duration < Value, std::ratio < 60 >> const & duration) { 2121ReusableStringStream rss; 2122rss << duration. count () << " m" ; 2123return rss. str (); 2124} 2125}; 2126template < typename Value > 2127struct StringMaker < std:: chrono ::duration < Value, std::ratio < 3600 >> > { 2128static std:: string convert( std :: chrono ::duration < Value, std::ratio < 3600 >> const & duration) { 2129ReusableStringStream rss; 2130rss << duration. count () << " h" ; 2131return rss. str (); 2132} 2133}; 2134 2135//////////// 2136// std::chrono::time_point specialization 2137// Generic time_point cannot be specialized, only std::chrono::time_point<system_clock> 2138template < typename Clock, typename Duration > 2139struct StringMaker < std:: chrono ::time_point < Clock, Duration>> { 2140static std ::string convert ( std ::chrono::time_point < Clock, Duration > const & time_point) { 2141return ::Catch::Detail:: stringify (time_point. time_since_epoch ()) + " since epoch" ; 2142} 2143}; 2144// std::chrono::time_point<system_clock> specialization 2145template < typename Duration > 2146struct StringMaker < std:: chrono ::time_point < std:: chrono ::system_clock, Duration>> { 2147static std ::string convert ( std ::chrono::time_point < std::chrono::system_clock, Duration > const & time_point) { 2148auto converted = std::chrono::system_clock:: to_time_t ( time_point ); 2149 2150#ifdef _MSC_VER 2151std :: tm timeInfo = {}; 2152gmtime_s ( & timeInfo, & converted); 2153#else 2154std :: tm * timeInfo = std:: gmtime ( & converted); 2155#endif 2156 2157auto const timeStampSize = sizeof ( "2017-01-16T17:06:45Z" ); 2158char timeStamp[timeStampSize]; 2159const char * const fmt = "%Y-%m-%dT%H:%M:%SZ" ; 2160 2161#ifdef _MSC_VER 2162std :: strftime (timeStamp, timeStampSize, fmt, & timeInfo); 2163#else 2164std :: strftime (timeStamp, timeStampSize, fmt, timeInfo); 2165#endif 2166return std:: string (timeStamp); 2167} 2168}; 2169} 2170#endif // CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER 2171 2172#define INTERNAL_CATCH_REGISTER_ENUM ( enumName, ... ) \ 2173namespace Catch { \ 2174template<> struct StringMaker<enumName> { \ 2175static std::string convert( enumName value ) { \ 2176static const auto& enumInfo = ::Catch::getMutableRegistryHub().getMutableEnumValuesRegistry().registerEnum( #enumName, #__VA_ARGS__, { __VA_ARGS__ } ); \ 2177return static_cast<std::string>(enumInfo.lookup( static_cast<int>( value ) )); \ 2178} \ 2179}; \ 2180} 2181 2182#define CATCH_REGISTER_ENUM ( enumName, ... ) INTERNAL_CATCH_REGISTER_ENUM( enumName, __VA_ARGS__ ) 2183 2184#ifdef _MSC_VER 2185#pragma warning(pop) 2186#endif 2187 2188// end catch_tostring.h 2189#include <iosfwd> 2190 2191#ifdef _MSC_VER 2192#pragma warning(push) 2193#pragma warning(disable:4389) // '==' : signed/unsigned mismatch 2194#pragma warning(disable:4018) // more "signed/unsigned mismatch" 2195#pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform) 2196#pragma warning(disable:4180) // qualifier applied to function type has no meaning 2197#pragma warning(disable:4800) // Forcing result to true or false 2198#endif 2199 2200namespace Catch { 2201 2202struct ITransientExpression { 2203auto isBinaryExpression() const -> bool { return m_isBinaryExpression ; } 2204auto getResult () const -> bool { return m_result; } 2205virtual void streamReconstructedExpression ( std ::ostream & os ) const = 0 ; 2206 2207ITransientExpression( bool isBinaryExpression, bool result ) 2208: m_isBinaryExpression ( isBinaryExpression ), 2209m_result ( result ) 2210{} 2211 2212// We don't actually need a virtual destructor, but many static analysers 2213// complain if it's not here :-( 2214virtual ~ ITransientExpression (); 2215 2216bool m_isBinaryExpression; 2217bool m_result; 2218 2219}; 2220 2221void formatReconstructedExpression ( std ::ostream & os, std ::string const & lhs, StringRef op, std ::string const & rhs ); 2222 2223template < typename LhsT, typename RhsT > 2224class BinaryExpr : public ITransientExpression { 2225LhsT m_lhs; 2226StringRef m_op; 2227RhsT m_rhs; 2228 2229void streamReconstructedExpression ( std ::ostream & os ) const override { 2230formatReconstructedExpression 2231( os , Catch ::Detail:: stringify ( m_lhs ), m_op , Catch ::Detail:: stringify ( m_rhs ) ); 2232} 2233 2234public : 2235BinaryExpr ( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs ) 2236: ITransientExpression{ true, comparisonResult }, 2237m_lhs ( lhs ), 2238m_op ( op ), 2239m_rhs ( rhs ) 2240{} 2241 2242template < typename T > 2243auto operator && ( T ) const -> BinaryExpr < LhsT, RhsT const &> const { 2244static_assert (always_false < T > ::value, 2245"chained comparisons are not supported inside assertions, " 2246"wrap the expression inside parentheses, or decompose it" ); 2247} 2248 2249template < typename T > 2250auto operator || ( T ) const -> BinaryExpr < LhsT, RhsT const &> const { 2251static_assert (always_false < T > ::value, 2252"chained comparisons are not supported inside assertions, " 2253"wrap the expression inside parentheses, or decompose it" ); 2254} 2255 2256template < typename T > 2257auto operator == ( T ) const -> BinaryExpr < LhsT, RhsT const &> const { 2258static_assert (always_false < T > ::value, 2259"chained comparisons are not supported inside assertions, " 2260"wrap the expression inside parentheses, or decompose it" ); 2261} 2262 2263template < typename T > 2264auto operator != ( T ) const -> BinaryExpr < LhsT, RhsT const &> const { 2265static_assert (always_false < T > ::value, 2266"chained comparisons are not supported inside assertions, " 2267"wrap the expression inside parentheses, or decompose it" ); 2268} 2269 2270template < typename T > 2271auto operator > ( T ) const -> BinaryExpr < LhsT, RhsT const &> const { 2272static_assert (always_false < T > ::value, 2273"chained comparisons are not supported inside assertions, " 2274"wrap the expression inside parentheses, or decompose it" ); 2275} 2276 2277template < typename T > 2278auto operator < ( T ) const -> BinaryExpr < LhsT, RhsT const &> const { 2279static_assert (always_false < T > ::value, 2280"chained comparisons are not supported inside assertions, " 2281"wrap the expression inside parentheses, or decompose it" ); 2282} 2283 2284template < typename T > 2285auto operator >= ( T ) const -> BinaryExpr < LhsT, RhsT const &> const { 2286static_assert (always_false < T > ::value, 2287"chained comparisons are not supported inside assertions, " 2288"wrap the expression inside parentheses, or decompose it" ); 2289} 2290 2291template < typename T > 2292auto operator <= ( T ) const -> BinaryExpr < LhsT, RhsT const &> const { 2293static_assert (always_false < T > ::value, 2294"chained comparisons are not supported inside assertions, " 2295"wrap the expression inside parentheses, or decompose it" ); 2296} 2297}; 2298 2299template < typename LhsT > 2300class UnaryExpr : public ITransientExpression { 2301LhsT m_lhs; 2302 2303void streamReconstructedExpression ( std ::ostream & os ) const override { 2304os << Catch:: Detail :: stringify ( m_lhs ); 2305} 2306 2307public : 2308explicit UnaryExpr ( LhsT lhs ) 2309: ITransientExpression{ false, static_cast < bool > (lhs) }, 2310m_lhs ( lhs ) 2311{} 2312}; 2313 2314// Specialised comparison functions to handle equality comparisons between ints and pointers (NULL deduces as an int) 2315template < typename LhsT, typename RhsT > 2316auto compareEqual( LhsT const & lhs, RhsT const & rhs ) -> bool { return static_cast < bool > (lhs == rhs); } 2317template < typename T > 2318auto compareEqual ( T * const & lhs, int rhs ) -> bool { return lhs == reinterpret_cast < void const *> ( rhs ); } 2319template < typename T > 2320auto compareEqual ( T * const & lhs, long rhs ) -> bool { return lhs == reinterpret_cast < void const *> ( rhs ); } 2321template < typename T > 2322auto compareEqual ( int lhs, T * const & rhs ) -> bool { return reinterpret_cast < void const *> ( lhs ) == rhs; } 2323template < typename T > 2324auto compareEqual( long lhs , T * const & rhs ) -> bool { return reinterpret_cast < void const *> ( lhs ) == rhs; } 2325 2326template < typename LhsT, typename RhsT > 2327auto compareNotEqual( LhsT const & lhs, RhsT && rhs ) -> bool { return static_cast < bool > (lhs != rhs); } 2328template < typename T > 2329auto compareNotEqual ( T * const & lhs, int rhs ) -> bool { return lhs != reinterpret_cast < void const *> ( rhs ); } 2330template < typename T > 2331auto compareNotEqual ( T * const & lhs, long rhs ) -> bool { return lhs != reinterpret_cast < void const *> ( rhs ); } 2332template < typename T > 2333auto compareNotEqual ( int lhs, T * const & rhs ) -> bool { return reinterpret_cast < void const *> ( lhs ) != rhs; } 2334template < typename T > 2335auto compareNotEqual( long lhs , T * const & rhs ) -> bool { return reinterpret_cast < void const *> ( lhs ) != rhs; } 2336 2337template < typename LhsT > 2338class ExprLhs { 2339LhsT m_lhs; 2340public : 2341explicit ExprLhs ( LhsT lhs ) : m_lhs ( lhs ) {} 2342 2343template < typename RhsT > 2344auto operator == ( RhsT const & rhs ) -> BinaryExpr < LhsT, RhsT const &> const { 2345return { compareEqual ( m_lhs, rhs ), m_lhs, "==" , rhs }; 2346} 2347auto operator == ( bool rhs ) -> BinaryExpr < LhsT, bool > const { 2348return { m_lhs == rhs, m_lhs, " == ", rhs }; 2349} 2350 2351template < typename RhsT > 2352auto operator != ( RhsT const & rhs ) -> BinaryExpr < LhsT, RhsT const &> const { 2353return { compareNotEqual ( m_lhs, rhs ), m_lhs, "!=" , rhs }; 2354} 2355auto operator != ( bool rhs ) -> BinaryExpr < LhsT, bool > const { 2356return { m_lhs != rhs, m_lhs, " != ", rhs }; 2357} 2358 2359template < typename RhsT > 2360auto operator > ( RhsT const & rhs ) -> BinaryExpr < LhsT, RhsT const &> const { 2361return { static_cast < bool > (m_lhs > rhs), m_lhs, ">" , rhs }; 2362} 2363template < typename RhsT > 2364auto operator < ( RhsT const & rhs ) -> BinaryExpr < LhsT, RhsT const &> const { 2365return { static_cast < bool > (m_lhs < rhs), m_lhs, "<" , rhs }; 2366} 2367template < typename RhsT > 2368auto operator >= ( RhsT const & rhs ) -> BinaryExpr < LhsT, RhsT const &> const { 2369return { static_cast < bool > (m_lhs >= rhs), m_lhs, ">=" , rhs }; 2370} 2371template < typename RhsT > 2372auto operator <= ( RhsT const & rhs ) -> BinaryExpr < LhsT, RhsT const &> const { 2373return { static_cast < bool > (m_lhs <= rhs), m_lhs, "<=" , rhs }; 2374} 2375template < typename RhsT > 2376auto operator | ( RhsT const & rhs) -> BinaryExpr < LhsT, RhsT const &> const { 2377return { static_cast < bool > (m_lhs | rhs), m_lhs, "|" , rhs }; 2378} 2379template < typename RhsT > 2380auto operator & ( RhsT const & rhs) -> BinaryExpr < LhsT, RhsT const &> const { 2381return { static_cast < bool > (m_lhs & rhs), m_lhs, "&" , rhs }; 2382} 2383template < typename RhsT > 2384auto operator ^ ( RhsT const & rhs) -> BinaryExpr < LhsT, RhsT const &> const { 2385return { static_cast < bool > (m_lhs ^ rhs), m_lhs, "^" , rhs }; 2386} 2387 2388template < typename RhsT > 2389auto operator && ( RhsT const & ) -> BinaryExpr < LhsT, RhsT const &> const { 2390static_assert (always_false < RhsT > ::value, 2391"operator&& is not supported inside assertions, " 2392"wrap the expression inside parentheses, or decompose it" ); 2393} 2394 2395template < typename RhsT > 2396auto operator || ( RhsT const & ) -> BinaryExpr < LhsT, RhsT const &> const { 2397static_assert (always_false < RhsT > ::value, 2398"operator|| is not supported inside assertions, " 2399"wrap the expression inside parentheses, or decompose it" ); 2400} 2401 2402auto makeUnaryExpr() const -> UnaryExpr < LhsT > { 2403return UnaryExpr < LhsT > { m_lhs }; 2404} 2405}; 2406 2407void handleExpression ( ITransientExpression const & expr ); 2408 2409template < typename T > 2410void handleExpression ( ExprLhs < T > const & expr ) { 2411handleExpression ( expr. makeUnaryExpr () ); 2412} 2413 2414struct Decomposer { 2415template < typename T > 2416auto operator <= ( T const & lhs ) -> ExprLhs < T const &> { 2417return ExprLhs < T const &> { lhs }; 2418} 2419 2420auto operator <=( bool value ) -> ExprLhs < bool > { 2421return ExprLhs < bool > { value }; 2422} 2423}; 2424 2425} // end namespace Catch 2426 2427#ifdef _MSC_VER 2428#pragma warning(pop) 2429#endif 2430 2431// end catch_decomposer.h 2432// start catch_interfaces_capture.h 2433 2434#include <string> 2435#include <chrono> 2436 2437namespace Catch { 2438 2439class AssertionResult; 2440struct AssertionInfo ; 2441struct SectionInfo ; 2442struct SectionEndInfo ; 2443struct MessageInfo ; 2444struct MessageBuilder ; 2445struct Counts ; 2446struct AssertionReaction ; 2447struct SourceLineInfo ; 2448 2449struct ITransientExpression ; 2450struct IGeneratorTracker ; 2451 2452#if defined( CATCH_CONFIG_ENABLE_BENCHMARKING ) 2453struct BenchmarkInfo ; 2454template < typename Duration = std:: chrono ::duration < double, std::nano>> 2455struct BenchmarkStats; 2456#endif // CATCH_CONFIG_ENABLE_BENCHMARKING 2457 2458struct IResultCapture { 2459 2460virtual ~ IResultCapture (); 2461 2462virtual bool sectionStarted ( SectionInfo const & sectionInfo, 2463Counts & assertions ) = 0 ; 2464virtual void sectionEnded ( SectionEndInfo const & endInfo ) = 0 ; 2465virtual void sectionEndedEarly ( SectionEndInfo const & endInfo ) = 0 ; 2466 2467virtual auto acquireGeneratorTracker ( StringRef generatorName, SourceLineInfo const & lineInfo ) -> IGeneratorTracker & = 0 ; 2468 2469#if defined( CATCH_CONFIG_ENABLE_BENCHMARKING ) 2470virtual void benchmarkPreparing ( std ::string const & name ) = 0 ; 2471virtual void benchmarkStarting ( BenchmarkInfo const & info ) = 0 ; 2472virtual void benchmarkEnded ( BenchmarkStats <> const & stats ) = 0 ; 2473virtual void benchmarkFailed ( std ::string const & error ) = 0 ; 2474#endif // CATCH_CONFIG_ENABLE_BENCHMARKING 2475 2476virtual void pushScopedMessage ( MessageInfo const & message ) = 0 ; 2477virtual void popScopedMessage ( MessageInfo const & message ) = 0 ; 2478 2479virtual void emplaceUnscopedMessage ( MessageBuilder const & builder ) = 0 ; 2480 2481virtual void handleFatalErrorCondition ( StringRef message ) = 0 ; 2482 2483virtual void handleExpr 2484( AssertionInfo const & info, 2485ITransientExpression const & expr, 2486AssertionReaction & reaction ) = 0 ; 2487virtual void handleMessage 2488( AssertionInfo const & info, 2489ResultWas ::OfType resultType, 2490StringRef const & message, 2491AssertionReaction & reaction ) = 0 ; 2492virtual void handleUnexpectedExceptionNotThrown 2493( AssertionInfo const & info, 2494AssertionReaction & reaction ) = 0 ; 2495virtual void handleUnexpectedInflightException 2496( AssertionInfo const & info, 2497std ::string const & message, 2498AssertionReaction & reaction ) = 0 ; 2499virtual void handleIncomplete 2500( AssertionInfo const & info ) = 0 ; 2501virtual void handleNonExpr 2502( AssertionInfo const & info, 2503ResultWas ::OfType resultType, 2504AssertionReaction & reaction ) = 0 ; 2505 2506virtual bool lastAssertionPassed () = 0 ; 2507virtual void assertionPassed () = 0 ; 2508 2509// Deprecated, do not use: 2510virtual std ::string getCurrentTestName () const = 0 ; 2511virtual const AssertionResult * getLastResult () const = 0 ; 2512virtual void exceptionEarlyReported () = 0 ; 2513}; 2514 2515IResultCapture & getResultCapture (); 2516} 2517 2518// end catch_interfaces_capture.h 2519namespace Catch { 2520 2521struct TestFailureException {}; 2522struct AssertionResultData ; 2523struct IResultCapture ; 2524class RunContext; 2525 2526class LazyExpression { 2527friend class AssertionHandler; 2528friend struct AssertionStats; 2529friend class RunContext; 2530 2531ITransientExpression const * m_transientExpression = nullptr ; 2532bool m_isNegated; 2533public : 2534LazyExpression( bool isNegated ); 2535LazyExpression ( LazyExpression const & other ); 2536LazyExpression & operator = ( LazyExpression const & ) = delete; 2537 2538explicit operator bool () const ; 2539 2540friend auto operator << ( std ::ostream & os, LazyExpression const & lazyExpr ) -> std::ostream & ; 2541}; 2542 2543struct AssertionReaction { 2544bool shouldDebugBreak = false; 2545bool shouldThrow = false; 2546}; 2547 2548class AssertionHandler { 2549AssertionInfo m_assertionInfo; 2550AssertionReaction m_reaction; 2551bool m_completed = false; 2552IResultCapture & m_resultCapture; 2553 2554public : 2555AssertionHandler 2556( StringRef const & macroName, 2557SourceLineInfo const & lineInfo, 2558StringRef capturedExpression, 2559ResultDisposition::Flags resultDisposition ); 2560~ AssertionHandler () { 2561if ( !m_completed ) { 2562m_resultCapture. handleIncomplete ( m_assertionInfo ); 2563} 2564} 2565 2566template < typename T > 2567void handleExpr ( ExprLhs < T > const & expr ) { 2568handleExpr ( expr. makeUnaryExpr () ); 2569} 2570void handleExpr ( ITransientExpression const & expr ); 2571 2572void handleMessage ( ResultWas ::OfType resultType, StringRef const & message); 2573 2574void handleExceptionThrownAsExpected (); 2575void handleUnexpectedExceptionNotThrown (); 2576void handleExceptionNotThrownAsExpected (); 2577void handleThrowingCallSkipped (); 2578void handleUnexpectedInflightException (); 2579 2580void complete (); 2581void setCompleted (); 2582 2583// query 2584auto allowThrows() const -> bool ; 2585}; 2586 2587void handleExceptionMatchExpr ( AssertionHandler & handler, std ::string const & str, StringRef const & matcherString ); 2588 2589} // namespace Catch 2590 2591// end catch_assertionhandler.h 2592// start catch_message.h 2593 2594#include <string> 2595#include <vector> 2596 2597namespace Catch { 2598 2599struct MessageInfo { 2600MessageInfo( StringRef const & _macroName, 2601SourceLineInfo const & _lineInfo , 2602ResultWas :: OfType _type ); 2603 2604StringRef macroName ; 2605std :: string message ; 2606SourceLineInfo lineInfo ; 2607ResultWas :: OfType type ; 2608unsigned int sequence ; 2609 2610bool operator == ( MessageInfo const & other ) const; 2611bool operator < ( MessageInfo const & other ) const; 2612private : 2613static unsigned int globalCount ; 2614}; 2615 2616struct MessageStream { 2617 2618template < typename T > 2619MessageStream & operator << ( T const & value ) { 2620m_stream << value ; 2621return * this ; 2622} 2623 2624ReusableStringStream m_stream; 2625}; 2626 2627struct MessageBuilder : MessageStream { 2628MessageBuilder( StringRef const & macroName, 2629SourceLineInfo const & lineInfo, 2630ResultWas::OfType type ); 2631 2632template < typename T > 2633MessageBuilder & operator << ( T const & value ) { 2634m_stream << value; 2635return * this; 2636} 2637 2638MessageInfo m_info; 2639}; 2640 2641class ScopedMessage { 2642public : 2643explicit ScopedMessage ( MessageBuilder const & builder ); 2644ScopedMessage ( ScopedMessage & duplicate ) = delete; 2645ScopedMessage ( ScopedMessage && old ); 2646~ ScopedMessage (); 2647 2648MessageInfo m_info; 2649bool m_moved; 2650}; 2651 2652class Capturer { 2653std ::vector < MessageInfo > m_messages; 2654IResultCapture & m_resultCapture = getResultCapture (); 2655size_t m_captured = 0 ; 2656public : 2657Capturer( StringRef macroName, SourceLineInfo const & lineInfo, ResultWas::OfType resultType, StringRef names ); 2658~ Capturer (); 2659 2660void captureValue ( size_t index, std ::string const & value ); 2661 2662template < typename T > 2663void captureValues ( size_t index, T const & value ) { 2664captureValue ( index, Catch::Detail:: stringify ( value ) ); 2665} 2666 2667template < typename T , typename... Ts > 2668void captureValues ( size_t index, T const & value, Ts const & ... values ) { 2669captureValue ( index, Catch::Detail:: stringify (value) ); 2670captureValues ( index + 1 , values... ); 2671} 2672}; 2673 2674} // end namespace Catch 2675 2676// end catch_message.h 2677#if !defined( CATCH_CONFIG_DISABLE ) 2678 2679#if !defined( CATCH_CONFIG_DISABLE_STRINGIFICATION ) 2680#define CATCH_INTERNAL_STRINGIFY (...) #__VA_ARGS__ 2681#else 2682#define CATCH_INTERNAL_STRINGIFY (...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION" 2683#endif 2684 2685#if defined( CATCH_CONFIG_FAST_COMPILE ) || defined( CATCH_CONFIG_DISABLE_EXCEPTIONS ) 2686 2687/////////////////////////////////////////////////////////////////////////////// 2688// Another way to speed-up compilation is to omit local try-catch for REQUIRE* 2689// macros. 2690#define INTERNAL_CATCH_TRY 2691#define INTERNAL_CATCH_CATCH ( capturer ) 2692 2693#else // CATCH_CONFIG_FAST_COMPILE 2694 2695#define INTERNAL_CATCH_TRY try 2696#define INTERNAL_CATCH_CATCH ( handler ) catch(...) { handler.handleUnexpectedInflightException(); } 2697 2698#endif 2699 2700#define INTERNAL_CATCH_REACT ( handler ) handler.complete(); 2701 2702/////////////////////////////////////////////////////////////////////////////// 2703#define INTERNAL_CATCH_TEST ( macroName, resultDisposition, ... ) \ 2704do { \ 2705CATCH_INTERNAL_IGNORE_BUT_WARN(__VA_ARGS__); \ 2706Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ 2707INTERNAL_CATCH_TRY { \ 2708CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 2709CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ 2710catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); \ 2711CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 2712} INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ 2713INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2714} while( (void)0, (false) && static_cast<bool>( !!(__VA_ARGS__) ) ) 2715 2716/////////////////////////////////////////////////////////////////////////////// 2717#define INTERNAL_CATCH_IF ( macroName, resultDisposition, ... ) \ 2718INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \ 2719if( Catch::getResultCapture().lastAssertionPassed() ) 2720 2721/////////////////////////////////////////////////////////////////////////////// 2722#define INTERNAL_CATCH_ELSE ( macroName, resultDisposition, ... ) \ 2723INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \ 2724if( !Catch::getResultCapture().lastAssertionPassed() ) 2725 2726/////////////////////////////////////////////////////////////////////////////// 2727#define INTERNAL_CATCH_NO_THROW ( macroName, resultDisposition, ... ) \ 2728do { \ 2729Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ 2730try { \ 2731static_cast<void>(__VA_ARGS__); \ 2732catchAssertionHandler.handleExceptionNotThrownAsExpected(); \ 2733} \ 2734catch( ... ) { \ 2735catchAssertionHandler.handleUnexpectedInflightException(); \ 2736} \ 2737INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2738} while( false ) 2739 2740/////////////////////////////////////////////////////////////////////////////// 2741#define INTERNAL_CATCH_THROWS ( macroName, resultDisposition, ... ) \ 2742do { \ 2743Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \ 2744if( catchAssertionHandler.allowThrows() ) \ 2745try { \ 2746static_cast<void>(__VA_ARGS__); \ 2747catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 2748} \ 2749catch( ... ) { \ 2750catchAssertionHandler.handleExceptionThrownAsExpected(); \ 2751} \ 2752else \ 2753catchAssertionHandler.handleThrowingCallSkipped(); \ 2754INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2755} while( false ) 2756 2757/////////////////////////////////////////////////////////////////////////////// 2758#define INTERNAL_CATCH_THROWS_AS ( macroName, exceptionType, resultDisposition, expr ) \ 2759do { \ 2760Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \ 2761if( catchAssertionHandler.allowThrows() ) \ 2762try { \ 2763static_cast<void>(expr); \ 2764catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 2765} \ 2766catch( exceptionType const& ) { \ 2767catchAssertionHandler.handleExceptionThrownAsExpected(); \ 2768} \ 2769catch( ... ) { \ 2770catchAssertionHandler.handleUnexpectedInflightException(); \ 2771} \ 2772else \ 2773catchAssertionHandler.handleThrowingCallSkipped(); \ 2774INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2775} while( false ) 2776 2777/////////////////////////////////////////////////////////////////////////////// 2778#define INTERNAL_CATCH_MSG ( macroName, messageType, resultDisposition, ... ) \ 2779do { \ 2780Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::StringRef(), resultDisposition ); \ 2781catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \ 2782INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2783} while( false ) 2784 2785/////////////////////////////////////////////////////////////////////////////// 2786#define INTERNAL_CATCH_CAPTURE ( varName, macroName, ... ) \ 2787auto varName = Catch::Capturer( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info, #__VA_ARGS__ ); \ 2788varName.captureValues( 0, __VA_ARGS__ ) 2789 2790/////////////////////////////////////////////////////////////////////////////// 2791#define INTERNAL_CATCH_INFO ( macroName, log ) \ 2792Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log ); 2793 2794/////////////////////////////////////////////////////////////////////////////// 2795#define INTERNAL_CATCH_UNSCOPED_INFO ( macroName, log ) \ 2796Catch::getResultCapture().emplaceUnscopedMessage( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log ) 2797 2798/////////////////////////////////////////////////////////////////////////////// 2799// Although this is matcher-based, it can be used with just a string 2800#define INTERNAL_CATCH_THROWS_STR_MATCHES ( macroName, resultDisposition, matcher, ... ) \ 2801do { \ 2802Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ 2803if( catchAssertionHandler.allowThrows() ) \ 2804try { \ 2805static_cast<void>(__VA_ARGS__); \ 2806catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 2807} \ 2808catch( ... ) { \ 2809Catch::handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher##_catch_sr ); \ 2810} \ 2811else \ 2812catchAssertionHandler.handleThrowingCallSkipped(); \ 2813INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2814} while( false ) 2815 2816#endif // CATCH_CONFIG_DISABLE 2817 2818// end catch_capture.hpp 2819// start catch_section.h 2820 2821// start catch_section_info.h 2822 2823// start catch_totals.h 2824 2825#include <cstddef> 2826 2827namespace Catch { 2828 2829struct Counts { 2830Counts operator - ( Counts const & other ) const; 2831Counts & operator += ( Counts const & other ); 2832 2833std :: size_t total () const; 2834bool allPassed () const; 2835bool allOk () const; 2836 2837std :: size_t passed = 0 ; 2838std :: size_t failed = 0 ; 2839std :: size_t failedButOk = 0 ; 2840}; 2841 2842struct Totals { 2843 2844Totals operator - ( Totals const & other ) const; 2845Totals & operator += ( Totals const & other ); 2846 2847Totals delta ( Totals const & prevTotals ) const; 2848 2849int error = 0 ; 2850Counts assertions ; 2851Counts testCases ; 2852}; 2853} 2854 2855// end catch_totals.h 2856#include <string> 2857 2858namespace Catch { 2859 2860struct SectionInfo { 2861SectionInfo 2862( SourceLineInfo const & _lineInfo, 2863std :: string const & _name ); 2864 2865// Deprecated 2866SectionInfo 2867( SourceLineInfo const & _lineInfo, 2868std :: string const & _name , 2869std :: string const & ) : SectionInfo ( _lineInfo , _name ) {} 2870 2871std ::string name; 2872std :: string description ; // !Deprecated: this will always be empty 2873SourceLineInfo lineInfo ; 2874}; 2875 2876struct SectionEndInfo { 2877SectionInfo sectionInfo ; 2878Counts prevAssertions ; 2879double durationInSeconds ; 2880}; 2881 2882} // end namespace Catch 2883 2884// end catch_section_info.h 2885// start catch_timer.h 2886 2887#include <cstdint> 2888 2889namespace Catch { 2890 2891auto getCurrentNanosecondsSinceEpoch() -> uint64_t ; 2892auto getEstimatedClockResolution () -> uint64_t ; 2893 2894class Timer { 2895uint64_t m_nanoseconds = 0 ; 2896public : 2897void start (); 2898auto getElapsedNanoseconds() const -> uint64_t ; 2899auto getElapsedMicroseconds () const -> uint64_t ; 2900auto getElapsedMilliseconds () const -> unsigned int ; 2901auto getElapsedSeconds () const -> double ; 2902}; 2903 2904} // namespace Catch 2905 2906// end catch_timer.h 2907#include <string> 2908 2909namespace Catch { 2910 2911class Section : NonCopyable { 2912public : 2913Section( SectionInfo const & info ); 2914~ Section (); 2915 2916// This indicates whether the section should be executed or not 2917explicit operator bool () const ; 2918 2919private : 2920SectionInfo m_info; 2921 2922std :: string m_name; 2923Counts m_assertions; 2924bool m_sectionIncluded; 2925Timer m_timer; 2926}; 2927 2928} // end namespace Catch 2929 2930#define INTERNAL_CATCH_SECTION ( ... ) \ 2931CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 2932CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ 2933if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \ 2934CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 2935 2936#define INTERNAL_CATCH_DYNAMIC_SECTION ( ... ) \ 2937CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 2938CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ 2939if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, (Catch::ReusableStringStream() << __VA_ARGS__).str() ) ) \ 2940CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 2941 2942// end catch_section.h 2943// start catch_interfaces_exception.h 2944 2945// start catch_interfaces_registry_hub.h 2946 2947#include <string> 2948#include <memory> 2949 2950namespace Catch { 2951 2952class TestCase; 2953struct ITestCaseRegistry ; 2954struct IExceptionTranslatorRegistry ; 2955struct IExceptionTranslator ; 2956struct IReporterRegistry ; 2957struct IReporterFactory ; 2958struct ITagAliasRegistry ; 2959struct IMutableEnumValuesRegistry ; 2960 2961class StartupExceptionRegistry; 2962 2963using IReporterFactoryPtr = std::shared_ptr < IReporterFactory > ; 2964 2965struct IRegistryHub { 2966virtual ~ IRegistryHub (); 2967 2968virtual IReporterRegistry const & getReporterRegistry () const = 0 ; 2969virtual ITestCaseRegistry const & getTestCaseRegistry () const = 0 ; 2970virtual ITagAliasRegistry const & getTagAliasRegistry () const = 0 ; 2971virtual IExceptionTranslatorRegistry const & getExceptionTranslatorRegistry () const = 0 ; 2972 2973virtual StartupExceptionRegistry const & getStartupExceptionRegistry () const = 0 ; 2974}; 2975 2976struct IMutableRegistryHub { 2977virtual ~ IMutableRegistryHub (); 2978virtual void registerReporter ( std ::string const & name, IReporterFactoryPtr const & factory ) = 0 ; 2979virtual void registerListener ( IReporterFactoryPtr const & factory ) = 0 ; 2980virtual void registerTest ( TestCase const & testInfo ) = 0 ; 2981virtual void registerTranslator ( const IExceptionTranslator * translator ) = 0 ; 2982virtual void registerTagAlias ( std ::string const & alias, std ::string const & tag, SourceLineInfo const & lineInfo ) = 0 ; 2983virtual void registerStartupException () noexcept = 0 ; 2984virtual IMutableEnumValuesRegistry & getMutableEnumValuesRegistry () = 0 ; 2985}; 2986 2987IRegistryHub const & getRegistryHub (); 2988IMutableRegistryHub & getMutableRegistryHub (); 2989void cleanUp (); 2990std :: string translateActiveException (); 2991 2992} 2993 2994// end catch_interfaces_registry_hub.h 2995#if defined( CATCH_CONFIG_DISABLE ) 2996#define INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG ( translatorName, signature) \ 2997static std::string translatorName( signature ) 2998#endif 2999 3000#include <exception> 3001#include <string> 3002#include <vector> 3003 3004namespace Catch { 3005using exceptionTranslateFunction = std:: string ( * )(); 3006 3007struct IExceptionTranslator ; 3008using ExceptionTranslators = std::vector < std::unique_ptr < IExceptionTranslator const>>; 3009 3010struct IExceptionTranslator { 3011virtual ~ IExceptionTranslator (); 3012virtual std ::string translate ( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0 ; 3013}; 3014 3015struct IExceptionTranslatorRegistry { 3016virtual ~ IExceptionTranslatorRegistry (); 3017 3018virtual std ::string translateActiveException () const = 0 ; 3019}; 3020 3021class ExceptionTranslatorRegistrar { 3022template < typename T > 3023class ExceptionTranslator : public IExceptionTranslator { 3024public : 3025 3026ExceptionTranslator ( std :: string ( * translateFunction)( T & ) ) 3027: m_translateFunction( translateFunction ) 3028{} 3029 3030std :: string translate( ExceptionTranslators :: const_iterator it, ExceptionTranslators:: const_iterator itEnd ) const override { 3031#if defined( CATCH_CONFIG_DISABLE_EXCEPTIONS ) 3032return "" ; 3033#else 3034try { 3035if ( it == itEnd ) 3036std ::rethrow_exception( std :: current_exception ()); 3037else 3038return ( * it) -> translate ( it + 1 , itEnd ); 3039} 3040catch ( T & ex ) { 3041return m_translateFunction ( ex ); 3042} 3043#endif 3044} 3045 3046protected : 3047std :: string ( * m_translateFunction)( T & ); 3048}; 3049 3050public : 3051template < typename T > 3052ExceptionTranslatorRegistrar ( std:: string ( * translateFunction)( T & ) ) { 3053getMutableRegistryHub (). registerTranslator 3054( new ExceptionTranslator < T > ( translateFunction ) ); 3055} 3056}; 3057} 3058 3059/////////////////////////////////////////////////////////////////////////////// 3060#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2 ( translatorName, signature ) \ 3061static std::string translatorName( signature ); \ 3062CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 3063CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 3064namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); } \ 3065CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 3066static std::string translatorName( signature ) 3067 3068#define INTERNAL_CATCH_TRANSLATE_EXCEPTION ( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) 3069 3070// end catch_interfaces_exception.h 3071// start catch_approx.h 3072 3073#include <type_traits> 3074 3075namespace Catch { 3076namespace Detail { 3077 3078class Approx { 3079private : 3080bool equalityComparisonImpl ( double other) const; 3081// Validates the new margin (margin >= 0) 3082// out-of-line to avoid including stdexcept in the header 3083void setMargin ( double margin); 3084// Validates the new epsilon (0 < epsilon < 1) 3085// out-of-line to avoid including stdexcept in the header 3086void setEpsilon ( double epsilon); 3087 3088public : 3089explicit Approx ( double value ); 3090 3091static Approx custom (); 3092 3093Approx operator - ( ) const ; 3094 3095template < typename T , typename = typename std :: enable_if < std :: is_constructible < double , T > :: value > :: type > 3096Approx operator ()( T const & value ) const { 3097Approx approx ( static_cast < double > ( value ) ); 3098approx . m_epsilon = m_epsilon ; 3099approx . m_margin = m_margin ; 3100approx . m_scale = m_scale ; 3101return approx ; 3102} 3103 3104template < typename T , typename = typename std :: enable_if < std :: is_constructible < double , T > :: value > :: type > 3105explicit Approx ( T const & value ): Approx (static_cast < double > ( value )) 3106{} 3107 3108template < typename T , typename = typename std :: enable_if < std :: is_constructible < double , T > :: value > :: type > 3109friend bool operator == ( const T & lhs , Approx const & rhs ) { 3110auto lhs_v = static_cast < double > (lhs); 3111return rhs. equalityComparisonImpl (lhs_v); 3112} 3113 3114template < typename T , typename = typename std ::enable_if < std::is_constructible < double, T > ::value > ::type > 3115friend bool operator == ( Approx const & lhs, const T & rhs ) { 3116return operator == ( rhs, lhs ); 3117} 3118 3119template < typename T , typename = typename std ::enable_if < std::is_constructible < double, T > ::value > ::type > 3120friend bool operator != ( T const & lhs, Approx const & rhs ) { 3121return !operator == ( lhs, rhs ); 3122} 3123 3124template < typename T , typename = typename std ::enable_if < std::is_constructible < double, T > ::value > ::type > 3125friend bool operator != ( Approx const & lhs, T const & rhs ) { 3126return !operator == ( rhs, lhs ); 3127} 3128 3129template < typename T , typename = typename std ::enable_if < std::is_constructible < double, T > ::value > ::type > 3130friend bool operator <= ( T const & lhs, Approx const & rhs ) { 3131return static_cast < double > (lhs) < rhs. m_value || lhs == rhs; 3132} 3133 3134template < typename T , typename = typename std ::enable_if < std::is_constructible < double, T > ::value > ::type > 3135friend bool operator <= ( Approx const & lhs, T const & rhs ) { 3136return lhs. m_value < static_cast < double > (rhs) || lhs == rhs; 3137} 3138 3139template < typename T , typename = typename std ::enable_if < std::is_constructible < double, T > ::value > ::type > 3140friend bool operator >= ( T const & lhs, Approx const & rhs ) { 3141return static_cast < double > (lhs) > rhs. m_value || lhs == rhs; 3142} 3143 3144template < typename T , typename = typename std ::enable_if < std::is_constructible < double, T > ::value > ::type > 3145friend bool operator >= ( Approx const & lhs, T const & rhs ) { 3146return lhs. m_value > static_cast < double > (rhs) || lhs == rhs; 3147} 3148 3149template < typename T , typename = typename std ::enable_if < std::is_constructible < double, T > ::value > ::type > 3150Approx & epsilon ( T const & newEpsilon ) { 3151double epsilonAsDouble = static_cast < double > (newEpsilon); 3152setEpsilon (epsilonAsDouble); 3153return * this; 3154} 3155 3156template < typename T , typename = typename std ::enable_if < std::is_constructible < double, T > ::value > ::type > 3157Approx & margin ( T const & newMargin ) { 3158double marginAsDouble = static_cast < double > (newMargin); 3159setMargin (marginAsDouble); 3160return * this; 3161} 3162 3163template < typename T , typename = typename std ::enable_if < std::is_constructible < double, T > ::value > ::type > 3164Approx & scale ( T const & newScale ) { 3165m_scale = static_cast < double > (newScale); 3166return * this; 3167} 3168 3169std :: string toString () const; 3170 3171private : 3172double m_epsilon; 3173double m_margin; 3174double m_scale; 3175double m_value; 3176}; 3177} // end namespace Detail 3178 3179namespace literals { 3180Detail :: Approx operator "" _a(long double val); 3181Detail :: Approx operator "" _a(unsigned long long val); 3182} // end namespace literals 3183 3184template <> 3185struct StringMaker < Catch::Detail::Approx > { 3186static std ::string convert ( Catch ::Detail::Approx const & value); 3187}; 3188 3189} // end namespace Catch 3190 3191// end catch_approx.h 3192// start catch_string_manip.h 3193 3194#include <string> 3195#include <iosfwd> 3196#include <vector> 3197 3198namespace Catch { 3199 3200bool startsWith ( std ::string const & s, std ::string const & prefix ); 3201bool startsWith ( std ::string const & s, char prefix ); 3202bool endsWith ( std ::string const & s, std ::string const & suffix ); 3203bool endsWith ( std ::string const & s, char suffix ); 3204bool contains ( std ::string const & s, std ::string const & infix ); 3205void toLowerInPlace ( std ::string & s ); 3206std :: string toLower( std :: string const & s ); 3207//! Returns a new string without whitespace at the start/end 3208std :: string trim( std :: string const & str ); 3209//! Returns a substring of the original ref without whitespace. Beware lifetimes! 3210StringRef trim ( StringRef ref); 3211 3212// !!! Be aware, returns refs into original string - make sure original string outlives them 3213std ::vector < StringRef > splitStringRef ( StringRef str, char delimiter ); 3214bool replaceInPlace ( std ::string & str, std ::string const & replaceThis, std ::string const & withThis ); 3215 3216struct pluralise { 3217pluralise( std :: size_t count , std ::string const & label ); 3218 3219friend std ::ostream & operator << ( std::ostream & os, pluralise const & pluraliser ); 3220 3221std :: size_t m_count ; 3222std :: string m_label ; 3223}; 3224} 3225 3226// end catch_string_manip.h 3227#ifndef CATCH_CONFIG_DISABLE_MATCHERS 3228// start catch_capture_matchers.h 3229 3230// start catch_matchers.h 3231 3232#include <string> 3233#include <vector> 3234 3235namespace Catch { 3236namespace Matchers { 3237namespace Impl { 3238 3239template < typename ArgT > struct MatchAllOf; 3240template < typename ArgT > struct MatchAnyOf; 3241template < typename ArgT > struct MatchNotOf; 3242 3243class MatcherUntypedBase { 3244public : 3245MatcherUntypedBase () = default; 3246MatcherUntypedBase ( MatcherUntypedBase const & ) = default; 3247MatcherUntypedBase & operator = ( MatcherUntypedBase const & ) = delete; 3248std :: string toString () const; 3249 3250protected : 3251virtual ~ MatcherUntypedBase (); 3252virtual std::string describe () const = 0 ; 3253mutable std::string m_cachedToString; 3254}; 3255 3256#ifdef __clang__ 3257# pragma clang diagnostic push 3258# pragma clang diagnostic ignored "-Wnon-virtual-dtor" 3259#endif 3260 3261template < typename ObjectT > 3262struct MatcherMethod { 3263virtual bool match ( ObjectT const & arg ) const = 0 ; 3264}; 3265 3266#if defined(__OBJC__) 3267// Hack to fix Catch GH issue #1661. Could use id for generic Object support. 3268// use of const for Object pointers is very uncommon and under ARC it causes some kind of signature mismatch that breaks compilation 3269template <> 3270struct MatcherMethod < NSString *> { 3271virtual bool match ( NSString * arg ) const = 0 ; 3272}; 3273#endif 3274 3275#ifdef __clang__ 3276# pragma clang diagnostic pop 3277#endif 3278 3279template < typename T > 3280struct MatcherBase : MatcherUntypedBase, MatcherMethod < T > { 3281 3282MatchAllOf < T > operator && ( MatcherBase const & other ) const; 3283MatchAnyOf < T > operator || ( MatcherBase const & other ) const; 3284MatchNotOf < T > operator ! () const; 3285}; 3286 3287template < typename ArgT > 3288struct MatchAllOf : MatcherBase < ArgT > { 3289bool match ( ArgT const & arg ) const override { 3290for ( auto matcher : m_matchers ) { 3291if (!matcher -> match (arg)) 3292return false; 3293} 3294return true; 3295} 3296std :: string describe () const override { 3297std :: string description; 3298description. reserve ( 4 + m_matchers. size () * 32 ); 3299description += "( " ; 3300bool first = true; 3301for ( auto matcher : m_matchers ) { 3302if ( first ) 3303first = false; 3304else 3305description += " and " ; 3306description += matcher -> toString (); 3307} 3308description += " )" ; 3309return description; 3310} 3311 3312MatchAllOf < ArgT > operator && ( MatcherBase < ArgT > const & other ) { 3313auto copy ( * this); 3314copy. m_matchers . push_back ( & other ); 3315return copy; 3316} 3317 3318std::vector < MatcherBase < ArgT > const *> m_matchers; 3319}; 3320template < typename ArgT > 3321struct MatchAnyOf : MatcherBase < ArgT > { 3322 3323bool match ( ArgT const & arg ) const override { 3324for ( auto matcher : m_matchers ) { 3325if (matcher -> match (arg)) 3326return true; 3327} 3328return false; 3329} 3330std :: string describe () const override { 3331std :: string description; 3332description. reserve ( 4 + m_matchers. size () * 32 ); 3333description += "( " ; 3334bool first = true; 3335for ( auto matcher : m_matchers ) { 3336if ( first ) 3337first = false; 3338else 3339description += " or " ; 3340description += matcher -> toString (); 3341} 3342description += " )" ; 3343return description; 3344} 3345 3346MatchAnyOf < ArgT > operator || ( MatcherBase < ArgT > const & other ) { 3347auto copy ( * this); 3348copy. m_matchers . push_back ( & other ); 3349return copy; 3350} 3351 3352std::vector < MatcherBase < ArgT > const *> m_matchers; 3353}; 3354 3355template < typename ArgT > 3356struct MatchNotOf : MatcherBase < ArgT > { 3357 3358MatchNotOf ( MatcherBase < ArgT > const & underlyingMatcher ) : m_underlyingMatcher ( underlyingMatcher ) {} 3359 3360bool match ( ArgT const & arg ) const override { 3361return !m_underlyingMatcher. match ( arg ); 3362} 3363 3364std::string describe () const override { 3365return "not " + m_underlyingMatcher. toString (); 3366} 3367MatcherBase < ArgT > const & m_underlyingMatcher; 3368}; 3369 3370template < typename T > 3371MatchAllOf < T > MatcherBase < T > ::operator && ( MatcherBase const & other ) const { 3372return MatchAllOf < T > () && * this && other; 3373} 3374template < typename T > 3375MatchAnyOf < T > MatcherBase < T > ::operator || ( MatcherBase const & other ) const { 3376return MatchAnyOf < T > () || * this || other; 3377} 3378template < typename T > 3379MatchNotOf < T > MatcherBase < T > :: operator ! () const { 3380return MatchNotOf < T > ( * this ); 3381} 3382 3383} // namespace Impl 3384 3385} // namespace Matchers 3386 3387using namespace Matchers; 3388using Matchers::Impl::MatcherBase; 3389 3390} // namespace Catch 3391 3392// end catch_matchers.h 3393// start catch_matchers_exception.hpp 3394 3395namespace Catch { 3396namespace Matchers { 3397namespace Exception { 3398 3399class ExceptionMessageMatcher : public MatcherBase < std::exception > { 3400std::string m_message; 3401public: 3402 3403ExceptionMessageMatcher (std::string const & message): 3404m_message (message) 3405{} 3406 3407bool match (std::exception const & ex) const override; 3408 3409std::string describe () const override; 3410}; 3411 3412} // namespace Exception 3413 3414Exception::ExceptionMessageMatcher Message (std::string const & message); 3415 3416} // namespace Matchers 3417} // namespace Catch 3418 3419// end catch_matchers_exception.hpp 3420// start catch_matchers_floating.h 3421 3422namespace Catch { 3423namespace Matchers { 3424 3425namespace Floating { 3426 3427enum class FloatingPointKind : uint8_t ; 3428 3429struct WithinAbsMatcher : MatcherBase < double > { 3430WithinAbsMatcher (double target, double margin); 3431bool match (double const & matchee) const override; 3432std::string describe () const override; 3433private: 3434double m_target; 3435double m_margin; 3436}; 3437 3438struct WithinUlpsMatcher : MatcherBase < double > { 3439WithinUlpsMatcher (double target, uint64_t ulps, FloatingPointKind baseType); 3440bool match (double const & matchee) const override; 3441std::string describe () const override; 3442private: 3443double m_target; 3444uint64_t m_ulps; 3445FloatingPointKind m_type; 3446}; 3447 3448// Given IEEE-754 format for floats and doubles, we can assume 3449// that float -> double promotion is lossless. Given this, we can 3450// assume that if we do the standard relative comparison of 3451// |lhs - rhs| <= epsilon * max(fabs(lhs), fabs(rhs)), then we get 3452// the same result if we do this for floats, as if we do this for 3453// doubles that were promoted from floats. 3454struct WithinRelMatcher : MatcherBase < double > { 3455WithinRelMatcher (double target, double epsilon); 3456bool match (double const & matchee) const override; 3457std::string describe () const override; 3458private: 3459double m_target; 3460double m_epsilon; 3461}; 3462 3463} // namespace Floating 3464 3465// The following functions create the actual matcher objects. 3466// This allows the types to be inferred 3467Floating::WithinUlpsMatcher WithinULP (double target, uint64_t maxUlpDiff); 3468Floating::WithinUlpsMatcher WithinULP (float target, uint64_t maxUlpDiff); 3469Floating::WithinAbsMatcher WithinAbs (double target, double margin); 3470Floating::WithinRelMatcher WithinRel (double target, double eps); 3471// defaults epsilon to 100*numeric_limits<double>::epsilon() 3472Floating::WithinRelMatcher WithinRel (double target); 3473Floating::WithinRelMatcher WithinRel (float target, float eps); 3474// defaults epsilon to 100*numeric_limits<float>::epsilon() 3475Floating::WithinRelMatcher WithinRel (float target); 3476 3477} // namespace Matchers 3478} // namespace Catch 3479 3480// end catch_matchers_floating.h 3481// start catch_matchers_generic.hpp 3482 3483#include < functional > 3484#include < string > 3485 3486namespace Catch { 3487namespace Matchers { 3488namespace Generic { 3489 3490namespace Detail { 3491std::string finalizeDescription (const std::string & desc); 3492} 3493 3494template < typename T > 3495class PredicateMatcher : public MatcherBase < T > { 3496std::function < bool ( T const & ) > m_predicate; 3497std::string m_description; 3498public: 3499 3500PredicateMatcher (std::function < bool ( T const & ) > const & elem, std::string const & descr) 3501: m_predicate (std:: move (elem)), 3502m_description (Detail:: finalizeDescription (descr)) 3503{} 3504 3505bool match ( T const & item ) const override { 3506return m_predicate (item); 3507} 3508 3509std::string describe() const override { 3510return m_description; 3511} 3512}; 3513 3514} // namespace Generic 3515 3516// The following functions create the actual matcher objects. 3517// The user has to explicitly specify type to the function, because 3518// inferring std::function<bool(T const&)> is hard (but possible) and 3519// requires a lot of TMP. 3520template < typename T > 3521Generic::PredicateMatcher < T > Predicate (std::function < bool ( T const & ) > const & predicate, std::string const & description = "" ) { 3522return Generic::PredicateMatcher < T > (predicate, description); 3523} 3524 3525} // namespace Matchers 3526} // namespace Catch 3527 3528// end catch_matchers_generic.hpp 3529// start catch_matchers_string.h 3530 3531#include <string> 3532 3533namespace Catch { 3534namespace Matchers { 3535 3536namespace StdString { 3537 3538struct CasedString 3539{ 3540CasedString( std :: string const & str , CaseSensitive :: Choice caseSensitivity ); 3541std :: string adjustString ( std ::string const & str ) const ; 3542std :: string caseSensitivitySuffix () const ; 3543 3544CaseSensitive :: Choice m_caseSensitivity ; 3545std :: string m_str ; 3546}; 3547 3548struct StringMatcherBase : MatcherBase < std::string > { 3549StringMatcherBase( std :: string const & operation, CasedString const & comparator ); 3550std :: string describe () const override; 3551 3552CasedString m_comparator; 3553std :: string m_operation; 3554}; 3555 3556struct EqualsMatcher : StringMatcherBase { 3557EqualsMatcher( CasedString const & comparator ); 3558bool match ( std ::string const & source ) const override; 3559}; 3560struct ContainsMatcher : StringMatcherBase { 3561ContainsMatcher( CasedString const & comparator ); 3562bool match ( std ::string const & source ) const override; 3563}; 3564struct StartsWithMatcher : StringMatcherBase { 3565StartsWithMatcher( CasedString const & comparator ); 3566bool match ( std ::string const & source ) const override; 3567}; 3568struct EndsWithMatcher : StringMatcherBase { 3569EndsWithMatcher( CasedString const & comparator ); 3570bool match ( std ::string const & source ) const override; 3571}; 3572 3573struct RegexMatcher : MatcherBase < std::string > { 3574RegexMatcher ( std :: string regex, CaseSensitive:: Choice caseSensitivity ); 3575bool match ( std ::string const & matchee ) const override; 3576std :: string describe () const override; 3577 3578private : 3579std :: string m_regex; 3580CaseSensitive :: Choice m_caseSensitivity; 3581}; 3582 3583} // namespace StdString 3584 3585// The following functions create the actual matcher objects. 3586// This allows the types to be inferred 3587 3588StdString :: EqualsMatcher Equals( std :: string const & str, CaseSensitive:: Choice caseSensitivity = CaseSensitive::Yes ); 3589StdString :: ContainsMatcher Contains( std :: string const & str, CaseSensitive:: Choice caseSensitivity = CaseSensitive::Yes ); 3590StdString :: EndsWithMatcher EndsWith( std :: string const & str, CaseSensitive:: Choice caseSensitivity = CaseSensitive::Yes ); 3591StdString :: StartsWithMatcher StartsWith( std :: string const & str, CaseSensitive:: Choice caseSensitivity = CaseSensitive::Yes ); 3592StdString :: RegexMatcher Matches( std :: string const & regex, CaseSensitive:: Choice caseSensitivity = CaseSensitive::Yes ); 3593 3594} // namespace Matchers 3595} // namespace Catch 3596 3597// end catch_matchers_string.h 3598// start catch_matchers_vector.h 3599 3600#include <algorithm> 3601 3602namespace Catch { 3603namespace Matchers { 3604 3605namespace Vector { 3606template < typename T , typename Alloc > 3607struct ContainsElementMatcher : MatcherBase < std::vector < T , Alloc>> { 3608 3609ContainsElementMatcher ( T const & comparator) : m_comparator( comparator ) {} 3610 3611bool match ( std ::vector < T , Alloc > const & v) const override { 3612for (auto const & el : v ) { 3613if ( el == m_comparator) { 3614return true; 3615} 3616} 3617return false; 3618} 3619 3620std :: string describe () const override { 3621return "Contains: " + ::Catch::Detail:: stringify ( m_comparator ); 3622} 3623 3624T const & m_comparator; 3625}; 3626 3627template < typename T , typename AllocComp, typename AllocMatch > 3628struct ContainsMatcher : MatcherBase < std::vector < T , AllocMatch>> { 3629 3630ContainsMatcher (std::vector < T , AllocComp > const & comparator) : m_comparator( comparator ) {} 3631 3632bool match ( std ::vector < T , AllocMatch > const & v) const override { 3633// !TBD: see note in EqualsMatcher 3634if (m_comparator. size () > v. size ()) 3635return false; 3636for (auto const & comparator : m_comparator) { 3637auto present = false; 3638for (const auto & el : v) { 3639if (el == comparator) { 3640present = true; 3641break ; 3642} 3643} 3644if (!present) { 3645return false; 3646} 3647} 3648return true; 3649} 3650std::string describe () const override { 3651return "Contains: " + ::Catch::Detail:: stringify ( m_comparator ); 3652} 3653 3654std::vector < T , AllocComp > const & m_comparator; 3655}; 3656 3657template < typename T , typename AllocComp, typename AllocMatch > 3658struct EqualsMatcher : MatcherBase < std::vector < T , AllocMatch>> { 3659 3660EqualsMatcher(std::vector < T , AllocComp > const & comparator) : m_comparator ( comparator ) {} 3661 3662bool match ( std ::vector < T , AllocMatch > const & v) const override { 3663// !TBD: This currently works if all elements can be compared using != 3664// - a more general approach would be via a compare template that defaults 3665// to using !=. but could be specialised for, e.g. std::vector<T, Alloc> etc 3666// - then just call that directly 3667if (m_comparator. size () != v. size ()) 3668return false; 3669for (std:: size_t i = 0 ; i < v. size (); ++ i) 3670if (m_comparator[i] != v[i]) 3671return false; 3672return true; 3673} 3674std :: string describe () const override { 3675return "Equals: " + ::Catch::Detail:: stringify ( m_comparator ); 3676} 3677std ::vector < T , AllocComp > const & m_comparator; 3678}; 3679 3680template < typename T , typename AllocComp, typename AllocMatch > 3681struct ApproxMatcher : MatcherBase < std::vector < T , AllocMatch>> { 3682 3683ApproxMatcher (std::vector < T , AllocComp > const & comparator) : m_comparator( comparator ) {} 3684 3685bool match ( std ::vector < T , AllocMatch > const & v) const override { 3686if (m_comparator. size () != v. size ()) 3687return false; 3688for (std:: size_t i = 0 ; i < v. size (); ++ i) 3689if (m_comparator[i] != approx (v[i])) 3690return false; 3691return true; 3692} 3693std :: string describe () const override { 3694return "is approx: " + ::Catch::Detail:: stringify ( m_comparator ); 3695} 3696template < typename = typename std ::enable_if < std::is_constructible < double, T > ::value > ::type > 3697ApproxMatcher & epsilon ( T const & newEpsilon ) { 3698approx. epsilon (newEpsilon); 3699return * this; 3700} 3701template < typename = typename std ::enable_if < std::is_constructible < double, T > ::value > ::type > 3702ApproxMatcher & margin ( T const & newMargin ) { 3703approx. margin (newMargin); 3704return * this; 3705} 3706template < typename = typename std ::enable_if < std::is_constructible < double, T > ::value > ::type > 3707ApproxMatcher & scale ( T const & newScale ) { 3708approx. scale (newScale); 3709return * this; 3710} 3711 3712std ::vector < T , AllocComp > const & m_comparator; 3713mutable Catch::Detail::Approx approx = Catch::Detail::Approx:: custom (); 3714}; 3715 3716template < typename T , typename AllocComp, typename AllocMatch > 3717struct UnorderedEqualsMatcher : MatcherBase < std::vector < T , AllocMatch>> { 3718UnorderedEqualsMatcher (std::vector < T , AllocComp > const & target) : m_target( target ) {} 3719bool match ( std ::vector < T , AllocMatch > const & vec) const override { 3720if (m_target. size () != vec. size ()) { 3721return false; 3722} 3723return std:: is_permutation (m_target. begin (), m_target. end (), vec. begin ()); 3724} 3725 3726std :: string describe () const override { 3727return "UnorderedEquals: " + ::Catch::Detail:: stringify (m_target); 3728} 3729private : 3730std ::vector < T , AllocComp > const & m_target; 3731}; 3732 3733} // namespace Vector 3734 3735// The following functions create the actual matcher objects. 3736// This allows the types to be inferred 3737 3738template < typename T , typename AllocComp = std::allocator < T > , typename AllocMatch = AllocComp > 3739Vector::ContainsMatcher < T , AllocComp, AllocMatch > Contains ( std::vector < T , AllocComp > const & comparator ) { 3740return Vector::ContainsMatcher < T , AllocComp, AllocMatch > ( comparator ); 3741} 3742 3743template < typename T , typename Alloc = std::allocator < T >> 3744Vector::ContainsElementMatcher < T , Alloc > VectorContains ( T const & comparator ) { 3745return Vector::ContainsElementMatcher < T , Alloc > ( comparator ); 3746} 3747 3748template < typename T , typename AllocComp = std::allocator < T > , typename AllocMatch = AllocComp > 3749Vector::EqualsMatcher < T , AllocComp, AllocMatch > Equals ( std::vector < T , AllocComp > const & comparator ) { 3750return Vector::EqualsMatcher < T , AllocComp, AllocMatch > ( comparator ); 3751} 3752 3753template < typename T , typename AllocComp = std::allocator < T > , typename AllocMatch = AllocComp > 3754Vector::ApproxMatcher < T , AllocComp, AllocMatch > Approx ( std::vector < T , AllocComp > const & comparator ) { 3755return Vector::ApproxMatcher < T , AllocComp, AllocMatch > ( comparator ); 3756} 3757 3758template < typename T , typename AllocComp = std::allocator < T > , typename AllocMatch = AllocComp > 3759Vector::UnorderedEqualsMatcher < T , AllocComp, AllocMatch > UnorderedEquals (std::vector < T , AllocComp > const & target) { 3760return Vector::UnorderedEqualsMatcher < T , AllocComp, AllocMatch > ( target ); 3761} 3762 3763} // namespace Matchers 3764} // namespace Catch 3765 3766// end catch_matchers_vector.h 3767namespace Catch { 3768 3769template < typename ArgT, typename MatcherT > 3770class MatchExpr : public ITransientExpression { 3771ArgT const & m_arg; 3772MatcherT m_matcher; 3773StringRef m_matcherString; 3774public : 3775MatchExpr( ArgT const & arg, MatcherT const & matcher, StringRef const & matcherString ) 3776: ITransientExpression{ true, matcher. match ( arg ) }, 3777m_arg ( arg ), 3778m_matcher ( matcher ), 3779m_matcherString ( matcherString ) 3780{} 3781 3782void streamReconstructedExpression ( std ::ostream & os ) const override { 3783auto matcherAsString = m_matcher. toString (); 3784os << Catch:: Detail :: stringify ( m_arg ) << ' ' ; 3785if ( matcherAsString == Detail::unprintableString ) 3786os << m_matcherString; 3787else 3788os << matcherAsString; 3789} 3790}; 3791 3792using StringMatcher = Matchers::Impl::MatcherBase < std::string > ; 3793 3794void handleExceptionMatchExpr ( AssertionHandler & handler, StringMatcher const & matcher, StringRef const & matcherString ); 3795 3796template < typename ArgT, typename MatcherT > 3797auto makeMatchExpr( ArgT const & arg, MatcherT const & matcher, StringRef const & matcherString ) -> MatchExpr < ArgT, MatcherT > { 3798return MatchExpr < ArgT, MatcherT > ( arg, matcher, matcherString ); 3799} 3800 3801} // namespace Catch 3802 3803/////////////////////////////////////////////////////////////////////////////// 3804#define INTERNAL_CHECK_THAT ( macroName, matcher, resultDisposition, arg ) \ 3805do { \ 3806Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ 3807INTERNAL_CATCH_TRY { \ 3808catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher, #matcher##_catch_sr ) ); \ 3809} INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ 3810INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 3811} while( false ) 3812 3813/////////////////////////////////////////////////////////////////////////////// 3814#define INTERNAL_CATCH_THROWS_MATCHES ( macroName, exceptionType, resultDisposition, matcher, ... ) \ 3815do { \ 3816Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ 3817if( catchAssertionHandler.allowThrows() ) \ 3818try { \ 3819static_cast<void>(__VA_ARGS__ ); \ 3820catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 3821} \ 3822catch( exceptionType const& ex ) { \ 3823catchAssertionHandler.handleExpr( Catch::makeMatchExpr( ex, matcher, #matcher##_catch_sr ) ); \ 3824} \ 3825catch( ... ) { \ 3826catchAssertionHandler.handleUnexpectedInflightException(); \ 3827} \ 3828else \ 3829catchAssertionHandler.handleThrowingCallSkipped(); \ 3830INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 3831} while( false ) 3832 3833// end catch_capture_matchers.h 3834#endif 3835// start catch_generators.hpp 3836 3837// start catch_interfaces_generatortracker.h 3838 3839 3840#include <memory> 3841 3842namespace Catch { 3843 3844namespace Generators { 3845class GeneratorUntypedBase { 3846public : 3847GeneratorUntypedBase () = default; 3848virtual ~ GeneratorUntypedBase (); 3849// Attempts to move the generator to the next element 3850// 3851// Returns true iff the move succeeded (and a valid element 3852// can be retrieved). 3853virtual bool next () = 0 ; 3854}; 3855using GeneratorBasePtr = std::unique_ptr < GeneratorUntypedBase > ; 3856 3857} // namespace Generators 3858 3859struct IGeneratorTracker { 3860virtual ~ IGeneratorTracker (); 3861virtual auto hasGenerator () const -> bool = 0 ; 3862virtual auto getGenerator () const -> Generators::GeneratorBasePtr const & = 0 ; 3863virtual void setGenerator ( Generators ::GeneratorBasePtr && generator ) = 0 ; 3864}; 3865 3866} // namespace Catch 3867 3868// end catch_interfaces_generatortracker.h 3869// start catch_enforce.h 3870 3871#include <exception> 3872 3873namespace Catch { 3874#if !defined( CATCH_CONFIG_DISABLE_EXCEPTIONS ) 3875template < typename Ex > 3876[[noreturn]] 3877void throw_exception ( Ex const & e) { 3878throw e; 3879} 3880#else // ^^ Exceptions are enabled // Exceptions are disabled vv 3881[[noreturn]] 3882void throw_exception ( std ::exception const & e); 3883#endif 3884 3885[[noreturn]] 3886void throw_logic_error ( std ::string const & msg); 3887[[noreturn]] 3888void throw_domain_error ( std ::string const & msg); 3889[[noreturn]] 3890void throw_runtime_error ( std ::string const & msg); 3891 3892} // namespace Catch; 3893 3894#define CATCH_MAKE_MSG (...) \ 3895(Catch::ReusableStringStream() << __VA_ARGS__).str() 3896 3897#define CATCH_INTERNAL_ERROR (...) \ 3898Catch::throw_logic_error(CATCH_MAKE_MSG( CATCH_INTERNAL_LINEINFO << ": Internal Catch2 error: " << __VA_ARGS__)) 3899 3900#define CATCH_ERROR (...) \ 3901Catch::throw_domain_error(CATCH_MAKE_MSG( __VA_ARGS__ )) 3902 3903#define CATCH_RUNTIME_ERROR (...) \ 3904Catch::throw_runtime_error(CATCH_MAKE_MSG( __VA_ARGS__ )) 3905 3906#define CATCH_ENFORCE ( condition, ... ) \ 3907do{ if( !(condition) ) CATCH_ERROR( __VA_ARGS__ ); } while(false) 3908 3909// end catch_enforce.h 3910#include <memory> 3911#include <vector> 3912#include <cassert> 3913 3914#include <utility> 3915#include <exception> 3916 3917namespace Catch { 3918 3919class GeneratorException : public std::exception { 3920const char * const m_msg = "" ; 3921 3922public : 3923GeneratorException( const char * msg): 3924m_msg ( msg ) 3925{} 3926 3927const char * what () const noexcept override final; 3928}; 3929 3930namespace Generators { 3931 3932// !TBD move this into its own location? 3933namespace pf{ 3934template < typename T , typename... Args > 3935std::unique_ptr < T > make_unique ( Args && ... args ) { 3936return std::unique_ptr < T > (new T ( std ::forward < Args > (args)...)); 3937} 3938} 3939 3940template < typename T > 3941struct IGenerator : GeneratorUntypedBase { 3942virtual ~ IGenerator () = default; 3943 3944// Returns the current element of the generator 3945// 3946// \Precondition The generator is either freshly constructed, 3947// or the last call to `next()` returned true 3948virtual T const & get () const = 0 ; 3949using type = T ; 3950}; 3951 3952template < typename T > 3953class SingleValueGenerator final : public IGenerator < T > { 3954T m_value; 3955public : 3956SingleValueGenerator ( T && value) : m_value ( std :: move (value)) {} 3957 3958T const & get () const override { 3959return m_value; 3960} 3961bool next () override { 3962return false; 3963} 3964}; 3965 3966template < typename T > 3967class FixedValuesGenerator final : public IGenerator < T > { 3968static_assert (!std::is_same < T , bool > ::value, 3969"FixedValuesGenerator does not support bools because of std::vector<bool>" 3970"specialization, use SingleValue Generator instead." ); 3971std ::vector < T > m_values; 3972size_t m_idx = 0 ; 3973public : 3974FixedValuesGenerator ( std ::initializer_list < T > values ) : m_values( values ) {} 3975 3976T const & get () const override { 3977return m_values[m_idx]; 3978} 3979bool next () override { 3980++ m_idx; 3981return m_idx < m_values. size (); 3982} 3983}; 3984 3985template < typename T > 3986class GeneratorWrapper final { 3987std ::unique_ptr < IGenerator < T >> m_generator; 3988public : 3989GeneratorWrapper ( std ::unique_ptr < IGenerator < T >> generator): 3990m_generator( std :: move ( generator )) 3991{} 3992T const & get () const { 3993return m_generator -> get (); 3994} 3995bool next () { 3996return m_generator -> next (); 3997} 3998}; 3999 4000template < typename T > 4001GeneratorWrapper < T > value ( T && value) { 4002return GeneratorWrapper < T > (pf::make_unique < SingleValueGenerator < T >>(std::forward < T > (value))); 4003} 4004template < typename T > 4005GeneratorWrapper < T > values (std::initializer_list < T > values) { 4006return GeneratorWrapper < T > (pf::make_unique < FixedValuesGenerator < T >>(values)); 4007} 4008 4009template < typename T > 4010class Generators : public IGenerator < T > { 4011std ::vector < GeneratorWrapper < T >> m_generators; 4012size_t m_current = 0 ; 4013 4014void populate ( GeneratorWrapper < T >&& generator) { 4015m_generators. emplace_back (std:: move (generator)); 4016} 4017void populate ( T && val) { 4018m_generators. emplace_back ( value (std::forward < T > (val))); 4019} 4020template < typename U > 4021void populate ( U && val) { 4022populate ( T (std::forward < U > (val))); 4023} 4024template < typename U , typename... Gs > 4025void populate ( U && valueOrGenerator, Gs && ... moreGenerators) { 4026populate (std::forward < U > (valueOrGenerator)); 4027populate ( std ::forward < Gs > (moreGenerators)...); 4028} 4029 4030public : 4031template < typename... Gs > 4032Generators (Gs && ... moreGenerators) { 4033m_generators. reserve ( sizeof ...(Gs)); 4034populate ( std ::forward < Gs > (moreGenerators)...); 4035} 4036 4037T const & get () const override { 4038return m_generators[m_current]. get (); 4039} 4040 4041bool next () override { 4042if (m_current >= m_generators. size ()) { 4043return false; 4044} 4045const bool current_status = m_generators[m_current]. next (); 4046if (!current_status) { 4047++ m_current; 4048} 4049return m_current < m_generators. size (); 4050} 4051}; 4052 4053template < typename... Ts > 4054GeneratorWrapper < std::tuple < Ts...>> table ( std::initializer_list < std::tuple < typename std::decay < Ts > ::type...>> tuples ) { 4055return values < std::tuple < Ts...>>( tuples ); 4056} 4057 4058// Tag type to signal that a generator sequence should convert arguments to a specific type 4059template < typename T > 4060struct as {}; 4061 4062template < typename T , typename... Gs > 4063auto makeGenerators ( GeneratorWrapper < T >&& generator, Gs && ... moreGenerators ) -> Generators < T > { 4064return Generators < T > (std:: move (generator), std::forward < Gs > (moreGenerators)...); 4065} 4066template < typename T > 4067auto makeGenerators ( GeneratorWrapper < T >&& generator ) -> Generators < T > { 4068return Generators < T > (std:: move (generator)); 4069} 4070template < typename T , typename... Gs > 4071auto makeGenerators ( T && val, Gs && ... moreGenerators ) -> Generators < T > { 4072return makeGenerators ( value ( std::forward < T > ( val ) ), std::forward < Gs > ( moreGenerators )... ); 4073} 4074template < typename T , typename U , typename... Gs > 4075auto makeGenerators ( as < T > , U && val, Gs && ... moreGenerators ) -> Generators < T > { 4076return makeGenerators ( value ( T ( std::forward < U > ( val ) ) ), std::forward < Gs > ( moreGenerators )... ); 4077} 4078 4079auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const & lineInfo ) -> IGeneratorTracker & ; 4080 4081template < typename L > 4082// Note: The type after -> is weird, because VS2015 cannot parse 4083// the expression used in the typedef inside, when it is in 4084// return type. Yeah. 4085auto generate ( StringRef generatorName, SourceLineInfo const & lineInfo, L const & generatorExpression ) -> decltype (std::declval < decltype ( generatorExpression ()) > (). get ()) { 4086using UnderlyingType = typename decltype ( generatorExpression ())::type; 4087 4088IGeneratorTracker & tracker = acquireGeneratorTracker ( generatorName, lineInfo ); 4089if (!tracker. hasGenerator ()) { 4090tracker. setGenerator (pf::make_unique < Generators < UnderlyingType>>( generatorExpression ())); 4091} 4092 4093auto const & generator = static_cast < IGenerator < UnderlyingType > const &> ( * tracker. getGenerator () ); 4094return generator. get (); 4095} 4096 4097} // namespace Generators 4098} // namespace Catch 4099 4100#define GENERATE ( ... ) \ 4101Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \ 4102CATCH_INTERNAL_LINEINFO, \ 4103[ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace) 4104#define GENERATE_COPY ( ... ) \ 4105Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \ 4106CATCH_INTERNAL_LINEINFO, \ 4107[=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace) 4108#define GENERATE_REF ( ... ) \ 4109Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \ 4110CATCH_INTERNAL_LINEINFO, \ 4111[&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace) 4112 4113// end catch_generators.hpp 4114// start catch_generators_generic.hpp 4115 4116namespace Catch { 4117namespace Generators { 4118 4119template < typename T > 4120class TakeGenerator : public IGenerator < T > { 4121GeneratorWrapper < T > m_generator; 4122size_t m_returned = 0 ; 4123size_t m_target; 4124public : 4125TakeGenerator( size_t target, GeneratorWrapper < T >&& generator): 4126m_generator ( std :: move ( generator )), 4127m_target ( target ) 4128{ 4129assert(target != 0 && "Empty generators are not allowed" ); 4130} 4131T const & get () const override { 4132return m_generator. get (); 4133} 4134bool next () override { 4135++ m_returned; 4136if (m_returned >= m_target) { 4137return false; 4138} 4139 4140const auto success = m_generator. next (); 4141// If the underlying generator does not contain enough values 4142// then we cut short as well 4143if (!success) { 4144m_returned = m_target; 4145} 4146return success; 4147} 4148}; 4149 4150template < typename T > 4151GeneratorWrapper < T > take (size_t target, GeneratorWrapper < T >&& generator) { 4152return GeneratorWrapper < T > (pf::make_unique < TakeGenerator < T >>(target, std:: move (generator))); 4153} 4154 4155template < typename T , typename Predicate > 4156class FilterGenerator : public IGenerator < T > { 4157GeneratorWrapper < T > m_generator; 4158Predicate m_predicate; 4159public : 4160template < typename P = Predicate > 4161FilterGenerator ( P && pred, GeneratorWrapper < T >&& generator): 4162m_generator ( std :: move (generator)), 4163m_predicate (std::forward < P > (pred)) 4164{ 4165if (! m_predicate (m_generator. get ())) { 4166// It might happen that there are no values that pass the 4167// filter. In that case we throw an exception. 4168auto has_initial_value = nextImpl (); 4169if (!has_initial_value) { 4170Catch :: throw_exception ( GeneratorException ( "No valid value found in filtered generator" )); 4171} 4172} 4173} 4174 4175T const & get () const override { 4176return m_generator. get (); 4177} 4178 4179bool next () override { 4180return nextImpl (); 4181} 4182 4183private : 4184bool nextImpl () { 4185bool success = m_generator. next (); 4186if (!success) { 4187return false; 4188} 4189while (! m_predicate (m_generator. get ()) && (success = m_generator. next ()) == true); 4190return success; 4191} 4192}; 4193 4194template < typename T , typename Predicate > 4195GeneratorWrapper < T > filter (Predicate && pred, GeneratorWrapper < T >&& generator) { 4196return GeneratorWrapper < T > (std::unique_ptr < IGenerator < T >>(pf::make_unique < FilterGenerator < T , Predicate>>(std::forward < Predicate > (pred), std:: move (generator)))); 4197} 4198 4199template < typename T > 4200class RepeatGenerator : public IGenerator < T > { 4201static_assert (!std::is_same < T , bool > ::value, 4202"RepeatGenerator currently does not support bools" 4203"because of std::vector<bool> specialization" ); 4204GeneratorWrapper < T > m_generator; 4205mutable std::vector < T > m_returned; 4206size_t m_target_repeats; 4207size_t m_current_repeat = 0 ; 4208size_t m_repeat_index = 0 ; 4209public : 4210RepeatGenerator( size_t repeats, GeneratorWrapper < T >&& generator): 4211m_generator ( std :: move ( generator )), 4212m_target_repeats ( repeats ) 4213{ 4214assert(m_target_repeats > 0 && "Repeat generator must repeat at least once" ); 4215} 4216 4217T const & get () const override { 4218if (m_current_repeat == 0 ) { 4219m_returned. push_back (m_generator. get ()); 4220return m_returned. back (); 4221} 4222return m_returned[m_repeat_index]; 4223} 4224 4225bool next () override { 4226// There are 2 basic cases: 4227// 1) We are still reading the generator 4228// 2) We are reading our own cache 4229 4230// In the first case, we need to poke the underlying generator. 4231// If it happily moves, we are left in that state, otherwise it is time to start reading from our cache 4232if (m_current_repeat == 0 ) { 4233const auto success = m_generator. next (); 4234if (!success) { 4235++ m_current_repeat; 4236} 4237return m_current_repeat < m_target_repeats; 4238} 4239 4240// In the second case, we need to move indices forward and check that we haven't run up against the end 4241++ m_repeat_index; 4242if (m_repeat_index == m_returned. size ()) { 4243m_repeat_index = 0 ; 4244++ m_current_repeat; 4245} 4246return m_current_repeat < m_target_repeats; 4247} 4248}; 4249 4250template < typename T > 4251GeneratorWrapper < T > repeat (size_t repeats, GeneratorWrapper < T >&& generator) { 4252return GeneratorWrapper < T > (pf::make_unique < RepeatGenerator < T >>(repeats, std:: move (generator))); 4253} 4254 4255template < typename T , typename U , typename Func > 4256class MapGenerator : public IGenerator < T > { 4257// TBD: provide static assert for mapping function, for friendly error message 4258GeneratorWrapper < U > m_generator; 4259Func m_function; 4260// To avoid returning dangling reference, we have to save the values 4261T m_cache; 4262public : 4263template < typename F2 = Func > 4264MapGenerator ( F2 && function, GeneratorWrapper < U >&& generator) : 4265m_generator ( std :: move (generator)), 4266m_function (std::forward < F2 > (function)), 4267m_cache ( m_function (m_generator. get ())) 4268{} 4269 4270T const & get () const override { 4271return m_cache; 4272} 4273bool next () override { 4274const auto success = m_generator. next (); 4275if (success) { 4276m_cache = m_function (m_generator. get ()); 4277} 4278return success; 4279} 4280}; 4281 4282template < typename Func, typename U , typename T = FunctionReturnType < Func, U >> 4283GeneratorWrapper < T > map (Func && function, GeneratorWrapper < U >&& generator) { 4284return GeneratorWrapper < T > ( 4285pf::make_unique < MapGenerator < T , U , Func>>(std::forward < Func > (function), std:: move (generator)) 4286); 4287} 4288 4289template < typename T , typename U , typename Func > 4290GeneratorWrapper < T > map (Func && function, GeneratorWrapper < U >&& generator) { 4291return GeneratorWrapper < T > ( 4292pf::make_unique < MapGenerator < T , U , Func>>(std::forward < Func > (function), std:: move (generator)) 4293); 4294} 4295 4296template < typename T > 4297class ChunkGenerator final : public IGenerator < std::vector < T >> { 4298std ::vector < T > m_chunk; 4299size_t m_chunk_size; 4300GeneratorWrapper < T > m_generator; 4301bool m_used_up = false; 4302public : 4303ChunkGenerator( size_t size, GeneratorWrapper < T > generator) : 4304m_chunk_size ( size ), m_generator ( std :: move ( generator )) 4305{ 4306m_chunk. reserve ( m_chunk_size ); 4307if (m_chunk_size != 0 ) { 4308m_chunk. push_back (m_generator. get ()); 4309for ( size_t i = 1 ; i < m_chunk_size; ++ i) { 4310if (!m_generator. next ()) { 4311Catch :: throw_exception ( GeneratorException ( "Not enough values to initialize the first chunk" )); 4312} 4313m_chunk. push_back (m_generator. get ()); 4314} 4315} 4316} 4317std ::vector < T > const & get () const override { 4318return m_chunk; 4319} 4320bool next () override { 4321m_chunk. clear (); 4322for ( size_t idx = 0 ; idx < m_chunk_size; ++ idx) { 4323if (!m_generator. next ()) { 4324return false; 4325} 4326m_chunk. push_back (m_generator. get ()); 4327} 4328return true; 4329} 4330}; 4331 4332template < typename T > 4333GeneratorWrapper < std::vector < T >> chunk (size_t size, GeneratorWrapper < T >&& generator) { 4334return GeneratorWrapper < std::vector < T >>( 4335pf::make_unique < ChunkGenerator < T >>(size, std:: move (generator)) 4336); 4337} 4338 4339} // namespace Generators 4340} // namespace Catch 4341 4342// end catch_generators_generic.hpp 4343// start catch_generators_specific.hpp 4344 4345// start catch_context.h 4346 4347#include <memory> 4348 4349namespace Catch { 4350 4351struct IResultCapture ; 4352struct IRunner ; 4353struct IConfig ; 4354struct IMutableContext ; 4355 4356using IConfigPtr = std::shared_ptr < IConfig const > ; 4357 4358struct IContext 4359{ 4360virtual ~ IContext (); 4361 4362virtual IResultCapture * getResultCapture () = 0 ; 4363virtual IRunner * getRunner () = 0 ; 4364virtual IConfigPtr const & getConfig () const = 0 ; 4365}; 4366 4367struct IMutableContext : IContext 4368{ 4369virtual ~ IMutableContext (); 4370virtual void setResultCapture ( IResultCapture * resultCapture ) = 0 ; 4371virtual void setRunner ( IRunner * runner ) = 0 ; 4372virtual void setConfig ( IConfigPtr const & config ) = 0 ; 4373 4374private : 4375static IMutableContext * currentContext; 4376friend IMutableContext & getCurrentMutableContext (); 4377friend void cleanUpContext (); 4378static void createContext (); 4379}; 4380 4381inline IMutableContext & getCurrentMutableContext () 4382{ 4383if ( !IMutableContext::currentContext ) 4384IMutableContext :: createContext (); 4385// NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn) 4386return * IMutableContext::currentContext; 4387} 4388 4389inline IContext & getCurrentContext () 4390{ 4391return getCurrentMutableContext (); 4392} 4393 4394void cleanUpContext (); 4395 4396class SimplePcg32; 4397SimplePcg32 & rng (); 4398} 4399 4400// end catch_context.h 4401// start catch_interfaces_config.h 4402 4403// start catch_option.hpp 4404 4405namespace Catch { 4406 4407// An optional type 4408template < typename T > 4409class Option { 4410public : 4411Option () : nullableValue( nullptr ) {} 4412Option( T const & _value ) 4413: nullableValue ( new( storage ) T ( _value ) ) 4414{} 4415Option( Option const & _other ) 4416: nullableValue ( _other ? new( storage ) T ( * _other ) : nullptr ) 4417{} 4418 4419~ Option () { 4420reset (); 4421} 4422 4423Option & operator = ( Option const & _other ) { 4424if ( & _other != this ) { 4425reset (); 4426if ( _other ) 4427nullableValue = new ( storage ) T ( * _other ); 4428} 4429return * this; 4430} 4431Option & operator = ( T const & _value ) { 4432reset (); 4433nullableValue = new ( storage ) T ( _value ); 4434return * this; 4435} 4436 4437void reset () { 4438if ( nullableValue ) 4439nullableValue -> ~ T (); 4440nullableValue = nullptr ; 4441} 4442 4443T & operator * () { return * nullableValue; } 4444T const & operator * () const { return * nullableValue; } 4445T * operator -> () { return nullableValue ; } 4446const T * operator -> () const { return nullableValue ; } 4447 4448T valueOr ( T const & defaultValue ) const { 4449return nullableValue ? * nullableValue : defaultValue ; 4450} 4451 4452bool some () const { return nullableValue != nullptr ; } 4453bool none () const { return nullableValue == nullptr ; } 4454 4455bool operator !() const { return nullableValue == nullptr ; } 4456explicit operator bool () const { 4457return some(); 4458} 4459 4460private : 4461T * nullableValue ; 4462alignas(alignof( T )) char storage [ sizeof ( T )]; 4463}; 4464 4465} // end namespace Catch 4466 4467// end catch_option.hpp 4468#include < chrono > 4469#include < iosfwd > 4470#include < string > 4471#include < vector > 4472#include < memory > 4473 4474namespace Catch { 4475 4476enum class Verbosity { 4477Quiet = 0 , 4478Normal , 4479High 4480}; 4481 4482struct WarnAbout { enum What { 4483Nothing = 0x00 , 4484NoAssertions = 0x01 , 4485NoTests = 0x02 4486}; }; 4487 4488struct ShowDurations { enum OrNot { 4489DefaultForReporter , 4490Always , 4491Never 4492}; }; 4493struct RunTests { enum InWhatOrder { 4494InDeclarationOrder , 4495InLexicographicalOrder , 4496InRandomOrder 4497}; }; 4498struct UseColour { enum YesOrNo { 4499Auto , 4500Yes , 4501No 4502}; }; 4503struct WaitForKeypress { enum When { 4504Never , 4505BeforeStart = 1 , 4506BeforeExit = 2 , 4507BeforeStartAndExit = BeforeStart | BeforeExit 4508}; }; 4509 4510class TestSpec ; 4511 4512struct IConfig : NonCopyable { 4513 4514virtual ~IConfig(); 4515 4516virtual bool allowThrows() const = 0 ; 4517virtual std :: ostream & stream() const = 0 ; 4518virtual std :: string name() const = 0 ; 4519virtual bool includeSuccessfulResults() const = 0 ; 4520virtual bool shouldDebugBreak() const = 0 ; 4521virtual bool warnAboutMissingAssertions() const = 0 ; 4522virtual bool warnAboutNoTests() const = 0 ; 4523virtual int abortAfter() const = 0 ; 4524virtual bool showInvisibles() const = 0 ; 4525virtual ShowDurations :: OrNot showDurations() const = 0 ; 4526virtual double minDuration() const = 0 ; 4527virtual TestSpec const & testSpec() const = 0 ; 4528virtual bool hasTestFilters() const = 0 ; 4529virtual std :: vector < std :: string > const & getTestsOrTags() const = 0 ; 4530virtual RunTests :: InWhatOrder runOrder() const = 0 ; 4531virtual unsigned int rngSeed() const = 0 ; 4532virtual UseColour :: YesOrNo useColour() const = 0 ; 4533virtual std :: vector < std :: string > const & getSectionsToRun() const = 0 ; 4534virtual Verbosity verbosity() const = 0 ; 4535 4536virtual bool benchmarkNoAnalysis() const = 0 ; 4537virtual int benchmarkSamples() const = 0 ; 4538virtual double benchmarkConfidenceInterval() const = 0 ; 4539virtual unsigned int benchmarkResamples() const = 0 ; 4540virtual std :: chrono :: milliseconds benchmarkWarmupTime() const = 0 ; 4541}; 4542 4543using IConfigPtr = std :: shared_ptr < IConfig const > ; 4544} 4545 4546// end catch_interfaces_config.h 4547// start catch_random_number_generator.h 4548 4549#include < cstdint > 4550 4551namespace Catch { 4552 4553// This is a simple implementation of C++11 Uniform Random Number 4554// Generator. It does not provide all operators, because Catch2 4555// does not use it, but it should behave as expected inside stdlib's 4556// distributions. 4557// The implementation is based on the PCG family (http://pcg-random.org) 4558class SimplePcg32 { 4559using state_type = std :: uint64_t ; 4560public : 4561using result_type = std :: uint32_t ; 4562static constexpr result_type ( min )() { 4563return 0 ; 4564} 4565static constexpr result_type ( max )() { 4566return static_cast < result_type > ( -1 ); 4567} 4568 4569// Provide some default initial state for the default constructor 4570SimplePcg32():SimplePcg32( 0xed743cc4U ) {} 4571 4572explicit SimplePcg32( result_type seed_ ); 4573 4574void seed( result_type seed_ ); 4575void discard( uint64_t skip ); 4576 4577result_type operator()(); 4578 4579private : 4580friend bool operator == ( SimplePcg32 const & lhs , SimplePcg32 const & rhs ); 4581friend bool operator != ( SimplePcg32 const & lhs , SimplePcg32 const & rhs ); 4582 4583// In theory we also need operator<< and operator>> 4584// In practice we do not use them, so we will skip them for now 4585 4586std :: uint64_t m_state ; 4587// This part of the state determines which "stream" of the numbers 4588// is chosen -- we take it as a constant for Catch2, so we only 4589// need to deal with seeding the main state. 4590// Picked by reading 8 bytes from `/dev/random` :-) 4591static const std :: uint64_t s_inc = ( 0x13ed0cc53f939476ULL << 1ULL ) | 1ULL ; 4592}; 4593 4594} // end namespace Catch 4595 4596// end catch_random_number_generator.h 4597#include < random > 4598 4599namespace Catch { 4600namespace Generators { 4601 4602template < typename Float > 4603class RandomFloatingGenerator final : public IGenerator < Float > { 4604Catch :: SimplePcg32 & m_rng ; 4605std :: uniform_real_distribution < Float > m_dist ; 4606Float m_current_number ; 4607public : 4608 4609RandomFloatingGenerator( Float a , Float b ): 4610m_rng(rng()), 4611m_dist( a , b ) { 4612static_cast < void > (next()); 4613} 4614 4615Float const & get() const override { 4616return m_current_number ; 4617} 4618bool next() override { 4619m_current_number = m_dist( m_rng ); 4620return true; 4621} 4622}; 4623 4624template < typename Integer > 4625class RandomIntegerGenerator final : public IGenerator < Integer > { 4626Catch :: SimplePcg32 & m_rng ; 4627std :: uniform_int_distribution < Integer > m_dist ; 4628Integer m_current_number ; 4629public : 4630 4631RandomIntegerGenerator ( Integer a , Integer b ): 4632m_rng( rng ()), 4633m_dist( a , b ) { 4634static_cast < void > (next()); 4635} 4636 4637Integer const & get() const override { 4638return m_current_number ; 4639} 4640bool next() override { 4641m_current_number = m_dist( m_rng ); 4642return true; 4643} 4644}; 4645 4646// TODO: Ideally this would be also constrained against the various char types, 4647// but I don't expect users to run into that in practice. 4648template < typename T > 4649typename std :: enable_if < std :: is_integral < T > :: value && ! std :: is_same < T , bool > :: value , 4650GeneratorWrapper < T >>:: type 4651random( T a , T b ) { 4652return GeneratorWrapper < T > ( 4653pf :: make_unique < RandomIntegerGenerator < T >>( a , b ) 4654); 4655} 4656 4657template < typename T > 4658typename std :: enable_if < std :: is_floating_point < T > :: value , 4659GeneratorWrapper < T >>:: type 4660random( T a , T b ) { 4661return GeneratorWrapper < T > ( 4662pf :: make_unique < RandomFloatingGenerator < T >>( a , b ) 4663); 4664} 4665 4666template < typename T > 4667class RangeGenerator final : public IGenerator < T > { 4668T m_current ; 4669T m_end ; 4670T m_step ; 4671bool m_positive ; 4672 4673public : 4674RangeGenerator ( T const & start , T const & end , T const & step ): 4675m_current( start ), 4676m_end( end ), 4677m_step( step ), 4678m_positive( m_step > T( 0 )) 4679{ 4680assert( m_current != m_end && "Range start and end cannot be equal" ); 4681assert( m_step != T( 0 ) && "Step size cannot be zero" ); 4682assert((( m_positive && m_current <= m_end ) || (! m_positive && m_current >= m_end )) && "Step moves away from end" ); 4683} 4684 4685RangeGenerator ( T const & start , T const & end ): 4686RangeGenerator( start , end , ( start < end ) ? T( 1 ) : T( -1 )) 4687{} 4688 4689T const & get() const override { 4690return m_current ; 4691} 4692 4693bool next() override { 4694m_current += m_step ; 4695return ( m_positive ) ? ( m_current < m_end ) : ( m_current > m_end ); 4696} 4697}; 4698 4699template < typename T > 4700GeneratorWrapper < T > range( T const & start , T const & end , T const & step ) { 4701static_assert ( std :: is_arithmetic < T > :: value && ! std :: is_same < T , bool > :: value , "Type must be numeric" ); 4702return GeneratorWrapper < T > ( pf :: make_unique < RangeGenerator < T >>( start , end , step )); 4703} 4704 4705template < typename T > 4706GeneratorWrapper < T > range( T const & start , T const & end ) { 4707static_assert ( std :: is_integral < T > :: value && ! std :: is_same < T , bool > :: value , "Type must be an integer" ); 4708return GeneratorWrapper < T > ( pf :: make_unique < RangeGenerator < T >>( start , end )); 4709} 4710 4711template < typename T > 4712class IteratorGenerator final : public IGenerator < T > { 4713static_assert(! std :: is_same < T , bool > :: value , 4714"IteratorGenerator currently does not support bools" 4715"because of std::vector<bool> specialization" ); 4716 4717std :: vector < T > m_elems ; 4718size_t m_current = 0 ; 4719public : 4720template < typename InputIterator , typename InputSentinel > 4721IteratorGenerator( InputIterator first , InputSentinel last ):m_elems( first , last ) { 4722if ( m_elems .empty()) { 4723Catch ::throw_exception(GeneratorException( "IteratorGenerator received no valid values" )); 4724} 4725} 4726 4727T const & get() const override { 4728return m_elems [ m_current ]; 4729} 4730 4731bool next() override { 4732++ m_current ; 4733return m_current != m_elems .size(); 4734} 4735}; 4736 4737template < typename InputIterator , 4738typename InputSentinel , 4739typename ResultType = typename std :: iterator_traits < InputIterator > :: value_type > 4740GeneratorWrapper < ResultType > from_range ( InputIterator from , InputSentinel to ) { 4741return GeneratorWrapper < ResultType > ( pf :: make_unique < IteratorGenerator < ResultType >>( from , to )); 4742} 4743 4744template < typename Container , 4745typename ResultType = typename Container :: value_type > 4746GeneratorWrapper < ResultType > from_range( Container const & cnt ) { 4747return GeneratorWrapper < ResultType > ( pf :: make_unique < IteratorGenerator < ResultType >>( cnt .begin(), cnt .end())); 4748} 4749 4750} // namespace Generators 4751} // namespace Catch 4752 4753// end catch_generators_specific.hpp 4754 4755// These files are included here so the single_include script doesn't put them 4756// in the conditionally compiled sections 4757// start catch_test_case_info.h 4758 4759#include < string > 4760#include < vector > 4761#include < memory > 4762 4763#ifdef __clang__ 4764#pragma clang diagnostic push 4765#pragma clang diagnostic ignored " - Wpadded " 4766#endif 4767 4768namespace Catch { 4769 4770struct ITestInvoker ; 4771 4772struct TestCaseInfo { 4773enum SpecialProperties { 4774None = 0 , 4775IsHidden = 1 << 1 , 4776ShouldFail = 1 << 2 , 4777MayFail = 1 << 3 , 4778Throws = 1 << 4 , 4779NonPortable = 1 << 5 , 4780Benchmark = 1 << 6 4781}; 4782 4783TestCaseInfo ( std :: string const & _name , 4784std :: string const & _className , 4785std :: string const & _description , 4786std :: vector < std :: string > const & _tags , 4787SourceLineInfo const & _lineInfo ); 4788 4789friend void setTags( TestCaseInfo & testCaseInfo , std :: vector < std :: string > tags ); 4790 4791bool isHidden() const ; 4792bool throws() const ; 4793bool okToFail() const ; 4794bool expectedToFail() const ; 4795 4796std :: string tagsAsString() const ; 4797 4798std :: string name ; 4799std :: string className ; 4800std :: string description ; 4801std :: vector < std :: string > tags ; 4802std :: vector < std :: string > lcaseTags ; 4803SourceLineInfo lineInfo ; 4804SpecialProperties properties ; 4805}; 4806 4807class TestCase : public TestCaseInfo { 4808public : 4809 4810TestCase( ITestInvoker * testCase , TestCaseInfo && info ); 4811 4812TestCase withName( std :: string const & _newName ) const ; 4813 4814void invoke() const ; 4815 4816TestCaseInfo const & getTestCaseInfo() const ; 4817 4818bool operator == ( TestCase const & other ) const ; 4819bool operator < ( TestCase const & other ) const ; 4820 4821private : 4822std :: shared_ptr < ITestInvoker > test ; 4823}; 4824 4825TestCase makeTestCase( ITestInvoker * testCase , 4826std :: string const & className , 4827NameAndTags const & nameAndTags , 4828SourceLineInfo const & lineInfo ); 4829} 4830 4831#ifdef __clang__ 4832#pragma clang diagnostic pop 4833#endif 4834 4835// end catch_test_case_info.h 4836// start catch_interfaces_runner.h 4837 4838namespace Catch { 4839 4840struct IRunner { 4841virtual ~ IRunner (); 4842virtual bool aborting () const = 0 ; 4843}; 4844} 4845 4846// end catch_interfaces_runner.h 4847 4848#ifdef __OBJC__ 4849// start catch_objc.hpp 4850 4851#import <objc/runtime.h> 4852 4853#include <string> 4854 4855// NB. Any general catch headers included here must be included 4856// in catch.hpp first to make sure they are included by the single 4857// header for non obj-usage 4858 4859/////////////////////////////////////////////////////////////////////////////// 4860// This protocol is really only here for (self) documenting purposes, since 4861// all its methods are optional. 4862@ protocol OcFixture 4863 4864@ optional 4865 4866- ( void ) setUp ; 4867- ( void ) tearDown ; 4868 4869@ end 4870 4871namespace Catch { 4872 4873class OcMethod : public ITestInvoker { 4874 4875public : 4876OcMethod ( Class cls , SEL sel ) : m_cls( cls ), m_sel( sel ) {} 4877 4878virtual void invoke() const { 4879id obj = [[ m_cls alloc ] init ]; 4880 4881performOptionalSelector ( obj , @selector( setUp ) ); 4882performOptionalSelector ( obj , m_sel ); 4883performOptionalSelector ( obj , @selector( tearDown ) ); 4884 4885arcSafeRelease ( obj ); 4886} 4887private : 4888virtual ~OcMethod() {} 4889 4890Class m_cls ; 4891SEL m_sel ; 4892}; 4893 4894namespace Detail { 4895 4896inline std :: string getAnnotation( Class cls , 4897std :: string const & annotationName , 4898std :: string const & testCaseName ) { 4899NSString * selStr = [[ NSString alloc ] initWithFormat :@ "Catch_%s_%s" , annotationName .c_str(), testCaseName .c_str()]; 4900SEL sel = NSSelectorFromString( selStr ); 4901arcSafeRelease( selStr ); 4902id value = performOptionalSelector( cls , sel ); 4903if ( value ) 4904return [( NSString * )value UTF8String]; 4905return "" ; 4906} 4907} 4908 4909inline std :: size_t registerTestMethods () { 4910std :: size_t noTestMethods = 0 ; 4911int noClasses = objc_getClassList ( nullptr , 0 ); 4912 4913Class * classes = ( CATCH_UNSAFE_UNRETAINED Class * ) malloc ( sizeof (Class) * noClasses); 4914objc_getClassList ( classes, noClasses ); 4915 4916for ( int c = 0 ; c < noClasses; c ++ ) { 4917Class cls = classes[c]; 4918{ 4919u_int count; 4920Method * methods = class_copyMethodList ( cls, & count ); 4921for ( u_int m = 0 ; m < count ; m ++ ) { 4922SEL selector = method_getName (methods[m]); 4923std :: string methodName = sel_getName (selector); 4924if ( startsWith ( methodName, "Catch_TestCase_" ) ) { 4925std :: string testCaseName = methodName. substr ( 15 ); 4926std :: string name = Detail:: getAnnotation ( cls, "Name" , testCaseName ); 4927std :: string desc = Detail:: getAnnotation ( cls, "Description" , testCaseName ); 4928const char * className = class_getName ( cls ); 4929 4930getMutableRegistryHub (). registerTest ( makeTestCase ( new OcMethod ( cls, selector ), className, NameAndTags ( name. c_str (), desc. c_str () ), SourceLineInfo ( "" , 0 ) ) ); 4931noTestMethods ++ ; 4932} 4933} 4934free (methods); 4935} 4936} 4937return noTestMethods; 4938} 4939 4940#if !defined( CATCH_CONFIG_DISABLE_MATCHERS ) 4941 4942namespace Matchers { 4943namespace Impl { 4944namespace NSStringMatchers { 4945 4946struct StringHolder : MatcherBase < NSString *> { 4947StringHolder ( NSString * substr ) : m_substr( [substr copy] ){} 4948StringHolder( StringHolder const & other ) : m_substr( [other. m_substr copy] ){} 4949StringHolder () { 4950arcSafeRelease ( m_substr ); 4951} 4952 4953bool match ( NSString * str ) const override { 4954return false; 4955} 4956 4957NSString * CATCH_ARC_STRONG m_substr; 4958}; 4959 4960struct Equals : StringHolder { 4961Equals ( NSString * substr ) : StringHolder ( substr ){} 4962 4963bool match ( NSString * str ) const override { 4964return (str != nil || m_substr == nil ) && 4965[str isEqualToString :m_substr]; 4966} 4967 4968std :: string describe () const override { 4969return "equals string: " + Catch::Detail:: stringify ( m_substr ); 4970} 4971}; 4972 4973struct Contains : StringHolder { 4974Contains ( NSString * substr ) : StringHolder ( substr ){} 4975 4976bool match ( NSString * str ) const override { 4977return (str != nil || m_substr == nil ) && 4978[str rangeOfString :m_substr]. location != NSNotFound; 4979} 4980 4981std :: string describe () const override { 4982return "contains string: " + Catch::Detail:: stringify ( m_substr ); 4983} 4984}; 4985 4986struct StartsWith : StringHolder { 4987StartsWith ( NSString * substr ) : StringHolder ( substr ){} 4988 4989bool match ( NSString * str ) const override { 4990return (str != nil || m_substr == nil ) && 4991[str rangeOfString :m_substr]. location == 0 ; 4992} 4993 4994std :: string describe () const override { 4995return "starts with: " + Catch::Detail:: stringify ( m_substr ); 4996} 4997}; 4998struct EndsWith : StringHolder { 4999EndsWith ( NSString * substr ) : StringHolder ( substr ){} 5000 5001bool match ( NSString * str ) const override { 5002return (str != nil || m_substr == nil ) && 5003[str rangeOfString :m_substr]. location == [str length] - [m_substr length]; 5004} 5005 5006std :: string describe () const override { 5007return "ends with: " + Catch::Detail:: stringify ( m_substr ); 5008} 5009}; 5010 5011} // namespace NSStringMatchers 5012} // namespace Impl 5013 5014inline Impl ::NSStringMatchers::Equals 5015Equals ( NSString * substr ){ return Impl::NSStringMatchers:: Equals ( substr ); } 5016 5017inline Impl ::NSStringMatchers::Contains 5018Contains ( NSString * substr ){ return Impl::NSStringMatchers:: Contains ( substr ); } 5019 5020inline Impl ::NSStringMatchers::StartsWith 5021StartsWith ( NSString * substr ){ return Impl::NSStringMatchers:: StartsWith ( substr ); } 5022 5023inline Impl ::NSStringMatchers::EndsWith 5024EndsWith ( NSString * substr ){ return Impl::NSStringMatchers:: EndsWith ( substr ); } 5025 5026} // namespace Matchers 5027 5028using namespace Matchers; 5029 5030#endif // CATCH_CONFIG_DISABLE_MATCHERS 5031 5032} // namespace Catch 5033 5034/////////////////////////////////////////////////////////////////////////////// 5035#define OC_MAKE_UNIQUE_NAME ( root , uniqueSuffix ) root##uniqueSuffix 5036#define OC_TEST_CASE2 ( name , desc , uniqueSuffix ) \ 5037+(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Name_test_, uniqueSuffix ) \ 5038{ \ 5039return @ name; \ 5040} \ 5041+(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Description_test_, uniqueSuffix ) \ 5042{ \ 5043return @ desc; \ 5044} \ 5045-(void) OC_MAKE_UNIQUE_NAME( Catch_TestCase_test_, uniqueSuffix ) 5046 5047#define OC_TEST_CASE ( name , desc ) OC_TEST_CASE2( name, desc, __LINE__ ) 5048 5049// end catch_objc.hpp 5050#endif 5051 5052// Benchmarking needs the externally-facing parts of reporters to work 5053#if defined( CATCH_CONFIG_EXTERNAL_INTERFACES ) || defined( CATCH_CONFIG_ENABLE_BENCHMARKING ) 5054// start catch_external_interfaces.h 5055 5056// start catch_reporter_bases.hpp 5057 5058// start catch_interfaces_reporter.h 5059 5060// start catch_config.hpp 5061 5062// start catch_test_spec_parser.h 5063 5064#ifdef __clang__ 5065#pragma clang diagnostic push 5066#pragma clang diagnostic ignored "-Wpadded" 5067#endif 5068 5069// start catch_test_spec.h 5070 5071#ifdef __clang__ 5072#pragma clang diagnostic push 5073#pragma clang diagnostic ignored "-Wpadded" 5074#endif 5075 5076// start catch_wildcard_pattern.h 5077 5078namespace Catch 5079{ 5080class WildcardPattern { 5081enum WildcardPosition { 5082NoWildcard = 0 , 5083WildcardAtStart = 1 , 5084WildcardAtEnd = 2 , 5085WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd 5086}; 5087 5088public : 5089 5090WildcardPattern ( std :: string const & pattern , CaseSensitive :: Choice caseSensitivity ); 5091virtual ~ WildcardPattern () = default ; 5092virtual bool matches ( std :: string const & str ) const ; 5093 5094private : 5095std :: string normaliseString ( std :: string const & str ) const; 5096CaseSensitive :: Choice m_caseSensitivity ; 5097WildcardPosition m_wildcard = NoWildcard ; 5098std :: string m_pattern ; 5099}; 5100} 5101 5102// end catch_wildcard_pattern.h 5103#include <string> 5104#include <vector> 5105#include <memory> 5106 5107namespace Catch { 5108 5109struct IConfig ; 5110 5111class TestSpec { 5112class Pattern { 5113public : 5114explicit Pattern ( std :: string const & name ); 5115virtual ~ Pattern (); 5116virtual bool matches ( TestCaseInfo const & testCase ) const = 0 ; 5117std :: string const & name () const ; 5118private : 5119std :: string const m_name ; 5120}; 5121using PatternPtr = std :: shared_ptr < Pattern > ; 5122 5123class NamePattern : public Pattern { 5124public : 5125explicit NamePattern ( std :: string const & name , std :: string const & filterString ); 5126bool matches ( TestCaseInfo const & testCase ) const override ; 5127private : 5128WildcardPattern m_wildcardPattern ; 5129}; 5130 5131class TagPattern : public Pattern { 5132public : 5133explicit TagPattern ( std :: string const & tag , std :: string const & filterString ); 5134bool matches ( TestCaseInfo const & testCase ) const override ; 5135private : 5136std :: string m_tag ; 5137}; 5138 5139class ExcludedPattern : public Pattern { 5140public : 5141explicit ExcludedPattern ( PatternPtr const & underlyingPattern ); 5142bool matches ( TestCaseInfo const & testCase ) const override ; 5143private : 5144PatternPtr m_underlyingPattern ; 5145}; 5146 5147struct Filter { 5148std :: vector < PatternPtr > m_patterns ; 5149 5150bool matches ( TestCaseInfo const & testCase ) const ; 5151std :: string name () const ; 5152}; 5153 5154public : 5155struct FilterMatch { 5156std :: string name ; 5157std :: vector < TestCase const *> tests ; 5158} ; 5159using Matches = std::vector < FilterMatch > ; 5160using vectorStrings = std::vector < std::string > ; 5161 5162bool hasFilters () const ; 5163bool matches ( TestCaseInfo const & testCase ) const; 5164Matches matchesByFilter ( std ::vector < TestCase > const & testCases, IConfig const & config ) const; 5165const vectorStrings & getInvalidArgs () const; 5166 5167private: 5168std::vector < Filter > m_filters; 5169std ::vector < std::string > m_invalidArgs; 5170friend class TestSpecParser; 5171}; 5172} 5173 5174#ifdef __clang__ 5175#pragma clang diagnostic pop 5176#endif 5177 5178// end catch_test_spec.h 5179// start catch_interfaces_tag_alias_registry.h 5180 5181#include <string> 5182 5183namespace Catch { 5184 5185struct TagAlias ; 5186 5187struct ITagAliasRegistry { 5188virtual ~ ITagAliasRegistry (); 5189// Nullptr if not present 5190virtual TagAlias const * find ( std ::string const & alias ) const = 0 ; 5191virtual std ::string expandAliases ( std::string const & unexpandedTestSpec ) const = 0 ; 5192 5193static ITagAliasRegistry const & get (); 5194}; 5195 5196} // end namespace Catch 5197 5198// end catch_interfaces_tag_alias_registry.h 5199namespace Catch { 5200 5201class TestSpecParser { 5202enum Mode { None, Name, QuotedName, Tag, EscapedName }; 5203Mode m_mode = None; 5204Mode lastMode = None; 5205bool m_exclusion = false; 5206std :: size_t m_pos = 0 ; 5207std :: size_t m_realPatternPos = 0 ; 5208std :: string m_arg; 5209std :: string m_substring; 5210std :: string m_patternName; 5211std::vector < std:: size_t > m_escapeChars; 5212TestSpec :: Filter m_currentFilter; 5213TestSpec m_testSpec; 5214ITagAliasRegistry const * m_tagAliases = nullptr ; 5215 5216public : 5217TestSpecParser( ITagAliasRegistry const & tagAliases ); 5218 5219TestSpecParser & parse ( std::string const & arg ); 5220TestSpec testSpec (); 5221 5222private : 5223bool visitChar ( char c ); 5224void startNewMode ( Mode mode ); 5225bool processNoneChar ( char c ); 5226void processNameChar ( char c ); 5227bool processOtherChar ( char c ); 5228void endMode (); 5229void escape (); 5230bool isControlChar ( char c ) const; 5231void saveLastMode (); 5232void revertBackToLastMode (); 5233void addFilter (); 5234bool separate (); 5235 5236// Handles common preprocessing of the pattern for name/tag patterns 5237std :: string preprocessPattern (); 5238// Adds the current pattern as a test name 5239void addNamePattern (); 5240// Adds the current pattern as a tag 5241void addTagPattern (); 5242 5243inline void addCharToPattern ( char c) { 5244m_substring += c; 5245m_patternName += c; 5246m_realPatternPos ++ ; 5247} 5248 5249}; 5250TestSpec parseTestSpec ( std ::string const & arg ); 5251 5252} // namespace Catch 5253 5254#ifdef __clang__ 5255#pragma clang diagnostic pop 5256#endif 5257 5258// end catch_test_spec_parser.h 5259// Libstdc++ doesn't like incomplete classes for unique_ptr 5260 5261#include <memory> 5262#include <vector> 5263#include <string> 5264 5265#ifndef CATCH_CONFIG_CONSOLE_WIDTH 5266#define CATCH_CONFIG_CONSOLE_WIDTH 80 5267#endif 5268 5269namespace Catch { 5270 5271struct IStream ; 5272 5273struct ConfigData { 5274bool listTests = false; 5275bool listTags = false; 5276bool listReporters = false; 5277bool listTestNamesOnly = false; 5278 5279bool showSuccessfulTests = false; 5280bool shouldDebugBreak = false; 5281bool noThrow = false; 5282bool showHelp = false; 5283bool showInvisibles = false; 5284bool filenamesAsTags = false; 5285bool libIdentify = false; 5286 5287int abortAfter = -1 ; 5288unsigned int rngSeed = 0 ; 5289 5290bool benchmarkNoAnalysis = false; 5291unsigned int benchmarkSamples = 100 ; 5292double benchmarkConfidenceInterval = 0.95 ; 5293unsigned int benchmarkResamples = 100000 ; 5294std :: chrono ::milliseconds::rep benchmarkWarmupTime = 100 ; 5295 5296Verbosity verbosity = Verbosity::Normal; 5297WarnAbout :: What warnings = WarnAbout ::Nothing; 5298ShowDurations :: OrNot showDurations = ShowDurations ::DefaultForReporter; 5299double minDuration = -1 ; 5300RunTests :: InWhatOrder runOrder = RunTests ::InDeclarationOrder; 5301UseColour :: YesOrNo useColour = UseColour ::Auto; 5302WaitForKeypress :: When waitForKeypress = WaitForKeypress ::Never; 5303 5304std :: string outputFilename ; 5305std :: string name ; 5306std :: string processName ; 5307#ifndef CATCH_CONFIG_DEFAULT_REPORTER 5308#define CATCH_CONFIG_DEFAULT_REPORTER "console" 5309#endif 5310std :: string reporterName = CATCH_CONFIG_DEFAULT_REPORTER ; 5311#undef CATCH_CONFIG_DEFAULT_REPORTER 5312 5313std :: vector < std ::string > testsOrTags; 5314std :: vector < std ::string > sectionsToRun; 5315}; 5316 5317class Config : public IConfig { 5318public : 5319 5320Config () = default; 5321Config( ConfigData const & data ); 5322virtual ~ Config () = default; 5323 5324std :: string const & getFilename () const; 5325 5326bool listTests () const ; 5327bool listTestNamesOnly () const; 5328bool listTags () const; 5329bool listReporters () const; 5330 5331std::string getProcessName () const; 5332std::string const & getReporterName () const; 5333 5334std::vector < std::string > const & getTestsOrTags () const override; 5335std::vector < std::string > const & getSectionsToRun () const override; 5336 5337TestSpec const & testSpec () const override; 5338bool hasTestFilters () const override; 5339 5340bool showHelp () const; 5341 5342// IConfig interface 5343bool allowThrows () const override; 5344std::ostream & stream () const override; 5345std::string name () const override; 5346bool includeSuccessfulResults () const override; 5347bool warnAboutMissingAssertions () const override; 5348bool warnAboutNoTests () const override; 5349ShowDurations::OrNot showDurations () const override; 5350double minDuration () const override; 5351RunTests::InWhatOrder runOrder () const override; 5352unsigned int rngSeed () const override; 5353UseColour::YesOrNo useColour () const override; 5354bool shouldDebugBreak () const override; 5355int abortAfter () const override; 5356bool showInvisibles () const override; 5357Verbosity verbosity () const override; 5358bool benchmarkNoAnalysis () const override; 5359int benchmarkSamples () const override; 5360double benchmarkConfidenceInterval () const override; 5361unsigned int benchmarkResamples () const override; 5362std::chrono::milliseconds benchmarkWarmupTime () const override; 5363 5364private: 5365 5366IStream const * openStream (); 5367ConfigData m_data; 5368 5369std ::unique_ptr < IStream const > m_stream; 5370TestSpec m_testSpec; 5371bool m_hasTestFilters = false; 5372}; 5373 5374} // end namespace Catch 5375 5376// end catch_config.hpp 5377// start catch_assertionresult.h 5378 5379#include < string > 5380 5381namespace Catch { 5382 5383struct AssertionResultData 5384{ 5385AssertionResultData() = delete ; 5386 5387AssertionResultData( ResultWas ::OfType _resultType , LazyExpression const & _lazyExpression ); 5388 5389std :: string message ; 5390mutable std ::string reconstructedExpression; 5391LazyExpression lazyExpression ; 5392ResultWas :: OfType resultType ; 5393 5394std :: string reconstructExpression () const ; 5395}; 5396 5397class AssertionResult { 5398public : 5399AssertionResult () = delete; 5400AssertionResult( AssertionInfo const & info, AssertionResultData const & data ); 5401 5402bool isOk () const ; 5403bool succeeded () const; 5404ResultWas::OfType getResultType () const; 5405bool hasExpression () const; 5406bool hasMessage () const; 5407std::string getExpression () const; 5408std::string getExpressionInMacro () const; 5409bool hasExpandedExpression () const; 5410std::string getExpandedExpression () const; 5411std::string getMessage () const; 5412SourceLineInfo getSourceInfo () const; 5413StringRef getTestMacroName () const; 5414 5415//protected: 5416AssertionInfo m_info; 5417AssertionResultData m_resultData; 5418}; 5419 5420} // end namespace Catch 5421 5422// end catch_assertionresult.h 5423#if defined( CATCH_CONFIG_ENABLE_BENCHMARKING ) 5424// start catch_estimate.hpp 5425 5426// Statistics estimates 5427 5428 5429namespace Catch { 5430namespace Benchmark { 5431template < typename Duration > 5432struct Estimate { 5433Duration point; 5434Duration lower_bound; 5435Duration upper_bound; 5436double confidence_interval; 5437 5438template < typename Duration2 > 5439operator Estimate < Duration2 > () const { 5440return { point, lower_bound, upper_bound, confidence_interval }; 5441} 5442}; 5443} // namespace Benchmark 5444} // namespace Catch 5445 5446// end catch_estimate.hpp 5447// start catch_outlier_classification.hpp 5448 5449// Outlier information 5450 5451namespace Catch { 5452namespace Benchmark { 5453struct OutlierClassification { 5454int samples_seen = 0 ; 5455int low_severe = 0 ; // more than 3 times IQR below Q1 5456int low_mild = 0 ; // 1.5 to 3 times IQR below Q1 5457int high_mild = 0 ; // 1.5 to 3 times IQR above Q3 5458int high_severe = 0 ; // more than 3 times IQR above Q3 5459 5460int total () const { 5461return low_severe + low_mild + high_mild + high_severe ; 5462} 5463}; 5464} // namespace Benchmark 5465} // namespace Catch 5466 5467// end catch_outlier_classification.hpp 5468 5469#include <iterator> 5470#endif // CATCH_CONFIG_ENABLE_BENCHMARKING 5471 5472#include <string> 5473#include <iosfwd> 5474#include <map> 5475#include <set> 5476#include <memory> 5477#include <algorithm> 5478 5479namespace Catch { 5480 5481struct ReporterConfig { 5482explicit ReporterConfig ( IConfigPtr const & _fullConfig ); 5483 5484ReporterConfig( IConfigPtr const & _fullConfig, std::ostream & _stream ); 5485 5486std :: ostream & stream () const ; 5487IConfigPtr fullConfig () const; 5488 5489private : 5490std ::ostream * m_stream; 5491IConfigPtr m_fullConfig ; 5492}; 5493 5494struct ReporterPreferences { 5495bool shouldRedirectStdOut = false; 5496bool shouldReportAllAssertions = false; 5497}; 5498 5499template < typename T > 5500struct LazyStat : Option < T > { 5501LazyStat & operator = ( T const & _value ) { 5502Option < T > ::operator = ( _value ); 5503used = false; 5504return * this; 5505} 5506void reset () { 5507Option < T > :: reset (); 5508used = false; 5509} 5510bool used = false; 5511}; 5512 5513struct TestRunInfo { 5514TestRunInfo( std :: string const & _name ); 5515std :: string name ; 5516}; 5517struct GroupInfo { 5518GroupInfo( std :: string const & _name , 5519std :: size_t _groupIndex , 5520std ::size_t _groupsCount ); 5521 5522std :: string name ; 5523std :: size_t groupIndex ; 5524std :: size_t groupsCounts ; 5525}; 5526 5527struct AssertionStats { 5528AssertionStats( AssertionResult const & _assertionResult, 5529std :: vector < MessageInfo > const & _infoMessages , 5530Totals const & _totals ); 5531 5532AssertionStats( AssertionStats const & ) = default ; 5533AssertionStats( AssertionStats && ) = default ; 5534AssertionStats & operator = ( AssertionStats const & ) = delete ; 5535AssertionStats & operator = ( AssertionStats && ) = delete ; 5536virtual ~ AssertionStats (); 5537 5538AssertionResult assertionResult ; 5539std :: vector < MessageInfo > infoMessages ; 5540Totals totals ; 5541}; 5542 5543struct SectionStats { 5544SectionStats( SectionInfo const & _sectionInfo, 5545Counts const & _assertions , 5546double _durationInSeconds , 5547bool _missingAssertions ); 5548SectionStats( SectionStats const & ) = default ; 5549SectionStats( SectionStats && ) = default ; 5550SectionStats & operator = ( SectionStats const & ) = default ; 5551SectionStats & operator = ( SectionStats && ) = default ; 5552virtual ~ SectionStats (); 5553 5554SectionInfo sectionInfo ; 5555Counts assertions ; 5556double durationInSeconds ; 5557bool missingAssertions ; 5558}; 5559 5560struct TestCaseStats { 5561TestCaseStats( TestCaseInfo const & _testInfo, 5562Totals const & _totals , 5563std :: string const & _stdOut , 5564std :: string const & _stdErr , 5565bool _aborting ); 5566 5567TestCaseStats( TestCaseStats const & ) = default ; 5568TestCaseStats( TestCaseStats && ) = default ; 5569TestCaseStats & operator = ( TestCaseStats const & ) = default ; 5570TestCaseStats & operator = ( TestCaseStats && ) = default ; 5571virtual ~ TestCaseStats (); 5572 5573TestCaseInfo testInfo ; 5574Totals totals ; 5575std :: string stdOut ; 5576std :: string stdErr ; 5577bool aborting ; 5578}; 5579 5580struct TestGroupStats { 5581TestGroupStats( GroupInfo const & _groupInfo, 5582Totals const & _totals , 5583bool _aborting ); 5584TestGroupStats( GroupInfo const & _groupInfo ); 5585 5586TestGroupStats( TestGroupStats const & ) = default ; 5587TestGroupStats( TestGroupStats && ) = default ; 5588TestGroupStats & operator = ( TestGroupStats const & ) = default ; 5589TestGroupStats & operator = ( TestGroupStats && ) = default ; 5590virtual ~ TestGroupStats (); 5591 5592GroupInfo groupInfo ; 5593Totals totals ; 5594bool aborting ; 5595}; 5596 5597struct TestRunStats { 5598TestRunStats( TestRunInfo const & _runInfo, 5599Totals const & _totals , 5600bool _aborting ); 5601 5602TestRunStats( TestRunStats const & ) = default ; 5603TestRunStats( TestRunStats && ) = default ; 5604TestRunStats & operator = ( TestRunStats const & ) = default ; 5605TestRunStats & operator = ( TestRunStats && ) = default ; 5606virtual ~ TestRunStats (); 5607 5608TestRunInfo runInfo ; 5609Totals totals ; 5610bool aborting ; 5611}; 5612 5613#if defined( CATCH_CONFIG_ENABLE_BENCHMARKING ) 5614struct BenchmarkInfo { 5615std :: string name ; 5616double estimatedDuration ; 5617int iterations ; 5618int samples ; 5619unsigned int resamples ; 5620double clockResolution ; 5621double clockCost ; 5622}; 5623 5624template < class Duration > 5625struct BenchmarkStats { 5626BenchmarkInfo info; 5627 5628std ::vector < Duration > samples; 5629Benchmark ::Estimate < Duration > mean; 5630Benchmark ::Estimate < Duration > standardDeviation; 5631Benchmark :: OutlierClassification outliers; 5632double outlierVariance; 5633 5634template < typename Duration2 > 5635operator BenchmarkStats < Duration2 > () const { 5636std ::vector < Duration2 > samples2; 5637samples2. reserve (samples. size ()); 5638std :: transform (samples. begin (), samples. end (), std:: back_inserter (samples2), [](Duration d) { return Duration2 (d); }); 5639return { 5640info, 5641std:: move (samples2), 5642mean, 5643standardDeviation, 5644outliers, 5645outlierVariance, 5646}; 5647} 5648}; 5649#endif // CATCH_CONFIG_ENABLE_BENCHMARKING 5650 5651struct IStreamingReporter { 5652virtual ~ IStreamingReporter () = default ; 5653 5654// Implementing class must also provide the following static methods: 5655// static std::string getDescription(); 5656// static std::set<Verbosity> getSupportedVerbosities() 5657 5658virtual ReporterPreferences getPreferences () const = 0 ; 5659 5660virtual void noMatchingTestCases ( std ::string const & spec ) = 0 ; 5661 5662virtual void reportInvalidArguments ( std ::string const & ) {} 5663 5664virtual void testRunStarting ( TestRunInfo const & testRunInfo ) = 0 ; 5665virtual void testGroupStarting ( GroupInfo const & groupInfo ) = 0 ; 5666 5667virtual void testCaseStarting ( TestCaseInfo const & testInfo ) = 0 ; 5668virtual void sectionStarting ( SectionInfo const & sectionInfo ) = 0 ; 5669 5670#if defined( CATCH_CONFIG_ENABLE_BENCHMARKING ) 5671virtual void benchmarkPreparing ( std ::string const & ) {} 5672virtual void benchmarkStarting ( BenchmarkInfo const & ) {} 5673virtual void benchmarkEnded ( BenchmarkStats <> const & ) {} 5674virtual void benchmarkFailed ( std ::string const & ) {} 5675#endif // CATCH_CONFIG_ENABLE_BENCHMARKING 5676 5677virtual void assertionStarting ( AssertionInfo const & assertionInfo ) = 0 ; 5678 5679// The return value indicates if the messages buffer should be cleared: 5680virtual bool assertionEnded ( AssertionStats const & assertionStats ) = 0 ; 5681 5682virtual void sectionEnded ( SectionStats const & sectionStats ) = 0 ; 5683virtual void testCaseEnded ( TestCaseStats const & testCaseStats ) = 0 ; 5684virtual void testGroupEnded ( TestGroupStats const & testGroupStats ) = 0 ; 5685virtual void testRunEnded ( TestRunStats const & testRunStats ) = 0 ; 5686 5687virtual void skipTest ( TestCaseInfo const & testInfo ) = 0 ; 5688 5689// Default empty implementation provided 5690virtual void fatalErrorEncountered ( StringRef name ); 5691 5692virtual bool isMulti () const ; 5693}; 5694using IStreamingReporterPtr = std :: unique_ptr < IStreamingReporter > ; 5695 5696struct IReporterFactory { 5697virtual ~ IReporterFactory (); 5698virtual IStreamingReporterPtr create ( ReporterConfig const & config ) const = 0 ; 5699virtual std :: string getDescription () const = 0 ; 5700}; 5701using IReporterFactoryPtr = std :: shared_ptr < IReporterFactory > ; 5702 5703struct IReporterRegistry { 5704using FactoryMap = std :: map < std :: string , IReporterFactoryPtr > ; 5705using Listeners = std :: vector < IReporterFactoryPtr > ; 5706 5707virtual ~ IReporterRegistry (); 5708virtual IStreamingReporterPtr create ( std :: string const & name , IConfigPtr const & config ) const = 0 ; 5709virtual FactoryMap const & getFactories () const = 0 ; 5710virtual Listeners const & getListeners () const = 0 ; 5711}; 5712 5713} // end namespace Catch 5714 5715// end catch_interfaces_reporter.h 5716#include <algorithm> 5717#include <cstring> 5718#include <cfloat> 5719#include <cstdio> 5720#include <cassert> 5721#include <memory> 5722#include <ostream> 5723 5724namespace Catch { 5725void prepareExpandedExpression ( AssertionResult & result ); 5726 5727// Returns double formatted as %.3f (format expected on output) 5728std :: string getFormattedDuration ( double duration ); 5729 5730//! Should the reporter show 5731bool shouldShowDuration ( IConfig const & config , double duration ); 5732 5733std :: string serializeFilters ( std :: vector < std :: string > const & container ); 5734 5735template < typename DerivedT > 5736struct StreamingReporterBase : IStreamingReporter { 5737 5738StreamingReporterBase ( ReporterConfig const & _config ) 5739: m_config ( _config . fullConfig () ), 5740stream ( _config . stream () ) 5741{ 5742m_reporterPrefs . shouldRedirectStdOut = false; 5743if( ! DerivedT :: getSupportedVerbosities (). count ( m_config -> verbosity () ) ) 5744CATCH_ERROR ( "Verbosity level not supported by this reporter" ); 5745} 5746 5747ReporterPreferences getPreferences () const override { 5748return m_reporterPrefs ; 5749} 5750 5751static std :: set < Verbosity > getSupportedVerbosities () { 5752return { Verbosity :: Normal }; 5753} 5754 5755~ StreamingReporterBase () override = default ; 5756 5757void noMatchingTestCases ( std :: string const & ) override {} 5758 5759void reportInvalidArguments ( std :: string const & ) override {} 5760 5761void testRunStarting ( TestRunInfo const & _testRunInfo ) override { 5762currentTestRunInfo = _testRunInfo ; 5763} 5764 5765void testGroupStarting ( GroupInfo const & _groupInfo ) override { 5766currentGroupInfo = _groupInfo ; 5767} 5768 5769void testCaseStarting ( TestCaseInfo const & _testInfo ) override { 5770currentTestCaseInfo = _testInfo ; 5771} 5772void sectionStarting ( SectionInfo const & _sectionInfo ) override { 5773m_sectionStack . push_back ( _sectionInfo ); 5774} 5775 5776void sectionEnded ( SectionStats const & /* _sectionStats */ ) override { 5777m_sectionStack . pop_back (); 5778} 5779void testCaseEnded ( TestCaseStats const & /* _testCaseStats */ ) override { 5780currentTestCaseInfo . reset (); 5781} 5782void testGroupEnded ( TestGroupStats const & /* _testGroupStats */ ) override { 5783currentGroupInfo . reset (); 5784} 5785void testRunEnded ( TestRunStats const & /* _testRunStats */ ) override { 5786currentTestCaseInfo . reset (); 5787currentGroupInfo . reset (); 5788currentTestRunInfo . reset (); 5789} 5790 5791void skipTest ( TestCaseInfo const & ) override { 5792// Don't do anything with this by default. 5793// It can optionally be overridden in the derived class. 5794} 5795 5796IConfigPtr m_config ; 5797std :: ostream & stream ; 5798 5799LazyStat < TestRunInfo > currentTestRunInfo ; 5800LazyStat < GroupInfo > currentGroupInfo ; 5801LazyStat < TestCaseInfo > currentTestCaseInfo ; 5802 5803std :: vector < SectionInfo > m_sectionStack ; 5804ReporterPreferences m_reporterPrefs ; 5805}; 5806 5807template < typename DerivedT > 5808struct CumulativeReporterBase : IStreamingReporter { 5809template < typename T , typename ChildNodeT > 5810struct Node { 5811explicit Node ( T const & _value ) : value ( _value ) {} 5812virtual ~ Node () {} 5813 5814using ChildNodes = std :: vector < std :: shared_ptr < ChildNodeT >>; 5815T value ; 5816ChildNodes children ; 5817}; 5818struct SectionNode { 5819explicit SectionNode ( SectionStats const & _stats ) : stats ( _stats ) {} 5820virtual ~ SectionNode () = default ; 5821 5822bool operator == ( SectionNode const & other ) const { 5823return stats . sectionInfo . lineInfo == other . stats . sectionInfo . lineInfo ; 5824} 5825bool operator == ( std :: shared_ptr < SectionNode > const & other ) const { 5826return operator == ( * other ); 5827} 5828 5829SectionStats stats ; 5830using ChildSections = std :: vector < std :: shared_ptr < SectionNode >>; 5831using Assertions = std :: vector < AssertionStats > ; 5832ChildSections childSections ; 5833Assertions assertions ; 5834std :: string stdOut ; 5835std :: string stdErr ; 5836}; 5837 5838struct BySectionInfo { 5839BySectionInfo ( SectionInfo const & other ) : m_other ( other ) {} 5840BySectionInfo ( BySectionInfo const & other ) : m_other ( other . m_other ) {} 5841bool operator () ( std :: shared_ptr < SectionNode > const & node ) const { 5842return (( node -> stats . sectionInfo . name == m_other . name ) && 5843( node -> stats . sectionInfo . lineInfo == m_other . lineInfo )); 5844} 5845void operator = ( BySectionInfo const & ) = delete ; 5846 5847private : 5848SectionInfo const & m_other ; 5849}; 5850 5851using TestCaseNode = Node < TestCaseStats , SectionNode > ; 5852using TestGroupNode = Node < TestGroupStats , TestCaseNode > ; 5853using TestRunNode = Node < TestRunStats , TestGroupNode > ; 5854 5855CumulativeReporterBase ( ReporterConfig const & _config ) 5856: m_config ( _config . fullConfig () ), 5857stream ( _config . stream () ) 5858{ 5859m_reporterPrefs . shouldRedirectStdOut = false; 5860if( ! DerivedT :: getSupportedVerbosities (). count ( m_config -> verbosity () ) ) 5861CATCH_ERROR ( "Verbosity level not supported by this reporter" ); 5862} 5863~ CumulativeReporterBase () override = default ; 5864 5865ReporterPreferences getPreferences () const override { 5866return m_reporterPrefs ; 5867} 5868 5869static std :: set < Verbosity > getSupportedVerbosities () { 5870return { Verbosity :: Normal }; 5871} 5872 5873void testRunStarting ( TestRunInfo const & ) override {} 5874void testGroupStarting ( GroupInfo const & ) override {} 5875 5876void testCaseStarting ( TestCaseInfo const & ) override {} 5877 5878void sectionStarting ( SectionInfo const & sectionInfo ) override { 5879SectionStats incompleteStats ( sectionInfo , Counts (), 0 , false ); 5880std :: shared_ptr < SectionNode > node ; 5881if( m_sectionStack . empty () ) { 5882if( ! m_rootSection ) 5883m_rootSection = std :: make_shared < SectionNode > ( incompleteStats ); 5884node = m_rootSection ; 5885} 5886else { 5887SectionNode & parentNode = * m_sectionStack . back (); 5888auto it = 5889std :: find_if ( parentNode . childSections . begin (), 5890parentNode . childSections . end (), 5891BySectionInfo ( sectionInfo ) ); 5892if( it == parentNode . childSections . end () ) { 5893node = std :: make_shared < SectionNode > ( incompleteStats ); 5894parentNode . childSections . push_back ( node ); 5895} 5896else 5897node = * it ; 5898} 5899m_sectionStack . push_back ( node ); 5900m_deepestSection = std :: move ( node ); 5901} 5902 5903void assertionStarting ( AssertionInfo const & ) override {} 5904 5905bool assertionEnded ( AssertionStats const & assertionStats ) override { 5906assert (! m_sectionStack . empty ()); 5907// AssertionResult holds a pointer to a temporary DecomposedExpression, 5908// which getExpandedExpression() calls to build the expression string. 5909// Our section stack copy of the assertionResult will likely outlive the 5910// temporary, so it must be expanded or discarded now to avoid calling 5911// a destroyed object later. 5912prepareExpandedExpression ( const_cast < AssertionResult &> ( assertionStats . assertionResult ) ); 5913SectionNode & sectionNode = * m_sectionStack . back (); 5914sectionNode . assertions . push_back ( assertionStats ); 5915return true; 5916} 5917void sectionEnded ( SectionStats const & sectionStats ) override { 5918assert (! m_sectionStack . empty ()); 5919SectionNode & node = * m_sectionStack . back (); 5920node . stats = sectionStats ; 5921m_sectionStack . pop_back (); 5922} 5923void testCaseEnded ( TestCaseStats const & testCaseStats ) override { 5924auto node = std :: make_shared < TestCaseNode > ( testCaseStats ); 5925assert ( m_sectionStack . size () == 0 ); 5926node -> children . push_back ( m_rootSection ); 5927m_testCases . push_back ( node ); 5928m_rootSection . reset (); 5929 5930assert ( m_deepestSection ); 5931m_deepestSection -> stdOut = testCaseStats . stdOut ; 5932m_deepestSection -> stdErr = testCaseStats . stdErr ; 5933} 5934void testGroupEnded ( TestGroupStats const & testGroupStats ) override { 5935auto node = std :: make_shared < TestGroupNode > ( testGroupStats ); 5936node -> children . swap ( m_testCases ); 5937m_testGroups . push_back ( node ); 5938} 5939void testRunEnded ( TestRunStats const & testRunStats ) override { 5940auto node = std :: make_shared < TestRunNode > ( testRunStats ); 5941node -> children . swap ( m_testGroups ); 5942m_testRuns . push_back ( node ); 5943testRunEndedCumulative (); 5944} 5945virtual void testRunEndedCumulative () = 0 ; 5946 5947void skipTest ( TestCaseInfo const & ) override {} 5948 5949IConfigPtr m_config ; 5950std :: ostream & stream ; 5951std :: vector < AssertionStats > m_assertions ; 5952std :: vector < std :: vector < std :: shared_ptr < SectionNode >> > m_sections ; 5953std :: vector < std :: shared_ptr < TestCaseNode >> m_testCases ; 5954std :: vector < std :: shared_ptr < TestGroupNode >> m_testGroups ; 5955 5956std :: vector < std :: shared_ptr < TestRunNode >> m_testRuns ; 5957 5958std :: shared_ptr < SectionNode > m_rootSection ; 5959std :: shared_ptr < SectionNode > m_deepestSection ; 5960std :: vector < std :: shared_ptr < SectionNode >> m_sectionStack ; 5961ReporterPreferences m_reporterPrefs ; 5962}; 5963 5964template < char C > 5965char const * getLineOfChars () { 5966static char line [ CATCH_CONFIG_CONSOLE_WIDTH ] = { 0 }; 5967if( ! * line ) { 5968std :: memset ( line , C , CATCH_CONFIG_CONSOLE_WIDTH - 1 ); 5969line [ CATCH_CONFIG_CONSOLE_WIDTH - 1 ] = 0 ; 5970} 5971return line ; 5972} 5973 5974struct TestEventListenerBase : StreamingReporterBase < TestEventListenerBase > { 5975TestEventListenerBase ( ReporterConfig const & _config ); 5976 5977static std :: set < Verbosity > getSupportedVerbosities (); 5978 5979void assertionStarting ( AssertionInfo const & ) override ; 5980bool assertionEnded ( AssertionStats const & ) override ; 5981}; 5982 5983} // end namespace Catch 5984 5985// end catch_reporter_bases.hpp 5986// start catch_console_colour.h 5987 5988namespace Catch { 5989 5990struct Colour { 5991enum Code { 5992None = 0 , 5993 5994White , 5995Red , 5996Green , 5997Blue , 5998Cyan , 5999Yellow , 6000Grey , 6001 6002Bright = 0x10 , 6003 6004BrightRed = Bright | Red , 6005BrightGreen = Bright | Green , 6006LightGrey = Bright | Grey , 6007BrightWhite = Bright | White , 6008BrightYellow = Bright | Yellow , 6009 6010// By intention 6011FileName = LightGrey , 6012Warning = BrightYellow , 6013ResultError = BrightRed , 6014ResultSuccess = BrightGreen , 6015ResultExpectedFailure = Warning , 6016 6017Error = BrightRed , 6018Success = Green , 6019 6020OriginalExpression = Cyan , 6021ReconstructedExpression = BrightYellow , 6022 6023SecondaryText = LightGrey , 6024Headers = White 6025}; 6026 6027// Use constructed object for RAII guard 6028Colour ( Code _colourCode ); 6029Colour ( Colour && other ) noexcept ; 6030Colour & operator = ( Colour && other ) noexcept ; 6031~ Colour ( ); 6032 6033// Use static method for one-shot changes 6034static void use ( Code _colourCode ); 6035 6036private: 6037bool m_moved = false; 6038}; 6039 6040std :: ostream & operator << ( std :: ostream & os , Colour const & ); 6041 6042} // end namespace Catch 6043 6044// end catch_console_colour.h 6045// start catch_reporter_registrars.hpp 6046 6047 6048namespace Catch { 6049 6050template < typename T > 6051class ReporterRegistrar { 6052 6053class ReporterFactory : public IReporterFactory { 6054 6055IStreamingReporterPtr create ( ReporterConfig const & config ) const override { 6056return std :: unique_ptr < T > ( new T ( config ) ); 6057} 6058 6059std ::string getDescription () const override { 6060return T :: getDescription (); 6061} 6062}; 6063 6064public : 6065 6066explicit ReporterRegistrar ( std:: string const & name ) { 6067getMutableRegistryHub (). registerReporter ( name , std :: make_shared < ReporterFactory > ( ) ); 6068} 6069}; 6070 6071template < typename T > 6072class ListenerRegistrar { 6073 6074class ListenerFactory : public IReporterFactory { 6075 6076IStreamingReporterPtr create ( ReporterConfig const & config ) const override { 6077return std::unique_ptr < T > ( new T ( config ) ); 6078} 6079std :: string getDescription () const override { 6080return std:: string (); 6081} 6082}; 6083 6084public : 6085 6086ListenerRegistrar () { 6087getMutableRegistryHub (). registerListener ( std::make_shared < ListenerFactory > () ); 6088} 6089}; 6090} 6091 6092#if !defined( CATCH_CONFIG_DISABLE ) 6093 6094#define CATCH_REGISTER_REPORTER ( name, reporterType ) \ 6095CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 6096CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 6097namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); } \ 6098CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 6099 6100#define CATCH_REGISTER_LISTENER ( listenerType ) \ 6101CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 6102CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 6103namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; } \ 6104CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 6105#else // CATCH_CONFIG_DISABLE 6106 6107#define CATCH_REGISTER_REPORTER (name, reporterType) 6108#define CATCH_REGISTER_LISTENER (listenerType) 6109 6110#endif // CATCH_CONFIG_DISABLE 6111 6112// end catch_reporter_registrars.hpp 6113// Allow users to base their work off existing reporters 6114// start catch_reporter_compact.h 6115 6116namespace Catch { 6117 6118struct CompactReporter : StreamingReporterBase < CompactReporter > { 6119 6120using StreamingReporterBase::StreamingReporterBase; 6121 6122~ CompactReporter () override; 6123 6124static std ::string getDescription (); 6125 6126void noMatchingTestCases ( std ::string const & spec) override; 6127 6128void assertionStarting ( AssertionInfo const & ) override; 6129 6130bool assertionEnded ( AssertionStats const & _assertionStats) override; 6131 6132void sectionEnded ( SectionStats const & _sectionStats) override; 6133 6134void testRunEnded ( TestRunStats const & _testRunStats) override; 6135 6136}; 6137 6138} // end namespace Catch 6139 6140// end catch_reporter_compact.h 6141// start catch_reporter_console.h 6142 6143#if defined(_MSC_VER) 6144#pragma warning(push) 6145#pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch 6146// Note that 4062 (not all labels are handled 6147// and default is missing) is enabled 6148#endif 6149 6150namespace Catch { 6151// Fwd decls 6152struct SummaryColumn ; 6153class TablePrinter; 6154 6155struct ConsoleReporter : StreamingReporterBase < ConsoleReporter > { 6156std ::unique_ptr < TablePrinter > m_tablePrinter; 6157 6158ConsoleReporter( ReporterConfig const & config); 6159~ ConsoleReporter () override; 6160static std ::string getDescription (); 6161 6162void noMatchingTestCases ( std ::string const & spec) override; 6163 6164void reportInvalidArguments ( std ::string const & arg) override; 6165 6166void assertionStarting ( AssertionInfo const & ) override; 6167 6168bool assertionEnded ( AssertionStats const & _assertionStats) override; 6169 6170void sectionStarting ( SectionInfo const & _sectionInfo) override; 6171void sectionEnded ( SectionStats const & _sectionStats) override; 6172 6173#if defined( CATCH_CONFIG_ENABLE_BENCHMARKING ) 6174void benchmarkPreparing ( std ::string const & name) override; 6175void benchmarkStarting ( BenchmarkInfo const & info) override; 6176void benchmarkEnded ( BenchmarkStats <> const & stats) override; 6177void benchmarkFailed ( std ::string const & error) override; 6178#endif // CATCH_CONFIG_ENABLE_BENCHMARKING 6179 6180void testCaseEnded ( TestCaseStats const & _testCaseStats) override; 6181void testGroupEnded ( TestGroupStats const & _testGroupStats) override; 6182void testRunEnded ( TestRunStats const & _testRunStats) override; 6183void testRunStarting ( TestRunInfo const & _testRunInfo) override; 6184private : 6185 6186void lazyPrint (); 6187 6188void lazyPrintWithoutClosingBenchmarkTable (); 6189void lazyPrintRunInfo (); 6190void lazyPrintGroupInfo (); 6191void printTestCaseAndSectionHeader (); 6192 6193void printClosedHeader ( std ::string const & _name); 6194void printOpenHeader ( std ::string const & _name); 6195 6196// if string has a : in first line will set indent to follow it on 6197// subsequent lines 6198void printHeaderString ( std ::string const & _string, std :: size_t indent = 0 ); 6199 6200void printTotals ( Totals const & totals); 6201void printSummaryRow ( std ::string const & label, std ::vector < SummaryColumn > const & cols, std :: size_t row); 6202 6203void printTotalsDivider ( Totals const & totals); 6204void printSummaryDivider (); 6205void printTestFilters (); 6206 6207private : 6208bool m_headerPrinted = false; 6209}; 6210 6211} // end namespace Catch 6212 6213#if defined(_MSC_VER) 6214#pragma warning(pop) 6215#endif 6216 6217// end catch_reporter_console.h 6218// start catch_reporter_junit.h 6219 6220// start catch_xmlwriter.h 6221 6222#include <vector> 6223 6224namespace Catch { 6225enum class XmlFormatting { 6226None = 0x00 , 6227Indent = 0x01 , 6228Newline = 0x02 , 6229}; 6230 6231XmlFormatting operator | ( XmlFormatting lhs, XmlFormatting rhs); 6232XmlFormatting operator & ( XmlFormatting lhs, XmlFormatting rhs); 6233 6234class XmlEncode { 6235public : 6236enum ForWhat { ForTextNodes, ForAttributes }; 6237 6238XmlEncode( std :: string const & str, ForWhat forWhat = ForTextNodes ); 6239 6240void encodeTo ( std ::ostream & os ) const; 6241 6242friend std::ostream & operator << ( std::ostream & os, XmlEncode const & xmlEncode ); 6243 6244private : 6245std :: string m_str; 6246ForWhat m_forWhat; 6247}; 6248 6249class XmlWriter { 6250public : 6251 6252class ScopedElement { 6253public : 6254ScopedElement ( XmlWriter * writer, XmlFormatting fmt ); 6255 6256ScopedElement ( ScopedElement && other ) noexcept; 6257ScopedElement & operator = ( ScopedElement && other ) noexcept; 6258 6259~ ScopedElement (); 6260 6261ScopedElement & writeText ( std::string const & text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent ); 6262 6263template < typename T > 6264ScopedElement & writeAttribute ( std::string const & name, T const & attribute ) { 6265m_writer -> writeAttribute ( name, attribute ); 6266return * this; 6267} 6268 6269private : 6270mutable XmlWriter * m_writer = nullptr ; 6271XmlFormatting m_fmt; 6272}; 6273 6274XmlWriter ( std ::ostream & os = Catch:: cout () ); 6275~ XmlWriter (); 6276 6277XmlWriter( XmlWriter const & ) = delete; 6278XmlWriter & operator = ( XmlWriter const & ) = delete; 6279 6280XmlWriter & startElement ( std::string const & name, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); 6281 6282ScopedElement scopedElement ( std ::string const & name, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); 6283 6284XmlWriter & endElement (XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); 6285 6286XmlWriter & writeAttribute ( std::string const & name, std::string const & attribute ); 6287 6288XmlWriter & writeAttribute ( std::string const & name, bool attribute ); 6289 6290template < typename T > 6291XmlWriter & writeAttribute ( std::string const & name, T const & attribute ) { 6292ReusableStringStream rss; 6293rss << attribute; 6294return writeAttribute ( name, rss. str () ); 6295} 6296 6297XmlWriter & writeText ( std::string const & text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); 6298 6299XmlWriter & writeComment (std::string const & text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); 6300 6301void writeStylesheetRef ( std ::string const & url ); 6302 6303XmlWriter & writeBlankLine (); 6304 6305void ensureTagClosed (); 6306 6307private : 6308 6309void applyFormatting ( XmlFormatting fmt); 6310 6311void writeDeclaration (); 6312 6313void newlineIfNecessary (); 6314 6315bool m_tagIsOpen = false; 6316bool m_needsNewline = false; 6317std ::vector < std::string > m_tags; 6318std :: string m_indent; 6319std ::ostream & m_os; 6320}; 6321 6322} 6323 6324// end catch_xmlwriter.h 6325namespace Catch { 6326 6327class JunitReporter : public CumulativeReporterBase < JunitReporter > { 6328public : 6329JunitReporter( ReporterConfig const & _config); 6330 6331~ JunitReporter () override; 6332 6333static std ::string getDescription (); 6334 6335void noMatchingTestCases ( std ::string const & /*spec*/ ) override; 6336 6337void testRunStarting ( TestRunInfo const & runInfo) override; 6338 6339void testGroupStarting ( GroupInfo const & groupInfo) override; 6340 6341void testCaseStarting ( TestCaseInfo const & testCaseInfo) override; 6342bool assertionEnded ( AssertionStats const & assertionStats) override; 6343 6344void testCaseEnded ( TestCaseStats const & testCaseStats) override; 6345 6346void testGroupEnded ( TestGroupStats const & testGroupStats) override; 6347 6348void testRunEndedCumulative () override ; 6349 6350void writeGroup ( TestGroupNode const & groupNode, double suiteTime); 6351 6352void writeTestCase ( TestCaseNode const & testCaseNode); 6353 6354void writeSection ( std ::string const & className, 6355std ::string const & rootName, 6356SectionNode const & sectionNode, 6357bool testOkToFail ); 6358 6359void writeAssertions ( SectionNode const & sectionNode); 6360void writeAssertion ( AssertionStats const & stats); 6361 6362XmlWriter xml; 6363Timer suiteTimer; 6364std ::string stdOutForSuite; 6365std ::string stdErrForSuite; 6366unsigned int unexpectedExceptions = 0 ; 6367bool m_okToFail = false; 6368}; 6369 6370} // end namespace Catch 6371 6372// end catch_reporter_junit.h 6373// start catch_reporter_xml.h 6374 6375namespace Catch { 6376class XmlReporter : public StreamingReporterBase < XmlReporter > { 6377public : 6378XmlReporter( ReporterConfig const & _config); 6379 6380~ XmlReporter () override; 6381 6382static std ::string getDescription (); 6383 6384virtual std::string getStylesheetRef () const ; 6385 6386void writeSourceInfo ( SourceLineInfo const & sourceInfo); 6387 6388public : // StreamingReporterBase 6389 6390void noMatchingTestCases ( std ::string const & s) override; 6391 6392void testRunStarting ( TestRunInfo const & testInfo) override; 6393 6394void testGroupStarting ( GroupInfo const & groupInfo) override; 6395 6396void testCaseStarting ( TestCaseInfo const & testInfo) override; 6397 6398void sectionStarting ( SectionInfo const & sectionInfo) override; 6399 6400void assertionStarting ( AssertionInfo const & ) override; 6401 6402bool assertionEnded ( AssertionStats const & assertionStats) override; 6403 6404void sectionEnded ( SectionStats const & sectionStats) override; 6405 6406void testCaseEnded ( TestCaseStats const & testCaseStats) override; 6407 6408void testGroupEnded ( TestGroupStats const & testGroupStats) override; 6409 6410void testRunEnded ( TestRunStats const & testRunStats) override; 6411 6412#if defined( CATCH_CONFIG_ENABLE_BENCHMARKING ) 6413void benchmarkPreparing ( std ::string const & name) override; 6414void benchmarkStarting ( BenchmarkInfo const & ) override; 6415void benchmarkEnded ( BenchmarkStats <> const & ) override; 6416void benchmarkFailed ( std ::string const & ) override; 6417#endif // CATCH_CONFIG_ENABLE_BENCHMARKING 6418 6419private: 6420Timer m_testCaseTimer; 6421XmlWriter m_xml; 6422int m_sectionDepth = 0 ; 6423}; 6424 6425} // end namespace Catch 6426 6427// end catch_reporter_xml.h 6428 6429// end catch_external_interfaces.h 6430#endif 6431 6432#if defined( CATCH_CONFIG_ENABLE_BENCHMARKING ) 6433// start catch_benchmarking_all.hpp 6434 6435// A proxy header that includes all of the benchmarking headers to allow 6436// concise include of the benchmarking features. You should prefer the 6437// individual includes in standard use. 6438 6439// start catch_benchmark.hpp 6440 6441// Benchmark 6442 6443// start catch_chronometer.hpp 6444 6445// User-facing chronometer 6446 6447 6448// start catch_clock.hpp 6449 6450// Clocks 6451 6452 6453#include <chrono> 6454#include <ratio> 6455 6456namespace Catch { 6457namespace Benchmark { 6458template < typename Clock > 6459using ClockDuration = typename Clock ::duration; 6460template < typename Clock > 6461using FloatDuration = std:: chrono ::duration < double, typename Clock ::period > ; 6462 6463template < typename Clock > 6464using TimePoint = typename Clock ::time_point; 6465 6466using default_clock = std::chrono::steady_clock; 6467 6468template < typename Clock > 6469struct now { 6470TimePoint < Clock > operator ()() const { 6471return Clock:: now (); 6472} 6473}; 6474 6475using fp_seconds = std::chrono::duration < double, std::ratio < 1 >>; 6476} // namespace Benchmark 6477} // namespace Catch 6478 6479// end catch_clock.hpp 6480// start catch_optimizer.hpp 6481 6482// Hinting the optimizer 6483 6484 6485#if defined(_MSC_VER) 6486# include <atomic> // atomic_thread_fence 6487#endif 6488 6489namespace Catch { 6490namespace Benchmark { 6491#if defined(__GNUC__) || defined(__clang__) 6492template < typename T > 6493inline void keep_memory ( T * p) { 6494asm volatile ( "" : : "g" (p) : "memory" ); 6495} 6496inline void keep_memory () { 6497asm volatile ( "" : : : "memory" ); 6498} 6499 6500namespace Detail { 6501inline void optimizer_barrier () { keep_memory (); } 6502} // namespace Detail 6503#elif defined(_MSC_VER) 6504 6505#pragma optimize("", off) 6506template < typename T > 6507inline void keep_memory ( T * p) { 6508// thanks @milleniumbug 6509* reinterpret_cast < char volatile *> (p) = * reinterpret_cast < char const volatile *> (p); 6510} 6511// TODO equivalent keep_memory() 6512#pragma optimize("", on) 6513 6514namespace Detail { 6515inline void optimizer_barrier () { 6516std ::atomic_thread_fence( std :: memory_order_seq_cst ); 6517} 6518} // namespace Detail 6519 6520#endif 6521 6522template < typename T > 6523inline void deoptimize_value ( T && x) { 6524keep_memory ( & x); 6525} 6526 6527template < typename Fn, typename... Args > 6528inline auto invoke_deoptimized (Fn && fn, Args && ... args) -> typename std ::enable_if < !std::is_same < void, decltype ( fn (args...)) > ::value > ::type { 6529deoptimize_value(std::forward < Fn > (fn) (std::forward < Args... > (args...))); 6530} 6531 6532template < typename Fn, typename... Args > 6533inline auto invoke_deoptimized (Fn && fn, Args && ... args) -> typename std ::enable_if < std::is_same < void, decltype ( fn (args...)) > ::value > ::type { 6534std ::forward < Fn > (fn) (std::forward < Args... > (args...)); 6535} 6536} // namespace Benchmark 6537} // namespace Catch 6538 6539// end catch_optimizer.hpp 6540// start catch_complete_invoke.hpp 6541 6542// Invoke with a special case for void 6543 6544 6545#include <type_traits> 6546#include <utility> 6547 6548namespace Catch { 6549namespace Benchmark { 6550namespace Detail { 6551template < typename T > 6552struct CompleteType { using type = T ; }; 6553template <> 6554struct CompleteType < void > { struct type {}; }; 6555 6556template < typename T > 6557using CompleteType_t = typename CompleteType < T > ::type; 6558 6559template < typename Result > 6560struct CompleteInvoker { 6561template < typename Fun, typename... Args > 6562static Result invoke (Fun && fun, Args && ... args) { 6563return std::forward < Fun > (fun)(std::forward < Args > (args)...); 6564} 6565}; 6566template <> 6567struct CompleteInvoker < void > { 6568template < typename Fun, typename... Args > 6569static CompleteType_t < void > invoke (Fun && fun, Args && ... args) { 6570std ::forward < Fun > (fun)(std::forward < Args > (args)...); 6571return {}; 6572} 6573}; 6574 6575// invoke and not return void :( 6576template < typename Fun, typename... Args > 6577CompleteType_t < FunctionReturnType < Fun, Args...>> complete_invoke (Fun && fun, Args && ... args) { 6578return CompleteInvoker < FunctionReturnType < Fun, Args...>>:: invoke (std::forward < Fun > (fun), std::forward < Args > (args)...); 6579} 6580 6581const std ::string benchmarkErrorMsg = "a benchmark failed to run successfully" ; 6582} // namespace Detail 6583 6584template < typename Fun > 6585Detail::CompleteType_t < FunctionReturnType < Fun>> user_code (Fun && fun) { 6586CATCH_TRY { 6587return Detail:: complete_invoke (std::forward < Fun > (fun)); 6588} CATCH_CATCH_ALL { 6589getResultCapture (). benchmarkFailed ( translateActiveException ()); 6590CATCH_RUNTIME_ERROR ( Detail :: benchmarkErrorMsg ); 6591} 6592} 6593} // namespace Benchmark 6594} // namespace Catch 6595 6596// end catch_complete_invoke.hpp 6597namespace Catch { 6598namespace Benchmark { 6599namespace Detail { 6600struct ChronometerConcept { 6601virtual void start () = 0 ; 6602virtual void finish () = 0 ; 6603virtual ~ ChronometerConcept () = default ; 6604}; 6605template < typename Clock > 6606struct ChronometerModel final : public ChronometerConcept { 6607void start () override { started = Clock:: now (); } 6608void finish () override { finished = Clock:: now (); } 6609 6610ClockDuration < Clock > elapsed () const { return finished - started; } 6611 6612TimePoint < Clock > started; 6613TimePoint < Clock > finished; 6614}; 6615} // namespace Detail 6616 6617struct Chronometer { 6618public : 6619template < typename Fun > 6620void measure ( Fun && fun ) { measure ( std :: forward < Fun > ( fun ), is_callable < Fun ( int ) > ( )); } 6621 6622int runs () const { return k ; } 6623 6624Chronometer ( Detail ::ChronometerConcept & meter, int k) 6625: impl ( & meter) 6626, k ( k ) {} 6627 6628private: 6629template < typename Fun > 6630void measure ( Fun && fun, std ::false_type) { 6631measure([ & fun]( int ) { return fun (); }, std :: true_type ()); 6632} 6633 6634template < typename Fun > 6635void measure ( Fun && fun, std ::true_type) { 6636Detail :: optimizer_barrier (); 6637impl -> start (); 6638for ( int i = 0 ; i < k; ++ i) invoke_deoptimized (fun, i); 6639impl -> finish (); 6640Detail :: optimizer_barrier (); 6641} 6642 6643Detail :: ChronometerConcept * impl; 6644int k; 6645}; 6646} // namespace Benchmark 6647} // namespace Catch 6648 6649// end catch_chronometer.hpp 6650// start catch_environment.hpp 6651 6652// Environment information 6653 6654 6655namespace Catch { 6656namespace Benchmark { 6657template < typename Duration > 6658struct EnvironmentEstimate { 6659Duration mean; 6660OutlierClassification outliers; 6661 6662template < typename Duration2 > 6663operator EnvironmentEstimate < Duration2 > () const { 6664return { mean, outliers }; 6665} 6666}; 6667template < typename Clock > 6668struct Environment { 6669using clock_type = Clock; 6670EnvironmentEstimate < FloatDuration < Clock>> clock_resolution; 6671EnvironmentEstimate < FloatDuration < Clock>> clock_cost; 6672}; 6673} // namespace Benchmark 6674} // namespace Catch 6675 6676// end catch_environment.hpp 6677// start catch_execution_plan.hpp 6678 6679// Execution plan 6680 6681 6682// start catch_benchmark_function.hpp 6683 6684// Dumb std::function implementation for consistent call overhead 6685 6686 6687#include <cassert> 6688#include <type_traits> 6689#include <utility> 6690#include <memory> 6691 6692namespace Catch { 6693namespace Benchmark { 6694namespace Detail { 6695template < typename T > 6696using Decay = typename std ::decay < T > ::type; 6697template < typename T , typename U > 6698struct is_related 6699: std::is_same < Decay < T > , Decay < U >> {}; 6700 6701/// We need to reinvent std::function because every piece of code that might add overhead 6702/// in a measurement context needs to have consistent performance characteristics so that we 6703/// can account for it in the measurement. 6704/// Implementations of std::function with optimizations that aren't always applicable, like 6705/// small buffer optimizations, are not uncommon. 6706/// This is effectively an implementation of std::function without any such optimizations; 6707/// it may be slow, but it is consistently slow. 6708struct BenchmarkFunction { 6709private : 6710struct callable { 6711virtual void call ( Chronometer meter) const = 0 ; 6712virtual callable * clone () const = 0 ; 6713virtual ~ callable () = default ; 6714}; 6715template < typename Fun > 6716struct model : public callable { 6717model (Fun && fun) : fun (std:: move (fun)) {} 6718model (Fun const & fun) : fun (fun) {} 6719 6720model < Fun >* clone () const override { return new model < Fun > ( * this ); } 6721 6722void call ( Chronometer meter) const override { 6723call (meter, is_callable < Fun (Chronometer) > ()); 6724} 6725void call ( Chronometer meter, std ::true_type) const { 6726fun (meter); 6727} 6728void call ( Chronometer meter, std ::false_type) const { 6729meter. measure (fun); 6730} 6731 6732Fun fun; 6733}; 6734 6735struct do_nothing { void operator ()() const {} }; 6736 6737template < typename T > 6738BenchmarkFunction (model < T >* c) : f (c) {} 6739 6740public : 6741BenchmarkFunction () 6742: f( new model < do_nothing > { {} }) {} 6743 6744template < typename Fun, 6745typename std ::enable_if < !is_related < Fun, BenchmarkFunction > ::value, int > ::type = 0 > 6746BenchmarkFunction (Fun && fun) 6747: f( new model < typename std::decay < Fun > ::type > (std::forward < Fun > (fun))) {} 6748 6749BenchmarkFunction (BenchmarkFunction && that) 6750: f ( std :: move (that. f )) {} 6751 6752BenchmarkFunction( BenchmarkFunction const & that) 6753: f ( that .f -> clone ()) {} 6754 6755BenchmarkFunction & operator = (BenchmarkFunction && that) { 6756f = std:: move (that. f ); 6757return * this; 6758} 6759 6760BenchmarkFunction & operator = ( BenchmarkFunction const & that ) { 6761f. reset (that. f -> clone ()); 6762return * this; 6763} 6764 6765void operator ()( Chronometer meter) const { f -> call (meter); } 6766 6767private : 6768std ::unique_ptr < callable > f; 6769}; 6770} // namespace Detail 6771} // namespace Benchmark 6772} // namespace Catch 6773 6774// end catch_benchmark_function.hpp 6775// start catch_repeat.hpp 6776 6777// repeat algorithm 6778 6779 6780#include <type_traits> 6781#include <utility> 6782 6783namespace Catch { 6784namespace Benchmark { 6785namespace Detail { 6786template < typename Fun > 6787struct repeater { 6788void operator ()( int k) const { 6789for ( int i = 0 ; i < k; ++ i) { 6790fun (); 6791} 6792} 6793Fun fun; 6794}; 6795template < typename Fun > 6796repeater < typename std ::decay < Fun > ::type > repeat (Fun && fun) { 6797return { std ::forward < Fun > (fun) }; 6798} 6799} // namespace Detail 6800} // namespace Benchmark 6801} // namespace Catch 6802 6803// end catch_repeat.hpp 6804// start catch_run_for_at_least.hpp 6805 6806// Run a function for a minimum amount of time 6807 6808 6809// start catch_measure.hpp 6810 6811// Measure 6812 6813 6814// start catch_timing.hpp 6815 6816// Timing 6817 6818 6819#include <tuple> 6820#include <type_traits> 6821 6822namespace Catch { 6823namespace Benchmark { 6824template < typename Duration, typename Result > 6825struct Timing { 6826Duration elapsed; 6827Result result; 6828int iterations; 6829}; 6830template < typename Clock, typename Func, typename... Args > 6831using TimingOf = Timing < ClockDuration < Clock > , Detail::CompleteType_t < FunctionReturnType < Func, Args...>> > ; 6832} // namespace Benchmark 6833} // namespace Catch 6834 6835// end catch_timing.hpp 6836#include <utility> 6837 6838namespace Catch { 6839namespace Benchmark { 6840namespace Detail { 6841template < typename Clock, typename Fun, typename... Args > 6842TimingOf < Clock, Fun, Args... > measure (Fun && fun, Args && ... args) { 6843auto start = Clock:: now (); 6844auto && r = Detail:: complete_invoke (fun, std::forward < Args > (args)...); 6845auto end = Clock:: now (); 6846auto delta = end - start; 6847return { delta, std::forward < decltype ( r ) > (r), 1 }; 6848} 6849} // namespace Detail 6850} // namespace Benchmark 6851} // namespace Catch 6852 6853// end catch_measure.hpp 6854#include <utility> 6855#include <type_traits> 6856 6857namespace Catch { 6858namespace Benchmark { 6859namespace Detail { 6860template < typename Clock, typename Fun > 6861TimingOf < Clock, Fun, int > measure_one (Fun && fun, int iters, std::false_type) { 6862return Detail::measure < Clock > (fun, iters); 6863} 6864template < typename Clock, typename Fun > 6865TimingOf < Clock, Fun, Chronometer > measure_one (Fun && fun, int iters, std::true_type) { 6866Detail::ChronometerModel < Clock > meter; 6867auto && result = Detail:: complete_invoke ( fun , Chronometer ( meter , iters )); 6868 6869return { meter. elapsed (), std:: move (result), iters }; 6870} 6871 6872template < typename Clock, typename Fun > 6873using run_for_at_least_argument_t = typename std ::conditional < is_callable < Fun (Chronometer) > ::value, Chronometer, int > ::type; 6874 6875struct optimized_away_error : std::exception { 6876const char * what () const noexcept override { 6877return "could not measure benchmark, maybe it was optimized away" ; 6878} 6879}; 6880 6881template < typename Clock, typename Fun > 6882TimingOf < Clock, Fun, run_for_at_least_argument_t < Clock, Fun>> run_for_at_least (ClockDuration < Clock > how_long, int seed, Fun && fun) { 6883auto iters = seed; 6884while (iters < ( 1 << 30 )) { 6885auto && Timing = measure_one < Clock > (fun, iters, is_callable < Fun (Chronometer) > ()); 6886 6887if (Timing. elapsed >= how_long) { 6888return { Timing. elapsed , std:: move (Timing. result ), iters }; 6889} 6890iters *= 2 ; 6891} 6892Catch ::throw_exception(optimized_away_error{}); 6893} 6894} // namespace Detail 6895} // namespace Benchmark 6896} // namespace Catch 6897 6898// end catch_run_for_at_least.hpp 6899#include <algorithm> 6900#include <iterator> 6901 6902namespace Catch { 6903namespace Benchmark { 6904template < typename Duration > 6905struct ExecutionPlan { 6906int iterations_per_sample; 6907Duration estimated_duration; 6908Detail :: BenchmarkFunction benchmark; 6909Duration warmup_time; 6910int warmup_iterations; 6911 6912template < typename Duration2 > 6913operator ExecutionPlan < Duration2 > () const { 6914return { iterations_per_sample, estimated_duration, benchmark, warmup_time, warmup_iterations }; 6915} 6916 6917template < typename Clock > 6918std::vector < FloatDuration < Clock>> run (const IConfig & cfg, Environment < FloatDuration < Clock>> env) const { 6919// warmup a bit 6920Detail ::run_for_at_least < Clock > (std::chrono::duration_cast < ClockDuration < Clock>>(warmup_time), warmup_iterations, Detail:: repeat (now < Clock > {})); 6921 6922std ::vector < FloatDuration < Clock>> times; 6923times. reserve (cfg. benchmarkSamples ()); 6924std :: generate_n ( std :: back_inserter (times), cfg. benchmarkSamples (), [this, env] { 6925Detail ::ChronometerModel < Clock > model; 6926this -> benchmark ( Chronometer (model, iterations_per_sample)); 6927auto sample_time = model. elapsed () - env. clock_cost . mean ; 6928if (sample_time < FloatDuration < Clock > :: zero ()) sample_time = FloatDuration < Clock > :: zero (); 6929return sample_time / iterations_per_sample; 6930}); 6931return times; 6932} 6933}; 6934} // namespace Benchmark 6935} // namespace Catch 6936 6937// end catch_execution_plan.hpp 6938// start catch_estimate_clock.hpp 6939 6940// Environment measurement 6941 6942 6943// start catch_stats.hpp 6944 6945// Statistical analysis tools 6946 6947 6948#include <algorithm> 6949#include <functional> 6950#include <vector> 6951#include <iterator> 6952#include <numeric> 6953#include <tuple> 6954#include <cmath> 6955#include <utility> 6956#include <cstddef> 6957#include <random> 6958 6959namespace Catch { 6960namespace Benchmark { 6961namespace Detail { 6962using sample = std::vector < double > ; 6963 6964double weighted_average_quantile ( int k, int q, std ::vector < double > ::iterator first, std ::vector < double > ::iterator last); 6965 6966template < typename Iterator > 6967OutlierClassification classify_outliers( Iterator first, Iterator last) { 6968std ::vector < double > copy (first, last); 6969 6970auto q1 = weighted_average_quantile ( 1 , 4 , copy. begin (), copy. end ()); 6971auto q3 = weighted_average_quantile ( 3 , 4 , copy. begin (), copy. end ()); 6972auto iqr = q3 - q1; 6973auto los = q1 - (iqr * 3. ); 6974auto lom = q1 - (iqr * 1.5 ); 6975auto him = q3 + (iqr * 1.5 ); 6976auto his = q3 + (iqr * 3. ); 6977 6978OutlierClassification o; 6979for (; first != last; ++ first) { 6980auto && t = * first; 6981if (t < los) ++ o. low_severe ; 6982else if (t < lom) ++ o. low_mild ; 6983else if (t > his) ++ o. high_severe ; 6984else if (t > him) ++ o. high_mild ; 6985++ o. samples_seen ; 6986} 6987return o; 6988} 6989 6990template < typename Iterator > 6991double mean (Iterator first, Iterator last) { 6992auto count = last - first; 6993double sum = std:: accumulate (first, last, 0. ); 6994return sum / count; 6995} 6996 6997template < typename URng, typename Iterator, typename Estimator > 6998sample resample (URng & rng, int resamples, Iterator first, Iterator last, Estimator & estimator) { 6999auto n = last - first; 7000std ::uniform_int_distribution < decltype (n) > dist ( 0 , n - 1 ); 7001 7002sample out; 7003out. reserve (resamples); 7004std :: generate_n ( std :: back_inserter (out), resamples, [n, first, & estimator, & dist, & rng] { 7005std::vector < double > resampled; 7006resampled. reserve (n); 7007std :: generate_n ( std :: back_inserter (resampled), n, [first, & dist, & rng] { return first[ dist (rng)]; }); 7008return estimator (resampled. begin (), resampled. end ()); 7009}); 7010std :: sort (out. begin (), out. end ()); 7011return out; 7012} 7013 7014template < typename Estimator, typename Iterator > 7015sample jackknife (Estimator && estimator, Iterator first, Iterator last) { 7016auto n = last - first; 7017auto second = std:: next ( first ); 7018sample results; 7019results. reserve (n); 7020 7021for (auto it = first; it != last; ++ it) { 7022std :: iter_swap (it, first); 7023results. push_back ( estimator (second, last)); 7024} 7025 7026return results; 7027} 7028 7029inline double normal_cdf ( double x) { 7030return std:: erfc ( - x / std:: sqrt ( 2.0 )) / 2.0 ; 7031} 7032 7033double erfc_inv ( double x); 7034 7035double normal_quantile ( double p); 7036 7037template < typename Iterator, typename Estimator > 7038Estimate < double > bootstrap (double confidence_level, Iterator first, Iterator last, sample const & resample, Estimator && estimator) { 7039auto n_samples = last - first; 7040 7041double point = estimator (first, last); 7042// Degenerate case with a single sample 7043if (n_samples == 1 ) return { point, point, point, confidence_level }; 7044 7045sample jack = jackknife (estimator, first, last); 7046double jack_mean = mean (jack. begin (), jack. end ()); 7047double sum_squares, sum_cubes; 7048std :: tie (sum_squares, sum_cubes) = std:: accumulate (jack. begin (), jack. end (), std:: make_pair ( 0. , 0. ), [jack_mean](std::pair < double, double > sqcb, double x) -> std ::pair < double, double > { 7049auto d = jack_mean - x; 7050auto d2 = d * d; 7051auto d3 = d2 * d; 7052return { sqcb. first + d2, sqcb. second + d3 }; 7053}); 7054 7055double accel = sum_cubes / ( 6 * std:: pow (sum_squares, 1.5 )); 7056int n = static_cast < int > (resample. size ()); 7057double prob_n = std:: count_if (resample. begin (), resample. end (), [point](double x) { return x < point; }) / ( double )n; 7058// degenerate case with uniform samples 7059if (prob_n == 0 ) return { point, point, point, confidence_level }; 7060 7061double bias = normal_quantile (prob_n); 7062double z1 = normal_quantile (( 1. - confidence_level) / 2. ); 7063 7064auto cumn = [n]( double x) -> int { 7065return std:: lround ( normal_cdf (x) * n); }; 7066auto a = [bias, accel ]( double b) { return bias + b / ( 1. - accel * b); }; 7067double b1 = bias + z1; 7068double b2 = bias - z1; 7069double a1 = a (b1); 7070double a2 = a (b2); 7071auto lo = ( std ::max)( cumn ( a1 ), 0 ); 7072auto hi = ( std ::min)( cumn ( a2 ), n - 1 ); 7073 7074return { point, resample[lo], resample[hi], confidence_level }; 7075} 7076 7077double outlier_variance ( Estimate < double > mean, Estimate < double > stddev, int n); 7078 7079struct bootstrap_analysis { 7080Estimate < double > mean ; 7081Estimate < double > standard_deviation ; 7082double outlier_variance ; 7083}; 7084 7085bootstrap_analysis analyse_samples ( double confidence_level, int n_resamples, std ::vector < double > ::iterator first, std ::vector < double > ::iterator last); 7086} // namespace Detail 7087} // namespace Benchmark 7088} // namespace Catch 7089 7090// end catch_stats.hpp 7091#include <algorithm> 7092#include <iterator> 7093#include <tuple> 7094#include <vector> 7095#include <cmath> 7096 7097namespace Catch { 7098namespace Benchmark { 7099namespace Detail { 7100template < typename Clock > 7101std::vector < double > resolution (int k) { 7102std ::vector < TimePoint < Clock>> times; 7103times. reserve (k + 1 ); 7104std :: generate_n ( std :: back_inserter (times), k + 1 , now < Clock > {}); 7105 7106std ::vector < double > deltas; 7107deltas. reserve (k); 7108std :: transform ( std :: next (times. begin ()), times. end (), times. begin (), 7109std:: back_inserter (deltas), 7110[](TimePoint < Clock > a, TimePoint < Clock > b) { return static_cast < double > ((a - b). count ()); }); 7111 7112return deltas; 7113} 7114 7115const auto warmup_iterations = 10000 ; 7116const auto warmup_time = std::chrono:: milliseconds ( 100 ); 7117const auto minimum_ticks = 1000 ; 7118const auto warmup_seed = 10000 ; 7119const auto clock_resolution_estimation_time = std::chrono:: milliseconds ( 500 ); 7120const auto clock_cost_estimation_time_limit = std::chrono:: seconds ( 1 ); 7121const auto clock_cost_estimation_tick_limit = 100000 ; 7122const auto clock_cost_estimation_time = std::chrono:: milliseconds ( 10 ); 7123const auto clock_cost_estimation_iterations = 10000 ; 7124 7125template < typename Clock > 7126int warmup () { 7127return run_for_at_least < Clock > (std::chrono::duration_cast < ClockDuration < Clock>>(warmup_time), warmup_seed, & resolution < Clock > ) 7128. iterations ; 7129} 7130template < typename Clock > 7131EnvironmentEstimate < FloatDuration < Clock>> estimate_clock_resolution (int iterations) { 7132auto r = run_for_at_least < Clock > (std::chrono::duration_cast < ClockDuration < Clock>>(clock_resolution_estimation_time), iterations, & resolution < Clock > ) 7133. result ; 7134return { 7135FloatDuration < Clock > ( mean (r. begin (), r. end ())), 7136classify_outliers (r. begin (), r. end ()), 7137}; 7138} 7139template < typename Clock > 7140EnvironmentEstimate < FloatDuration < Clock>> estimate_clock_cost (FloatDuration < Clock > resolution) { 7141auto time_limit = ( std ::min)( 7142resolution * clock_cost_estimation_tick_limit, 7143FloatDuration < Clock > (clock_cost_estimation_time_limit)); 7144auto time_clock = []( int k) { 7145return Detail::measure < Clock > ([k] { 7146for ( int i = 0 ; i < k; ++ i) { 7147volatile auto ignored = Clock:: now (); 7148( void )ignored; 7149} 7150}). elapsed ; 7151}; 7152time_clock ( 1 ); 7153int iters = clock_cost_estimation_iterations; 7154auto && r = run_for_at_least < Clock > (std::chrono::duration_cast < ClockDuration < Clock>>(clock_cost_estimation_time), iters, time_clock); 7155std ::vector < double > times; 7156int nsamples = static_cast < int > (std:: ceil (time_limit / r. elapsed )); 7157times. reserve (nsamples); 7158std :: generate_n ( std :: back_inserter (times), nsamples, [time_clock, & r] { 7159return static_cast < double > (( time_clock (r. iterations ) / r. iterations ). count ()); 7160}); 7161return { 7162FloatDuration < Clock > ( mean (times. begin (), times. end ())), 7163classify_outliers (times. begin (), times. end ()), 7164}; 7165} 7166 7167template < typename Clock > 7168Environment < FloatDuration < Clock>> measure_environment () { 7169static Environment < FloatDuration < Clock>> * env = nullptr ; 7170if (env) { 7171return * env; 7172} 7173 7174auto iters = Detail::warmup < Clock > (); 7175auto resolution = Detail::estimate_clock_resolution < Clock > (iters); 7176auto cost = Detail::estimate_clock_cost < Clock > (resolution.mean); 7177 7178env = new Environment < FloatDuration < Clock>>{ resolution, cost }; 7179return * env; 7180} 7181} // namespace Detail 7182} // namespace Benchmark 7183} // namespace Catch 7184 7185// end catch_estimate_clock.hpp 7186// start catch_analyse.hpp 7187 7188// Run and analyse one benchmark 7189 7190 7191// start catch_sample_analysis.hpp 7192 7193// Benchmark results 7194 7195 7196#include <algorithm> 7197#include <vector> 7198#include <string> 7199#include <iterator> 7200 7201namespace Catch { 7202namespace Benchmark { 7203template < typename Duration > 7204struct SampleAnalysis { 7205std ::vector < Duration > samples; 7206Estimate < Duration > mean; 7207Estimate < Duration > standard_deviation; 7208OutlierClassification outliers; 7209double outlier_variance; 7210 7211template < typename Duration2 > 7212operator SampleAnalysis < Duration2 > () const { 7213std ::vector < Duration2 > samples2; 7214samples2. reserve (samples. size ()); 7215std :: transform (samples. begin (), samples. end (), std:: back_inserter (samples2), [](Duration d) { return Duration2 (d); }); 7216return { 7217std :: move (samples2), 7218mean, 7219standard_deviation, 7220outliers, 7221outlier_variance, 7222}; 7223} 7224}; 7225} // namespace Benchmark 7226} // namespace Catch 7227 7228// end catch_sample_analysis.hpp 7229#include <algorithm> 7230#include <iterator> 7231#include <vector> 7232 7233namespace Catch { 7234namespace Benchmark { 7235namespace Detail { 7236template < typename Duration, typename Iterator > 7237SampleAnalysis < Duration > analyse (const IConfig & cfg, Environment < Duration > , Iterator first, Iterator last) { 7238if (!cfg. benchmarkNoAnalysis ()) { 7239std ::vector < double > samples; 7240samples. reserve (last - first); 7241std :: transform (first, last, std:: back_inserter (samples), [](Duration d) { return d. count (); }); 7242 7243auto analysis = Catch::Benchmark::Detail:: analyse_samples ( cfg . benchmarkConfidenceInterval (), cfg . benchmarkResamples (), samples . begin (), samples . end ()); 7244auto outliers = Catch::Benchmark::Detail:: classify_outliers ( samples . begin (), samples . end ()); 7245 7246auto wrap_estimate = [](Estimate < double > e) { 7247return Estimate < Duration > { 7248Duration (e. point ), 7249Duration (e. lower_bound ), 7250Duration (e. upper_bound ), 7251e. confidence_interval , 7252}; 7253}; 7254std ::vector < Duration > samples2; 7255samples2. reserve (samples. size ()); 7256std :: transform (samples. begin (), samples. end (), std:: back_inserter (samples2), []( double d) { return Duration (d); }); 7257return { 7258std :: move (samples2), 7259wrap_estimate (analysis. mean ), 7260wrap_estimate (analysis. standard_deviation ), 7261outliers, 7262analysis. outlier_variance , 7263}; 7264} else { 7265std ::vector < Duration > samples; 7266samples. reserve (last - first); 7267 7268Duration mean = Duration ( 0 ); 7269int i = 0 ; 7270for (auto it = first; it < last; ++ it, ++ i) { 7271samples. push_back ( Duration ( * it)); 7272mean += Duration ( * it); 7273} 7274mean /= i; 7275 7276return { 7277std :: move (samples), 7278Estimate < Duration > {mean, mean, mean, 0.0 }, 7279Estimate < Duration > { Duration ( 0 ), Duration ( 0 ), Duration ( 0 ), 0.0 }, 7280OutlierClassification{}, 72810.0 7282}; 7283} 7284} 7285} // namespace Detail 7286} // namespace Benchmark 7287} // namespace Catch 7288 7289// end catch_analyse.hpp 7290#include <algorithm> 7291#include <functional> 7292#include <string> 7293#include <vector> 7294#include <cmath> 7295 7296namespace Catch { 7297namespace Benchmark { 7298struct Benchmark { 7299Benchmark( std :: string && name) 7300: name ( std :: move ( name )) {} 7301 7302template < class FUN > 7303Benchmark ( std ::string && name, FUN && func) 7304: fun(std:: move (func)), name ( std :: move ( name )) {} 7305 7306template < typename Clock > 7307ExecutionPlan < FloatDuration < Clock >> prepare ( const IConfig & cfg, Environment < FloatDuration < Clock>> env) const { 7308auto min_time = env . clock_resolution . mean * Detail ::minimum_ticks; 7309auto run_time = std ::max(min_time, std::chrono::duration_cast < decltype (min_time) > (cfg. benchmarkWarmupTime ())); 7310auto && test = Detail ::run_for_at_least < Clock > (std::chrono::duration_cast < ClockDuration < Clock>>(run_time), 1 , fun); 7311int new_iters = static_cast < int > ( std :: ceil (min_time * test. iterations / test. elapsed )); 7312return { new_iters , test . elapsed / test . iterations * new_iters * cfg . benchmarkSamples (), fun , std ::chrono::duration_cast < FloatDuration < Clock>>(cfg. benchmarkWarmupTime ()), Detail ::warmup_iterations }; 7313} 7314 7315template < typename Clock = default_clock > 7316void run () { 7317IConfigPtr cfg = getCurrentContext (). getConfig (); 7318 7319auto env = Detail::measure_environment < Clock > (); 7320 7321getResultCapture (). benchmarkPreparing (name); 7322CATCH_TRY { 7323auto plan = user_code([ & ] { 7324return prepare < Clock > ( * cfg, env); 7325}); 7326 7327BenchmarkInfo info { 7328name, 7329plan. estimated_duration . count (), 7330plan. iterations_per_sample , 7331cfg -> benchmarkSamples (), 7332cfg -> benchmarkResamples (), 7333env. clock_resolution . mean . count (), 7334env. clock_cost . mean . count () 7335}; 7336 7337getResultCapture (). benchmarkStarting (info); 7338 7339auto samples = user_code([ & ] { 7340return plan. template run < Clock > ( * cfg, env); 7341}); 7342 7343auto analysis = Detail::analyse( * cfg, env, samples. begin (), samples. end ()); 7344BenchmarkStats < FloatDuration < Clock>> stats{ info, analysis. samples , analysis. mean , analysis. standard_deviation , analysis. outliers , analysis. outlier_variance }; 7345getResultCapture (). benchmarkEnded (stats); 7346 7347} CATCH_CATCH_ALL { 7348if ( translateActiveException () != Detail::benchmarkErrorMsg) // benchmark errors have been reported, otherwise rethrow. 7349std ::rethrow_exception( std :: current_exception ()); 7350} 7351} 7352 7353// sets lambda to be used in fun *and* executes benchmark! 7354template < typename Fun, 7355typename std ::enable_if < !Detail::is_related < Fun, Benchmark > ::value, int > ::type = 0 > 7356Benchmark & operator = (Fun func ) { 7357fun = Detail:: BenchmarkFunction (func); 7358run (); 7359return * this; 7360} 7361 7362explicit operator bool () { 7363return true; 7364} 7365 7366private : 7367Detail :: BenchmarkFunction fun; 7368std :: string name; 7369}; 7370} 7371} // namespace Catch 7372 7373#define INTERNAL_CATCH_GET_1_ARG (arg1, arg2, ...) arg1 7374#define INTERNAL_CATCH_GET_2_ARG (arg1, arg2, ...) arg2 7375 7376#define INTERNAL_CATCH_BENCHMARK (BenchmarkName, name, benchmarkIndex)\ 7377if( Catch::Benchmark::Benchmark BenchmarkName{name} ) \ 7378BenchmarkName = [&](int benchmarkIndex) 7379 7380#define INTERNAL_CATCH_BENCHMARK_ADVANCED (BenchmarkName, name)\ 7381if( Catch::Benchmark::Benchmark BenchmarkName{name} ) \ 7382BenchmarkName = [&] 7383 7384// end catch_benchmark.hpp 7385// start catch_constructor.hpp 7386 7387// Constructor and destructor helpers 7388 7389 7390#include <type_traits> 7391 7392namespace Catch { 7393namespace Benchmark { 7394namespace Detail { 7395template < typename T , bool Destruct > 7396struct ObjectStorage 7397{ 7398using TStorage = typename std ::aligned_storage < sizeof ( T ), std::alignment_of < T > ::value > ::type; 7399 7400ObjectStorage () : data () {} 7401 7402ObjectStorage( const ObjectStorage & other) 7403{ 7404new ( & data) T (other. stored_object ()); 7405} 7406 7407ObjectStorage (ObjectStorage && other) 7408{ 7409new ( & data) T ( std :: move (other. stored_object ())); 7410} 7411 7412~ ObjectStorage () { destruct_on_exit < T > (); } 7413 7414template < typename... Args > 7415void construct (Args && ... args) 7416{ 7417new ( & data) T (std::forward < Args > (args)...); 7418} 7419 7420template < bool AllowManualDestruction = !Destruct > 7421typename std::enable_if < AllowManualDestruction > ::type destruct () 7422{ 7423stored_object ().~ T (); 7424} 7425 7426private : 7427// If this is a constructor benchmark, destruct the underlying object 7428template < typename U > 7429void destruct_on_exit (typename std::enable_if < Destruct, U > ::type * = 0 ) { destruct < true > (); } 7430// Otherwise, don't 7431template < typename U > 7432void destruct_on_exit (typename std::enable_if < !Destruct, U > ::type * = 0 ) { } 7433 7434T & stored_object () { 7435return * static_cast < T *> (static_cast < void *> ( & data)); 7436} 7437 7438T const & stored_object () const { 7439return * static_cast < T *> (static_cast < void *> ( & data)); 7440} 7441 7442TStorage data; 7443}; 7444} 7445 7446template < typename T > 7447using storage_for = Detail::ObjectStorage < T , true > ; 7448 7449template < typename T > 7450using destructable_object = Detail::ObjectStorage < T , false > ; 7451} 7452} 7453 7454// end catch_constructor.hpp 7455// end catch_benchmarking_all.hpp 7456#endif 7457 7458#endif // ! CATCH_CONFIG_IMPL_ONLY 7459 7460#ifdef CATCH_IMPL 7461// start catch_impl.hpp 7462 7463#ifdef __clang__ 7464#pragma clang diagnostic push 7465#pragma clang diagnostic ignored "-Wweak-vtables" 7466#endif 7467 7468// Keep these here for external reporters 7469// start catch_test_case_tracker.h 7470 7471#include <string> 7472#include <vector> 7473#include <memory> 7474 7475namespace Catch { 7476namespace TestCaseTracking { 7477 7478struct NameAndLocation { 7479std :: string name ; 7480SourceLineInfo location ; 7481 7482NameAndLocation( std :: string const & _name , SourceLineInfo const & _location ); 7483friend bool operator == ( NameAndLocation const & lhs , NameAndLocation const & rhs) { 7484return lhs.name == rhs.name 7485&& lhs.location == rhs. location ; 7486} 7487}; 7488 7489class ITracker; 7490 7491using ITrackerPtr = std::shared_ptr < ITracker > ; 7492 7493class ITracker { 7494NameAndLocation m_nameAndLocation; 7495 7496public : 7497ITracker( NameAndLocation const & nameAndLoc) : 7498m_nameAndLocation ( nameAndLoc ) 7499{} 7500 7501// static queries 7502NameAndLocation const & nameAndLocation () const { 7503return m_nameAndLocation; 7504} 7505 7506virtual ~ ITracker (); 7507 7508// dynamic queries 7509virtual bool isComplete () const = 0 ; // Successfully completed or failed 7510virtual bool isSuccessfullyCompleted () const = 0 ; 7511virtual bool isOpen () const = 0 ; // Started but not complete 7512virtual bool hasChildren () const = 0 ; 7513virtual bool hasStarted () const = 0 ; 7514 7515virtual ITracker & parent () = 0 ; 7516 7517// actions 7518virtual void close () = 0 ; // Successfully complete 7519virtual void fail () = 0 ; 7520virtual void markAsNeedingAnotherRun () = 0 ; 7521 7522virtual void addChild ( ITrackerPtr const & child ) = 0 ; 7523virtual ITrackerPtr findChild( NameAndLocation const & nameAndLocation ) = 0 ; 7524virtual void openChild () = 0 ; 7525 7526// Debug/ checking 7527virtual bool isSectionTracker () const = 0 ; 7528virtual bool isGeneratorTracker () const = 0 ; 7529}; 7530 7531class TrackerContext { 7532 7533enum RunState { 7534NotStarted, 7535Executing, 7536CompletedCycle 7537}; 7538 7539ITrackerPtr m_rootTracker; 7540ITracker * m_currentTracker = nullptr ; 7541RunState m_runState = NotStarted; 7542 7543public : 7544 7545ITracker & startRun (); 7546void endRun (); 7547 7548void startCycle (); 7549void completeCycle (); 7550 7551bool completedCycle () const ; 7552ITracker & currentTracker (); 7553void setCurrentTracker ( ITracker * tracker ); 7554}; 7555 7556class TrackerBase : public ITracker { 7557protected : 7558enum CycleState { 7559NotStarted, 7560Executing, 7561ExecutingChildren, 7562NeedsAnotherRun, 7563CompletedSuccessfully, 7564Failed 7565}; 7566 7567using Children = std::vector < ITrackerPtr > ; 7568TrackerContext & m_ctx; 7569ITracker * m_parent; 7570Children m_children; 7571CycleState m_runState = NotStarted; 7572 7573public : 7574TrackerBase( NameAndLocation const & nameAndLocation, TrackerContext & ctx, ITracker * parent ); 7575 7576bool isComplete () const override ; 7577bool isSuccessfullyCompleted () const override; 7578bool isOpen () const override; 7579bool hasChildren () const override; 7580bool hasStarted () const override { 7581return m_runState != NotStarted; 7582} 7583 7584void addChild ( ITrackerPtr const & child ) override; 7585 7586ITrackerPtr findChild ( NameAndLocation const & nameAndLocation ) override; 7587ITracker & parent () override; 7588 7589void openChild () override ; 7590 7591bool isSectionTracker () const override; 7592bool isGeneratorTracker () const override; 7593 7594void open (); 7595 7596void close () override; 7597void fail () override; 7598void markAsNeedingAnotherRun () override; 7599 7600private: 7601void moveToParent (); 7602void moveToThis (); 7603}; 7604 7605class SectionTracker : public TrackerBase { 7606std ::vector < std::string > m_filters; 7607std :: string m_trimmed_name; 7608public : 7609SectionTracker( NameAndLocation const & nameAndLocation, TrackerContext & ctx, ITracker * parent ); 7610 7611bool isSectionTracker () const override ; 7612 7613bool isComplete () const override; 7614 7615static SectionTracker & acquire ( TrackerContext & ctx, NameAndLocation const & nameAndLocation ); 7616 7617void tryOpen (); 7618 7619void addInitialFilters ( std ::vector < std::string > const & filters ); 7620void addNextFilters ( std ::vector < std::string > const & filters ); 7621//! Returns filters active in this tracker 7622std ::vector < std::string > const & getFilters () const; 7623//! Returns whitespace-trimmed name of the tracked section 7624std::string const & trimmedName () const; 7625}; 7626 7627} // namespace TestCaseTracking 7628 7629using TestCaseTracking::ITracker; 7630using TestCaseTracking::TrackerContext; 7631using TestCaseTracking::SectionTracker; 7632 7633} // namespace Catch 7634 7635// end catch_test_case_tracker.h 7636 7637// start catch_leak_detector.h 7638 7639namespace Catch { 7640 7641struct LeakDetector { 7642LeakDetector( ); 7643~ LeakDetector (); 7644}; 7645 7646} 7647// end catch_leak_detector.h 7648// Cpp files will be included in the single-header file here 7649// start catch_stats.cpp 7650 7651// Statistical analysis tools 7652 7653#if defined( CATCH_CONFIG_ENABLE_BENCHMARKING ) 7654 7655#include <cassert> 7656#include <random> 7657 7658#if defined( CATCH_CONFIG_USE_ASYNC ) 7659#include <future> 7660#endif 7661 7662namespace { 7663double erf_inv (double x ) { 7664// Code accompanying the article "Approximating the erfinv function" in GPU Computing Gems, Volume 2 7665double w , p ; 7666 7667w = - log (( 1.0 - x ) * ( 1.0 + x )); 7668 7669if ( w < 6.250000 ) { 7670w = w - 3.125000 ; 7671p = -3.6444120640178196996e-21 ; 7672p = -1.685059138182016589e-19 + p * w ; 7673p = 1.2858480715256400167e-18 + p * w ; 7674p = 1.115787767802518096e-17 + p * w ; 7675p = -1.333171662854620906e-16 + p * w ; 7676p = 2.0972767875968561637e-17 + p * w ; 7677p = 6.6376381343583238325e-15 + p * w ; 7678p = -4.0545662729752068639e-14 + p * w ; 7679p = -8.1519341976054721522e-14 + p * w ; 7680p = 2.6335093153082322977e-12 + p * w ; 7681p = -1.2975133253453532498e-11 + p * w ; 7682p = -5.4154120542946279317e-11 + p * w ; 7683p = 1.051212273321532285e-09 + p * w ; 7684p = -4.1126339803469836976e-09 + p * w ; 7685p = -2.9070369957882005086e-08 + p * w ; 7686p = 4.2347877827932403518e-07 + p * w ; 7687p = -1.3654692000834678645e-06 + p * w ; 7688p = -1.3882523362786468719e-05 + p * w ; 7689p = 0.0001867342080340571352 + p * w ; 7690p = -0.00074070253416626697512 + p * w ; 7691p = -0.0060336708714301490533 + p * w ; 7692p = 0.24015818242558961693 + p * w ; 7693p = 1.6536545626831027356 + p * w ; 7694} else if ( w < 16.000000 ) { 7695w = sqrt ( w ) - 3.250000 ; 7696p = 2.2137376921775787049e-09 ; 7697p = 9.0756561938885390979e-08 + p * w ; 7698p = -2.7517406297064545428e-07 + p * w ; 7699p = 1.8239629214389227755e-08 + p * w ; 7700p = 1.5027403968909827627e-06 + p * w ; 7701p = -4.013867526981545969e-06 + p * w ; 7702p = 2.9234449089955446044e-06 + p * w ; 7703p = 1.2475304481671778723e-05 + p * w ; 7704p = -4.7318229009055733981e-05 + p * w ; 7705p = 6.8284851459573175448e-05 + p * w ; 7706p = 2.4031110387097893999e-05 + p * w ; 7707p = -0.0003550375203628474796 + p * w ; 7708p = 0.00095328937973738049703 + p * w ; 7709p = -0.0016882755560235047313 + p * w ; 7710p = 0.0024914420961078508066 + p * w ; 7711p = -0.0037512085075692412107 + p * w ; 7712p = 0.005370914553590063617 + p * w ; 7713p = 1.0052589676941592334 + p * w ; 7714p = 3.0838856104922207635 + p * w ; 7715} else { 7716w = sqrt ( w ) - 5.000000 ; 7717p = -2.7109920616438573243e-11 ; 7718p = -2.5556418169965252055e-10 + p * w ; 7719p = 1.5076572693500548083e-09 + p * w ; 7720p = -3.7894654401267369937e-09 + p * w ; 7721p = 7.6157012080783393804e-09 + p * w ; 7722p = -1.4960026627149240478e-08 + p * w ; 7723p = 2.9147953450901080826e-08 + p * w ; 7724p = -6.7711997758452339498e-08 + p * w ; 7725p = 2.2900482228026654717e-07 + p * w ; 7726p = -9.9298272942317002539e-07 + p * w ; 7727p = 4.5260625972231537039e-06 + p * w ; 7728p = -1.9681778105531670567e-05 + p * w ; 7729p = 7.5995277030017761139e-05 + p * w ; 7730p = -0.00021503011930044477347 + p * w ; 7731p = -0.00013871931833623122026 + p * w ; 7732p = 1.0103004648645343977 + p * w ; 7733p = 4.8499064014085844221 + p * w ; 7734} 7735return p * x ; 7736} 7737 7738double standard_deviation (std:: vector < double > :: iterator first , std:: vector < double > :: iterator last ) { 7739auto m = Catch :: Benchmark :: Detail :: mean (first, last); 7740double variance = std :: accumulate ( first , last , 0. , [m](double a, double b) { 7741double diff = b - m; 7742return a + diff * diff; 7743}) / (last - first); 7744return std:: sqrt (variance); 7745} 7746 7747} 7748 7749namespace Catch { 7750namespace Benchmark { 7751namespace Detail { 7752 7753double weighted_average_quantile ( int k, int q, std ::vector < double > ::iterator first, std ::vector < double > ::iterator last) { 7754auto count = last - first; 7755double idx = (count - 1 ) * k / static_cast < double > (q); 7756int j = static_cast < int > (idx); 7757double g = idx - j; 7758std :: nth_element (first, first + j, last); 7759auto xj = first[j]; 7760if (g == 0 ) return xj; 7761 7762auto xj1 = * std:: min_element (first + ( j + 1 ), last ); 7763return xj + g * (xj1 - xj); 7764} 7765 7766double erfc_inv ( double x) { 7767return erf_inv ( 1.0 - x); 7768} 7769 7770double normal_quantile ( double p) { 7771static const double ROOT_TWO = std:: sqrt ( 2.0 ); 7772 7773double result = 0.0 ; 7774assert (p >= 0 && p <= 1 ); 7775if (p < 0 || p > 1 ) { 7776return result; 7777} 7778 7779result = - erfc_inv ( 2.0 * p); 7780// result *= normal distribution standard deviation (1.0) * sqrt(2) 7781result *= /*sd * */ ROOT_TWO ; 7782// result += normal disttribution mean (0) 7783return result; 7784} 7785 7786double outlier_variance ( Estimate < double > mean, Estimate < double > stddev, int n) { 7787double sb = stddev. point ; 7788double mn = mean. point / n; 7789double mg_min = mn / 2. ; 7790double sg = (std::min)(mg_min / 4. , sb / std:: sqrt (n)); 7791double sg2 = sg * sg; 7792double sb2 = sb * sb; 7793 7794auto c_max = [n, mn, sb2, sg2]( double x) -> double { 7795double k = mn - x; 7796double d = k * k; 7797double nd = n * d; 7798double k0 = - n * nd; 7799double k1 = sb2 - n * sg2 + nd; 7800double det = k1 * k1 - 4 * sg2 * k0; 7801return ( int )( -2. * k0 / (k1 + std:: sqrt (det))); 7802}; 7803 7804auto var_out = [n, sb2, sg2]( double c) { 7805double nc = n - c; 7806return (nc / n) * (sb2 - nc * sg2); 7807}; 7808 7809return (std::min)( var_out ( 1 ), var_out ((std::min)( c_max ( 0. ), c_max (mg_min)))) / sb2; 7810} 7811 7812bootstrap_analysis analyse_samples ( double confidence_level, int n_resamples, std ::vector < double > ::iterator first, std ::vector < double > ::iterator last) { 7813CATCH_INTERNAL_START_WARNINGS_SUPPRESSION 7814CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS 7815static std ::random_device entropy; 7816CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 7817 7818auto n = static_cast < int > (last - first); // seriously, one can't use integral types without hell in C++ 7819 7820auto mean = & Detail::mean < std::vector < double > ::iterator > ; 7821auto stddev = & standard_deviation; 7822 7823#if defined( CATCH_CONFIG_USE_ASYNC ) 7824auto Estimate = [ = ]( double ( * f)( std ::vector < double > ::iterator, std ::vector < double > ::iterator)) { 7825auto seed = entropy (); 7826return std:: async (std::launch::async, [ = ] { 7827std :: mt19937 rng ( seed ); 7828auto resampled = resample ( rng , n_resamples , first , last , f ); 7829return bootstrap (confidence_level, first, last, resampled, f); 7830}); 7831}; 7832 7833auto mean_future = Estimate ( mean ); 7834auto stddev_future = Estimate ( stddev ); 7835 7836auto mean_estimate = mean_future. get (); 7837auto stddev_estimate = stddev_future. get (); 7838#else 7839auto Estimate = [ = ]( double ( * f)( std ::vector < double > ::iterator, std ::vector < double > ::iterator)) { 7840auto seed = entropy (); 7841std :: mt19937 rng ( seed ); 7842auto resampled = resample ( rng , n_resamples , first , last , f ); 7843return bootstrap (confidence_level, first, last, resampled, f); 7844}; 7845 7846auto mean_estimate = Estimate ( mean ); 7847auto stddev_estimate = Estimate ( stddev ); 7848#endif // CATCH_USE_ASYNC 7849 7850double outlier_variance = Detail:: outlier_variance (mean_estimate, stddev_estimate, n); 7851 7852return { mean_estimate, stddev_estimate, outlier_variance }; 7853} 7854} // namespace Detail 7855} // namespace Benchmark 7856} // namespace Catch 7857 7858#endif // CATCH_CONFIG_ENABLE_BENCHMARKING 7859// end catch_stats.cpp 7860// start catch_approx.cpp 7861 7862#include <cmath> 7863#include <limits> 7864 7865namespace { 7866 7867// Performs equivalent check of std::fabs(lhs - rhs) <= margin 7868// But without the subtraction to allow for INFINITY in comparison 7869bool marginComparison ( double lhs , double rhs , double margin ) { 7870return ( lhs + margin >= rhs ) && ( rhs + margin >= lhs ); 7871} 7872 7873} 7874 7875namespace Catch { 7876namespace Detail { 7877 7878Approx :: Approx ( double value ) 7879: m_epsilon ( std :: numeric_limits < float > :: epsilon () * 100 ), 7880m_margin ( 0.0 ), 7881m_scale ( 0.0 ), 7882m_value ( value ) 7883{} 7884 7885Approx Approx :: custom () { 7886return Approx ( 0 ); 7887} 7888 7889Approx Approx :: operator - () const { 7890auto temp ( * this ); 7891temp . m_value = - temp . m_value ; 7892return temp ; 7893} 7894 7895std :: string Approx :: toString () const { 7896ReusableStringStream rss ; 7897rss << " Approx ( " << :: Catch :: Detail :: stringify ( m_value ) << " )"; 7898return rss . str (); 7899} 7900 7901bool Approx :: equalityComparisonImpl (const double other ) const { 7902// First try with fixed margin, then compute margin based on epsilon, scale and Approx's value 7903// Thanks to Richard Harris for his help refining the scaled margin value 7904return marginComparison ( m_value , other , m_margin ) 7905|| marginComparison ( m_value , other , m_epsilon * ( m_scale + std :: fabs ( std :: isinf ( m_value )? 0 : m_value ))); 7906} 7907 7908void Approx :: setMargin ( double newMargin ) { 7909CATCH_ENFORCE ( newMargin >= 0 , 7910" Invalid Approx :: margin : " << newMargin << '.' 7911<< " Approx :: Margin has to be non - negative ."); 7912m_margin = newMargin ; 7913} 7914 7915void Approx :: setEpsilon ( double newEpsilon ) { 7916CATCH_ENFORCE ( newEpsilon >= 0 && newEpsilon <= 1.0 , 7917" Invalid Approx :: epsilon : " << newEpsilon << '.' 7918<< " Approx :: epsilon has to be in [ 0 , 1 ]"); 7919m_epsilon = newEpsilon ; 7920} 7921 7922} // end namespace Detail 7923 7924namespace literals { 7925Detail :: Approx operator "" _a (long double val ) { 7926return Detail :: Approx ( val ); 7927} 7928Detail :: Approx operator "" _a (unsigned long long val ) { 7929return Detail :: Approx ( val ); 7930} 7931} // end namespace literals 7932 7933std :: string StringMaker < Catch :: Detail :: Approx > :: convert ( Catch :: Detail :: Approx const & value ) { 7934return value . toString (); 7935} 7936 7937} // end namespace Catch 7938// end catch_approx.cpp 7939// start catch_assertionhandler.cpp 7940 7941// start catch_debugger.h 7942 7943namespace Catch { 7944bool isDebuggerActive (); 7945} 7946 7947#ifdef CATCH_PLATFORM_MAC 7948 7949#if defined( __i386__ ) || defined( __x86_64__ ) 7950#define CATCH_TRAP () __asm__(" int $3 \ n " : : ) /* NOLINT */ 7951#elif defined( __aarch64__ ) 7952#define CATCH_TRAP () __asm__(".inst 0xd4200000") 7953#endif 7954 7955#elif defined(CATCH_PLATFORM_IPHONE) 7956 7957// use inline assembler 7958#if defined( __i386__ ) || defined( __x86_64__ ) 7959#define CATCH_TRAP () __asm__("int $3") 7960#elif defined( __aarch64__ ) 7961#define CATCH_TRAP () __asm__(".inst 0xd4200000") 7962#elif defined( __arm__ ) && !defined( __thumb__ ) 7963#define CATCH_TRAP () __asm__(".inst 0xe7f001f0") 7964#elif defined( __arm__ ) && defined( __thumb__ ) 7965#define CATCH_TRAP () __asm__(".inst 0xde01") 7966#endif 7967 7968#elif defined(CATCH_PLATFORM_LINUX) 7969// If we can use inline assembler, do it because this allows us to break 7970// directly at the location of the failing check instead of breaking inside 7971// raise() called from it, i.e. one stack frame below. 7972#if defined( __GNUC__ ) && (defined( __i386 ) || defined( __x86_64 )) 7973#define CATCH_TRAP () asm volatile ("int $3") /* NOLINT */ 7974#else // Fall back to the generic way. 7975#include <signal.h> 7976 7977#define CATCH_TRAP () raise(SIGTRAP) 7978#endif 7979#elif defined(_MSC_VER) 7980#define CATCH_TRAP () __debugbreak() 7981#elif defined(__MINGW32__) 7982extern "C" __declspec( dllimport ) void __stdcall DebugBreak (); 7983#define CATCH_TRAP () DebugBreak() 7984#endif 7985 7986#ifndef CATCH_BREAK_INTO_DEBUGGER 7987#ifdef CATCH_TRAP 7988#define CATCH_BREAK_INTO_DEBUGGER () []{ if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } }() 7989#else 7990#define CATCH_BREAK_INTO_DEBUGGER () []{}() 7991#endif 7992#endif 7993 7994// end catch_debugger.h 7995// start catch_run_context.h 7996 7997// start catch_fatal_condition.h 7998 7999#include <cassert> 8000 8001namespace Catch { 8002 8003// Wrapper for platform-specific fatal error (signals/SEH) handlers 8004// 8005// Tries to be cooperative with other handlers, and not step over 8006// other handlers. This means that unknown structured exceptions 8007// are passed on, previous signal handlers are called, and so on. 8008// 8009// Can only be instantiated once, and assumes that once a signal 8010// is caught, the binary will end up terminating. Thus, there 8011class FatalConditionHandler { 8012bool m_started = false; 8013 8014// Install/disengage implementation for specific platform. 8015// Should be if-defed to work on current platform, can assume 8016// engage-disengage 1:1 pairing. 8017void engage_platform (); 8018void disengage_platform (); 8019public : 8020// Should also have platform-specific implementations as needed 8021FatalConditionHandler (); 8022~ FatalConditionHandler (); 8023 8024void engage () { 8025assert (! m_started && "Handler cannot be installed twice." ); 8026m_started = true; 8027engage_platform (); 8028} 8029 8030void disengage () { 8031assert ( m_started && "Handler cannot be uninstalled without being installed first" ); 8032m_started = false; 8033disengage_platform (); 8034} 8035}; 8036 8037//! Simple RAII guard for (dis)engaging the FatalConditionHandler 8038class FatalConditionHandlerGuard { 8039FatalConditionHandler * m_handler ; 8040public : 8041FatalConditionHandlerGuard ( FatalConditionHandler * handler ): 8042m_handler ( handler ) { 8043m_handler -> engage (); 8044} 8045~ FatalConditionHandlerGuard () { 8046m_handler -> disengage (); 8047} 8048}; 8049 8050} // end namespace Catch 8051 8052// end catch_fatal_condition.h 8053#include <string> 8054 8055namespace Catch { 8056 8057struct IMutableContext ; 8058 8059/////////////////////////////////////////////////////////////////////////// 8060 8061class RunContext : public IResultCapture , public IRunner { 8062 8063public : 8064RunContext ( RunContext const & ) = delete ; 8065RunContext & operator = ( RunContext const & ) = delete ; 8066 8067explicit RunContext ( IConfigPtr const & _config , IStreamingReporterPtr && reporter ); 8068 8069~ RunContext () override ; 8070 8071void testGroupStarting ( std :: string const & testSpec , std :: size_t groupIndex , std :: size_t groupsCount ); 8072void testGroupEnded ( std :: string const & testSpec , Totals const & totals , std :: size_t groupIndex , std :: size_t groupsCount ); 8073 8074Totals runTest ( TestCase const & testCase ); 8075 8076IConfigPtr config () const; 8077IStreamingReporter & reporter () const ; 8078 8079public : // IResultCapture 8080 8081// Assertion handlers 8082void handleExpr 8083( AssertionInfo const & info , 8084ITransientExpression const & expr , 8085AssertionReaction & reaction ) override ; 8086void handleMessage 8087( AssertionInfo const & info , 8088ResultWas :: OfType resultType , 8089StringRef const & message , 8090AssertionReaction & reaction ) override ; 8091void handleUnexpectedExceptionNotThrown 8092( AssertionInfo const & info , 8093AssertionReaction & reaction ) override ; 8094void handleUnexpectedInflightException 8095( AssertionInfo const & info , 8096std :: string const & message , 8097AssertionReaction & reaction ) override ; 8098void handleIncomplete 8099( AssertionInfo const & info ) override ; 8100void handleNonExpr 8101( AssertionInfo const & info , 8102ResultWas :: OfType resultType , 8103AssertionReaction & reaction ) override ; 8104 8105bool sectionStarted ( SectionInfo const & sectionInfo , Counts & assertions ) override ; 8106 8107void sectionEnded ( SectionEndInfo const & endInfo ) override ; 8108void sectionEndedEarly ( SectionEndInfo const & endInfo ) override ; 8109 8110auto acquireGeneratorTracker ( StringRef generatorName , SourceLineInfo const & lineInfo ) -> IGeneratorTracker & override ; 8111 8112#if defined( CATCH_CONFIG_ENABLE_BENCHMARKING ) 8113void benchmarkPreparing ( std :: string const & name ) override ; 8114void benchmarkStarting ( BenchmarkInfo const & info ) override ; 8115void benchmarkEnded ( BenchmarkStats <> const & stats ) override ; 8116void benchmarkFailed ( std :: string const & error ) override ; 8117#endif // CATCH_CONFIG_ENABLE_BENCHMARKING 8118 8119void pushScopedMessage ( MessageInfo const & message ) override ; 8120void popScopedMessage ( MessageInfo const & message ) override ; 8121 8122void emplaceUnscopedMessage ( MessageBuilder const & builder ) override ; 8123 8124std :: string getCurrentTestName () const override ; 8125 8126const AssertionResult * getLastResult () const override ; 8127 8128void exceptionEarlyReported () override ; 8129 8130void handleFatalErrorCondition ( StringRef message ) override; 8131 8132bool lastAssertionPassed () override; 8133 8134void assertionPassed () override; 8135 8136public: 8137// !TBD We need to do this another way! 8138bool aborting () const final; 8139 8140private: 8141 8142void runCurrentTest ( std ::string & redirectedCout, std ::string & redirectedCerr ); 8143void invokeActiveTestCase (); 8144 8145void resetAssertionInfo (); 8146bool testForMissingAssertions ( Counts & assertions ); 8147 8148void assertionEnded ( AssertionResult const & result ); 8149void reportExpr 8150( AssertionInfo const & info, 8151ResultWas ::OfType resultType, 8152ITransientExpression const * expr, 8153bool negated ); 8154 8155void populateReaction ( AssertionReaction & reaction ); 8156 8157private : 8158 8159void handleUnfinishedSections (); 8160 8161TestRunInfo m_runInfo; 8162IMutableContext & m_context; 8163TestCase const * m_activeTestCase = nullptr ; 8164ITracker * m_testCaseTracker = nullptr ; 8165Option < AssertionResult > m_lastResult; 8166 8167IConfigPtr m_config; 8168Totals m_totals; 8169IStreamingReporterPtr m_reporter; 8170std ::vector < MessageInfo > m_messages; 8171std ::vector < ScopedMessage > m_messageScopes; /* Keeps owners of so-called unscoped messages. */ 8172AssertionInfo m_lastAssertionInfo; 8173std ::vector < SectionEndInfo > m_unfinishedSections; 8174std ::vector < ITracker *> m_activeSections; 8175TrackerContext m_trackerContext; 8176FatalConditionHandler m_fatalConditionhandler; 8177bool m_lastAssertionPassed = false; 8178bool m_shouldReportUnexpected = true; 8179bool m_includeSuccessfulResults; 8180}; 8181 8182void seedRng ( IConfig const & config); 8183unsigned int rngSeed (); 8184} // end namespace Catch 8185 8186// end catch_run_context.h 8187namespace Catch { 8188 8189namespace { 8190auto operator <<( std::ostream & os, ITransientExpression const & expr ) -> std::ostream & { 8191expr. streamReconstructedExpression ( os ); 8192return os; 8193} 8194} 8195 8196LazyExpression :: LazyExpression ( bool isNegated ) 8197: m_isNegated ( isNegated ) 8198{} 8199 8200LazyExpression ::LazyExpression( LazyExpression const & other ) : m_isNegated ( other. m_isNegated ) {} 8201 8202LazyExpression :: operator bool () const { 8203return m_transientExpression != nullptr ; 8204} 8205 8206auto operator << ( std :: ostream & os, LazyExpression const & lazyExpr ) -> std::ostream & { 8207if ( lazyExpr. m_isNegated ) 8208os << "!" ; 8209 8210if ( lazyExpr ) { 8211if ( lazyExpr. m_isNegated && lazyExpr. m_transientExpression -> isBinaryExpression () ) 8212os << "(" << * lazyExpr. m_transientExpression << ")" ; 8213else 8214os << * lazyExpr. m_transientExpression ; 8215} 8216else { 8217os << "{** error - unchecked empty expression requested **}" ; 8218} 8219return os; 8220} 8221 8222AssertionHandler ::AssertionHandler 8223( StringRef const & macroName, 8224SourceLineInfo const & lineInfo, 8225StringRef capturedExpression, 8226ResultDisposition:: Flags resultDisposition ) 8227: m_assertionInfo { macroName, lineInfo, capturedExpression, resultDisposition }, 8228m_resultCapture ( getResultCapture () ) 8229{} 8230 8231void AssertionHandler:: handleExpr ( ITransientExpression const & expr ) { 8232m_resultCapture. handleExpr ( m_assertionInfo , expr , m_reaction ); 8233} 8234void AssertionHandler:: handleMessage ( ResultWas ::OfType resultType, StringRef const & message) { 8235m_resultCapture. handleMessage ( m_assertionInfo, resultType, message, m_reaction ); 8236} 8237 8238auto AssertionHandler :: allowThrows () const -> bool { 8239return getCurrentContext (). getConfig () -> allowThrows (); 8240} 8241 8242void AssertionHandler:: complete () { 8243setCompleted (); 8244if( m_reaction .shouldDebugBreak ) { 8245 8246// If you find your debugger stopping you here then go one level up on the 8247// call-stack for the code that caused it (typically a failed assertion) 8248 8249// (To go back to the test and change execution, jump over the throw, next) 8250CATCH_BREAK_INTO_DEBUGGER (); 8251} 8252if (m_reaction. shouldThrow ) { 8253#if !defined( CATCH_CONFIG_DISABLE_EXCEPTIONS ) 8254throw Catch:: TestFailureException (); 8255#else 8256CATCH_ERROR ( "Test failure requires aborting test!" ); 8257#endif 8258} 8259} 8260void AssertionHandler:: setCompleted () { 8261m_completed = true; 8262} 8263 8264void AssertionHandler:: handleUnexpectedInflightException () { 8265m_resultCapture. handleUnexpectedInflightException ( m_assertionInfo, Catch:: translateActiveException (), m_reaction ); 8266} 8267 8268void AssertionHandler:: handleExceptionThrownAsExpected () { 8269m_resultCapture. handleNonExpr (m_assertionInfo, ResultWas::Ok, m_reaction); 8270} 8271void AssertionHandler:: handleExceptionNotThrownAsExpected () { 8272m_resultCapture. handleNonExpr (m_assertionInfo, ResultWas::Ok, m_reaction); 8273} 8274 8275void AssertionHandler:: handleUnexpectedExceptionNotThrown () { 8276m_resultCapture. handleUnexpectedExceptionNotThrown ( m_assertionInfo, m_reaction ); 8277} 8278 8279void AssertionHandler:: handleThrowingCallSkipped () { 8280m_resultCapture. handleNonExpr (m_assertionInfo, ResultWas::Ok, m_reaction); 8281} 8282 8283// This is the overload that takes a string and infers the Equals matcher from it 8284// The more general overload, that takes any string matcher, is in catch_capture_matchers.cpp 8285void handleExceptionMatchExpr ( AssertionHandler & handler, std ::string const & str, StringRef const & matcherString ) { 8286handleExceptionMatchExpr ( handler, Matchers:: Equals ( str ), matcherString ); 8287} 8288 8289} // namespace Catch 8290// end catch_assertionhandler.cpp 8291// start catch_assertionresult.cpp 8292 8293namespace Catch { 8294AssertionResultData :: AssertionResultData ( ResultWas :: OfType _resultType, LazyExpression const & _lazyExpression): 8295lazyExpression (_lazyExpression), 8296resultType (_resultType) {} 8297 8298std :: string AssertionResultData:: reconstructExpression () const { 8299 8300if ( reconstructedExpression. empty () ) { 8301if ( lazyExpression ) { 8302ReusableStringStream rss; 8303rss << lazyExpression; 8304reconstructedExpression = rss. str (); 8305} 8306} 8307return reconstructedExpression; 8308} 8309 8310AssertionResult ::AssertionResult( AssertionInfo const & info, AssertionResultData const & data ) 8311: m_info ( info ), 8312m_resultData ( data ) 8313{} 8314 8315// Result was a success 8316bool AssertionResult:: succeeded () const { 8317return Catch :: isOk ( m_resultData .resultType ); 8318} 8319 8320// Result was a success, or failure is suppressed 8321bool AssertionResult:: isOk () const { 8322return Catch:: isOk ( m_resultData. resultType ) || shouldSuppressFailure ( m_info. resultDisposition ); 8323} 8324 8325ResultWas :: OfType AssertionResult:: getResultType () const { 8326return m_resultData. resultType ; 8327} 8328 8329bool AssertionResult:: hasExpression () const { 8330return !m_info. capturedExpression . empty (); 8331} 8332 8333bool AssertionResult:: hasMessage () const { 8334return !m_resultData. message . empty (); 8335} 8336 8337std :: string AssertionResult:: getExpression () const { 8338// Possibly overallocating by 3 characters should be basically free 8339std :: string expr; expr. reserve (m_info. capturedExpression . size () + 3 ); 8340if ( isFalseTest (m_info. resultDisposition )) { 8341expr += "!(" ; 8342} 8343expr += m_info. capturedExpression ; 8344if ( isFalseTest (m_info. resultDisposition )) { 8345expr += ')' ; 8346} 8347return expr; 8348} 8349 8350std :: string AssertionResult:: getExpressionInMacro () const { 8351std :: string expr; 8352if ( m_info. macroName . empty () ) 8353expr = static_cast < std::string > (m_info. capturedExpression ); 8354else { 8355expr. reserve ( m_info. macroName . size () + m_info. capturedExpression . size () + 4 ); 8356expr += m_info. macroName ; 8357expr += "( " ; 8358expr += m_info. capturedExpression ; 8359expr += " )" ; 8360} 8361return expr; 8362} 8363 8364bool AssertionResult:: hasExpandedExpression () const { 8365return hasExpression () && getExpandedExpression () != getExpression (); 8366} 8367 8368std :: string AssertionResult:: getExpandedExpression () const { 8369std :: string expr = m_resultData. reconstructExpression (); 8370return expr. empty () 8371? getExpression () 8372: expr; 8373} 8374 8375std :: string AssertionResult:: getMessage () const { 8376return m_resultData. message ; 8377} 8378SourceLineInfo AssertionResult:: getSourceInfo () const { 8379return m_info. lineInfo ; 8380} 8381 8382StringRef AssertionResult:: getTestMacroName () const { 8383return m_info. macroName ; 8384} 8385 8386} // end namespace Catch 8387// end catch_assertionresult.cpp 8388// start catch_capture_matchers.cpp 8389 8390namespace Catch { 8391 8392using StringMatcher = Matchers::Impl::MatcherBase < std::string > ; 8393 8394// This is the general overload that takes a any string matcher 8395// There is another overload, in catch_assertionhandler.h/.cpp, that only takes a string and infers 8396// the Equals matcher (so the header does not mention matchers) 8397void handleExceptionMatchExpr ( AssertionHandler & handler, StringMatcher const & matcher, StringRef const & matcherString ) { 8398std :: string exceptionMessage = Catch:: translateActiveException (); 8399MatchExpr < std::string, StringMatcher const &> expr ( exceptionMessage, matcher, matcherString ); 8400handler. handleExpr ( expr ); 8401} 8402 8403} // namespace Catch 8404// end catch_capture_matchers.cpp 8405// start catch_commandline.cpp 8406 8407// start catch_commandline.h 8408 8409// start catch_clara.h 8410 8411// Use Catch's value for console width (store Clara's off to the side, if present) 8412#ifdef CLARA_CONFIG_CONSOLE_WIDTH 8413#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 8414#undef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 8415#endif 8416#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH-1 8417 8418#ifdef __clang__ 8419#pragma clang diagnostic push 8420#pragma clang diagnostic ignored "-Wweak-vtables" 8421#pragma clang diagnostic ignored "-Wexit-time-destructors" 8422#pragma clang diagnostic ignored "-Wshadow" 8423#endif 8424 8425// start clara.hpp 8426// Copyright 2017 Two Blue Cubes Ltd. All rights reserved. 8427// 8428// Distributed under the Boost Software License, Version 1.0. (See accompanying 8429// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8430// 8431// See https://github.com/philsquared/Clara for more details 8432 8433// Clara v1.1.5 8434 8435 8436#ifndef CATCH_CLARA_CONFIG_CONSOLE_WIDTH 8437#define CATCH_CLARA_CONFIG_CONSOLE_WIDTH 80 8438#endif 8439 8440#ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 8441#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CLARA_CONFIG_CONSOLE_WIDTH 8442#endif 8443 8444#ifndef CLARA_CONFIG_OPTIONAL_TYPE 8445#ifdef __has_include 8446#if __has_include( < optional > ) && __cplusplus >= 201703L 8447#include <optional> 8448#define CLARA_CONFIG_OPTIONAL_TYPE std::optional 8449#endif 8450#endif 8451#endif 8452 8453// ----------- #included from clara_textflow.hpp ----------- 8454 8455// TextFlowCpp 8456// 8457// A single-header library for wrapping and laying out basic text, by Phil Nash 8458// 8459// Distributed under the Boost Software License, Version 1.0. (See accompanying 8460// file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8461// 8462// This project is hosted at https://github.com/philsquared/textflowcpp 8463 8464 8465#include <cassert> 8466#include <ostream> 8467#include <sstream> 8468#include <vector> 8469 8470#ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 8471#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 80 8472#endif 8473 8474namespace Catch { 8475namespace clara { 8476namespace TextFlow { 8477 8478inline auto isWhitespace( char c) -> bool { 8479static std::string chars = " \t\n\r" ; 8480return chars. find (c) != std::string::npos; 8481} 8482inline auto isBreakableBefore( char c) -> bool { 8483static std::string chars = "[({<|" ; 8484return chars. find (c) != std::string::npos; 8485} 8486inline auto isBreakableAfter( char c) -> bool { 8487static std::string chars = "])}>.,:;*+-=&/\\" ; 8488return chars. find (c) != std::string::npos; 8489} 8490 8491class Columns; 8492 8493class Column { 8494std ::vector < std::string > m_strings; 8495size_t m_width = CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH ; 8496size_t m_indent = 0 ; 8497size_t m_initialIndent = std::string::npos; 8498 8499public : 8500class iterator { 8501friend Column; 8502 8503Column const & m_column; 8504size_t m_stringIndex = 0 ; 8505size_t m_pos = 0 ; 8506 8507size_t m_len = 0 ; 8508size_t m_end = 0 ; 8509bool m_suffix = false; 8510 8511iterator( Column const & column, size_t stringIndex) 8512: m_column (column), 8513m_stringIndex (stringIndex) {} 8514 8515auto line() const -> std :: string const & { return m_column .m_strings[m_stringIndex]; } 8516 8517auto isBoundary ( size_t at) const -> bool { 8518assert (at > 0 ); 8519assert (at <= line (). size ()); 8520 8521return at == line (). size () || 8522( isWhitespace ( line ()[at]) && ! isWhitespace ( line ()[at - 1 ])) || 8523isBreakableBefore ( line ()[at]) || 8524isBreakableAfter ( line ()[at - 1 ]); 8525} 8526 8527void calcLength () { 8528assert (m_stringIndex < m_column. m_strings . size ()); 8529 8530m_suffix = false; 8531auto width = m_column. m_width - indent (); 8532m_end = m_pos; 8533if ( line ()[m_pos] == '\n' ) { 8534++ m_end; 8535} 8536while (m_end < line (). size () && line ()[m_end] != '\n' ) 8537++ m_end; 8538 8539if (m_end < m_pos + width) { 8540m_len = m_end - m_pos; 8541} else { 8542size_t len = width; 8543while (len > 0 && ! isBoundary (m_pos + len)) 8544-- len; 8545while (len > 0 && isWhitespace ( line ()[m_pos + len - 1 ])) 8546-- len; 8547 8548if (len > 0 ) { 8549m_len = len; 8550} else { 8551m_suffix = true; 8552m_len = width - 1 ; 8553} 8554} 8555} 8556 8557auto indent() const -> size_t { 8558auto initial = m_pos == 0 && m_stringIndex == 0 ? m_column. m_initialIndent : std:: string ::npos; 8559return initial == std::string::npos ? m_column. m_indent : initial; 8560} 8561 8562auto addIndentAndSuffix( std :: string const & plain ) const -> std::string { 8563return std:: string ( indent (), ' ' ) + (m_suffix ? plain + "-" : plain); 8564} 8565 8566public : 8567using difference_type = std:: ptrdiff_t ; 8568using value_type = std::string; 8569using pointer = value_type * ; 8570using reference = value_type & ; 8571using iterator_category = std::forward_iterator_tag; 8572 8573explicit iterator ( Column const & column) : m_column (column) { 8574assert (m_column. m_width > m_column. m_indent ); 8575assert (m_column. m_initialIndent == std::string::npos || m_column. m_width > m_column. m_initialIndent ); 8576calcLength (); 8577if (m_len == 0 ) 8578m_stringIndex ++ ; // Empty string 8579} 8580 8581auto operator * () const -> std::string { 8582assert (m_stringIndex < m_column. m_strings . size ()); 8583assert (m_pos <= m_end); 8584return addIndentAndSuffix ( line (). substr (m_pos, m_len)); 8585} 8586 8587auto operator ++ () -> iterator & { 8588m_pos += m_len; 8589if (m_pos < line (). size () && line ()[m_pos] == '\n' ) 8590m_pos += 1 ; 8591else 8592while (m_pos < line (). size () && isWhitespace ( line ()[m_pos])) 8593++ m_pos; 8594 8595if (m_pos == line (). size ()) { 8596m_pos = 0 ; 8597++ m_stringIndex; 8598} 8599if (m_stringIndex < m_column. m_strings . size ()) 8600calcLength (); 8601return * this; 8602} 8603auto operator ++ ( int ) -> iterator { 8604iterator prev ( * this ); 8605operator ++ (); 8606return prev; 8607} 8608 8609auto operator == (iterator const & other) const -> bool { 8610return 8611m_pos == other. m_pos && 8612m_stringIndex == other. m_stringIndex && 8613& m_column == & other. m_column ; 8614} 8615auto operator != (iterator const & other) const -> bool { 8616return !operator == (other); 8617} 8618}; 8619using const_iterator = iterator; 8620 8621explicit Column ( std ::string const & text) { m_strings. push_back (text); } 8622 8623auto width( size_t newWidth ) -> Column & { 8624assert (newWidth > 0 ); 8625m_width = newWidth; 8626return * this; 8627} 8628auto indent( size_t newIndent ) -> Column & { 8629m_indent = newIndent; 8630return * this; 8631} 8632auto initialIndent( size_t newIndent ) -> Column & { 8633m_initialIndent = newIndent; 8634return * this; 8635} 8636 8637auto width() const -> size_t { return m_width; } 8638auto begin() const -> iterator { return iterator ( * this); } 8639auto end() const -> iterator { return { * this, m_strings. size () }; } 8640 8641inline friend std::ostream & operator << (std::ostream & os, Column const & col) { 8642bool first = true; 8643for (auto line : col ) { 8644if ( first ) 8645first = false; 8646else 8647os << "\n" ; 8648os << line; 8649} 8650return os; 8651} 8652 8653auto operator + ( Column const & other) -> Columns ; 8654 8655auto toString () const -> std ::string { 8656std::ostringstream oss; 8657oss << * this; 8658return oss. str (); 8659} 8660}; 8661 8662class Spacer : public Column { 8663 8664public: 8665explicit Spacer (size_t spaceWidth) : Column ( "" ) { 8666width (spaceWidth); 8667} 8668}; 8669 8670class Columns { 8671std::vector < Column > m_columns; 8672 8673public: 8674 8675class iterator { 8676friend Columns; 8677struct EndTag {}; 8678 8679std::vector < Column > const & m_columns; 8680std::vector < Column::iterator > m_iterators; 8681size_t m_activeIterators; 8682 8683iterator (Columns const & columns, EndTag) 8684: m_columns (columns. m_columns ), 8685m_activeIterators ( 0 ) { 8686m_iterators. reserve (m_columns. size ()); 8687 8688for (auto const & col : m_columns) 8689m_iterators. push_back (col. end ()); 8690} 8691 8692public : 8693using difference_type = std:: ptrdiff_t ; 8694using value_type = std::string; 8695using pointer = value_type * ; 8696using reference = value_type & ; 8697using iterator_category = std::forward_iterator_tag; 8698 8699explicit iterator ( Columns const & columns) 8700: m_columns (columns.m_columns), 8701m_activeIterators ( m_columns . size ()) { 8702m_iterators. reserve (m_columns. size ()); 8703 8704for (auto const & col : m_columns) 8705m_iterators. push_back ( col . begin ()); 8706} 8707 8708auto operator == ( iterator const & other ) const -> bool { 8709return m_iterators == other. m_iterators ; 8710} 8711auto operator != ( iterator const & other ) const -> bool { 8712return m_iterators != other. m_iterators ; 8713} 8714auto operator * ( ) const -> std :: string { 8715std :: string row , padding ; 8716 8717for ( size_t i = 0 ; i < m_columns . size (); ++ i ) { 8718auto width = m_columns[i]. width (); 8719if (m_iterators[i] != m_columns[i]. end ()) { 8720std :: string col = * m_iterators[i]; 8721row += padding + col; 8722if (col. size () < width) 8723padding = std:: string (width - col. size (), ' ' ); 8724else 8725padding = "" ; 8726} else { 8727padding += std:: string (width, ' ' ); 8728} 8729} 8730return row; 8731} 8732auto operator ++ () -> iterator & { 8733for ( size_t i = 0 ; i < m_columns. size (); ++ i) { 8734if (m_iterators[i] != m_columns[i]. end ()) 8735++ m_iterators[i]; 8736} 8737return * this; 8738} 8739auto operator ++ ( int ) -> iterator { 8740iterator prev ( * this ); 8741operator ++ (); 8742return prev; 8743} 8744}; 8745using const_iterator = iterator; 8746 8747auto begin() const -> iterator { return iterator ( * this); } 8748auto end() const -> iterator { return { * this, iterator:: EndTag () }; } 8749 8750auto operator += ( Column const & col) -> Columns & { 8751m_columns. push_back (col); 8752return * this; 8753} 8754auto operator + ( Column const & col) -> Columns { 8755Columns combined = * this; 8756combined += col; 8757return combined; 8758} 8759 8760inline friend std::ostream & operator << (std::ostream & os, Columns const & cols) { 8761 8762bool first = true; 8763for (auto line : cols ) { 8764if ( first ) 8765first = false; 8766else 8767os << "\n" ; 8768os << line; 8769} 8770return os; 8771} 8772 8773auto toString () const -> std ::string { 8774std::ostringstream oss; 8775oss << * this; 8776return oss. str (); 8777} 8778}; 8779 8780inline auto Column::operator + ( Column const & other) -> Columns { 8781Columns cols; 8782cols += * this; 8783cols += other; 8784return cols; 8785} 8786} 8787 8788} 8789} 8790 8791// ----------- end of #include from clara_textflow.hpp ----------- 8792// ........... back in clara.hpp 8793 8794#include < cctype > 8795#include < string > 8796#include < memory > 8797#include < set > 8798#include < algorithm > 8799 8800#if ! defined ( CATCH_PLATFORM_WINDOWS ) && ( defined ( WIN32 ) || defined (__WIN32__) || defined (_WIN32) || defined (_MSC_VER) ) 8801#define CATCH_PLATFORM_WINDOWS 8802#endif 8803 8804namespace Catch { namespace clara { 8805namespace detail { 8806 8807// Traits for extracting arg and return type of lambdas (for single argument lambdas) 8808template < typename L > 8809struct UnaryLambdaTraits : UnaryLambdaTraits < decltype ( & L :: operator () ) > {}; 8810 8811template < typename ClassT, typename ReturnT, typename... Args > 8812struct UnaryLambdaTraits < ReturnT ( ClassT:: * )( Args... ) const > { 8813static const bool isValid = false; 8814}; 8815 8816template < typename ClassT, typename ReturnT, typename ArgT > 8817struct UnaryLambdaTraits < ReturnT( ClassT:: * )( ArgT ) const > { 8818static const bool isValid = true; 8819using ArgType = typename std ::remove_const < typename std ::remove_reference < ArgT > ::type > ::type; 8820using ReturnType = ReturnT; 8821}; 8822 8823class TokenStream; 8824 8825// Transport for raw args (copied from main args, or supplied via init list for testing) 8826class Args { 8827friend TokenStream; 8828std :: string m_exeName; 8829std ::vector < std::string > m_args; 8830 8831public : 8832Args( int argc, char const * const * argv ) 8833: m_exeName ( argv [ 0 ]), 8834m_args ( argv + 1 , argv + argc) {} 8835 8836Args( std ::initializer_list < std::string > args ) 8837: m_exeName( * args. begin () ), 8838m_args ( args . begin () + 1 , args . end () ) 8839{} 8840 8841auto exeName () const -> std::string { 8842return m_exeName; 8843} 8844}; 8845 8846// Wraps a token coming from a token stream. These may not directly correspond to strings as a single string 8847// may encode an option + its argument if the : or = form is used 8848enum class TokenType { 8849Option, Argument 8850}; 8851struct Token { 8852TokenType type ; 8853std :: string token ; 8854}; 8855 8856inline auto isOptPrefix( char c ) -> bool { 8857return c == '-' 8858#ifdef CATCH_PLATFORM_WINDOWS 8859|| c == '/' 8860#endif 8861; 8862} 8863 8864// Abstracts iterators into args as a stream of tokens, with option arguments uniformly handled 8865class TokenStream { 8866using Iterator = std::vector < std::string > ::const_iterator; 8867Iterator it; 8868Iterator itEnd; 8869std ::vector < Token > m_tokenBuffer; 8870 8871void loadBuffer () { 8872m_tokenBuffer. resize ( 0 ); 8873 8874// Skip any empty strings 8875while ( it != itEnd && it -> empty () ) 8876++ it; 8877 8878if ( it != itEnd ) { 8879auto const & next = * it; 8880if ( isOptPrefix ( next[ 0 ] ) ) { 8881auto delimiterPos = next. find_first_of ( " :=" ); 8882if ( delimiterPos != std::string::npos ) { 8883m_tokenBuffer. push_back ( { TokenType ::Option, next. substr ( 0 , delimiterPos ) } ); 8884m_tokenBuffer. push_back ( { TokenType ::Argument, next. substr ( delimiterPos + 1 ) } ); 8885} else { 8886if ( next[ 1 ] != '-' && next. size () > 2 ) { 8887std :: string opt = "- " ; 8888for ( size_t i = 1 ; i < next. size (); ++ i ) { 8889opt[ 1 ] = next[i]; 8890m_tokenBuffer. push_back ( { TokenType ::Option, opt } ); 8891} 8892} else { 8893m_tokenBuffer. push_back ( { TokenType ::Option, next } ); 8894} 8895} 8896} else { 8897m_tokenBuffer. push_back ( { TokenType ::Argument, next } ); 8898} 8899} 8900} 8901 8902public : 8903explicit TokenStream ( Args const & args ) : TokenStream ( args. m_args . begin (), args. m_args . end () ) {} 8904 8905TokenStream( Iterator it, Iterator itEnd ) : it ( it ), itEnd ( itEnd ) { 8906loadBuffer (); 8907} 8908 8909explicit operator bool () const { 8910return !m_tokenBuffer. empty () || it != itEnd; 8911} 8912 8913auto count() const -> size_t { return m_tokenBuffer. size () + (itEnd - it); } 8914 8915auto operator * () const -> Token { 8916assert ( !m_tokenBuffer. empty () ); 8917return m_tokenBuffer. front (); 8918} 8919 8920auto operator -> () const -> Token const * { 8921assert ( !m_tokenBuffer. empty () ); 8922return & m_tokenBuffer. front (); 8923} 8924 8925auto operator ++ () -> TokenStream & { 8926if ( m_tokenBuffer. size () >= 2 ) { 8927m_tokenBuffer. erase ( m_tokenBuffer. begin () ); 8928} else { 8929if ( it != itEnd ) 8930++ it; 8931loadBuffer (); 8932} 8933return * this; 8934} 8935}; 8936 8937class ResultBase { 8938public : 8939enum Type { 8940Ok, LogicError, RuntimeError 8941}; 8942 8943protected : 8944ResultBase( Type type ) : m_type ( type ) {} 8945virtual ~ ResultBase () = default; 8946 8947virtual void enforceOk () const = 0 ; 8948 8949Type m_type; 8950}; 8951 8952template < typename T > 8953class ResultValueBase : public ResultBase { 8954public : 8955auto value() const -> T const & { 8956enforceOk (); 8957return m_value ; 8958} 8959 8960protected : 8961ResultValueBase ( Type type ) : ResultBase( type ) {} 8962 8963ResultValueBase ( ResultValueBase const & other ) : ResultBase( other ) { 8964if ( m_type == ResultBase::Ok ) 8965new ( & m_value ) T ( other.m_value ); 8966} 8967 8968ResultValueBase ( Type , T const & value ) : ResultBase ( Ok ) { 8969new ( & m_value ) T ( value ); 8970} 8971 8972auto operator = ( ResultValueBase const & other ) -> ResultValueBase & { 8973if ( m_type == ResultBase::Ok ) 8974m_value.~ T (); 8975ResultBase ::operator = (other); 8976if ( m_type == ResultBase::Ok ) 8977new ( & m_value ) T ( other. m_value ); 8978return * this; 8979} 8980 8981~ ResultValueBase () override { 8982if ( m_type == Ok ) 8983m_value.~ T (); 8984} 8985 8986union { 8987T m_value ; 8988}; 8989}; 8990 8991template <> 8992class ResultValueBase < void > : public ResultBase { 8993protected : 8994using ResultBase::ResultBase; 8995}; 8996 8997template < typename T = void > 8998class BasicResult : public ResultValueBase < T > { 8999public: 9000template < typename U > 9001explicit BasicResult ( BasicResult < U > const & other ) 9002: ResultValueBase < T > ( other. type () ), 9003m_errorMessage ( other. errorMessage () ) 9004{ 9005assert ( type () != ResultBase::Ok ); 9006} 9007 9008template < typename U > 9009static auto ok( U const & value ) -> BasicResult { return { ResultBase ::Ok, value }; } 9010static auto ok() -> BasicResult { return { ResultBase::Ok }; } 9011static auto logicError( std :: string const & message ) -> BasicResult { return { ResultBase ::LogicError, message }; } 9012static auto runtimeError( std :: string const & message ) -> BasicResult { return { ResultBase ::RuntimeError, message }; } 9013 9014explicit operator bool () const { return m_type == ResultBase::Ok; } 9015auto type() const -> ResultBase ::Type { return m_type; } 9016auto errorMessage() const -> std ::string { return m_errorMessage; } 9017 9018protected : 9019void enforceOk () const override { 9020 9021// Errors shouldn't reach this point, but if they do 9022// the actual error message will be in m_errorMessage 9023assert ( m_type != ResultBase::LogicError ); 9024assert ( m_type != ResultBase::RuntimeError ); 9025if ( m_type != ResultBase::Ok ) 9026std :: abort (); 9027} 9028 9029std :: string m_errorMessage; // Only populated if resultType is an error 9030 9031BasicResult ( ResultBase :: Type type, std:: string const & message ) 9032: ResultValueBase < T > (type), 9033m_errorMessage (message) 9034{ 9035assert ( m_type != ResultBase::Ok ); 9036} 9037 9038using ResultValueBase < T > ::ResultValueBase; 9039using ResultBase::m_type; 9040}; 9041 9042enum class ParseResultType { 9043Matched, NoMatch, ShortCircuitAll, ShortCircuitSame 9044}; 9045 9046class ParseState { 9047public : 9048 9049ParseState( ParseResultType type, TokenStream const & remainingTokens ) 9050: m_type ( type ), 9051m_remainingTokens ( remainingTokens ) 9052{} 9053 9054auto type () const -> ParseResultType { return m_type; } 9055auto remainingTokens() const -> TokenStream { return m_remainingTokens; } 9056 9057private : 9058ParseResultType m_type; 9059TokenStream m_remainingTokens; 9060}; 9061 9062using Result = BasicResult < void > ; 9063using ParserResult = BasicResult < ParseResultType > ; 9064using InternalParseResult = BasicResult < ParseState > ; 9065 9066struct HelpColumns { 9067std :: string left ; 9068std :: string right ; 9069}; 9070 9071template < typename T > 9072inline auto convertInto( std :: string const & source , T & target ) -> ParserResult { 9073std :: stringstream ss; 9074ss << source; 9075ss >> target; 9076if ( ss. fail () ) 9077return ParserResult:: runtimeError ( "Unable to convert '" + source + "' to destination type" ); 9078else 9079return ParserResult:: ok ( ParseResultType::Matched ); 9080} 9081inline auto convertInto( std :: string const & source , std :: string & target ) -> ParserResult { 9082target = source; 9083return ParserResult:: ok ( ParseResultType::Matched ); 9084} 9085inline auto convertInto( std :: string const & source , bool & target ) -> ParserResult { 9086std :: string srcLC = source; 9087std :: transform ( srcLC. begin (), srcLC. end (), srcLC. begin (), []( unsigned char c ) { return static_cast < char > ( std:: tolower (c) ); } ); 9088if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on" ) 9089target = true; 9090else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off" ) 9091target = false; 9092else 9093return ParserResult:: runtimeError ( "Expected a boolean value but did not recognise: '" + source + "'" ); 9094return ParserResult:: ok ( ParseResultType::Matched ); 9095} 9096#ifdef CLARA_CONFIG_OPTIONAL_TYPE 9097template < typename T > 9098inline auto convertInto( std :: string const & source , CLARA_CONFIG_OPTIONAL_TYPE < T >& target ) -> ParserResult { 9099T temp; 9100auto result = convertInto ( source , temp ); 9101if ( result ) 9102target = std:: move (temp); 9103return result; 9104} 9105#endif // CLARA_CONFIG_OPTIONAL_TYPE 9106 9107struct NonCopyable { 9108NonCopyable () = default ; 9109NonCopyable( NonCopyable const & ) = delete ; 9110NonCopyable( NonCopyable && ) = delete ; 9111NonCopyable & operator = ( NonCopyable const & ) = delete ; 9112NonCopyable & operator = ( NonCopyable && ) = delete ; 9113}; 9114 9115struct BoundRef : NonCopyable { 9116virtual ~ BoundRef () = default; 9117virtual auto isContainer () const -> bool { return false; } 9118virtual auto isFlag () const -> bool { return false; } 9119}; 9120struct BoundValueRefBase : BoundRef { 9121virtual auto setValue ( std ::string const & arg ) -> ParserResult = 0 ; 9122}; 9123struct BoundFlagRefBase : BoundRef { 9124virtual auto setFlag ( bool flag ) -> ParserResult = 0 ; 9125virtual auto isFlag () const -> bool { return true; } 9126}; 9127 9128template < typename T > 9129struct BoundValueRef : BoundValueRefBase { 9130T & m_ref; 9131 9132explicit BoundValueRef ( T & ref ) : m_ref ( ref ) {} 9133 9134auto setValue( std :: string const & arg ) -> ParserResult override { 9135return convertInto ( arg, m_ref ); 9136} 9137}; 9138 9139template < typename T > 9140struct BoundValueRef < std::vector < T >> : BoundValueRefBase { 9141std ::vector < T > & m_ref; 9142 9143explicit BoundValueRef ( std ::vector < T > & ref ) : m_ref ( ref ) {} 9144 9145auto isContainer() const -> bool override { return true; } 9146 9147auto setValue( std :: string const & arg ) -> ParserResult override { 9148T temp; 9149auto result = convertInto ( arg , temp ); 9150if ( result ) 9151m_ref. push_back ( temp ); 9152return result; 9153} 9154}; 9155 9156struct BoundFlagRef : BoundFlagRefBase { 9157bool & m_ref; 9158 9159explicit BoundFlagRef ( bool & ref ) : m_ref ( ref ) {} 9160 9161auto setFlag( bool flag ) -> ParserResult override { 9162m_ref = flag; 9163return ParserResult:: ok ( ParseResultType::Matched ); 9164} 9165}; 9166 9167template < typename ReturnType > 9168struct LambdaInvoker { 9169static_assert ( std ::is_same < ReturnType, ParserResult > ::value, "Lambda must return void or clara::ParserResult" ); 9170 9171template < typename L , typename ArgType > 9172static auto invoke( L const & lambda, ArgType const & arg ) -> ParserResult { 9173return lambda ( arg ); 9174} 9175}; 9176 9177template <> 9178struct LambdaInvoker < void > { 9179template < typename L , typename ArgType > 9180static auto invoke( L const & lambda, ArgType const & arg ) -> ParserResult { 9181lambda ( arg ); 9182return ParserResult:: ok ( ParseResultType::Matched ); 9183} 9184}; 9185 9186template < typename ArgType, typename L > 9187inline auto invokeLambda( L const & lambda, std::string const & arg ) -> ParserResult { 9188ArgType temp{}; 9189auto result = convertInto ( arg , temp ); 9190return !result 9191? result 9192: LambdaInvoker < typename UnaryLambdaTraits < L > ::ReturnType > :: invoke ( lambda, temp ); 9193} 9194 9195template < typename L > 9196struct BoundLambda : BoundValueRefBase { 9197L m_lambda; 9198 9199static_assert ( UnaryLambdaTraits < L > ::isValid, "Supplied lambda must take exactly one argument" ); 9200explicit BoundLambda ( L const & lambda ) : m_lambda ( lambda ) {} 9201 9202auto setValue( std :: string const & arg ) -> ParserResult override { 9203return invokeLambda < typename UnaryLambdaTraits < L > ::ArgType > ( m_lambda, arg ); 9204} 9205}; 9206 9207template < typename L > 9208struct BoundFlagLambda : BoundFlagRefBase { 9209L m_lambda; 9210 9211static_assert ( UnaryLambdaTraits < L > ::isValid, "Supplied lambda must take exactly one argument" ); 9212static_assert ( std ::is_same < typename UnaryLambdaTraits < L > ::ArgType, bool > ::value, "flags must be boolean" ); 9213 9214explicit BoundFlagLambda ( L const & lambda ) : m_lambda ( lambda ) {} 9215 9216auto setFlag( bool flag ) -> ParserResult override { 9217return LambdaInvoker < typename UnaryLambdaTraits < L > ::ReturnType > :: invoke ( m_lambda, flag ); 9218} 9219}; 9220 9221enum class Optionality { Optional, Required }; 9222 9223struct Parser ; 9224 9225class ParserBase { 9226public : 9227virtual ~ ParserBase () = default; 9228virtual auto validate () const -> Result { return Result:: ok (); } 9229virtual auto parse ( std ::string const & exeName, TokenStream const & tokens) const -> InternalParseResult = 0 ; 9230virtual auto cardinality () const -> size_t { return 1 ; } 9231 9232auto parse ( Args const & args ) const -> InternalParseResult { 9233return parse ( args. exeName (), TokenStream ( args ) ); 9234} 9235}; 9236 9237template < typename DerivedT > 9238class ComposableParserImpl : public ParserBase { 9239public : 9240template < typename T > 9241auto operator|( T const & other ) const -> Parser ; 9242 9243template < typename T > 9244auto operator + ( T const & other ) const -> Parser ; 9245}; 9246 9247// Common code and state for Args and Opts 9248template < typename DerivedT > 9249class ParserRefImpl : public ComposableParserImpl < DerivedT > { 9250protected : 9251Optionality m_optionality = Optionality::Optional; 9252std ::shared_ptr < BoundRef > m_ref; 9253std :: string m_hint; 9254std :: string m_description; 9255 9256explicit ParserRefImpl ( std ::shared_ptr < BoundRef > const & ref ) : m_ref ( ref ) {} 9257 9258public : 9259template < typename T > 9260ParserRefImpl ( T & ref, std::string const & hint ) 9261: m_ref ( std ::make_shared < BoundValueRef < T >>( ref ) ), 9262m_hint ( hint ) 9263{} 9264 9265template < typename LambdaT > 9266ParserRefImpl ( LambdaT const & ref, std::string const & hint ) 9267: m_ref ( std ::make_shared < BoundLambda < LambdaT>>( ref ) ), 9268m_hint (hint) 9269{} 9270 9271auto operator( )( std :: string const & description ) -> DerivedT & { 9272m_description = description ; 9273return static_cast < DerivedT &> ( * this ); 9274} 9275 9276auto optional () -> DerivedT & { 9277m_optionality = Optionality :: Optional ; 9278return static_cast < DerivedT &> ( * this ); 9279}; 9280 9281auto required () -> DerivedT & { 9282m_optionality = Optionality :: Required ; 9283return static_cast < DerivedT &> ( * this ); 9284}; 9285 9286auto isOptional () const -> bool { 9287return m_optionality == Optionality :: Optional ; 9288} 9289 9290auto cardinality () const -> size_t override { 9291if ( m_ref -> isContainer () ) 9292return 0 ; 9293else 9294return 1 ; 9295} 9296 9297auto hint () const -> std:: string { return m_hint ; } 9298}; 9299 9300class ExeName : public ComposableParserImpl < ExeName > { 9301std :: shared_ptr < std :: string > m_name ; 9302std :: shared_ptr < BoundValueRefBase > m_ref ; 9303 9304template < typename LambdaT > 9305static auto makeRef (LambdaT const & lambda ) -> std :: shared_ptr < BoundValueRefBase > { 9306return std :: make_shared < BoundLambda < LambdaT >>( lambda ) ; 9307} 9308 9309public : 9310ExeName () : m_name ( std:: make_shared < std :: string > ( "<executable>" ) ) {} 9311 9312explicit ExeName ( std:: string & ref ) : ExeName () { 9313m_ref = std :: make_shared < BoundValueRef < std :: string >>( ref ); 9314} 9315 9316template < typename LambdaT > 9317explicit ExeName ( LambdaT const & lambda ) : ExeName () { 9318m_ref = std :: make_shared < BoundLambda < LambdaT >>( lambda ); 9319} 9320 9321// The exe name is not parsed out of the normal tokens, but is handled specially 9322auto parse ( std::string const & , TokenStream const & tokens ) const -> InternalParseResult override { 9323return InternalParseResult :: ok ( ParseState ( ParseResultType :: NoMatch , tokens ) ); 9324} 9325 9326auto name () const -> std:: string { return * m_name ; } 9327auto set ( std::string const & newName ) -> ParserResult { 9328 9329auto lastSlash = newName. find_last_of ( "\\/" ); 9330auto filename = ( lastSlash == std::string::npos ) 9331? newName 9332: newName. substr ( lastSlash + 1 ); 9333 9334* m_name = filename; 9335if ( m_ref ) 9336return m_ref -> setValue ( filename ); 9337else 9338return ParserResult:: ok ( ParseResultType::Matched ); 9339} 9340}; 9341 9342class Arg : public ParserRefImpl < Arg > { 9343public : 9344using ParserRefImpl::ParserRefImpl; 9345 9346auto parse( std :: string const & , TokenStream const & tokens ) const -> InternalParseResult override { 9347auto validationResult = validate (); 9348if ( !validationResult ) 9349return InternalParseResult ( validationResult ); 9350 9351auto remainingTokens = tokens; 9352auto const & token = * remainingTokens; 9353if ( token. type != TokenType::Argument ) 9354return InternalParseResult:: ok ( ParseState ( ParseResultType::NoMatch, remainingTokens ) ); 9355 9356assert ( !m_ref -> isFlag () ); 9357auto valueRef = static_cast < detail::BoundValueRefBase * >( m_ref. get () ); 9358 9359auto result = valueRef -> setValue ( remainingTokens -> token ); 9360if ( !result ) 9361return InternalParseResult ( result ); 9362else 9363return InternalParseResult:: ok ( ParseState ( ParseResultType::Matched, ++ remainingTokens ) ); 9364} 9365}; 9366 9367inline auto normaliseOpt( std :: string const & optName ) -> std::string { 9368#ifdef CATCH_PLATFORM_WINDOWS 9369if ( optName[ 0 ] == '/' ) 9370return "-" + optName. substr ( 1 ); 9371else 9372#endif 9373return optName; 9374} 9375 9376class Opt : public ParserRefImpl < Opt > { 9377protected : 9378std ::vector < std::string > m_optNames; 9379 9380public : 9381template < typename LambdaT > 9382explicit Opt( LambdaT const & ref ) : ParserRefImpl ( std ::make_shared < BoundFlagLambda < LambdaT>>( ref ) ) {} 9383 9384explicit Opt ( bool & ref ) : ParserRefImpl ( std::make_shared < BoundFlagRef > ( ref ) ) {} 9385 9386template < typename LambdaT > 9387Opt ( LambdaT const & ref, std::string const & hint ) : ParserRefImpl ( ref, hint ) {} 9388 9389template < typename T > 9390Opt ( T & ref, std::string const & hint ) : ParserRefImpl ( ref, hint ) {} 9391 9392auto operator []( std ::string const & optName ) -> Opt & { 9393m_optNames. push_back ( optName ); 9394return * this; 9395} 9396 9397auto getHelpColumns() const -> std ::vector < HelpColumns > { 9398std::ostringstream oss; 9399bool first = true; 9400for ( auto const & opt : m_optNames ) { 9401if ( first ) 9402first = false; 9403else 9404oss << ", " ; 9405oss << opt; 9406} 9407if ( !m_hint. empty () ) 9408oss << " <" << m_hint << ">" ; 9409return { { oss. str (), m_description } }; 9410} 9411 9412auto isMatch( std :: string const & optToken ) const -> bool { 9413auto normalisedToken = normaliseOpt ( optToken ); 9414for ( auto const & name : m_optNames ) { 9415if ( normaliseOpt ( name ) == normalisedToken ) 9416return true; 9417} 9418return false; 9419} 9420 9421using ParserBase::parse; 9422 9423auto parse( std :: string const & , TokenStream const & tokens ) const -> InternalParseResult override { 9424auto validationResult = validate (); 9425if ( !validationResult ) 9426return InternalParseResult ( validationResult ); 9427 9428auto remainingTokens = tokens; 9429if ( remainingTokens && remainingTokens -> type == TokenType::Option ) { 9430auto const & token = * remainingTokens; 9431if ( isMatch (token. token ) ) { 9432if ( m_ref -> isFlag () ) { 9433auto flagRef = static_cast < detail::BoundFlagRefBase * >( m_ref. get () ); 9434auto result = flagRef -> setFlag ( true ); 9435if ( !result ) 9436return InternalParseResult ( result ); 9437if ( result. value () == ParseResultType::ShortCircuitAll ) 9438return InternalParseResult:: ok ( ParseState ( result. value (), remainingTokens ) ); 9439} else { 9440auto valueRef = static_cast < detail::BoundValueRefBase * >( m_ref. get () ); 9441++ remainingTokens; 9442if ( !remainingTokens ) 9443return InternalParseResult:: runtimeError ( "Expected argument following " + token. token ); 9444auto const & argToken = * remainingTokens; 9445if ( argToken. type != TokenType::Argument ) 9446return InternalParseResult:: runtimeError ( "Expected argument following " + token. token ); 9447auto result = valueRef -> setValue ( argToken. token ); 9448if ( !result ) 9449return InternalParseResult ( result ); 9450if ( result. value () == ParseResultType::ShortCircuitAll ) 9451return InternalParseResult:: ok ( ParseState ( result. value (), remainingTokens ) ); 9452} 9453return InternalParseResult:: ok ( ParseState ( ParseResultType::Matched, ++ remainingTokens ) ); 9454} 9455} 9456return InternalParseResult:: ok ( ParseState ( ParseResultType::NoMatch, remainingTokens ) ); 9457} 9458 9459auto validate() const -> Result override { 9460if ( m_optNames. empty () ) 9461return Result:: logicError ( "No options supplied to Opt" ); 9462for ( auto const & name : m_optNames ) { 9463if ( name. empty () ) 9464return Result:: logicError ( "Option name cannot be empty" ); 9465#ifdef CATCH_PLATFORM_WINDOWS 9466if( name [ 0 ] != ' - ' && name[ 0 ] != '/' ) 9467return Result::logicError( "Option name must begin with '-' or '/'" ); 9468#else 9469if ( name[ 0 ] != '-' ) 9470return Result:: logicError ( "Option name must begin with '-'" ); 9471#endif 9472} 9473return ParserRefImpl:: validate (); 9474} 9475}; 9476 9477struct Help : Opt { 9478Help ( bool & showHelpFlag ) 9479: Opt([ & ]( bool flag ) { 9480showHelpFlag = flag; 9481return ParserResult:: ok ( ParseResultType::ShortCircuitAll ); 9482}) 9483{ 9484static_cast < Opt &> ( * this ) 9485( "display usage information" ) 9486[ "-?" ][ "-h" ][ "--help" ] 9487. optional (); 9488} 9489}; 9490 9491struct Parser : ParserBase { 9492 9493mutable ExeName m_exeName; 9494std ::vector < Opt > m_options; 9495std ::vector < Arg > m_args; 9496 9497auto operator |=( ExeName const & exeName ) -> Parser & { 9498m_exeName = exeName; 9499return * this; 9500} 9501 9502auto operator |=( Arg const & arg ) -> Parser & { 9503m_args. push_back (arg); 9504return * this; 9505} 9506 9507auto operator |=( Opt const & opt ) -> Parser & { 9508m_options. push_back (opt); 9509return * this; 9510} 9511 9512auto operator |=( Parser const & other ) -> Parser & { 9513m_options. insert (m_options. end (), other. m_options . begin (), other. m_options . end ()); 9514m_args. insert (m_args. end (), other. m_args . begin (), other. m_args . end ()); 9515return * this; 9516} 9517 9518template < typename T > 9519auto operator|( T const & other ) const -> Parser { 9520return Parser ( * this ) |= other; 9521} 9522 9523// Forward deprecated interface with '+' instead of '|' 9524template < typename T > 9525auto operator += ( T const & other ) -> Parser & { return operator|=( other ); } 9526template < typename T > 9527auto operator + ( T const & other ) const -> Parser { return operator|( other ); } 9528 9529auto getHelpColumns() const -> std :: vector < HelpColumns > { 9530std::vector < HelpColumns > cols; 9531for (auto const & o : m_options) { 9532auto childCols = o.getHelpColumns(); 9533cols. insert ( cols. end (), childCols. begin (), childCols. end () ); 9534} 9535return cols; 9536} 9537 9538void writeToStream ( std ::ostream & os ) const { 9539if (!m_exeName. name (). empty ()) { 9540os << "usage:\n" << " " << m_exeName. name () << " " ; 9541bool required = true, first = true; 9542for ( auto const & arg : m_args ) { 9543if ( first ) 9544first = false; 9545else 9546os << " " ; 9547if ( arg. isOptional () && required ) { 9548os << "[" ; 9549required = false; 9550} 9551os << "<" << arg. hint () << ">" ; 9552if ( arg. cardinality () == 0 ) 9553os << " ... " ; 9554} 9555if ( !required ) 9556os << "]" ; 9557if ( !m_options. empty () ) 9558os << " options" ; 9559os << "\n\nwhere options are:" << std::endl; 9560} 9561 9562auto rows = getHelpColumns (); 9563size_t consoleWidth = CATCH_CLARA_CONFIG_CONSOLE_WIDTH ; 9564size_t optWidth = 0 ; 9565for ( auto const & cols : rows ) 9566optWidth = (std::max)(optWidth, cols. left . size () + 2 ); 9567 9568optWidth = (std::min)(optWidth, consoleWidth/ 2 ); 9569 9570for ( auto const & cols : rows ) { 9571auto row = 9572TextFlow:: Column ( cols. left ). width ( optWidth ). indent ( 2 ) + 9573TextFlow:: Spacer ( 4 ) + 9574TextFlow:: Column ( cols. right ). width ( consoleWidth - 7 - optWidth ); 9575os << row << std::endl; 9576} 9577} 9578 9579friend auto operator<<( std::ostream & os, Parser const & parser ) -> std ::ostream & { 9580parser. writeToStream ( os ); 9581return os; 9582} 9583 9584auto validate () const -> Result override { 9585for ( auto const & opt : m_options ) { 9586auto result = opt. validate (); 9587if ( !result ) 9588return result; 9589} 9590for ( auto const & arg : m_args ) { 9591auto result = arg. validate (); 9592if ( !result ) 9593return result; 9594} 9595return Result:: ok (); 9596} 9597 9598using ParserBase::parse; 9599 9600auto parse ( std::string const & exeName, TokenStream const & tokens ) const -> InternalParseResult override { 9601 9602struct ParserInfo { 9603ParserBase const * parser = nullptr ; 9604size_t count = 0 ; 9605}; 9606const size_t totalParsers = m_options. size () + m_args. size (); 9607assert ( totalParsers < 512 ); 9608// ParserInfo parseInfos[totalParsers]; // <-- this is what we really want to do 9609ParserInfo parseInfos[ 512 ]; 9610 9611{ 9612size_t i = 0 ; 9613for (auto const & opt : m_options) parseInfos[i ++ ]. parser = & opt; 9614for (auto const & arg : m_args) parseInfos[i ++ ]. parser = & arg; 9615} 9616 9617m_exeName. set ( exeName ); 9618 9619auto result = InternalParseResult:: ok ( ParseState ( ParseResultType::NoMatch, tokens ) ); 9620while ( result. value (). remainingTokens () ) { 9621bool tokenParsed = false; 9622 9623for ( size_t i = 0 ; i < totalParsers; ++ i ) { 9624auto & parseInfo = parseInfos[i]; 9625if ( parseInfo. parser -> cardinality () == 0 || parseInfo. count < parseInfo. parser -> cardinality () ) { 9626result = parseInfo. parser -> parse (exeName, result. value (). remainingTokens ()); 9627if (!result) 9628return result; 9629if (result. value (). type () != ParseResultType::NoMatch) { 9630tokenParsed = true; 9631++ parseInfo. count ; 9632break ; 9633} 9634} 9635} 9636 9637if ( result. value (). type () == ParseResultType::ShortCircuitAll ) 9638return result; 9639if ( !tokenParsed ) 9640return InternalParseResult:: runtimeError ( "Unrecognised token: " + result. value (). remainingTokens () -> token ); 9641} 9642// !TBD Check missing required options 9643return result; 9644} 9645}; 9646 9647template < typename DerivedT > 9648template < typename T > 9649auto ComposableParserImpl < DerivedT > ::operator|( T const & other ) const -> Parser { 9650return Parser () | static_cast < DerivedT const &> ( * this ) | other; 9651} 9652} // namespace detail 9653 9654// A Combined parser 9655using detail::Parser; 9656 9657// A parser for options 9658using detail::Opt; 9659 9660// A parser for arguments 9661using detail::Arg; 9662 9663// Wrapper for argc, argv from main() 9664using detail::Args; 9665 9666// Specifies the name of the executable 9667using detail::ExeName; 9668 9669// Convenience wrapper for option parser that specifies the help option 9670using detail::Help; 9671 9672// enum of result types from a parse 9673using detail::ParseResultType; 9674 9675// Result type for parser operation 9676using detail::ParserResult; 9677 9678}} // namespace Catch::clara 9679 9680// end clara.hpp 9681#ifdef __clang__ 9682#pragma clang diagnostic pop 9683#endif 9684 9685// Restore Clara's value for console width, if present 9686#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH 9687#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH 9688#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH 9689#endif 9690 9691// end catch_clara.h 9692namespace Catch { 9693 9694clara :: Parser makeCommandLineParser ( ConfigData & config ); 9695 9696} // end namespace Catch 9697 9698// end catch_commandline.h 9699#include <fstream> 9700#include <ctime> 9701 9702namespace Catch { 9703 9704clara :: Parser makeCommandLineParser ( ConfigData & config ) { 9705 9706using namespace clara; 9707 9708auto const setWarning = [ & ]( std::string const & warning ) { 9709auto warningSet = [ & ]() { 9710if ( warning == "NoAssertions" ) 9711return WarnAbout::NoAssertions; 9712 9713if ( warning == "NoTests" ) 9714return WarnAbout::NoTests; 9715 9716return WarnAbout::Nothing; 9717}(); 9718 9719if (warningSet == WarnAbout::Nothing) 9720return ParserResult:: runtimeError ( "Unrecognised warning: '" + warning + "'" ); 9721config. warnings = static_cast < WarnAbout::What > ( config. warnings | warningSet ); 9722return ParserResult:: ok ( ParseResultType::Matched ); 9723}; 9724auto const loadTestNamesFromFile = [ & ]( std::string const & filename ) { 9725std :: ifstream f ( filename . c_str () ); 9726if ( !f. is_open () ) 9727return ParserResult:: runtimeError ( "Unable to load input file: '" + filename + "'" ); 9728 9729std :: string line; 9730while ( std:: getline ( f, line ) ) { 9731line = trim (line); 9732if ( !line. empty () && ! startsWith ( line, '#' ) ) { 9733if ( ! startsWith ( line, '"' ) ) 9734line = '"' + line + '"' ; 9735config. testsOrTags . push_back ( line ); 9736config. testsOrTags . emplace_back ( "," ); 9737} 9738} 9739//Remove comma in the end 9740if (!config. testsOrTags . empty ()) 9741config. testsOrTags . erase ( config. testsOrTags . end () - 1 ); 9742 9743return ParserResult:: ok ( ParseResultType::Matched ); 9744}; 9745auto const setTestOrder = [ & ]( std::string const & order ) { 9746if ( startsWith ( "declared" , order ) ) 9747config. runOrder = RunTests::InDeclarationOrder; 9748else if ( startsWith ( "lexical" , order ) ) 9749config. runOrder = RunTests::InLexicographicalOrder; 9750else if ( startsWith ( "random" , order ) ) 9751config. runOrder = RunTests::InRandomOrder; 9752else 9753return clara::ParserResult:: runtimeError ( "Unrecognised ordering: '" + order + "'" ); 9754return ParserResult:: ok ( ParseResultType::Matched ); 9755}; 9756auto const setRngSeed = [ & ]( std::string const & seed ) { 9757if ( seed != "time" ) 9758return clara::detail:: convertInto ( seed, config. rngSeed ); 9759config. rngSeed = static_cast < unsigned int > ( std:: time ( nullptr ) ); 9760return ParserResult:: ok ( ParseResultType::Matched ); 9761}; 9762auto const setColourUsage = [ & ]( std::string const & useColour ) { 9763auto mode = toLower ( useColour ); 9764 9765if ( mode == "yes" ) 9766config. useColour = UseColour::Yes; 9767else if ( mode == "no" ) 9768config. useColour = UseColour::No; 9769else if ( mode == "auto" ) 9770config. useColour = UseColour::Auto; 9771else 9772return ParserResult:: runtimeError ( "colour mode must be one of: auto, yes or no. '" + useColour + "' not recognised" ); 9773return ParserResult:: ok ( ParseResultType::Matched ); 9774}; 9775auto const setWaitForKeypress = [ & ]( std::string const & keypress ) { 9776auto keypressLc = toLower ( keypress ); 9777if (keypressLc == "never" ) 9778config. waitForKeypress = WaitForKeypress::Never; 9779else if ( keypressLc == "start" ) 9780config. waitForKeypress = WaitForKeypress::BeforeStart; 9781else if ( keypressLc == "exit" ) 9782config. waitForKeypress = WaitForKeypress::BeforeExit; 9783else if ( keypressLc == "both" ) 9784config. waitForKeypress = WaitForKeypress::BeforeStartAndExit; 9785else 9786return ParserResult:: runtimeError ( "keypress argument must be one of: never, start, exit or both. '" + keypress + "' not recognised" ); 9787return ParserResult:: ok ( ParseResultType::Matched ); 9788}; 9789auto const setVerbosity = [ & ]( std::string const & verbosity ) { 9790auto lcVerbosity = toLower ( verbosity ); 9791if ( lcVerbosity == "quiet" ) 9792config. verbosity = Verbosity::Quiet; 9793else if ( lcVerbosity == "normal" ) 9794config. verbosity = Verbosity::Normal; 9795else if ( lcVerbosity == "high" ) 9796config. verbosity = Verbosity::High; 9797else 9798return ParserResult:: runtimeError ( "Unrecognised verbosity, '" + verbosity + "'" ); 9799return ParserResult:: ok ( ParseResultType::Matched ); 9800}; 9801auto const setReporter = [ & ]( std::string const & reporter ) { 9802IReporterRegistry :: FactoryMap const & factories = getRegistryHub (). getReporterRegistry (). getFactories (); 9803 9804auto lcReporter = toLower ( reporter ); 9805auto result = factories. find ( lcReporter ); 9806 9807if ( factories. end () != result ) 9808config. reporterName = lcReporter; 9809else 9810return ParserResult:: runtimeError ( "Unrecognized reporter, '" + reporter + "'. Check available with --list-reporters" ); 9811return ParserResult:: ok ( ParseResultType::Matched ); 9812}; 9813 9814auto cli 9815= ExeName ( config. processName ) 9816| Help ( config. showHelp ) 9817| Opt ( config. listTests ) 9818[ "-l" ][ "--list-tests" ] 9819( "list all/matching test cases" ) 9820| Opt ( config. listTags ) 9821[ "-t" ][ "--list-tags" ] 9822( "list all/matching tags" ) 9823| Opt ( config. showSuccessfulTests ) 9824[ "-s" ][ "--success" ] 9825( "include successful tests in output" ) 9826| Opt ( config. shouldDebugBreak ) 9827[ "-b" ][ "--break" ] 9828( "break into debugger on failure" ) 9829| Opt ( config. noThrow ) 9830[ "-e" ][ "--nothrow" ] 9831( "skip exception tests" ) 9832| Opt ( config. showInvisibles ) 9833[ "-i" ][ "--invisibles" ] 9834( "show invisibles (tabs, newlines)" ) 9835| Opt ( config. outputFilename , "filename" ) 9836[ "-o" ][ "--out" ] 9837( "output filename" ) 9838| Opt ( setReporter, "name" ) 9839[ "-r" ][ "--reporter" ] 9840( "reporter to use (defaults to console)" ) 9841| Opt ( config. name , "name" ) 9842[ "-n" ][ "--name" ] 9843( "suite name" ) 9844| Opt( [ & ]( bool ){ config. abortAfter = 1 ; } ) 9845[ "-a" ][ "--abort" ] 9846( "abort at first failure" ) 9847| Opt( [ & ]( int x ){ config. abortAfter = x; }, "no. failures" ) 9848[ "-x" ][ "--abortx" ] 9849( "abort after x failures" ) 9850| Opt ( setWarning, "warning name" ) 9851[ "-w" ][ "--warn" ] 9852( "enable warnings" ) 9853| Opt( [ & ]( bool flag ) { config. showDurations = flag ? ShowDurations::Always : ShowDurations ::Never; }, "yes|no" ) 9854[ "-d" ][ "--durations" ] 9855( "show test durations" ) 9856| Opt ( config. minDuration , "seconds" ) 9857[ "-D" ][ "--min-duration" ] 9858( "show test durations for tests taking at least the given number of seconds" ) 9859| Opt ( loadTestNamesFromFile, "filename" ) 9860[ "-f" ][ "--input-file" ] 9861( "load test names to run from a file" ) 9862| Opt ( config. filenamesAsTags ) 9863[ "-#" ][ "--filenames-as-tags" ] 9864( "adds a tag for the filename" ) 9865| Opt ( config. sectionsToRun , "section name" ) 9866[ "-c" ][ "--section" ] 9867( "specify section to run" ) 9868| Opt ( setVerbosity, "quiet|normal|high" ) 9869[ "-v" ][ "--verbosity" ] 9870( "set output verbosity" ) 9871| Opt ( config. listTestNamesOnly ) 9872[ "--list-test-names-only" ] 9873( "list all/matching test cases names only" ) 9874| Opt ( config. listReporters ) 9875[ "--list-reporters" ] 9876( "list all reporters" ) 9877| Opt ( setTestOrder, "decl|lex|rand" ) 9878[ "--order" ] 9879( "test case order (defaults to decl)" ) 9880| Opt ( setRngSeed, "'time'|number" ) 9881[ "--rng-seed" ] 9882( "set a specific seed for random numbers" ) 9883| Opt ( setColourUsage, "yes|no" ) 9884[ "--use-colour" ] 9885( "should output be colourised" ) 9886| Opt ( config. libIdentify ) 9887[ "--libidentify" ] 9888( "report name and version according to libidentify standard" ) 9889| Opt ( setWaitForKeypress, "never|start|exit|both" ) 9890[ "--wait-for-keypress" ] 9891( "waits for a keypress before exiting" ) 9892| Opt ( config. benchmarkSamples , "samples" ) 9893[ "--benchmark-samples" ] 9894( "number of samples to collect (default: 100)" ) 9895| Opt ( config. benchmarkResamples , "resamples" ) 9896[ "--benchmark-resamples" ] 9897( "number of resamples for the bootstrap (default: 100000)" ) 9898| Opt ( config. benchmarkConfidenceInterval , "confidence interval" ) 9899[ "--benchmark-confidence-interval" ] 9900( "confidence interval for the bootstrap (between 0 and 1, default: 0.95)" ) 9901| Opt ( config. benchmarkNoAnalysis ) 9902[ "--benchmark-no-analysis" ] 9903( "perform only measurements; do not perform any analysis" ) 9904| Opt ( config. benchmarkWarmupTime , "benchmarkWarmupTime" ) 9905[ "--benchmark-warmup-time" ] 9906( "amount of time in milliseconds spent on warming up each test (default: 100)" ) 9907| Arg ( config. testsOrTags , "test name|pattern|tags" ) 9908( "which test or tests to use" ); 9909 9910return cli; 9911} 9912 9913} // end namespace Catch 9914// end catch_commandline.cpp 9915// start catch_common.cpp 9916 9917#include <cstring> 9918#include <ostream> 9919 9920namespace Catch { 9921 9922bool SourceLineInfo ::operator == ( SourceLineInfo const & other ) const noexcept { 9923return line == other. line && (file == other. file || std:: strcmp (file, other. file ) == 0 ); 9924} 9925bool SourceLineInfo ::operator < ( SourceLineInfo const & other ) const noexcept { 9926// We can assume that the same file will usually have the same pointer. 9927// Thus, if the pointers are the same, there is no point in calling the strcmp 9928return line < other. line || ( line == other. line && file != other. file && (std:: strcmp (file, other. file ) < 0 )); 9929} 9930 9931std ::ostream & operator << ( std::ostream & os, SourceLineInfo const & info ) { 9932#ifndef __GNUG__ 9933os << info. file << '(' << info. line << ')' ; 9934#else 9935os << info. file << ':' << info. line ; 9936#endif 9937return os; 9938} 9939 9940std :: string StreamEndStop::operator + () const { 9941return std:: string (); 9942} 9943 9944NonCopyable :: NonCopyable () = default; 9945NonCopyable ::~ NonCopyable () = default; 9946 9947} 9948// end catch_common.cpp 9949// start catch_config.cpp 9950 9951namespace Catch { 9952 9953Config ::Config( ConfigData const & data ) 9954: m_data ( data ), 9955m_stream ( openStream () ) 9956{ 9957// We need to trim filter specs to avoid trouble with superfluous 9958// whitespace (esp. important for bdd macros, as those are manually 9959// aligned with whitespace). 9960 9961for (auto & elem : m_data.testsOrTags) { 9962elem = trim (elem); 9963} 9964for (auto & elem : m_data. sectionsToRun ) { 9965elem = trim (elem); 9966} 9967 9968TestSpecParser parser (ITagAliasRegistry:: get ()); 9969if (!m_data. testsOrTags . empty ()) { 9970m_hasTestFilters = true; 9971for (auto const & testOrTags : m_data. testsOrTags ) { 9972parser. parse (testOrTags); 9973} 9974} 9975m_testSpec = parser. testSpec (); 9976} 9977 9978std::string const & Config:: getFilename () const { 9979return m_data. outputFilename ; 9980} 9981 9982bool Config:: listTests () const { return m_data. listTests ; } 9983bool Config:: listTestNamesOnly () const { return m_data. listTestNamesOnly ; } 9984bool Config:: listTags () const { return m_data. listTags ; } 9985bool Config:: listReporters () const { return m_data. listReporters ; } 9986 9987std::string Config::getProcessName() const { return m_data.processName; } 9988std::string const & Config::getReporterName() const { return m_data.reporterName; } 9989 9990std::vector < std::string > const & Config::getTestsOrTags() const { return m_data.testsOrTags; } 9991std::vector < std::string > const & Config::getSectionsToRun() const { return m_data.sectionsToRun; } 9992 9993TestSpec const & Config::testSpec() const { return m_testSpec; } 9994bool Config::hasTestFilters() const { return m_hasTestFilters; } 9995 9996bool Config::showHelp() const { return m_data.showHelp; } 9997 9998// IConfig interface 9999bool Config::allowThrows() const { return !m_data.noThrow; } 10000std::ostream & Config::stream() const { return m_stream -> stream(); } 10001std::string Config::name() const { return m_data.name.empty() ? m_data.processName : m_data.name; } 10002bool Config::includeSuccessfulResults() const { return m_data.showSuccessfulTests; } 10003bool Config::warnAboutMissingAssertions() const { return !!(m_data.warnings & WarnAbout::NoAssertions); } 10004bool Config::warnAboutNoTests() const { return !!(m_data.warnings & WarnAbout::NoTests); } 10005ShowDurations::OrNot Config::showDurations() const { return m_data.showDurations; } 10006double Config::minDuration() const { return m_data.minDuration; } 10007RunTests::InWhatOrder Config::runOrder() const { return m_data.runOrder; } 10008unsigned int Config::rngSeed() const { return m_data.rngSeed; } 10009UseColour::YesOrNo Config::useColour() const { return m_data.useColour; } 10010bool Config::shouldDebugBreak() const { return m_data.shouldDebugBreak; } 10011int Config::abortAfter() const { return m_data.abortAfter; } 10012bool Config::showInvisibles() const { return m_data.showInvisibles; } 10013Verbosity Config::verbosity() const { return m_data.verbosity; } 10014 10015bool Config::benchmarkNoAnalysis() const { return m_data.benchmarkNoAnalysis; } 10016int Config::benchmarkSamples() const { return m_data.benchmarkSamples; } 10017double Config::benchmarkConfidenceInterval() const { return m_data.benchmarkConfidenceInterval; } 10018unsigned int Config::benchmarkResamples() const { return m_data.benchmarkResamples; } 10019std::chrono::milliseconds Config::benchmarkWarmupTime() const { return std::chrono::milliseconds(m_data.benchmarkWarmupTime); } 10020 10021IStream const * Config::openStream() { 10022return Catch::makeStream(m_data.outputFilename); 10023} 10024 10025} // end namespace Catch 10026// end catch_config.cpp 10027// start catch_console_colour.cpp 10028 10029#if defined(__clang__) 10030# pragma clang diagnostic push 10031# pragma clang diagnostic ignored " - Wexit - time - destructors" 10032#endif 10033 10034// start catch_errno_guard.h 10035 10036namespace Catch { 10037 10038class ErrnoGuard { 10039public: 10040ErrnoGuard(); 10041~ErrnoGuard(); 10042private: 10043int m_oldErrno; 10044}; 10045 10046} 10047 10048// end catch_errno_guard.h 10049// start catch_windows_h_proxy.h 10050 10051 10052#if defined( CATCH_PLATFORM_WINDOWS ) 10053 10054#if !defined( NOMINMAX ) && !defined( CATCH_CONFIG_NO_NOMINMAX ) 10055# define CATCH_DEFINED_NOMINMAX 10056# define NOMINMAX 10057#endif 10058#if !defined( WIN32_LEAN_AND_MEAN ) && !defined( CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN ) 10059# define CATCH_DEFINED_WIN32_LEAN_AND_MEAN 10060# define WIN32_LEAN_AND_MEAN 10061#endif 10062 10063#ifdef __AFXDLL 10064#include < AfxWin.h > 10065#else 10066#include < windows.h > 10067#endif 10068 10069#ifdef CATCH_DEFINED_NOMINMAX 10070# undef NOMINMAX 10071#endif 10072#ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN 10073# undef WIN32_LEAN_AND_MEAN 10074#endif 10075 10076#endif // defined(CATCH_PLATFORM_WINDOWS) 10077 10078// end catch_windows_h_proxy.h 10079#include < sstream > 10080 10081namespace Catch { 10082namespace { 10083 10084struct IColourImpl { 10085virtual ~IColourImpl() = default ; 10086virtual void use( Colour::Code _colourCode ) = 0 ; 10087}; 10088 10089struct NoColourImpl : IColourImpl { 10090void use( Colour::Code ) override {} 10091 10092static IColourImpl * instance() { 10093static NoColourImpl s_instance; 10094return & s_instance; 10095} 10096}; 10097 10098} // anon namespace 10099} // namespace Catch 10100 10101#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI ) 10102# ifdef CATCH_PLATFORM_WINDOWS 10103# define CATCH_CONFIG_COLOUR_WINDOWS 10104# else 10105# define CATCH_CONFIG_COLOUR_ANSI 10106# endif 10107#endif 10108 10109#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) ///////////////////////////////////////// 10110 10111namespace Catch { 10112namespace { 10113 10114class Win32ColourImpl : public IColourImpl { 10115public: 10116Win32ColourImpl() : stdoutHandle( GetStdHandle( STD_OUTPUT_HANDLE ) ) 10117{ 10118CONSOLE_SCREEN_BUFFER_INFO csbiInfo; 10119GetConsoleScreenBufferInfo( stdoutHandle, & csbiInfo ); 10120originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY ); 10121originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ); 10122} 10123 10124void use( Colour::Code _colourCode ) override { 10125switch ( _colourCode ) { 10126case Colour::None: return setTextAttribute( originalForegroundAttributes ); 10127case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); 10128case Colour::Red: return setTextAttribute( FOREGROUND_RED ); 10129case Colour::Green: return setTextAttribute( FOREGROUND_GREEN ); 10130case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE ); 10131case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN ); 10132case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN ); 10133case Colour::Grey: return setTextAttribute( 0 ); 10134 10135case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY ); 10136case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED ); 10137case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN ); 10138case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); 10139case Colour::BrightYellow: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN ); 10140 10141case Colour::Bright: CATCH_INTERNAL_ERROR ( "not a colour" ); 10142 10143default : 10144CATCH_ERROR ( "Unknown colour requested" ); 10145} 10146} 10147 10148private: 10149void setTextAttribute( WORD _textAttribute ) { 10150SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes ); 10151} 10152HANDLE stdoutHandle; 10153WORD originalForegroundAttributes; 10154WORD originalBackgroundAttributes; 10155}; 10156 10157IColourImpl * platformColourInstance() { 10158static Win32ColourImpl s_instance; 10159 10160IConfigPtr config = getCurrentContext().getConfig(); 10161UseColour::YesOrNo colourMode = config 10162? config -> useColour() 10163: UseColour::Auto; 10164if ( colourMode == UseColour::Auto ) 10165colourMode = UseColour::Yes; 10166return colourMode == UseColour::Yes 10167? & s_instance 10168: NoColourImpl::instance(); 10169} 10170 10171} // end anon namespace 10172} // end namespace Catch 10173 10174#elif defined( CATCH_CONFIG_COLOUR_ANSI ) ////////////////////////////////////// 10175 10176#include < unistd.h > 10177 10178namespace Catch { 10179namespace { 10180 10181// use POSIX/ ANSI console terminal codes 10182// Thanks to Adam Strzelecki for original contribution 10183// (http://github.com/nanoant) 10184// https://github.com/philsquared/Catch/pull/131 10185class PosixColourImpl : public IColourImpl { 10186public: 10187void use( Colour::Code _colourCode ) override { 10188switch ( _colourCode ) { 10189case Colour::None: 10190case Colour::White: return setColour( "[ 0 m" ); 10191case Colour::Red: return setColour( "[ 0 ; 31 m" ); 10192case Colour::Green: return setColour( "[ 0 ; 32 m" ); 10193case Colour::Blue: return setColour( "[ 0 ; 34 m" ); 10194case Colour::Cyan: return setColour( "[ 0 ; 36 m" ); 10195case Colour::Yellow: return setColour( "[ 0 ; 33 m" ); 10196case Colour::Grey: return setColour( "[ 1 ; 30 m" ); 10197 10198case Colour::LightGrey: return setColour( "[ 0 ; 37 m" ); 10199case Colour::BrightRed: return setColour( "[ 1 ; 31 m" ); 10200case Colour::BrightGreen: return setColour( "[ 1 ; 32 m" ); 10201case Colour::BrightWhite: return setColour( "[ 1 ; 37 m" ); 10202case Colour::BrightYellow: return setColour( "[ 1 ; 33 m" ); 10203 10204case Colour::Bright: CATCH_INTERNAL_ERROR ( "not a colour" ); 10205default : CATCH_INTERNAL_ERROR ( "Unknown colour requested" ); 10206} 10207} 10208static IColourImpl * instance() { 10209static PosixColourImpl s_instance; 10210return & s_instance; 10211} 10212 10213private: 10214void setColour( const char * _escapeCode ) { 10215getCurrentContext().getConfig() -> stream() 10216<< '\ 033 ' << _escapeCode; 10217} 10218}; 10219 10220bool useColourOnPlatform() { 10221return 10222#if defined( CATCH_PLATFORM_MAC ) || defined( CATCH_PLATFORM_IPHONE ) 10223!isDebuggerActive() && 10224#endif 10225#if !( defined (__DJGPP__) && defined (__STRICT_ANSI__)) 10226isatty ( STDOUT_FILENO ) 10227#else 10228false 10229#endif 10230; 10231} 10232IColourImpl * platformColourInstance () { 10233ErrnoGuard guard; 10234IConfigPtr config = getCurrentContext (). getConfig (); 10235UseColour::YesOrNo colourMode = config 10236? config -> useColour () 10237: UseColour::Auto; 10238if ( colourMode == UseColour::Auto ) 10239colourMode = useColourOnPlatform () 10240? UseColour::Yes 10241: UseColour::No; 10242return colourMode == UseColour::Yes 10243? PosixColourImpl:: instance () 10244: NoColourImpl:: instance (); 10245} 10246 10247} // end anon namespace 10248} // end namespace Catch 10249 10250#else // not Windows or ANSI /////////////////////////////////////////////// 10251 10252namespace Catch { 10253 10254static IColourImpl * platformColourInstance () { return NoColourImpl:: instance (); } 10255 10256} // end namespace Catch 10257 10258#endif // Windows/ ANSI/ None 10259 10260namespace Catch { 10261 10262Colour ::Colour( Code _colourCode ) { use ( _colourCode ); } 10263Colour :: Colour ( Colour && other ) noexcept { 10264m_moved = other. m_moved ; 10265other. m_moved = true; 10266} 10267Colour & Colour::operator = ( Colour && other ) noexcept { 10268m_moved = other. m_moved ; 10269other. m_moved = true; 10270return * this; 10271} 10272 10273Colour ::~ Colour (){ if ( !m_moved ) use ( None ); } 10274 10275void Colour:: use ( Code _colourCode ) { 10276static IColourImpl * impl = platformColourInstance (); 10277// Strictly speaking, this cannot possibly happen. 10278// However, under some conditions it does happen (see #1626), 10279// and this change is small enough that we can let practicality 10280// triumph over purity in this case. 10281if (impl != nullptr ) { 10282impl -> use ( _colourCode ); 10283} 10284} 10285 10286std ::ostream & operator << ( std::ostream & os, Colour const & ) { 10287return os; 10288} 10289 10290} // end namespace Catch 10291 10292#if defined(__clang__) 10293# pragma clang diagnostic pop 10294#endif 10295 10296// end catch_console_colour.cpp 10297// start catch_context.cpp 10298 10299namespace Catch { 10300 10301class Context : public IMutableContext, NonCopyable { 10302 10303public : // IContext 10304IResultCapture * getResultCapture () override { 10305return m_resultCapture; 10306} 10307IRunner * getRunner () override { 10308return m_runner; 10309} 10310 10311IConfigPtr const & getConfig () const override { 10312return m_config; 10313} 10314 10315~ Context () override; 10316 10317public : // IMutableContext 10318void setResultCapture ( IResultCapture * resultCapture ) override { 10319m_resultCapture = resultCapture; 10320} 10321void setRunner ( IRunner * runner ) override { 10322m_runner = runner; 10323} 10324void setConfig ( IConfigPtr const & config ) override { 10325m_config = config; 10326} 10327 10328friend IMutableContext & getCurrentMutableContext (); 10329 10330private : 10331IConfigPtr m_config; 10332IRunner * m_runner = nullptr ; 10333IResultCapture * m_resultCapture = nullptr ; 10334}; 10335 10336IMutableContext * IMutableContext::currentContext = nullptr ; 10337 10338void IMutableContext:: createContext () 10339{ 10340currentContext = new Context (); 10341} 10342 10343void cleanUpContext () { 10344delete IMutableContext::currentContext; 10345IMutableContext ::currentContext = nullptr ; 10346} 10347IContext ::~ IContext () = default; 10348IMutableContext ::~ IMutableContext () = default; 10349Context ::~ Context () = default; 10350 10351SimplePcg32 & rng () { 10352static SimplePcg32 s_rng; 10353return s_rng; 10354} 10355 10356} 10357// end catch_context.cpp 10358// start catch_debug_console.cpp 10359 10360// start catch_debug_console.h 10361 10362#include <string> 10363 10364namespace Catch { 10365void writeToDebugConsole ( std ::string const & text ); 10366} 10367 10368// end catch_debug_console.h 10369#if defined( CATCH_CONFIG_ANDROID_LOGWRITE ) 10370#include <android/log.h> 10371 10372namespace Catch { 10373void writeToDebugConsole ( std ::string const & text ) { 10374__android_log_write ( ANDROID_LOG_DEBUG , "Catch" , text. c_str () ); 10375} 10376} 10377 10378#elif defined( CATCH_PLATFORM_WINDOWS ) 10379 10380namespace Catch { 10381void writeToDebugConsole ( std ::string const & text ) { 10382:: OutputDebugStringA ( text. c_str () ); 10383} 10384} 10385 10386#else 10387 10388namespace Catch { 10389void writeToDebugConsole ( std ::string const & text ) { 10390// !TBD: Need a version for Mac/ XCode and other IDEs 10391Catch :: cout () << text; 10392} 10393} 10394 10395#endif // Platform 10396// end catch_debug_console.cpp 10397// start catch_debugger.cpp 10398 10399#if defined( CATCH_PLATFORM_MAC ) || defined( CATCH_PLATFORM_IPHONE ) 10400 10401# include <cassert> 10402# include <sys/types.h> 10403# include <unistd.h> 10404# include <cstddef> 10405# include <ostream> 10406 10407#ifdef __apple_build_version__ 10408// These headers will only compile with AppleClang (XCode) 10409// For other compilers (Clang, GCC, ... ) we need to exclude them 10410# include <sys/sysctl.h> 10411#endif 10412 10413namespace Catch { 10414#ifdef __apple_build_version__ 10415// The following function is taken directly from the following technical note: 10416// https://developer.apple.com/library/archive/qa/qa1361/_index.html 10417 10418// Returns true if the current process is being debugged (either 10419// running under the debugger or has a debugger attached post facto). 10420bool isDebuggerActive (){ 10421int mib[ 4 ]; 10422struct kinfo_proc info; 10423std :: size_t size; 10424 10425// Initialize the flags so that, if sysctl fails for some bizarre 10426// reason, we get a predictable result. 10427 10428info. kp_proc . p_flag = 0 ; 10429 10430// Initialize mib, which tells sysctl the info we want, in this case 10431// we're looking for information about a specific process ID. 10432 10433mib[ 0 ] = CTL_KERN ; 10434mib[ 1 ] = KERN_PROC ; 10435mib[ 2 ] = KERN_PROC_PID ; 10436mib[ 3 ] = getpid (); 10437 10438// Call sysctl. 10439 10440size = sizeof (info); 10441if ( sysctl (mib, sizeof (mib) / sizeof ( * mib), & info, & size, nullptr , 0 ) != 0 ) { 10442Catch :: cerr () << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; 10443return false; 10444} 10445 10446// We're being debugged if the P_TRACED flag is set. 10447 10448return ( (info. kp_proc . p_flag & P_TRACED ) != 0 ); 10449} 10450#else 10451bool isDebuggerActive () { 10452// We need to find another way to determine this for non-appleclang compilers on macOS 10453return false; 10454} 10455#endif 10456} // namespace Catch 10457 10458#elif defined( CATCH_PLATFORM_LINUX ) 10459#include <fstream> 10460#include <string> 10461 10462namespace Catch{ 10463// The standard POSIX way of detecting a debugger is to attempt to 10464// ptrace() the process, but this needs to be done from a child and not 10465// this process itself to still allow attaching to this process later 10466// if wanted, so is rather heavy. Under Linux we have the PID of the 10467// "debugger" (which doesn't need to be gdb, of course, it could also 10468// be strace, for example) in /proc/$PID/status, so just get it from 10469// there instead. 10470bool isDebuggerActive (){ 10471// Libstdc++ has a bug, where std::ifstream sets errno to 0 10472// This way our users can properly assert over errno values 10473ErrnoGuard guard; 10474std:: ifstream in("/proc/self/status "); 10475for( std::string line; std:: getline (in, line); ) { 10476static const int PREFIX_LEN = 11 ; 10477if ( line. compare ( 0 , PREFIX_LEN , "TracerPid:\t" ) == 0 ) { 10478// We're traced if the PID is not 0 and no other PID starts 10479// with 0 digit, so it's enough to check for just a single 10480// character. 10481return line. length () > PREFIX_LEN && line[ PREFIX_LEN ] != '0' ; 10482} 10483} 10484 10485return false; 10486} 10487} // namespace Catch 10488#elif defined(_MSC_VER) 10489extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent (); 10490namespace Catch { 10491bool isDebuggerActive () { 10492return IsDebuggerPresent () != 0 ; 10493} 10494} 10495#elif defined(__MINGW32__) 10496extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent (); 10497namespace Catch { 10498bool isDebuggerActive () { 10499return IsDebuggerPresent () != 0 ; 10500} 10501} 10502#else 10503namespace Catch { 10504bool isDebuggerActive () { return false; } 10505} 10506#endif // Platform 10507// end catch_debugger.cpp 10508// start catch_decomposer.cpp 10509 10510namespace Catch { 10511 10512ITransientExpression ::~ ITransientExpression () = default; 10513 10514void formatReconstructedExpression ( std ::ostream & os, std ::string const & lhs, StringRef op, std ::string const & rhs ) { 10515if ( lhs. size () + rhs. size () < 40 && 10516lhs. find ( '\n' ) == std::string::npos && 10517rhs. find ( '\n' ) == std::string::npos ) 10518os << lhs << " " << op << " " << rhs; 10519else 10520os << lhs << "\n" << op << "\n" << rhs; 10521} 10522} 10523// end catch_decomposer.cpp 10524// start catch_enforce.cpp 10525 10526#include <stdexcept> 10527 10528namespace Catch { 10529#if defined( CATCH_CONFIG_DISABLE_EXCEPTIONS ) && !defined( CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER ) 10530[[noreturn]] 10531void throw_exception ( std ::exception const & e) { 10532Catch :: cerr () << "Catch will terminate because it needed to throw an exception.\n" 10533<< "The message was: " << e. what () << '\n' ; 10534std :: terminate (); 10535} 10536#endif 10537 10538[[noreturn]] 10539void throw_logic_error ( std ::string const & msg) { 10540throw_exception( std :: logic_error ( msg )); 10541} 10542 10543[[noreturn]] 10544void throw_domain_error ( std ::string const & msg) { 10545throw_exception( std :: domain_error ( msg )); 10546} 10547 10548[[noreturn]] 10549void throw_runtime_error ( std ::string const & msg) { 10550throw_exception( std :: runtime_error ( msg )); 10551} 10552 10553} // namespace Catch; 10554// end catch_enforce.cpp 10555// start catch_enum_values_registry.cpp 10556// start catch_enum_values_registry.h 10557 10558#include <vector> 10559#include <memory> 10560 10561namespace Catch { 10562 10563namespace Detail { 10564 10565std ::unique_ptr < EnumInfo > makeEnumInfo ( StringRef enumName, StringRef allValueNames, std::vector < int > const & values ); 10566 10567class EnumValuesRegistry : public IMutableEnumValuesRegistry { 10568 10569std ::vector < std::unique_ptr < EnumInfo>> m_enumInfos; 10570 10571EnumInfo const & registerEnum ( StringRef enumName, StringRef allEnums, std ::vector < int > const & values) override; 10572}; 10573 10574std ::vector < StringRef > parseEnums ( StringRef enums ); 10575 10576} // Detail 10577 10578} // Catch 10579 10580// end catch_enum_values_registry.h 10581 10582#include <map> 10583#include <cassert> 10584 10585namespace Catch { 10586 10587IMutableEnumValuesRegistry ::~ IMutableEnumValuesRegistry () {} 10588 10589namespace Detail { 10590 10591namespace { 10592// Extracts the actual name part of an enum instance 10593// In other words, it returns the Blue part of Bikeshed::Colour::Blue 10594StringRef extractInstanceName ( StringRef enumInstance) { 10595// Find last occurrence of ":" 10596size_t name_start = enumInstance. size (); 10597while (name_start > 0 && enumInstance[name_start - 1 ] != ':' ) { 10598-- name_start; 10599} 10600return enumInstance. substr (name_start, enumInstance. size () - name_start); 10601} 10602} 10603 10604std ::vector < StringRef > parseEnums ( StringRef enums ) { 10605auto enumValues = splitStringRef ( enums, ',' ); 10606std ::vector < StringRef > parsed; 10607parsed. reserve ( enumValues. size () ); 10608for ( auto const & enumValue : enumValues ) { 10609parsed. push_back ( trim ( extractInstanceName ( enumValue ))); 10610} 10611return parsed; 10612} 10613 10614EnumInfo ::~ EnumInfo () {} 10615 10616StringRef EnumInfo:: lookup ( int value ) const { 10617for ( auto const & valueToName : m_values ) { 10618if ( valueToName.first == value ) 10619return valueToName.second; 10620} 10621return "{** unexpected enum value **}" _sr; 10622} 10623 10624std::unique_ptr < EnumInfo > makeEnumInfo ( StringRef enumName, StringRef allValueNames, std::vector < int > const & values ) { 10625std::unique_ptr < EnumInfo > enumInfo ( new EnumInfo ); 10626enumInfo -> m_name = enumName; 10627enumInfo -> m_values . reserve ( values. size () ); 10628 10629const auto valueNames = Catch::Detail:: parseEnums ( allValueNames ); 10630assert ( valueNames. size () == values. size () ); 10631std:: size_t i = 0 ; 10632for ( auto value : values ) 10633enumInfo -> m_values . emplace_back (value, valueNames[i ++ ]); 10634 10635return enumInfo; 10636} 10637 10638EnumInfo const & EnumValuesRegistry:: registerEnum ( StringRef enumName, StringRef allValueNames, std ::vector < int > const & values ) { 10639m_enumInfos. push_back ( makeEnumInfo (enumName, allValueNames, values)); 10640return * m_enumInfos. back (); 10641} 10642 10643} // Detail 10644} // Catch 10645 10646// end catch_enum_values_registry.cpp 10647// start catch_errno_guard.cpp 10648 10649#include <cerrno> 10650 10651namespace Catch { 10652ErrnoGuard :: ErrnoGuard ():m_oldErrno( errno ){} 10653ErrnoGuard ::~ ErrnoGuard () { errno = m_oldErrno; } 10654} 10655// end catch_errno_guard.cpp 10656// start catch_exception_translator_registry.cpp 10657 10658// start catch_exception_translator_registry.h 10659 10660#include <vector> 10661#include <string> 10662#include <memory> 10663 10664namespace Catch { 10665 10666class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { 10667public : 10668~ ExceptionTranslatorRegistry (); 10669virtual void registerTranslator ( const IExceptionTranslator * translator ); 10670std :: string translateActiveException () const override; 10671std :: string tryTranslators () const; 10672 10673private : 10674std ::vector < std::unique_ptr < IExceptionTranslator const>> m_translators; 10675}; 10676} 10677 10678// end catch_exception_translator_registry.h 10679#ifdef __OBJC__ 10680#import "Foundation/Foundation.h" 10681#endif 10682 10683namespace Catch { 10684 10685ExceptionTranslatorRegistry ::~ ExceptionTranslatorRegistry () { 10686} 10687 10688void ExceptionTranslatorRegistry:: registerTranslator ( const IExceptionTranslator * translator ) { 10689m_translators. push_back ( std::unique_ptr < const IExceptionTranslator > ( translator ) ); 10690} 10691 10692#if !defined( CATCH_CONFIG_DISABLE_EXCEPTIONS ) 10693std :: string ExceptionTranslatorRegistry:: translateActiveException () const { 10694try { 10695#ifdef __OBJC__ 10696// In Objective-C try objective-c exceptions first 10697@try { 10698return tryTranslators (); 10699} 10700@ catch (NSException * exception) { 10701return Catch::Detail::stringify( [exception description] ); 10702} 10703#else 10704// Compiling a mixed mode project with MSVC means that CLR 10705// exceptions will be caught in (...) as well. However, these 10706// do not fill-in std::current_exception and thus lead to crash 10707// when attempting rethrow. 10708// /EHa switch also causes structured exceptions to be caught 10709// here, but they fill-in current_exception properly, so 10710// at worst the output should be a little weird, instead of 10711// causing a crash. 10712if (std:: current_exception () == nullptr ) { 10713return "Non C++ exception. Possibly a CLR exception." ; 10714} 10715return tryTranslators (); 10716#endif 10717} 10718catch ( TestFailureException & ) { 10719std ::rethrow_exception( std :: current_exception ()); 10720} 10721catch ( std::exception & ex ) { 10722return ex. what (); 10723} 10724catch ( std::string & msg ) { 10725return msg; 10726} 10727catch ( const char * msg ) { 10728return msg; 10729} 10730catch (...) { 10731return "Unknown exception" ; 10732} 10733} 10734 10735std::string ExceptionTranslatorRegistry:: tryTranslators () const { 10736if (m_translators. empty ()) { 10737std ::rethrow_exception( std :: current_exception ()); 10738} else { 10739return m_translators[ 0 ] -> translate (m_translators. begin () + 1 , m_translators. end ()); 10740} 10741} 10742 10743#else // ^^ Exceptions are enabled // Exceptions are disabled vv 10744std::string ExceptionTranslatorRegistry:: translateActiveException () const { 10745CATCH_INTERNAL_ERROR ( "Attempted to translate active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!" ); 10746} 10747 10748std::string ExceptionTranslatorRegistry:: tryTranslators () const { 10749CATCH_INTERNAL_ERROR ( "Attempted to use exception translators under CATCH_CONFIG_DISABLE_EXCEPTIONS!" ); 10750} 10751#endif 10752 10753} 10754// end catch_exception_translator_registry.cpp 10755// start catch_fatal_condition.cpp 10756 10757#include < algorithm > 10758 10759#if ! defined ( CATCH_CONFIG_WINDOWS_SEH ) && ! defined ( CATCH_CONFIG_POSIX_SIGNALS ) 10760 10761namespace Catch { 10762 10763// If neither SEH nor signal handling is required, the handler impls 10764// do not have to do anything, and can be empty. 10765void FatalConditionHandler:: engage_platform () {} 10766void FatalConditionHandler:: disengage_platform () {} 10767FatalConditionHandler :: FatalConditionHandler () = default; 10768FatalConditionHandler ::~ FatalConditionHandler () = default; 10769 10770} // end namespace Catch 10771 10772#endif // !CATCH_CONFIG_WINDOWS_SEH && !CATCH_CONFIG_POSIX_SIGNALS 10773 10774#if defined( CATCH_CONFIG_WINDOWS_SEH ) && defined ( CATCH_CONFIG_POSIX_SIGNALS ) 10775#error "Inconsistent configuration: Windows' SEH handling and POSIX signals cannot be enabled at the same time" 10776#endif // CATCH_CONFIG_WINDOWS_SEH && CATCH_CONFIG_POSIX_SIGNALS 10777 10778#if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS ) 10779 10780namespace { 10781//! Signals fatal error message to the run context 10782void reportFatal ( char const * const message ) { 10783Catch :: getCurrentContext (). getResultCapture () -> handleFatalErrorCondition ( message ); 10784} 10785 10786//! Minimal size Catch2 needs for its own fatal error handling. 10787//! Picked anecdotally, so it might not be sufficient on all 10788//! platforms, and for all configurations. 10789constexpr std :: size_t minStackSizeForErrors = 32 * 1024 ; 10790} // end unnamed namespace 10791 10792#endif // CATCH_CONFIG_WINDOWS_SEH || CATCH_CONFIG_POSIX_SIGNALS 10793 10794#if defined( CATCH_CONFIG_WINDOWS_SEH ) 10795 10796namespace Catch { 10797 10798struct SignalDefs { DWORD id ; const char * name ; }; 10799 10800// There is no 1-1 mapping between signals and windows exceptions. 10801// Windows can easily distinguish between SO and SigSegV, 10802// but SigInt, SigTerm, etc are handled differently. 10803static SignalDefs signalDefs[] = { 10804{ static_cast < DWORD > ( EXCEPTION_ILLEGAL_INSTRUCTION ), "SIGILL - Illegal instruction signal" }, 10805{ static_cast < DWORD > ( EXCEPTION_STACK_OVERFLOW ), "SIGSEGV - Stack overflow" }, 10806{ static_cast < DWORD > ( EXCEPTION_ACCESS_VIOLATION ), "SIGSEGV - Segmentation violation signal" }, 10807{ static_cast < DWORD > ( EXCEPTION_INT_DIVIDE_BY_ZERO ), "Divide by zero error" }, 10808}; 10809 10810static LONG CALLBACK handleVectoredException ( PEXCEPTION_POINTERS ExceptionInfo) { 10811for (auto const & def : signalDefs ) { 10812if ( ExceptionInfo -> ExceptionRecord -> ExceptionCode == def.id) { 10813reportFatal ( def .name); 10814} 10815} 10816// If its not an exception we care about, pass it along. 10817// This stops us from eating debugger breaks etc. 10818return EXCEPTION_CONTINUE_SEARCH ; 10819} 10820 10821// Since we do not support multiple instantiations, we put these 10822// into global variables and rely on cleaning them up in outlined 10823// constructors/destructors 10824static PVOID exceptionHandlerHandle = nullptr ; 10825 10826// For MSVC, we reserve part of the stack memory for handling 10827// memory overflow structured exception. 10828FatalConditionHandler :: FatalConditionHandler () { 10829ULONG guaranteeSize = static_cast < ULONG > (minStackSizeForErrors); 10830if (! SetThreadStackGuarantee ( & guaranteeSize)) { 10831// We do not want to fully error out, because needing 10832// the stack reserve should be rare enough anyway. 10833Catch :: cerr () 10834<< "Failed to reserve piece of stack." 10835<< " Stack overflows will not be reported successfully." ; 10836} 10837} 10838 10839// We do not attempt to unset the stack guarantee, because 10840// Windows does not support lowering the stack size guarantee. 10841FatalConditionHandler ::~ FatalConditionHandler () = default; 10842 10843void FatalConditionHandler:: engage_platform () { 10844// Register as first handler in current chain 10845exceptionHandlerHandle = AddVectoredExceptionHandler ( 1 , handleVectoredException); 10846if (!exceptionHandlerHandle) { 10847CATCH_RUNTIME_ERROR ( "Could not register vectored exception handler" ); 10848} 10849} 10850 10851void FatalConditionHandler:: disengage_platform () { 10852if (! RemoveVectoredExceptionHandler (exceptionHandlerHandle)) { 10853CATCH_RUNTIME_ERROR ( "Could not unregister vectored exception handler" ); 10854} 10855exceptionHandlerHandle = nullptr ; 10856} 10857 10858} // end namespace Catch 10859 10860#endif // CATCH_CONFIG_WINDOWS_SEH 10861 10862#if defined( CATCH_CONFIG_POSIX_SIGNALS ) 10863 10864#include <signal.h> 10865 10866namespace Catch { 10867 10868struct SignalDefs { 10869int id ; 10870const char * name ; 10871}; 10872 10873static SignalDefs signalDefs[] = { 10874{ SIGINT , "SIGINT - Terminal interrupt signal" }, 10875{ SIGILL , "SIGILL - Illegal instruction signal" }, 10876{ SIGFPE , "SIGFPE - Floating point error signal" }, 10877{ SIGSEGV , "SIGSEGV - Segmentation violation signal" }, 10878{ SIGTERM , "SIGTERM - Termination request signal" }, 10879{ SIGABRT , "SIGABRT - Abort (abnormal termination) signal" } 10880}; 10881 10882// Older GCCs trigger -Wmissing-field-initializers for T foo = {} 10883// which is zero initialization, but not explicit. We want to avoid 10884// that. 10885#if defined(__GNUC__) 10886# pragma GCC diagnostic push 10887# pragma GCC diagnostic ignored "-Wmissing-field-initializers" 10888#endif 10889 10890static char * altStackMem = nullptr ; 10891static std :: size_t altStackSize = 0 ; 10892static stack_t oldSigStack{}; 10893static struct sigaction oldSigActions[ sizeof (signalDefs) / sizeof (SignalDefs)]{}; 10894 10895static void restorePreviousSignalHandlers () { 10896// We set signal handlers back to the previous ones. Hopefully 10897// nobody overwrote them in the meantime, and doesn't expect 10898// their signal handlers to live past ours given that they 10899// installed them after ours.. 10900for (std:: size_t i = 0 ; i < sizeof (signalDefs) / sizeof (SignalDefs); ++ i) { 10901sigaction (signalDefs[i]. id , & oldSigActions[i], nullptr ); 10902} 10903// Return the old stack 10904sigaltstack ( & oldSigStack, nullptr ); 10905} 10906 10907static void handleSignal ( int sig ) { 10908char const * name = "<unknown signal>" ; 10909for (auto const & def : signalDefs ) { 10910if ( sig == def.id) { 10911name = def. name ; 10912break; 10913} 10914} 10915// We need to restore previous signal handlers and let them do 10916// their thing, so that the users can have the debugger break 10917// when a signal is raised, and so on. 10918restorePreviousSignalHandlers (); 10919reportFatal ( name ); 10920raise ( sig ); 10921} 10922 10923FatalConditionHandler:: FatalConditionHandler () { 10924assert (!altStackMem && "Cannot initialize POSIX signal handler when one already exists" ); 10925if (altStackSize == 0 ) { 10926altStackSize = std:: max (static_cast < size_t > ( SIGSTKSZ ), minStackSizeForErrors); 10927} 10928altStackMem = new char[altStackSize](); 10929} 10930 10931FatalConditionHandler::~ FatalConditionHandler () { 10932delete[] altStackMem; 10933// We signal that another instance can be constructed by zeroing 10934// out the pointer. 10935altStackMem = nullptr ; 10936} 10937 10938void FatalConditionHandler:: engage_platform () { 10939stack_t sigStack; 10940sigStack. ss_sp = altStackMem; 10941sigStack. ss_size = altStackSize; 10942sigStack. ss_flags = 0 ; 10943sigaltstack( & sigStack, & oldSigStack); 10944struct sigaction sa = { }; 10945 10946sa. sa_handler = handleSignal; 10947sa. sa_flags = SA_ONSTACK ; 10948for (std:: size_t i = 0 ; i < sizeof (signalDefs)/ sizeof (SignalDefs); ++ i) { 10949sigaction (signalDefs[i]. id , & sa, & oldSigActions[i]); 10950} 10951} 10952 10953#if defined(__GNUC__) 10954# pragma GCC diagnostic pop 10955#endif 10956 10957void FatalConditionHandler:: disengage_platform () { 10958restorePreviousSignalHandlers (); 10959} 10960 10961} // end namespace Catch 10962 10963#endif // CATCH_CONFIG_POSIX_SIGNALS 10964// end catch_fatal_condition.cpp 10965// start catch_generators.cpp 10966 10967#include <limits> 10968#include <set> 10969 10970namespace Catch { 10971 10972IGeneratorTracker ::~ IGeneratorTracker () {} 10973 10974const char * GeneratorException:: what () const noexcept { 10975return m_msg; 10976} 10977 10978namespace Generators { 10979 10980GeneratorUntypedBase ::~ GeneratorUntypedBase () {} 10981 10982auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const & lineInfo ) -> IGeneratorTracker & { 10983return getResultCapture (). acquireGeneratorTracker ( generatorName, lineInfo ); 10984} 10985 10986} // namespace Generators 10987} // namespace Catch 10988// end catch_generators.cpp 10989// start catch_interfaces_capture.cpp 10990 10991namespace Catch { 10992IResultCapture ::~ IResultCapture () = default; 10993} 10994// end catch_interfaces_capture.cpp 10995// start catch_interfaces_config.cpp 10996 10997namespace Catch { 10998IConfig ::~ IConfig () = default; 10999} 11000// end catch_interfaces_config.cpp 11001// start catch_interfaces_exception.cpp 11002 11003namespace Catch { 11004IExceptionTranslator ::~ IExceptionTranslator () = default; 11005IExceptionTranslatorRegistry ::~ IExceptionTranslatorRegistry () = default; 11006} 11007// end catch_interfaces_exception.cpp 11008// start catch_interfaces_registry_hub.cpp 11009 11010namespace Catch { 11011IRegistryHub ::~ IRegistryHub () = default; 11012IMutableRegistryHub ::~ IMutableRegistryHub () = default; 11013} 11014// end catch_interfaces_registry_hub.cpp 11015// start catch_interfaces_reporter.cpp 11016 11017// start catch_reporter_listening.h 11018 11019namespace Catch { 11020 11021class ListeningReporter : public IStreamingReporter { 11022using Reporters = std::vector < IStreamingReporterPtr > ; 11023Reporters m_listeners; 11024IStreamingReporterPtr m_reporter = nullptr ; 11025ReporterPreferences m_preferences; 11026 11027public : 11028ListeningReporter (); 11029 11030void addListener ( IStreamingReporterPtr && listener ); 11031void addReporter ( IStreamingReporterPtr && reporter ); 11032 11033public : // IStreamingReporter 11034 11035ReporterPreferences getPreferences () const override; 11036 11037void noMatchingTestCases ( std ::string const & spec ) override; 11038 11039void reportInvalidArguments ( std ::string const & arg) override; 11040 11041static std ::set < Verbosity > getSupportedVerbosities (); 11042 11043#if defined( CATCH_CONFIG_ENABLE_BENCHMARKING ) 11044void benchmarkPreparing ( std ::string const & name) override; 11045void benchmarkStarting ( BenchmarkInfo const & benchmarkInfo ) override; 11046void benchmarkEnded ( BenchmarkStats <> const & benchmarkStats ) override; 11047void benchmarkFailed ( std ::string const & ) override; 11048#endif // CATCH_CONFIG_ENABLE_BENCHMARKING 11049 11050void testRunStarting ( TestRunInfo const & testRunInfo ) override; 11051void testGroupStarting ( GroupInfo const & groupInfo ) override; 11052void testCaseStarting ( TestCaseInfo const & testInfo ) override; 11053void sectionStarting ( SectionInfo const & sectionInfo ) override; 11054void assertionStarting ( AssertionInfo const & assertionInfo ) override; 11055 11056// The return value indicates if the messages buffer should be cleared: 11057bool assertionEnded ( AssertionStats const & assertionStats ) override; 11058void sectionEnded ( SectionStats const & sectionStats ) override; 11059void testCaseEnded ( TestCaseStats const & testCaseStats ) override; 11060void testGroupEnded ( TestGroupStats const & testGroupStats ) override; 11061void testRunEnded ( TestRunStats const & testRunStats ) override; 11062 11063void skipTest ( TestCaseInfo const & testInfo ) override; 11064bool isMulti () const override ; 11065 11066}; 11067 11068} // end namespace Catch 11069 11070// end catch_reporter_listening.h 11071namespace Catch { 11072 11073ReporterConfig ::ReporterConfig( IConfigPtr const & _fullConfig ) 11074: m_stream ( & _fullConfig -> stream () ), m_fullConfig ( _fullConfig ) {} 11075 11076ReporterConfig ::ReporterConfig( IConfigPtr const & _fullConfig, std::ostream & _stream ) 11077: m_stream ( & _stream ), m_fullConfig ( _fullConfig ) {} 11078 11079std ::ostream & ReporterConfig:: stream () const { return * m_stream; } 11080IConfigPtr ReporterConfig:: fullConfig () const { return m_fullConfig; } 11081 11082TestRunInfo ::TestRunInfo( std :: string const & _name ) : name( _name ) {} 11083 11084GroupInfo ::GroupInfo( std :: string const & _name, 11085std:: size_t _groupIndex, 11086std:: size_t _groupsCount ) 11087: name ( _name ), 11088groupIndex ( _groupIndex ), 11089groupsCounts ( _groupsCount ) 11090{} 11091 11092AssertionStats ::AssertionStats( AssertionResult const & _assertionResult, 11093std::vector < MessageInfo > const & _infoMessages, 11094Totals const & _totals ) 11095: assertionResult ( _assertionResult ), 11096infoMessages ( _infoMessages ), 11097totals ( _totals ) 11098{ 11099assertionResult. m_resultData . lazyExpression . m_transientExpression = _assertionResult. m_resultData . lazyExpression . m_transientExpression ; 11100 11101if ( assertionResult. hasMessage () ) { 11102// Copy message into messages list. 11103// !TBD This should have been done earlier, somewhere 11104MessageBuilder builder ( assertionResult . getTestMacroName (), assertionResult . getSourceInfo (), assertionResult . getResultType () ); 11105builder << assertionResult. getMessage (); 11106builder. m_info . message = builder. m_stream . str (); 11107 11108infoMessages. push_back ( builder. m_info ); 11109} 11110} 11111 11112AssertionStats ::~ AssertionStats () = default; 11113 11114SectionStats ::SectionStats( SectionInfo const & _sectionInfo, 11115Counts const & _assertions, 11116double _durationInSeconds, 11117bool _missingAssertions ) 11118: sectionInfo ( _sectionInfo ), 11119assertions ( _assertions ), 11120durationInSeconds ( _durationInSeconds ), 11121missingAssertions ( _missingAssertions ) 11122{} 11123 11124SectionStats ::~ SectionStats () = default; 11125 11126TestCaseStats ::TestCaseStats( TestCaseInfo const & _testInfo, 11127Totals const & _totals, 11128std:: string const & _stdOut, 11129std:: string const & _stdErr, 11130bool _aborting ) 11131: testInfo ( _testInfo ), 11132totals ( _totals ), 11133stdOut ( _stdOut ), 11134stdErr ( _stdErr ), 11135aborting ( _aborting ) 11136{} 11137 11138TestCaseStats ::~ TestCaseStats () = default; 11139 11140TestGroupStats ::TestGroupStats( GroupInfo const & _groupInfo, 11141Totals const & _totals, 11142bool _aborting ) 11143: groupInfo ( _groupInfo ), 11144totals ( _totals ), 11145aborting ( _aborting ) 11146{} 11147 11148TestGroupStats ::TestGroupStats( GroupInfo const & _groupInfo ) 11149: groupInfo ( _groupInfo ), 11150aborting ( false ) 11151{} 11152 11153TestGroupStats ::~ TestGroupStats () = default; 11154 11155TestRunStats ::TestRunStats( TestRunInfo const & _runInfo, 11156Totals const & _totals, 11157bool _aborting ) 11158: runInfo ( _runInfo ), 11159totals ( _totals ), 11160aborting ( _aborting ) 11161{} 11162 11163TestRunStats ::~ TestRunStats () = default; 11164 11165void IStreamingReporter:: fatalErrorEncountered ( StringRef ) {} 11166bool IStreamingReporter:: isMulti () const { return false; } 11167 11168IReporterFactory ::~ IReporterFactory () = default; 11169IReporterRegistry ::~ IReporterRegistry () = default; 11170 11171} // end namespace Catch 11172// end catch_interfaces_reporter.cpp 11173// start catch_interfaces_runner.cpp 11174 11175namespace Catch { 11176IRunner ::~ IRunner () = default; 11177} 11178// end catch_interfaces_runner.cpp 11179// start catch_interfaces_testcase.cpp 11180 11181namespace Catch { 11182ITestInvoker ::~ ITestInvoker () = default; 11183ITestCaseRegistry ::~ ITestCaseRegistry () = default; 11184} 11185// end catch_interfaces_testcase.cpp 11186// start catch_leak_detector.cpp 11187 11188#ifdef CATCH_CONFIG_WINDOWS_CRTDBG 11189#include <crtdbg.h> 11190 11191namespace Catch { 11192 11193LeakDetector :: LeakDetector () { 11194int flag = _CrtSetDbgFlag (_CRTDBG_REPORT_FLAG); 11195flag |= _CRTDBG_LEAK_CHECK_DF; 11196flag |= _CRTDBG_ALLOC_MEM_DF; 11197_CrtSetDbgFlag (flag); 11198_CrtSetReportMode (_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); 11199_CrtSetReportFile (_CRT_WARN, _CRTDBG_FILE_STDERR); 11200// Change this to leaking allocation's number to break there 11201_CrtSetBreakAlloc ( -1 ); 11202} 11203} 11204 11205#else 11206 11207Catch :: LeakDetector :: LeakDetector () {} 11208 11209#endif 11210 11211Catch :: LeakDetector ::~ LeakDetector () { 11212Catch :: cleanUp (); 11213} 11214// end catch_leak_detector.cpp 11215// start catch_list.cpp 11216 11217// start catch_list.h 11218 11219#include <set> 11220 11221namespace Catch { 11222 11223std :: size_t listTests ( Config const & config ); 11224 11225std :: size_t listTestsNamesOnly ( Config const & config ); 11226 11227struct TagInfo { 11228void add ( std ::string const & spelling ); 11229std :: string all () const ; 11230 11231std :: set < std ::string > spellings; 11232std :: size_t count = 0 ; 11233}; 11234 11235std :: size_t listTags ( Config const & config ); 11236 11237std :: size_t listReporters (); 11238 11239Option < std:: size_t > list ( std::shared_ptr < Config > const & config ); 11240 11241} // end namespace Catch 11242 11243// end catch_list.h 11244// start catch_text.h 11245 11246namespace Catch { 11247using namespace clara ::TextFlow; 11248} 11249 11250// end catch_text.h 11251#include <limits> 11252#include <algorithm> 11253#include <iomanip> 11254 11255namespace Catch { 11256 11257std :: size_t listTests ( Config const & config ) { 11258TestSpec const & testSpec = config. testSpec (); 11259if ( config. hasTestFilters () ) 11260Catch :: cout () << "Matching test cases:\n" ; 11261else { 11262Catch :: cout () << "All available test cases:\n" ; 11263} 11264 11265auto matchedTestCases = filterTests ( getAllTestCasesSorted ( config ), testSpec , config ); 11266for ( auto const & testCaseInfo : matchedTestCases ) { 11267Colour::Code colour = testCaseInfo. isHidden () 11268? Colour::SecondaryText 11269: Colour::None; 11270Colour colourGuard ( colour ); 11271 11272Catch:: cout () << Column ( testCaseInfo. name ). initialIndent ( 2 ). indent ( 4 ) << "\n" ; 11273if ( config. verbosity () >= Verbosity::High ) { 11274Catch :: cout () << Column ( Catch::Detail:: stringify ( testCaseInfo. lineInfo ) ). indent ( 4 ) << std::endl; 11275std :: string description = testCaseInfo. description ; 11276if ( description. empty () ) 11277description = "(NO DESCRIPTION)" ; 11278Catch :: cout () << Column ( description ). indent ( 4 ) << std::endl; 11279} 11280if ( !testCaseInfo. tags . empty () ) 11281Catch :: cout () << Column ( testCaseInfo. tagsAsString () ). indent ( 6 ) << "\n" ; 11282} 11283 11284if ( !config. hasTestFilters () ) 11285Catch :: cout () << pluralise ( matchedTestCases. size (), "test case" ) << '\n' << std::endl; 11286else 11287Catch :: cout () << pluralise ( matchedTestCases. size (), "matching test case" ) << '\n' << std::endl; 11288return matchedTestCases. size (); 11289} 11290 11291std :: size_t listTestsNamesOnly ( Config const & config ) { 11292TestSpec const & testSpec = config. testSpec (); 11293std :: size_t matchedTests = 0 ; 11294std ::vector < TestCase > matchedTestCases = filterTests ( getAllTestCasesSorted ( config ), testSpec, config ); 11295for ( auto const & testCaseInfo : matchedTestCases ) { 11296matchedTests ++ ; 11297if ( startsWith ( testCaseInfo. name , '#' ) ) 11298Catch:: cout () << '"' << testCaseInfo. name << '"' ; 11299else 11300Catch:: cout () << testCaseInfo. name ; 11301if ( config. verbosity () >= Verbosity::High ) 11302Catch:: cout () << "\t@" << testCaseInfo. lineInfo ; 11303Catch:: cout () << std::endl; 11304} 11305return matchedTests; 11306} 11307 11308void TagInfo:: add ( std::string const & spelling ) { 11309++ count; 11310spellings. insert ( spelling ); 11311} 11312 11313std::string TagInfo:: all () const { 11314size_t size = 0 ; 11315for (auto const & spelling : spellings) { 11316// Add 2 for the brackes 11317size += spelling. size () + 2 ; 11318} 11319 11320std::string out; out. reserve (size); 11321for (auto const & spelling : spellings) { 11322out += '[' ; 11323out += spelling; 11324out += ']' ; 11325} 11326return out; 11327} 11328 11329std:: size_t listTags ( Config const & config ) { 11330TestSpec const & testSpec = config. testSpec (); 11331if ( config. hasTestFilters () ) 11332Catch :: cout () << "Tags for matching test cases:\n" ; 11333else { 11334Catch :: cout () << "All available tags:\n" ; 11335} 11336 11337std ::map < std::string, TagInfo > tagCounts; 11338 11339std ::vector < TestCase > matchedTestCases = filterTests ( getAllTestCasesSorted ( config ), testSpec, config ); 11340for ( auto const & testCase : matchedTestCases ) { 11341for ( auto const & tagName : testCase. getTestCaseInfo ().tags ) { 11342std::string lcaseTagName = toLower ( tagName ); 11343auto countIt = tagCounts. find ( lcaseTagName ); 11344if ( countIt == tagCounts. end () ) 11345countIt = tagCounts. insert ( std:: make_pair ( lcaseTagName, TagInfo () ) ). first ; 11346countIt -> second . add ( tagName ); 11347} 11348} 11349 11350for ( auto const & tagCount : tagCounts ) { 11351ReusableStringStream rss; 11352rss << " " << std:: setw ( 2 ) << tagCount. second . count << " " ; 11353auto str = rss. str (); 11354auto wrapper = Column ( tagCount. second . all () ) 11355. initialIndent ( 0 ) 11356. indent ( str. size () ) 11357. width ( CATCH_CONFIG_CONSOLE_WIDTH - 10 ); 11358Catch :: cout () << str << wrapper << '\n' ; 11359} 11360Catch :: cout () << pluralise ( tagCounts. size (), "tag" ) << '\n' << std::endl; 11361return tagCounts. size (); 11362} 11363 11364std :: size_t listReporters () { 11365Catch :: cout () << "Available reporters:\n" ; 11366IReporterRegistry :: FactoryMap const & factories = getRegistryHub (). getReporterRegistry (). getFactories (); 11367std :: size_t maxNameLen = 0 ; 11368for ( auto const & factoryKvp : factories ) 11369maxNameLen = (std::max)( maxNameLen, factoryKvp. first . size () ); 11370 11371for ( auto const & factoryKvp : factories ) { 11372Catch:: cout () 11373<< Column ( factoryKvp. first + ":" ) 11374. indent ( 2 ) 11375. width ( 5 + maxNameLen ) 11376+ Column ( factoryKvp. second -> getDescription () ) 11377. initialIndent ( 0 ) 11378. indent ( 2 ) 11379. width ( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen - 8 ) 11380<< "\n" ; 11381} 11382Catch:: cout () << std::endl; 11383return factories. size (); 11384} 11385 11386Option < std:: size_t > list ( std::shared_ptr < Config > const & config ) { 11387Option < std:: size_t > listedCount; 11388getCurrentMutableContext (). setConfig ( config ); 11389if ( config -> listTests () ) 11390listedCount = listedCount. valueOr ( 0 ) + listTests ( * config ); 11391if ( config -> listTestNamesOnly () ) 11392listedCount = listedCount. valueOr ( 0 ) + listTestsNamesOnly ( * config ); 11393if ( config -> listTags () ) 11394listedCount = listedCount. valueOr ( 0 ) + listTags ( * config ); 11395if ( config -> listReporters () ) 11396listedCount = listedCount. valueOr ( 0 ) + listReporters (); 11397return listedCount; 11398} 11399 11400} // end namespace Catch 11401// end catch_list.cpp 11402// start catch_matchers.cpp 11403 11404namespace Catch { 11405namespace Matchers { 11406namespace Impl { 11407 11408std :: string MatcherUntypedBase :: toString () const { 11409if( m_cachedToString . empty () ) 11410m_cachedToString = describe (); 11411return m_cachedToString ; 11412} 11413 11414MatcherUntypedBase ::~ MatcherUntypedBase () = default ; 11415 11416} // namespace Impl 11417} // namespace Matchers 11418 11419using namespace Matchers ; 11420using Matchers :: Impl :: MatcherBase ; 11421 11422} // namespace Catch 11423// end catch_matchers.cpp 11424// start catch_matchers_exception.cpp 11425 11426namespace Catch { 11427namespace Matchers { 11428namespace Exception { 11429 11430bool ExceptionMessageMatcher :: match ( std :: exception const & ex ) const { 11431return ex . what () == m_message ; 11432} 11433 11434std :: string ExceptionMessageMatcher :: describe () const { 11435return "exception message matches \"" + m_message + "\"" ; 11436} 11437 11438} 11439Exception :: ExceptionMessageMatcher Message ( std :: string const & message ) { 11440return Exception :: ExceptionMessageMatcher ( message ); 11441} 11442 11443// namespace Exception 11444} // namespace Matchers 11445} // namespace Catch 11446// end catch_matchers_exception.cpp 11447// start catch_matchers_floating.cpp 11448 11449// start catch_polyfills.hpp 11450 11451namespace Catch { 11452bool isnan ( float f ); 11453bool isnan ( double d ); 11454} 11455 11456// end catch_polyfills.hpp 11457// start catch_to_string.hpp 11458 11459#include <string> 11460 11461namespace Catch { 11462template < typename T > 11463std :: string to_string ( T const & t ) { 11464#if defined( CATCH_CONFIG_CPP11_TO_STRING ) 11465return std :: to_string ( t ); 11466#else 11467ReusableStringStream rss ; 11468rss << t ; 11469return rss . str (); 11470#endif 11471} 11472} // end namespace Catch 11473 11474// end catch_to_string.hpp 11475#include <algorithm> 11476#include <cmath> 11477#include <cstdlib> 11478#include <cstdint> 11479#include <cstring> 11480#include <sstream> 11481#include <type_traits> 11482#include <iomanip> 11483#include <limits> 11484 11485namespace Catch { 11486namespace { 11487 11488int32_t convert ( float f ) { 11489static_assert (sizeof( float ) == sizeof( int32_t ), "Important ULP matcher assumption violated" ); 11490int32_t i ; 11491std :: memcpy ( & i , & f , sizeof( f )); 11492return i ; 11493} 11494 11495int64_t convert ( double d ) { 11496static_assert (sizeof( double ) == sizeof( int64_t ), "Important ULP matcher assumption violated" ); 11497int64_t i ; 11498std :: memcpy ( & i , & d , sizeof( d )); 11499return i ; 11500} 11501 11502template < typename FP > 11503bool almostEqualUlps ( FP lhs , FP rhs , uint64_t maxUlpDiff ) { 11504// Comparison with NaN should always be false. 11505// This way we can rule it out before getting into the ugly details 11506if ( Catch :: isnan ( lhs ) || Catch :: isnan ( rhs )) { 11507return false; 11508} 11509 11510auto lc = convert ( lhs ); 11511auto rc = convert ( rhs ); 11512 11513if (( lc < 0 ) != ( rc < 0 )) { 11514// Potentially we can have +0 and -0 11515return lhs == rhs ; 11516} 11517 11518// static cast as a workaround for IBM XLC 11519auto ulpDiff = std :: abs ( static_cast < FP > ( lc - rc )); 11520return static_cast < uint64_t > ( ulpDiff ) <= maxUlpDiff ; 11521} 11522 11523#if defined( CATCH_CONFIG_GLOBAL_NEXTAFTER ) 11524 11525float nextafter ( float x , float y ) { 11526return :: nextafterf ( x , y ); 11527} 11528 11529double nextafter ( double x , double y ) { 11530return :: nextafter ( x , y ); 11531} 11532 11533#endif // ^^^ CATCH_CONFIG_GLOBAL_NEXTAFTER ^^^ 11534 11535template < typename FP > 11536FP step ( FP start , FP direction , uint64_t steps ) { 11537for ( uint64_t i = 0 ; i < steps ; ++ i ) { 11538#if defined( CATCH_CONFIG_GLOBAL_NEXTAFTER ) 11539start = Catch :: nextafter ( start , direction ); 11540#else 11541start = std :: nextafter ( start , direction ); 11542#endif 11543} 11544return start ; 11545} 11546 11547// Performs equivalent check of std::fabs(lhs - rhs) <= margin 11548// But without the subtraction to allow for INFINITY in comparison 11549bool marginComparison ( double lhs , double rhs , double margin ) { 11550return ( lhs + margin >= rhs ) && ( rhs + margin >= lhs ); 11551} 11552 11553template < typename FloatingPoint > 11554void write ( std :: ostream & out , FloatingPoint num ) { 11555out << std :: scientific 11556<< std :: setprecision ( std :: numeric_limits < FloatingPoint > :: max_digits10 - 1 ) 11557<< num ; 11558} 11559 11560} // end anonymous namespace 11561 11562namespace Matchers { 11563namespace Floating { 11564 11565enum class FloatingPointKind : uint8_t { 11566Float , 11567Double 11568}; 11569 11570WithinAbsMatcher :: WithinAbsMatcher ( double target , double margin ) 11571: m_target { target }, m_margin { margin } { 11572CATCH_ENFORCE ( margin >= 0 , "Invalid margin: " << margin << '.' 11573<< " Margin has to be non-negative." ); 11574} 11575 11576// Performs equivalent check of std::fabs(lhs - rhs) <= margin 11577// But without the subtraction to allow for INFINITY in comparison 11578bool WithinAbsMatcher :: match ( double const & matchee ) const { 11579return ( matchee + m_margin >= m_target ) && ( m_target + m_margin >= matchee ); 11580} 11581 11582std :: string WithinAbsMatcher :: describe () const { 11583return "is within " + :: Catch :: Detail :: stringify ( m_margin ) + " of " + :: Catch :: Detail :: stringify ( m_target ); 11584} 11585 11586WithinUlpsMatcher :: WithinUlpsMatcher ( double target , uint64_t ulps , FloatingPointKind baseType ) 11587: m_target { target }, m_ulps { ulps }, m_type { baseType } { 11588CATCH_ENFORCE ( m_type == FloatingPointKind :: Double 11589|| m_ulps < ( std :: numeric_limits < uint32_t > :: max )(), 11590"Provided ULP is impossibly large for a float comparison." ); 11591} 11592 11593#if defined( __clang__ ) 11594#pragma clang diagnostic push 11595// Clang <3.5 reports on the default branch in the switch below 11596#pragma clang diagnostic ignored "-Wunreachable-code" 11597#endif 11598 11599bool WithinUlpsMatcher :: match ( double const & matchee ) const { 11600switch ( m_type ) { 11601case FloatingPointKind :: Float : 11602return almostEqualUlps < float > ( static_cast < float > ( matchee ), static_cast < float > ( m_target ), m_ulps ); 11603case FloatingPointKind :: Double : 11604return almostEqualUlps < double > ( matchee , m_target , m_ulps ); 11605default: 11606CATCH_INTERNAL_ERROR ( "Unknown FloatingPointKind value" ); 11607} 11608} 11609 11610#if defined( __clang__ ) 11611#pragma clang diagnostic pop 11612#endif 11613 11614std :: string WithinUlpsMatcher :: describe () const { 11615std :: stringstream ret ; 11616 11617ret << "is within " << m_ulps << " ULPs of " ; 11618 11619if ( m_type == FloatingPointKind :: Float ) { 11620write ( ret , static_cast < float > ( m_target )); 11621ret << 'f' ; 11622} else { 11623write ( ret , m_target ); 11624} 11625 11626ret << " ([" ; 11627if ( m_type == FloatingPointKind :: Double ) { 11628write ( ret , step ( m_target , static_cast < double > ( - INFINITY ), m_ulps )); 11629ret << ", " ; 11630write ( ret , step ( m_target , static_cast < double > ( INFINITY ), m_ulps )); 11631} else { 11632// We have to cast INFINITY to float because of MinGW, see #1782 11633write ( ret , step ( static_cast < float > ( m_target ), static_cast < float > ( - INFINITY ), m_ulps )); 11634ret << ", " ; 11635write ( ret , step ( static_cast < float > ( m_target ), static_cast < float > ( INFINITY ), m_ulps )); 11636} 11637ret << "])" ; 11638 11639return ret . str (); 11640} 11641 11642WithinRelMatcher :: WithinRelMatcher ( double target , double epsilon ): 11643m_target ( target ), 11644m_epsilon ( epsilon ){ 11645CATCH_ENFORCE ( m_epsilon >= 0. , "Relative comparison with epsilon < 0 does not make sense." ); 11646CATCH_ENFORCE ( m_epsilon < 1. , "Relative comparison with epsilon >= 1 does not make sense." ); 11647} 11648 11649bool WithinRelMatcher :: match ( double const & matchee ) const { 11650const auto relMargin = m_epsilon * (std::max)(std:: fabs (matchee), std:: fabs (m_target)); 11651return marginComparison (matchee, m_target, 11652std:: isinf (relMargin)? 0 : relMargin); 11653} 11654 11655std :: string WithinRelMatcher:: describe () const { 11656Catch :: ReusableStringStream sstr; 11657sstr << "and " << m_target << " are within " << m_epsilon * 100. << "% of each other" ; 11658return sstr. str (); 11659} 11660 11661} // namespace Floating 11662 11663Floating :: WithinUlpsMatcher WithinULP ( double target, uint64_t maxUlpDiff) { 11664return Floating:: WithinUlpsMatcher (target, maxUlpDiff, Floating::FloatingPointKind::Double); 11665} 11666 11667Floating :: WithinUlpsMatcher WithinULP ( float target, uint64_t maxUlpDiff) { 11668return Floating:: WithinUlpsMatcher (target, maxUlpDiff, Floating::FloatingPointKind::Float); 11669} 11670 11671Floating :: WithinAbsMatcher WithinAbs ( double target, double margin) { 11672return Floating:: WithinAbsMatcher (target, margin); 11673} 11674 11675Floating :: WithinRelMatcher WithinRel ( double target, double eps) { 11676return Floating:: WithinRelMatcher (target, eps); 11677} 11678 11679Floating :: WithinRelMatcher WithinRel ( double target) { 11680return Floating:: WithinRelMatcher (target, std::numeric_limits < double > :: epsilon () * 100 ); 11681} 11682 11683Floating :: WithinRelMatcher WithinRel ( float target, float eps) { 11684return Floating:: WithinRelMatcher (target, eps); 11685} 11686 11687Floating :: WithinRelMatcher WithinRel ( float target) { 11688return Floating:: WithinRelMatcher (target, std::numeric_limits < float > :: epsilon () * 100 ); 11689} 11690 11691} // namespace Matchers 11692} // namespace Catch 11693// end catch_matchers_floating.cpp 11694// start catch_matchers_generic.cpp 11695 11696std :: string Catch:: Matchers :: Generic :: Detail :: finalizeDescription ( const std ::string & desc) { 11697if (desc. empty ()) { 11698return "matches undescribed predicate" ; 11699} else { 11700return "matches predicate: \"" + desc + '"' ; 11701} 11702} 11703// end catch_matchers_generic.cpp 11704// start catch_matchers_string.cpp 11705 11706#include <regex> 11707 11708namespace Catch { 11709namespace Matchers { 11710 11711namespace StdString { 11712 11713CasedString ::CasedString( std :: string const & str, CaseSensitive:: Choice caseSensitivity ) 11714: m_caseSensitivity ( caseSensitivity ), 11715m_str ( adjustString ( str ) ) 11716{} 11717std :: string CasedString::adjustString( std :: string const & str ) const { 11718return m_caseSensitivity == CaseSensitive::No 11719? toLower ( str ) 11720: str; 11721} 11722std :: string CasedString:: caseSensitivitySuffix () const { 11723return m_caseSensitivity == CaseSensitive::No 11724? " (case insensitive)" 11725: std:: string (); 11726} 11727 11728StringMatcherBase ::StringMatcherBase( std :: string const & operation, CasedString const & comparator ) 11729: m_comparator ( comparator ), 11730m_operation ( operation ) { 11731} 11732 11733std :: string StringMatcherBase:: describe () const { 11734std :: string description; 11735description. reserve ( 5 + m_operation. size () + m_comparator. m_str . size () + 11736m_comparator. caseSensitivitySuffix (). size ()); 11737description += m_operation; 11738description += ": \"" ; 11739description += m_comparator. m_str ; 11740description += "\"" ; 11741description += m_comparator. caseSensitivitySuffix (); 11742return description; 11743} 11744 11745EqualsMatcher ::EqualsMatcher( CasedString const & comparator ) : StringMatcherBase ( "equals" , comparator ) {} 11746 11747bool EqualsMatcher:: match ( std ::string const & source ) const { 11748return m_comparator. adjustString ( source ) == m_comparator. m_str ; 11749} 11750 11751ContainsMatcher ::ContainsMatcher( CasedString const & comparator ) : StringMatcherBase ( "contains" , comparator ) {} 11752 11753bool ContainsMatcher:: match ( std ::string const & source ) const { 11754return contains ( m_comparator. adjustString ( source ), m_comparator. m_str ); 11755} 11756 11757StartsWithMatcher ::StartsWithMatcher( CasedString const & comparator ) : StringMatcherBase ( "starts with" , comparator ) {} 11758 11759bool StartsWithMatcher:: match ( std ::string const & source ) const { 11760return startsWith ( m_comparator. adjustString ( source ), m_comparator. m_str ); 11761} 11762 11763EndsWithMatcher ::EndsWithMatcher( CasedString const & comparator ) : StringMatcherBase ( "ends with" , comparator ) {} 11764 11765bool EndsWithMatcher:: match ( std ::string const & source ) const { 11766return endsWith ( m_comparator. adjustString ( source ), m_comparator. m_str ); 11767} 11768 11769RegexMatcher ::RegexMatcher( std :: string regex, CaseSensitive:: Choice caseSensitivity): m_regex( std :: move ( regex )), m_caseSensitivity (caseSensitivity) {} 11770 11771bool RegexMatcher:: match ( std ::string const & matchee) const { 11772auto flags = std::regex::ECMAScript; // ECMAScript is the default syntax option anyway 11773if (m_caseSensitivity == CaseSensitive::Choice::No) { 11774flags |= std:: regex ::icase; 11775} 11776auto reg = std:: regex ( m_regex , flags ); 11777return std:: regex_match (matchee, reg); 11778} 11779 11780std :: string RegexMatcher:: describe () const { 11781return "matches " + :: Catch :: Detail :: stringify (m_regex) + ((m_caseSensitivity == CaseSensitive:: Choice ::Yes)? " case sensitively" : " case insensitively" ); 11782} 11783 11784} // namespace StdString 11785 11786StdString :: EqualsMatcher Equals( std :: string const & str, CaseSensitive:: Choice caseSensitivity ) { 11787return StdString::EqualsMatcher( StdString :: CasedString ( str , caseSensitivity ) ); 11788} 11789StdString:: ContainsMatcher Contains( std :: string const & str, CaseSensitive:: Choice caseSensitivity ) { 11790return StdString::ContainsMatcher( StdString :: CasedString ( str , caseSensitivity ) ); 11791} 11792StdString:: EndsWithMatcher EndsWith( std :: string const & str, CaseSensitive:: Choice caseSensitivity ) { 11793return StdString::EndsWithMatcher( StdString :: CasedString ( str , caseSensitivity ) ); 11794} 11795StdString:: StartsWithMatcher StartsWith( std :: string const & str, CaseSensitive:: Choice caseSensitivity ) { 11796return StdString::StartsWithMatcher( StdString :: CasedString ( str , caseSensitivity ) ); 11797} 11798 11799StdString:: RegexMatcher Matches( std :: string const & regex, CaseSensitive:: Choice caseSensitivity) { 11800return StdString:: RegexMatcher (regex, caseSensitivity); 11801} 11802 11803} // namespace Matchers 11804} // namespace Catch 11805// end catch_matchers_string.cpp 11806// start catch_message.cpp 11807 11808// start catch_uncaught_exceptions.h 11809 11810namespace Catch { 11811bool uncaught_exceptions (); 11812} // end namespace Catch 11813 11814// end catch_uncaught_exceptions.h 11815#include <cassert> 11816#include <stack> 11817 11818namespace Catch { 11819 11820MessageInfo ::MessageInfo( StringRef const & _macroName, 11821SourceLineInfo const & _lineInfo, 11822ResultWas:: OfType _type ) 11823: macroName ( _macroName ), 11824lineInfo ( _lineInfo ), 11825type ( _type ), 11826sequence ( ++ globalCount ) 11827{} 11828 11829bool MessageInfo::operator == ( MessageInfo const & other ) const { 11830return sequence == other. sequence ; 11831} 11832 11833bool MessageInfo::operator < ( MessageInfo const & other ) const { 11834return sequence < other. sequence ; 11835} 11836 11837// This may need protecting if threading support is added 11838unsigned int MessageInfo::globalCount = 0 ; 11839 11840//////////////////////////////////////////////////////////////////////////// 11841 11842Catch :: MessageBuilder ::MessageBuilder( StringRef const & macroName, 11843SourceLineInfo const & lineInfo, 11844ResultWas:: OfType type ) 11845: m_info (macroName, lineInfo, type) {} 11846 11847//////////////////////////////////////////////////////////////////////////// 11848 11849ScopedMessage ::ScopedMessage( MessageBuilder const & builder ) 11850: m_info ( builder. m_info ), m_moved () 11851{ 11852m_info. message = builder. m_stream . str (); 11853getResultCapture (). pushScopedMessage ( m_info ); 11854} 11855 11856ScopedMessage :: ScopedMessage ( ScopedMessage && old ) 11857: m_info ( old. m_info ), m_moved () 11858{ 11859old. m_moved = true; 11860} 11861 11862ScopedMessage ::~ ScopedMessage () { 11863if ( ! uncaught_exceptions () && !m_moved ){ 11864getResultCapture (). popScopedMessage (m_info); 11865} 11866} 11867 11868Capturer ::Capturer( StringRef macroName, SourceLineInfo const & lineInfo, ResultWas:: OfType resultType, StringRef names ) { 11869auto trimmed = [ & ] ( size_t start, size_t end) { 11870while ( names [start] == ',' || isspace( static_cast < unsigned char > (names[start]))) { 11871++ start; 11872} 11873while (names[end] == ',' || isspace (static_cast < unsigned char > (names[end]))) { 11874-- end; 11875} 11876return names. substr (start, end - start + 1 ); 11877}; 11878auto skipq = [ & ] ( size_t start, char quote) { 11879for (auto i = start + 1 ; i < names. size () ; ++ i) { 11880if (names[i] == quote) 11881return i; 11882if (names[i] == '\\' ) 11883++ i; 11884} 11885CATCH_INTERNAL_ERROR ( "CAPTURE parsing encountered unmatched quote" ); 11886}; 11887 11888size_t start = 0 ; 11889std ::stack < char > openings; 11890for ( size_t pos = 0 ; pos < names. size (); ++ pos) { 11891char c = names[pos]; 11892switch (c) { 11893case '[' : 11894case '{' : 11895case '(' : 11896// It is basically impossible to disambiguate between 11897// comparison and start of template args in this context 11898// case '<': 11899openings. push (c); 11900break ; 11901case ']' : 11902case '}' : 11903case ')' : 11904// case '>': 11905openings. pop (); 11906break ; 11907case '"' : 11908case '\'' : 11909pos = skipq (pos, c); 11910break ; 11911case ',' : 11912if (start != pos && openings. empty ()) { 11913m_messages. emplace_back (macroName, lineInfo, resultType); 11914m_messages. back (). message = static_cast < std::string > ( trimmed (start, pos)); 11915m_messages. back (). message += " := " ; 11916start = pos; 11917} 11918} 11919} 11920assert (openings. empty () && "Mismatched openings" ); 11921m_messages. emplace_back (macroName, lineInfo, resultType); 11922m_messages. back (). message = static_cast < std::string > ( trimmed (start, names. size () - 1 )); 11923m_messages. back (). message += " := " ; 11924} 11925Capturer ::~ Capturer () { 11926if ( ! uncaught_exceptions () ){ 11927assert ( m_captured == m_messages. size () ); 11928for ( size_t i = 0 ; i < m_captured; ++ i ) 11929m_resultCapture. popScopedMessage ( m_messages[i] ); 11930} 11931} 11932 11933void Capturer:: captureValue ( size_t index, std ::string const & value ) { 11934assert ( index < m_messages. size () ); 11935m_messages[index]. message += value; 11936m_resultCapture. pushScopedMessage ( m_messages[index] ); 11937m_captured ++ ; 11938} 11939 11940} // end namespace Catch 11941// end catch_message.cpp 11942// start catch_output_redirect.cpp 11943 11944// start catch_output_redirect.h 11945#ifndef TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H 11946#define TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H 11947 11948#include <cstdio> 11949#include <iosfwd> 11950#include <string> 11951 11952namespace Catch { 11953 11954class RedirectedStream { 11955std ::ostream & m_originalStream; 11956std ::ostream & m_redirectionStream; 11957std :: streambuf * m_prevBuf; 11958 11959public : 11960RedirectedStream ( std ::ostream & originalStream, std::ostream & redirectionStream ); 11961~ RedirectedStream (); 11962}; 11963 11964class RedirectedStdOut { 11965ReusableStringStream m_rss; 11966RedirectedStream m_cout; 11967public : 11968RedirectedStdOut (); 11969auto str() const -> std :: string ; 11970}; 11971 11972// StdErr has two constituent streams in C++, std::cerr and std::clog 11973// This means that we need to redirect 2 streams into 1 to keep proper 11974// order of writes 11975class RedirectedStdErr { 11976ReusableStringStream m_rss; 11977RedirectedStream m_cerr; 11978RedirectedStream m_clog; 11979public : 11980RedirectedStdErr (); 11981auto str() const -> std :: string ; 11982}; 11983 11984class RedirectedStreams { 11985public : 11986RedirectedStreams( RedirectedStreams const & ) = delete; 11987RedirectedStreams & operator = ( RedirectedStreams const & ) = delete; 11988RedirectedStreams (RedirectedStreams && ) = delete; 11989RedirectedStreams & operator = (RedirectedStreams && ) = delete; 11990 11991RedirectedStreams ( std ::string & redirectedCout, std::string & redirectedCerr); 11992~ RedirectedStreams (); 11993private : 11994std ::string & m_redirectedCout; 11995std ::string & m_redirectedCerr; 11996RedirectedStdOut m_redirectedStdOut; 11997RedirectedStdErr m_redirectedStdErr; 11998}; 11999 12000#if defined( CATCH_CONFIG_NEW_CAPTURE ) 12001 12002// Windows's implementation of std::tmpfile is terrible (it tries 12003// to create a file inside system folder, thus requiring elevated 12004// privileges for the binary), so we have to use tmpnam(_s) and 12005// create the file ourselves there. 12006class TempFile { 12007public : 12008TempFile( TempFile const & ) = delete; 12009TempFile & operator = ( TempFile const & ) = delete; 12010TempFile (TempFile && ) = delete; 12011TempFile & operator = (TempFile && ) = delete; 12012 12013TempFile (); 12014~ TempFile (); 12015 12016std :: FILE * getFile (); 12017std :: string getContents (); 12018 12019private : 12020std :: FILE * m_file = nullptr ; 12021#if defined(_MSC_VER) 12022char m_buffer[L_tmpnam] = { 0 }; 12023#endif 12024}; 12025 12026class OutputRedirect { 12027public : 12028OutputRedirect( OutputRedirect const & ) = delete; 12029OutputRedirect & operator = ( OutputRedirect const & ) = delete; 12030OutputRedirect (OutputRedirect && ) = delete; 12031OutputRedirect & operator = (OutputRedirect && ) = delete; 12032 12033OutputRedirect ( std ::string & stdout_dest, std::string & stderr_dest); 12034~ OutputRedirect (); 12035 12036private : 12037int m_originalStdout = -1 ; 12038int m_originalStderr = -1 ; 12039TempFile m_stdoutFile; 12040TempFile m_stderrFile; 12041std ::string & m_stdoutDest; 12042std ::string & m_stderrDest; 12043}; 12044 12045#endif 12046 12047} // end namespace Catch 12048 12049#endif // TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H 12050// end catch_output_redirect.h 12051#include <cstdio> 12052#include <cstring> 12053#include <fstream> 12054#include <sstream> 12055#include <stdexcept> 12056 12057#if defined( CATCH_CONFIG_NEW_CAPTURE ) 12058#if defined(_MSC_VER) 12059#include <io.h> //_dup and _dup2 12060#define dup _dup 12061#define dup2 _dup2 12062#define fileno _fileno 12063#else 12064#include <unistd.h> // dup and dup2 12065#endif 12066#endif 12067 12068namespace Catch { 12069 12070RedirectedStream :: RedirectedStream ( std ::ostream & originalStream, std::ostream & redirectionStream ) 12071: m_originalStream ( originalStream ), 12072m_redirectionStream ( redirectionStream ), 12073m_prevBuf ( m_originalStream. rdbuf () ) 12074{ 12075m_originalStream. rdbuf ( m_redirectionStream. rdbuf () ); 12076} 12077 12078RedirectedStream ::~ RedirectedStream () { 12079m_originalStream. rdbuf ( m_prevBuf ); 12080} 12081 12082RedirectedStdOut :: RedirectedStdOut () : m_cout ( Catch :: cout (), m_rss. get () ) {} 12083auto RedirectedStdOut :: str () const -> std ::string { return m_rss. str (); } 12084 12085RedirectedStdErr :: RedirectedStdErr () 12086: m_cerr( Catch :: cerr (), m_rss. get () ), 12087m_clog ( Catch:: clog (), m_rss. get () ) 12088{} 12089auto RedirectedStdErr :: str () const -> std ::string { return m_rss. str (); } 12090 12091RedirectedStreams :: RedirectedStreams ( std ::string & redirectedCout, std::string & redirectedCerr) 12092: m_redirectedCout (redirectedCout), 12093m_redirectedCerr (redirectedCerr) 12094{} 12095 12096RedirectedStreams ::~ RedirectedStreams () { 12097m_redirectedCout += m_redirectedStdOut. str (); 12098m_redirectedCerr += m_redirectedStdErr. str (); 12099} 12100 12101#if defined( CATCH_CONFIG_NEW_CAPTURE ) 12102 12103#if defined(_MSC_VER) 12104TempFile :: TempFile () { 12105if ( tmpnam_s (m_buffer)) { 12106CATCH_RUNTIME_ERROR ( "Could not get a temp filename" ); 12107} 12108if ( fopen_s ( & m_file, m_buffer, "w+" )) { 12109char buffer[ 100 ]; 12110if ( strerror_s (buffer, errno)) { 12111CATCH_RUNTIME_ERROR ( "Could not translate errno to a string" ); 12112} 12113CATCH_RUNTIME_ERROR ( "Could not open the temp file: '" << m_buffer << "' because: " << buffer); 12114} 12115} 12116#else 12117TempFile :: TempFile () { 12118m_file = std:: tmpfile (); 12119if (!m_file) { 12120CATCH_RUNTIME_ERROR ( "Could not create a temp file." ); 12121} 12122} 12123 12124#endif 12125 12126TempFile ::~ TempFile () { 12127// TBD: What to do about errors here? 12128std :: fclose (m_file); 12129// We manually create the file on Windows only, on Linux 12130// it will be autodeleted 12131#if defined(_MSC_VER) 12132std :: remove (m_buffer); 12133#endif 12134} 12135 12136FILE * TempFile:: getFile () { 12137return m_file; 12138} 12139 12140std :: string TempFile:: getContents () { 12141std :: stringstream sstr; 12142char buffer[ 100 ] = {}; 12143std :: rewind (m_file); 12144while (std:: fgets (buffer, sizeof (buffer), m_file)) { 12145sstr << buffer; 12146} 12147return sstr. str (); 12148} 12149 12150OutputRedirect :: OutputRedirect ( std ::string & stdout_dest, std::string & stderr_dest) : 12151m_originalStdout ( dup ( 1 )), 12152m_originalStderr ( dup ( 2 )), 12153m_stdoutDest (stdout_dest), 12154m_stderrDest (stderr_dest) { 12155dup2 ( fileno (m_stdoutFile. getFile ()), 1 ); 12156dup2 ( fileno (m_stderrFile. getFile ()), 2 ); 12157} 12158 12159OutputRedirect ::~ OutputRedirect () { 12160Catch :: cout () << std::flush; 12161fflush (stdout); 12162// Since we support overriding these streams, we flush cerr 12163// even though std::cerr is unbuffered 12164Catch :: cerr () << std::flush; 12165Catch :: clog () << std::flush; 12166fflush (stderr); 12167 12168dup2 (m_originalStdout, 1 ); 12169dup2 (m_originalStderr, 2 ); 12170 12171m_stdoutDest += m_stdoutFile. getContents (); 12172m_stderrDest += m_stderrFile. getContents (); 12173} 12174 12175#endif // CATCH_CONFIG_NEW_CAPTURE 12176 12177} // namespace Catch 12178 12179#if defined( CATCH_CONFIG_NEW_CAPTURE ) 12180#if defined(_MSC_VER) 12181#undef dup 12182#undef dup2 12183#undef fileno 12184#endif 12185#endif 12186// end catch_output_redirect.cpp 12187// start catch_polyfills.cpp 12188 12189#include <cmath> 12190 12191namespace Catch { 12192 12193#if !defined( CATCH_CONFIG_POLYFILL_ISNAN ) 12194bool isnan ( float f) { 12195return std:: isnan (f); 12196} 12197bool isnan ( double d) { 12198return std:: isnan (d); 12199} 12200#else 12201// For now we only use this for embarcadero 12202bool isnan ( float f) { 12203return std:: _isnan (f); 12204} 12205bool isnan ( double d) { 12206return std:: _isnan (d); 12207} 12208#endif 12209 12210} // end namespace Catch 12211// end catch_polyfills.cpp 12212// start catch_random_number_generator.cpp 12213 12214namespace Catch { 12215 12216namespace { 12217 12218#if defined(_MSC_VER) 12219#pragma warning(push) 12220#pragma warning(disable:4146) // we negate uint32 during the rotate 12221#endif 12222// Safe rotr implementation thanks to John Regehr 12223uint32_t rotate_right ( uint32_t val, uint32_t count) { 12224const uint32_t mask = 31 ; 12225count &= mask; 12226return (val >> count) | (val << ( - count & mask)); 12227} 12228 12229#if defined(_MSC_VER) 12230#pragma warning(pop) 12231#endif 12232 12233} 12234 12235SimplePcg32 ::SimplePcg32( result_type seed_) { 12236seed (seed_); 12237} 12238 12239void SimplePcg32:: seed ( result_type seed_) { 12240m_state = 0 ; 12241( * this)(); 12242m_state += seed_; 12243( * this)(); 12244} 12245 12246void SimplePcg32:: discard ( uint64_t skip) { 12247// We could implement this to run in O(log n) steps, but this 12248// should suffice for our use case. 12249for ( uint64_t s = 0 ; s < skip; ++ s) { 12250static_cast < void > (( * this)()); 12251} 12252} 12253 12254SimplePcg32 :: result_type SimplePcg32:: operator ()() { 12255// prepare the output value 12256const uint32_t xorshifted = static_cast < uint32_t > (((m_state >> 18u ) ^ m_state) >> 27u ); 12257const auto output = rotate_right (xorshifted, m_state >> 59u ); 12258 12259// advance state 12260m_state = m_state * 6364136223846793005ULL + s_inc; 12261 12262return output; 12263} 12264 12265bool operator == (SimplePcg32 const & lhs, SimplePcg32 const & rhs) { 12266return lhs. m_state == rhs. m_state ; 12267} 12268 12269bool operator != (SimplePcg32 const & lhs, SimplePcg32 const & rhs) { 12270return lhs. m_state != rhs. m_state ; 12271} 12272} 12273// end catch_random_number_generator.cpp 12274// start catch_registry_hub.cpp 12275 12276// start catch_test_case_registry_impl.h 12277 12278#include <vector> 12279#include <set> 12280#include <algorithm> 12281#include <ios> 12282 12283namespace Catch { 12284 12285class TestCase; 12286struct IConfig ; 12287 12288std ::vector < TestCase > sortTests ( IConfig const & config, std::vector < TestCase > const & unsortedTestCases ); 12289 12290bool isThrowSafe ( TestCase const & testCase, IConfig const & config ); 12291bool matchTest ( TestCase const & testCase, TestSpec const & testSpec, IConfig const & config ); 12292 12293void enforceNoDuplicateTestCases ( std ::vector < TestCase > const & functions ); 12294 12295std ::vector < TestCase > filterTests ( std::vector < TestCase > const & testCases, TestSpec const & testSpec, IConfig const & config ); 12296std ::vector < TestCase > const & getAllTestCasesSorted ( IConfig const & config ); 12297 12298class TestRegistry : public ITestCaseRegistry { 12299public : 12300virtual ~ TestRegistry () = default; 12301 12302virtual void registerTest ( TestCase const & testCase ); 12303 12304std ::vector < TestCase > const & getAllTests () const override; 12305std ::vector < TestCase > const & getAllTestsSorted ( IConfig const & config ) const override; 12306 12307private : 12308std ::vector < TestCase > m_functions; 12309mutable RunTests::InWhatOrder m_currentSortOrder = RunTests::InDeclarationOrder; 12310mutable std::vector < TestCase > m_sortedFunctions; 12311std :: size_t m_unnamedCount = 0 ; 12312std :: ios_base :: Init m_ostreamInit; // Forces cout/ cerr to be initialised 12313}; 12314 12315/////////////////////////////////////////////////////////////////////////// 12316 12317class TestInvokerAsFunction : public ITestInvoker { 12318void ( * m_testAsFunction)(); 12319public : 12320TestInvokerAsFunction ( void ( * testAsFunction)() ) noexcept; 12321 12322void invoke () const override ; 12323}; 12324 12325std :: string extractClassName ( StringRef const & classOrQualifiedMethodName ); 12326 12327/////////////////////////////////////////////////////////////////////////// 12328 12329} // end namespace Catch 12330 12331// end catch_test_case_registry_impl.h 12332// start catch_reporter_registry.h 12333 12334#include <map> 12335 12336namespace Catch { 12337 12338class ReporterRegistry : public IReporterRegistry { 12339 12340public : 12341 12342~ ReporterRegistry () override; 12343 12344IStreamingReporterPtr create ( std ::string const & name, IConfigPtr const & config ) const override; 12345 12346void registerReporter ( std ::string const & name, IReporterFactoryPtr const & factory ); 12347void registerListener ( IReporterFactoryPtr const & factory ); 12348 12349FactoryMap const & getFactories () const override ; 12350Listeners const & getListeners () const override; 12351 12352private: 12353FactoryMap m_factories; 12354Listeners m_listeners; 12355}; 12356} 12357 12358// end catch_reporter_registry.h 12359// start catch_tag_alias_registry.h 12360 12361// start catch_tag_alias.h 12362 12363#include <string> 12364 12365namespace Catch { 12366 12367struct TagAlias { 12368TagAlias( std :: string const & _tag , SourceLineInfo _lineInfo ); 12369 12370std :: string tag ; 12371SourceLineInfo lineInfo ; 12372}; 12373 12374} // end namespace Catch 12375 12376// end catch_tag_alias.h 12377#include <map> 12378 12379namespace Catch { 12380 12381class TagAliasRegistry : public ITagAliasRegistry { 12382public : 12383~ TagAliasRegistry () override; 12384TagAlias const * find ( std ::string const & alias ) const override; 12385std :: string expandAliases( std :: string const & unexpandedTestSpec ) const override; 12386void add ( std ::string const & alias, std ::string const & tag, SourceLineInfo const & lineInfo ); 12387 12388private : 12389std ::map < std::string, TagAlias > m_registry; 12390}; 12391 12392} // end namespace Catch 12393 12394// end catch_tag_alias_registry.h 12395// start catch_startup_exception_registry.h 12396 12397#include <vector> 12398#include <exception> 12399 12400namespace Catch { 12401 12402class StartupExceptionRegistry { 12403#if !defined( CATCH_CONFIG_DISABLE_EXCEPTIONS ) 12404public : 12405void add( std :: exception_ptr const & exception) noexcept; 12406std ::vector < std::exception_ptr > const & getExceptions () const noexcept; 12407private : 12408std ::vector < std::exception_ptr > m_exceptions; 12409#endif 12410}; 12411 12412} // end namespace Catch 12413 12414// end catch_startup_exception_registry.h 12415// start catch_singletons.hpp 12416 12417namespace Catch { 12418 12419struct ISingleton { 12420virtual ~ ISingleton (); 12421}; 12422 12423void addSingleton ( ISingleton * singleton ); 12424void cleanupSingletons (); 12425 12426template < typename SingletonImplT, typename InterfaceT = SingletonImplT, typename MutableInterfaceT = InterfaceT > 12427class Singleton : SingletonImplT, public ISingleton { 12428 12429static auto getInternal() -> Singleton * { 12430static Singleton * s_instance = nullptr ; 12431if ( !s_instance ) { 12432s_instance = new Singleton; 12433addSingleton ( s_instance ); 12434} 12435return s_instance; 12436} 12437 12438public : 12439static auto get() -> InterfaceT const & { 12440return * getInternal (); 12441} 12442static auto getMutable() -> MutableInterfaceT & { 12443return * getInternal (); 12444} 12445}; 12446 12447} // namespace Catch 12448 12449// end catch_singletons.hpp 12450namespace Catch { 12451 12452namespace { 12453 12454class RegistryHub : public IRegistryHub, public IMutableRegistryHub, 12455private NonCopyable { 12456 12457public: // IRegistryHub 12458RegistryHub () = default; 12459IReporterRegistry const & getReporterRegistry () const override { 12460return m_reporterRegistry; 12461} 12462ITestCaseRegistry const & getTestCaseRegistry () const override { 12463return m_testCaseRegistry; 12464} 12465IExceptionTranslatorRegistry const & getExceptionTranslatorRegistry () const override { 12466return m_exceptionTranslatorRegistry; 12467} 12468ITagAliasRegistry const & getTagAliasRegistry () const override { 12469return m_tagAliasRegistry; 12470} 12471StartupExceptionRegistry const & getStartupExceptionRegistry () const override { 12472return m_exceptionRegistry; 12473} 12474 12475public : // IMutableRegistryHub 12476void registerReporter ( std ::string const & name, IReporterFactoryPtr const & factory ) override { 12477m_reporterRegistry. registerReporter ( name, factory ); 12478} 12479void registerListener ( IReporterFactoryPtr const & factory ) override { 12480m_reporterRegistry. registerListener ( factory ); 12481} 12482void registerTest ( TestCase const & testInfo ) override { 12483m_testCaseRegistry. registerTest ( testInfo ); 12484} 12485void registerTranslator ( const IExceptionTranslator * translator ) override { 12486m_exceptionTranslatorRegistry. registerTranslator ( translator ); 12487} 12488void registerTagAlias ( std ::string const & alias, std ::string const & tag, SourceLineInfo const & lineInfo ) override { 12489m_tagAliasRegistry. add ( alias, tag, lineInfo ); 12490} 12491void registerStartupException () noexcept override { 12492#if !defined( CATCH_CONFIG_DISABLE_EXCEPTIONS ) 12493m_exceptionRegistry. add (std:: current_exception ()); 12494#else 12495CATCH_INTERNAL_ERROR ( "Attempted to register active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!" ); 12496#endif 12497} 12498IMutableEnumValuesRegistry & getMutableEnumValuesRegistry () override { 12499return m_enumValuesRegistry; 12500} 12501 12502private : 12503TestRegistry m_testCaseRegistry; 12504ReporterRegistry m_reporterRegistry; 12505ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; 12506TagAliasRegistry m_tagAliasRegistry; 12507StartupExceptionRegistry m_exceptionRegistry; 12508Detail :: EnumValuesRegistry m_enumValuesRegistry; 12509}; 12510} 12511 12512using RegistryHubSingleton = Singleton < RegistryHub, IRegistryHub, IMutableRegistryHub > ; 12513 12514IRegistryHub const & getRegistryHub () { 12515return RegistryHubSingleton:: get (); 12516} 12517IMutableRegistryHub & getMutableRegistryHub () { 12518return RegistryHubSingleton:: getMutable (); 12519} 12520void cleanUp () { 12521cleanupSingletons (); 12522cleanUpContext (); 12523} 12524std :: string translateActiveException () { 12525return getRegistryHub (). getExceptionTranslatorRegistry (). translateActiveException (); 12526} 12527 12528} // end namespace Catch 12529// end catch_registry_hub.cpp 12530// start catch_reporter_registry.cpp 12531 12532namespace Catch { 12533 12534ReporterRegistry ::~ ReporterRegistry () = default; 12535 12536IStreamingReporterPtr ReporterRegistry:: create ( std ::string const & name, IConfigPtr const & config ) const { 12537auto it = m_factories. find ( name ); 12538if ( it == m_factories. end () ) 12539return nullptr ; 12540return it -> second -> create ( ReporterConfig ( config ) ); 12541} 12542 12543void ReporterRegistry:: registerReporter ( std ::string const & name, IReporterFactoryPtr const & factory ) { 12544m_factories. emplace (name, factory); 12545} 12546void ReporterRegistry:: registerListener ( IReporterFactoryPtr const & factory ) { 12547m_listeners. push_back ( factory ); 12548} 12549 12550IReporterRegistry :: FactoryMap const & ReporterRegistry:: getFactories () const { 12551return m_factories; 12552} 12553IReporterRegistry :: Listeners const & ReporterRegistry:: getListeners () const { 12554return m_listeners; 12555} 12556 12557} 12558// end catch_reporter_registry.cpp 12559// start catch_result_type.cpp 12560 12561namespace Catch { 12562 12563bool isOk ( ResultWas ::OfType resultType ) { 12564return ( resultType & ResultWas::FailureBit ) == 0 ; 12565} 12566bool isJustInfo ( int flags ) { 12567return flags == ResultWas::Info; 12568} 12569 12570ResultDisposition:: Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { 12571return static_cast < ResultDisposition::Flags > ( static_cast < int > ( lhs ) | static_cast < int > ( rhs ) ); 12572} 12573 12574bool shouldContinueOnFailure ( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0 ; } 12575bool shouldSuppressFailure ( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0 ; } 12576 12577} // end namespace Catch 12578// end catch_result_type.cpp 12579// start catch_run_context.cpp 12580 12581#include <cassert> 12582#include <algorithm> 12583#include <sstream> 12584 12585namespace Catch { 12586 12587namespace Generators { 12588struct GeneratorTracker : TestCaseTracking::TrackerBase, IGeneratorTracker { 12589GeneratorBasePtr m_generator; 12590 12591GeneratorTracker( TestCaseTracking :: NameAndLocation const & nameAndLocation, TrackerContext & ctx, ITracker * parent ) 12592: TrackerBase ( nameAndLocation, ctx, parent ) 12593{} 12594~ GeneratorTracker (); 12595 12596static GeneratorTracker & acquire ( TrackerContext & ctx, TestCaseTracking::NameAndLocation const & nameAndLocation ) { 12597std ::shared_ptr < GeneratorTracker > tracker; 12598 12599ITracker & currentTracker = ctx. currentTracker (); 12600// Under specific circumstances, the generator we want 12601// to acquire is also the current tracker. If this is 12602// the case, we have to avoid looking through current 12603// tracker's children, and instead return the current 12604// tracker. 12605// A case where this check is important is e.g. 12606// for (int i = 0; i < 5; ++i) { 12607// int n = GENERATE(1, 2); 12608// } 12609// 12610// without it, the code above creates 5 nested generators. 12611if (currentTracker. nameAndLocation () == nameAndLocation) { 12612auto thisTracker = currentTracker. parent (). findChild (nameAndLocation); 12613assert (thisTracker); 12614assert (thisTracker -> isGeneratorTracker ()); 12615tracker = std::static_pointer_cast < GeneratorTracker > (thisTracker); 12616} else if ( TestCaseTracking::ITrackerPtr childTracker = currentTracker. findChild ( nameAndLocation ) ) { 12617assert ( childTracker ); 12618assert ( childTracker -> isGeneratorTracker () ); 12619tracker = std::static_pointer_cast < GeneratorTracker > ( childTracker ); 12620} else { 12621tracker = std::make_shared < GeneratorTracker > ( nameAndLocation, ctx, & currentTracker ); 12622currentTracker. addChild ( tracker ); 12623} 12624 12625if ( !tracker -> isComplete () ) { 12626tracker -> open (); 12627} 12628 12629return * tracker; 12630} 12631 12632// TrackerBase interface 12633bool isGeneratorTracker () const override { return true; } 12634auto hasGenerator() const -> bool override { 12635return !!m_generator; 12636} 12637void close () override { 12638TrackerBase :: close (); 12639// If a generator has a child (it is followed by a section) 12640// and none of its children have started, then we must wait 12641// until later to start consuming its values. 12642// This catches cases where `GENERATE` is placed between two 12643// `SECTION`s. 12644// **The check for m_children.empty cannot be removed**. 12645// doing so would break `GENERATE` _not_ followed by `SECTION`s. 12646const bool should_wait_for_child = [ & ]() { 12647// No children -> nobody to wait for 12648if ( m_children. empty () ) { 12649return false; 12650} 12651// If at least one child started executing, don't wait 12652if ( std:: find_if ( 12653m_children. begin (), 12654m_children. end (), 12655[]( TestCaseTracking::ITrackerPtr tracker ) { 12656return tracker -> hasStarted (); 12657} ) ! = m_children. end () ) { 12658return false; 12659} 12660 12661// No children have started. We need to check if they _can_ 12662// start, and thus we should wait for them, or they cannot 12663// start (due to filters), and we shouldn't wait for them 12664auto * parent = m_parent; 12665// This is safe: there is always at least one section 12666// tracker in a test case tracking tree 12667while ( !parent -> isSectionTracker () ) { 12668parent = & ( parent -> parent () ); 12669} 12670assert ( parent && 12671"Missing root (test case) level section" ); 12672 12673auto const & parentSection = 12674static_cast < SectionTracker &> ( * parent ); 12675auto const & filters = parentSection. getFilters (); 12676// No filters -> no restrictions on running sections 12677if ( filters. empty () ) { 12678return true; 12679} 12680 12681for ( auto const & child : m_children ) { 12682if ( child -> isSectionTracker () && 12683std:: find ( filters. begin (), 12684filters. end (), 12685static_cast < SectionTracker &> ( * child ) 12686. trimmedName () ) != 12687filters. end () ) { 12688return true; 12689} 12690} 12691return false; 12692}(); 12693 12694// This check is a bit tricky, because m_generator->next() 12695// has a side-effect, where it consumes generator's current 12696// value, but we do not want to invoke the side-effect if 12697// this generator is still waiting for any child to start. 12698if ( should_wait_for_child || 12699( m_runState == CompletedSuccessfully && 12700m_generator -> next () ) ) { 12701m_children. clear (); 12702m_runState = Executing; 12703} 12704} 12705 12706// IGeneratorTracker interface 12707auto getGenerator() const -> GeneratorBasePtr const & override { 12708return m_generator; 12709} 12710void setGenerator ( GeneratorBasePtr && generator ) override { 12711m_generator = std:: move ( generator ); 12712} 12713}; 12714GeneratorTracker ::~ GeneratorTracker () {} 12715} 12716 12717RunContext ::RunContext( IConfigPtr const & _config, IStreamingReporterPtr && reporter) 12718: m_runInfo (_config -> name ()), 12719m_context ( getCurrentMutableContext ()), 12720m_config (_config), 12721m_reporter (std:: move (reporter)), 12722m_lastAssertionInfo{ StringRef (), SourceLineInfo ( "" , 0 ), StringRef (), ResultDisposition::Normal }, 12723m_includeSuccessfulResults ( m_config -> includeSuccessfulResults () || m_reporter -> getPreferences (). shouldReportAllAssertions ) 12724{ 12725m_context. setRunner (this); 12726m_context. setConfig (m_config); 12727m_context. setResultCapture (this); 12728m_reporter -> testRunStarting (m_runInfo); 12729} 12730 12731RunContext ::~ RunContext () { 12732m_reporter -> testRunEnded ( TestRunStats (m_runInfo, m_totals, aborting ())); 12733} 12734 12735void RunContext:: testGroupStarting ( std ::string const & testSpec, std :: size_t groupIndex, std :: size_t groupsCount) { 12736m_reporter -> testGroupStarting ( GroupInfo (testSpec, groupIndex, groupsCount)); 12737} 12738 12739void RunContext:: testGroupEnded ( std ::string const & testSpec, Totals const & totals, std :: size_t groupIndex, std :: size_t groupsCount) { 12740m_reporter -> testGroupEnded ( TestGroupStats ( GroupInfo (testSpec, groupIndex, groupsCount), totals, aborting ())); 12741} 12742 12743Totals RunContext:: runTest ( TestCase const & testCase) { 12744Totals prevTotals = m_totals; 12745 12746std :: string redirectedCout; 12747std :: string redirectedCerr; 12748 12749auto const & testInfo = testCase. getTestCaseInfo (); 12750 12751m_reporter -> testCaseStarting (testInfo); 12752 12753m_activeTestCase = & testCase; 12754 12755ITracker & rootTracker = m_trackerContext. startRun (); 12756assert (rootTracker. isSectionTracker ()); 12757static_cast < SectionTracker &> (rootTracker). addInitialFilters (m_config -> getSectionsToRun ()); 12758do { 12759m_trackerContext. startCycle (); 12760m_testCaseTracker = & SectionTracker:: acquire (m_trackerContext, TestCaseTracking:: NameAndLocation (testInfo. name , testInfo. lineInfo )); 12761runCurrentTest (redirectedCout, redirectedCerr); 12762} while (!m_testCaseTracker -> isSuccessfullyCompleted () && ! aborting ()); 12763 12764Totals deltaTotals = m_totals. delta (prevTotals); 12765if (testInfo. expectedToFail () && deltaTotals. testCases . passed > 0 ) { 12766deltaTotals. assertions . failed ++ ; 12767deltaTotals. testCases . passed -- ; 12768deltaTotals. testCases . failed ++ ; 12769} 12770m_totals. testCases += deltaTotals. testCases ; 12771m_reporter -> testCaseEnded ( TestCaseStats (testInfo, 12772deltaTotals, 12773redirectedCout, 12774redirectedCerr, 12775aborting ())); 12776 12777m_activeTestCase = nullptr ; 12778m_testCaseTracker = nullptr ; 12779 12780return deltaTotals; 12781} 12782 12783IConfigPtr RunContext:: config () const { 12784return m_config; 12785} 12786 12787IStreamingReporter & RunContext:: reporter () const { 12788return * m_reporter; 12789} 12790 12791void RunContext:: assertionEnded ( AssertionResult const & result) { 12792if (result. getResultType () == ResultWas::Ok) { 12793m_totals. assertions . passed ++ ; 12794m_lastAssertionPassed = true; 12795} else if (!result. isOk ()) { 12796m_lastAssertionPassed = false; 12797if ( m_activeTestCase -> getTestCaseInfo (). okToFail () ) 12798m_totals. assertions . failedButOk ++ ; 12799else 12800m_totals. assertions . failed ++ ; 12801} 12802else { 12803m_lastAssertionPassed = true; 12804} 12805 12806// We have no use for the return value (whether messages should be cleared), because messages were made scoped 12807// and should be let to clear themselves out. 12808static_cast < void > (m_reporter -> assertionEnded ( AssertionStats (result, m_messages, m_totals))); 12809 12810if (result. getResultType () != ResultWas::Warning) 12811m_messageScopes. clear (); 12812 12813// Reset working state 12814resetAssertionInfo (); 12815m_lastResult = result; 12816} 12817void RunContext:: resetAssertionInfo () { 12818m_lastAssertionInfo. macroName = StringRef (); 12819m_lastAssertionInfo. capturedExpression = "{Unknown expression after the reported line}" _sr; 12820} 12821 12822bool RunContext:: sectionStarted ( SectionInfo const & sectionInfo, Counts & assertions) { 12823ITracker & sectionTracker = SectionTracker:: acquire (m_trackerContext, TestCaseTracking:: NameAndLocation (sectionInfo. name , sectionInfo. lineInfo )); 12824if (!sectionTracker. isOpen ()) 12825return false; 12826m_activeSections. push_back ( & sectionTracker); 12827 12828m_lastAssertionInfo. lineInfo = sectionInfo. lineInfo ; 12829 12830m_reporter -> sectionStarting (sectionInfo); 12831 12832assertions = m_totals. assertions ; 12833 12834return true; 12835} 12836auto RunContext :: acquireGeneratorTracker ( StringRef generatorName, SourceLineInfo const & lineInfo ) -> IGeneratorTracker & { 12837using namespace Generators; 12838GeneratorTracker & tracker = GeneratorTracker:: acquire (m_trackerContext, 12839TestCaseTracking:: NameAndLocation ( static_cast < std::string > (generatorName), lineInfo ) ); 12840m_lastAssertionInfo. lineInfo = lineInfo; 12841return tracker; 12842} 12843 12844bool RunContext:: testForMissingAssertions ( Counts & assertions) { 12845if (assertions. total () != 0 ) 12846return false; 12847if (!m_config -> warnAboutMissingAssertions ()) 12848return false; 12849if (m_trackerContext. currentTracker (). hasChildren ()) 12850return false; 12851m_totals. assertions . failed ++ ; 12852assertions. failed ++ ; 12853return true; 12854} 12855 12856void RunContext:: sectionEnded ( SectionEndInfo const & endInfo) { 12857Counts assertions = m_totals. assertions - endInfo. prevAssertions ; 12858bool missingAssertions = testForMissingAssertions (assertions); 12859 12860if (!m_activeSections. empty ()) { 12861m_activeSections. back () -> close (); 12862m_activeSections. pop_back (); 12863} 12864 12865m_reporter -> sectionEnded ( SectionStats (endInfo. sectionInfo , assertions, endInfo. durationInSeconds , missingAssertions)); 12866m_messages. clear (); 12867m_messageScopes. clear (); 12868} 12869 12870void RunContext:: sectionEndedEarly ( SectionEndInfo const & endInfo) { 12871if (m_unfinishedSections. empty ()) 12872m_activeSections. back () -> fail (); 12873else 12874m_activeSections. back () -> close (); 12875m_activeSections. pop_back (); 12876 12877m_unfinishedSections. push_back (endInfo); 12878} 12879 12880#if defined( CATCH_CONFIG_ENABLE_BENCHMARKING ) 12881void RunContext:: benchmarkPreparing ( std ::string const & name) { 12882m_reporter -> benchmarkPreparing (name); 12883} 12884void RunContext:: benchmarkStarting ( BenchmarkInfo const & info ) { 12885m_reporter -> benchmarkStarting ( info ); 12886} 12887void RunContext:: benchmarkEnded ( BenchmarkStats <> const & stats ) { 12888m_reporter -> benchmarkEnded ( stats ); 12889} 12890void RunContext:: benchmarkFailed ( std ::string const & error) { 12891m_reporter -> benchmarkFailed (error); 12892} 12893#endif // CATCH_CONFIG_ENABLE_BENCHMARKING 12894 12895void RunContext:: pushScopedMessage ( MessageInfo const & message) { 12896m_messages. push_back (message); 12897} 12898 12899void RunContext:: popScopedMessage ( MessageInfo const & message) { 12900m_messages. erase (std:: remove (m_messages. begin (), m_messages. end (), message), m_messages. end ()); 12901} 12902 12903void RunContext:: emplaceUnscopedMessage ( MessageBuilder const & builder ) { 12904m_messageScopes. emplace_back ( builder ); 12905} 12906 12907std :: string RunContext:: getCurrentTestName () const { 12908return m_activeTestCase 12909? m_activeTestCase -> getTestCaseInfo (). name 12910: std:: string (); 12911} 12912 12913const AssertionResult * RunContext:: getLastResult () const { 12914return & ( * m_lastResult); 12915} 12916 12917void RunContext:: exceptionEarlyReported () { 12918m_shouldReportUnexpected = false; 12919} 12920 12921void RunContext:: handleFatalErrorCondition ( StringRef message ) { 12922// First notify reporter that bad things happened 12923m_reporter -> fatalErrorEncountered (message); 12924 12925// Don't rebuild the result -- the stringification itself can cause more fatal errors 12926// Instead, fake a result data. 12927AssertionResultData tempResult ( ResultWas ::FatalErrorCondition, { false } ); 12928tempResult. message = static_cast < std::string > (message); 12929AssertionResult result ( m_lastAssertionInfo , tempResult ); 12930 12931assertionEnded (result); 12932 12933handleUnfinishedSections (); 12934 12935// Recreate section for test case (as we will lose the one that was in scope) 12936auto const & testCaseInfo = m_activeTestCase -> getTestCaseInfo (); 12937SectionInfo testCaseSection ( testCaseInfo .lineInfo, testCaseInfo .name); 12938 12939Counts assertions; 12940assertions. failed = 1 ; 12941SectionStats testCaseSectionStats (testCaseSection, assertions, 0 , false); 12942m_reporter -> sectionEnded (testCaseSectionStats); 12943 12944auto const & testInfo = m_activeTestCase -> getTestCaseInfo (); 12945 12946Totals deltaTotals; 12947deltaTotals. testCases . failed = 1 ; 12948deltaTotals. assertions . failed = 1 ; 12949m_reporter -> testCaseEnded ( TestCaseStats (testInfo, 12950deltaTotals, 12951std:: string (), 12952std:: string (), 12953false)); 12954m_totals. testCases . failed ++ ; 12955testGroupEnded ( std :: string (), m_totals, 1 , 1 ); 12956m_reporter -> testRunEnded ( TestRunStats (m_runInfo, m_totals, false)); 12957} 12958 12959bool RunContext:: lastAssertionPassed () { 12960return m_lastAssertionPassed; 12961} 12962 12963void RunContext:: assertionPassed () { 12964m_lastAssertionPassed = true; 12965++ m_totals. assertions . passed ; 12966resetAssertionInfo (); 12967m_messageScopes. clear (); 12968} 12969 12970bool RunContext:: aborting () const { 12971return m_totals. assertions . failed >= static_cast < std:: size_t > (m_config -> abortAfter ()); 12972} 12973 12974void RunContext:: runCurrentTest ( std ::string & redirectedCout, std ::string & redirectedCerr) { 12975auto const & testCaseInfo = m_activeTestCase -> getTestCaseInfo (); 12976SectionInfo testCaseSection ( testCaseInfo .lineInfo, testCaseInfo .name); 12977m_reporter -> sectionStarting (testCaseSection); 12978Counts prevAssertions = m_totals. assertions ; 12979double duration = 0 ; 12980m_shouldReportUnexpected = true; 12981m_lastAssertionInfo = { "TEST_CASE" _sr, testCaseInfo. lineInfo , StringRef (), ResultDisposition::Normal }; 12982 12983seedRng ( * m_config); 12984 12985Timer timer; 12986CATCH_TRY { 12987if (m_reporter -> getPreferences (). shouldRedirectStdOut ) { 12988#if !defined( CATCH_CONFIG_EXPERIMENTAL_REDIRECT ) 12989RedirectedStreams redirectedStreams ( redirectedCout , redirectedCerr ); 12990 12991timer. start (); 12992invokeActiveTestCase (); 12993#else 12994OutputRedirect r ( redirectedCout , redirectedCerr ); 12995timer. start (); 12996invokeActiveTestCase (); 12997#endif 12998} else { 12999timer. start (); 13000invokeActiveTestCase (); 13001} 13002duration = timer. getElapsedSeconds (); 13003} CATCH_CATCH_ANON (TestFailureException & ) { 13004// This just means the test was aborted due to failure 13005} CATCH_CATCH_ALL { 13006// Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions 13007// are reported without translation at the point of origin. 13008if ( m_shouldReportUnexpected ) { 13009AssertionReaction dummyReaction; 13010handleUnexpectedInflightException ( m_lastAssertionInfo, translateActiveException (), dummyReaction ); 13011} 13012} 13013Counts assertions = m_totals. assertions - prevAssertions; 13014bool missingAssertions = testForMissingAssertions (assertions); 13015 13016m_testCaseTracker -> close (); 13017handleUnfinishedSections (); 13018m_messages. clear (); 13019m_messageScopes. clear (); 13020 13021SectionStats testCaseSectionStats ( testCaseSection , assertions , duration , missingAssertions ); 13022m_reporter -> sectionEnded (testCaseSectionStats); 13023} 13024 13025void RunContext:: invokeActiveTestCase () { 13026FatalConditionHandlerGuard _ ( & m_fatalConditionhandler ); 13027m_activeTestCase -> invoke (); 13028} 13029 13030void RunContext:: handleUnfinishedSections () { 13031// If sections ended prematurely due to an exception we stored their 13032// infos here so we can tear them down outside the unwind process. 13033for (auto it = m_unfinishedSections. rbegin (), 13034itEnd = m_unfinishedSections. rend (); 13035it != itEnd; 13036++ it) 13037sectionEnded ( * it); 13038m_unfinishedSections. clear (); 13039} 13040 13041void RunContext:: handleExpr ( 13042AssertionInfo const & info, 13043ITransientExpression const & expr, 13044AssertionReaction & reaction 13045) { 13046m_reporter -> assertionStarting ( info ); 13047 13048bool negated = isFalseTest ( info. resultDisposition ); 13049bool result = expr. getResult () != negated; 13050 13051if ( result ) { 13052if (!m_includeSuccessfulResults) { 13053assertionPassed (); 13054} 13055else { 13056reportExpr (info, ResultWas::Ok, & expr, negated); 13057} 13058} 13059else { 13060reportExpr (info, ResultWas::ExpressionFailed, & expr, negated ); 13061populateReaction ( reaction ); 13062} 13063} 13064void RunContext:: reportExpr ( 13065AssertionInfo const & info, 13066ResultWas ::OfType resultType, 13067ITransientExpression const * expr, 13068bool negated ) { 13069 13070m_lastAssertionInfo = info; 13071AssertionResultData data ( resultType , LazyExpression ( negated ) ); 13072 13073AssertionResult assertionResult{ info, data }; 13074assertionResult. m_resultData . lazyExpression . m_transientExpression = expr; 13075 13076assertionEnded ( assertionResult ); 13077} 13078 13079void RunContext:: handleMessage ( 13080AssertionInfo const & info, 13081ResultWas ::OfType resultType, 13082StringRef const & message, 13083AssertionReaction & reaction 13084) { 13085m_reporter -> assertionStarting ( info ); 13086 13087m_lastAssertionInfo = info; 13088 13089AssertionResultData data ( resultType , LazyExpression ( false ) ); 13090data. message = static_cast < std::string > (message); 13091AssertionResult assertionResult{ m_lastAssertionInfo, data }; 13092assertionEnded ( assertionResult ); 13093if ( !assertionResult. isOk () ) 13094populateReaction ( reaction ); 13095} 13096void RunContext:: handleUnexpectedExceptionNotThrown ( 13097AssertionInfo const & info, 13098AssertionReaction & reaction 13099) { 13100handleNonExpr (info, Catch::ResultWas::DidntThrowException, reaction); 13101} 13102 13103void RunContext:: handleUnexpectedInflightException ( 13104AssertionInfo const & info, 13105std ::string const & message, 13106AssertionReaction & reaction 13107) { 13108m_lastAssertionInfo = info; 13109 13110AssertionResultData data ( ResultWas ::ThrewException, LazyExpression ( false ) ); 13111data. message = message; 13112AssertionResult assertionResult{ info, data }; 13113assertionEnded ( assertionResult ); 13114populateReaction ( reaction ); 13115} 13116 13117void RunContext:: populateReaction ( AssertionReaction & reaction ) { 13118reaction. shouldDebugBreak = m_config -> shouldDebugBreak (); 13119reaction. shouldThrow = aborting () || (m_lastAssertionInfo. resultDisposition & ResultDisposition::Normal); 13120} 13121 13122void RunContext:: handleIncomplete ( 13123AssertionInfo const & info 13124) { 13125m_lastAssertionInfo = info; 13126 13127AssertionResultData data ( ResultWas ::ThrewException, LazyExpression ( false ) ); 13128data. message = "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE" ; 13129AssertionResult assertionResult{ info, data }; 13130assertionEnded ( assertionResult ); 13131} 13132void RunContext:: handleNonExpr ( 13133AssertionInfo const & info, 13134ResultWas ::OfType resultType, 13135AssertionReaction & reaction 13136) { 13137m_lastAssertionInfo = info; 13138 13139AssertionResultData data ( resultType , LazyExpression ( false ) ); 13140AssertionResult assertionResult{ info, data }; 13141assertionEnded ( assertionResult ); 13142 13143if ( !assertionResult. isOk () ) 13144populateReaction ( reaction ); 13145} 13146 13147IResultCapture & getResultCapture () { 13148if (auto * capture = getCurrentContext (). getResultCapture ()) 13149return * capture; 13150else 13151CATCH_INTERNAL_ERROR ( "No result capture instance" ); 13152} 13153 13154void seedRng ( IConfig const & config) { 13155if (config. rngSeed () != 0 ) { 13156std :: srand (config. rngSeed ()); 13157rng (). seed (config. rngSeed ()); 13158} 13159} 13160 13161unsigned int rngSeed () { 13162return getCurrentContext (). getConfig () -> rngSeed (); 13163} 13164 13165} 13166// end catch_run_context.cpp 13167// start catch_section.cpp 13168 13169namespace Catch { 13170 13171Section ::Section( SectionInfo const & info ) 13172: m_info ( info ), 13173m_sectionIncluded ( getResultCapture (). sectionStarted ( m_info, m_assertions ) ) 13174{ 13175m_timer. start (); 13176} 13177 13178Section ::~ Section () { 13179if ( m_sectionIncluded ) { 13180SectionEndInfo endInfo{ m_info, m_assertions, m_timer. getElapsedSeconds () }; 13181if ( uncaught_exceptions () ) 13182getResultCapture (). sectionEndedEarly ( endInfo ); 13183else 13184getResultCapture (). sectionEnded ( endInfo ); 13185} 13186} 13187 13188// This indicates whether the section should be executed or not 13189Section :: operator bool () const { 13190return m_sectionIncluded; 13191} 13192 13193} // end namespace Catch 13194// end catch_section.cpp 13195// start catch_section_info.cpp 13196 13197namespace Catch { 13198 13199SectionInfo ::SectionInfo 13200( SourceLineInfo const & _lineInfo, 13201std:: string const & _name ) 13202: name ( _name ), 13203lineInfo ( _lineInfo ) 13204{} 13205 13206} // end namespace Catch 13207// end catch_section_info.cpp 13208// start catch_session.cpp 13209 13210// start catch_session.h 13211 13212#include <memory> 13213 13214namespace Catch { 13215 13216class Session : NonCopyable { 13217public : 13218 13219Session (); 13220~ Session () override; 13221 13222void showHelp () const ; 13223void libIdentify (); 13224 13225int applyCommandLine ( int argc, char const * const * argv ); 13226#if defined( CATCH_CONFIG_WCHAR ) && defined(_WIN32) && defined( UNICODE ) 13227int applyCommandLine ( int argc, wchar_t const * const * argv ); 13228#endif 13229 13230void useConfigData ( ConfigData const & configData ); 13231 13232template < typename CharT > 13233int run (int argc, CharT const * const argv[]) { 13234if (m_startupExceptions) 13235return 1 ; 13236int returnCode = applyCommandLine (argc, argv); 13237if (returnCode == 0 ) 13238returnCode = run (); 13239return returnCode; 13240} 13241 13242int run (); 13243 13244clara :: Parser const & cli () const; 13245void cli ( clara ::Parser const & newParser ); 13246ConfigData & configData (); 13247Config & config (); 13248private : 13249int runInternal (); 13250 13251clara :: Parser m_cli; 13252ConfigData m_configData; 13253std ::shared_ptr < Config > m_config; 13254bool m_startupExceptions = false; 13255}; 13256 13257} // end namespace Catch 13258 13259// end catch_session.h 13260// start catch_version.h 13261 13262#include <iosfwd> 13263 13264namespace Catch { 13265 13266// Versioning information 13267struct Version { 13268Version( Version const & ) = delete ; 13269Version & operator = ( Version const & ) = delete ; 13270Version( unsigned int _majorVersion , 13271unsigned int _minorVersion , 13272unsigned int _patchNumber , 13273char const * const _branchName , 13274unsigned int _buildNumber ); 13275 13276unsigned int const majorVersion ; 13277unsigned int const minorVersion ; 13278unsigned int const patchNumber ; 13279 13280// buildNumber is only used if branchName is not null 13281char const * const branchName ; 13282unsigned int const buildNumber ; 13283 13284friend std ::ostream & operator << ( std::ostream & os, Version const & version ); 13285}; 13286 13287Version const & libraryVersion (); 13288} 13289 13290// end catch_version.h 13291#include <cstdlib> 13292#include <iomanip> 13293#include <set> 13294#include <iterator> 13295 13296namespace Catch { 13297 13298namespace { 13299const int MaxExitCode = 255 ; 13300 13301IStreamingReporterPtr createReporter ( std ::string const & reporterName, IConfigPtr const & config) { 13302auto reporter = Catch:: getRegistryHub ().getReporterRegistry(). create ( reporterName , config ); 13303CATCH_ENFORCE ( reporter , "No reporter registered with name: '" << reporterName << "'" ); 13304 13305return reporter; 13306} 13307 13308IStreamingReporterPtr makeReporter ( std ::shared_ptr < Config > const & config) { 13309if (Catch:: getRegistryHub (). getReporterRegistry (). getListeners (). empty ()) { 13310return createReporter (config -> getReporterName (), config); 13311} 13312 13313// On older platforms, returning std::unique_ptr<ListeningReporter> 13314// when the return type is std::unique_ptr<IStreamingReporter> 13315// doesn't compile without a std::move call. However, this causes 13316// a warning on newer platforms. Thus, we have to work around 13317// it a bit and downcast the pointer manually. 13318auto ret = std::unique_ptr < IStreamingReporter > (new ListeningReporter); 13319auto & multi = static_cast < ListeningReporter &> ( * ret); 13320auto const & listeners = Catch:: getRegistryHub (). getReporterRegistry (). getListeners (); 13321for (auto const & listener : listeners) { 13322multi. addListener ( listener -> create ( Catch :: ReporterConfig ( config ))); 13323} 13324multi. addReporter ( createReporter (config -> getReporterName (), config)); 13325return ret; 13326} 13327 13328class TestGroup { 13329public: 13330explicit TestGroup (std::shared_ptr < Config > const & config) 13331: m_config{config} 13332, m_context{config, makeReporter (config)} 13333{ 13334auto const & allTestCases = getAllTestCasesSorted ( * m_config); 13335m_matches = m_config -> testSpec(). matchesByFilter (allTestCases, * m_config); 13336auto const & invalidArgs = m_config -> testSpec (). getInvalidArgs (); 13337 13338if (m_matches. empty () && invalidArgs. empty ()) { 13339for (auto const & test : allTestCases ) 13340if (! test . isHidden ()) 13341m_tests. emplace ( & test); 13342} else { 13343for (auto const & match : m_matches) 13344m_tests. insert (match.tests. begin (), match.tests. end ()); 13345} 13346} 13347 13348Totals execute () { 13349auto const & invalidArgs = m_config -> testSpec (). getInvalidArgs (); 13350Totals totals; 13351m_context. testGroupStarting (m_config -> name (), 1 , 1 ); 13352for (auto const & testCase : m_tests) { 13353if (!m_context. aborting ()) 13354totals += m_context. runTest ( * testCase); 13355else 13356m_context. reporter (). skipTest ( * testCase); 13357} 13358 13359for (auto const & match : m_matches) { 13360if (match. tests . empty ()) { 13361m_context. reporter (). noMatchingTestCases (match. name ); 13362totals. error = -1 ; 13363} 13364} 13365 13366if (!invalidArgs. empty ()) { 13367for (auto const & invalidArg: invalidArgs) 13368m_context. reporter (). reportInvalidArguments (invalidArg); 13369} 13370 13371m_context. testGroupEnded (m_config -> name (), totals, 1 , 1 ); 13372return totals; 13373} 13374 13375private: 13376using Tests = std::set < TestCase const *> ; 13377 13378std::shared_ptr < Config > m_config; 13379RunContext m_context; 13380Tests m_tests; 13381TestSpec::Matches m_matches; 13382}; 13383 13384void applyFilenamesAsTags(Catch::IConfig const & config) { 13385auto & tests = const_cast < std::vector < TestCase >& >( getAllTestCasesSorted (config)); 13386for (auto & testCase : tests) { 13387auto tags = testCase. tags ; 13388 13389std::string filename = testCase. lineInfo . file ; 13390auto lastSlash = filename. find_last_of ( "\\/" ); 13391if (lastSlash != std::string::npos) { 13392filename. erase ( 0 , lastSlash); 13393filename[ 0 ] = '#' ; 13394} 13395 13396auto lastDot = filename. find_last_of ( '.' ); 13397if (lastDot != std::string::npos) { 13398filename. erase (lastDot); 13399} 13400 13401tags. push_back (std:: move (filename)); 13402setTags (testCase, tags); 13403} 13404} 13405 13406} // anon namespace 13407 13408Session:: Session () { 13409static bool alreadyInstantiated = false; 13410if ( alreadyInstantiated ) { 13411CATCH_TRY { CATCH_INTERNAL_ERROR ( "Only one instance of Catch::Session can ever be used" ); } 13412CATCH_CATCH_ALL { getMutableRegistryHub (). registerStartupException (); } 13413} 13414 13415// There cannot be exceptions at startup in no-exception mode. 13416#if !defined( CATCH_CONFIG_DISABLE_EXCEPTIONS ) 13417const auto & exceptions = getRegistryHub (). getStartupExceptionRegistry (). getExceptions (); 13418if ( !exceptions. empty () ) { 13419config (); 13420getCurrentMutableContext (). setConfig (m_config); 13421 13422m_startupExceptions = true; 13423Colour colourGuard ( Colour ::Red ); 13424Catch :: cerr () << "Errors occurred during startup!" << '\n' ; 13425// iterate over all exceptions and notify user 13426for ( const auto & ex_ptr : exceptions ) { 13427try { 13428std:: rethrow_exception ( ex_ptr ); 13429} catch ( std::exception const & ex ) { 13430Catch:: cerr () << Column ( ex. what () ). indent ( 2 ) << '\n' ; 13431} 13432} 13433} 13434#endif 13435 13436alreadyInstantiated = true; 13437m_cli = makeCommandLineParser ( m_configData ); 13438} 13439Session::~ Session () { 13440Catch::cleanUp(); 13441} 13442 13443void Session:: showHelp () const { 13444Catch :: cout () 13445<< "\nCatch v" << libraryVersion () << "\n" 13446<< m_cli << std::endl 13447<< "For more detailed usage please see the project docs\n" << std::endl; 13448} 13449void Session:: libIdentify () { 13450Catch :: cout () 13451<< std::left << std:: setw ( 16 ) << "description: " << "A Catch2 test executable\n" 13452<< std::left << std:: setw ( 16 ) << "category: " << "testframework\n" 13453<< std::left << std:: setw ( 16 ) << "framework: " << "Catch Test\n" 13454<< std::left << std:: setw ( 16 ) << "version: " << libraryVersion () << std::endl; 13455} 13456 13457int Session:: applyCommandLine ( int argc, char const * const * argv ) { 13458if ( m_startupExceptions ) 13459return 1 ; 13460 13461auto result = m_cli. parse ( clara:: Args ( argc, argv ) ); 13462if ( !result ) { 13463config (); 13464getCurrentMutableContext (). setConfig (m_config); 13465Catch :: cerr () 13466<< Colour ( Colour::Red ) 13467<< "\nError(s) in input:\n" 13468<< Column ( result. errorMessage () ). indent ( 2 ) 13469<< "\n\n" ; 13470Catch :: cerr () << "Run with -? for usage\n" << std::endl; 13471return MaxExitCode; 13472} 13473 13474if ( m_configData. showHelp ) 13475showHelp (); 13476if ( m_configData. libIdentify ) 13477libIdentify (); 13478m_config. reset (); 13479return 0 ; 13480} 13481 13482#if defined( CATCH_CONFIG_WCHAR ) && defined(_WIN32) && defined( UNICODE ) 13483int Session:: applyCommandLine ( int argc, wchar_t const * const * argv ) { 13484 13485char ** utf8Argv = new char * [ argc ]; 13486 13487for ( int i = 0 ; i < argc; ++ i ) { 13488int bufSize = WideCharToMultiByte ( CP_UTF8 , 0 , argv[i], -1 , nullptr , 0 , nullptr , nullptr ); 13489 13490utf8Argv[ i ] = new char[ bufSize ]; 13491 13492WideCharToMultiByte ( CP_UTF8 , 0 , argv[i], -1 , utf8Argv[i], bufSize, nullptr , nullptr ); 13493} 13494 13495int returnCode = applyCommandLine ( argc, utf8Argv ); 13496 13497for ( int i = 0 ; i < argc; ++ i ) 13498delete [] utf8Argv[ i ]; 13499 13500delete [] utf8Argv; 13501 13502return returnCode; 13503} 13504#endif 13505 13506void Session:: useConfigData ( ConfigData const & configData ) { 13507m_configData = configData; 13508m_config. reset (); 13509} 13510 13511int Session:: run () { 13512if ( ( m_configData. waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) { 13513Catch :: cout () << "...waiting for enter/ return before starting" << std::endl; 13514static_cast < void > (std:: getchar ()); 13515} 13516int exitCode = runInternal (); 13517if ( ( m_configData. waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) { 13518Catch :: cout () << "...waiting for enter/ return before exiting, with code: " << exitCode << std::endl; 13519static_cast < void > (std:: getchar ()); 13520} 13521return exitCode; 13522} 13523 13524clara :: Parser const & Session:: cli () const { 13525return m_cli; 13526} 13527void Session:: cli ( clara ::Parser const & newParser ) { 13528m_cli = newParser; 13529} 13530ConfigData & Session:: configData () { 13531return m_configData; 13532} 13533Config & Session:: config () { 13534if ( !m_config ) 13535m_config = std::make_shared < Config > ( m_configData ); 13536return * m_config; 13537} 13538 13539int Session:: runInternal () { 13540if ( m_startupExceptions ) 13541return 1 ; 13542 13543if (m_configData. showHelp || m_configData. libIdentify ) { 13544return 0 ; 13545} 13546 13547CATCH_TRY { 13548config (); // Force config to be constructed 13549 13550seedRng ( * m_config ); 13551 13552if ( m_configData. filenamesAsTags ) 13553applyFilenamesAsTags ( * m_config ); 13554 13555// Handle list request 13556if ( Option < std:: size_t > listed = list ( m_config ) ) 13557return static_cast < int > ( * listed ); 13558 13559TestGroup tests { m_config }; 13560auto const totals = tests. execute (); 13561 13562if ( m_config -> warnAboutNoTests () && totals. error == -1 ) 13563return 2 ; 13564 13565// Note that on unices only the lower 8 bits are usually used, clamping 13566// the return value to 255 prevents false negative when some multiple 13567// of 256 tests has failed 13568return (std::min) (MaxExitCode, (std::max) (totals. error , static_cast < int > (totals. assertions . failed ))); 13569} 13570#if !defined( CATCH_CONFIG_DISABLE_EXCEPTIONS ) 13571catch ( std ::exception & ex ) { 13572Catch :: cerr () << ex. what () << std::endl; 13573return MaxExitCode; 13574} 13575#endif 13576} 13577 13578} // end namespace Catch 13579// end catch_session.cpp 13580// start catch_singletons.cpp 13581 13582#include <vector> 13583 13584namespace Catch { 13585 13586namespace { 13587static auto getSingletons () -> std :: vector < ISingleton *>*& { 13588static std :: vector < ISingleton *>* g_singletons = nullptr ; 13589if ( ! g_singletons ) 13590g_singletons = new std :: vector < ISingleton *> (); 13591return g_singletons ; 13592} 13593} 13594 13595ISingleton ::~ ISingleton () {} 13596 13597void addSingleton ( ISingleton * singleton ) { 13598getSingletons () -> push_back ( singleton ); 13599} 13600void cleanupSingletons () { 13601auto & singletons = getSingletons (); 13602for( auto singleton : * singletons ) 13603delete singleton ; 13604delete singletons ; 13605singletons = nullptr ; 13606} 13607 13608} // namespace Catch 13609// end catch_singletons.cpp 13610// start catch_startup_exception_registry.cpp 13611 13612#if !defined( CATCH_CONFIG_DISABLE_EXCEPTIONS ) 13613namespace Catch { 13614void StartupExceptionRegistry :: add ( std :: exception_ptr const & exception ) noexcept { 13615CATCH_TRY { 13616m_exceptions . push_back ( exception ); 13617} CATCH_CATCH_ALL { 13618// If we run out of memory during start-up there's really not a lot more we can do about it 13619std :: terminate (); 13620} 13621} 13622 13623std :: vector < std :: exception_ptr > const & StartupExceptionRegistry :: getExceptions () const noexcept { 13624return m_exceptions; 13625} 13626 13627} // end namespace Catch 13628#endif 13629// end catch_startup_exception_registry.cpp 13630// start catch_stream.cpp 13631 13632#include <cstdio> 13633#include <iostream> 13634#include <fstream> 13635#include <sstream> 13636#include <vector> 13637#include <memory> 13638 13639namespace Catch { 13640 13641Catch :: IStream ::~ IStream () = default; 13642 13643namespace Detail { namespace { 13644template < typename WriterF, std:: size_t bufferSize = 256 > 13645class StreamBufImpl : public std::streambuf { 13646char data[bufferSize]; 13647WriterF m_writer; 13648 13649public : 13650StreamBufImpl () { 13651setp ( data, data + sizeof (data) ); 13652} 13653 13654~ StreamBufImpl () noexcept { 13655StreamBufImpl :: sync (); 13656} 13657 13658private : 13659int overflow ( int c ) override { 13660sync (); 13661 13662if ( c != EOF ) { 13663if ( pbase () == epptr () ) 13664m_writer ( std:: string ( 1 , static_cast < char > ( c ) ) ); 13665else 13666sputc ( static_cast < char > ( c ) ); 13667} 13668return 0 ; 13669} 13670 13671int sync () override { 13672if ( pbase () != pptr () ) { 13673m_writer ( std ::string( pbase (), static_cast < std:: string ::size_type > ( pptr () - pbase () ) ) ); 13674setp ( pbase (), epptr () ); 13675} 13676return 0 ; 13677} 13678}; 13679 13680/////////////////////////////////////////////////////////////////////////// 13681 13682struct OutputDebugWriter { 13683 13684void operator ()( std ::string const & str ) { 13685writeToDebugConsole ( str ); 13686} 13687}; 13688 13689/////////////////////////////////////////////////////////////////////////// 13690 13691class FileStream : public IStream { 13692mutable std::ofstream m_ofs; 13693public : 13694FileStream( StringRef filename ) { 13695m_ofs. open ( filename. c_str () ); 13696CATCH_ENFORCE ( !m_ofs. fail (), "Unable to open file: '" << filename << "'" ); 13697} 13698~ FileStream () override = default; 13699public : // IStream 13700std ::ostream & stream () const override { 13701return m_ofs; 13702} 13703}; 13704 13705/////////////////////////////////////////////////////////////////////////// 13706 13707class CoutStream : public IStream { 13708mutable std::ostream m_os; 13709public : 13710// Store the streambuf from cout up-front because 13711// cout may get redirected when running tests 13712CoutStream () : m_os ( Catch :: cout (). rdbuf () ) {} 13713~ CoutStream () override = default; 13714 13715public : // IStream 13716std ::ostream & stream () const override { return m_os; } 13717}; 13718 13719/////////////////////////////////////////////////////////////////////////// 13720 13721class DebugOutStream : public IStream { 13722std ::unique_ptr < StreamBufImpl < OutputDebugWriter>> m_streamBuf; 13723mutable std::ostream m_os; 13724public : 13725DebugOutStream () 13726: m_streamBuf( new StreamBufImpl < OutputDebugWriter > () ), 13727m_os ( m_streamBuf. get () ) 13728{} 13729 13730~ DebugOutStream () override = default; 13731 13732public : // IStream 13733std ::ostream & stream () const override { return m_os; } 13734}; 13735 13736}} // namespace anon::detail 13737 13738/////////////////////////////////////////////////////////////////////////// 13739 13740auto makeStream( StringRef const & filename ) -> IStream const * { 13741if ( filename. empty () ) 13742return new Detail :: CoutStream (); 13743else if ( filename [ 0 ] == '%' ) { 13744if ( filename == "%debug" ) 13745return new Detail :: DebugOutStream (); 13746else 13747CATCH_ERROR ( "Unrecognised stream: '" << filename << "'" ); 13748} 13749else 13750return new Detail:: FileStream ( filename ); 13751} 13752 13753// This class encapsulates the idea of a pool of ostringstreams that can be reused. 13754struct StringStreams { 13755std :: vector < std ::unique_ptr < std::ostringstream>> m_streams; 13756std :: vector < std ::size_t > m_unused; 13757std :: ostringstream m_referenceStream ; // Used for copy state/ flags from 13758 13759auto add() -> std :: size_t { 13760if ( m_unused.empty() ) { 13761m_streams . push_back ( std ::unique_ptr < std::ostringstream > ( new std::ostringstream ) ); 13762return m_streams . size () - 1 ; 13763} 13764else { 13765auto index = m_unused. back (); 13766m_unused. pop_back (); 13767return index; 13768} 13769} 13770 13771void release ( std:: size_t index ) { 13772m_streams[index] -> copyfmt ( m_referenceStream ); // Restore initial flags and other state 13773m_unused. push_back (index); 13774} 13775}; 13776 13777ReusableStringStream :: ReusableStringStream () 13778: m_index( Singleton < StringStreams > :: getMutable (). add () ), 13779m_oss ( Singleton < StringStreams > :: getMutable (). m_streams [m_index]. get () ) 13780{} 13781 13782ReusableStringStream ::~ ReusableStringStream () { 13783static_cast < std::ostringstream * >( m_oss ) -> str ( "" ); 13784m_oss -> clear (); 13785Singleton < StringStreams > :: getMutable (). release ( m_index ); 13786} 13787 13788auto ReusableStringStream :: str () const -> std ::string { 13789return static_cast < std::ostringstream *> ( m_oss ) -> str (); 13790} 13791 13792/////////////////////////////////////////////////////////////////////////// 13793 13794#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions 13795std ::ostream & cout () { return std::cout; } 13796std ::ostream & cerr () { return std::cerr; } 13797std ::ostream & clog () { return std::clog; } 13798#endif 13799} 13800// end catch_stream.cpp 13801// start catch_string_manip.cpp 13802 13803#include <algorithm> 13804#include <ostream> 13805#include <cstring> 13806#include <cctype> 13807#include <vector> 13808 13809namespace Catch { 13810 13811namespace { 13812char toLowerCh ( char c) { 13813return static_cast < char > ( std:: tolower ( static_cast < unsigned char > (c) ) ); 13814} 13815} 13816 13817bool startsWith ( std ::string const & s, std ::string const & prefix ) { 13818return s. size () >= prefix. size () && std:: equal (prefix. begin (), prefix. end (), s. begin ()); 13819} 13820bool startsWith ( std ::string const & s, char prefix ) { 13821return !s. empty () && s[ 0 ] == prefix; 13822} 13823bool endsWith ( std ::string const & s, std ::string const & suffix ) { 13824return s. size () >= suffix. size () && std:: equal (suffix. rbegin (), suffix. rend (), s. rbegin ()); 13825} 13826bool endsWith ( std ::string const & s, char suffix ) { 13827return !s. empty () && s[s. size () - 1 ] == suffix; 13828} 13829bool contains ( std ::string const & s, std ::string const & infix ) { 13830return s. find ( infix ) != std::string::npos; 13831} 13832void toLowerInPlace ( std ::string & s ) { 13833std :: transform ( s. begin (), s. end (), s. begin (), toLowerCh ); 13834} 13835std :: string toLower( std :: string const & s ) { 13836std:: string lc = s; 13837toLowerInPlace ( lc ); 13838return lc; 13839} 13840std :: string trim( std :: string const & str ) { 13841static char const * whitespaceChars = "\n\r\t " ; 13842std :: string :: size_type start = str. find_first_not_of ( whitespaceChars ); 13843std :: string :: size_type end = str. find_last_not_of ( whitespaceChars ); 13844 13845return start != std::string::npos ? str. substr ( start, 1 + end - start ) : std:: string (); 13846} 13847 13848StringRef trim ( StringRef ref) { 13849const auto is_ws = []( char c) { 13850return c == ' ' || c == '\t' || c == '\n' || c == '\r' ; 13851}; 13852size_t real_begin = 0 ; 13853while (real_begin < ref. size () && is_ws (ref[real_begin])) { ++ real_begin; } 13854size_t real_end = ref. size (); 13855while (real_end > real_begin && is_ws (ref[real_end - 1 ])) { -- real_end; } 13856 13857return ref. substr (real_begin, real_end - real_begin); 13858} 13859 13860bool replaceInPlace ( std ::string & str, std ::string const & replaceThis, std ::string const & withThis ) { 13861bool replaced = false; 13862std :: size_t i = str. find ( replaceThis ); 13863while ( i != std::string::npos ) { 13864replaced = true; 13865str = str. substr ( 0 , i ) + withThis + str. substr ( i + replaceThis. size () ); 13866if ( i < str. size () - withThis. size () ) 13867i = str. find ( replaceThis, i + withThis. size () ); 13868else 13869i = std:: string ::npos; 13870} 13871return replaced; 13872} 13873 13874std ::vector < StringRef > splitStringRef ( StringRef str, char delimiter ) { 13875std ::vector < StringRef > subStrings; 13876std :: size_t start = 0 ; 13877for (std:: size_t pos = 0 ; pos < str. size (); ++ pos ) { 13878if ( str[pos] == delimiter ) { 13879if ( pos - start > 1 ) 13880subStrings. push_back ( str. substr ( start, pos - start ) ); 13881start = pos + 1 ; 13882} 13883} 13884if ( start < str. size () ) 13885subStrings. push_back ( str. substr ( start, str. size () - start ) ); 13886return subStrings; 13887} 13888 13889pluralise :: pluralise ( std :: size_t count, std:: string const & label ) 13890: m_count ( count ), 13891m_label ( label ) 13892{} 13893 13894std ::ostream & operator << ( std::ostream & os, pluralise const & pluraliser ) { 13895os << pluraliser. m_count << ' ' << pluraliser. m_label ; 13896if ( pluraliser. m_count != 1 ) 13897os << 's' ; 13898return os; 13899} 13900 13901} 13902// end catch_string_manip.cpp 13903// start catch_stringref.cpp 13904 13905#include <algorithm> 13906#include <ostream> 13907#include <cstring> 13908#include <cstdint> 13909 13910namespace Catch { 13911StringRef ::StringRef( char const * rawChars ) noexcept 13912: StringRef( rawChars, static_cast < StringRef::size_type > (std:: strlen (rawChars) ) ) 13913{} 13914 13915auto StringRef :: c_str () const -> char const * { 13916CATCH_ENFORCE ( isNullTerminated (), "Called StringRef::c_str() on a non-null-terminated instance" ); 13917return m_start; 13918} 13919auto StringRef :: data () const noexcept -> char const * { 13920return m_start; 13921} 13922 13923auto StringRef :: substr ( size_type start, size_type size ) const noexcept -> StringRef { 13924if (start < m_size) { 13925return StringRef (m_start + start, (std::min)(m_size - start, size)); 13926} else { 13927return StringRef (); 13928} 13929} 13930auto StringRef :: operator == ( StringRef const & other ) const noexcept -> bool { 13931return m_size == other. m_size 13932&& (std:: memcmp ( m_start, other. m_start , m_size ) == 0 ); 13933} 13934 13935auto operator << ( std :: ostream & os, StringRef const & str ) -> std::ostream & { 13936return os. write (str. data (), str. size ()); 13937} 13938 13939auto operator += ( std::string & lhs, StringRef const & rhs ) -> std::string & { 13940lhs. append ( rhs . data (), rhs . size ()); 13941return lhs; 13942} 13943 13944} // namespace Catch 13945// end catch_stringref.cpp 13946// start catch_tag_alias.cpp 13947 13948namespace Catch { 13949TagAlias :: TagAlias ( std :: string const & _tag, SourceLineInfo _lineInfo): tag (_tag), lineInfo (_lineInfo) {} 13950} 13951// end catch_tag_alias.cpp 13952// start catch_tag_alias_autoregistrar.cpp 13953 13954namespace Catch { 13955 13956RegistrarForTagAliases ::RegistrarForTagAliases( char const * alias, char const * tag, SourceLineInfo const & lineInfo) { 13957CATCH_TRY { 13958getMutableRegistryHub (). registerTagAlias (alias, tag, lineInfo); 13959} CATCH_CATCH_ALL { 13960// Do not throw when constructing global objects, instead register the exception to be processed later 13961getMutableRegistryHub (). registerStartupException (); 13962} 13963} 13964 13965} 13966// end catch_tag_alias_autoregistrar.cpp 13967// start catch_tag_alias_registry.cpp 13968 13969#include <sstream> 13970 13971namespace Catch { 13972 13973TagAliasRegistry ::~ TagAliasRegistry () {} 13974 13975TagAlias const * TagAliasRegistry:: find ( std ::string const & alias ) const { 13976auto it = m_registry. find ( alias ); 13977if ( it != m_registry. end () ) 13978return & (it -> second ); 13979else 13980return nullptr ; 13981} 13982 13983std :: string TagAliasRegistry::expandAliases( std :: string const & unexpandedTestSpec ) const { 13984std :: string expandedTestSpec = unexpandedTestSpec; 13985for ( auto const & registryKvp : m_registry ) { 13986std:: size_t pos = expandedTestSpec. find ( registryKvp. first ); 13987if ( pos != std::string::npos ) { 13988expandedTestSpec = expandedTestSpec. substr ( 0 , pos ) + 13989registryKvp. second . tag + 13990expandedTestSpec. substr ( pos + registryKvp. first . size () ); 13991} 13992} 13993return expandedTestSpec; 13994} 13995 13996void TagAliasRegistry:: add ( std::string const & alias, std::string const & tag, SourceLineInfo const & lineInfo ) { 13997CATCH_ENFORCE ( startsWith (alias, "[@" ) && endsWith (alias, ']' ), 13998"error: tag alias, '" << alias << "' is not of the form [@alias name].\n" << lineInfo ); 13999 14000CATCH_ENFORCE ( m_registry. insert (std:: make_pair (alias, TagAlias (tag, lineInfo))). second , 14001"error: tag alias, '" << alias << "' already registered.\n" 14002<< "\tFirst seen at: " << find (alias) -> lineInfo << "\n" 14003<< "\tRedefined at: " << lineInfo ); 14004} 14005 14006ITagAliasRegistry::~ ITagAliasRegistry () {} 14007 14008ITagAliasRegistry const & ITagAliasRegistry:: get () { 14009return getRegistryHub (). getTagAliasRegistry (); 14010} 14011 14012} // end namespace Catch 14013// end catch_tag_alias_registry.cpp 14014// start catch_test_case_info.cpp 14015 14016#include < cctype > 14017#include < exception > 14018#include < algorithm > 14019#include < sstream > 14020 14021namespace Catch { 14022 14023namespace { 14024TestCaseInfo::SpecialProperties parseSpecialTag ( std::string const & tag ) { 14025if ( startsWith ( tag, '.' ) || 14026tag == "!hide" ) 14027return TestCaseInfo::IsHidden; 14028else if( tag == "!throws " ) 14029return TestCaseInfo::Throws; 14030else if( tag == "!shouldfail " ) 14031return TestCaseInfo::ShouldFail; 14032else if( tag == "!mayfail " ) 14033return TestCaseInfo::MayFail; 14034else if( tag == "!nonportable " ) 14035return TestCaseInfo::NonPortable; 14036else if( tag == "!benchmark " ) 14037return static_cast < TestCaseInfo::SpecialProperties > ( TestCaseInfo::Benchmark | TestCaseInfo::IsHidden ); 14038else 14039return TestCaseInfo ::None; 14040} 14041bool isReservedTag ( std ::string const & tag ) { 14042return parseSpecialTag ( tag ) == TestCaseInfo::None && tag. size () > 0 && !std:: isalnum ( static_cast < unsigned char > (tag[ 0 ]) ); 14043} 14044void enforceNotReservedTag ( std ::string const & tag, SourceLineInfo const & _lineInfo ) { 14045CATCH_ENFORCE ( ! isReservedTag (tag), 14046"Tag name: [" << tag << "] is not allowed.\n" 14047<< "Tag names starting with non alphanumeric characters are reserved\n" 14048<< _lineInfo ); 14049} 14050} 14051 14052TestCase makeTestCase ( ITestInvoker * _testCase, 14053std ::string const & _className, 14054NameAndTags const & nameAndTags, 14055SourceLineInfo const & _lineInfo ) 14056{ 14057bool isHidden = false; 14058 14059// Parse out tags 14060std ::vector < std::string > tags; 14061std :: string desc, tag; 14062bool inTag = false; 14063for ( char c : nameAndTags.tags) { 14064if ( !inTag ) { 14065if ( c == '[' ) 14066inTag = true; 14067else 14068desc += c; 14069} 14070else { 14071if ( c == ']' ) { 14072TestCaseInfo :: SpecialProperties prop = parseSpecialTag ( tag ); 14073if ( ( prop & TestCaseInfo::IsHidden ) != 0 ) 14074isHidden = true; 14075else if ( prop == TestCaseInfo::None ) 14076enforceNotReservedTag ( tag, _lineInfo ); 14077 14078// Merged hide tags like `[.approvals]` should be added as 14079// `[.][approvals]`. The `[.]` is added at later point, so 14080// we only strip the prefix 14081if ( startsWith (tag, '.' ) && tag. size () > 1 ) { 14082tag. erase ( 0 , 1 ); 14083} 14084tags. push_back ( tag ); 14085tag. clear (); 14086inTag = false; 14087} 14088else 14089tag += c; 14090} 14091} 14092if ( isHidden ) { 14093// Add all "hidden" tags to make them behave identically 14094tags. insert ( tags. end (), { "." , "!hide" } ); 14095} 14096 14097TestCaseInfo info ( static_cast < std::string > (nameAndTags.name), _className, desc, tags, _lineInfo ); 14098return TestCase ( _testCase, std:: move (info) ); 14099} 14100 14101void setTags ( TestCaseInfo & testCaseInfo, std ::vector < std::string > tags ) { 14102std :: sort ( begin (tags), end (tags)); 14103tags. erase (std:: unique ( begin (tags), end (tags)), end (tags)); 14104testCaseInfo. lcaseTags . clear (); 14105 14106for ( auto const & tag : tags ) { 14107std::string lcaseTag = toLower ( tag ); 14108testCaseInfo. properties = static_cast < TestCaseInfo::SpecialProperties > ( testCaseInfo. properties | parseSpecialTag ( lcaseTag ) ); 14109testCaseInfo. lcaseTags . push_back ( lcaseTag ); 14110} 14111testCaseInfo. tags = std:: move (tags); 14112} 14113 14114TestCaseInfo:: TestCaseInfo ( std::string const & _name, 14115std::string const & _className, 14116std::string const & _description, 14117std::vector < std::string > const & _tags, 14118SourceLineInfo const & _lineInfo ) 14119: name ( _name ), 14120className ( _className ), 14121description ( _description ), 14122lineInfo ( _lineInfo ), 14123properties ( None ) 14124{ 14125setTags ( * this, _tags ); 14126} 14127 14128bool TestCaseInfo::isHidden() const { 14129return ( properties & IsHidden ) != 0 ; 14130} 14131bool TestCaseInfo:: throws () const { 14132return ( properties & Throws ) != 0 ; 14133} 14134bool TestCaseInfo:: okToFail () const { 14135return ( properties & (ShouldFail | MayFail ) ) != 0 ; 14136} 14137bool TestCaseInfo:: expectedToFail () const { 14138return ( properties & (ShouldFail ) ) != 0 ; 14139} 14140 14141std :: string TestCaseInfo:: tagsAsString () const { 14142std :: string ret; 14143// '[' and ']' per tag 14144std :: size_t full_size = 2 * tags. size (); 14145for ( const auto & tag : tags) { 14146full_size += tag. size (); 14147} 14148ret. reserve (full_size); 14149for (const auto & tag : tags) { 14150ret. push_back ( '[' ); 14151ret. append (tag); 14152ret. push_back ( ']' ); 14153} 14154 14155return ret; 14156} 14157 14158TestCase:: TestCase ( ITestInvoker * testCase, TestCaseInfo && info ) : TestCaseInfo ( std:: move (info) ), test ( testCase ) {} 14159 14160TestCase TestCase:: withName ( std::string const & _newName ) const { 14161TestCase other ( * this ); 14162other.name = _newName; 14163return other; 14164} 14165 14166void TestCase::invoke() const { 14167test -> invoke (); 14168} 14169 14170bool TestCase ::operator == ( TestCase const & other ) const { 14171return test. get () == other. test . get () && 14172name == other. name && 14173className == other. className ; 14174} 14175 14176bool TestCase ::operator < ( TestCase const & other ) const { 14177return name < other. name ; 14178} 14179 14180TestCaseInfo const & TestCase:: getTestCaseInfo () const 14181{ 14182return * this; 14183} 14184 14185} // end namespace Catch 14186// end catch_test_case_info.cpp 14187// start catch_test_case_registry_impl.cpp 14188 14189#include <algorithm> 14190#include <sstream> 14191 14192namespace Catch { 14193 14194namespace { 14195struct TestHasher { 14196using hash_t = uint64_t ; 14197 14198explicit TestHasher ( hash_t hashSuffix ): 14199m_hashSuffix{ hashSuffix } {} 14200 14201uint32_t operator ()( TestCase const & t ) const { 14202// FNV-1a hash with multiplication fold. 14203const hash_t prime = 1099511628211u ; 14204hash_t hash = 14695981039346656037u ; 14205for ( const char c : t. name ) { 14206hash ^= c; 14207hash *= prime ; 14208} 14209hash ^= m_hashSuffix; 14210hash *= prime; 14211const uint32_t low{ static_cast < uint32_t > ( hash ) }; 14212const uint32_t high{ static_cast < uint32_t > ( hash >> 32 ) }; 14213return low * high; 14214} 14215 14216private : 14217hash_t m_hashSuffix; 14218}; 14219} // end unnamed namespace 14220 14221std ::vector < TestCase > sortTests ( IConfig const & config, std::vector < TestCase > const & unsortedTestCases ) { 14222switch ( config. runOrder () ) { 14223case RunTests:: InDeclarationOrder : 14224// already in declaration order 14225break ; 14226 14227case RunTests:: InLexicographicalOrder : { 14228std ::vector < TestCase > sorted = unsortedTestCases; 14229std :: sort ( sorted. begin (), sorted. end () ); 14230return sorted; 14231} 14232 14233case RunTests:: InRandomOrder : { 14234seedRng ( config ); 14235TestHasher h{ config. rngSeed () }; 14236 14237using hashedTest = std::pair < TestHasher::hash_t, TestCase const *> ; 14238std ::vector < hashedTest > indexed_tests; 14239indexed_tests. reserve ( unsortedTestCases. size () ); 14240 14241for (auto const & testCase : unsortedTestCases) { 14242indexed_tests. emplace_back ( h ( testCase ), & testCase ); 14243} 14244 14245std :: sort (indexed_tests. begin (), indexed_tests. end (), 14246[](hashedTest const & lhs, hashedTest const & rhs) { 14247if (lhs. first == rhs. first ) { 14248return lhs. second -> name < rhs. second -> name ; 14249} 14250return lhs. first < rhs. first ; 14251}); 14252 14253std ::vector < TestCase > sorted; 14254sorted. reserve ( indexed_tests. size () ); 14255 14256for (auto const & hashed : indexed_tests) { 14257sorted.emplace_back( * hashed.second); 14258} 14259 14260return sorted; 14261} 14262} 14263return unsortedTestCases; 14264} 14265 14266bool isThrowSafe ( TestCase const & testCase, IConfig const & config ) { 14267return !testCase. throws () || config. allowThrows (); 14268} 14269 14270bool matchTest ( TestCase const & testCase, TestSpec const & testSpec, IConfig const & config ) { 14271return testSpec. matches ( testCase ) && isThrowSafe ( testCase, config ); 14272} 14273 14274void enforceNoDuplicateTestCases ( std ::vector < TestCase > const & functions ) { 14275std ::set < TestCase > seenFunctions; 14276for ( auto const & function : functions ) { 14277auto prev = seenFunctions. insert ( function ); 14278CATCH_ENFORCE ( prev. second , 14279"error: TEST_CASE( \"" << function. name << "\" ) already defined.\n" 14280<< "\tFirst seen at " << prev. first -> getTestCaseInfo (). lineInfo << "\n" 14281<< "\tRedefined at " << function. getTestCaseInfo (). lineInfo ); 14282} 14283} 14284 14285std::vector < TestCase > filterTests ( std::vector < TestCase > const & testCases, TestSpec const & testSpec, IConfig const & config ) { 14286std::vector < TestCase > filtered; 14287filtered. reserve ( testCases. size () ); 14288for (auto const & testCase : testCases) { 14289if ((!testSpec. hasFilters () && !testCase. isHidden ()) || 14290(testSpec. hasFilters () && matchTest (testCase, testSpec, config))) { 14291filtered. push_back (testCase); 14292} 14293} 14294return filtered; 14295} 14296std::vector < TestCase > const & getAllTestCasesSorted ( IConfig const & config ) { 14297return getRegistryHub (). getTestCaseRegistry (). getAllTestsSorted ( config ); 14298} 14299 14300void TestRegistry:: registerTest ( TestCase const & testCase ) { 14301std::string name = testCase. getTestCaseInfo (). name ; 14302if ( name. empty () ) { 14303ReusableStringStream rss; 14304rss << "Anonymous test case " << ++ m_unnamedCount; 14305return registerTest ( testCase. withName ( rss. str () ) ); 14306} 14307m_functions. push_back ( testCase ); 14308} 14309 14310std ::vector < TestCase > const & TestRegistry:: getAllTests () const { 14311return m_functions; 14312} 14313std ::vector < TestCase > const & TestRegistry::getAllTestsSorted( IConfig const & config ) const { 14314if ( m_sortedFunctions. empty () ) 14315enforceNoDuplicateTestCases ( m_functions ); 14316 14317if ( m_currentSortOrder != config. runOrder () || m_sortedFunctions. empty () ) { 14318m_sortedFunctions = sortTests ( config, m_functions ); 14319m_currentSortOrder = config. runOrder (); 14320} 14321return m_sortedFunctions; 14322} 14323 14324/////////////////////////////////////////////////////////////////////////// 14325TestInvokerAsFunction :: TestInvokerAsFunction ( void ( * testAsFunction)() ) noexcept : m_testAsFunction( testAsFunction ) {} 14326 14327void TestInvokerAsFunction:: invoke () const { 14328m_testAsFunction (); 14329} 14330 14331std :: string extractClassName ( StringRef const & classOrQualifiedMethodName ) { 14332std :: string className ( classOrQualifiedMethodName ); 14333if ( startsWith ( className, '&' ) ) 14334{ 14335std :: size_t lastColons = className. rfind ( "::" ); 14336std :: size_t penultimateColons = className. rfind ( "::" , lastColons - 1 ); 14337if ( penultimateColons == std::string::npos ) 14338penultimateColons = 1 ; 14339className = className. substr ( penultimateColons, lastColons - penultimateColons ); 14340} 14341return className; 14342} 14343 14344} // end namespace Catch 14345// end catch_test_case_registry_impl.cpp 14346// start catch_test_case_tracker.cpp 14347 14348#include <algorithm> 14349#include <cassert> 14350#include <stdexcept> 14351#include <memory> 14352#include <sstream> 14353 14354#if defined(__clang__) 14355# pragma clang diagnostic push 14356# pragma clang diagnostic ignored "-Wexit-time-destructors" 14357#endif 14358 14359namespace Catch { 14360namespace TestCaseTracking { 14361 14362NameAndLocation ::NameAndLocation( std :: string const & _name, SourceLineInfo const & _location ) 14363: name ( _name ), 14364location ( _location ) 14365{} 14366 14367ITracker ::~ ITracker () = default; 14368 14369ITracker & TrackerContext:: startRun () { 14370m_rootTracker = std::make_shared < SectionTracker > ( NameAndLocation ( "{root}" , CATCH_INTERNAL_LINEINFO ), * this, nullptr ); 14371m_currentTracker = nullptr ; 14372m_runState = Executing; 14373return * m_rootTracker; 14374} 14375 14376void TrackerContext:: endRun () { 14377m_rootTracker. reset (); 14378m_currentTracker = nullptr ; 14379m_runState = NotStarted; 14380} 14381 14382void TrackerContext:: startCycle () { 14383m_currentTracker = m_rootTracker. get (); 14384m_runState = Executing; 14385} 14386void TrackerContext:: completeCycle () { 14387m_runState = CompletedCycle; 14388} 14389 14390bool TrackerContext:: completedCycle () const { 14391return m_runState == CompletedCycle; 14392} 14393ITracker & TrackerContext:: currentTracker () { 14394return * m_currentTracker; 14395} 14396void TrackerContext:: setCurrentTracker ( ITracker * tracker ) { 14397m_currentTracker = tracker; 14398} 14399 14400TrackerBase ::TrackerBase( NameAndLocation const & nameAndLocation, TrackerContext & ctx, ITracker * parent ): 14401ITracker (nameAndLocation), 14402m_ctx ( ctx ), 14403m_parent ( parent ) 14404{} 14405 14406bool TrackerBase:: isComplete () const { 14407return m_runState == CompletedSuccessfully || m_runState == Failed; 14408} 14409bool TrackerBase:: isSuccessfullyCompleted () const { 14410return m_runState == CompletedSuccessfully; 14411} 14412bool TrackerBase:: isOpen () const { 14413return m_runState != NotStarted && ! isComplete (); 14414} 14415bool TrackerBase:: hasChildren () const { 14416return !m_children. empty (); 14417} 14418 14419void TrackerBase:: addChild ( ITrackerPtr const & child ) { 14420m_children. push_back ( child ); 14421} 14422 14423ITrackerPtr TrackerBase:: findChild ( NameAndLocation const & nameAndLocation ) { 14424auto it = std:: find_if ( m_children . begin (), m_children . end (), 14425[ & nameAndLocation ]( ITrackerPtr const & tracker ){ 14426return 14427tracker -> nameAndLocation (). location == nameAndLocation . location && 14428tracker -> nameAndLocation (). name == nameAndLocation . name ; 14429} ); 14430return ( it != m_children . end () ) 14431? * it 14432: nullptr ; 14433} 14434ITracker & TrackerBase :: parent () { 14435assert ( m_parent ); // Should always be non-null except for root 14436return * m_parent ; 14437} 14438 14439void TrackerBase :: openChild () { 14440if ( m_runState != ExecutingChildren ) { 14441m_runState = ExecutingChildren ; 14442if ( m_parent ) 14443m_parent -> openChild (); 14444} 14445} 14446 14447bool TrackerBase :: isSectionTracker () const { return false; } 14448bool TrackerBase :: isGeneratorTracker () const { return false; } 14449 14450void TrackerBase :: open () { 14451m_runState = Executing ; 14452moveToThis (); 14453if ( m_parent ) 14454m_parent -> openChild (); 14455} 14456 14457void TrackerBase :: close () { 14458 14459// Close any still open children (e.g. generators) 14460while ( & m_ctx . currentTracker () != this ) 14461m_ctx . currentTracker (). close (); 14462 14463switch ( m_runState ) { 14464case NeedsAnotherRun : 14465break ; 14466 14467case Executing : 14468m_runState = CompletedSuccessfully ; 14469break ; 14470case ExecutingChildren : 14471if ( std :: all_of ( m_children . begin (), m_children . end (), []( ITrackerPtr const & t ){ return t -> isComplete (); }) ) 14472m_runState = CompletedSuccessfully ; 14473break ; 14474 14475case NotStarted : 14476case CompletedSuccessfully : 14477case Failed : 14478CATCH_INTERNAL_ERROR ( "Illogical state: " << m_runState ); 14479 14480default : 14481CATCH_INTERNAL_ERROR ( "Unknown state: " << m_runState ); 14482} 14483moveToParent (); 14484m_ctx . completeCycle (); 14485} 14486void TrackerBase :: fail () { 14487m_runState = Failed ; 14488if ( m_parent ) 14489m_parent -> markAsNeedingAnotherRun (); 14490moveToParent (); 14491m_ctx . completeCycle (); 14492} 14493void TrackerBase :: markAsNeedingAnotherRun () { 14494m_runState = NeedsAnotherRun ; 14495} 14496 14497void TrackerBase :: moveToParent () { 14498assert ( m_parent ); 14499m_ctx . setCurrentTracker ( m_parent ); 14500} 14501void TrackerBase :: moveToThis () { 14502m_ctx . setCurrentTracker ( this ); 14503} 14504 14505SectionTracker :: SectionTracker ( NameAndLocation const & nameAndLocation , TrackerContext & ctx , ITracker * parent ) 14506: TrackerBase ( nameAndLocation , ctx , parent ), 14507m_trimmed_name ( trim ( nameAndLocation . name )) 14508{ 14509if ( parent ) { 14510while ( ! parent -> isSectionTracker () ) 14511parent = & parent -> parent (); 14512 14513SectionTracker & parentSection = static_cast < SectionTracker &> ( * parent ); 14514addNextFilters ( parentSection . m_filters ); 14515} 14516} 14517 14518bool SectionTracker :: isComplete () const { 14519bool complete = true; 14520 14521if (m_filters. empty () 14522|| m_filters [ 0 ] == "" 14523|| std :: find (m_filters. begin (), m_filters. end (), m_trimmed_name) != m_filters . end ()) { 14524complete = TrackerBase :: isComplete (); 14525} 14526return complete; 14527} 14528 14529bool SectionTracker :: isSectionTracker () const { return true; } 14530 14531SectionTracker & SectionTracker :: acquire ( TrackerContext & ctx , NameAndLocation const & nameAndLocation ) { 14532std :: shared_ptr < SectionTracker > section ; 14533 14534ITracker & currentTracker = ctx . currentTracker (); 14535if ( ITrackerPtr childTracker = currentTracker . findChild ( nameAndLocation ) ) { 14536assert ( childTracker ); 14537assert ( childTracker -> isSectionTracker () ); 14538section = std :: static_pointer_cast < SectionTracker > ( childTracker ); 14539} 14540else { 14541section = std :: make_shared < SectionTracker > ( nameAndLocation , ctx , & currentTracker ); 14542currentTracker . addChild ( section ); 14543} 14544if ( ! ctx . completedCycle () ) 14545section -> tryOpen (); 14546return * section ; 14547} 14548 14549void SectionTracker :: tryOpen () { 14550if ( ! isComplete () ) 14551open (); 14552} 14553 14554void SectionTracker :: addInitialFilters ( std:: vector < std :: string > const & filters ) { 14555if ( ! filters . empty () ) { 14556m_filters . reserve ( m_filters . size () + filters . size () + 2 ); 14557m_filters . emplace_back ( "" ); // Root - should never be consulted 14558m_filters . emplace_back ( "" ); // Test Case - not a section filter 14559m_filters . insert ( m_filters . end (), filters . begin (), filters . end () ); 14560} 14561} 14562void SectionTracker :: addNextFilters ( std:: vector < std :: string > const & filters ) { 14563if ( filters . size () > 1 ) 14564m_filters . insert ( m_filters . end (), filters . begin () + 1 , filters . end () ); 14565} 14566 14567std :: vector < std :: string > const & SectionTracker :: getFilters () const { 14568return m_filters ; 14569} 14570 14571std ::string const & SectionTracker :: trimmedName () const { 14572return m_trimmed_name ; 14573} 14574 14575} // namespace TestCaseTracking 14576 14577using TestCaseTracking :: ITracker ; 14578using TestCaseTracking :: TrackerContext ; 14579using TestCaseTracking :: SectionTracker ; 14580 14581} // namespace Catch 14582 14583#if defined( __clang__ ) 14584# pragma clang diagnostic pop 14585#endif 14586// end catch_test_case_tracker.cpp 14587// start catch_test_registry.cpp 14588 14589namespace Catch { 14590 14591auto makeTestInvoker ( void( * testAsFunction)() ) noexcept -> ITestInvoker * { 14592return new ( std :: nothrow ) TestInvokerAsFunction ( testAsFunction ); 14593} 14594 14595NameAndTags :: NameAndTags ( StringRef const & name_ , StringRef const & tags_ ) noexcept : name ( name_ ), tags ( tags_ ) {} 14596 14597AutoReg :: AutoReg ( ITestInvoker * invoker , SourceLineInfo const & lineInfo , StringRef const & classOrMethod , NameAndTags const & nameAndTags ) noexcept { 14598CATCH_TRY { 14599getMutableRegistryHub () 14600. registerTest ( 14601makeTestCase ( 14602invoker , 14603extractClassName ( classOrMethod ), 14604nameAndTags , 14605lineInfo )); 14606} CATCH_CATCH_ALL { 14607// Do not throw when constructing global objects, instead register the exception to be processed later 14608getMutableRegistryHub (). registerStartupException (); 14609} 14610} 14611 14612AutoReg ::~ AutoReg () = default ; 14613} 14614// end catch_test_registry.cpp 14615// start catch_test_spec.cpp 14616 14617#include <algorithm> 14618#include <string> 14619#include <vector> 14620#include <memory> 14621 14622namespace Catch { 14623 14624TestSpec :: Pattern :: Pattern ( std::string const & name ) 14625: m_name ( name ) 14626{} 14627 14628TestSpec :: Pattern ::~ Pattern () = default ; 14629 14630std ::string const & TestSpec :: Pattern :: name () const { 14631return m_name ; 14632} 14633 14634TestSpec :: NamePattern :: NamePattern ( std::string const & name , std ::string const & filterString ) 14635: Pattern ( filterString ) 14636, m_wildcardPattern ( toLower ( name ), CaseSensitive :: No ) 14637{} 14638 14639bool TestSpec :: NamePattern :: matches ( TestCaseInfo const & testCase ) const { 14640return m_wildcardPattern . matches ( testCase . name ); 14641} 14642 14643TestSpec :: TagPattern :: TagPattern ( std::string const & tag , std ::string const & filterString ) 14644: Pattern ( filterString ) 14645, m_tag ( toLower ( tag ) ) 14646{} 14647 14648bool TestSpec :: TagPattern :: matches ( TestCaseInfo const & testCase ) const { 14649return std :: find ( begin ( testCase . lcaseTags ), 14650end ( testCase . lcaseTags ), 14651m_tag ) != end ( testCase . lcaseTags ); 14652} 14653 14654TestSpec :: ExcludedPattern :: ExcludedPattern ( PatternPtr const & underlyingPattern ) 14655: Pattern ( underlyingPattern -> name () ) 14656, m_underlyingPattern ( underlyingPattern ) 14657{} 14658 14659bool TestSpec :: ExcludedPattern :: matches ( TestCaseInfo const & testCase ) const { 14660return ! m_underlyingPattern -> matches ( testCase ); 14661} 14662 14663bool TestSpec :: Filter :: matches ( TestCaseInfo const & testCase ) const { 14664return std :: all_of ( m_patterns . begin (), m_patterns . end (), [ & ]( PatternPtr const & p ){ return p -> matches ( testCase ); } ); 14665} 14666 14667std ::string TestSpec :: Filter :: name () const { 14668std ::string name ; 14669for ( auto const & p : m_patterns ) 14670name += p -> name (); 14671return name ; 14672} 14673 14674bool TestSpec :: hasFilters () const { 14675return ! m_filters . empty (); 14676} 14677 14678bool TestSpec :: matches ( TestCaseInfo const & testCase ) const { 14679return std :: any_of ( m_filters . begin (), m_filters . end (), [ & ]( Filter const & f ){ return f . matches ( testCase ); } ); 14680} 14681 14682TestSpec ::Matches TestSpec :: matchesByFilter ( std:: vector < TestCase > const & testCases , IConfig const & config ) const 14683{ 14684Matches matches ( m_filters. size () ); 14685std :: transform ( m_filters . begin (), m_filters . end (), matches . begin (), [ & ]( Filter const & filter ){ 14686std :: vector < TestCase const *> currentMatches ; 14687for ( auto const & test : testCases ) 14688if ( isThrowSafe ( test, config ) && filter . matches ( test ) ) 14689currentMatches . emplace_back ( & test ); 14690return FilterMatch { filter . name (), currentMatches }; 14691} ); 14692return matches ; 14693} 14694 14695const TestSpec:: vectorStrings & TestSpec :: getInvalidArgs () const { 14696return ( m_invalidArgs ); 14697} 14698 14699} 14700// end catch_test_spec.cpp 14701// start catch_test_spec_parser.cpp 14702 14703namespace Catch { 14704 14705TestSpecParser :: TestSpecParser ( ITagAliasRegistry const & tagAliases ) : m_tagAliases ( & tagAliases ) {} 14706 14707TestSpecParser & TestSpecParser :: parse ( std::string const & arg ) { 14708m_mode = None ; 14709m_exclusion = false; 14710m_arg = m_tagAliases -> expandAliases ( arg ); 14711m_escapeChars . clear (); 14712m_substring . reserve ( m_arg . size ()); 14713m_patternName . reserve ( m_arg . size ()); 14714m_realPatternPos = 0 ; 14715 14716for ( m_pos = 0 ; m_pos < m_arg . size (); ++ m_pos ) 14717//if visitChar fails 14718if ( ! visitChar ( m_arg [ m_pos ] ) ){ 14719m_testSpec . m_invalidArgs . push_back ( arg ); 14720break ; 14721} 14722endMode (); 14723return * this ; 14724} 14725TestSpec TestSpecParser :: testSpec () { 14726addFilter (); 14727return m_testSpec ; 14728} 14729bool TestSpecParser :: visitChar ( char c ) { 14730if ( ( m_mode != EscapedName ) && ( c == '\\' ) ) { 14731escape (); 14732addCharToPattern ( c ); 14733return true; 14734} else if (( m_mode != EscapedName ) && ( c == ',' ) ) { 14735return separate (); 14736} 14737 14738switch ( m_mode ) { 14739case None : 14740if ( processNoneChar ( c ) ) 14741return true; 14742break ; 14743case Name : 14744processNameChar ( c ); 14745break ; 14746case EscapedName : 14747endMode (); 14748addCharToPattern ( c ); 14749return true; 14750default : 14751case Tag : 14752case QuotedName : 14753if ( processOtherChar ( c ) ) 14754return true; 14755break ; 14756} 14757 14758m_substring += c ; 14759if ( ! isControlChar ( c ) ) { 14760m_patternName += c ; 14761m_realPatternPos ++ ; 14762} 14763return true; 14764} 14765// Two of the processing methods return true to signal the caller to return 14766// without adding the given character to the current pattern strings 14767bool TestSpecParser :: processNoneChar ( char c ) { 14768switch ( c ) { 14769case ' ' : 14770return true; 14771case '~' : 14772m_exclusion = true; 14773return false; 14774case '[' : 14775startNewMode ( Tag ); 14776return false; 14777case '"' : 14778startNewMode ( QuotedName ); 14779return false; 14780default : 14781startNewMode ( Name ); 14782return false; 14783} 14784} 14785void TestSpecParser :: processNameChar ( char c ) { 14786if ( c == '[' ) { 14787if ( m_substring == "exclude:" ) 14788m_exclusion = true; 14789else 14790endMode (); 14791startNewMode ( Tag ); 14792} 14793} 14794bool TestSpecParser :: processOtherChar ( char c ) { 14795if ( ! isControlChar ( c ) ) 14796return false; 14797m_substring += c ; 14798endMode (); 14799return true; 14800} 14801void TestSpecParser :: startNewMode ( Mode mode ) { 14802m_mode = mode ; 14803} 14804void TestSpecParser :: endMode () { 14805switch ( m_mode ) { 14806case Name : 14807case QuotedName : 14808return addNamePattern (); 14809case Tag : 14810return addTagPattern (); 14811case EscapedName : 14812revertBackToLastMode (); 14813return ; 14814case None : 14815default : 14816return startNewMode ( None ); 14817} 14818} 14819void TestSpecParser :: escape () { 14820saveLastMode (); 14821m_mode = EscapedName ; 14822m_escapeChars . push_back ( m_realPatternPos ); 14823} 14824bool TestSpecParser :: isControlChar ( char c ) const { 14825switch ( m_mode ) { 14826default : 14827return false; 14828case None : 14829return c == '~' ; 14830case Name : 14831return c == '[' ; 14832case EscapedName : 14833return true; 14834case QuotedName : 14835return c == '"' ; 14836case Tag : 14837return c == '[' || c == ']' ; 14838} 14839} 14840 14841void TestSpecParser :: addFilter () { 14842if ( ! m_currentFilter . m_patterns . empty () ) { 14843m_testSpec . m_filters . push_back ( m_currentFilter ); 14844m_currentFilter = TestSpec :: Filter (); 14845} 14846} 14847 14848void TestSpecParser :: saveLastMode () { 14849lastMode = m_mode ; 14850} 14851 14852void TestSpecParser :: revertBackToLastMode () { 14853m_mode = lastMode ; 14854} 14855 14856bool TestSpecParser :: separate () { 14857if ( ( m_mode == QuotedName ) || ( m_mode == Tag ) ){ 14858//invalid argument, signal failure to previous scope. 14859m_mode = None ; 14860m_pos = m_arg . size (); 14861m_substring . clear (); 14862m_patternName . clear (); 14863m_realPatternPos = 0 ; 14864return false; 14865} 14866endMode (); 14867addFilter (); 14868return true; //success 14869} 14870 14871std ::string TestSpecParser :: preprocessPattern () { 14872std ::string token = m_patternName ; 14873for ( std ::size_t i = 0 ; i < m_escapeChars . size (); ++ i ) 14874token = token . substr ( 0 , m_escapeChars [ i ] - i ) + token . substr ( m_escapeChars [ i ] - i + 1 ); 14875m_escapeChars . clear (); 14876if ( startsWith ( token , "exclude:" )) { 14877m_exclusion = true; 14878token = token . substr ( 8 ); 14879} 14880 14881m_patternName . clear (); 14882m_realPatternPos = 0 ; 14883 14884return token ; 14885} 14886 14887void TestSpecParser :: addNamePattern () { 14888auto token = preprocessPattern (); 14889 14890if (! token . empty ()) { 14891TestSpec ::PatternPtr pattern = std :: make_shared < TestSpec :: NamePattern > ( token , m_substring ); 14892if ( m_exclusion ) 14893pattern = std :: make_shared < TestSpec :: ExcludedPattern > ( pattern ); 14894m_currentFilter . m_patterns . push_back ( pattern ); 14895} 14896m_substring . clear (); 14897m_exclusion = false; 14898m_mode = None ; 14899} 14900 14901void TestSpecParser :: addTagPattern () { 14902auto token = preprocessPattern (); 14903 14904if (! token . empty ()) { 14905// If the tag pattern is the "hide and tag" shorthand (e.g. [.foo]) 14906// we have to create a separate hide tag and shorten the real one 14907if ( token . size () > 1 && token [ 0 ] == '.' ) { 14908token . erase ( token . begin ()); 14909TestSpec ::PatternPtr pattern = std :: make_shared < TestSpec :: TagPattern > ( "." , m_substring ); 14910if ( m_exclusion ) { 14911pattern = std :: make_shared < TestSpec :: ExcludedPattern > ( pattern ); 14912} 14913m_currentFilter . m_patterns . push_back ( pattern ); 14914} 14915 14916TestSpec ::PatternPtr pattern = std :: make_shared < TestSpec :: TagPattern > ( token , m_substring ); 14917 14918if ( m_exclusion ) { 14919pattern = std :: make_shared < TestSpec :: ExcludedPattern > ( pattern ); 14920} 14921m_currentFilter . m_patterns . push_back ( pattern ); 14922} 14923m_substring . clear (); 14924m_exclusion = false; 14925m_mode = None ; 14926} 14927 14928TestSpec parseTestSpec ( std:: string const & arg ) { 14929return TestSpecParser ( ITagAliasRegistry :: get () ). parse ( arg ). testSpec (); 14930} 14931 14932} // namespace Catch 14933// end catch_test_spec_parser.cpp 14934// start catch_timer.cpp 14935 14936#include <chrono> 14937 14938static const uint64_t nanosecondsInSecond = 1000000000 ; 14939 14940namespace Catch { 14941 14942auto getCurrentNanosecondsSinceEpoch () -> uint64_t { 14943return std :: chrono :: duration_cast < std :: chrono :: nanoseconds > ( std::chrono::high_resolution_clock::now().time_since_epoch() ). count (); 14944} 14945 14946namespace { 14947auto estimateClockResolution () -> uint64_t { 14948uint64_t sum = 0 ; 14949static const uint64_t iterations = 1000000 ; 14950 14951auto startTime = getCurrentNanosecondsSinceEpoch (); 14952 14953for ( std::size_t i = 0 ; i < iterations ; ++ i ) { 14954 14955uint64_t ticks ; 14956uint64_t baseTicks = getCurrentNanosecondsSinceEpoch (); 14957do { 14958ticks = getCurrentNanosecondsSinceEpoch (); 14959} while ( ticks == baseTicks ); 14960 14961auto delta = ticks - baseTicks; 14962sum += delta; 14963 14964// If we have been calibrating for over 3 seconds -- the clock 14965// is terrible and we should move on. 14966// TBD: How to signal that the measured resolution is probably wrong? 14967if (ticks > startTime + 3 * nanosecondsInSecond) { 14968return sum / ( i + 1u ); 14969} 14970} 14971 14972// We're just taking the mean, here. To do better we could take the std. dev and exclude outliers 14973// - and potentially do more iterations if there's a high variance. 14974return sum/iterations; 14975} 14976} 14977auto getEstimatedClockResolution() -> uint64_t { 14978static auto s_resolution = estimateClockResolution (); 14979return s_resolution; 14980} 14981 14982void Timer:: start () { 14983m_nanoseconds = getCurrentNanosecondsSinceEpoch (); 14984} 14985auto Timer :: getElapsedNanoseconds () const -> uint64_t { 14986return getCurrentNanosecondsSinceEpoch () - m_nanoseconds; 14987} 14988auto Timer:: getElapsedMicroseconds () const -> uint64_t { 14989return getElapsedNanoseconds ()/ 1000 ; 14990} 14991auto Timer:: getElapsedMilliseconds () const -> unsigned int { 14992return static_cast < unsigned int > ( getElapsedMicroseconds ()/ 1000 ); 14993} 14994auto Timer:: getElapsedSeconds () const -> double { 14995return getElapsedMicroseconds ()/ 1000000.0 ; 14996} 14997 14998} // namespace Catch 14999// end catch_timer.cpp 15000// start catch_tostring.cpp 15001 15002#if defined(__clang__) 15003# pragma clang diagnostic push 15004# pragma clang diagnostic ignored "-Wexit-time-destructors" 15005# pragma clang diagnostic ignored "-Wglobal-constructors" 15006#endif 15007 15008// Enable specific decls locally 15009#if !defined( CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER ) 15010#define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER 15011#endif 15012 15013#include <cmath> 15014#include <iomanip> 15015 15016namespace Catch { 15017 15018namespace Detail { 15019 15020const std ::string unprintableString = "{?}" ; 15021 15022namespace { 15023const int hexThreshold = 255 ; 15024 15025struct Endianness { 15026enum Arch { Big, Little }; 15027 15028static Arch which () { 15029int one = 1 ; 15030// If the lowest byte we read is non-zero, we can assume 15031// that little endian format is used. 15032auto value = * reinterpret_cast < char *> ( & one); 15033return value ? Little : Big; 15034} 15035}; 15036} 15037 15038std :: string rawMemoryToString ( const void * object, std :: size_t size ) { 15039// Reverse order for little endian architectures 15040int i = 0 , end = static_cast < int > ( size ), inc = 1 ; 15041if ( Endianness:: which () == Endianness::Little ) { 15042i = end - 1 ; 15043end = inc = -1 ; 15044} 15045 15046unsigned char const * bytes = static_cast < unsigned char const *> (object); 15047ReusableStringStream rss; 15048rss << "0x" << std:: setfill ( '0' ) << std::hex; 15049for ( ; i != end; i += inc ) 15050rss << std:: setw ( 2 ) << static_cast < unsigned > (bytes[i]); 15051return rss. str (); 15052} 15053} 15054 15055template < typename T > 15056std:: string fpToString ( T value, int precision ) { 15057if (Catch:: isnan (value)) { 15058return "nan" ; 15059} 15060 15061ReusableStringStream rss; 15062rss << std:: setprecision ( precision ) 15063<< std::fixed 15064<< value; 15065std :: string d = rss. str (); 15066std :: size_t i = d. find_last_not_of ( '0' ); 15067if ( i != std::string::npos && i != d. size () - 1 ) { 15068if ( d[i] == '.' ) 15069i ++ ; 15070d = d. substr ( 0 , i + 1 ); 15071} 15072return d; 15073} 15074 15075//// ======================================================= //// 15076// 15077// Out-of-line defs for full specialization of StringMaker 15078// 15079//// ======================================================= //// 15080 15081std:: string StringMaker < std::string > :: convert (const std::string & str) { 15082if (! getCurrentContext (). getConfig () -> showInvisibles ()) { 15083return '"' + str + '"' ; 15084} 15085 15086std :: string s( "\"" ); 15087for ( char c : str) { 15088switch (c) { 15089case '\n' : 15090s. append ( "\\n" ); 15091break ; 15092case '\t' : 15093s. append ( "\\t" ); 15094break ; 15095default : 15096s. push_back (c); 15097break ; 15098} 15099} 15100s. append ( "\"" ); 15101return s; 15102} 15103 15104#ifdef CATCH_CONFIG_CPP17_STRING_VIEW 15105std:: string StringMaker < std::string_view > :: convert (std::string_view str) { 15106return ::Catch::Detail:: stringify (std::string{ str }); 15107} 15108#endif 15109 15110std :: string StringMaker < char const *> :: convert ( char const * str) { 15111if (str) { 15112return ::Catch::Detail:: stringify (std::string{ str }); 15113} else { 15114return { "{null string}" }; 15115} 15116} 15117std:: string StringMaker < char *> :: convert (char * str) { 15118if (str) { 15119return ::Catch::Detail:: stringify (std::string{ str }); 15120} else { 15121return { "{null string}" }; 15122} 15123} 15124 15125#ifdef CATCH_CONFIG_WCHAR 15126std:: string StringMaker < std::wstring > :: convert (const std::wstring & wstr) { 15127std :: string s; 15128s. reserve (wstr. size ()); 15129for (auto c : wstr) { 15130s += ( c <= 0xff ) ? static_cast < char > (c) : '?' ; 15131} 15132return ::Catch::Detail:: stringify (s); 15133} 15134 15135# ifdef CATCH_CONFIG_CPP17_STRING_VIEW 15136std::string StringMaker < std::wstring_view > :: convert (std::wstring_view str) { 15137return StringMaker < std::wstring > :: convert (std:: wstring (str)); 15138} 15139# endif 15140 15141std::string StringMaker < wchar_t const *> ::convert(wchar_t const * str) { 15142if (str) { 15143return ::Catch::Detail::stringify(std::wstring{ str }); 15144} else { 15145return { "{null string}" }; 15146} 15147} 15148std::string StringMaker < wchar_t *> ::convert(wchar_t * str) { 15149if (str) { 15150return ::Catch::Detail::stringify(std::wstring{ str }); 15151} else { 15152return { "{null string}" }; 15153} 15154} 15155#endif 15156 15157#if defined( CATCH_CONFIG_CPP17_BYTE ) 15158#include < cstddef > 15159std::string StringMaker < std::byte > ::convert(std::byte value) { 15160return ::Catch::Detail::stringify(std::to_integer < unsigned long long > (value)); 15161} 15162#endif // defined(CATCH_CONFIG_CPP17_BYTE) 15163 15164std::string StringMaker < int > ::convert( int value) { 15165return ::Catch::Detail::stringify(static_cast < long long > (value)); 15166} 15167std::string StringMaker < long > ::convert(long value) { 15168return ::Catch::Detail::stringify(static_cast < long long > (value)); 15169} 15170std::string StringMaker < long long > ::convert(long long value) { 15171ReusableStringStream rss; 15172rss << value; 15173if (value > Detail::hexThreshold) { 15174rss << " ( 0 x" << std::hex << value << ')'; 15175} 15176return rss.str(); 15177} 15178 15179std::string StringMaker < unsigned int > ::convert(unsigned int value) { 15180return ::Catch::Detail::stringify(static_cast < unsigned long long > (value)); 15181} 15182std::string StringMaker < unsigned long > ::convert(unsigned long value) { 15183return ::Catch::Detail::stringify(static_cast < unsigned long long > (value)); 15184} 15185std::string StringMaker < unsigned long long > ::convert(unsigned long long value) { 15186ReusableStringStream rss; 15187rss << value; 15188if (value > Detail::hexThreshold) { 15189rss << " ( 0 x" << std::hex << value << ')'; 15190} 15191return rss.str(); 15192} 15193 15194std::string StringMaker < bool > ::convert( bool b) { 15195return b ? "true" : "false"; 15196} 15197 15198std::string StringMaker < signed char > ::convert(signed char value) { 15199if (value == '\r') { 15200return "'\\r'" ; 15201} else if (value == '\f' ) { 15202return "'\\f'" ; 15203} else if (value == '\n' ) { 15204return "'\\n'" ; 15205} else if (value == '\t' ) { 15206return "'\\t'" ; 15207} else if ( '\0' <= value && value < ' ' ) { 15208return ::Catch::Detail:: stringify (static_cast < unsigned int > (value)); 15209} else { 15210char chstr[] = "' '" ; 15211chstr[ 1 ] = value; 15212return chstr; 15213} 15214} 15215std::string StringMaker < char > :: convert (char c) { 15216return ::Catch::Detail:: stringify (static_cast < signed char > (c)); 15217} 15218std::string StringMaker < unsigned char > :: convert (unsigned char c) { 15219return ::Catch::Detail:: stringify (static_cast < char > (c)); 15220} 15221 15222std::string StringMaker < std:: nullptr_t > :: convert (std:: nullptr_t ) { 15223return "nullptr" ; 15224} 15225 15226int StringMaker < float > ::precision = 5 ; 15227 15228std::string StringMaker < float > :: convert (float value) { 15229return fpToString (value, precision) + 'f' ; 15230} 15231 15232int StringMaker < double > ::precision = 10 ; 15233 15234std::string StringMaker < double > :: convert (double value) { 15235return fpToString (value, precision); 15236} 15237 15238std::string ratio_string < std::atto > :: symbol () { return "a" ; } 15239std::string ratio_string < std::femto > :: symbol () { return "f" ; } 15240std::string ratio_string < std::pico > :: symbol () { return "p" ; } 15241std::string ratio_string < std::nano > :: symbol () { return "n" ; } 15242std::string ratio_string < std::micro > :: symbol () { return "u" ; } 15243std::string ratio_string < std::milli > :: symbol () { return "m" ; } 15244 15245} // end namespace Catch 15246 15247#if defined(__clang__) 15248# pragma clang diagnostic pop 15249#endif 15250 15251// end catch_tostring.cpp 15252// start catch_totals.cpp 15253 15254namespace Catch { 15255 15256Counts Counts:: operator - ( Counts const & other ) const { 15257Counts diff; 15258diff. passed = passed - other. passed ; 15259diff. failed = failed - other. failed ; 15260diff. failedButOk = failedButOk - other. failedButOk ; 15261return diff; 15262} 15263 15264Counts & Counts::operator += ( Counts const & other ) { 15265passed += other. passed ; 15266failed += other. failed ; 15267failedButOk += other. failedButOk ; 15268return * this; 15269} 15270 15271std :: size_t Counts:: total () const { 15272return passed + failed + failedButOk; 15273} 15274bool Counts:: allPassed () const { 15275return failed == 0 && failedButOk == 0 ; 15276} 15277bool Counts:: allOk () const { 15278return failed == 0 ; 15279} 15280 15281Totals Totals:: operator - ( Totals const & other ) const { 15282Totals diff; 15283diff. assertions = assertions - other. assertions ; 15284diff. testCases = testCases - other. testCases ; 15285return diff; 15286} 15287 15288Totals & Totals::operator += ( Totals const & other ) { 15289assertions += other. assertions ; 15290testCases += other. testCases ; 15291return * this; 15292} 15293 15294Totals Totals:: delta ( Totals const & prevTotals ) const { 15295Totals diff = * this - prevTotals; 15296if ( diff. assertions . failed > 0 ) 15297++ diff. testCases . failed ; 15298else if ( diff. assertions . failedButOk > 0 ) 15299++ diff. testCases . failedButOk ; 15300else 15301++ diff. testCases . passed ; 15302return diff; 15303} 15304 15305} 15306// end catch_totals.cpp 15307// start catch_uncaught_exceptions.cpp 15308 15309// start catch_config_uncaught_exceptions.hpp 15310 15311// Copyright Catch2 Authors 15312// Distributed under the Boost Software License, Version 1.0. 15313// (See accompanying file LICENSE_1_0.txt or copy at 15314// https://www.boost.org/LICENSE_1_0.txt) 15315 15316// SPDX-License-Identifier: BSL-1.0 15317 15318#ifndef CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP 15319#define CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP 15320 15321#if defined( _MSC_VER ) 15322# if _MSC_VER >= 1900 // Visual Studio 2015 or newer 15323# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS 15324# endif 15325#endif 15326 15327#include <exception> 15328 15329#if defined( __cpp_lib_uncaught_exceptions ) \ 15330&& !defined( CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS ) 15331 15332# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS 15333#endif // __cpp_lib_uncaught_exceptions 15334 15335#if defined( CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS ) \ 15336&& !defined( CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS ) \ 15337&& !defined( CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS ) 15338 15339# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS 15340#endif 15341 15342#endif // CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP 15343// end catch_config_uncaught_exceptions.hpp 15344#include <exception> 15345 15346namespace Catch { 15347bool uncaught_exceptions () { 15348#if defined( CATCH_CONFIG_DISABLE_EXCEPTIONS ) 15349return false; 15350#elif defined( CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS ) 15351return std :: uncaught_exceptions () > 0 ; 15352#else 15353return std :: uncaught_exception (); 15354#endif 15355} 15356} // end namespace Catch 15357// end catch_uncaught_exceptions.cpp 15358// start catch_version.cpp 15359 15360#include <ostream> 15361 15362namespace Catch { 15363 15364Version :: Version 15365( unsigned int _majorVersion , 15366unsigned int _minorVersion , 15367unsigned int _patchNumber , 15368char const * const _branchName , 15369unsigned int _buildNumber ) 15370: majorVersion ( _majorVersion ), 15371minorVersion ( _minorVersion ), 15372patchNumber ( _patchNumber ), 15373branchName ( _branchName ), 15374buildNumber ( _buildNumber ) 15375{} 15376 15377std :: ostream & operator << ( std :: ostream & os , Version const & version ) { 15378os << version . majorVersion << '.' 15379<< version . minorVersion << '.' 15380<< version . patchNumber ; 15381// branchName is never null -> 0th char is \0 if it is empty 15382if ( version . branchName [ 0 ]) { 15383os << '-' << version . branchName 15384<< '.' << version . buildNumber ; 15385} 15386return os ; 15387} 15388 15389Version const & libraryVersion () { 15390static Version version ( 2 , 13 , 8 , "" , 0 ); 15391return version ; 15392} 15393 15394} 15395// end catch_version.cpp 15396// start catch_wildcard_pattern.cpp 15397 15398namespace Catch { 15399 15400WildcardPattern :: WildcardPattern ( std :: string const & pattern , 15401CaseSensitive :: Choice caseSensitivity ) 15402: m_caseSensitivity ( caseSensitivity ), 15403m_pattern ( normaliseString ( pattern ) ) 15404{ 15405if( startsWith ( m_pattern , '*' ) ) { 15406m_pattern = m_pattern . substr ( 1 ); 15407m_wildcard = WildcardAtStart ; 15408} 15409if( endsWith ( m_pattern , '*' ) ) { 15410m_pattern = m_pattern . substr ( 0 , m_pattern . size () - 1 ); 15411m_wildcard = static_cast < WildcardPosition > ( m_wildcard | WildcardAtEnd ); 15412} 15413} 15414 15415bool WildcardPattern :: matches ( std :: string const & str ) const { 15416switch( m_wildcard ) { 15417case NoWildcard : 15418return m_pattern == normaliseString ( str ); 15419case WildcardAtStart : 15420return endsWith ( normaliseString ( str ), m_pattern ); 15421case WildcardAtEnd : 15422return startsWith ( normaliseString ( str ), m_pattern ); 15423case WildcardAtBothEnds : 15424return contains ( normaliseString ( str ), m_pattern ); 15425default: 15426CATCH_INTERNAL_ERROR ( "Unknown enum" ); 15427} 15428} 15429 15430std :: string WildcardPattern :: normaliseString ( std :: string const & str ) const { 15431return trim ( m_caseSensitivity == CaseSensitive :: No ? toLower ( str ) : str ); 15432} 15433} 15434// end catch_wildcard_pattern.cpp 15435// start catch_xmlwriter.cpp 15436 15437#include <iomanip> 15438#include <type_traits> 15439 15440namespace Catch { 15441 15442namespace { 15443 15444size_t trailingBytes ( unsigned char c ) { 15445if (( c & 0xE0 ) == 0xC0 ) { 15446return 2 ; 15447} 15448if (( c & 0xF0 ) == 0xE0 ) { 15449return 3 ; 15450} 15451if (( c & 0xF8 ) == 0xF0 ) { 15452return 4 ; 15453} 15454CATCH_INTERNAL_ERROR ( "Invalid multibyte utf-8 start byte encountered" ); 15455} 15456 15457uint32_t headerValue ( unsigned char c ) { 15458if (( c & 0xE0 ) == 0xC0 ) { 15459return c & 0x1F ; 15460} 15461if (( c & 0xF0 ) == 0xE0 ) { 15462return c & 0x0F ; 15463} 15464if (( c & 0xF8 ) == 0xF0 ) { 15465return c & 0x07 ; 15466} 15467CATCH_INTERNAL_ERROR ( "Invalid multibyte utf-8 start byte encountered" ); 15468} 15469 15470void hexEscapeChar ( std :: ostream & os , unsigned char c ) { 15471std :: ios_base :: fmtflags f ( os . flags ()); 15472os << "\\x" 15473<< std :: uppercase << std :: hex << std :: setfill ( '0' ) << std :: setw ( 2 ) 15474<< static_cast < int > ( c ); 15475os . flags ( f ); 15476} 15477 15478bool shouldNewline ( XmlFormatting fmt ) { 15479return !!( static_cast < std :: underlying_type < XmlFormatting > :: type > ( fmt & XmlFormatting :: Newline )); 15480} 15481 15482bool shouldIndent ( XmlFormatting fmt ) { 15483return !!( static_cast < std :: underlying_type < XmlFormatting > :: type > ( fmt & XmlFormatting :: Indent )); 15484} 15485 15486} // anonymous namespace 15487 15488XmlFormatting operator | ( XmlFormatting lhs , XmlFormatting rhs ) { 15489return static_cast < XmlFormatting > ( 15490static_cast < std :: underlying_type < XmlFormatting > :: type > ( lhs ) | 15491static_cast < std :: underlying_type < XmlFormatting > :: type > ( rhs ) 15492); 15493} 15494 15495XmlFormatting operator & ( XmlFormatting lhs , XmlFormatting rhs ) { 15496return static_cast < XmlFormatting > ( 15497static_cast < std :: underlying_type < XmlFormatting > :: type > ( lhs ) & 15498static_cast < std :: underlying_type < XmlFormatting > :: type > ( rhs ) 15499); 15500} 15501 15502XmlEncode :: XmlEncode ( std :: string const & str , ForWhat forWhat ) 15503: m_str ( str ), 15504m_forWhat ( forWhat ) 15505{} 15506 15507void XmlEncode :: encodeTo ( std :: ostream & os ) const { 15508// Apostrophe escaping not necessary if we always use " to write attributes 15509// (see: http://www.w3.org/TR/xml/#syntax) 15510 15511for( std :: size_t idx = 0 ; idx < m_str . size (); ++ idx ) { 15512unsigned char c = m_str [ idx ]; 15513switch ( c ) { 15514case '<' : os << "<" ; break; 15515case '&' : os << "&" ; break; 15516 15517case '>' : 15518// See: http://www.w3.org/TR/xml/#syntax 15519if ( idx > 2 && m_str [ idx - 1 ] == ']' && m_str [ idx - 2 ] == ']' ) 15520os << ">" ; 15521else 15522os << c ; 15523break; 15524 15525case '\"' : 15526if ( m_forWhat == ForAttributes ) 15527os << """ ; 15528else 15529os << c ; 15530break; 15531 15532default: 15533// Check for control characters and invalid utf-8 15534 15535// Escape control characters in standard ascii 15536// see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0 15537if ( c < 0x09 || ( c > 0x0D && c < 0x20 ) || c == 0x7F ) { 15538hexEscapeChar ( os , c ); 15539break; 15540} 15541 15542// Plain ASCII: Write it to stream 15543if ( c < 0x7F ) { 15544os << c ; 15545break; 15546} 15547 15548// UTF-8 territory 15549// Check if the encoding is valid and if it is not, hex escape bytes. 15550// Important: We do not check the exact decoded values for validity, only the encoding format 15551// First check that this bytes is a valid lead byte: 15552// This means that it is not encoded as 1111 1XXX 15553// Or as 10XX XXXX 15554if ( c < 0xC0 || 15555c >= 0xF8 ) { 15556hexEscapeChar ( os , c ); 15557break; 15558} 15559 15560auto encBytes = trailingBytes ( c ); 15561// Are there enough bytes left to avoid accessing out-of-bounds memory? 15562if ( idx + encBytes - 1 >= m_str . size ()) { 15563hexEscapeChar ( os , c ); 15564break; 15565} 15566// The header is valid, check data 15567// The next encBytes bytes must together be a valid utf-8 15568// This means: bitpattern 10XX XXXX and the extracted value is sane (ish) 15569bool valid = true; 15570uint32_t value = headerValue ( c ); 15571for ( std :: size_t n = 1 ; n < encBytes ; ++ n ) { 15572unsigned char nc = m_str [ idx + n ]; 15573valid &= (( nc & 0xC0 ) == 0x80 ); 15574value = ( value << 6 ) | ( nc & 0x3F ); 15575} 15576 15577if ( 15578// Wrong bit pattern of following bytes 15579(! valid ) || 15580// Overlong encodings 15581( value < 0x80 ) || 15582( 0x80 <= value && value < 0x800 && encBytes > 2 ) || 15583( 0x800 < value && value < 0x10000 && encBytes > 3 ) || 15584// Encoded value out of range 15585( value >= 0x110000 ) 15586) { 15587hexEscapeChar ( os , c ); 15588break; 15589} 15590 15591// If we got here, this is in fact a valid(ish) utf-8 sequence 15592for ( std :: size_t n = 0 ; n < encBytes ; ++ n ) { 15593os << m_str [ idx + n ]; 15594} 15595idx += encBytes - 1 ; 15596break; 15597} 15598} 15599} 15600 15601std :: ostream & operator << ( std :: ostream & os , XmlEncode const & xmlEncode ) { 15602xmlEncode . encodeTo ( os ); 15603return os ; 15604} 15605 15606XmlWriter :: ScopedElement :: ScopedElement ( XmlWriter * writer , XmlFormatting fmt ) 15607: m_writer ( writer ), 15608m_fmt ( fmt ) 15609{} 15610 15611XmlWriter :: ScopedElement :: ScopedElement ( ScopedElement && other ) noexcept 15612: m_writer ( other . m_writer ), 15613m_fmt ( other . m_fmt ) 15614{ 15615other . m_writer = nullptr ; 15616other . m_fmt = XmlFormatting :: None ; 15617} 15618XmlWriter :: ScopedElement & XmlWriter :: ScopedElement :: operator = ( ScopedElement && other ) noexcept { 15619if ( m_writer ) { 15620m_writer -> endElement (); 15621} 15622m_writer = other . m_writer ; 15623other . m_writer = nullptr ; 15624m_fmt = other . m_fmt ; 15625other . m_fmt = XmlFormatting :: None ; 15626return * this ; 15627} 15628 15629XmlWriter :: ScopedElement ::~ ScopedElement () { 15630if ( m_writer ) { 15631m_writer -> endElement ( m_fmt ); 15632} 15633} 15634 15635XmlWriter :: ScopedElement & XmlWriter :: ScopedElement :: writeText ( std :: string const & text , XmlFormatting fmt ) { 15636m_writer -> writeText ( text , fmt ); 15637return * this ; 15638} 15639 15640XmlWriter :: XmlWriter ( std :: ostream & os ) : m_os ( os ) 15641{ 15642writeDeclaration (); 15643} 15644 15645XmlWriter ::~ XmlWriter () { 15646while (! m_tags . empty ()) { 15647endElement (); 15648} 15649newlineIfNecessary (); 15650} 15651 15652XmlWriter & XmlWriter :: startElement ( std :: string const & name , XmlFormatting fmt ) { 15653ensureTagClosed (); 15654newlineIfNecessary (); 15655if ( shouldIndent ( fmt )) { 15656m_os << m_indent ; 15657m_indent += " " ; 15658} 15659m_os << '<' << name ; 15660m_tags . push_back ( name ); 15661m_tagIsOpen = true; 15662applyFormatting ( fmt ); 15663return * this ; 15664} 15665 15666XmlWriter :: ScopedElement XmlWriter :: scopedElement ( std :: string const & name , XmlFormatting fmt ) { 15667ScopedElement scoped ( this , fmt ); 15668startElement ( name , fmt ); 15669return scoped ; 15670} 15671 15672XmlWriter & XmlWriter :: endElement ( XmlFormatting fmt ) { 15673m_indent = m_indent . substr ( 0 , m_indent . size () - 2 ); 15674 15675if( m_tagIsOpen ) { 15676m_os << "/>" ; 15677m_tagIsOpen = false; 15678} else { 15679newlineIfNecessary (); 15680if ( shouldIndent ( fmt )) { 15681m_os << m_indent ; 15682} 15683m_os << "</" << m_tags . back () << ">" ; 15684} 15685m_os << std :: flush ; 15686applyFormatting ( fmt ); 15687m_tags . pop_back (); 15688return * this ; 15689} 15690 15691XmlWriter & XmlWriter :: writeAttribute ( std :: string const & name , std :: string const & attribute ) { 15692if( ! name . empty () && ! attribute . empty () ) 15693m_os << ' ' << name << "=\"" << XmlEncode ( attribute , XmlEncode :: ForAttributes ) << '"' ; 15694return * this ; 15695} 15696 15697XmlWriter & XmlWriter :: writeAttribute ( std :: string const & name , bool attribute ) { 15698m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"' ; 15699return * this ; 15700} 15701 15702XmlWriter & XmlWriter :: writeText ( std :: string const & text , XmlFormatting fmt ) { 15703if( ! text . empty () ){ 15704bool tagWasOpen = m_tagIsOpen ; 15705ensureTagClosed (); 15706if ( tagWasOpen && shouldIndent ( fmt )) { 15707m_os << m_indent ; 15708} 15709m_os << XmlEncode ( text ); 15710applyFormatting ( fmt ); 15711} 15712return * this ; 15713} 15714 15715XmlWriter & XmlWriter :: writeComment ( std :: string const & text , XmlFormatting fmt ) { 15716ensureTagClosed (); 15717if ( shouldIndent ( fmt )) { 15718m_os << m_indent ; 15719} 15720m_os << "<!--" << text << "-->" ; 15721applyFormatting ( fmt ); 15722return * this ; 15723} 15724 15725void XmlWriter :: writeStylesheetRef ( std :: string const & url ) { 15726m_os << "<?xml-stylesheet type=\"text/xsl\" href=\"" << url << "\"?>\n" ; 15727} 15728 15729XmlWriter & XmlWriter :: writeBlankLine () { 15730ensureTagClosed (); 15731m_os << '\n' ; 15732return * this ; 15733} 15734 15735void XmlWriter :: ensureTagClosed () { 15736if( m_tagIsOpen ) { 15737m_os << '>' << std :: flush ; 15738newlineIfNecessary (); 15739m_tagIsOpen = false; 15740} 15741} 15742 15743void XmlWriter :: applyFormatting ( XmlFormatting fmt ) { 15744m_needsNewline = shouldNewline ( fmt ); 15745} 15746 15747void XmlWriter :: writeDeclaration () { 15748m_os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" ; 15749} 15750 15751void XmlWriter :: newlineIfNecessary () { 15752if( m_needsNewline ) { 15753m_os << std :: endl ; 15754m_needsNewline = false; 15755} 15756} 15757} 15758// end catch_xmlwriter.cpp 15759// start catch_reporter_bases.cpp 15760 15761#include <cstring> 15762#include <cfloat> 15763#include <cstdio> 15764#include <cassert> 15765#include <memory> 15766 15767namespace Catch { 15768void prepareExpandedExpression ( AssertionResult & result ) { 15769result . getExpandedExpression (); 15770} 15771 15772// Because formatting using c++ streams is stateful, drop down to C is required 15773// Alternatively we could use stringstream, but its performance is... not good. 15774std :: string getFormattedDuration ( double duration ) { 15775// Max exponent + 1 is required to represent the whole part 15776// + 1 for decimal point 15777// + 3 for the 3 decimal places 15778// + 1 for null terminator 15779const std :: size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1 ; 15780char buffer [ maxDoubleSize ]; 15781 15782// Save previous errno, to prevent sprintf from overwriting it 15783ErrnoGuard guard ; 15784#ifdef _MSC_VER 15785sprintf_s ( buffer , "%.3f" , duration ); 15786#else 15787std :: sprintf ( buffer , "%.3f" , duration ); 15788#endif 15789return std :: string ( buffer ); 15790} 15791 15792bool shouldShowDuration ( IConfig const & config , double duration ) { 15793if ( config . showDurations () == ShowDurations :: Always ) { 15794return true; 15795} 15796if ( config . showDurations () == ShowDurations :: Never ) { 15797return false; 15798} 15799const double min = config . minDuration (); 15800return min >= 0 && duration >= min ; 15801} 15802 15803std :: string serializeFilters ( std :: vector < std :: string > const & container ) { 15804ReusableStringStream oss ; 15805bool first = true; 15806for (auto && filter : container ) 15807{ 15808if (! first ) 15809oss << ' '; 15810else 15811first = false; 15812 15813oss << filter ; 15814} 15815return oss . str (); 15816} 15817 15818TestEventListenerBase :: TestEventListenerBase ( ReporterConfig const & _config ) 15819: StreamingReporterBase ( _config ) {} 15820 15821std :: set < Verbosity > TestEventListenerBase :: getSupportedVerbosities () { 15822return { Verbosity :: Quiet , Verbosity :: Normal , Verbosity :: High }; 15823} 15824 15825void TestEventListenerBase :: assertionStarting ( AssertionInfo const & ) {} 15826 15827bool TestEventListenerBase :: assertionEnded ( AssertionStats const & ) { 15828return false; 15829} 15830 15831} // end namespace Catch 15832// end catch_reporter_bases.cpp 15833// start catch_reporter_compact.cpp 15834 15835namespace { 15836 15837#ifdef CATCH_PLATFORM_MAC 15838const char * failedString () { return "FAILED" ; } 15839const char * passedString () { return "PASSED" ; } 15840#else 15841const char * failedString () { return "failed" ; } 15842const char * passedString () { return "passed" ; } 15843#endif 15844 15845// Colour::LightGrey 15846Catch :: Colour :: Code dimColour () { return Catch :: Colour :: FileName ; } 15847 15848std :: string bothOrAll ( std :: size_t count ) { 15849return count == 1 ? std :: string () : 15850count == 2 ? "both " : "all " ; 15851} 15852 15853} // anon namespace 15854 15855namespace Catch { 15856namespace { 15857// Colour, message variants: 15858// - white: No tests ran. 15859// - red: Failed [both/all] N test cases, failed [both/all] M assertions. 15860// - white: Passed [both/all] N test cases (no assertions). 15861// - red: Failed N tests cases, failed M assertions. 15862// - green: Passed [both/all] N tests cases with M assertions. 15863void printTotals ( std :: ostream & out , const Totals & totals ) { 15864if ( totals . testCases . total () == 0 ) { 15865out << "No tests ran." ; 15866} else if ( totals . testCases . failed == totals . testCases . total ()) { 15867Colour colour ( Colour :: ResultError ); 15868const std :: string qualify_assertions_failed = 15869totals . assertions . failed == totals . assertions . total () ? 15870bothOrAll ( totals . assertions . failed ) : std :: string (); 15871out << 15872"Failed " << bothOrAll ( totals . testCases . failed ) 15873<< pluralise ( totals . testCases . failed , "test case" ) << ", " 15874"failed " << qualify_assertions_failed << 15875pluralise ( totals . assertions . failed , "assertion" ) << '.' ; 15876} else if ( totals . assertions . total () == 0 ) { 15877out << 15878"Passed " << bothOrAll ( totals . testCases . total ()) 15879<< pluralise ( totals . testCases . total (), "test case" ) 15880<< " (no assertions)." ; 15881} else if ( totals . assertions . failed ) { 15882Colour colour ( Colour :: ResultError ); 15883out << 15884"Failed " << pluralise ( totals . testCases . failed , "test case" ) << ", " 15885"failed " << pluralise ( totals . assertions . failed , "assertion" ) << '.' ; 15886} else { 15887Colour colour ( Colour :: ResultSuccess ); 15888out << 15889"Passed " << bothOrAll ( totals . testCases . passed ) 15890<< pluralise ( totals . testCases . passed , "test case" ) << 15891" with " << pluralise ( totals . assertions . passed , "assertion" ) << '.' ; 15892} 15893} 15894 15895// Implementation of CompactReporter formatting 15896class AssertionPrinter { 15897public : 15898AssertionPrinter & operator = ( AssertionPrinter const & ) = delete ; 15899AssertionPrinter ( AssertionPrinter const & ) = delete ; 15900AssertionPrinter ( std :: ostream & _stream , AssertionStats const & _stats , bool _printInfoMessages ) 15901: stream ( _stream ) 15902, result ( _stats . assertionResult ) 15903, messages ( _stats . infoMessages ) 15904, itMessage ( _stats . infoMessages . begin ()) 15905, printInfoMessages ( _printInfoMessages ) {} 15906 15907void () { 15908printSourceInfo (); 15909 15910itMessage = messages . begin (); 15911 15912switch ( result . getResultType ()) { 15913case ResultWas :: Ok : 15914printResultType ( Colour :: ResultSuccess , passedString ()); 15915printOriginalExpression (); 15916printReconstructedExpression (); 15917if (! result . hasExpression ()) 15918printRemainingMessages ( Colour :: None ); 15919else 15920printRemainingMessages (); 15921break; 15922case ResultWas :: ExpressionFailed : 15923if ( result . isOk ()) 15924printResultType ( Colour :: ResultSuccess , failedString () + std :: string ( " - but was ok" )); 15925else 15926printResultType ( Colour :: Error , failedString ()); 15927printOriginalExpression (); 15928printReconstructedExpression (); 15929printRemainingMessages (); 15930break; 15931case ResultWas :: ThrewException : 15932printResultType ( Colour :: Error , failedString ()); 15933printIssue ( "unexpected exception with message:" ); 15934printMessage (); 15935printExpressionWas (); 15936printRemainingMessages (); 15937break; 15938case ResultWas :: FatalErrorCondition : 15939printResultType ( Colour :: Error , failedString ()); 15940printIssue ( "fatal error condition with message:" ); 15941printMessage (); 15942printExpressionWas (); 15943printRemainingMessages (); 15944break; 15945case ResultWas :: DidntThrowException : 15946printResultType ( Colour :: Error , failedString ()); 15947printIssue ( "expected exception, got none" ); 15948printExpressionWas (); 15949printRemainingMessages (); 15950break; 15951case ResultWas :: Info : 15952printResultType ( Colour :: None , "info" ); 15953printMessage (); 15954printRemainingMessages (); 15955break; 15956case ResultWas :: Warning : 15957printResultType ( Colour :: None , "warning" ); 15958printMessage (); 15959printRemainingMessages (); 15960break; 15961case ResultWas :: ExplicitFailure : 15962printResultType ( Colour :: Error , failedString ()); 15963printIssue ( "explicitly" ); 15964printRemainingMessages ( Colour :: None ) ; 15965break ; 15966// These cases are here to prevent compiler warnings 15967case ResultWas:: Unknown : 15968case ResultWas:: FailureBit : 15969case ResultWas:: Exception : 15970printResultType ( Colour ::Error, "** internal error **" ); 15971break ; 15972} 15973} 15974 15975private : 15976void printSourceInfo () const { 15977Colour colourGuard ( Colour ::FileName); 15978stream << result. getSourceInfo () << ':' ; 15979} 15980 15981void printResultType ( Colour ::Code colour, std ::string const & passOrFail) const { 15982if (!passOrFail. empty ()) { 15983{ 15984Colour colourGuard ( colour ); 15985stream << ' ' << passOrFail; 15986} 15987stream << ':' ; 15988} 15989} 15990 15991void printIssue ( std ::string const & issue) const { 15992stream << ' ' << issue; 15993} 15994 15995void printExpressionWas () { 15996if (result. hasExpression ()) { 15997stream << ';' ; 15998{ 15999Colour colour ( dimColour ()); 16000stream << " expression was:" ; 16001} 16002printOriginalExpression (); 16003} 16004} 16005 16006void printOriginalExpression () const { 16007if (result. hasExpression ()) { 16008stream << ' ' << result. getExpression (); 16009} 16010} 16011 16012void printReconstructedExpression () const { 16013if (result. hasExpandedExpression ()) { 16014{ 16015Colour colour ( dimColour ()); 16016stream << " for: " ; 16017} 16018stream << result. getExpandedExpression (); 16019} 16020} 16021 16022void printMessage () { 16023if (itMessage != messages. end ()) { 16024stream << " '" << itMessage -> message << '\'' ; 16025++ itMessage; 16026} 16027} 16028 16029void printRemainingMessages ( Colour ::Code colour = dimColour ()) { 16030if (itMessage == messages. end ()) 16031return; 16032 16033const auto itEnd = messages. cend (); 16034const auto N = static_cast < std:: size_t > (std:: distance (itMessage, itEnd)); 16035 16036{ 16037Colour colourGuard ( colour ); 16038stream << " with " << pluralise ( N , "message" ) << ':' ; 16039} 16040 16041while (itMessage != itEnd) { 16042// If this assertion is a warning ignore any INFO messages 16043if (printInfoMessages || itMessage -> type != ResultWas::Info) { 16044printMessage (); 16045if (itMessage != itEnd) { 16046Colour colourGuard ( dimColour ()); 16047stream << " and" ; 16048} 16049continue ; 16050} 16051++ itMessage; 16052} 16053} 16054 16055private : 16056std ::ostream & stream; 16057AssertionResult const & result; 16058std ::vector < MessageInfo > messages; 16059std ::vector < MessageInfo > :: const_iterator itMessage; 16060bool printInfoMessages; 16061}; 16062 16063} // anon namespace 16064 16065std :: string CompactReporter:: getDescription () { 16066return "Reports test results on a single line, suitable for IDEs" ; 16067} 16068 16069void CompactReporter:: noMatchingTestCases ( std ::string const & spec ) { 16070stream << "No test cases matched '" << spec << '\'' << std::endl; 16071} 16072 16073void CompactReporter:: assertionStarting ( AssertionInfo const & ) {} 16074 16075bool CompactReporter:: assertionEnded ( AssertionStats const & _assertionStats ) { 16076AssertionResult const & result = _assertionStats. assertionResult ; 16077 16078bool printInfoMessages = true; 16079 16080// Drop out if result was successful and we're not printing those 16081if ( !m_config -> includeSuccessfulResults () && result. isOk () ) { 16082if ( result. getResultType () != ResultWas::Warning ) 16083return false; 16084printInfoMessages = false; 16085} 16086 16087AssertionPrinter printer ( stream , _assertionStats , printInfoMessages ); 16088printer. (); 16089 16090stream << std::endl; 16091return true; 16092} 16093 16094void CompactReporter:: sectionEnded ( SectionStats const & _sectionStats) { 16095double dur = _sectionStats. durationInSeconds ; 16096if ( shouldShowDuration ( * m_config, dur ) ) { 16097stream << getFormattedDuration ( dur ) << " s: " << _sectionStats. sectionInfo . name << std::endl; 16098} 16099} 16100 16101void CompactReporter:: testRunEnded ( TestRunStats const & _testRunStats ) { 16102printTotals ( stream, _testRunStats. totals ); 16103stream << '\n' << std::endl; 16104StreamingReporterBase :: testRunEnded ( _testRunStats ); 16105} 16106 16107CompactReporter ::~ CompactReporter () {} 16108 16109CATCH_REGISTER_REPORTER ( "compact" , CompactReporter ) 16110 16111} // end namespace Catch 16112// end catch_reporter_compact.cpp 16113// start catch_reporter_console.cpp 16114 16115#include <cfloat> 16116#include <cstdio> 16117 16118#if defined(_MSC_VER) 16119#pragma warning(push) 16120#pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch 16121// Note that 4062 (not all labels are handled and default is missing) is enabled 16122#endif 16123 16124#if defined(__clang__) 16125# pragma clang diagnostic push 16126// For simplicity, benchmarking-only helpers are always enabled 16127# pragma clang diagnostic ignored "-Wunused-function" 16128#endif 16129 16130namespace Catch { 16131 16132namespace { 16133 16134// Formatter impl for ConsoleReporter 16135class ConsoleAssertionPrinter { 16136public : 16137ConsoleAssertionPrinter & operator = ( ConsoleAssertionPrinter const & ) = delete; 16138ConsoleAssertionPrinter( ConsoleAssertionPrinter const & ) = delete; 16139ConsoleAssertionPrinter ( std ::ostream & _stream, AssertionStats const & _stats, bool _printInfoMessages) 16140: stream (_stream), 16141stats (_stats), 16142result (_stats. assertionResult ), 16143colour (Colour::None), 16144message (result. getMessage ()), 16145messages (_stats. infoMessages ), 16146printInfoMessages (_printInfoMessages) { 16147switch (result. getResultType ()) { 16148case ResultWas::Ok: 16149colour = Colour::Success; 16150passOrFail = "PASSED" ; 16151//if( result.hasMessage() ) 16152if (_stats. infoMessages . size () == 1 ) 16153messageLabel = "with message" ; 16154if (_stats. infoMessages . size () > 1 ) 16155messageLabel = "with messages" ; 16156break ; 16157case ResultWas:: ExpressionFailed : 16158if (result. isOk ()) { 16159colour = Colour::Success; 16160passOrFail = "FAILED - but was ok" ; 16161} else { 16162colour = Colour::Error; 16163passOrFail = "FAILED" ; 16164} 16165if (_stats. infoMessages . size () == 1 ) 16166messageLabel = "with message" ; 16167if (_stats. infoMessages . size () > 1 ) 16168messageLabel = "with messages" ; 16169break ; 16170case ResultWas:: ThrewException : 16171colour = Colour::Error; 16172passOrFail = "FAILED" ; 16173messageLabel = "due to unexpected exception with " ; 16174if (_stats. infoMessages . size () == 1 ) 16175messageLabel += "message" ; 16176if (_stats. infoMessages . size () > 1 ) 16177messageLabel += "messages" ; 16178break ; 16179case ResultWas:: FatalErrorCondition : 16180colour = Colour::Error; 16181passOrFail = "FAILED" ; 16182messageLabel = "due to a fatal error condition" ; 16183break ; 16184case ResultWas:: DidntThrowException : 16185colour = Colour::Error; 16186passOrFail = "FAILED" ; 16187messageLabel = "because no exception was thrown where one was expected" ; 16188break ; 16189case ResultWas:: Info : 16190messageLabel = "info" ; 16191break ; 16192case ResultWas:: Warning : 16193messageLabel = "warning" ; 16194break ; 16195case ResultWas:: ExplicitFailure : 16196passOrFail = "FAILED" ; 16197colour = Colour::Error; 16198if (_stats. infoMessages . size () == 1 ) 16199messageLabel = "explicitly with message" ; 16200if (_stats. infoMessages . size () > 1 ) 16201messageLabel = "explicitly with messages" ; 16202break ; 16203// These cases are here to prevent compiler warnings 16204case ResultWas:: Unknown : 16205case ResultWas:: FailureBit : 16206case ResultWas:: Exception : 16207passOrFail = "** internal error **" ; 16208colour = Colour::Error; 16209break ; 16210} 16211} 16212 16213void () const { 16214printSourceInfo (); 16215if (stats. totals . assertions . total () > 0 ) { 16216printResultType (); 16217printOriginalExpression (); 16218printReconstructedExpression (); 16219} else { 16220stream << '\n' ; 16221} 16222printMessage (); 16223} 16224 16225private : 16226void printResultType () const { 16227if (!passOrFail. empty ()) { 16228Colour colourGuard ( colour ); 16229stream << passOrFail << ":\n" ; 16230} 16231} 16232void printOriginalExpression () const { 16233if (result. hasExpression ()) { 16234Colour colourGuard ( Colour ::OriginalExpression); 16235stream << " " ; 16236stream << result. getExpressionInMacro (); 16237stream << '\n' ; 16238} 16239} 16240void printReconstructedExpression () const { 16241if (result. hasExpandedExpression ()) { 16242stream << "with expansion:\n" ; 16243Colour colourGuard ( Colour ::ReconstructedExpression); 16244stream << Column (result. getExpandedExpression ()). indent ( 2 ) << '\n' ; 16245} 16246} 16247void printMessage () const { 16248if (!messageLabel. empty ()) 16249stream << messageLabel << ':' << '\n' ; 16250for (auto const & msg : messages ) { 16251// If this assertion is a warning ignore any INFO messages 16252if ( printInfoMessages || msg.type != ResultWas::Info) 16253stream << Column (msg.message). indent ( 2 ) << '\n' ; 16254} 16255} 16256void printSourceInfo () const { 16257Colour colourGuard ( Colour ::FileName); 16258stream << result. getSourceInfo () << ": " ; 16259} 16260 16261std::ostream & stream; 16262AssertionStats const & stats; 16263AssertionResult const & result; 16264Colour::Code colour; 16265std::string passOrFail; 16266std::string messageLabel; 16267std::string message; 16268std::vector < MessageInfo > messages; 16269bool printInfoMessages; 16270}; 16271 16272std:: size_t makeRatio (std:: size_t number, std:: size_t total) { 16273std:: size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number / total : 0 ; 16274return (ratio == 0 && number > 0 ) ? 1 : ratio; 16275} 16276 16277std:: size_t & findMax (std:: size_t & i, std:: size_t & j, std:: size_t & k) { 16278if (i > j && i > k) 16279return i; 16280else if (j > k) 16281return j; 16282else 16283return k; 16284} 16285 16286struct ColumnInfo { 16287enum Justification { Left, Right }; 16288std::string name; 16289int width; 16290Justification justification; 16291}; 16292struct ColumnBreak {}; 16293struct RowBreak {}; 16294 16295class Duration { 16296enum class Unit { 16297Auto, 16298Nanoseconds, 16299Microseconds, 16300Milliseconds, 16301Seconds, 16302Minutes 16303}; 16304static const uint64_t s_nanosecondsInAMicrosecond = 1000 ; 16305static const uint64_t s_nanosecondsInAMillisecond = 1000 * s_nanosecondsInAMicrosecond; 16306static const uint64_t s_nanosecondsInASecond = 1000 * s_nanosecondsInAMillisecond; 16307static const uint64_t s_nanosecondsInAMinute = 60 * s_nanosecondsInASecond; 16308 16309double m_inNanoseconds; 16310Unit m_units; 16311 16312public: 16313explicit Duration( double inNanoseconds, Unit units = Unit::Auto) 16314: m_inNanoseconds (inNanoseconds), 16315m_units (units) { 16316if (m_units == Unit::Auto) { 16317if (m_inNanoseconds < s_nanosecondsInAMicrosecond) 16318m_units = Unit::Nanoseconds; 16319else if (m_inNanoseconds < s_nanosecondsInAMillisecond) 16320m_units = Unit::Microseconds; 16321else if (m_inNanoseconds < s_nanosecondsInASecond) 16322m_units = Unit::Milliseconds; 16323else if (m_inNanoseconds < s_nanosecondsInAMinute) 16324m_units = Unit::Seconds; 16325else 16326m_units = Unit::Minutes; 16327} 16328 16329} 16330 16331auto value() const -> double { 16332switch (m_units) { 16333case Unit:: Microseconds : 16334return m_inNanoseconds / static_cast < double > (s_nanosecondsInAMicrosecond); 16335case Unit:: Milliseconds : 16336return m_inNanoseconds / static_cast < double > (s_nanosecondsInAMillisecond); 16337case Unit:: Seconds : 16338return m_inNanoseconds / static_cast < double > (s_nanosecondsInASecond); 16339case Unit:: Minutes : 16340return m_inNanoseconds / static_cast < double > (s_nanosecondsInAMinute); 16341default : 16342return m_inNanoseconds; 16343} 16344} 16345auto unitsAsString() const -> std ::string { 16346switch (m_units) { 16347case Unit:: Nanoseconds : 16348return "ns" ; 16349case Unit:: Microseconds : 16350return "us" ; 16351case Unit:: Milliseconds : 16352return "ms" ; 16353case Unit:: Seconds : 16354return "s" ; 16355case Unit:: Minutes : 16356return "m" ; 16357default : 16358return "** internal error **" ; 16359} 16360 16361} 16362friend auto operator << ( std ::ostream & os, Duration const & duration) -> std::ostream & { 16363return os << duration. value () << ' ' << duration. unitsAsString (); 16364} 16365}; 16366} // end anon namespace 16367 16368class TablePrinter { 16369std ::ostream & m_os; 16370std ::vector < ColumnInfo > m_columnInfos; 16371std :: ostringstream m_oss; 16372int m_currentColumn = -1 ; 16373bool m_isOpen = false; 16374 16375public : 16376TablePrinter ( std ::ostream & os, std::vector < ColumnInfo > columnInfos ) 16377: m_os ( os ), 16378m_columnInfos ( std:: move ( columnInfos ) ) {} 16379 16380auto columnInfos() const -> std :: vector < ColumnInfo > const & { 16381return m_columnInfos ; 16382} 16383 16384void open () { 16385if (!m_isOpen) { 16386m_isOpen = true; 16387* this << RowBreak (); 16388 16389Columns headerCols; 16390Spacer spacer ( 2 ); 16391for (auto const & info : m_columnInfos) { 16392headerCols += Column ( info .name). width (static_cast < std:: size_t > (info.width - 2 )); 16393headerCols += spacer; 16394} 16395m_os << headerCols << '\n' ; 16396 16397m_os << Catch::getLineOfChars < '-' > () << '\n' ; 16398} 16399} 16400void close () { 16401if (m_isOpen) { 16402* this << RowBreak (); 16403m_os << std::endl; 16404m_isOpen = false; 16405} 16406} 16407 16408template < typename T > 16409friend TablePrinter & operator << (TablePrinter & tp, T const & value) { 16410tp. m_oss << value; 16411return tp; 16412} 16413 16414friend TablePrinter & operator << (TablePrinter & tp, ColumnBreak) { 16415auto colStr = tp. m_oss . str (); 16416const auto strSize = colStr. size (); 16417tp. m_oss . str ( "" ); 16418tp. open (); 16419if (tp. m_currentColumn == static_cast < int > (tp. m_columnInfos . size () - 1 )) { 16420tp. m_currentColumn = -1 ; 16421tp. m_os << '\n' ; 16422} 16423tp. m_currentColumn ++ ; 16424 16425auto colInfo = tp. m_columnInfos [tp. m_currentColumn ]; 16426auto padding = (strSize + 1 < static_cast < std:: size_t > (colInfo. width )) 16427? std:: string (colInfo. width - (strSize + 1 ), ' ' ) 16428: std:: string (); 16429if (colInfo. justification == ColumnInfo::Left) 16430tp. m_os << colStr << padding << ' ' ; 16431else 16432tp. m_os << padding << colStr << ' ' ; 16433return tp; 16434} 16435 16436friend TablePrinter & operator << (TablePrinter & tp, RowBreak) { 16437if (tp. m_currentColumn > 0 ) { 16438tp. m_os << '\n' ; 16439tp. m_currentColumn = -1 ; 16440} 16441return tp; 16442} 16443}; 16444 16445ConsoleReporter:: ConsoleReporter (ReporterConfig const & config) 16446: StreamingReporterBase (config), 16447m_tablePrinter(new TablePrinter(config. stream (), 16448[ & config]() -> std ::vector < ColumnInfo > { 16449if (config. fullConfig () -> benchmarkNoAnalysis ()) 16450{ 16451return { 16452{ "benchmark name" , CATCH_CONFIG_CONSOLE_WIDTH - 43 , ColumnInfo::Left }, 16453{ " samples" , 14 , ColumnInfo::Right }, 16454{ " iterations" , 14 , ColumnInfo::Right }, 16455{ " mean" , 14 , ColumnInfo::Right } 16456}; 16457} 16458else 16459{ 16460return { 16461{ "benchmark name" , CATCH_CONFIG_CONSOLE_WIDTH - 43 , ColumnInfo::Left }, 16462{ "samples mean std dev" , 14 , ColumnInfo::Right }, 16463{ "iterations low mean low std dev" , 14 , ColumnInfo::Right }, 16464{ "estimated high mean high std dev" , 14 , ColumnInfo::Right } 16465}; 16466} 16467}())) {} 16468ConsoleReporter::~ ConsoleReporter () = default; 16469 16470std :: string ConsoleReporter:: getDescription () { 16471return "Reports test results as plain lines of text" ; 16472} 16473 16474void ConsoleReporter:: noMatchingTestCases ( std ::string const & spec) { 16475stream << "No test cases matched '" << spec << '\'' << std::endl; 16476} 16477 16478void ConsoleReporter:: reportInvalidArguments ( std ::string const & arg){ 16479stream << "Invalid Filter: " << arg << std::endl; 16480} 16481 16482void ConsoleReporter:: assertionStarting ( AssertionInfo const & ) {} 16483 16484bool ConsoleReporter:: assertionEnded ( AssertionStats const & _assertionStats) { 16485AssertionResult const & result = _assertionStats. assertionResult ; 16486 16487bool includeResults = m_config -> includeSuccessfulResults () || !result. isOk (); 16488 16489// Drop out if result was successful but we're not printing them. 16490if (!includeResults && result. getResultType () != ResultWas::Warning) 16491return false; 16492 16493lazyPrint (); 16494 16495ConsoleAssertionPrinter printer ( stream , _assertionStats , includeResults ); 16496printer. (); 16497stream << std::endl; 16498return true; 16499} 16500 16501void ConsoleReporter:: sectionStarting ( SectionInfo const & _sectionInfo) { 16502m_tablePrinter -> close (); 16503m_headerPrinted = false; 16504StreamingReporterBase :: sectionStarting (_sectionInfo); 16505} 16506void ConsoleReporter:: sectionEnded ( SectionStats const & _sectionStats) { 16507m_tablePrinter -> close (); 16508if (_sectionStats. missingAssertions ) { 16509lazyPrint (); 16510Colour colour ( Colour ::ResultError); 16511if (m_sectionStack. size () > 1 ) 16512stream << "\nNo assertions in section" ; 16513else 16514stream << "\nNo assertions in test case" ; 16515stream << " '" << _sectionStats. sectionInfo . name << "'\n" << std::endl; 16516} 16517double dur = _sectionStats. durationInSeconds ; 16518if ( shouldShowDuration ( * m_config, dur)) { 16519stream << getFormattedDuration (dur) << " s: " << _sectionStats. sectionInfo . name << std::endl; 16520} 16521if (m_headerPrinted) { 16522m_headerPrinted = false; 16523} 16524StreamingReporterBase :: sectionEnded (_sectionStats); 16525} 16526 16527#if defined( CATCH_CONFIG_ENABLE_BENCHMARKING ) 16528void ConsoleReporter:: benchmarkPreparing ( std ::string const & name) { 16529lazyPrintWithoutClosingBenchmarkTable (); 16530 16531auto nameCol = Column (name). width (static_cast < std:: size_t > (m_tablePrinter -> columnInfos ()[ 0 ]. width - 2 )); 16532 16533bool firstLine = true; 16534for (auto line : nameCol) { 16535if (!firstLine) 16536( * m_tablePrinter) << ColumnBreak () << ColumnBreak () << ColumnBreak (); 16537else 16538firstLine = false; 16539 16540( * m_tablePrinter) << line << ColumnBreak (); 16541} 16542} 16543 16544void ConsoleReporter:: benchmarkStarting ( BenchmarkInfo const & info) { 16545( * m_tablePrinter) << info. samples << ColumnBreak () 16546<< info. iterations << ColumnBreak (); 16547if (!m_config -> benchmarkNoAnalysis ()) 16548( * m_tablePrinter) << Duration (info. estimatedDuration ) << ColumnBreak (); 16549} 16550void ConsoleReporter:: benchmarkEnded ( BenchmarkStats <> const & stats) { 16551if (m_config -> benchmarkNoAnalysis ()) 16552{ 16553( * m_tablePrinter) << Duration (stats. mean . point . count ()) << ColumnBreak (); 16554} 16555else 16556{ 16557( * m_tablePrinter) << ColumnBreak () 16558<< Duration (stats. mean . point . count ()) << ColumnBreak () 16559<< Duration (stats. mean . lower_bound . count ()) << ColumnBreak () 16560<< Duration (stats. mean . upper_bound . count ()) << ColumnBreak () << ColumnBreak () 16561<< Duration (stats. standardDeviation . point . count ()) << ColumnBreak () 16562<< Duration (stats. standardDeviation . lower_bound . count ()) << ColumnBreak () 16563<< Duration (stats. standardDeviation . upper_bound . count ()) << ColumnBreak () << ColumnBreak () << ColumnBreak () << ColumnBreak () << ColumnBreak (); 16564} 16565} 16566 16567void ConsoleReporter:: benchmarkFailed ( std ::string const & error) { 16568Colour colour ( Colour ::Red); 16569( * m_tablePrinter) 16570<< "Benchmark failed (" << error << ')' 16571<< ColumnBreak () << RowBreak (); 16572} 16573#endif // CATCH_CONFIG_ENABLE_BENCHMARKING 16574 16575void ConsoleReporter:: testCaseEnded ( TestCaseStats const & _testCaseStats) { 16576m_tablePrinter -> close (); 16577StreamingReporterBase :: testCaseEnded (_testCaseStats); 16578m_headerPrinted = false; 16579} 16580void ConsoleReporter:: testGroupEnded ( TestGroupStats const & _testGroupStats) { 16581if (currentGroupInfo. used ) { 16582printSummaryDivider (); 16583stream << "Summary for group '" << _testGroupStats. groupInfo . name << "':\n" ; 16584printTotals (_testGroupStats. totals ); 16585stream << '\n' << std::endl; 16586} 16587StreamingReporterBase :: testGroupEnded (_testGroupStats); 16588} 16589void ConsoleReporter:: testRunEnded ( TestRunStats const & _testRunStats) { 16590printTotalsDivider (_testRunStats. totals ); 16591printTotals (_testRunStats. totals ); 16592stream << std::endl; 16593StreamingReporterBase :: testRunEnded (_testRunStats); 16594} 16595void ConsoleReporter:: testRunStarting ( TestRunInfo const & _testInfo) { 16596StreamingReporterBase :: testRunStarting (_testInfo); 16597printTestFilters (); 16598} 16599 16600void ConsoleReporter:: lazyPrint () { 16601 16602m_tablePrinter -> close (); 16603lazyPrintWithoutClosingBenchmarkTable (); 16604} 16605 16606void ConsoleReporter:: lazyPrintWithoutClosingBenchmarkTable () { 16607 16608if (!currentTestRunInfo. used ) 16609lazyPrintRunInfo (); 16610if (!currentGroupInfo. used ) 16611lazyPrintGroupInfo (); 16612 16613if (!m_headerPrinted) { 16614printTestCaseAndSectionHeader (); 16615m_headerPrinted = true; 16616} 16617} 16618void ConsoleReporter:: lazyPrintRunInfo () { 16619stream << '\n' << getLineOfChars < '~' > () << '\n' ; 16620Colour colour ( Colour ::SecondaryText); 16621stream << currentTestRunInfo -> name 16622<< " is a Catch v" << libraryVersion () << " host application.\n" 16623<< "Run with -? for options\n\n" ; 16624 16625if (m_config -> rngSeed () != 0 ) 16626stream << "Randomness seeded to: " << m_config -> rngSeed () << "\n\n" ; 16627 16628currentTestRunInfo. used = true; 16629} 16630void ConsoleReporter:: lazyPrintGroupInfo () { 16631if (!currentGroupInfo -> name . empty () && currentGroupInfo -> groupsCounts > 1 ) { 16632printClosedHeader ( "Group: " + currentGroupInfo -> name ); 16633currentGroupInfo. used = true; 16634} 16635} 16636void ConsoleReporter:: printTestCaseAndSectionHeader () { 16637assert (!m_sectionStack. empty ()); 16638printOpenHeader (currentTestCaseInfo -> name ); 16639 16640if (m_sectionStack. size () > 1 ) { 16641Colour colourGuard ( Colour ::Headers); 16642 16643auto 16644it = m_sectionStack. begin () + 1 , // Skip first section (test case) 16645itEnd = m_sectionStack. end (); 16646for (; it != itEnd; ++ it) 16647printHeaderString (it -> name , 2 ); 16648} 16649 16650SourceLineInfo lineInfo = m_sectionStack. back (). lineInfo ; 16651 16652stream << getLineOfChars < '-' > () << '\n' ; 16653Colour colourGuard ( Colour ::FileName); 16654stream << lineInfo << '\n' ; 16655stream << getLineOfChars < '.' > () << '\n' << std::endl; 16656} 16657 16658void ConsoleReporter:: printClosedHeader ( std ::string const & _name) { 16659printOpenHeader (_name); 16660stream << getLineOfChars < '.' > () << '\n' ; 16661} 16662void ConsoleReporter:: printOpenHeader ( std ::string const & _name) { 16663stream << getLineOfChars < '-' > () << '\n' ; 16664{ 16665Colour colourGuard ( Colour ::Headers); 16666printHeaderString (_name); 16667} 16668} 16669 16670// if string has a : in first line will set indent to follow it on 16671// subsequent lines 16672void ConsoleReporter:: printHeaderString ( std ::string const & _string, std :: size_t indent) { 16673std :: size_t i = _string. find ( ": " ); 16674if (i != std::string::npos) 16675i += 2 ; 16676else 16677i = 0 ; 16678stream << Column (_string). indent (indent + i). initialIndent (indent) << '\n' ; 16679} 16680 16681struct SummaryColumn { 16682 16683SummaryColumn( std :: string _label , Colour ::Code _colour ) 16684: label ( std:: move ( _label ) ), 16685colour ( _colour ) {} 16686SummaryColumn addRow ( std :: size_t count ) { 16687ReusableStringStream rss ; 16688rss << count ; 16689std :: string row = rss . str (); 16690for ( auto & oldRow : rows) { 16691while ( oldRow . size () < row . size ()) 16692oldRow = ' ' + oldRow ; 16693while ( oldRow .size() > row . size ()) 16694row = ' ' + row ; 16695} 16696rows. push_back ( row ); 16697return * this; 16698} 16699 16700std :: string label; 16701Colour :: Code colour; 16702std ::vector < std::string > rows; 16703 16704}; 16705 16706void ConsoleReporter:: printTotals ( Totals const & totals ) { 16707if (totals. testCases . total () == 0 ) { 16708stream << Colour (Colour::Warning) << "No tests ran\n" ; 16709} else if (totals. assertions . total () > 0 && totals. testCases . allPassed ()) { 16710stream << Colour (Colour::ResultSuccess) << "All tests passed" ; 16711stream << " (" 16712<< pluralise (totals. assertions . passed , "assertion" ) << " in " 16713<< pluralise (totals. testCases . passed , "test case" ) << ')' 16714<< '\n' ; 16715} else { 16716 16717std ::vector < SummaryColumn > columns; 16718columns. push_back ( SummaryColumn ( "" , Colour::None) 16719. addRow (totals. testCases . total ()) 16720. addRow (totals. assertions . total ())); 16721columns. push_back ( SummaryColumn ( "passed" , Colour::Success) 16722. addRow (totals. testCases . passed ) 16723. addRow (totals. assertions . passed )); 16724columns. push_back ( SummaryColumn ( "failed" , Colour::ResultError) 16725. addRow (totals. testCases . failed ) 16726. addRow (totals. assertions . failed )); 16727columns. push_back ( SummaryColumn ( "failed as expected" , Colour::ResultExpectedFailure) 16728. addRow (totals. testCases . failedButOk ) 16729. addRow (totals. assertions . failedButOk )); 16730 16731printSummaryRow ( "test cases" , columns, 0 ); 16732printSummaryRow ( "assertions" , columns, 1 ); 16733} 16734} 16735void ConsoleReporter:: printSummaryRow ( std ::string const & label, std ::vector < SummaryColumn > const & cols, std :: size_t row) { 16736for (auto col : cols) { 16737std::string value = col. rows [row]; 16738if (col. label . empty ()) { 16739stream << label << ": " ; 16740if (value != "0" ) 16741stream << value; 16742else 16743stream << Colour (Colour::Warning) << "- none -" ; 16744} else if (value != "0" ) { 16745stream << Colour (Colour::LightGrey) << " | " ; 16746stream << Colour (col. colour ) 16747<< value << ' ' << col. label ; 16748} 16749} 16750stream << '\n' ; 16751} 16752 16753void ConsoleReporter::printTotalsDivider(Totals const & totals) { 16754if (totals. testCases . total () > 0 ) { 16755std :: size_t failedRatio = makeRatio (totals. testCases . failed , totals. testCases . total ()); 16756std :: size_t failedButOkRatio = makeRatio (totals. testCases . failedButOk , totals. testCases . total ()); 16757std :: size_t passedRatio = makeRatio (totals. testCases . passed , totals. testCases . total ()); 16758while (failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH - 1 ) 16759findMax (failedRatio, failedButOkRatio, passedRatio) ++ ; 16760while (failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH - 1 ) 16761findMax (failedRatio, failedButOkRatio, passedRatio) -- ; 16762 16763stream << Colour (Colour::Error) << std:: string (failedRatio, '=' ); 16764stream << Colour (Colour::ResultExpectedFailure) << std:: string (failedButOkRatio, '=' ); 16765if (totals. testCases . allPassed ()) 16766stream << Colour (Colour::ResultSuccess) << std:: string (passedRatio, '=' ); 16767else 16768stream << Colour (Colour::Success) << std:: string (passedRatio, '=' ); 16769} else { 16770stream << Colour (Colour::Warning) << std:: string ( CATCH_CONFIG_CONSOLE_WIDTH - 1 , '=' ); 16771} 16772stream << '\n' ; 16773} 16774void ConsoleReporter:: printSummaryDivider () { 16775stream << getLineOfChars < '-' > () << '\n' ; 16776} 16777 16778void ConsoleReporter:: printTestFilters () { 16779if (m_config -> testSpec (). hasFilters ()) { 16780Colour guard ( Colour ::BrightYellow); 16781stream << "Filters: " << serializeFilters (m_config -> getTestsOrTags ()) << '\n' ; 16782} 16783} 16784 16785CATCH_REGISTER_REPORTER ( "console" , ConsoleReporter) 16786 16787} // end namespace Catch 16788 16789#if defined(_MSC_VER) 16790#pragma warning(pop) 16791#endif 16792 16793#if defined(__clang__) 16794# pragma clang diagnostic pop 16795#endif 16796// end catch_reporter_console.cpp 16797// start catch_reporter_junit.cpp 16798 16799#include <cassert> 16800#include <sstream> 16801#include <ctime> 16802#include <algorithm> 16803#include <iomanip> 16804 16805namespace Catch { 16806 16807namespace { 16808std :: string getCurrentTimestamp () { 16809// Beware, this is not reentrant because of backward compatibility issues 16810// Also, UTC only, again because of backward compatibility (%z is C++11) 16811time_t rawtime; 16812std :: time ( & rawtime); 16813auto const timeStampSize = sizeof ( "2017-01-16T17:06:45Z" ); 16814 16815#ifdef _MSC_VER 16816std :: tm timeInfo = {}; 16817gmtime_s ( & timeInfo, & rawtime); 16818#else 16819std :: tm * timeInfo; 16820timeInfo = std:: gmtime ( & rawtime); 16821#endif 16822 16823char timeStamp[timeStampSize]; 16824const char * const fmt = "%Y-%m-%dT%H:%M:%SZ" ; 16825 16826#ifdef _MSC_VER 16827std :: strftime (timeStamp, timeStampSize, fmt, & timeInfo); 16828#else 16829std :: strftime (timeStamp, timeStampSize, fmt, timeInfo); 16830#endif 16831return std:: string (timeStamp, timeStampSize - 1 ); 16832} 16833 16834std:: string fileNameTag( const std ::vector < std::string > & tags) { 16835auto it = std:: find_if ( begin (tags), 16836end (tags), 16837[] (std:: string const & tag ) {return tag. front () == '#' ; }); 16838if (it != tags. end ()) 16839return it -> substr ( 1 ); 16840return std:: string (); 16841} 16842 16843// Formats the duration in seconds to 3 decimal places. 16844// This is done because some genius defined Maven Surefire schema 16845// in a way that only accepts 3 decimal places, and tools like 16846// Jenkins use that schema for validation JUnit reporter output. 16847std :: string formatDuration ( double seconds ) { 16848ReusableStringStream rss; 16849rss << std::fixed << std:: setprecision ( 3 ) << seconds; 16850return rss. str (); 16851} 16852 16853} // anonymous namespace 16854 16855JunitReporter ::JunitReporter( ReporterConfig const & _config ) 16856: CumulativeReporterBase ( _config ), 16857xml ( _config. stream () ) 16858{ 16859m_reporterPrefs. shouldRedirectStdOut = true; 16860m_reporterPrefs. shouldReportAllAssertions = true; 16861} 16862 16863JunitReporter ::~ JunitReporter () {} 16864 16865std :: string JunitReporter:: getDescription () { 16866return "Reports test results in an XML format that looks like Ant's junitreport target" ; 16867} 16868 16869void JunitReporter:: noMatchingTestCases ( std ::string const & /*spec*/ ) {} 16870 16871void JunitReporter:: testRunStarting ( TestRunInfo const & runInfo ) { 16872CumulativeReporterBase :: testRunStarting ( runInfo ); 16873xml. startElement ( "testsuites" ); 16874} 16875 16876void JunitReporter:: testGroupStarting ( GroupInfo const & groupInfo ) { 16877suiteTimer. start (); 16878stdOutForSuite. clear (); 16879stdErrForSuite. clear (); 16880unexpectedExceptions = 0 ; 16881CumulativeReporterBase :: testGroupStarting ( groupInfo ); 16882} 16883 16884void JunitReporter:: testCaseStarting ( TestCaseInfo const & testCaseInfo ) { 16885m_okToFail = testCaseInfo. okToFail (); 16886} 16887 16888bool JunitReporter:: assertionEnded ( AssertionStats const & assertionStats ) { 16889if ( assertionStats. assertionResult . getResultType () == ResultWas::ThrewException && !m_okToFail ) 16890unexpectedExceptions ++ ; 16891return CumulativeReporterBase:: assertionEnded ( assertionStats ); 16892} 16893 16894void JunitReporter:: testCaseEnded ( TestCaseStats const & testCaseStats ) { 16895stdOutForSuite += testCaseStats. stdOut ; 16896stdErrForSuite += testCaseStats. stdErr ; 16897CumulativeReporterBase :: testCaseEnded ( testCaseStats ); 16898} 16899 16900void JunitReporter:: testGroupEnded ( TestGroupStats const & testGroupStats ) { 16901double suiteTime = suiteTimer. getElapsedSeconds (); 16902CumulativeReporterBase :: testGroupEnded ( testGroupStats ); 16903writeGroup ( * m_testGroups. back (), suiteTime ); 16904} 16905 16906void JunitReporter:: testRunEndedCumulative () { 16907xml. endElement (); 16908} 16909 16910void JunitReporter:: writeGroup ( TestGroupNode const & groupNode, double suiteTime ) { 16911XmlWriter :: ScopedElement e = xml. scopedElement ( "testsuite" ); 16912 16913TestGroupStats const & stats = groupNode. value ; 16914xml. writeAttribute ( "name" , stats. groupInfo . name ); 16915xml. writeAttribute ( "errors" , unexpectedExceptions ); 16916xml. writeAttribute ( "failures" , stats. totals . assertions . failed - unexpectedExceptions ); 16917xml. writeAttribute ( "tests" , stats. totals . assertions . total () ); 16918xml. writeAttribute ( "hostname" , "tbd" ); // !TBD 16919if ( m_config -> showDurations () == ShowDurations::Never ) 16920xml. writeAttribute ( "time" , "" ); 16921else 16922xml. writeAttribute ( "time" , formatDuration ( suiteTime ) ); 16923xml. writeAttribute ( "timestamp" , getCurrentTimestamp () ); 16924 16925// Write properties if there are any 16926if (m_config -> hasTestFilters () || m_config -> rngSeed () != 0 ) { 16927auto properties = xml. scopedElement ( "properties" ); 16928if (m_config -> hasTestFilters ()) { 16929xml. scopedElement ( "property" ) 16930. writeAttribute ( "name" , "filters" ) 16931. writeAttribute ( "value" , serializeFilters (m_config -> getTestsOrTags ())); 16932} 16933if (m_config -> rngSeed () != 0 ) { 16934xml. scopedElement ( "property" ) 16935. writeAttribute ( "name" , "random-seed" ) 16936. writeAttribute ( "value" , m_config -> rngSeed ()); 16937} 16938} 16939 16940// Write test cases 16941for ( auto const & child : groupNode.children ) 16942writeTestCase ( * child ); 16943 16944xml. scopedElement ( "system-out" ). writeText ( trim ( stdOutForSuite ), XmlFormatting::Newline ); 16945xml. scopedElement ( "system-err" ). writeText ( trim ( stdErrForSuite ), XmlFormatting::Newline ); 16946} 16947 16948void JunitReporter:: writeTestCase ( TestCaseNode const & testCaseNode ) { 16949TestCaseStats const & stats = testCaseNode. value ; 16950 16951// All test cases have exactly one section - which represents the 16952// test case itself. That section may have 0-n nested sections 16953assert ( testCaseNode. children . size () == 1 ); 16954SectionNode const & rootSection = * testCaseNode. children . front (); 16955 16956std::string className = stats. testInfo . className ; 16957 16958if ( className. empty () ) { 16959className = fileNameTag (stats. testInfo . tags ); 16960if ( className. empty () ) 16961className = "global" ; 16962} 16963 16964if ( !m_config -> name (). empty () ) 16965className = m_config -> name () + "." + className; 16966 16967writeSection ( className, "" , rootSection, stats. testInfo . okToFail () ); 16968} 16969 16970void JunitReporter:: writeSection ( std ::string const & className, 16971std ::string const & rootName, 16972SectionNode const & sectionNode, 16973bool testOkToFail) { 16974std :: string name = trim ( sectionNode. stats . sectionInfo . name ); 16975if ( !rootName. empty () ) 16976name = rootName + '/' + name; 16977 16978if ( !sectionNode. assertions . empty () || 16979!sectionNode. stdOut . empty () || 16980!sectionNode. stdErr . empty () ) { 16981XmlWriter :: ScopedElement e = xml. scopedElement ( "testcase" ); 16982if ( className. empty () ) { 16983xml. writeAttribute ( "classname" , name ); 16984xml. writeAttribute ( "name" , "root" ); 16985} 16986else { 16987xml. writeAttribute ( "classname" , className ); 16988xml. writeAttribute ( "name" , name ); 16989} 16990xml. writeAttribute ( "time" , formatDuration ( sectionNode. stats . durationInSeconds ) ); 16991// This is not ideal, but it should be enough to mimic gtest's 16992// junit output. 16993// Ideally the JUnit reporter would also handle `skipTest` 16994// events and write those out appropriately. 16995xml. writeAttribute ( "status" , "run" ); 16996 16997if (sectionNode. stats . assertions . failedButOk ) { 16998xml. scopedElement ( "skipped" ) 16999. writeAttribute ( "message" , "TEST_CASE tagged with !mayfail" ); 17000} 17001 17002writeAssertions ( sectionNode ); 17003 17004if ( !sectionNode. stdOut . empty () ) 17005xml. scopedElement ( "system-out" ). writeText ( trim ( sectionNode. stdOut ), XmlFormatting::Newline ); 17006if ( !sectionNode. stdErr . empty () ) 17007xml. scopedElement ( "system-err" ). writeText ( trim ( sectionNode. stdErr ), XmlFormatting::Newline ); 17008} 17009for ( auto const & childNode : sectionNode.childSections ) 17010if ( className.empty() ) 17011writeSection( name, "" , * childNode, testOkToFail ); 17012else 17013writeSection ( className, name, * childNode, testOkToFail ); 17014} 17015 17016void JunitReporter:: writeAssertions ( SectionNode const & sectionNode ) { 17017for ( auto const & assertion : sectionNode. assertions ) 17018writeAssertion ( assertion ); 17019} 17020 17021void JunitReporter:: writeAssertion ( AssertionStats const & stats ) { 17022AssertionResult const & result = stats. assertionResult ; 17023if ( !result. isOk () ) { 17024std :: string elementName; 17025switch ( result. getResultType () ) { 17026case ResultWas:: ThrewException : 17027case ResultWas:: FatalErrorCondition : 17028elementName = "error" ; 17029break ; 17030case ResultWas:: ExplicitFailure : 17031case ResultWas:: ExpressionFailed : 17032case ResultWas:: DidntThrowException : 17033elementName = "failure" ; 17034break ; 17035 17036// We should never see these here: 17037case ResultWas:: Info : 17038case ResultWas:: Warning : 17039case ResultWas:: Ok : 17040case ResultWas:: Unknown : 17041case ResultWas:: FailureBit : 17042case ResultWas:: Exception : 17043elementName = "internalError" ; 17044break ; 17045} 17046 17047XmlWriter :: ScopedElement e = xml. scopedElement ( elementName ); 17048 17049xml. writeAttribute ( "message" , result. getExpression () ); 17050xml. writeAttribute ( "type" , result. getTestMacroName () ); 17051 17052ReusableStringStream rss; 17053if (stats. totals . assertions . total () > 0 ) { 17054rss << "FAILED" << ":\n" ; 17055if (result. hasExpression ()) { 17056rss << " " ; 17057rss << result. getExpressionInMacro (); 17058rss << '\n' ; 17059} 17060if (result. hasExpandedExpression ()) { 17061rss << "with expansion:\n" ; 17062rss << Column (result. getExpandedExpression ()). indent ( 2 ) << '\n' ; 17063} 17064} else { 17065rss << '\n' ; 17066} 17067 17068if ( !result. getMessage (). empty () ) 17069rss << result. getMessage () << '\n' ; 17070for ( auto const & msg : stats.infoMessages ) 17071if ( msg.type == ResultWas::Info ) 17072rss << msg.message << '\n' ; 17073 17074rss << "at " << result. getSourceInfo (); 17075xml. writeText ( rss. str (), XmlFormatting::Newline ); 17076} 17077} 17078 17079CATCH_REGISTER_REPORTER ( "junit" , JunitReporter ) 17080 17081} // end namespace Catch 17082// end catch_reporter_junit.cpp 17083// start catch_reporter_listening.cpp 17084 17085#include < cassert > 17086 17087namespace Catch { 17088 17089ListeningReporter:: ListeningReporter () { 17090// We will assume that listeners will always want all assertions 17091m_preferences. shouldReportAllAssertions = true; 17092} 17093 17094void ListeningReporter:: addListener ( IStreamingReporterPtr && listener ) { 17095m_listeners. push_back ( std:: move ( listener ) ); 17096} 17097 17098void ListeningReporter:: addReporter (IStreamingReporterPtr && reporter) { 17099assert (!m_reporter && "Listening reporter can wrap only 1 real reporter" ); 17100m_reporter = std:: move ( reporter ); 17101m_preferences. shouldRedirectStdOut = m_reporter -> getPreferences (). shouldRedirectStdOut ; 17102} 17103 17104ReporterPreferences ListeningReporter:: getPreferences () const { 17105return m_preferences; 17106} 17107 17108std::set < Verbosity > ListeningReporter:: getSupportedVerbosities () { 17109return std::set < Verbosity > { }; 17110} 17111 17112void ListeningReporter:: noMatchingTestCases ( std::string const & spec ) { 17113for ( auto const & listener : m_listeners ) { 17114listener -> noMatchingTestCases ( spec ); 17115} 17116m_reporter -> noMatchingTestCases ( spec ); 17117} 17118 17119void ListeningReporter:: reportInvalidArguments (std::string const & arg){ 17120for ( auto const & listener : m_listeners ) { 17121listener -> reportInvalidArguments ( arg ); 17122} 17123m_reporter -> reportInvalidArguments ( arg ); 17124} 17125 17126#if defined( CATCH_CONFIG_ENABLE_BENCHMARKING ) 17127void ListeningReporter ::benchmarkPreparing( std :: string const & name ) { 17128for (auto const & listener : m_listeners) { 17129listener -> benchmarkPreparing ( name ); 17130} 17131m_reporter -> benchmarkPreparing (name); 17132} 17133void ListeningReporter:: benchmarkStarting ( BenchmarkInfo const & benchmarkInfo ) { 17134for ( auto const & listener : m_listeners ) { 17135listener -> benchmarkStarting ( benchmarkInfo ); 17136} 17137m_reporter -> benchmarkStarting ( benchmarkInfo ); 17138} 17139void ListeningReporter:: benchmarkEnded ( BenchmarkStats < > const & benchmarkStats ) { 17140for ( auto const & listener : m_listeners ) { 17141listener -> benchmarkEnded ( benchmarkStats ); 17142} 17143m_reporter -> benchmarkEnded ( benchmarkStats ); 17144} 17145 17146void ListeningReporter:: benchmarkFailed ( std::string const & error ) { 17147for (auto const & listener : m_listeners) { 17148listener -> benchmarkFailed (error); 17149} 17150m_reporter -> benchmarkFailed (error); 17151} 17152#endif // CATCH_CONFIG_ENABLE_BENCHMARKING 17153 17154void ListeningReporter:: testRunStarting ( TestRunInfo const & testRunInfo ) { 17155for ( auto const & listener : m_listeners ) { 17156listener -> testRunStarting ( testRunInfo ); 17157} 17158m_reporter -> testRunStarting ( testRunInfo ); 17159} 17160 17161void ListeningReporter:: testGroupStarting ( GroupInfo const & groupInfo ) { 17162for ( auto const & listener : m_listeners ) { 17163listener -> testGroupStarting ( groupInfo ); 17164} 17165m_reporter -> testGroupStarting ( groupInfo ); 17166} 17167 17168void ListeningReporter:: testCaseStarting ( TestCaseInfo const & testInfo ) { 17169for ( auto const & listener : m_listeners ) { 17170listener -> testCaseStarting ( testInfo ); 17171} 17172m_reporter -> testCaseStarting ( testInfo ); 17173} 17174 17175void ListeningReporter:: sectionStarting ( SectionInfo const & sectionInfo ) { 17176for ( auto const & listener : m_listeners ) { 17177listener -> sectionStarting ( sectionInfo ); 17178} 17179m_reporter -> sectionStarting ( sectionInfo ); 17180} 17181 17182void ListeningReporter:: assertionStarting ( AssertionInfo const & assertionInfo ) { 17183for ( auto const & listener : m_listeners ) { 17184listener -> assertionStarting ( assertionInfo ); 17185} 17186m_reporter -> assertionStarting ( assertionInfo ); 17187} 17188 17189// The return value indicates if the messages buffer should be cleared: 17190bool ListeningReporter:: assertionEnded ( AssertionStats const & assertionStats ) { 17191for ( auto const & listener : m_listeners ) { 17192static_cast < void > ( listener -> assertionEnded ( assertionStats ) ); 17193} 17194return m_reporter -> assertionEnded ( assertionStats ); 17195} 17196 17197void ListeningReporter:: sectionEnded ( SectionStats const & sectionStats ) { 17198for ( auto const & listener : m_listeners ) { 17199listener -> sectionEnded ( sectionStats ); 17200} 17201m_reporter -> sectionEnded ( sectionStats ); 17202} 17203 17204void ListeningReporter:: testCaseEnded ( TestCaseStats const & testCaseStats ) { 17205for ( auto const & listener : m_listeners ) { 17206listener -> testCaseEnded ( testCaseStats ); 17207} 17208m_reporter -> testCaseEnded ( testCaseStats ); 17209} 17210 17211void ListeningReporter:: testGroupEnded ( TestGroupStats const & testGroupStats ) { 17212for ( auto const & listener : m_listeners ) { 17213listener -> testGroupEnded ( testGroupStats ); 17214} 17215m_reporter -> testGroupEnded ( testGroupStats ); 17216} 17217 17218void ListeningReporter:: testRunEnded ( TestRunStats const & testRunStats ) { 17219for ( auto const & listener : m_listeners ) { 17220listener -> testRunEnded ( testRunStats ); 17221} 17222m_reporter -> testRunEnded ( testRunStats ); 17223} 17224 17225void ListeningReporter:: skipTest ( TestCaseInfo const & testInfo ) { 17226for ( auto const & listener : m_listeners ) { 17227listener -> skipTest ( testInfo ); 17228} 17229m_reporter -> skipTest ( testInfo ); 17230} 17231 17232bool ListeningReporter:: isMulti () const { 17233return true; 17234} 17235 17236} // end namespace Catch 17237// end catch_reporter_listening.cpp 17238// start catch_reporter_xml.cpp 17239 17240#if defined(_MSC_VER) 17241#pragma warning(push) 17242#pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch 17243// Note that 4062 (not all labels are handled 17244// and default is missing) is enabled 17245#endif 17246 17247namespace Catch { 17248XmlReporter ::XmlReporter( ReporterConfig const & _config ) 17249: StreamingReporterBase ( _config ), 17250m_xml (_config. stream ()) 17251{ 17252m_reporterPrefs. shouldRedirectStdOut = true; 17253m_reporterPrefs. shouldReportAllAssertions = true; 17254} 17255 17256XmlReporter ::~ XmlReporter () = default; 17257 17258std :: string XmlReporter:: getDescription () { 17259return "Reports test results as an XML document" ; 17260} 17261 17262std :: string XmlReporter:: getStylesheetRef () const { 17263return std:: string (); 17264} 17265 17266void XmlReporter:: writeSourceInfo ( SourceLineInfo const & sourceInfo ) { 17267m_xml 17268. writeAttribute ( "filename" , sourceInfo. file ) 17269. writeAttribute ( "line" , sourceInfo. line ); 17270} 17271 17272void XmlReporter:: noMatchingTestCases ( std ::string const & s ) { 17273StreamingReporterBase :: noMatchingTestCases ( s ); 17274} 17275 17276void XmlReporter:: testRunStarting ( TestRunInfo const & testInfo ) { 17277StreamingReporterBase :: testRunStarting ( testInfo ); 17278std :: string stylesheetRef = getStylesheetRef (); 17279if ( !stylesheetRef. empty () ) 17280m_xml. writeStylesheetRef ( stylesheetRef ); 17281m_xml. startElement ( "Catch" ); 17282if ( !m_config -> name (). empty () ) 17283m_xml. writeAttribute ( "name" , m_config -> name () ); 17284if (m_config -> testSpec (). hasFilters ()) 17285m_xml. writeAttribute ( "filters" , serializeFilters ( m_config -> getTestsOrTags () ) ); 17286if ( m_config -> rngSeed () != 0 ) 17287m_xml. scopedElement ( "Randomness" ) 17288. writeAttribute ( "seed" , m_config -> rngSeed () ); 17289} 17290 17291void XmlReporter:: testGroupStarting ( GroupInfo const & groupInfo ) { 17292StreamingReporterBase :: testGroupStarting ( groupInfo ); 17293m_xml. startElement ( "Group" ) 17294. writeAttribute ( "name" , groupInfo. name ); 17295} 17296 17297void XmlReporter:: testCaseStarting ( TestCaseInfo const & testInfo ) { 17298StreamingReporterBase :: testCaseStarting (testInfo); 17299m_xml. startElement ( "TestCase" ) 17300. writeAttribute ( "name" , trim ( testInfo. name ) ) 17301. writeAttribute ( "description" , testInfo. description ) 17302. writeAttribute ( "tags" , testInfo. tagsAsString () ); 17303 17304writeSourceInfo ( testInfo. lineInfo ); 17305 17306if ( m_config -> showDurations () == ShowDurations::Always ) 17307m_testCaseTimer. start (); 17308m_xml. ensureTagClosed (); 17309} 17310 17311void XmlReporter:: sectionStarting ( SectionInfo const & sectionInfo ) { 17312StreamingReporterBase :: sectionStarting ( sectionInfo ); 17313if ( m_sectionDepth ++ > 0 ) { 17314m_xml. startElement ( "Section" ) 17315. writeAttribute ( "name" , trim ( sectionInfo. name ) ); 17316writeSourceInfo ( sectionInfo. lineInfo ); 17317m_xml. ensureTagClosed (); 17318} 17319} 17320 17321void XmlReporter:: assertionStarting ( AssertionInfo const & ) { } 17322 17323bool XmlReporter:: assertionEnded ( AssertionStats const & assertionStats ) { 17324 17325AssertionResult const & result = assertionStats. assertionResult ; 17326 17327bool includeResults = m_config -> includeSuccessfulResults () || !result. isOk (); 17328 17329if ( includeResults || result. getResultType () == ResultWas::Warning ) { 17330// Print any info messages in <Info> tags. 17331for ( auto const & msg : assertionStats.infoMessages ) { 17332if ( msg.type == ResultWas::Info && includeResults ) { 17333m_xml. scopedElement ( " Info " ) 17334. writeText ( msg.message ); 17335} else if ( msg .type == ResultWas::Warning ) { 17336m_xml. scopedElement ( " Warning " ) 17337. writeText ( msg.message ); 17338} 17339} 17340} 17341 17342// Drop out if result was successful but we're not printing them. 17343if ( !includeResults && result. getResultType () != ResultWas::Warning ) 17344return true; 17345 17346// Print the expression if there is one. 17347if ( result. hasExpression () ) { 17348m_xml. startElement ( "Expression" ) 17349. writeAttribute ( "success" , result. succeeded () ) 17350. writeAttribute ( "type" , result. getTestMacroName () ); 17351 17352writeSourceInfo ( result. getSourceInfo () ); 17353 17354m_xml. scopedElement ( "Original" ) 17355. writeText ( result. getExpression () ); 17356m_xml. scopedElement ( "Expanded" ) 17357. writeText ( result. getExpandedExpression () ); 17358} 17359 17360// And... Print a result applicable to each result type. 17361switch ( result. getResultType () ) { 17362case ResultWas:: ThrewException : 17363m_xml. startElement ( "Exception" ); 17364writeSourceInfo ( result. getSourceInfo () ); 17365m_xml. writeText ( result. getMessage () ); 17366m_xml. endElement (); 17367break ; 17368case ResultWas:: FatalErrorCondition : 17369m_xml. startElement ( "FatalErrorCondition" ); 17370writeSourceInfo ( result. getSourceInfo () ); 17371m_xml. writeText ( result. getMessage () ); 17372m_xml. endElement (); 17373break ; 17374case ResultWas:: Info : 17375m_xml. scopedElement ( "Info" ) 17376. writeText ( result. getMessage () ); 17377break ; 17378case ResultWas:: Warning : 17379// Warning will already have been written 17380break ; 17381case ResultWas:: ExplicitFailure : 17382m_xml. startElement ( "Failure" ); 17383writeSourceInfo ( result. getSourceInfo () ); 17384m_xml. writeText ( result. getMessage () ); 17385m_xml. endElement (); 17386break ; 17387default : 17388break ; 17389} 17390 17391if ( result. hasExpression () ) 17392m_xml. endElement (); 17393 17394return true; 17395} 17396 17397void XmlReporter:: sectionEnded ( SectionStats const & sectionStats ) { 17398StreamingReporterBase :: sectionEnded ( sectionStats ); 17399if ( -- m_sectionDepth > 0 ) { 17400XmlWriter :: ScopedElement e = m_xml. scopedElement ( "OverallResults" ); 17401e. writeAttribute ( "successes" , sectionStats. assertions . passed ); 17402e. writeAttribute ( "failures" , sectionStats. assertions . failed ); 17403e. writeAttribute ( "expectedFailures" , sectionStats. assertions . failedButOk ); 17404 17405if ( m_config -> showDurations () == ShowDurations::Always ) 17406e. writeAttribute ( "durationInSeconds" , sectionStats. durationInSeconds ); 17407 17408m_xml. endElement (); 17409} 17410} 17411 17412void XmlReporter:: testCaseEnded ( TestCaseStats const & testCaseStats ) { 17413StreamingReporterBase :: testCaseEnded ( testCaseStats ); 17414XmlWriter :: ScopedElement e = m_xml. scopedElement ( "OverallResult" ); 17415e. writeAttribute ( "success" , testCaseStats. totals . assertions . allOk () ); 17416 17417if ( m_config -> showDurations () == ShowDurations::Always ) 17418e. writeAttribute ( "durationInSeconds" , m_testCaseTimer. getElapsedSeconds () ); 17419 17420if ( !testCaseStats. stdOut . empty () ) 17421m_xml. scopedElement ( "StdOut" ). writeText ( trim ( testCaseStats. stdOut ), XmlFormatting::Newline ); 17422if ( !testCaseStats. stdErr . empty () ) 17423m_xml. scopedElement ( "StdErr" ). writeText ( trim ( testCaseStats. stdErr ), XmlFormatting::Newline ); 17424 17425m_xml. endElement (); 17426} 17427 17428void XmlReporter:: testGroupEnded ( TestGroupStats const & testGroupStats ) { 17429StreamingReporterBase :: testGroupEnded ( testGroupStats ); 17430// TODO: Check testGroupStats.aborting and act accordingly. 17431m_xml. scopedElement ( "OverallResults" ) 17432. writeAttribute ( "successes" , testGroupStats. totals . assertions . passed ) 17433. writeAttribute ( "failures" , testGroupStats. totals . assertions . failed ) 17434. writeAttribute ( "expectedFailures" , testGroupStats. totals . assertions . failedButOk ); 17435m_xml. scopedElement ( "OverallResultsCases" ) 17436. writeAttribute ( "successes" , testGroupStats. totals . testCases . passed ) 17437. writeAttribute ( "failures" , testGroupStats. totals . testCases . failed ) 17438. writeAttribute ( "expectedFailures" , testGroupStats. totals . testCases . failedButOk ); 17439m_xml. endElement (); 17440} 17441 17442void XmlReporter:: testRunEnded ( TestRunStats const & testRunStats ) { 17443StreamingReporterBase :: testRunEnded ( testRunStats ); 17444m_xml. scopedElement ( "OverallResults" ) 17445. writeAttribute ( "successes" , testRunStats. totals . assertions . passed ) 17446. writeAttribute ( "failures" , testRunStats. totals . assertions . failed ) 17447. writeAttribute ( "expectedFailures" , testRunStats. totals . assertions . failedButOk ); 17448m_xml. scopedElement ( "OverallResultsCases" ) 17449. writeAttribute ( "successes" , testRunStats. totals . testCases . passed ) 17450. writeAttribute ( "failures" , testRunStats. totals . testCases . failed ) 17451. writeAttribute ( "expectedFailures" , testRunStats. totals . testCases . failedButOk ); 17452m_xml. endElement (); 17453} 17454 17455#if defined( CATCH_CONFIG_ENABLE_BENCHMARKING ) 17456void XmlReporter:: benchmarkPreparing ( std ::string const & name) { 17457m_xml. startElement ( "BenchmarkResults" ) 17458. writeAttribute ( "name" , name); 17459} 17460 17461void XmlReporter:: benchmarkStarting ( BenchmarkInfo const & info) { 17462m_xml. writeAttribute ( "samples" , info. samples ) 17463. writeAttribute ( "resamples" , info. resamples ) 17464. writeAttribute ( "iterations" , info. iterations ) 17465. writeAttribute ( "clockResolution" , info. clockResolution ) 17466. writeAttribute ( "estimatedDuration" , info. estimatedDuration ) 17467. writeComment ( "All values in nano seconds" ); 17468} 17469 17470void XmlReporter:: benchmarkEnded ( BenchmarkStats <> const & benchmarkStats) { 17471m_xml. startElement ( "mean" ) 17472. writeAttribute ( "value" , benchmarkStats. mean . point . count ()) 17473. writeAttribute ( "lowerBound" , benchmarkStats. mean . lower_bound . count ()) 17474. writeAttribute ( "upperBound" , benchmarkStats. mean . upper_bound . count ()) 17475. writeAttribute ( "ci" , benchmarkStats. mean . confidence_interval ); 17476m_xml. endElement (); 17477m_xml. startElement ( "standardDeviation" ) 17478. writeAttribute ( "value" , benchmarkStats. standardDeviation . point . count ()) 17479. writeAttribute ( "lowerBound" , benchmarkStats. standardDeviation . lower_bound . count ()) 17480. writeAttribute ( "upperBound" , benchmarkStats. standardDeviation . upper_bound . count ()) 17481. writeAttribute ( "ci" , benchmarkStats. standardDeviation . confidence_interval ); 17482m_xml. endElement (); 17483m_xml. startElement ( "outliers" ) 17484. writeAttribute ( "variance" , benchmarkStats. outlierVariance ) 17485. writeAttribute ( "lowMild" , benchmarkStats. outliers . low_mild ) 17486. writeAttribute ( "lowSevere" , benchmarkStats. outliers . low_severe ) 17487. writeAttribute ( "highMild" , benchmarkStats. outliers . high_mild ) 17488. writeAttribute ( "highSevere" , benchmarkStats. outliers . high_severe ); 17489m_xml. endElement (); 17490m_xml. endElement (); 17491} 17492 17493void XmlReporter:: benchmarkFailed ( std ::string const & error) { 17494m_xml. scopedElement ( "failed" ). 17495writeAttribute ( "message" , error); 17496m_xml. endElement (); 17497} 17498#endif // CATCH_CONFIG_ENABLE_BENCHMARKING 17499 17500CATCH_REGISTER_REPORTER ( "xml" , XmlReporter ) 17501 17502} // end namespace Catch 17503 17504#if defined(_MSC_VER) 17505#pragma warning(pop) 17506#endif 17507// end catch_reporter_xml.cpp 17508 17509namespace Catch { 17510LeakDetector leakDetector; 17511} 17512 17513#ifdef __clang__ 17514#pragma clang diagnostic pop 17515#endif 17516 17517// end catch_impl.hpp 17518#endif 17519 17520#ifdef CATCH_CONFIG_MAIN 17521// start catch_default_main.hpp 17522 17523#ifndef __OBJC__ 17524 17525#if defined( CATCH_CONFIG_WCHAR ) && defined( CATCH_PLATFORM_WINDOWS ) && defined(_UNICODE) && !defined( DO_NOT_USE_WMAIN ) 17526// Standard C/C++ Win32 Unicode wmain entry point 17527extern "C" int wmain ( int argc, wchar_t * argv[], wchar_t * []) { 17528#else 17529// Standard C/C++ main entry point 17530int main ( int argc, char * argv[]) { 17531#endif 17532 17533return Catch:: Session (). run ( argc, argv ); 17534} 17535 17536#else // __OBJC__ 17537 17538// Objective-C entry point 17539int main ( int argc, char * const argv[]) { 17540#if ! CATCH_ARC_ENABLED 17541NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 17542#endif 17543 17544Catch::registerTestMethods(); 17545int result = Catch:: Session (). run ( argc, ( char ** )argv ); 17546 17547#if ! CATCH_ARC_ENABLED 17548[ pool drain]; 17549#endif 17550 17551return result; 17552} 17553 17554#endif // __OBJC__ 17555 17556// end catch_default_main.hpp 17557#endif 17558 17559#if !defined( CATCH_CONFIG_IMPL_ONLY ) 17560 17561#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED 17562# undef CLARA_CONFIG_MAIN 17563#endif 17564 17565#if !defined( CATCH_CONFIG_DISABLE ) 17566////// 17567// If this config identifier is defined then all CATCH macros are prefixed with CATCH_ 17568#ifdef CATCH_CONFIG_PREFIX_ALL 17569 17570#define CATCH_REQUIRE ( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17571#define CATCH_REQUIRE_FALSE ( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 17572 17573#define CATCH_REQUIRE_THROWS ( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17574#define CATCH_REQUIRE_THROWS_AS ( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) 17575#define CATCH_REQUIRE_THROWS_WITH ( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) 17576#if !defined( CATCH_CONFIG_DISABLE_MATCHERS ) 17577#define CATCH_REQUIRE_THROWS_MATCHES ( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) 17578#endif // CATCH_CONFIG_DISABLE_MATCHERS 17579#define CATCH_REQUIRE_NOTHROW ( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17580 17581#define CATCH_CHECK ( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17582#define CATCH_CHECK_FALSE ( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 17583#define CATCH_CHECKED_IF ( ... ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17584#define CATCH_CHECKED_ELSE ( ... ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17585#define CATCH_CHECK_NOFAIL ( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) 17586 17587#define CATCH_CHECK_THROWS ( ... ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17588#define CATCH_CHECK_THROWS_AS ( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) 17589#define CATCH_CHECK_THROWS_WITH ( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 17590#if !defined( CATCH_CONFIG_DISABLE_MATCHERS ) 17591#define CATCH_CHECK_THROWS_MATCHES ( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 17592#endif // CATCH_CONFIG_DISABLE_MATCHERS 17593#define CATCH_CHECK_NOTHROW ( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17594 17595#if !defined( CATCH_CONFIG_DISABLE_MATCHERS ) 17596#define CATCH_CHECK_THAT ( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) 17597 17598#define CATCH_REQUIRE_THAT ( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) 17599#endif // CATCH_CONFIG_DISABLE_MATCHERS 17600 17601#define CATCH_INFO ( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) 17602#define CATCH_UNSCOPED_INFO ( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "CATCH_UNSCOPED_INFO", msg ) 17603#define CATCH_WARN ( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) 17604#define CATCH_CAPTURE ( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CATCH_CAPTURE",__VA_ARGS__ ) 17605 17606#define CATCH_TEST_CASE ( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) 17607#define CATCH_TEST_CASE_METHOD ( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17608#define CATCH_METHOD_AS_TEST_CASE ( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) 17609#define CATCH_REGISTER_TEST_CASE ( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) 17610#define CATCH_SECTION ( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) 17611#define CATCH_DYNAMIC_SECTION ( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ ) 17612#define CATCH_FAIL ( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17613#define CATCH_FAIL_CHECK ( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17614#define CATCH_SUCCEED ( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17615 17616#define CATCH_ANON_TEST_CASE () INTERNAL_CATCH_TESTCASE() 17617 17618#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 17619#define CATCH_TEMPLATE_TEST_CASE ( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17620#define CATCH_TEMPLATE_TEST_CASE_SIG ( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) 17621#define CATCH_TEMPLATE_TEST_CASE_METHOD ( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17622#define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG ( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) 17623#define CATCH_TEMPLATE_PRODUCT_TEST_CASE ( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) 17624#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG ( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) 17625#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD ( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17626#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG ( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) 17627#else 17628#define CATCH_TEMPLATE_TEST_CASE ( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) ) 17629#define CATCH_TEMPLATE_TEST_CASE_SIG ( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) ) 17630#define CATCH_TEMPLATE_TEST_CASE_METHOD ( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) 17631#define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG ( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) ) 17632#define CATCH_TEMPLATE_PRODUCT_TEST_CASE ( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) ) 17633#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG ( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) ) 17634#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD ( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) 17635#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG ( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) ) 17636#endif 17637 17638#if !defined( CATCH_CONFIG_RUNTIME_STATIC_REQUIRE ) 17639#define CATCH_STATIC_REQUIRE ( ... ) static_assert( __VA_ARGS__ , #__VA_ARGS__ ); CATCH_SUCCEED( #__VA_ARGS__ ) 17640#define CATCH_STATIC_REQUIRE_FALSE ( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); CATCH_SUCCEED( #__VA_ARGS__ ) 17641#else 17642#define CATCH_STATIC_REQUIRE ( ... ) CATCH_REQUIRE( __VA_ARGS__ ) 17643#define CATCH_STATIC_REQUIRE_FALSE ( ... ) CATCH_REQUIRE_FALSE( __VA_ARGS__ ) 17644#endif 17645 17646// "BDD-style" convenience wrappers 17647#define CATCH_SCENARIO ( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) 17648#define CATCH_SCENARIO_METHOD ( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) 17649#define CATCH_GIVEN ( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc ) 17650#define CATCH_AND_GIVEN ( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc ) 17651#define CATCH_WHEN ( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc ) 17652#define CATCH_AND_WHEN ( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc ) 17653#define CATCH_THEN ( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc ) 17654#define CATCH_AND_THEN ( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc ) 17655 17656#if defined( CATCH_CONFIG_ENABLE_BENCHMARKING ) 17657#define CATCH_BENCHMARK (...) \ 17658INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_B_E_N_C_H_), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,)) 17659#define CATCH_BENCHMARK_ADVANCED (name) \ 17660INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_B_E_N_C_H_), name) 17661#endif // CATCH_CONFIG_ENABLE_BENCHMARKING 17662 17663// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required 17664#else 17665 17666#define REQUIRE ( ... ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17667#define REQUIRE_FALSE ( ... ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 17668 17669#define REQUIRE_THROWS ( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17670#define REQUIRE_THROWS_AS ( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) 17671#define REQUIRE_THROWS_WITH ( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) 17672#if !defined( CATCH_CONFIG_DISABLE_MATCHERS ) 17673#define REQUIRE_THROWS_MATCHES ( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) 17674#endif // CATCH_CONFIG_DISABLE_MATCHERS 17675#define REQUIRE_NOTHROW ( ... ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17676 17677#define CHECK ( ... ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17678#define CHECK_FALSE ( ... ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 17679#define CHECKED_IF ( ... ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17680#define CHECKED_ELSE ( ... ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17681#define CHECK_NOFAIL ( ... ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) 17682 17683#define CHECK_THROWS ( ... ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17684#define CHECK_THROWS_AS ( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) 17685#define CHECK_THROWS_WITH ( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 17686#if !defined( CATCH_CONFIG_DISABLE_MATCHERS ) 17687#define CHECK_THROWS_MATCHES ( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 17688#endif // CATCH_CONFIG_DISABLE_MATCHERS 17689#define CHECK_NOTHROW ( ... ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17690 17691#if !defined( CATCH_CONFIG_DISABLE_MATCHERS ) 17692#define CHECK_THAT ( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) 17693 17694#define REQUIRE_THAT ( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) 17695#endif // CATCH_CONFIG_DISABLE_MATCHERS 17696 17697#define INFO ( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) 17698#define UNSCOPED_INFO ( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "UNSCOPED_INFO", msg ) 17699#define WARN ( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) 17700#define CAPTURE ( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE",__VA_ARGS__ ) 17701 17702#define TEST_CASE ( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) 17703#define TEST_CASE_METHOD ( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17704#define METHOD_AS_TEST_CASE ( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) 17705#define REGISTER_TEST_CASE ( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) 17706#define SECTION ( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) 17707#define DYNAMIC_SECTION ( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ ) 17708#define FAIL ( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) 17709#define FAIL_CHECK ( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17710#define SUCCEED ( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 17711#define ANON_TEST_CASE () INTERNAL_CATCH_TESTCASE() 17712 17713#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 17714#define TEMPLATE_TEST_CASE ( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17715#define TEMPLATE_TEST_CASE_SIG ( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) 17716#define TEMPLATE_TEST_CASE_METHOD ( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17717#define TEMPLATE_TEST_CASE_METHOD_SIG ( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) 17718#define TEMPLATE_PRODUCT_TEST_CASE ( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) 17719#define TEMPLATE_PRODUCT_TEST_CASE_SIG ( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) 17720#define TEMPLATE_PRODUCT_TEST_CASE_METHOD ( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17721#define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG ( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) 17722#define TEMPLATE_LIST_TEST_CASE ( ... ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(__VA_ARGS__) 17723#define TEMPLATE_LIST_TEST_CASE_METHOD ( className, ... ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17724#else 17725#define TEMPLATE_TEST_CASE ( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) ) 17726#define TEMPLATE_TEST_CASE_SIG ( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) ) 17727#define TEMPLATE_TEST_CASE_METHOD ( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) 17728#define TEMPLATE_TEST_CASE_METHOD_SIG ( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) ) 17729#define TEMPLATE_PRODUCT_TEST_CASE ( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) ) 17730#define TEMPLATE_PRODUCT_TEST_CASE_SIG ( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) ) 17731#define TEMPLATE_PRODUCT_TEST_CASE_METHOD ( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) 17732#define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG ( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) ) 17733#define TEMPLATE_LIST_TEST_CASE ( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE( __VA_ARGS__ ) ) 17734#define TEMPLATE_LIST_TEST_CASE_METHOD ( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) 17735#endif 17736 17737#if !defined( CATCH_CONFIG_RUNTIME_STATIC_REQUIRE ) 17738#define STATIC_REQUIRE ( ... ) static_assert( __VA_ARGS__, #__VA_ARGS__ ); SUCCEED( #__VA_ARGS__ ) 17739#define STATIC_REQUIRE_FALSE ( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); SUCCEED( "!(" #__VA_ARGS__ ")" ) 17740#else 17741#define STATIC_REQUIRE ( ... ) REQUIRE( __VA_ARGS__ ) 17742#define STATIC_REQUIRE_FALSE ( ... ) REQUIRE_FALSE( __VA_ARGS__ ) 17743#endif 17744 17745#endif 17746 17747#define CATCH_TRANSLATE_EXCEPTION ( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) 17748 17749// "BDD-style" convenience wrappers 17750#define SCENARIO ( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) 17751#define SCENARIO_METHOD ( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) 17752 17753#define GIVEN ( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc ) 17754#define AND_GIVEN ( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc ) 17755#define WHEN ( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc ) 17756#define AND_WHEN ( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc ) 17757#define THEN ( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc ) 17758#define AND_THEN ( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc ) 17759 17760#if defined( CATCH_CONFIG_ENABLE_BENCHMARKING ) 17761#define BENCHMARK (...) \ 17762INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_B_E_N_C_H_), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,)) 17763#define BENCHMARK_ADVANCED (name) \ 17764INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_B_E_N_C_H_), name) 17765#endif // CATCH_CONFIG_ENABLE_BENCHMARKING 17766 17767using Catch::Detail::Approx; 17768 17769#else // CATCH_CONFIG_DISABLE 17770 17771////// 17772// If this config identifier is defined then all CATCH macros are prefixed with CATCH_ 17773#ifdef CATCH_CONFIG_PREFIX_ALL 17774 17775#define CATCH_REQUIRE ( ... ) (void)(0) 17776#define CATCH_REQUIRE_FALSE ( ... ) (void)(0) 17777 17778#define CATCH_REQUIRE_THROWS ( ... ) (void)(0) 17779#define CATCH_REQUIRE_THROWS_AS ( expr, exceptionType ) (void)(0) 17780#define CATCH_REQUIRE_THROWS_WITH ( expr, matcher ) (void)(0) 17781#if !defined( CATCH_CONFIG_DISABLE_MATCHERS ) 17782#define CATCH_REQUIRE_THROWS_MATCHES ( expr, exceptionType, matcher ) (void)(0) 17783#endif // CATCH_CONFIG_DISABLE_MATCHERS 17784#define CATCH_REQUIRE_NOTHROW ( ... ) (void)(0) 17785 17786#define CATCH_CHECK ( ... ) (void)(0) 17787#define CATCH_CHECK_FALSE ( ... ) (void)(0) 17788#define CATCH_CHECKED_IF ( ... ) if (__VA_ARGS__) 17789#define CATCH_CHECKED_ELSE ( ... ) if (!(__VA_ARGS__)) 17790#define CATCH_CHECK_NOFAIL ( ... ) (void)(0) 17791 17792#define CATCH_CHECK_THROWS ( ... ) (void)(0) 17793#define CATCH_CHECK_THROWS_AS ( expr, exceptionType ) (void)(0) 17794#define CATCH_CHECK_THROWS_WITH ( expr, matcher ) (void)(0) 17795#if !defined( CATCH_CONFIG_DISABLE_MATCHERS ) 17796#define CATCH_CHECK_THROWS_MATCHES ( expr, exceptionType, matcher ) (void)(0) 17797#endif // CATCH_CONFIG_DISABLE_MATCHERS 17798#define CATCH_CHECK_NOTHROW ( ... ) (void)(0) 17799 17800#if !defined( CATCH_CONFIG_DISABLE_MATCHERS ) 17801#define CATCH_CHECK_THAT ( arg, matcher ) (void)(0) 17802 17803#define CATCH_REQUIRE_THAT ( arg, matcher ) (void)(0) 17804#endif // CATCH_CONFIG_DISABLE_MATCHERS 17805 17806#define CATCH_INFO ( msg ) (void)(0) 17807#define CATCH_UNSCOPED_INFO ( msg ) (void)(0) 17808#define CATCH_WARN ( msg ) (void)(0) 17809#define CATCH_CAPTURE ( msg ) (void)(0) 17810 17811#define CATCH_TEST_CASE ( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ )) 17812#define CATCH_TEST_CASE_METHOD ( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ )) 17813#define CATCH_METHOD_AS_TEST_CASE ( method, ... ) 17814#define CATCH_REGISTER_TEST_CASE ( Function, ... ) (void)(0) 17815#define CATCH_SECTION ( ... ) 17816#define CATCH_DYNAMIC_SECTION ( ... ) 17817#define CATCH_FAIL ( ... ) (void)(0) 17818#define CATCH_FAIL_CHECK ( ... ) (void)(0) 17819#define CATCH_SUCCEED ( ... ) (void)(0) 17820 17821#define CATCH_ANON_TEST_CASE () INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ )) 17822 17823#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 17824#define CATCH_TEMPLATE_TEST_CASE ( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) 17825#define CATCH_TEMPLATE_TEST_CASE_SIG ( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) 17826#define CATCH_TEMPLATE_TEST_CASE_METHOD ( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__) 17827#define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG ( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) 17828#define CATCH_TEMPLATE_PRODUCT_TEST_CASE ( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17829#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG ( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17830#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD ( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17831#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG ( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17832#else 17833#define CATCH_TEMPLATE_TEST_CASE ( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) ) 17834#define CATCH_TEMPLATE_TEST_CASE_SIG ( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) ) 17835#define CATCH_TEMPLATE_TEST_CASE_METHOD ( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__ ) ) 17836#define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG ( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) ) 17837#define CATCH_TEMPLATE_PRODUCT_TEST_CASE ( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17838#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG ( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17839#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD ( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17840#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG ( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17841#endif 17842 17843// "BDD-style" convenience wrappers 17844#define CATCH_SCENARIO ( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ )) 17845#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 ) 17846#define CATCH_GIVEN ( desc ) 17847#define CATCH_AND_GIVEN ( desc ) 17848#define CATCH_WHEN ( desc ) 17849#define CATCH_AND_WHEN ( desc ) 17850#define CATCH_THEN ( desc ) 17851#define CATCH_AND_THEN ( desc ) 17852 17853#define CATCH_STATIC_REQUIRE ( ... ) (void)(0) 17854#define CATCH_STATIC_REQUIRE_FALSE ( ... ) (void)(0) 17855 17856// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required 17857#else 17858 17859#define REQUIRE ( ... ) (void)(0) 17860#define REQUIRE_FALSE ( ... ) (void)(0) 17861 17862#define REQUIRE_THROWS ( ... ) (void)(0) 17863#define REQUIRE_THROWS_AS ( expr, exceptionType ) (void)(0) 17864#define REQUIRE_THROWS_WITH ( expr, matcher ) (void)(0) 17865#if !defined( CATCH_CONFIG_DISABLE_MATCHERS ) 17866#define REQUIRE_THROWS_MATCHES ( expr, exceptionType, matcher ) (void)(0) 17867#endif // CATCH_CONFIG_DISABLE_MATCHERS 17868#define REQUIRE_NOTHROW ( ... ) (void)(0) 17869 17870#define CHECK ( ... ) (void)(0) 17871#define CHECK_FALSE ( ... ) (void)(0) 17872#define CHECKED_IF ( ... ) if (__VA_ARGS__) 17873#define CHECKED_ELSE ( ... ) if (!(__VA_ARGS__)) 17874#define CHECK_NOFAIL ( ... ) (void)(0) 17875 17876#define CHECK_THROWS ( ... ) (void)(0) 17877#define CHECK_THROWS_AS ( expr, exceptionType ) (void)(0) 17878#define CHECK_THROWS_WITH ( expr, matcher ) (void)(0) 17879#if !defined( CATCH_CONFIG_DISABLE_MATCHERS ) 17880#define CHECK_THROWS_MATCHES ( expr, exceptionType, matcher ) (void)(0) 17881#endif // CATCH_CONFIG_DISABLE_MATCHERS 17882#define CHECK_NOTHROW ( ... ) (void)(0) 17883 17884#if !defined( CATCH_CONFIG_DISABLE_MATCHERS ) 17885#define CHECK_THAT ( arg, matcher ) (void)(0) 17886 17887#define REQUIRE_THAT ( arg, matcher ) (void)(0) 17888#endif // CATCH_CONFIG_DISABLE_MATCHERS 17889 17890#define INFO ( msg ) (void)(0) 17891#define UNSCOPED_INFO ( msg ) (void)(0) 17892#define WARN ( msg ) (void)(0) 17893#define CAPTURE ( msg ) (void)(0) 17894 17895#define TEST_CASE ( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ )) 17896#define TEST_CASE_METHOD ( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ )) 17897#define METHOD_AS_TEST_CASE ( method, ... ) 17898#define REGISTER_TEST_CASE ( Function, ... ) (void)(0) 17899#define SECTION ( ... ) 17900#define DYNAMIC_SECTION ( ... ) 17901#define FAIL ( ... ) (void)(0) 17902#define FAIL_CHECK ( ... ) (void)(0) 17903#define SUCCEED ( ... ) (void)(0) 17904#define ANON_TEST_CASE () INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ )) 17905 17906#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 17907#define TEMPLATE_TEST_CASE ( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) 17908#define TEMPLATE_TEST_CASE_SIG ( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) 17909#define TEMPLATE_TEST_CASE_METHOD ( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__) 17910#define TEMPLATE_TEST_CASE_METHOD_SIG ( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) 17911#define TEMPLATE_PRODUCT_TEST_CASE ( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17912#define TEMPLATE_PRODUCT_TEST_CASE_SIG ( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17913#define TEMPLATE_PRODUCT_TEST_CASE_METHOD ( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17914#define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG ( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17915#else 17916#define TEMPLATE_TEST_CASE ( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) ) 17917#define TEMPLATE_TEST_CASE_SIG ( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) ) 17918#define TEMPLATE_TEST_CASE_METHOD ( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__ ) ) 17919#define TEMPLATE_TEST_CASE_METHOD_SIG ( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) ) 17920#define TEMPLATE_PRODUCT_TEST_CASE ( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17921#define TEMPLATE_PRODUCT_TEST_CASE_SIG ( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ ) 17922#define TEMPLATE_PRODUCT_TEST_CASE_METHOD ( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17923#define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG ( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 17924#endif 17925 17926#define STATIC_REQUIRE ( ... ) (void)(0) 17927#define STATIC_REQUIRE_FALSE ( ... ) (void)(0) 17928 17929#endif 17930 17931#define CATCH_TRANSLATE_EXCEPTION ( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) 17932 17933// "BDD-style" convenience wrappers 17934#define SCENARIO ( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ) ) 17935#define SCENARIO_METHOD ( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ), className ) 17936 17937#define GIVEN ( desc ) 17938#define AND_GIVEN ( desc ) 17939#define WHEN ( desc ) 17940#define AND_WHEN ( desc ) 17941#define THEN ( desc ) 17942#define AND_THEN ( desc ) 17943 17944using Catch::Detail::Approx; 17945 17946#endif 17947 17948#endif // ! CATCH_CONFIG_IMPL_ONLY 17949 17950// start catch_reenable_warnings.h 17951 17952 17953#ifdef __clang__ 17954# ifdef __ICC // icpc defines the __clang__ macro 17955# pragma warning(pop) 17956# else 17957# pragma clang diagnostic pop 17958# endif 17959#elif defined __GNUC__ 17960# pragma GCC diagnostic pop 17961#endif 17962 17963// end catch_reenable_warnings.h 17964// end catch.hpp 17965#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED