The open source OpenXR runtime
at main 14057 lines 521 kB view raw
1 2// Copyright Catch2 Authors 3// Distributed under the Boost Software License, Version 1.0. 4// (See accompanying file LICENSE.txt or copy at 5// https://www.boost.org/LICENSE_1_0.txt) 6 7// SPDX-License-Identifier: BSL-1.0 8 9// Catch v3.6.0 10// Generated: 2024-05-05 20:53:27.071502 11// ---------------------------------------------------------- 12// This file is an amalgamation of multiple different files. 13// You probably shouldn't edit it directly. 14// ---------------------------------------------------------- 15#ifndef CATCH_AMALGAMATED_HPP_INCLUDED 16#define CATCH_AMALGAMATED_HPP_INCLUDED 17 18 19/** \file 20 * This is a convenience header for Catch2. It includes **all** of Catch2 headers. 21 * 22 * Generally the Catch2 users should use specific includes they need, 23 * but this header can be used instead for ease-of-experimentation, or 24 * just plain convenience, at the cost of (significantly) increased 25 * compilation times. 26 * 27 * When a new header is added to either the top level folder, or to the 28 * corresponding internal subfolder, it should be added here. Headers 29 * added to the various subparts (e.g. matchers, generators, etc...), 30 * should go their respective catch-all headers. 31 */ 32 33#ifndef CATCH_ALL_HPP_INCLUDED 34#define CATCH_ALL_HPP_INCLUDED 35 36 37 38/** \file 39 * This is a convenience header for Catch2's benchmarking. It includes 40 * **all** of Catch2 headers related to benchmarking. 41 * 42 * Generally the Catch2 users should use specific includes they need, 43 * but this header can be used instead for ease-of-experimentation, or 44 * just plain convenience, at the cost of (significantly) increased 45 * compilation times. 46 * 47 * When a new header is added to either the `benchmark` folder, or to 48 * the corresponding internal (detail) subfolder, it should be added here. 49 */ 50 51#ifndef CATCH_BENCHMARK_ALL_HPP_INCLUDED 52#define CATCH_BENCHMARK_ALL_HPP_INCLUDED 53 54 55 56// Adapted from donated nonius code. 57 58#ifndef CATCH_BENCHMARK_HPP_INCLUDED 59#define CATCH_BENCHMARK_HPP_INCLUDED 60 61 62 63#ifndef CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED 64#define CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED 65 66// Detect a number of compiler features - by compiler 67// The following features are defined: 68// 69// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported? 70// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported? 71// CATCH_CONFIG_DISABLE_EXCEPTIONS : Are exceptions enabled? 72// **************** 73// Note to maintainers: if new toggles are added please document them 74// in configuration.md, too 75// **************** 76 77// In general each macro has a _NO_<feature name> form 78// (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature. 79// Many features, at point of detection, define an _INTERNAL_ macro, so they 80// can be combined, en-mass, with the _NO_ forms later. 81 82 83 84#ifndef CATCH_PLATFORM_HPP_INCLUDED 85#define CATCH_PLATFORM_HPP_INCLUDED 86 87// See e.g.: 88// https://opensource.apple.com/source/CarbonHeaders/CarbonHeaders-18.1/TargetConditionals.h.auto.html 89#ifdef __APPLE__ 90# ifndef __has_extension 91# define __has_extension(x) 0 92# endif 93# include <TargetConditionals.h> 94# if (defined(TARGET_OS_OSX) && TARGET_OS_OSX == 1) || \ 95 (defined(TARGET_OS_MAC) && TARGET_OS_MAC == 1) 96# define CATCH_PLATFORM_MAC 97# elif (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1) 98# define CATCH_PLATFORM_IPHONE 99# endif 100 101#elif defined(linux) || defined(__linux) || defined(__linux__) 102# define CATCH_PLATFORM_LINUX 103 104#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__) 105# define CATCH_PLATFORM_WINDOWS 106 107# if defined( WINAPI_FAMILY ) && ( WINAPI_FAMILY == WINAPI_FAMILY_APP ) 108# define CATCH_PLATFORM_WINDOWS_UWP 109# endif 110 111#elif defined(__ORBIS__) || defined(__PROSPERO__) 112# define CATCH_PLATFORM_PLAYSTATION 113 114#endif 115 116#endif // CATCH_PLATFORM_HPP_INCLUDED 117 118#ifdef __cplusplus 119 120# if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) 121# define CATCH_CPP17_OR_GREATER 122# endif 123 124# if (__cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) 125# define CATCH_CPP20_OR_GREATER 126# endif 127 128#endif 129 130// Only GCC compiler should be used in this block, so other compilers trying to 131// mask themselves as GCC should be ignored. 132#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__) && !defined(__LCC__) && !defined(__NVCOMPILER) 133# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" ) 134# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" ) 135 136// This only works on GCC 9+. so we have to also add a global suppression of Wparentheses 137// for older versions of GCC. 138# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ 139 _Pragma( "GCC diagnostic ignored \"-Wparentheses\"" ) 140 141# define CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT \ 142 _Pragma( "GCC diagnostic ignored \"-Wunused-result\"" ) 143 144# define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ 145 _Pragma( "GCC diagnostic ignored \"-Wunused-variable\"" ) 146 147# define CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \ 148 _Pragma( "GCC diagnostic ignored \"-Wuseless-cast\"" ) 149 150# define CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \ 151 _Pragma( "GCC diagnostic ignored \"-Wshadow\"" ) 152 153# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) 154 155#endif 156 157#if defined(__NVCOMPILER) 158# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "diag push" ) 159# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "diag pop" ) 160# define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS _Pragma( "diag_suppress declared_but_not_referenced" ) 161#endif 162 163#if defined(__CUDACC__) && !defined(__clang__) 164# ifdef __NVCC_DIAG_PRAGMA_SUPPORT__ 165// New pragmas introduced in CUDA 11.5+ 166# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "nv_diagnostic push" ) 167# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "nv_diagnostic pop" ) 168# define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS _Pragma( "nv_diag_suppress 177" ) 169# else 170# define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS _Pragma( "diag_suppress 177" ) 171# endif 172#endif 173 174// clang-cl defines _MSC_VER as well as __clang__, which could cause the 175// start/stop internal suppression macros to be double defined. 176#if defined(__clang__) && !defined(_MSC_VER) 177 178# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" ) 179# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic pop" ) 180 181#endif // __clang__ && !_MSC_VER 182 183#if defined(__clang__) 184 185// As of this writing, IBM XL's implementation of __builtin_constant_p has a bug 186// which results in calls to destructors being emitted for each temporary, 187// without a matching initialization. In practice, this can result in something 188// like `std::string::~string` being called on an uninitialized value. 189// 190// For example, this code will likely segfault under IBM XL: 191// ``` 192// REQUIRE(std::string("12") + "34" == "1234") 193// ``` 194// 195// Similarly, NVHPC's implementation of `__builtin_constant_p` has a bug which 196// results in calls to the immediately evaluated lambda expressions to be 197// reported as unevaluated lambdas. 198// https://developer.nvidia.com/nvidia_bug/3321845. 199// 200// Therefore, `CATCH_INTERNAL_IGNORE_BUT_WARN` is not implemented. 201# if !defined(__ibmxl__) && !defined(__CUDACC__) && !defined( __NVCOMPILER ) 202# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) /* NOLINT(cppcoreguidelines-pro-type-vararg, hicpp-vararg) */ 203# endif 204 205 206# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 207 _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ 208 _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") 209 210# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ 211 _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) 212 213# define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ 214 _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" ) 215 216# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ 217 _Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" ) 218 219# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 220 _Pragma( "clang diagnostic ignored \"-Wunused-template\"" ) 221 222# define CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS \ 223 _Pragma( "clang diagnostic ignored \"-Wcomma\"" ) 224 225# define CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \ 226 _Pragma( "clang diagnostic ignored \"-Wshadow\"" ) 227 228#endif // __clang__ 229 230 231//////////////////////////////////////////////////////////////////////////////// 232// We know some environments not to support full POSIX signals 233#if defined( CATCH_PLATFORM_WINDOWS ) || \ 234 defined( CATCH_PLATFORM_PLAYSTATION ) || \ 235 defined( __CYGWIN__ ) || \ 236 defined( __QNX__ ) || \ 237 defined( __EMSCRIPTEN__ ) || \ 238 defined( __DJGPP__ ) || \ 239 defined( __OS400__ ) 240# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS 241#else 242# define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS 243#endif 244 245//////////////////////////////////////////////////////////////////////////////// 246// Assume that some platforms do not support getenv. 247#if defined( CATCH_PLATFORM_WINDOWS_UWP ) || \ 248 defined( CATCH_PLATFORM_PLAYSTATION ) || \ 249 defined( _GAMING_XBOX ) 250# define CATCH_INTERNAL_CONFIG_NO_GETENV 251#else 252# define CATCH_INTERNAL_CONFIG_GETENV 253#endif 254 255//////////////////////////////////////////////////////////////////////////////// 256// Android somehow still does not support std::to_string 257#if defined(__ANDROID__) 258# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING 259#endif 260 261//////////////////////////////////////////////////////////////////////////////// 262// Not all Windows environments support SEH properly 263#if defined(__MINGW32__) 264# define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH 265#endif 266 267//////////////////////////////////////////////////////////////////////////////// 268// PS4 269#if defined(__ORBIS__) 270# define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE 271#endif 272 273//////////////////////////////////////////////////////////////////////////////// 274// Cygwin 275#ifdef __CYGWIN__ 276 277// Required for some versions of Cygwin to declare gettimeofday 278// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin 279# define _BSD_SOURCE 280// some versions of cygwin (most) do not support std::to_string. Use the libstd check. 281// https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813 282# if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \ 283 && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF)) 284 285# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING 286 287# endif 288#endif // __CYGWIN__ 289 290//////////////////////////////////////////////////////////////////////////////// 291// Visual C++ 292#if defined(_MSC_VER) 293 294// We want to defer to nvcc-specific warning suppression if we are compiled 295// with nvcc masquerading for MSVC. 296# if !defined( __CUDACC__ ) 297# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 298 __pragma( warning( push ) ) 299# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 300 __pragma( warning( pop ) ) 301# endif 302 303// Universal Windows platform does not support SEH 304// Or console colours (or console at all...) 305# if defined(CATCH_PLATFORM_WINDOWS_UWP) 306# define CATCH_INTERNAL_CONFIG_NO_COLOUR_WIN32 307# else 308# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH 309# endif 310 311// MSVC traditional preprocessor needs some workaround for __VA_ARGS__ 312// _MSVC_TRADITIONAL == 0 means new conformant preprocessor 313// _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor 314# if !defined(__clang__) // Handle Clang masquerading for msvc 315# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) 316# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 317# endif // MSVC_TRADITIONAL 318# endif // __clang__ 319 320#endif // _MSC_VER 321 322#if defined(_REENTRANT) || defined(_MSC_VER) 323// Enable async processing, as -pthread is specified or no additional linking is required 324# define CATCH_INTERNAL_CONFIG_USE_ASYNC 325#endif // _MSC_VER 326 327//////////////////////////////////////////////////////////////////////////////// 328// Check if we are compiled with -fno-exceptions or equivalent 329#if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND) 330# define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED 331#endif 332 333 334//////////////////////////////////////////////////////////////////////////////// 335// Embarcadero C++Build 336#if defined(__BORLANDC__) 337 #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN 338#endif 339 340//////////////////////////////////////////////////////////////////////////////// 341 342// RTX is a special version of Windows that is real time. 343// This means that it is detected as Windows, but does not provide 344// the same set of capabilities as real Windows does. 345#if defined(UNDER_RTSS) || defined(RTX64_BUILD) 346 #define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH 347 #define CATCH_INTERNAL_CONFIG_NO_ASYNC 348 #define CATCH_INTERNAL_CONFIG_NO_COLOUR_WIN32 349#endif 350 351#if !defined(_GLIBCXX_USE_C99_MATH_TR1) 352#define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER 353#endif 354 355// Various stdlib support checks that require __has_include 356#if defined(__has_include) 357 // Check if string_view is available and usable 358 #if __has_include(<string_view>) && defined(CATCH_CPP17_OR_GREATER) 359 # define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW 360 #endif 361 362 // Check if optional is available and usable 363 # if __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER) 364 # define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL 365 # endif // __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER) 366 367 // Check if byte is available and usable 368 # if __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER) 369 # include <cstddef> 370 # if defined(__cpp_lib_byte) && (__cpp_lib_byte > 0) 371 # define CATCH_INTERNAL_CONFIG_CPP17_BYTE 372 # endif 373 # endif // __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER) 374 375 // Check if variant is available and usable 376 # if __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER) 377 # if defined(__clang__) && (__clang_major__ < 8) 378 // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852 379 // fix should be in clang 8, workaround in libstdc++ 8.2 380 # include <ciso646> 381 # if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) 382 # define CATCH_CONFIG_NO_CPP17_VARIANT 383 # else 384 # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT 385 # endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) 386 # else 387 # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT 388 # endif // defined(__clang__) && (__clang_major__ < 8) 389 # endif // __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER) 390#endif // defined(__has_include) 391 392 393#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) 394# define CATCH_CONFIG_WINDOWS_SEH 395#endif 396// This is set by default, because we assume that unix compilers are posix-signal-compatible by default. 397#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) 398# define CATCH_CONFIG_POSIX_SIGNALS 399#endif 400 401#if defined(CATCH_INTERNAL_CONFIG_GETENV) && !defined(CATCH_INTERNAL_CONFIG_NO_GETENV) && !defined(CATCH_CONFIG_NO_GETENV) && !defined(CATCH_CONFIG_GETENV) 402# define CATCH_CONFIG_GETENV 403#endif 404 405#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING) 406# define CATCH_CONFIG_CPP11_TO_STRING 407#endif 408 409#if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL) 410# define CATCH_CONFIG_CPP17_OPTIONAL 411#endif 412 413#if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW) 414# define CATCH_CONFIG_CPP17_STRING_VIEW 415#endif 416 417#if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT) 418# define CATCH_CONFIG_CPP17_VARIANT 419#endif 420 421#if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && !defined(CATCH_CONFIG_NO_CPP17_BYTE) && !defined(CATCH_CONFIG_CPP17_BYTE) 422# define CATCH_CONFIG_CPP17_BYTE 423#endif 424 425 426#if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) 427# define CATCH_INTERNAL_CONFIG_NEW_CAPTURE 428#endif 429 430#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) 431# define CATCH_CONFIG_NEW_CAPTURE 432#endif 433 434#if !defined( CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED ) && \ 435 !defined( CATCH_CONFIG_DISABLE_EXCEPTIONS ) && \ 436 !defined( CATCH_CONFIG_NO_DISABLE_EXCEPTIONS ) 437# define CATCH_CONFIG_DISABLE_EXCEPTIONS 438#endif 439 440#if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN) 441# define CATCH_CONFIG_POLYFILL_ISNAN 442#endif 443 444#if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC) 445# define CATCH_CONFIG_USE_ASYNC 446#endif 447 448#if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER) 449# define CATCH_CONFIG_GLOBAL_NEXTAFTER 450#endif 451 452 453// Even if we do not think the compiler has that warning, we still have 454// to provide a macro that can be used by the code. 455#if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION) 456# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION 457#endif 458#if !defined(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION) 459# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 460#endif 461#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) 462# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS 463#endif 464#if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS) 465# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS 466#endif 467#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT) 468# define CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT 469#endif 470#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS) 471# define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS 472#endif 473#if !defined(CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS) 474# define CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS 475#endif 476#if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS) 477# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS 478#endif 479#if !defined( CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS ) 480# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS 481#endif 482#if !defined( CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS ) 483# define CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS 484#endif 485#if !defined( CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS ) 486# define CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS 487#endif 488 489 490// The goal of this macro is to avoid evaluation of the arguments, but 491// still have the compiler warn on problems inside... 492#if !defined(CATCH_INTERNAL_IGNORE_BUT_WARN) 493# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) 494#endif 495 496#if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10) 497# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS 498#elif defined(__clang__) && (__clang_major__ < 5) 499# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS 500#endif 501 502 503#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 504#define CATCH_TRY if ((true)) 505#define CATCH_CATCH_ALL if ((false)) 506#define CATCH_CATCH_ANON(type) if ((false)) 507#else 508#define CATCH_TRY try 509#define CATCH_CATCH_ALL catch (...) 510#define CATCH_CATCH_ANON(type) catch (type) 511#endif 512 513#if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) 514#define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 515#endif 516 517#if defined( CATCH_PLATFORM_WINDOWS ) && \ 518 !defined( CATCH_CONFIG_COLOUR_WIN32 ) && \ 519 !defined( CATCH_CONFIG_NO_COLOUR_WIN32 ) && \ 520 !defined( CATCH_INTERNAL_CONFIG_NO_COLOUR_WIN32 ) 521# define CATCH_CONFIG_COLOUR_WIN32 522#endif 523 524#if defined( CATCH_CONFIG_SHARED_LIBRARY ) && defined( _MSC_VER ) && \ 525 !defined( CATCH_CONFIG_STATIC ) 526# ifdef Catch2_EXPORTS 527# define CATCH_EXPORT //__declspec( dllexport ) // not needed 528# else 529# define CATCH_EXPORT __declspec( dllimport ) 530# endif 531#else 532# define CATCH_EXPORT 533#endif 534 535#endif // CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED 536 537 538#ifndef CATCH_CONTEXT_HPP_INCLUDED 539#define CATCH_CONTEXT_HPP_INCLUDED 540 541 542namespace Catch { 543 544 class IResultCapture; 545 class IConfig; 546 547 class Context { 548 IConfig const* m_config = nullptr; 549 IResultCapture* m_resultCapture = nullptr; 550 551 CATCH_EXPORT static Context* currentContext; 552 friend Context& getCurrentMutableContext(); 553 friend Context const& getCurrentContext(); 554 static void createContext(); 555 friend void cleanUpContext(); 556 557 public: 558 IResultCapture* getResultCapture() const { return m_resultCapture; } 559 IConfig const* getConfig() const { return m_config; } 560 void setResultCapture( IResultCapture* resultCapture ); 561 void setConfig( IConfig const* config ); 562 }; 563 564 Context& getCurrentMutableContext(); 565 566 inline Context const& getCurrentContext() { 567 // We duplicate the logic from `getCurrentMutableContext` here, 568 // to avoid paying the call overhead in debug mode. 569 if ( !Context::currentContext ) { Context::createContext(); } 570 // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn) 571 return *Context::currentContext; 572 } 573 574 void cleanUpContext(); 575 576 class SimplePcg32; 577 SimplePcg32& sharedRng(); 578} 579 580#endif // CATCH_CONTEXT_HPP_INCLUDED 581 582 583#ifndef CATCH_MOVE_AND_FORWARD_HPP_INCLUDED 584#define CATCH_MOVE_AND_FORWARD_HPP_INCLUDED 585 586#include <type_traits> 587 588//! Replacement for std::move with better compile time performance 589#define CATCH_MOVE(...) static_cast<std::remove_reference_t<decltype(__VA_ARGS__)>&&>(__VA_ARGS__) 590 591//! Replacement for std::forward with better compile time performance 592#define CATCH_FORWARD(...) static_cast<decltype(__VA_ARGS__)&&>(__VA_ARGS__) 593 594#endif // CATCH_MOVE_AND_FORWARD_HPP_INCLUDED 595 596 597#ifndef CATCH_TEST_FAILURE_EXCEPTION_HPP_INCLUDED 598#define CATCH_TEST_FAILURE_EXCEPTION_HPP_INCLUDED 599 600namespace Catch { 601 602 //! Used to signal that an assertion macro failed 603 struct TestFailureException{}; 604 //! Used to signal that the remainder of a test should be skipped 605 struct TestSkipException {}; 606 607 /** 608 * Outlines throwing of `TestFailureException` into a single TU 609 * 610 * Also handles `CATCH_CONFIG_DISABLE_EXCEPTIONS` for callers. 611 */ 612 [[noreturn]] void throw_test_failure_exception(); 613 614 /** 615 * Outlines throwing of `TestSkipException` into a single TU 616 * 617 * Also handles `CATCH_CONFIG_DISABLE_EXCEPTIONS` for callers. 618 */ 619 [[noreturn]] void throw_test_skip_exception(); 620 621} // namespace Catch 622 623#endif // CATCH_TEST_FAILURE_EXCEPTION_HPP_INCLUDED 624 625 626#ifndef CATCH_UNIQUE_NAME_HPP_INCLUDED 627#define CATCH_UNIQUE_NAME_HPP_INCLUDED 628 629 630 631 632/** \file 633 * Wrapper for the CONFIG configuration option 634 * 635 * When generating internal unique names, there are two options. Either 636 * we mix in the current line number, or mix in an incrementing number. 637 * We prefer the latter, using `__COUNTER__`, but users might want to 638 * use the former. 639 */ 640 641#ifndef CATCH_CONFIG_COUNTER_HPP_INCLUDED 642#define CATCH_CONFIG_COUNTER_HPP_INCLUDED 643 644 645#if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L ) 646 #define CATCH_INTERNAL_CONFIG_COUNTER 647#endif 648 649#if defined( CATCH_INTERNAL_CONFIG_COUNTER ) && \ 650 !defined( CATCH_CONFIG_NO_COUNTER ) && \ 651 !defined( CATCH_CONFIG_COUNTER ) 652# define CATCH_CONFIG_COUNTER 653#endif 654 655 656#endif // CATCH_CONFIG_COUNTER_HPP_INCLUDED 657#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line 658#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) 659#ifdef CATCH_CONFIG_COUNTER 660# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) 661#else 662# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) 663#endif 664 665#endif // CATCH_UNIQUE_NAME_HPP_INCLUDED 666 667 668#ifndef CATCH_INTERFACES_CAPTURE_HPP_INCLUDED 669#define CATCH_INTERFACES_CAPTURE_HPP_INCLUDED 670 671#include <string> 672#include <chrono> 673 674 675 676#ifndef CATCH_STRINGREF_HPP_INCLUDED 677#define CATCH_STRINGREF_HPP_INCLUDED 678 679#include <cstddef> 680#include <string> 681#include <iosfwd> 682#include <cassert> 683 684#include <cstring> 685 686namespace Catch { 687 688 /// A non-owning string class (similar to the forthcoming std::string_view) 689 /// Note that, because a StringRef may be a substring of another string, 690 /// it may not be null terminated. 691 class StringRef { 692 public: 693 using size_type = std::size_t; 694 using const_iterator = const char*; 695 696 static constexpr size_type npos{ static_cast<size_type>( -1 ) }; 697 698 private: 699 static constexpr char const* const s_empty = ""; 700 701 char const* m_start = s_empty; 702 size_type m_size = 0; 703 704 public: // construction 705 constexpr StringRef() noexcept = default; 706 707 StringRef( char const* rawChars ) noexcept; 708 709 constexpr StringRef( char const* rawChars, size_type size ) noexcept 710 : m_start( rawChars ), 711 m_size( size ) 712 {} 713 714 StringRef( std::string const& stdString ) noexcept 715 : m_start( stdString.c_str() ), 716 m_size( stdString.size() ) 717 {} 718 719 explicit operator std::string() const { 720 return std::string(m_start, m_size); 721 } 722 723 public: // operators 724 auto operator == ( StringRef other ) const noexcept -> bool { 725 return m_size == other.m_size 726 && (std::memcmp( m_start, other.m_start, m_size ) == 0); 727 } 728 auto operator != (StringRef other) const noexcept -> bool { 729 return !(*this == other); 730 } 731 732 constexpr auto operator[] ( size_type index ) const noexcept -> char { 733 assert(index < m_size); 734 return m_start[index]; 735 } 736 737 bool operator<(StringRef rhs) const noexcept; 738 739 public: // named queries 740 constexpr auto empty() const noexcept -> bool { 741 return m_size == 0; 742 } 743 constexpr auto size() const noexcept -> size_type { 744 return m_size; 745 } 746 747 // Returns a substring of [start, start + length). 748 // If start + length > size(), then the substring is [start, size()). 749 // If start > size(), then the substring is empty. 750 constexpr StringRef substr(size_type start, size_type length) const noexcept { 751 if (start < m_size) { 752 const auto shortened_size = m_size - start; 753 return StringRef(m_start + start, (shortened_size < length) ? shortened_size : length); 754 } else { 755 return StringRef(); 756 } 757 } 758 759 // Returns the current start pointer. May not be null-terminated. 760 constexpr char const* data() const noexcept { 761 return m_start; 762 } 763 764 constexpr const_iterator begin() const { return m_start; } 765 constexpr const_iterator end() const { return m_start + m_size; } 766 767 768 friend std::string& operator += (std::string& lhs, StringRef rhs); 769 friend std::ostream& operator << (std::ostream& os, StringRef str); 770 friend std::string operator+(StringRef lhs, StringRef rhs); 771 772 /** 773 * Provides a three-way comparison with rhs 774 * 775 * Returns negative number if lhs < rhs, 0 if lhs == rhs, and a positive 776 * number if lhs > rhs 777 */ 778 int compare( StringRef rhs ) const; 779 }; 780 781 782 constexpr auto operator ""_sr( char const* rawChars, std::size_t size ) noexcept -> StringRef { 783 return StringRef( rawChars, size ); 784 } 785} // namespace Catch 786 787constexpr auto operator ""_catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef { 788 return Catch::StringRef( rawChars, size ); 789} 790 791#endif // CATCH_STRINGREF_HPP_INCLUDED 792 793 794#ifndef CATCH_RESULT_TYPE_HPP_INCLUDED 795#define CATCH_RESULT_TYPE_HPP_INCLUDED 796 797namespace Catch { 798 799 // ResultWas::OfType enum 800 struct ResultWas { enum OfType { 801 Unknown = -1, 802 Ok = 0, 803 Info = 1, 804 Warning = 2, 805 // TODO: Should explicit skip be considered "not OK" (cf. isOk)? I.e., should it have the failure bit? 806 ExplicitSkip = 4, 807 808 FailureBit = 0x10, 809 810 ExpressionFailed = FailureBit | 1, 811 ExplicitFailure = FailureBit | 2, 812 813 Exception = 0x100 | FailureBit, 814 815 ThrewException = Exception | 1, 816 DidntThrowException = Exception | 2, 817 818 FatalErrorCondition = 0x200 | FailureBit 819 820 }; }; 821 822 bool isOk( ResultWas::OfType resultType ); 823 bool isJustInfo( int flags ); 824 825 826 // ResultDisposition::Flags enum 827 struct ResultDisposition { enum Flags { 828 Normal = 0x01, 829 830 ContinueOnFailure = 0x02, // Failures fail test, but execution continues 831 FalseTest = 0x04, // Prefix expression with ! 832 SuppressFail = 0x08 // Failures are reported but do not fail the test 833 }; }; 834 835 ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ); 836 837 bool shouldContinueOnFailure( int flags ); 838 inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; } 839 bool shouldSuppressFailure( int flags ); 840 841} // end namespace Catch 842 843#endif // CATCH_RESULT_TYPE_HPP_INCLUDED 844 845 846#ifndef CATCH_UNIQUE_PTR_HPP_INCLUDED 847#define CATCH_UNIQUE_PTR_HPP_INCLUDED 848 849#include <cassert> 850#include <type_traits> 851 852 853namespace Catch { 854namespace Detail { 855 /** 856 * A reimplementation of `std::unique_ptr` for improved compilation performance 857 * 858 * Does not support arrays nor custom deleters. 859 */ 860 template <typename T> 861 class unique_ptr { 862 T* m_ptr; 863 public: 864 constexpr unique_ptr(std::nullptr_t = nullptr): 865 m_ptr{} 866 {} 867 explicit constexpr unique_ptr(T* ptr): 868 m_ptr(ptr) 869 {} 870 871 template <typename U, typename = std::enable_if_t<std::is_base_of<T, U>::value>> 872 unique_ptr(unique_ptr<U>&& from): 873 m_ptr(from.release()) 874 {} 875 876 template <typename U, typename = std::enable_if_t<std::is_base_of<T, U>::value>> 877 unique_ptr& operator=(unique_ptr<U>&& from) { 878 reset(from.release()); 879 880 return *this; 881 } 882 883 unique_ptr(unique_ptr const&) = delete; 884 unique_ptr& operator=(unique_ptr const&) = delete; 885 886 unique_ptr(unique_ptr&& rhs) noexcept: 887 m_ptr(rhs.m_ptr) { 888 rhs.m_ptr = nullptr; 889 } 890 unique_ptr& operator=(unique_ptr&& rhs) noexcept { 891 reset(rhs.release()); 892 893 return *this; 894 } 895 896 ~unique_ptr() { 897 delete m_ptr; 898 } 899 900 T& operator*() { 901 assert(m_ptr); 902 return *m_ptr; 903 } 904 T const& operator*() const { 905 assert(m_ptr); 906 return *m_ptr; 907 } 908 T* operator->() noexcept { 909 assert(m_ptr); 910 return m_ptr; 911 } 912 T const* operator->() const noexcept { 913 assert(m_ptr); 914 return m_ptr; 915 } 916 917 T* get() { return m_ptr; } 918 T const* get() const { return m_ptr; } 919 920 void reset(T* ptr = nullptr) { 921 delete m_ptr; 922 m_ptr = ptr; 923 } 924 925 T* release() { 926 auto temp = m_ptr; 927 m_ptr = nullptr; 928 return temp; 929 } 930 931 explicit operator bool() const { 932 return m_ptr; 933 } 934 935 friend void swap(unique_ptr& lhs, unique_ptr& rhs) { 936 auto temp = lhs.m_ptr; 937 lhs.m_ptr = rhs.m_ptr; 938 rhs.m_ptr = temp; 939 } 940 }; 941 942 //! Specialization to cause compile-time error for arrays 943 template <typename T> 944 class unique_ptr<T[]>; 945 946 template <typename T, typename... Args> 947 unique_ptr<T> make_unique(Args&&... args) { 948 return unique_ptr<T>(new T(CATCH_FORWARD(args)...)); 949 } 950 951 952} // end namespace Detail 953} // end namespace Catch 954 955#endif // CATCH_UNIQUE_PTR_HPP_INCLUDED 956 957 958#ifndef CATCH_BENCHMARK_STATS_FWD_HPP_INCLUDED 959#define CATCH_BENCHMARK_STATS_FWD_HPP_INCLUDED 960 961 962 963// Adapted from donated nonius code. 964 965#ifndef CATCH_CLOCK_HPP_INCLUDED 966#define CATCH_CLOCK_HPP_INCLUDED 967 968#include <chrono> 969 970namespace Catch { 971 namespace Benchmark { 972 using IDuration = std::chrono::nanoseconds; 973 using FDuration = std::chrono::duration<double, std::nano>; 974 975 template <typename Clock> 976 using TimePoint = typename Clock::time_point; 977 978 using default_clock = std::chrono::steady_clock; 979 } // namespace Benchmark 980} // namespace Catch 981 982#endif // CATCH_CLOCK_HPP_INCLUDED 983 984namespace Catch { 985 986 // We cannot forward declare the type with default template argument 987 // multiple times, so it is split out into a separate header so that 988 // we can prevent multiple declarations in dependees 989 template <typename Duration = Benchmark::FDuration> 990 struct BenchmarkStats; 991 992} // end namespace Catch 993 994#endif // CATCH_BENCHMARK_STATS_FWD_HPP_INCLUDED 995 996namespace Catch { 997 998 class AssertionResult; 999 struct AssertionInfo; 1000 struct SectionInfo; 1001 struct SectionEndInfo; 1002 struct MessageInfo; 1003 struct MessageBuilder; 1004 struct Counts; 1005 struct AssertionReaction; 1006 struct SourceLineInfo; 1007 1008 class ITransientExpression; 1009 class IGeneratorTracker; 1010 1011 struct BenchmarkInfo; 1012 1013 namespace Generators { 1014 class GeneratorUntypedBase; 1015 using GeneratorBasePtr = Catch::Detail::unique_ptr<GeneratorUntypedBase>; 1016 } 1017 1018 1019 class IResultCapture { 1020 public: 1021 virtual ~IResultCapture(); 1022 1023 virtual void notifyAssertionStarted( AssertionInfo const& info ) = 0; 1024 virtual bool sectionStarted( StringRef sectionName, 1025 SourceLineInfo const& sectionLineInfo, 1026 Counts& assertions ) = 0; 1027 virtual void sectionEnded( SectionEndInfo&& endInfo ) = 0; 1028 virtual void sectionEndedEarly( SectionEndInfo&& endInfo ) = 0; 1029 1030 virtual IGeneratorTracker* 1031 acquireGeneratorTracker( StringRef generatorName, 1032 SourceLineInfo const& lineInfo ) = 0; 1033 virtual IGeneratorTracker* 1034 createGeneratorTracker( StringRef generatorName, 1035 SourceLineInfo lineInfo, 1036 Generators::GeneratorBasePtr&& generator ) = 0; 1037 1038 virtual void benchmarkPreparing( StringRef name ) = 0; 1039 virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0; 1040 virtual void benchmarkEnded( BenchmarkStats<> const& stats ) = 0; 1041 virtual void benchmarkFailed( StringRef error ) = 0; 1042 1043 virtual void pushScopedMessage( MessageInfo const& message ) = 0; 1044 virtual void popScopedMessage( MessageInfo const& message ) = 0; 1045 1046 virtual void emplaceUnscopedMessage( MessageBuilder&& builder ) = 0; 1047 1048 virtual void handleFatalErrorCondition( StringRef message ) = 0; 1049 1050 virtual void handleExpr 1051 ( AssertionInfo const& info, 1052 ITransientExpression const& expr, 1053 AssertionReaction& reaction ) = 0; 1054 virtual void handleMessage 1055 ( AssertionInfo const& info, 1056 ResultWas::OfType resultType, 1057 StringRef message, 1058 AssertionReaction& reaction ) = 0; 1059 virtual void handleUnexpectedExceptionNotThrown 1060 ( AssertionInfo const& info, 1061 AssertionReaction& reaction ) = 0; 1062 virtual void handleUnexpectedInflightException 1063 ( AssertionInfo const& info, 1064 std::string&& message, 1065 AssertionReaction& reaction ) = 0; 1066 virtual void handleIncomplete 1067 ( AssertionInfo const& info ) = 0; 1068 virtual void handleNonExpr 1069 ( AssertionInfo const &info, 1070 ResultWas::OfType resultType, 1071 AssertionReaction &reaction ) = 0; 1072 1073 1074 1075 virtual bool lastAssertionPassed() = 0; 1076 virtual void assertionPassed() = 0; 1077 1078 // Deprecated, do not use: 1079 virtual std::string getCurrentTestName() const = 0; 1080 virtual const AssertionResult* getLastResult() const = 0; 1081 virtual void exceptionEarlyReported() = 0; 1082 }; 1083 1084 IResultCapture& getResultCapture(); 1085} 1086 1087#endif // CATCH_INTERFACES_CAPTURE_HPP_INCLUDED 1088 1089 1090#ifndef CATCH_INTERFACES_CONFIG_HPP_INCLUDED 1091#define CATCH_INTERFACES_CONFIG_HPP_INCLUDED 1092 1093 1094 1095#ifndef CATCH_NONCOPYABLE_HPP_INCLUDED 1096#define CATCH_NONCOPYABLE_HPP_INCLUDED 1097 1098namespace Catch { 1099 namespace Detail { 1100 1101 //! Deriving classes become noncopyable and nonmovable 1102 class NonCopyable { 1103 NonCopyable( NonCopyable const& ) = delete; 1104 NonCopyable( NonCopyable&& ) = delete; 1105 NonCopyable& operator=( NonCopyable const& ) = delete; 1106 NonCopyable& operator=( NonCopyable&& ) = delete; 1107 1108 protected: 1109 NonCopyable() noexcept = default; 1110 }; 1111 1112 } // namespace Detail 1113} // namespace Catch 1114 1115#endif // CATCH_NONCOPYABLE_HPP_INCLUDED 1116 1117#include <chrono> 1118#include <iosfwd> 1119#include <string> 1120#include <vector> 1121 1122namespace Catch { 1123 1124 enum class Verbosity { 1125 Quiet = 0, 1126 Normal, 1127 High 1128 }; 1129 1130 struct WarnAbout { enum What { 1131 Nothing = 0x00, 1132 //! A test case or leaf section did not run any assertions 1133 NoAssertions = 0x01, 1134 //! A command line test spec matched no test cases 1135 UnmatchedTestSpec = 0x02, 1136 }; }; 1137 1138 enum class ShowDurations { 1139 DefaultForReporter, 1140 Always, 1141 Never 1142 }; 1143 enum class TestRunOrder { 1144 Declared, 1145 LexicographicallySorted, 1146 Randomized 1147 }; 1148 enum class ColourMode : std::uint8_t { 1149 //! Let Catch2 pick implementation based on platform detection 1150 PlatformDefault, 1151 //! Use ANSI colour code escapes 1152 ANSI, 1153 //! Use Win32 console colour API 1154 Win32, 1155 //! Don't use any colour 1156 None 1157 }; 1158 struct WaitForKeypress { enum When { 1159 Never, 1160 BeforeStart = 1, 1161 BeforeExit = 2, 1162 BeforeStartAndExit = BeforeStart | BeforeExit 1163 }; }; 1164 1165 class TestSpec; 1166 class IStream; 1167 1168 class IConfig : public Detail::NonCopyable { 1169 public: 1170 virtual ~IConfig(); 1171 1172 virtual bool allowThrows() const = 0; 1173 virtual StringRef name() const = 0; 1174 virtual bool includeSuccessfulResults() const = 0; 1175 virtual bool shouldDebugBreak() const = 0; 1176 virtual bool warnAboutMissingAssertions() const = 0; 1177 virtual bool warnAboutUnmatchedTestSpecs() const = 0; 1178 virtual bool zeroTestsCountAsSuccess() const = 0; 1179 virtual int abortAfter() const = 0; 1180 virtual bool showInvisibles() const = 0; 1181 virtual ShowDurations showDurations() const = 0; 1182 virtual double minDuration() const = 0; 1183 virtual TestSpec const& testSpec() const = 0; 1184 virtual bool hasTestFilters() const = 0; 1185 virtual std::vector<std::string> const& getTestsOrTags() const = 0; 1186 virtual TestRunOrder runOrder() const = 0; 1187 virtual uint32_t rngSeed() const = 0; 1188 virtual unsigned int shardCount() const = 0; 1189 virtual unsigned int shardIndex() const = 0; 1190 virtual ColourMode defaultColourMode() const = 0; 1191 virtual std::vector<std::string> const& getSectionsToRun() const = 0; 1192 virtual Verbosity verbosity() const = 0; 1193 1194 virtual bool skipBenchmarks() const = 0; 1195 virtual bool benchmarkNoAnalysis() const = 0; 1196 virtual unsigned int benchmarkSamples() const = 0; 1197 virtual double benchmarkConfidenceInterval() const = 0; 1198 virtual unsigned int benchmarkResamples() const = 0; 1199 virtual std::chrono::milliseconds benchmarkWarmupTime() const = 0; 1200 }; 1201} 1202 1203#endif // CATCH_INTERFACES_CONFIG_HPP_INCLUDED 1204 1205 1206#ifndef CATCH_INTERFACES_REGISTRY_HUB_HPP_INCLUDED 1207#define CATCH_INTERFACES_REGISTRY_HUB_HPP_INCLUDED 1208 1209 1210#include <string> 1211 1212namespace Catch { 1213 1214 class TestCaseHandle; 1215 struct TestCaseInfo; 1216 class ITestCaseRegistry; 1217 class IExceptionTranslatorRegistry; 1218 class IExceptionTranslator; 1219 class ReporterRegistry; 1220 class IReporterFactory; 1221 class ITagAliasRegistry; 1222 class ITestInvoker; 1223 class IMutableEnumValuesRegistry; 1224 struct SourceLineInfo; 1225 1226 class StartupExceptionRegistry; 1227 class EventListenerFactory; 1228 1229 using IReporterFactoryPtr = Detail::unique_ptr<IReporterFactory>; 1230 1231 class IRegistryHub { 1232 public: 1233 virtual ~IRegistryHub(); // = default 1234 1235 virtual ReporterRegistry const& getReporterRegistry() const = 0; 1236 virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; 1237 virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0; 1238 virtual IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const = 0; 1239 1240 1241 virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0; 1242 }; 1243 1244 class IMutableRegistryHub { 1245 public: 1246 virtual ~IMutableRegistryHub(); // = default 1247 virtual void registerReporter( std::string const& name, IReporterFactoryPtr factory ) = 0; 1248 virtual void registerListener( Detail::unique_ptr<EventListenerFactory> factory ) = 0; 1249 virtual void registerTest(Detail::unique_ptr<TestCaseInfo>&& testInfo, Detail::unique_ptr<ITestInvoker>&& invoker) = 0; 1250 virtual void registerTranslator( Detail::unique_ptr<IExceptionTranslator>&& translator ) = 0; 1251 virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0; 1252 virtual void registerStartupException() noexcept = 0; 1253 virtual IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() = 0; 1254 }; 1255 1256 IRegistryHub const& getRegistryHub(); 1257 IMutableRegistryHub& getMutableRegistryHub(); 1258 void cleanUp(); 1259 std::string translateActiveException(); 1260 1261} 1262 1263#endif // CATCH_INTERFACES_REGISTRY_HUB_HPP_INCLUDED 1264 1265 1266#ifndef CATCH_BENCHMARK_STATS_HPP_INCLUDED 1267#define CATCH_BENCHMARK_STATS_HPP_INCLUDED 1268 1269 1270 1271// Adapted from donated nonius code. 1272 1273#ifndef CATCH_ESTIMATE_HPP_INCLUDED 1274#define CATCH_ESTIMATE_HPP_INCLUDED 1275 1276namespace Catch { 1277 namespace Benchmark { 1278 template <typename Type> 1279 struct Estimate { 1280 Type point; 1281 Type lower_bound; 1282 Type upper_bound; 1283 double confidence_interval; 1284 }; 1285 } // namespace Benchmark 1286} // namespace Catch 1287 1288#endif // CATCH_ESTIMATE_HPP_INCLUDED 1289 1290 1291// Adapted from donated nonius code. 1292 1293#ifndef CATCH_OUTLIER_CLASSIFICATION_HPP_INCLUDED 1294#define CATCH_OUTLIER_CLASSIFICATION_HPP_INCLUDED 1295 1296namespace Catch { 1297 namespace Benchmark { 1298 struct OutlierClassification { 1299 int samples_seen = 0; 1300 int low_severe = 0; // more than 3 times IQR below Q1 1301 int low_mild = 0; // 1.5 to 3 times IQR below Q1 1302 int high_mild = 0; // 1.5 to 3 times IQR above Q3 1303 int high_severe = 0; // more than 3 times IQR above Q3 1304 1305 int total() const { 1306 return low_severe + low_mild + high_mild + high_severe; 1307 } 1308 }; 1309 } // namespace Benchmark 1310} // namespace Catch 1311 1312#endif // CATCH_OUTLIERS_CLASSIFICATION_HPP_INCLUDED 1313// The fwd decl & default specialization needs to be seen by VS2017 before 1314// BenchmarkStats itself, or VS2017 will report compilation error. 1315 1316#include <string> 1317#include <vector> 1318 1319namespace Catch { 1320 1321 struct BenchmarkInfo { 1322 std::string name; 1323 double estimatedDuration; 1324 int iterations; 1325 unsigned int samples; 1326 unsigned int resamples; 1327 double clockResolution; 1328 double clockCost; 1329 }; 1330 1331 // We need to keep template parameter for backwards compatibility, 1332 // but we also do not want to use the template paraneter. 1333 template <class Dummy> 1334 struct BenchmarkStats { 1335 BenchmarkInfo info; 1336 1337 std::vector<Benchmark::FDuration> samples; 1338 Benchmark::Estimate<Benchmark::FDuration> mean; 1339 Benchmark::Estimate<Benchmark::FDuration> standardDeviation; 1340 Benchmark::OutlierClassification outliers; 1341 double outlierVariance; 1342 }; 1343 1344 1345} // end namespace Catch 1346 1347#endif // CATCH_BENCHMARK_STATS_HPP_INCLUDED 1348 1349 1350// Adapted from donated nonius code. 1351 1352#ifndef CATCH_ENVIRONMENT_HPP_INCLUDED 1353#define CATCH_ENVIRONMENT_HPP_INCLUDED 1354 1355 1356namespace Catch { 1357 namespace Benchmark { 1358 struct EnvironmentEstimate { 1359 FDuration mean; 1360 OutlierClassification outliers; 1361 }; 1362 struct Environment { 1363 EnvironmentEstimate clock_resolution; 1364 EnvironmentEstimate clock_cost; 1365 }; 1366 } // namespace Benchmark 1367} // namespace Catch 1368 1369#endif // CATCH_ENVIRONMENT_HPP_INCLUDED 1370 1371 1372// Adapted from donated nonius code. 1373 1374#ifndef CATCH_EXECUTION_PLAN_HPP_INCLUDED 1375#define CATCH_EXECUTION_PLAN_HPP_INCLUDED 1376 1377 1378 1379// Adapted from donated nonius code. 1380 1381#ifndef CATCH_BENCHMARK_FUNCTION_HPP_INCLUDED 1382#define CATCH_BENCHMARK_FUNCTION_HPP_INCLUDED 1383 1384 1385 1386// Adapted from donated nonius code. 1387 1388#ifndef CATCH_CHRONOMETER_HPP_INCLUDED 1389#define CATCH_CHRONOMETER_HPP_INCLUDED 1390 1391 1392 1393// Adapted from donated nonius code. 1394 1395#ifndef CATCH_OPTIMIZER_HPP_INCLUDED 1396#define CATCH_OPTIMIZER_HPP_INCLUDED 1397 1398#if defined(_MSC_VER) || defined(__IAR_SYSTEMS_ICC__) 1399# include <atomic> // atomic_thread_fence 1400#endif 1401 1402 1403#include <type_traits> 1404 1405namespace Catch { 1406 namespace Benchmark { 1407#if defined(__GNUC__) || defined(__clang__) 1408 template <typename T> 1409 inline void keep_memory(T* p) { 1410 asm volatile("" : : "g"(p) : "memory"); 1411 } 1412 inline void keep_memory() { 1413 asm volatile("" : : : "memory"); 1414 } 1415 1416 namespace Detail { 1417 inline void optimizer_barrier() { keep_memory(); } 1418 } // namespace Detail 1419#elif defined(_MSC_VER) || defined(__IAR_SYSTEMS_ICC__) 1420 1421#if defined(_MSVC_VER) 1422#pragma optimize("", off) 1423#elif defined(__IAR_SYSTEMS_ICC__) 1424// For IAR the pragma only affects the following function 1425#pragma optimize=disable 1426#endif 1427 template <typename T> 1428 inline void keep_memory(T* p) { 1429 // thanks @milleniumbug 1430 *reinterpret_cast<char volatile*>(p) = *reinterpret_cast<char const volatile*>(p); 1431 } 1432 // TODO equivalent keep_memory() 1433#if defined(_MSVC_VER) 1434#pragma optimize("", on) 1435#endif 1436 1437 namespace Detail { 1438 inline void optimizer_barrier() { 1439 std::atomic_thread_fence(std::memory_order_seq_cst); 1440 } 1441 } // namespace Detail 1442 1443#endif 1444 1445 template <typename T> 1446 inline void deoptimize_value(T&& x) { 1447 keep_memory(&x); 1448 } 1449 1450 template <typename Fn, typename... Args> 1451 inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> std::enable_if_t<!std::is_same<void, decltype(fn(args...))>::value> { 1452 deoptimize_value(CATCH_FORWARD(fn) (CATCH_FORWARD(args)...)); 1453 } 1454 1455 template <typename Fn, typename... Args> 1456 inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> std::enable_if_t<std::is_same<void, decltype(fn(args...))>::value> { 1457 CATCH_FORWARD((fn)) (CATCH_FORWARD(args)...); 1458 } 1459 } // namespace Benchmark 1460} // namespace Catch 1461 1462#endif // CATCH_OPTIMIZER_HPP_INCLUDED 1463 1464 1465#ifndef CATCH_META_HPP_INCLUDED 1466#define CATCH_META_HPP_INCLUDED 1467 1468#include <type_traits> 1469 1470namespace Catch { 1471 template <typename> 1472 struct true_given : std::true_type {}; 1473 1474 struct is_callable_tester { 1475 template <typename Fun, typename... Args> 1476 static true_given<decltype(std::declval<Fun>()(std::declval<Args>()...))> test(int); 1477 template <typename...> 1478 static std::false_type test(...); 1479 }; 1480 1481 template <typename T> 1482 struct is_callable; 1483 1484 template <typename Fun, typename... Args> 1485 struct is_callable<Fun(Args...)> : decltype(is_callable_tester::test<Fun, Args...>(0)) {}; 1486 1487 1488#if defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703 1489 // std::result_of is deprecated in C++17 and removed in C++20. Hence, it is 1490 // replaced with std::invoke_result here. 1491 template <typename Func, typename... U> 1492 using FunctionReturnType = std::remove_reference_t<std::remove_cv_t<std::invoke_result_t<Func, U...>>>; 1493#else 1494 template <typename Func, typename... U> 1495 using FunctionReturnType = std::remove_reference_t<std::remove_cv_t<std::result_of_t<Func(U...)>>>; 1496#endif 1497 1498} // namespace Catch 1499 1500namespace mpl_{ 1501 struct na; 1502} 1503 1504#endif // CATCH_META_HPP_INCLUDED 1505 1506namespace Catch { 1507 namespace Benchmark { 1508 namespace Detail { 1509 struct ChronometerConcept { 1510 virtual void start() = 0; 1511 virtual void finish() = 0; 1512 virtual ~ChronometerConcept(); // = default; 1513 1514 ChronometerConcept() = default; 1515 ChronometerConcept(ChronometerConcept const&) = default; 1516 ChronometerConcept& operator=(ChronometerConcept const&) = default; 1517 }; 1518 template <typename Clock> 1519 struct ChronometerModel final : public ChronometerConcept { 1520 void start() override { started = Clock::now(); } 1521 void finish() override { finished = Clock::now(); } 1522 1523 IDuration elapsed() const { 1524 return std::chrono::duration_cast<std::chrono::nanoseconds>( 1525 finished - started ); 1526 } 1527 1528 TimePoint<Clock> started; 1529 TimePoint<Clock> finished; 1530 }; 1531 } // namespace Detail 1532 1533 struct Chronometer { 1534 public: 1535 template <typename Fun> 1536 void measure(Fun&& fun) { measure(CATCH_FORWARD(fun), is_callable<Fun(int)>()); } 1537 1538 int runs() const { return repeats; } 1539 1540 Chronometer(Detail::ChronometerConcept& meter, int repeats_) 1541 : impl(&meter) 1542 , repeats(repeats_) {} 1543 1544 private: 1545 template <typename Fun> 1546 void measure(Fun&& fun, std::false_type) { 1547 measure([&fun](int) { return fun(); }, std::true_type()); 1548 } 1549 1550 template <typename Fun> 1551 void measure(Fun&& fun, std::true_type) { 1552 Detail::optimizer_barrier(); 1553 impl->start(); 1554 for (int i = 0; i < repeats; ++i) invoke_deoptimized(fun, i); 1555 impl->finish(); 1556 Detail::optimizer_barrier(); 1557 } 1558 1559 Detail::ChronometerConcept* impl; 1560 int repeats; 1561 }; 1562 } // namespace Benchmark 1563} // namespace Catch 1564 1565#endif // CATCH_CHRONOMETER_HPP_INCLUDED 1566 1567#include <type_traits> 1568 1569namespace Catch { 1570 namespace Benchmark { 1571 namespace Detail { 1572 template <typename T, typename U> 1573 struct is_related 1574 : std::is_same<std::decay_t<T>, std::decay_t<U>> {}; 1575 1576 /// We need to reinvent std::function because every piece of code that might add overhead 1577 /// in a measurement context needs to have consistent performance characteristics so that we 1578 /// can account for it in the measurement. 1579 /// Implementations of std::function with optimizations that aren't always applicable, like 1580 /// small buffer optimizations, are not uncommon. 1581 /// This is effectively an implementation of std::function without any such optimizations; 1582 /// it may be slow, but it is consistently slow. 1583 struct BenchmarkFunction { 1584 private: 1585 struct callable { 1586 virtual void call(Chronometer meter) const = 0; 1587 virtual Catch::Detail::unique_ptr<callable> clone() const = 0; 1588 virtual ~callable(); // = default; 1589 1590 callable() = default; 1591 callable(callable const&) = default; 1592 callable& operator=(callable const&) = default; 1593 }; 1594 template <typename Fun> 1595 struct model : public callable { 1596 model(Fun&& fun_) : fun(CATCH_MOVE(fun_)) {} 1597 model(Fun const& fun_) : fun(fun_) {} 1598 1599 Catch::Detail::unique_ptr<callable> clone() const override { 1600 return Catch::Detail::make_unique<model<Fun>>( *this ); 1601 } 1602 1603 void call(Chronometer meter) const override { 1604 call(meter, is_callable<Fun(Chronometer)>()); 1605 } 1606 void call(Chronometer meter, std::true_type) const { 1607 fun(meter); 1608 } 1609 void call(Chronometer meter, std::false_type) const { 1610 meter.measure(fun); 1611 } 1612 1613 Fun fun; 1614 }; 1615 1616 struct do_nothing { void operator()() const {} }; 1617 1618 template <typename T> 1619 BenchmarkFunction(model<T>* c) : f(c) {} 1620 1621 public: 1622 BenchmarkFunction() 1623 : f(new model<do_nothing>{ {} }) {} 1624 1625 template <typename Fun, 1626 std::enable_if_t<!is_related<Fun, BenchmarkFunction>::value, int> = 0> 1627 BenchmarkFunction(Fun&& fun) 1628 : f(new model<std::decay_t<Fun>>(CATCH_FORWARD(fun))) {} 1629 1630 BenchmarkFunction( BenchmarkFunction&& that ) noexcept: 1631 f( CATCH_MOVE( that.f ) ) {} 1632 1633 BenchmarkFunction(BenchmarkFunction const& that) 1634 : f(that.f->clone()) {} 1635 1636 BenchmarkFunction& 1637 operator=( BenchmarkFunction&& that ) noexcept { 1638 f = CATCH_MOVE( that.f ); 1639 return *this; 1640 } 1641 1642 BenchmarkFunction& operator=(BenchmarkFunction const& that) { 1643 f = that.f->clone(); 1644 return *this; 1645 } 1646 1647 void operator()(Chronometer meter) const { f->call(meter); } 1648 1649 private: 1650 Catch::Detail::unique_ptr<callable> f; 1651 }; 1652 } // namespace Detail 1653 } // namespace Benchmark 1654} // namespace Catch 1655 1656#endif // CATCH_BENCHMARK_FUNCTION_HPP_INCLUDED 1657 1658 1659// Adapted from donated nonius code. 1660 1661#ifndef CATCH_REPEAT_HPP_INCLUDED 1662#define CATCH_REPEAT_HPP_INCLUDED 1663 1664#include <type_traits> 1665 1666namespace Catch { 1667 namespace Benchmark { 1668 namespace Detail { 1669 template <typename Fun> 1670 struct repeater { 1671 void operator()(int k) const { 1672 for (int i = 0; i < k; ++i) { 1673 fun(); 1674 } 1675 } 1676 Fun fun; 1677 }; 1678 template <typename Fun> 1679 repeater<std::decay_t<Fun>> repeat(Fun&& fun) { 1680 return { CATCH_FORWARD(fun) }; 1681 } 1682 } // namespace Detail 1683 } // namespace Benchmark 1684} // namespace Catch 1685 1686#endif // CATCH_REPEAT_HPP_INCLUDED 1687 1688 1689// Adapted from donated nonius code. 1690 1691#ifndef CATCH_RUN_FOR_AT_LEAST_HPP_INCLUDED 1692#define CATCH_RUN_FOR_AT_LEAST_HPP_INCLUDED 1693 1694 1695 1696// Adapted from donated nonius code. 1697 1698#ifndef CATCH_MEASURE_HPP_INCLUDED 1699#define CATCH_MEASURE_HPP_INCLUDED 1700 1701 1702 1703// Adapted from donated nonius code. 1704 1705#ifndef CATCH_COMPLETE_INVOKE_HPP_INCLUDED 1706#define CATCH_COMPLETE_INVOKE_HPP_INCLUDED 1707 1708 1709namespace Catch { 1710 namespace Benchmark { 1711 namespace Detail { 1712 template <typename T> 1713 struct CompleteType { using type = T; }; 1714 template <> 1715 struct CompleteType<void> { struct type {}; }; 1716 1717 template <typename T> 1718 using CompleteType_t = typename CompleteType<T>::type; 1719 1720 template <typename Result> 1721 struct CompleteInvoker { 1722 template <typename Fun, typename... Args> 1723 static Result invoke(Fun&& fun, Args&&... args) { 1724 return CATCH_FORWARD(fun)(CATCH_FORWARD(args)...); 1725 } 1726 }; 1727 template <> 1728 struct CompleteInvoker<void> { 1729 template <typename Fun, typename... Args> 1730 static CompleteType_t<void> invoke(Fun&& fun, Args&&... args) { 1731 CATCH_FORWARD(fun)(CATCH_FORWARD(args)...); 1732 return {}; 1733 } 1734 }; 1735 1736 // invoke and not return void :( 1737 template <typename Fun, typename... Args> 1738 CompleteType_t<FunctionReturnType<Fun, Args...>> complete_invoke(Fun&& fun, Args&&... args) { 1739 return CompleteInvoker<FunctionReturnType<Fun, Args...>>::invoke(CATCH_FORWARD(fun), CATCH_FORWARD(args)...); 1740 } 1741 1742 } // namespace Detail 1743 1744 template <typename Fun> 1745 Detail::CompleteType_t<FunctionReturnType<Fun>> user_code(Fun&& fun) { 1746 return Detail::complete_invoke(CATCH_FORWARD(fun)); 1747 } 1748 } // namespace Benchmark 1749} // namespace Catch 1750 1751#endif // CATCH_COMPLETE_INVOKE_HPP_INCLUDED 1752 1753 1754// Adapted from donated nonius code. 1755 1756#ifndef CATCH_TIMING_HPP_INCLUDED 1757#define CATCH_TIMING_HPP_INCLUDED 1758 1759 1760#include <type_traits> 1761 1762namespace Catch { 1763 namespace Benchmark { 1764 template <typename Result> 1765 struct Timing { 1766 IDuration elapsed; 1767 Result result; 1768 int iterations; 1769 }; 1770 template <typename Func, typename... Args> 1771 using TimingOf = Timing<Detail::CompleteType_t<FunctionReturnType<Func, Args...>>>; 1772 } // namespace Benchmark 1773} // namespace Catch 1774 1775#endif // CATCH_TIMING_HPP_INCLUDED 1776 1777namespace Catch { 1778 namespace Benchmark { 1779 namespace Detail { 1780 template <typename Clock, typename Fun, typename... Args> 1781 TimingOf<Fun, Args...> measure(Fun&& fun, Args&&... args) { 1782 auto start = Clock::now(); 1783 auto&& r = Detail::complete_invoke(fun, CATCH_FORWARD(args)...); 1784 auto end = Clock::now(); 1785 auto delta = end - start; 1786 return { delta, CATCH_FORWARD(r), 1 }; 1787 } 1788 } // namespace Detail 1789 } // namespace Benchmark 1790} // namespace Catch 1791 1792#endif // CATCH_MEASURE_HPP_INCLUDED 1793 1794#include <type_traits> 1795 1796namespace Catch { 1797 namespace Benchmark { 1798 namespace Detail { 1799 template <typename Clock, typename Fun> 1800 TimingOf<Fun, int> measure_one(Fun&& fun, int iters, std::false_type) { 1801 return Detail::measure<Clock>(fun, iters); 1802 } 1803 template <typename Clock, typename Fun> 1804 TimingOf<Fun, Chronometer> measure_one(Fun&& fun, int iters, std::true_type) { 1805 Detail::ChronometerModel<Clock> meter; 1806 auto&& result = Detail::complete_invoke(fun, Chronometer(meter, iters)); 1807 1808 return { meter.elapsed(), CATCH_MOVE(result), iters }; 1809 } 1810 1811 template <typename Clock, typename Fun> 1812 using run_for_at_least_argument_t = std::conditional_t<is_callable<Fun(Chronometer)>::value, Chronometer, int>; 1813 1814 1815 [[noreturn]] 1816 void throw_optimized_away_error(); 1817 1818 template <typename Clock, typename Fun> 1819 TimingOf<Fun, run_for_at_least_argument_t<Clock, Fun>> 1820 run_for_at_least(IDuration how_long, 1821 const int initial_iterations, 1822 Fun&& fun) { 1823 auto iters = initial_iterations; 1824 while (iters < (1 << 30)) { 1825 auto&& Timing = measure_one<Clock>(fun, iters, is_callable<Fun(Chronometer)>()); 1826 1827 if (Timing.elapsed >= how_long) { 1828 return { Timing.elapsed, CATCH_MOVE(Timing.result), iters }; 1829 } 1830 iters *= 2; 1831 } 1832 throw_optimized_away_error(); 1833 } 1834 } // namespace Detail 1835 } // namespace Benchmark 1836} // namespace Catch 1837 1838#endif // CATCH_RUN_FOR_AT_LEAST_HPP_INCLUDED 1839 1840#include <vector> 1841 1842namespace Catch { 1843 namespace Benchmark { 1844 struct ExecutionPlan { 1845 int iterations_per_sample; 1846 FDuration estimated_duration; 1847 Detail::BenchmarkFunction benchmark; 1848 FDuration warmup_time; 1849 int warmup_iterations; 1850 1851 template <typename Clock> 1852 std::vector<FDuration> run(const IConfig &cfg, Environment env) const { 1853 // warmup a bit 1854 Detail::run_for_at_least<Clock>( 1855 std::chrono::duration_cast<IDuration>( warmup_time ), 1856 warmup_iterations, 1857 Detail::repeat( []() { return Clock::now(); } ) 1858 ); 1859 1860 std::vector<FDuration> times; 1861 const auto num_samples = cfg.benchmarkSamples(); 1862 times.reserve( num_samples ); 1863 for ( size_t i = 0; i < num_samples; ++i ) { 1864 Detail::ChronometerModel<Clock> model; 1865 this->benchmark( Chronometer( model, iterations_per_sample ) ); 1866 auto sample_time = model.elapsed() - env.clock_cost.mean; 1867 if ( sample_time < FDuration::zero() ) { 1868 sample_time = FDuration::zero(); 1869 } 1870 times.push_back(sample_time / iterations_per_sample); 1871 } 1872 return times; 1873 } 1874 }; 1875 } // namespace Benchmark 1876} // namespace Catch 1877 1878#endif // CATCH_EXECUTION_PLAN_HPP_INCLUDED 1879 1880 1881// Adapted from donated nonius code. 1882 1883#ifndef CATCH_ESTIMATE_CLOCK_HPP_INCLUDED 1884#define CATCH_ESTIMATE_CLOCK_HPP_INCLUDED 1885 1886 1887 1888// Adapted from donated nonius code. 1889 1890#ifndef CATCH_STATS_HPP_INCLUDED 1891#define CATCH_STATS_HPP_INCLUDED 1892 1893 1894#include <vector> 1895 1896namespace Catch { 1897 namespace Benchmark { 1898 namespace Detail { 1899 using sample = std::vector<double>; 1900 1901 double weighted_average_quantile( int k, 1902 int q, 1903 double* first, 1904 double* last ); 1905 1906 OutlierClassification 1907 classify_outliers( double const* first, double const* last ); 1908 1909 double mean( double const* first, double const* last ); 1910 1911 double normal_cdf( double x ); 1912 1913 double erfc_inv(double x); 1914 1915 double normal_quantile(double p); 1916 1917 Estimate<double> 1918 bootstrap( double confidence_level, 1919 double* first, 1920 double* last, 1921 sample const& resample, 1922 double ( *estimator )( double const*, double const* ) ); 1923 1924 struct bootstrap_analysis { 1925 Estimate<double> mean; 1926 Estimate<double> standard_deviation; 1927 double outlier_variance; 1928 }; 1929 1930 bootstrap_analysis analyse_samples(double confidence_level, 1931 unsigned int n_resamples, 1932 double* first, 1933 double* last); 1934 } // namespace Detail 1935 } // namespace Benchmark 1936} // namespace Catch 1937 1938#endif // CATCH_STATS_HPP_INCLUDED 1939 1940#include <algorithm> 1941#include <vector> 1942#include <cmath> 1943 1944namespace Catch { 1945 namespace Benchmark { 1946 namespace Detail { 1947 template <typename Clock> 1948 std::vector<double> resolution(int k) { 1949 std::vector<TimePoint<Clock>> times; 1950 times.reserve(static_cast<size_t>(k + 1)); 1951 for ( int i = 0; i < k + 1; ++i ) { 1952 times.push_back( Clock::now() ); 1953 } 1954 1955 std::vector<double> deltas; 1956 deltas.reserve(static_cast<size_t>(k)); 1957 for ( size_t idx = 1; idx < times.size(); ++idx ) { 1958 deltas.push_back( static_cast<double>( 1959 ( times[idx] - times[idx - 1] ).count() ) ); 1960 } 1961 1962 return deltas; 1963 } 1964 1965 constexpr auto warmup_iterations = 10000; 1966 constexpr auto warmup_time = std::chrono::milliseconds(100); 1967 constexpr auto minimum_ticks = 1000; 1968 constexpr auto warmup_seed = 10000; 1969 constexpr auto clock_resolution_estimation_time = std::chrono::milliseconds(500); 1970 constexpr auto clock_cost_estimation_time_limit = std::chrono::seconds(1); 1971 constexpr auto clock_cost_estimation_tick_limit = 100000; 1972 constexpr auto clock_cost_estimation_time = std::chrono::milliseconds(10); 1973 constexpr auto clock_cost_estimation_iterations = 10000; 1974 1975 template <typename Clock> 1976 int warmup() { 1977 return run_for_at_least<Clock>(warmup_time, warmup_seed, &resolution<Clock>) 1978 .iterations; 1979 } 1980 template <typename Clock> 1981 EnvironmentEstimate estimate_clock_resolution(int iterations) { 1982 auto r = run_for_at_least<Clock>(clock_resolution_estimation_time, iterations, &resolution<Clock>) 1983 .result; 1984 return { 1985 FDuration(mean(r.data(), r.data() + r.size())), 1986 classify_outliers(r.data(), r.data() + r.size()), 1987 }; 1988 } 1989 template <typename Clock> 1990 EnvironmentEstimate estimate_clock_cost(FDuration resolution) { 1991 auto time_limit = (std::min)( 1992 resolution * clock_cost_estimation_tick_limit, 1993 FDuration(clock_cost_estimation_time_limit)); 1994 auto time_clock = [](int k) { 1995 return Detail::measure<Clock>([k] { 1996 for (int i = 0; i < k; ++i) { 1997 volatile auto ignored = Clock::now(); 1998 (void)ignored; 1999 } 2000 }).elapsed; 2001 }; 2002 time_clock(1); 2003 int iters = clock_cost_estimation_iterations; 2004 auto&& r = run_for_at_least<Clock>(clock_cost_estimation_time, iters, time_clock); 2005 std::vector<double> times; 2006 int nsamples = static_cast<int>(std::ceil(time_limit / r.elapsed)); 2007 times.reserve(static_cast<size_t>(nsamples)); 2008 for ( int s = 0; s < nsamples; ++s ) { 2009 times.push_back( static_cast<double>( 2010 ( time_clock( r.iterations ) / r.iterations ) 2011 .count() ) ); 2012 } 2013 return { 2014 FDuration(mean(times.data(), times.data() + times.size())), 2015 classify_outliers(times.data(), times.data() + times.size()), 2016 }; 2017 } 2018 2019 template <typename Clock> 2020 Environment measure_environment() { 2021#if defined(__clang__) 2022# pragma clang diagnostic push 2023# pragma clang diagnostic ignored "-Wexit-time-destructors" 2024#endif 2025 static Catch::Detail::unique_ptr<Environment> env; 2026#if defined(__clang__) 2027# pragma clang diagnostic pop 2028#endif 2029 if (env) { 2030 return *env; 2031 } 2032 2033 auto iters = Detail::warmup<Clock>(); 2034 auto resolution = Detail::estimate_clock_resolution<Clock>(iters); 2035 auto cost = Detail::estimate_clock_cost<Clock>(resolution.mean); 2036 2037 env = Catch::Detail::make_unique<Environment>( Environment{resolution, cost} ); 2038 return *env; 2039 } 2040 } // namespace Detail 2041 } // namespace Benchmark 2042} // namespace Catch 2043 2044#endif // CATCH_ESTIMATE_CLOCK_HPP_INCLUDED 2045 2046 2047// Adapted from donated nonius code. 2048 2049#ifndef CATCH_ANALYSE_HPP_INCLUDED 2050#define CATCH_ANALYSE_HPP_INCLUDED 2051 2052 2053 2054// Adapted from donated nonius code. 2055 2056#ifndef CATCH_SAMPLE_ANALYSIS_HPP_INCLUDED 2057#define CATCH_SAMPLE_ANALYSIS_HPP_INCLUDED 2058 2059 2060#include <vector> 2061 2062namespace Catch { 2063 namespace Benchmark { 2064 struct SampleAnalysis { 2065 std::vector<FDuration> samples; 2066 Estimate<FDuration> mean; 2067 Estimate<FDuration> standard_deviation; 2068 OutlierClassification outliers; 2069 double outlier_variance; 2070 }; 2071 } // namespace Benchmark 2072} // namespace Catch 2073 2074#endif // CATCH_SAMPLE_ANALYSIS_HPP_INCLUDED 2075 2076 2077namespace Catch { 2078 class IConfig; 2079 2080 namespace Benchmark { 2081 namespace Detail { 2082 SampleAnalysis analyse(const IConfig &cfg, FDuration* first, FDuration* last); 2083 } // namespace Detail 2084 } // namespace Benchmark 2085} // namespace Catch 2086 2087#endif // CATCH_ANALYSE_HPP_INCLUDED 2088 2089#include <algorithm> 2090#include <chrono> 2091#include <exception> 2092#include <string> 2093#include <cmath> 2094 2095namespace Catch { 2096 namespace Benchmark { 2097 struct Benchmark { 2098 Benchmark(std::string&& benchmarkName) 2099 : name(CATCH_MOVE(benchmarkName)) {} 2100 2101 template <class FUN> 2102 Benchmark(std::string&& benchmarkName , FUN &&func) 2103 : fun(CATCH_MOVE(func)), name(CATCH_MOVE(benchmarkName)) {} 2104 2105 template <typename Clock> 2106 ExecutionPlan prepare(const IConfig &cfg, Environment env) const { 2107 auto min_time = env.clock_resolution.mean * Detail::minimum_ticks; 2108 auto run_time = std::max(min_time, std::chrono::duration_cast<decltype(min_time)>(cfg.benchmarkWarmupTime())); 2109 auto&& test = Detail::run_for_at_least<Clock>(std::chrono::duration_cast<IDuration>(run_time), 1, fun); 2110 int new_iters = static_cast<int>(std::ceil(min_time * test.iterations / test.elapsed)); 2111 return { new_iters, test.elapsed / test.iterations * new_iters * cfg.benchmarkSamples(), fun, std::chrono::duration_cast<FDuration>(cfg.benchmarkWarmupTime()), Detail::warmup_iterations }; 2112 } 2113 2114 template <typename Clock = default_clock> 2115 void run() { 2116 static_assert( Clock::is_steady, 2117 "Benchmarking clock should be steady" ); 2118 auto const* cfg = getCurrentContext().getConfig(); 2119 2120 auto env = Detail::measure_environment<Clock>(); 2121 2122 getResultCapture().benchmarkPreparing(name); 2123 CATCH_TRY{ 2124 auto plan = user_code([&] { 2125 return prepare<Clock>(*cfg, env); 2126 }); 2127 2128 BenchmarkInfo info { 2129 CATCH_MOVE(name), 2130 plan.estimated_duration.count(), 2131 plan.iterations_per_sample, 2132 cfg->benchmarkSamples(), 2133 cfg->benchmarkResamples(), 2134 env.clock_resolution.mean.count(), 2135 env.clock_cost.mean.count() 2136 }; 2137 2138 getResultCapture().benchmarkStarting(info); 2139 2140 auto samples = user_code([&] { 2141 return plan.template run<Clock>(*cfg, env); 2142 }); 2143 2144 auto analysis = Detail::analyse(*cfg, samples.data(), samples.data() + samples.size()); 2145 BenchmarkStats<> stats{ CATCH_MOVE(info), CATCH_MOVE(analysis.samples), analysis.mean, analysis.standard_deviation, analysis.outliers, analysis.outlier_variance }; 2146 getResultCapture().benchmarkEnded(stats); 2147 } CATCH_CATCH_ANON (TestFailureException const&) { 2148 getResultCapture().benchmarkFailed("Benchmark failed due to failed assertion"_sr); 2149 } CATCH_CATCH_ALL{ 2150 getResultCapture().benchmarkFailed(translateActiveException()); 2151 // We let the exception go further up so that the 2152 // test case is marked as failed. 2153 std::rethrow_exception(std::current_exception()); 2154 } 2155 } 2156 2157 // sets lambda to be used in fun *and* executes benchmark! 2158 template <typename Fun, std::enable_if_t<!Detail::is_related<Fun, Benchmark>::value, int> = 0> 2159 Benchmark & operator=(Fun func) { 2160 auto const* cfg = getCurrentContext().getConfig(); 2161 if (!cfg->skipBenchmarks()) { 2162 fun = Detail::BenchmarkFunction(func); 2163 run(); 2164 } 2165 return *this; 2166 } 2167 2168 explicit operator bool() { 2169 return true; 2170 } 2171 2172 private: 2173 Detail::BenchmarkFunction fun; 2174 std::string name; 2175 }; 2176 } 2177} // namespace Catch 2178 2179#define INTERNAL_CATCH_GET_1_ARG(arg1, arg2, ...) arg1 2180#define INTERNAL_CATCH_GET_2_ARG(arg1, arg2, ...) arg2 2181 2182#define INTERNAL_CATCH_BENCHMARK(BenchmarkName, name, benchmarkIndex)\ 2183 if( Catch::Benchmark::Benchmark BenchmarkName{name} ) \ 2184 BenchmarkName = [&](int benchmarkIndex) 2185 2186#define INTERNAL_CATCH_BENCHMARK_ADVANCED(BenchmarkName, name)\ 2187 if( Catch::Benchmark::Benchmark BenchmarkName{name} ) \ 2188 BenchmarkName = [&] 2189 2190#if defined(CATCH_CONFIG_PREFIX_ALL) 2191 2192#define CATCH_BENCHMARK(...) \ 2193 INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_BENCHMARK_), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,)) 2194#define CATCH_BENCHMARK_ADVANCED(name) \ 2195 INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_BENCHMARK_), name) 2196 2197#else 2198 2199#define BENCHMARK(...) \ 2200 INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_BENCHMARK_), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,)) 2201#define BENCHMARK_ADVANCED(name) \ 2202 INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_BENCHMARK_), name) 2203 2204#endif 2205 2206#endif // CATCH_BENCHMARK_HPP_INCLUDED 2207 2208 2209// Adapted from donated nonius code. 2210 2211#ifndef CATCH_CONSTRUCTOR_HPP_INCLUDED 2212#define CATCH_CONSTRUCTOR_HPP_INCLUDED 2213 2214 2215#include <type_traits> 2216 2217namespace Catch { 2218 namespace Benchmark { 2219 namespace Detail { 2220 template <typename T, bool Destruct> 2221 struct ObjectStorage 2222 { 2223 ObjectStorage() = default; 2224 2225 ObjectStorage(const ObjectStorage& other) 2226 { 2227 new(&data) T(other.stored_object()); 2228 } 2229 2230 ObjectStorage(ObjectStorage&& other) 2231 { 2232 new(data) T(CATCH_MOVE(other.stored_object())); 2233 } 2234 2235 ~ObjectStorage() { destruct_on_exit<T>(); } 2236 2237 template <typename... Args> 2238 void construct(Args&&... args) 2239 { 2240 new (data) T(CATCH_FORWARD(args)...); 2241 } 2242 2243 template <bool AllowManualDestruction = !Destruct> 2244 std::enable_if_t<AllowManualDestruction> destruct() 2245 { 2246 stored_object().~T(); 2247 } 2248 2249 private: 2250 // If this is a constructor benchmark, destruct the underlying object 2251 template <typename U> 2252 void destruct_on_exit(std::enable_if_t<Destruct, U>* = nullptr) { destruct<true>(); } 2253 // Otherwise, don't 2254 template <typename U> 2255 void destruct_on_exit(std::enable_if_t<!Destruct, U>* = nullptr) { } 2256 2257#if defined( __GNUC__ ) && __GNUC__ <= 6 2258# pragma GCC diagnostic push 2259# pragma GCC diagnostic ignored "-Wstrict-aliasing" 2260#endif 2261 T& stored_object() { return *reinterpret_cast<T*>( data ); } 2262 2263 T const& stored_object() const { 2264 return *reinterpret_cast<T const*>( data ); 2265 } 2266#if defined( __GNUC__ ) && __GNUC__ <= 6 2267# pragma GCC diagnostic pop 2268#endif 2269 2270 alignas( T ) unsigned char data[sizeof( T )]{}; 2271 }; 2272 } // namespace Detail 2273 2274 template <typename T> 2275 using storage_for = Detail::ObjectStorage<T, true>; 2276 2277 template <typename T> 2278 using destructable_object = Detail::ObjectStorage<T, false>; 2279 } // namespace Benchmark 2280} // namespace Catch 2281 2282#endif // CATCH_CONSTRUCTOR_HPP_INCLUDED 2283 2284#endif // CATCH_BENCHMARK_ALL_HPP_INCLUDED 2285 2286 2287#ifndef CATCH_APPROX_HPP_INCLUDED 2288#define CATCH_APPROX_HPP_INCLUDED 2289 2290 2291 2292#ifndef CATCH_TOSTRING_HPP_INCLUDED 2293#define CATCH_TOSTRING_HPP_INCLUDED 2294 2295 2296#include <vector> 2297#include <cstddef> 2298#include <type_traits> 2299#include <string> 2300 2301 2302 2303 2304/** \file 2305 * Wrapper for the WCHAR configuration option 2306 * 2307 * We want to support platforms that do not provide `wchar_t`, so we 2308 * sometimes have to disable providing wchar_t overloads through Catch2, 2309 * e.g. the StringMaker specialization for `std::wstring`. 2310 */ 2311 2312#ifndef CATCH_CONFIG_WCHAR_HPP_INCLUDED 2313#define CATCH_CONFIG_WCHAR_HPP_INCLUDED 2314 2315 2316// We assume that WCHAR should be enabled by default, and only disabled 2317// for a shortlist (so far only DJGPP) of compilers. 2318 2319#if defined(__DJGPP__) 2320# define CATCH_INTERNAL_CONFIG_NO_WCHAR 2321#endif // __DJGPP__ 2322 2323#if !defined( CATCH_INTERNAL_CONFIG_NO_WCHAR ) && \ 2324 !defined( CATCH_CONFIG_NO_WCHAR ) && \ 2325 !defined( CATCH_CONFIG_WCHAR ) 2326# define CATCH_CONFIG_WCHAR 2327#endif 2328 2329#endif // CATCH_CONFIG_WCHAR_HPP_INCLUDED 2330 2331 2332#ifndef CATCH_REUSABLE_STRING_STREAM_HPP_INCLUDED 2333#define CATCH_REUSABLE_STRING_STREAM_HPP_INCLUDED 2334 2335 2336#include <iosfwd> 2337#include <cstddef> 2338#include <ostream> 2339#include <string> 2340 2341namespace Catch { 2342 2343 class ReusableStringStream : Detail::NonCopyable { 2344 std::size_t m_index; 2345 std::ostream* m_oss; 2346 public: 2347 ReusableStringStream(); 2348 ~ReusableStringStream(); 2349 2350 //! Returns the serialized state 2351 std::string str() const; 2352 //! Sets internal state to `str` 2353 void str(std::string const& str); 2354 2355#if defined(__GNUC__) && !defined(__clang__) 2356#pragma GCC diagnostic push 2357// Old versions of GCC do not understand -Wnonnull-compare 2358#pragma GCC diagnostic ignored "-Wpragmas" 2359// Streaming a function pointer triggers Waddress and Wnonnull-compare 2360// on GCC, because it implicitly converts it to bool and then decides 2361// that the check it uses (a? true : false) is tautological and cannot 2362// be null... 2363#pragma GCC diagnostic ignored "-Waddress" 2364#pragma GCC diagnostic ignored "-Wnonnull-compare" 2365#endif 2366 2367 template<typename T> 2368 auto operator << ( T const& value ) -> ReusableStringStream& { 2369 *m_oss << value; 2370 return *this; 2371 } 2372 2373#if defined(__GNUC__) && !defined(__clang__) 2374#pragma GCC diagnostic pop 2375#endif 2376 auto get() -> std::ostream& { return *m_oss; } 2377 }; 2378} 2379 2380#endif // CATCH_REUSABLE_STRING_STREAM_HPP_INCLUDED 2381 2382 2383#ifndef CATCH_VOID_TYPE_HPP_INCLUDED 2384#define CATCH_VOID_TYPE_HPP_INCLUDED 2385 2386 2387namespace Catch { 2388 namespace Detail { 2389 2390 template <typename...> 2391 struct make_void { using type = void; }; 2392 2393 template <typename... Ts> 2394 using void_t = typename make_void<Ts...>::type; 2395 2396 } // namespace Detail 2397} // namespace Catch 2398 2399 2400#endif // CATCH_VOID_TYPE_HPP_INCLUDED 2401 2402 2403#ifndef CATCH_INTERFACES_ENUM_VALUES_REGISTRY_HPP_INCLUDED 2404#define CATCH_INTERFACES_ENUM_VALUES_REGISTRY_HPP_INCLUDED 2405 2406 2407#include <vector> 2408 2409namespace Catch { 2410 2411 namespace Detail { 2412 struct EnumInfo { 2413 StringRef m_name; 2414 std::vector<std::pair<int, StringRef>> m_values; 2415 2416 ~EnumInfo(); 2417 2418 StringRef lookup( int value ) const; 2419 }; 2420 } // namespace Detail 2421 2422 class IMutableEnumValuesRegistry { 2423 public: 2424 virtual ~IMutableEnumValuesRegistry(); // = default; 2425 2426 virtual Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::vector<int> const& values ) = 0; 2427 2428 template<typename E> 2429 Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::initializer_list<E> values ) { 2430 static_assert(sizeof(int) >= sizeof(E), "Cannot serialize enum to int"); 2431 std::vector<int> intValues; 2432 intValues.reserve( values.size() ); 2433 for( auto enumValue : values ) 2434 intValues.push_back( static_cast<int>( enumValue ) ); 2435 return registerEnum( enumName, allEnums, intValues ); 2436 } 2437 }; 2438 2439} // Catch 2440 2441#endif // CATCH_INTERFACES_ENUM_VALUES_REGISTRY_HPP_INCLUDED 2442 2443#ifdef CATCH_CONFIG_CPP17_STRING_VIEW 2444#include <string_view> 2445#endif 2446 2447#ifdef _MSC_VER 2448#pragma warning(push) 2449#pragma warning(disable:4180) // We attempt to stream a function (address) by const&, which MSVC complains about but is harmless 2450#endif 2451 2452// We need a dummy global operator<< so we can bring it into Catch namespace later 2453struct Catch_global_namespace_dummy{}; 2454std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy); 2455 2456namespace Catch { 2457 // Bring in global namespace operator<< for ADL lookup in 2458 // `IsStreamInsertable` below. 2459 using ::operator<<; 2460 2461 namespace Detail { 2462 2463 inline std::size_t catch_strnlen(const char *str, std::size_t n) { 2464 auto ret = std::char_traits<char>::find(str, n, '\0'); 2465 if (ret != nullptr) { 2466 return static_cast<std::size_t>(ret - str); 2467 } 2468 return n; 2469 } 2470 2471 constexpr StringRef unprintableString = "{?}"_sr; 2472 2473 //! Encases `string in quotes, and optionally escapes invisibles 2474 std::string convertIntoString( StringRef string, bool escapeInvisibles ); 2475 2476 //! Encases `string` in quotes, and escapes invisibles if user requested 2477 //! it via CLI 2478 std::string convertIntoString( StringRef string ); 2479 2480 std::string rawMemoryToString( const void *object, std::size_t size ); 2481 2482 template<typename T> 2483 std::string rawMemoryToString( const T& object ) { 2484 return rawMemoryToString( &object, sizeof(object) ); 2485 } 2486 2487 template<typename T> 2488 class IsStreamInsertable { 2489 template<typename Stream, typename U> 2490 static auto test(int) 2491 -> decltype(std::declval<Stream&>() << std::declval<U>(), std::true_type()); 2492 2493 template<typename, typename> 2494 static auto test(...)->std::false_type; 2495 2496 public: 2497 static const bool value = decltype(test<std::ostream, const T&>(0))::value; 2498 }; 2499 2500 template<typename E> 2501 std::string convertUnknownEnumToString( E e ); 2502 2503 template<typename T> 2504 std::enable_if_t< 2505 !std::is_enum<T>::value && !std::is_base_of<std::exception, T>::value, 2506 std::string> convertUnstreamable( T const& ) { 2507 return std::string(Detail::unprintableString); 2508 } 2509 template<typename T> 2510 std::enable_if_t< 2511 !std::is_enum<T>::value && std::is_base_of<std::exception, T>::value, 2512 std::string> convertUnstreamable(T const& ex) { 2513 return ex.what(); 2514 } 2515 2516 2517 template<typename T> 2518 std::enable_if_t< 2519 std::is_enum<T>::value, 2520 std::string> convertUnstreamable( T const& value ) { 2521 return convertUnknownEnumToString( value ); 2522 } 2523 2524#if defined(_MANAGED) 2525 //! Convert a CLR string to a utf8 std::string 2526 template<typename T> 2527 std::string clrReferenceToString( T^ ref ) { 2528 if (ref == nullptr) 2529 return std::string("null"); 2530 auto bytes = System::Text::Encoding::UTF8->GetBytes(ref->ToString()); 2531 cli::pin_ptr<System::Byte> p = &bytes[0]; 2532 return std::string(reinterpret_cast<char const *>(p), bytes->Length); 2533 } 2534#endif 2535 2536 } // namespace Detail 2537 2538 2539 template <typename T, typename = void> 2540 struct StringMaker { 2541 template <typename Fake = T> 2542 static 2543 std::enable_if_t<::Catch::Detail::IsStreamInsertable<Fake>::value, std::string> 2544 convert(const Fake& value) { 2545 ReusableStringStream rss; 2546 // NB: call using the function-like syntax to avoid ambiguity with 2547 // user-defined templated operator<< under clang. 2548 rss.operator<<(value); 2549 return rss.str(); 2550 } 2551 2552 template <typename Fake = T> 2553 static 2554 std::enable_if_t<!::Catch::Detail::IsStreamInsertable<Fake>::value, std::string> 2555 convert( const Fake& value ) { 2556#if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER) 2557 return Detail::convertUnstreamable(value); 2558#else 2559 return CATCH_CONFIG_FALLBACK_STRINGIFIER(value); 2560#endif 2561 } 2562 }; 2563 2564 namespace Detail { 2565 2566 // This function dispatches all stringification requests inside of Catch. 2567 // Should be preferably called fully qualified, like ::Catch::Detail::stringify 2568 template <typename T> 2569 std::string stringify(const T& e) { 2570 return ::Catch::StringMaker<std::remove_cv_t<std::remove_reference_t<T>>>::convert(e); 2571 } 2572 2573 template<typename E> 2574 std::string convertUnknownEnumToString( E e ) { 2575 return ::Catch::Detail::stringify(static_cast<std::underlying_type_t<E>>(e)); 2576 } 2577 2578#if defined(_MANAGED) 2579 template <typename T> 2580 std::string stringify( T^ e ) { 2581 return ::Catch::StringMaker<T^>::convert(e); 2582 } 2583#endif 2584 2585 } // namespace Detail 2586 2587 // Some predefined specializations 2588 2589 template<> 2590 struct StringMaker<std::string> { 2591 static std::string convert(const std::string& str); 2592 }; 2593 2594#ifdef CATCH_CONFIG_CPP17_STRING_VIEW 2595 template<> 2596 struct StringMaker<std::string_view> { 2597 static std::string convert(std::string_view str); 2598 }; 2599#endif 2600 2601 template<> 2602 struct StringMaker<char const *> { 2603 static std::string convert(char const * str); 2604 }; 2605 template<> 2606 struct StringMaker<char *> { 2607 static std::string convert(char * str); 2608 }; 2609 2610#if defined(CATCH_CONFIG_WCHAR) 2611 template<> 2612 struct StringMaker<std::wstring> { 2613 static std::string convert(const std::wstring& wstr); 2614 }; 2615 2616# ifdef CATCH_CONFIG_CPP17_STRING_VIEW 2617 template<> 2618 struct StringMaker<std::wstring_view> { 2619 static std::string convert(std::wstring_view str); 2620 }; 2621# endif 2622 2623 template<> 2624 struct StringMaker<wchar_t const *> { 2625 static std::string convert(wchar_t const * str); 2626 }; 2627 template<> 2628 struct StringMaker<wchar_t *> { 2629 static std::string convert(wchar_t * str); 2630 }; 2631#endif // CATCH_CONFIG_WCHAR 2632 2633 template<size_t SZ> 2634 struct StringMaker<char[SZ]> { 2635 static std::string convert(char const* str) { 2636 return Detail::convertIntoString( 2637 StringRef( str, Detail::catch_strnlen( str, SZ ) ) ); 2638 } 2639 }; 2640 template<size_t SZ> 2641 struct StringMaker<signed char[SZ]> { 2642 static std::string convert(signed char const* str) { 2643 auto reinterpreted = reinterpret_cast<char const*>(str); 2644 return Detail::convertIntoString( 2645 StringRef(reinterpreted, Detail::catch_strnlen(reinterpreted, SZ))); 2646 } 2647 }; 2648 template<size_t SZ> 2649 struct StringMaker<unsigned char[SZ]> { 2650 static std::string convert(unsigned char const* str) { 2651 auto reinterpreted = reinterpret_cast<char const*>(str); 2652 return Detail::convertIntoString( 2653 StringRef(reinterpreted, Detail::catch_strnlen(reinterpreted, SZ))); 2654 } 2655 }; 2656 2657#if defined(CATCH_CONFIG_CPP17_BYTE) 2658 template<> 2659 struct StringMaker<std::byte> { 2660 static std::string convert(std::byte value); 2661 }; 2662#endif // defined(CATCH_CONFIG_CPP17_BYTE) 2663 template<> 2664 struct StringMaker<int> { 2665 static std::string convert(int value); 2666 }; 2667 template<> 2668 struct StringMaker<long> { 2669 static std::string convert(long value); 2670 }; 2671 template<> 2672 struct StringMaker<long long> { 2673 static std::string convert(long long value); 2674 }; 2675 template<> 2676 struct StringMaker<unsigned int> { 2677 static std::string convert(unsigned int value); 2678 }; 2679 template<> 2680 struct StringMaker<unsigned long> { 2681 static std::string convert(unsigned long value); 2682 }; 2683 template<> 2684 struct StringMaker<unsigned long long> { 2685 static std::string convert(unsigned long long value); 2686 }; 2687 2688 template<> 2689 struct StringMaker<bool> { 2690 static std::string convert(bool b) { 2691 using namespace std::string_literals; 2692 return b ? "true"s : "false"s; 2693 } 2694 }; 2695 2696 template<> 2697 struct StringMaker<char> { 2698 static std::string convert(char c); 2699 }; 2700 template<> 2701 struct StringMaker<signed char> { 2702 static std::string convert(signed char value); 2703 }; 2704 template<> 2705 struct StringMaker<unsigned char> { 2706 static std::string convert(unsigned char value); 2707 }; 2708 2709 template<> 2710 struct StringMaker<std::nullptr_t> { 2711 static std::string convert(std::nullptr_t) { 2712 using namespace std::string_literals; 2713 return "nullptr"s; 2714 } 2715 }; 2716 2717 template<> 2718 struct StringMaker<float> { 2719 static std::string convert(float value); 2720 CATCH_EXPORT static int precision; 2721 }; 2722 2723 template<> 2724 struct StringMaker<double> { 2725 static std::string convert(double value); 2726 CATCH_EXPORT static int precision; 2727 }; 2728 2729 template <typename T> 2730 struct StringMaker<T*> { 2731 template <typename U> 2732 static std::string convert(U* p) { 2733 if (p) { 2734 return ::Catch::Detail::rawMemoryToString(p); 2735 } else { 2736 return "nullptr"; 2737 } 2738 } 2739 }; 2740 2741 template <typename R, typename C> 2742 struct StringMaker<R C::*> { 2743 static std::string convert(R C::* p) { 2744 if (p) { 2745 return ::Catch::Detail::rawMemoryToString(p); 2746 } else { 2747 return "nullptr"; 2748 } 2749 } 2750 }; 2751 2752#if defined(_MANAGED) 2753 template <typename T> 2754 struct StringMaker<T^> { 2755 static std::string convert( T^ ref ) { 2756 return ::Catch::Detail::clrReferenceToString(ref); 2757 } 2758 }; 2759#endif 2760 2761 namespace Detail { 2762 template<typename InputIterator, typename Sentinel = InputIterator> 2763 std::string rangeToString(InputIterator first, Sentinel last) { 2764 ReusableStringStream rss; 2765 rss << "{ "; 2766 if (first != last) { 2767 rss << ::Catch::Detail::stringify(*first); 2768 for (++first; first != last; ++first) 2769 rss << ", " << ::Catch::Detail::stringify(*first); 2770 } 2771 rss << " }"; 2772 return rss.str(); 2773 } 2774 } 2775 2776} // namespace Catch 2777 2778////////////////////////////////////////////////////// 2779// Separate std-lib types stringification, so it can be selectively enabled 2780// This means that we do not bring in their headers 2781 2782#if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS) 2783# define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER 2784# define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER 2785# define CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER 2786# define CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER 2787#endif 2788 2789// Separate std::pair specialization 2790#if defined(CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER) 2791#include <utility> 2792namespace Catch { 2793 template<typename T1, typename T2> 2794 struct StringMaker<std::pair<T1, T2> > { 2795 static std::string convert(const std::pair<T1, T2>& pair) { 2796 ReusableStringStream rss; 2797 rss << "{ " 2798 << ::Catch::Detail::stringify(pair.first) 2799 << ", " 2800 << ::Catch::Detail::stringify(pair.second) 2801 << " }"; 2802 return rss.str(); 2803 } 2804 }; 2805} 2806#endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER 2807 2808#if defined(CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_OPTIONAL) 2809#include <optional> 2810namespace Catch { 2811 template<typename T> 2812 struct StringMaker<std::optional<T> > { 2813 static std::string convert(const std::optional<T>& optional) { 2814 if (optional.has_value()) { 2815 return ::Catch::Detail::stringify(*optional); 2816 } else { 2817 return "{ }"; 2818 } 2819 } 2820 }; 2821 template <> 2822 struct StringMaker<std::nullopt_t> { 2823 static std::string convert(const std::nullopt_t&) { 2824 return "{ }"; 2825 } 2826 }; 2827} 2828#endif // CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER 2829 2830// Separate std::tuple specialization 2831#if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER) 2832#include <tuple> 2833namespace Catch { 2834 namespace Detail { 2835 template< 2836 typename Tuple, 2837 std::size_t N = 0, 2838 bool = (N < std::tuple_size<Tuple>::value) 2839 > 2840 struct TupleElementPrinter { 2841 static void print(const Tuple& tuple, std::ostream& os) { 2842 os << (N ? ", " : " ") 2843 << ::Catch::Detail::stringify(std::get<N>(tuple)); 2844 TupleElementPrinter<Tuple, N + 1>::print(tuple, os); 2845 } 2846 }; 2847 2848 template< 2849 typename Tuple, 2850 std::size_t N 2851 > 2852 struct TupleElementPrinter<Tuple, N, false> { 2853 static void print(const Tuple&, std::ostream&) {} 2854 }; 2855 2856 } 2857 2858 2859 template<typename ...Types> 2860 struct StringMaker<std::tuple<Types...>> { 2861 static std::string convert(const std::tuple<Types...>& tuple) { 2862 ReusableStringStream rss; 2863 rss << '{'; 2864 Detail::TupleElementPrinter<std::tuple<Types...>>::print(tuple, rss.get()); 2865 rss << " }"; 2866 return rss.str(); 2867 } 2868 }; 2869} 2870#endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER 2871 2872#if defined(CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_VARIANT) 2873#include <variant> 2874namespace Catch { 2875 template<> 2876 struct StringMaker<std::monostate> { 2877 static std::string convert(const std::monostate&) { 2878 return "{ }"; 2879 } 2880 }; 2881 2882 template<typename... Elements> 2883 struct StringMaker<std::variant<Elements...>> { 2884 static std::string convert(const std::variant<Elements...>& variant) { 2885 if (variant.valueless_by_exception()) { 2886 return "{valueless variant}"; 2887 } else { 2888 return std::visit( 2889 [](const auto& value) { 2890 return ::Catch::Detail::stringify(value); 2891 }, 2892 variant 2893 ); 2894 } 2895 } 2896 }; 2897} 2898#endif // CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER 2899 2900namespace Catch { 2901 // Import begin/ end from std here 2902 using std::begin; 2903 using std::end; 2904 2905 namespace Detail { 2906 template <typename T, typename = void> 2907 struct is_range_impl : std::false_type {}; 2908 2909 template <typename T> 2910 struct is_range_impl<T, void_t<decltype(begin(std::declval<T>()))>> : std::true_type {}; 2911 } // namespace Detail 2912 2913 template <typename T> 2914 struct is_range : Detail::is_range_impl<T> {}; 2915 2916#if defined(_MANAGED) // Managed types are never ranges 2917 template <typename T> 2918 struct is_range<T^> { 2919 static const bool value = false; 2920 }; 2921#endif 2922 2923 template<typename Range> 2924 std::string rangeToString( Range const& range ) { 2925 return ::Catch::Detail::rangeToString( begin( range ), end( range ) ); 2926 } 2927 2928 // Handle vector<bool> specially 2929 template<typename Allocator> 2930 std::string rangeToString( std::vector<bool, Allocator> const& v ) { 2931 ReusableStringStream rss; 2932 rss << "{ "; 2933 bool first = true; 2934 for( bool b : v ) { 2935 if( first ) 2936 first = false; 2937 else 2938 rss << ", "; 2939 rss << ::Catch::Detail::stringify( b ); 2940 } 2941 rss << " }"; 2942 return rss.str(); 2943 } 2944 2945 template<typename R> 2946 struct StringMaker<R, std::enable_if_t<is_range<R>::value && !::Catch::Detail::IsStreamInsertable<R>::value>> { 2947 static std::string convert( R const& range ) { 2948 return rangeToString( range ); 2949 } 2950 }; 2951 2952 template <typename T, size_t SZ> 2953 struct StringMaker<T[SZ]> { 2954 static std::string convert(T const(&arr)[SZ]) { 2955 return rangeToString(arr); 2956 } 2957 }; 2958 2959 2960} // namespace Catch 2961 2962// Separate std::chrono::duration specialization 2963#include <ctime> 2964#include <ratio> 2965#include <chrono> 2966 2967 2968namespace Catch { 2969 2970template <class Ratio> 2971struct ratio_string { 2972 static std::string symbol() { 2973 Catch::ReusableStringStream rss; 2974 rss << '[' << Ratio::num << '/' 2975 << Ratio::den << ']'; 2976 return rss.str(); 2977 } 2978}; 2979 2980template <> 2981struct ratio_string<std::atto> { 2982 static char symbol() { return 'a'; } 2983}; 2984template <> 2985struct ratio_string<std::femto> { 2986 static char symbol() { return 'f'; } 2987}; 2988template <> 2989struct ratio_string<std::pico> { 2990 static char symbol() { return 'p'; } 2991}; 2992template <> 2993struct ratio_string<std::nano> { 2994 static char symbol() { return 'n'; } 2995}; 2996template <> 2997struct ratio_string<std::micro> { 2998 static char symbol() { return 'u'; } 2999}; 3000template <> 3001struct ratio_string<std::milli> { 3002 static char symbol() { return 'm'; } 3003}; 3004 3005 //////////// 3006 // std::chrono::duration specializations 3007 template<typename Value, typename Ratio> 3008 struct StringMaker<std::chrono::duration<Value, Ratio>> { 3009 static std::string convert(std::chrono::duration<Value, Ratio> const& duration) { 3010 ReusableStringStream rss; 3011 rss << duration.count() << ' ' << ratio_string<Ratio>::symbol() << 's'; 3012 return rss.str(); 3013 } 3014 }; 3015 template<typename Value> 3016 struct StringMaker<std::chrono::duration<Value, std::ratio<1>>> { 3017 static std::string convert(std::chrono::duration<Value, std::ratio<1>> const& duration) { 3018 ReusableStringStream rss; 3019 rss << duration.count() << " s"; 3020 return rss.str(); 3021 } 3022 }; 3023 template<typename Value> 3024 struct StringMaker<std::chrono::duration<Value, std::ratio<60>>> { 3025 static std::string convert(std::chrono::duration<Value, std::ratio<60>> const& duration) { 3026 ReusableStringStream rss; 3027 rss << duration.count() << " m"; 3028 return rss.str(); 3029 } 3030 }; 3031 template<typename Value> 3032 struct StringMaker<std::chrono::duration<Value, std::ratio<3600>>> { 3033 static std::string convert(std::chrono::duration<Value, std::ratio<3600>> const& duration) { 3034 ReusableStringStream rss; 3035 rss << duration.count() << " h"; 3036 return rss.str(); 3037 } 3038 }; 3039 3040 //////////// 3041 // std::chrono::time_point specialization 3042 // Generic time_point cannot be specialized, only std::chrono::time_point<system_clock> 3043 template<typename Clock, typename Duration> 3044 struct StringMaker<std::chrono::time_point<Clock, Duration>> { 3045 static std::string convert(std::chrono::time_point<Clock, Duration> const& time_point) { 3046 return ::Catch::Detail::stringify(time_point.time_since_epoch()) + " since epoch"; 3047 } 3048 }; 3049 // std::chrono::time_point<system_clock> specialization 3050 template<typename Duration> 3051 struct StringMaker<std::chrono::time_point<std::chrono::system_clock, Duration>> { 3052 static std::string convert(std::chrono::time_point<std::chrono::system_clock, Duration> const& time_point) { 3053 auto converted = std::chrono::system_clock::to_time_t(time_point); 3054 3055#ifdef _MSC_VER 3056 std::tm timeInfo = {}; 3057 gmtime_s(&timeInfo, &converted); 3058#else 3059 std::tm* timeInfo = std::gmtime(&converted); 3060#endif 3061 3062 auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); 3063 char timeStamp[timeStampSize]; 3064 const char * const fmt = "%Y-%m-%dT%H:%M:%SZ"; 3065 3066#ifdef _MSC_VER 3067 std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); 3068#else 3069 std::strftime(timeStamp, timeStampSize, fmt, timeInfo); 3070#endif 3071 return std::string(timeStamp, timeStampSize - 1); 3072 } 3073 }; 3074} 3075 3076 3077#define INTERNAL_CATCH_REGISTER_ENUM( enumName, ... ) \ 3078namespace Catch { \ 3079 template<> struct StringMaker<enumName> { \ 3080 static std::string convert( enumName value ) { \ 3081 static const auto& enumInfo = ::Catch::getMutableRegistryHub().getMutableEnumValuesRegistry().registerEnum( #enumName, #__VA_ARGS__, { __VA_ARGS__ } ); \ 3082 return static_cast<std::string>(enumInfo.lookup( static_cast<int>( value ) )); \ 3083 } \ 3084 }; \ 3085} 3086 3087#define CATCH_REGISTER_ENUM( enumName, ... ) INTERNAL_CATCH_REGISTER_ENUM( enumName, __VA_ARGS__ ) 3088 3089#ifdef _MSC_VER 3090#pragma warning(pop) 3091#endif 3092 3093#endif // CATCH_TOSTRING_HPP_INCLUDED 3094 3095#include <type_traits> 3096 3097namespace Catch { 3098 3099 class Approx { 3100 private: 3101 bool equalityComparisonImpl(double other) const; 3102 // Sets and validates the new margin (margin >= 0) 3103 void setMargin(double margin); 3104 // Sets and validates the new epsilon (0 < epsilon < 1) 3105 void setEpsilon(double epsilon); 3106 3107 public: 3108 explicit Approx ( double value ); 3109 3110 static Approx custom(); 3111 3112 Approx operator-() const; 3113 3114 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>> 3115 Approx operator()( T const& value ) const { 3116 Approx approx( static_cast<double>(value) ); 3117 approx.m_epsilon = m_epsilon; 3118 approx.m_margin = m_margin; 3119 approx.m_scale = m_scale; 3120 return approx; 3121 } 3122 3123 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>> 3124 explicit Approx( T const& value ): Approx(static_cast<double>(value)) 3125 {} 3126 3127 3128 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>> 3129 friend bool operator == ( const T& lhs, Approx const& rhs ) { 3130 auto lhs_v = static_cast<double>(lhs); 3131 return rhs.equalityComparisonImpl(lhs_v); 3132 } 3133 3134 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>> 3135 friend bool operator == ( Approx const& lhs, const T& rhs ) { 3136 return operator==( rhs, lhs ); 3137 } 3138 3139 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>> 3140 friend bool operator != ( T const& lhs, Approx const& rhs ) { 3141 return !operator==( lhs, rhs ); 3142 } 3143 3144 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>> 3145 friend bool operator != ( Approx const& lhs, T const& rhs ) { 3146 return !operator==( rhs, lhs ); 3147 } 3148 3149 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>> 3150 friend bool operator <= ( T const& lhs, Approx const& rhs ) { 3151 return static_cast<double>(lhs) < rhs.m_value || lhs == rhs; 3152 } 3153 3154 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>> 3155 friend bool operator <= ( Approx const& lhs, T const& rhs ) { 3156 return lhs.m_value < static_cast<double>(rhs) || lhs == rhs; 3157 } 3158 3159 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>> 3160 friend bool operator >= ( T const& lhs, Approx const& rhs ) { 3161 return static_cast<double>(lhs) > rhs.m_value || lhs == rhs; 3162 } 3163 3164 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>> 3165 friend bool operator >= ( Approx const& lhs, T const& rhs ) { 3166 return lhs.m_value > static_cast<double>(rhs) || lhs == rhs; 3167 } 3168 3169 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>> 3170 Approx& epsilon( T const& newEpsilon ) { 3171 const auto epsilonAsDouble = static_cast<double>(newEpsilon); 3172 setEpsilon(epsilonAsDouble); 3173 return *this; 3174 } 3175 3176 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>> 3177 Approx& margin( T const& newMargin ) { 3178 const auto marginAsDouble = static_cast<double>(newMargin); 3179 setMargin(marginAsDouble); 3180 return *this; 3181 } 3182 3183 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>> 3184 Approx& scale( T const& newScale ) { 3185 m_scale = static_cast<double>(newScale); 3186 return *this; 3187 } 3188 3189 std::string toString() const; 3190 3191 private: 3192 double m_epsilon; 3193 double m_margin; 3194 double m_scale; 3195 double m_value; 3196 }; 3197 3198namespace literals { 3199 Approx operator ""_a(long double val); 3200 Approx operator ""_a(unsigned long long val); 3201} // end namespace literals 3202 3203template<> 3204struct StringMaker<Catch::Approx> { 3205 static std::string convert(Catch::Approx const& value); 3206}; 3207 3208} // end namespace Catch 3209 3210#endif // CATCH_APPROX_HPP_INCLUDED 3211 3212 3213#ifndef CATCH_ASSERTION_INFO_HPP_INCLUDED 3214#define CATCH_ASSERTION_INFO_HPP_INCLUDED 3215 3216 3217 3218#ifndef CATCH_SOURCE_LINE_INFO_HPP_INCLUDED 3219#define CATCH_SOURCE_LINE_INFO_HPP_INCLUDED 3220 3221#include <cstddef> 3222#include <iosfwd> 3223 3224namespace Catch { 3225 3226 struct SourceLineInfo { 3227 3228 SourceLineInfo() = delete; 3229 constexpr SourceLineInfo( char const* _file, std::size_t _line ) noexcept: 3230 file( _file ), 3231 line( _line ) 3232 {} 3233 3234 bool operator == ( SourceLineInfo const& other ) const noexcept; 3235 bool operator < ( SourceLineInfo const& other ) const noexcept; 3236 3237 char const* file; 3238 std::size_t line; 3239 3240 friend std::ostream& operator << (std::ostream& os, SourceLineInfo const& info); 3241 }; 3242} 3243 3244#define CATCH_INTERNAL_LINEINFO \ 3245 ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) ) 3246 3247#endif // CATCH_SOURCE_LINE_INFO_HPP_INCLUDED 3248 3249namespace Catch { 3250 3251 struct AssertionInfo { 3252 // AssertionInfo() = delete; 3253 3254 StringRef macroName; 3255 SourceLineInfo lineInfo; 3256 StringRef capturedExpression; 3257 ResultDisposition::Flags resultDisposition; 3258 }; 3259 3260} // end namespace Catch 3261 3262#endif // CATCH_ASSERTION_INFO_HPP_INCLUDED 3263 3264 3265#ifndef CATCH_ASSERTION_RESULT_HPP_INCLUDED 3266#define CATCH_ASSERTION_RESULT_HPP_INCLUDED 3267 3268 3269 3270#ifndef CATCH_LAZY_EXPR_HPP_INCLUDED 3271#define CATCH_LAZY_EXPR_HPP_INCLUDED 3272 3273#include <iosfwd> 3274 3275namespace Catch { 3276 3277 class ITransientExpression; 3278 3279 class LazyExpression { 3280 friend class AssertionHandler; 3281 friend struct AssertionStats; 3282 friend class RunContext; 3283 3284 ITransientExpression const* m_transientExpression = nullptr; 3285 bool m_isNegated; 3286 public: 3287 LazyExpression( bool isNegated ): 3288 m_isNegated(isNegated) 3289 {} 3290 LazyExpression(LazyExpression const& other) = default; 3291 LazyExpression& operator = ( LazyExpression const& ) = delete; 3292 3293 explicit operator bool() const { 3294 return m_transientExpression != nullptr; 3295 } 3296 3297 friend auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream&; 3298 }; 3299 3300} // namespace Catch 3301 3302#endif // CATCH_LAZY_EXPR_HPP_INCLUDED 3303 3304#include <string> 3305 3306namespace Catch { 3307 3308 struct AssertionResultData 3309 { 3310 AssertionResultData() = delete; 3311 3312 AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression ); 3313 3314 std::string message; 3315 mutable std::string reconstructedExpression; 3316 LazyExpression lazyExpression; 3317 ResultWas::OfType resultType; 3318 3319 std::string reconstructExpression() const; 3320 }; 3321 3322 class AssertionResult { 3323 public: 3324 AssertionResult() = delete; 3325 AssertionResult( AssertionInfo const& info, AssertionResultData&& data ); 3326 3327 bool isOk() const; 3328 bool succeeded() const; 3329 ResultWas::OfType getResultType() const; 3330 bool hasExpression() const; 3331 bool hasMessage() const; 3332 std::string getExpression() const; 3333 std::string getExpressionInMacro() const; 3334 bool hasExpandedExpression() const; 3335 std::string getExpandedExpression() const; 3336 StringRef getMessage() const; 3337 SourceLineInfo getSourceInfo() const; 3338 StringRef getTestMacroName() const; 3339 3340 //protected: 3341 AssertionInfo m_info; 3342 AssertionResultData m_resultData; 3343 }; 3344 3345} // end namespace Catch 3346 3347#endif // CATCH_ASSERTION_RESULT_HPP_INCLUDED 3348 3349 3350#ifndef CATCH_CONFIG_HPP_INCLUDED 3351#define CATCH_CONFIG_HPP_INCLUDED 3352 3353 3354 3355#ifndef CATCH_TEST_SPEC_HPP_INCLUDED 3356#define CATCH_TEST_SPEC_HPP_INCLUDED 3357 3358#ifdef __clang__ 3359#pragma clang diagnostic push 3360#pragma clang diagnostic ignored "-Wpadded" 3361#endif 3362 3363 3364 3365#ifndef CATCH_WILDCARD_PATTERN_HPP_INCLUDED 3366#define CATCH_WILDCARD_PATTERN_HPP_INCLUDED 3367 3368 3369 3370#ifndef CATCH_CASE_SENSITIVE_HPP_INCLUDED 3371#define CATCH_CASE_SENSITIVE_HPP_INCLUDED 3372 3373namespace Catch { 3374 3375 enum class CaseSensitive { Yes, No }; 3376 3377} // namespace Catch 3378 3379#endif // CATCH_CASE_SENSITIVE_HPP_INCLUDED 3380 3381#include <string> 3382 3383namespace Catch 3384{ 3385 class WildcardPattern { 3386 enum WildcardPosition { 3387 NoWildcard = 0, 3388 WildcardAtStart = 1, 3389 WildcardAtEnd = 2, 3390 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd 3391 }; 3392 3393 public: 3394 3395 WildcardPattern( std::string const& pattern, CaseSensitive caseSensitivity ); 3396 bool matches( std::string const& str ) const; 3397 3398 private: 3399 std::string normaliseString( std::string const& str ) const; 3400 CaseSensitive m_caseSensitivity; 3401 WildcardPosition m_wildcard = NoWildcard; 3402 std::string m_pattern; 3403 }; 3404} 3405 3406#endif // CATCH_WILDCARD_PATTERN_HPP_INCLUDED 3407 3408#include <iosfwd> 3409#include <string> 3410#include <vector> 3411 3412namespace Catch { 3413 3414 class IConfig; 3415 struct TestCaseInfo; 3416 class TestCaseHandle; 3417 3418 class TestSpec { 3419 3420 class Pattern { 3421 public: 3422 explicit Pattern( std::string const& name ); 3423 virtual ~Pattern(); 3424 virtual bool matches( TestCaseInfo const& testCase ) const = 0; 3425 std::string const& name() const; 3426 private: 3427 virtual void serializeTo( std::ostream& out ) const = 0; 3428 // Writes string that would be reparsed into the pattern 3429 friend std::ostream& operator<<(std::ostream& out, 3430 Pattern const& pattern) { 3431 pattern.serializeTo( out ); 3432 return out; 3433 } 3434 3435 std::string const m_name; 3436 }; 3437 3438 class NamePattern : public Pattern { 3439 public: 3440 explicit NamePattern( std::string const& name, std::string const& filterString ); 3441 bool matches( TestCaseInfo const& testCase ) const override; 3442 private: 3443 void serializeTo( std::ostream& out ) const override; 3444 3445 WildcardPattern m_wildcardPattern; 3446 }; 3447 3448 class TagPattern : public Pattern { 3449 public: 3450 explicit TagPattern( std::string const& tag, std::string const& filterString ); 3451 bool matches( TestCaseInfo const& testCase ) const override; 3452 private: 3453 void serializeTo( std::ostream& out ) const override; 3454 3455 std::string m_tag; 3456 }; 3457 3458 struct Filter { 3459 std::vector<Detail::unique_ptr<Pattern>> m_required; 3460 std::vector<Detail::unique_ptr<Pattern>> m_forbidden; 3461 3462 //! Serializes this filter into a string that would be parsed into 3463 //! an equivalent filter 3464 void serializeTo( std::ostream& out ) const; 3465 friend std::ostream& operator<<(std::ostream& out, Filter const& f) { 3466 f.serializeTo( out ); 3467 return out; 3468 } 3469 3470 bool matches( TestCaseInfo const& testCase ) const; 3471 }; 3472 3473 static std::string extractFilterName( Filter const& filter ); 3474 3475 public: 3476 struct FilterMatch { 3477 std::string name; 3478 std::vector<TestCaseHandle const*> tests; 3479 }; 3480 using Matches = std::vector<FilterMatch>; 3481 using vectorStrings = std::vector<std::string>; 3482 3483 bool hasFilters() const; 3484 bool matches( TestCaseInfo const& testCase ) const; 3485 Matches matchesByFilter( std::vector<TestCaseHandle> const& testCases, IConfig const& config ) const; 3486 const vectorStrings & getInvalidSpecs() const; 3487 3488 private: 3489 std::vector<Filter> m_filters; 3490 std::vector<std::string> m_invalidSpecs; 3491 3492 friend class TestSpecParser; 3493 //! Serializes this test spec into a string that would be parsed into 3494 //! equivalent test spec 3495 void serializeTo( std::ostream& out ) const; 3496 friend std::ostream& operator<<(std::ostream& out, 3497 TestSpec const& spec) { 3498 spec.serializeTo( out ); 3499 return out; 3500 } 3501 }; 3502} 3503 3504#ifdef __clang__ 3505#pragma clang diagnostic pop 3506#endif 3507 3508#endif // CATCH_TEST_SPEC_HPP_INCLUDED 3509 3510 3511#ifndef CATCH_OPTIONAL_HPP_INCLUDED 3512#define CATCH_OPTIONAL_HPP_INCLUDED 3513 3514 3515#include <cassert> 3516 3517namespace Catch { 3518 3519 // An optional type 3520 template<typename T> 3521 class Optional { 3522 public: 3523 Optional(): nullableValue( nullptr ) {} 3524 ~Optional() { reset(); } 3525 3526 Optional( T const& _value ): 3527 nullableValue( new ( storage ) T( _value ) ) {} 3528 Optional( T&& _value ): 3529 nullableValue( new ( storage ) T( CATCH_MOVE( _value ) ) ) {} 3530 3531 Optional& operator=( T const& _value ) { 3532 reset(); 3533 nullableValue = new ( storage ) T( _value ); 3534 return *this; 3535 } 3536 Optional& operator=( T&& _value ) { 3537 reset(); 3538 nullableValue = new ( storage ) T( CATCH_MOVE( _value ) ); 3539 return *this; 3540 } 3541 3542 Optional( Optional const& _other ): 3543 nullableValue( _other ? new ( storage ) T( *_other ) : nullptr ) {} 3544 Optional( Optional&& _other ): 3545 nullableValue( _other ? new ( storage ) T( CATCH_MOVE( *_other ) ) 3546 : nullptr ) {} 3547 3548 Optional& operator=( Optional const& _other ) { 3549 if ( &_other != this ) { 3550 reset(); 3551 if ( _other ) { nullableValue = new ( storage ) T( *_other ); } 3552 } 3553 return *this; 3554 } 3555 Optional& operator=( Optional&& _other ) { 3556 if ( &_other != this ) { 3557 reset(); 3558 if ( _other ) { 3559 nullableValue = new ( storage ) T( CATCH_MOVE( *_other ) ); 3560 } 3561 } 3562 return *this; 3563 } 3564 3565 void reset() { 3566 if ( nullableValue ) { nullableValue->~T(); } 3567 nullableValue = nullptr; 3568 } 3569 3570 T& operator*() { 3571 assert(nullableValue); 3572 return *nullableValue; 3573 } 3574 T const& operator*() const { 3575 assert(nullableValue); 3576 return *nullableValue; 3577 } 3578 T* operator->() { 3579 assert(nullableValue); 3580 return nullableValue; 3581 } 3582 const T* operator->() const { 3583 assert(nullableValue); 3584 return nullableValue; 3585 } 3586 3587 T valueOr( T const& defaultValue ) const { 3588 return nullableValue ? *nullableValue : defaultValue; 3589 } 3590 3591 bool some() const { return nullableValue != nullptr; } 3592 bool none() const { return nullableValue == nullptr; } 3593 3594 bool operator !() const { return nullableValue == nullptr; } 3595 explicit operator bool() const { 3596 return some(); 3597 } 3598 3599 friend bool operator==(Optional const& a, Optional const& b) { 3600 if (a.none() && b.none()) { 3601 return true; 3602 } else if (a.some() && b.some()) { 3603 return *a == *b; 3604 } else { 3605 return false; 3606 } 3607 } 3608 friend bool operator!=(Optional const& a, Optional const& b) { 3609 return !( a == b ); 3610 } 3611 3612 private: 3613 T* nullableValue; 3614 alignas(alignof(T)) char storage[sizeof(T)]; 3615 }; 3616 3617} // end namespace Catch 3618 3619#endif // CATCH_OPTIONAL_HPP_INCLUDED 3620 3621 3622#ifndef CATCH_RANDOM_SEED_GENERATION_HPP_INCLUDED 3623#define CATCH_RANDOM_SEED_GENERATION_HPP_INCLUDED 3624 3625#include <cstdint> 3626 3627namespace Catch { 3628 3629 enum class GenerateFrom { 3630 Time, 3631 RandomDevice, 3632 //! Currently equivalent to RandomDevice, but can change at any point 3633 Default 3634 }; 3635 3636 std::uint32_t generateRandomSeed(GenerateFrom from); 3637 3638} // end namespace Catch 3639 3640#endif // CATCH_RANDOM_SEED_GENERATION_HPP_INCLUDED 3641 3642 3643#ifndef CATCH_REPORTER_SPEC_PARSER_HPP_INCLUDED 3644#define CATCH_REPORTER_SPEC_PARSER_HPP_INCLUDED 3645 3646 3647#include <map> 3648#include <string> 3649#include <vector> 3650 3651namespace Catch { 3652 3653 enum class ColourMode : std::uint8_t; 3654 3655 namespace Detail { 3656 //! Splits the reporter spec into reporter name and kv-pair options 3657 std::vector<std::string> splitReporterSpec( StringRef reporterSpec ); 3658 3659 Optional<ColourMode> stringToColourMode( StringRef colourMode ); 3660 } 3661 3662 /** 3663 * Structured reporter spec that a reporter can be created from 3664 * 3665 * Parsing has been validated, but semantics have not. This means e.g. 3666 * that the colour mode is known to Catch2, but it might not be 3667 * compiled into the binary, and the output filename might not be 3668 * openable. 3669 */ 3670 class ReporterSpec { 3671 std::string m_name; 3672 Optional<std::string> m_outputFileName; 3673 Optional<ColourMode> m_colourMode; 3674 std::map<std::string, std::string> m_customOptions; 3675 3676 friend bool operator==( ReporterSpec const& lhs, 3677 ReporterSpec const& rhs ); 3678 friend bool operator!=( ReporterSpec const& lhs, 3679 ReporterSpec const& rhs ) { 3680 return !( lhs == rhs ); 3681 } 3682 3683 public: 3684 ReporterSpec( 3685 std::string name, 3686 Optional<std::string> outputFileName, 3687 Optional<ColourMode> colourMode, 3688 std::map<std::string, std::string> customOptions ); 3689 3690 std::string const& name() const { return m_name; } 3691 3692 Optional<std::string> const& outputFile() const { 3693 return m_outputFileName; 3694 } 3695 3696 Optional<ColourMode> const& colourMode() const { return m_colourMode; } 3697 3698 std::map<std::string, std::string> const& customOptions() const { 3699 return m_customOptions; 3700 } 3701 }; 3702 3703 /** 3704 * Parses provided reporter spec string into 3705 * 3706 * Returns empty optional on errors, e.g. 3707 * * field that is not first and not a key+value pair 3708 * * duplicated keys in kv pair 3709 * * unknown catch reporter option 3710 * * empty key/value in an custom kv pair 3711 * * ... 3712 */ 3713 Optional<ReporterSpec> parseReporterSpec( StringRef reporterSpec ); 3714 3715} 3716 3717#endif // CATCH_REPORTER_SPEC_PARSER_HPP_INCLUDED 3718 3719#include <chrono> 3720#include <map> 3721#include <string> 3722#include <vector> 3723 3724namespace Catch { 3725 3726 class IStream; 3727 3728 /** 3729 * `ReporterSpec` but with the defaults filled in. 3730 * 3731 * Like `ReporterSpec`, the semantics are unchecked. 3732 */ 3733 struct ProcessedReporterSpec { 3734 std::string name; 3735 std::string outputFilename; 3736 ColourMode colourMode; 3737 std::map<std::string, std::string> customOptions; 3738 friend bool operator==( ProcessedReporterSpec const& lhs, 3739 ProcessedReporterSpec const& rhs ); 3740 friend bool operator!=( ProcessedReporterSpec const& lhs, 3741 ProcessedReporterSpec const& rhs ) { 3742 return !( lhs == rhs ); 3743 } 3744 }; 3745 3746 struct ConfigData { 3747 3748 bool listTests = false; 3749 bool listTags = false; 3750 bool listReporters = false; 3751 bool listListeners = false; 3752 3753 bool showSuccessfulTests = false; 3754 bool shouldDebugBreak = false; 3755 bool noThrow = false; 3756 bool showHelp = false; 3757 bool showInvisibles = false; 3758 bool filenamesAsTags = false; 3759 bool libIdentify = false; 3760 bool allowZeroTests = false; 3761 3762 int abortAfter = -1; 3763 uint32_t rngSeed = generateRandomSeed(GenerateFrom::Default); 3764 3765 unsigned int shardCount = 1; 3766 unsigned int shardIndex = 0; 3767 3768 bool skipBenchmarks = false; 3769 bool benchmarkNoAnalysis = false; 3770 unsigned int benchmarkSamples = 100; 3771 double benchmarkConfidenceInterval = 0.95; 3772 unsigned int benchmarkResamples = 100'000; 3773 std::chrono::milliseconds::rep benchmarkWarmupTime = 100; 3774 3775 Verbosity verbosity = Verbosity::Normal; 3776 WarnAbout::What warnings = WarnAbout::Nothing; 3777 ShowDurations showDurations = ShowDurations::DefaultForReporter; 3778 double minDuration = -1; 3779 TestRunOrder runOrder = TestRunOrder::Declared; 3780 ColourMode defaultColourMode = ColourMode::PlatformDefault; 3781 WaitForKeypress::When waitForKeypress = WaitForKeypress::Never; 3782 3783 std::string defaultOutputFilename; 3784 std::string name; 3785 std::string processName; 3786 std::vector<ReporterSpec> reporterSpecifications; 3787 3788 std::vector<std::string> testsOrTags; 3789 std::vector<std::string> sectionsToRun; 3790 }; 3791 3792 3793 class Config : public IConfig { 3794 public: 3795 3796 Config() = default; 3797 Config( ConfigData const& data ); 3798 ~Config() override; // = default in the cpp file 3799 3800 bool listTests() const; 3801 bool listTags() const; 3802 bool listReporters() const; 3803 bool listListeners() const; 3804 3805 std::vector<ReporterSpec> const& getReporterSpecs() const; 3806 std::vector<ProcessedReporterSpec> const& 3807 getProcessedReporterSpecs() const; 3808 3809 std::vector<std::string> const& getTestsOrTags() const override; 3810 std::vector<std::string> const& getSectionsToRun() const override; 3811 3812 TestSpec const& testSpec() const override; 3813 bool hasTestFilters() const override; 3814 3815 bool showHelp() const; 3816 3817 // IConfig interface 3818 bool allowThrows() const override; 3819 StringRef name() const override; 3820 bool includeSuccessfulResults() const override; 3821 bool warnAboutMissingAssertions() const override; 3822 bool warnAboutUnmatchedTestSpecs() const override; 3823 bool zeroTestsCountAsSuccess() const override; 3824 ShowDurations showDurations() const override; 3825 double minDuration() const override; 3826 TestRunOrder runOrder() const override; 3827 uint32_t rngSeed() const override; 3828 unsigned int shardCount() const override; 3829 unsigned int shardIndex() const override; 3830 ColourMode defaultColourMode() const override; 3831 bool shouldDebugBreak() const override; 3832 int abortAfter() const override; 3833 bool showInvisibles() const override; 3834 Verbosity verbosity() const override; 3835 bool skipBenchmarks() const override; 3836 bool benchmarkNoAnalysis() const override; 3837 unsigned int benchmarkSamples() const override; 3838 double benchmarkConfidenceInterval() const override; 3839 unsigned int benchmarkResamples() const override; 3840 std::chrono::milliseconds benchmarkWarmupTime() const override; 3841 3842 private: 3843 // Reads Bazel env vars and applies them to the config 3844 void readBazelEnvVars(); 3845 3846 ConfigData m_data; 3847 std::vector<ProcessedReporterSpec> m_processedReporterSpecs; 3848 TestSpec m_testSpec; 3849 bool m_hasTestFilters = false; 3850 }; 3851} // end namespace Catch 3852 3853#endif // CATCH_CONFIG_HPP_INCLUDED 3854 3855 3856#ifndef CATCH_GET_RANDOM_SEED_HPP_INCLUDED 3857#define CATCH_GET_RANDOM_SEED_HPP_INCLUDED 3858 3859#include <cstdint> 3860 3861namespace Catch { 3862 //! Returns Catch2's current RNG seed. 3863 std::uint32_t getSeed(); 3864} 3865 3866#endif // CATCH_GET_RANDOM_SEED_HPP_INCLUDED 3867 3868 3869#ifndef CATCH_MESSAGE_HPP_INCLUDED 3870#define CATCH_MESSAGE_HPP_INCLUDED 3871 3872 3873 3874 3875/** \file 3876 * Wrapper for the CATCH_CONFIG_PREFIX_MESSAGES configuration option 3877 * 3878 * CATCH_CONFIG_PREFIX_ALL can be used to avoid clashes with other macros 3879 * by prepending CATCH_. This may not be desirable if the only clashes are with 3880 * logger macros such as INFO and WARN. In this cases 3881 * CATCH_CONFIG_PREFIX_MESSAGES can be used to only prefix a small subset 3882 * of relevant macros. 3883 * 3884 */ 3885 3886#ifndef CATCH_CONFIG_PREFIX_MESSAGES_HPP_INCLUDED 3887#define CATCH_CONFIG_PREFIX_MESSAGES_HPP_INCLUDED 3888 3889 3890#if defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_PREFIX_MESSAGES) 3891 #define CATCH_CONFIG_PREFIX_MESSAGES 3892#endif 3893 3894#endif // CATCH_CONFIG_PREFIX_MESSAGES_HPP_INCLUDED 3895 3896 3897#ifndef CATCH_STREAM_END_STOP_HPP_INCLUDED 3898#define CATCH_STREAM_END_STOP_HPP_INCLUDED 3899 3900 3901namespace Catch { 3902 3903 // Use this in variadic streaming macros to allow 3904 // << +StreamEndStop 3905 // as well as 3906 // << stuff +StreamEndStop 3907 struct StreamEndStop { 3908 constexpr StringRef operator+() const { return StringRef(); } 3909 3910 template <typename T> 3911 constexpr friend T const& operator+( T const& value, StreamEndStop ) { 3912 return value; 3913 } 3914 }; 3915 3916} // namespace Catch 3917 3918#endif // CATCH_STREAM_END_STOP_HPP_INCLUDED 3919 3920 3921#ifndef CATCH_MESSAGE_INFO_HPP_INCLUDED 3922#define CATCH_MESSAGE_INFO_HPP_INCLUDED 3923 3924 3925#include <string> 3926 3927namespace Catch { 3928 3929 struct MessageInfo { 3930 MessageInfo( StringRef _macroName, 3931 SourceLineInfo const& _lineInfo, 3932 ResultWas::OfType _type ); 3933 3934 StringRef macroName; 3935 std::string message; 3936 SourceLineInfo lineInfo; 3937 ResultWas::OfType type; 3938 unsigned int sequence; 3939 3940 bool operator == (MessageInfo const& other) const { 3941 return sequence == other.sequence; 3942 } 3943 bool operator < (MessageInfo const& other) const { 3944 return sequence < other.sequence; 3945 } 3946 private: 3947 static unsigned int globalCount; 3948 }; 3949 3950} // end namespace Catch 3951 3952#endif // CATCH_MESSAGE_INFO_HPP_INCLUDED 3953 3954#include <string> 3955#include <vector> 3956 3957namespace Catch { 3958 3959 struct SourceLineInfo; 3960 class IResultCapture; 3961 3962 struct MessageStream { 3963 3964 template<typename T> 3965 MessageStream& operator << ( T const& value ) { 3966 m_stream << value; 3967 return *this; 3968 } 3969 3970 ReusableStringStream m_stream; 3971 }; 3972 3973 struct MessageBuilder : MessageStream { 3974 MessageBuilder( StringRef macroName, 3975 SourceLineInfo const& lineInfo, 3976 ResultWas::OfType type ): 3977 m_info(macroName, lineInfo, type) {} 3978 3979 template<typename T> 3980 MessageBuilder&& operator << ( T const& value ) && { 3981 m_stream << value; 3982 return CATCH_MOVE(*this); 3983 } 3984 3985 MessageInfo m_info; 3986 }; 3987 3988 class ScopedMessage { 3989 public: 3990 explicit ScopedMessage( MessageBuilder&& builder ); 3991 ScopedMessage( ScopedMessage& duplicate ) = delete; 3992 ScopedMessage( ScopedMessage&& old ) noexcept; 3993 ~ScopedMessage(); 3994 3995 MessageInfo m_info; 3996 bool m_moved = false; 3997 }; 3998 3999 class Capturer { 4000 std::vector<MessageInfo> m_messages; 4001 IResultCapture& m_resultCapture; 4002 size_t m_captured = 0; 4003 public: 4004 Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names ); 4005 4006 Capturer(Capturer const&) = delete; 4007 Capturer& operator=(Capturer const&) = delete; 4008 4009 ~Capturer(); 4010 4011 void captureValue( size_t index, std::string const& value ); 4012 4013 template<typename T> 4014 void captureValues( size_t index, T const& value ) { 4015 captureValue( index, Catch::Detail::stringify( value ) ); 4016 } 4017 4018 template<typename T, typename... Ts> 4019 void captureValues( size_t index, T const& value, Ts const&... values ) { 4020 captureValue( index, Catch::Detail::stringify(value) ); 4021 captureValues( index+1, values... ); 4022 } 4023 }; 4024 4025} // end namespace Catch 4026 4027/////////////////////////////////////////////////////////////////////////////// 4028#define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \ 4029 do { \ 4030 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::StringRef(), resultDisposition ); \ 4031 catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \ 4032 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 4033 } while( false ) 4034 4035/////////////////////////////////////////////////////////////////////////////// 4036#define INTERNAL_CATCH_CAPTURE( varName, macroName, ... ) \ 4037 Catch::Capturer varName( macroName##_catch_sr, \ 4038 CATCH_INTERNAL_LINEINFO, \ 4039 Catch::ResultWas::Info, \ 4040 #__VA_ARGS__##_catch_sr ); \ 4041 varName.captureValues( 0, __VA_ARGS__ ) 4042 4043/////////////////////////////////////////////////////////////////////////////// 4044#define INTERNAL_CATCH_INFO( macroName, log ) \ 4045 const Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log ) 4046 4047/////////////////////////////////////////////////////////////////////////////// 4048#define INTERNAL_CATCH_UNSCOPED_INFO( macroName, log ) \ 4049 Catch::getResultCapture().emplaceUnscopedMessage( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log ) 4050 4051 4052#if defined(CATCH_CONFIG_PREFIX_MESSAGES) && !defined(CATCH_CONFIG_DISABLE) 4053 4054 #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) 4055 #define CATCH_UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "CATCH_UNSCOPED_INFO", msg ) 4056 #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) 4057 #define CATCH_CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CATCH_CAPTURE", __VA_ARGS__ ) 4058 4059#elif defined(CATCH_CONFIG_PREFIX_MESSAGES) && defined(CATCH_CONFIG_DISABLE) 4060 4061 #define CATCH_INFO( msg ) (void)(0) 4062 #define CATCH_UNSCOPED_INFO( msg ) (void)(0) 4063 #define CATCH_WARN( msg ) (void)(0) 4064 #define CATCH_CAPTURE( ... ) (void)(0) 4065 4066#elif !defined(CATCH_CONFIG_PREFIX_MESSAGES) && !defined(CATCH_CONFIG_DISABLE) 4067 4068 #define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) 4069 #define UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "UNSCOPED_INFO", msg ) 4070 #define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) 4071 #define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE", __VA_ARGS__ ) 4072 4073#elif !defined(CATCH_CONFIG_PREFIX_MESSAGES) && defined(CATCH_CONFIG_DISABLE) 4074 4075 #define INFO( msg ) (void)(0) 4076 #define UNSCOPED_INFO( msg ) (void)(0) 4077 #define WARN( msg ) (void)(0) 4078 #define CAPTURE( ... ) (void)(0) 4079 4080#endif // end of user facing macro declarations 4081 4082 4083 4084 4085#endif // CATCH_MESSAGE_HPP_INCLUDED 4086 4087 4088#ifndef CATCH_SECTION_INFO_HPP_INCLUDED 4089#define CATCH_SECTION_INFO_HPP_INCLUDED 4090 4091 4092 4093#ifndef CATCH_TOTALS_HPP_INCLUDED 4094#define CATCH_TOTALS_HPP_INCLUDED 4095 4096#include <cstdint> 4097 4098namespace Catch { 4099 4100 struct Counts { 4101 Counts operator - ( Counts const& other ) const; 4102 Counts& operator += ( Counts const& other ); 4103 4104 std::uint64_t total() const; 4105 bool allPassed() const; 4106 bool allOk() const; 4107 4108 std::uint64_t passed = 0; 4109 std::uint64_t failed = 0; 4110 std::uint64_t failedButOk = 0; 4111 std::uint64_t skipped = 0; 4112 }; 4113 4114 struct Totals { 4115 4116 Totals operator - ( Totals const& other ) const; 4117 Totals& operator += ( Totals const& other ); 4118 4119 Totals delta( Totals const& prevTotals ) const; 4120 4121 Counts assertions; 4122 Counts testCases; 4123 }; 4124} 4125 4126#endif // CATCH_TOTALS_HPP_INCLUDED 4127 4128#include <string> 4129 4130namespace Catch { 4131 4132 struct SectionInfo { 4133 // The last argument is ignored, so that people can write 4134 // SECTION("ShortName", "Proper description that is long") and 4135 // still use the `-c` flag comfortably. 4136 SectionInfo( SourceLineInfo const& _lineInfo, std::string _name, 4137 const char* const = nullptr ): 4138 name(CATCH_MOVE(_name)), 4139 lineInfo(_lineInfo) 4140 {} 4141 4142 std::string name; 4143 SourceLineInfo lineInfo; 4144 }; 4145 4146 struct SectionEndInfo { 4147 SectionInfo sectionInfo; 4148 Counts prevAssertions; 4149 double durationInSeconds; 4150 }; 4151 4152} // end namespace Catch 4153 4154#endif // CATCH_SECTION_INFO_HPP_INCLUDED 4155 4156 4157#ifndef CATCH_SESSION_HPP_INCLUDED 4158#define CATCH_SESSION_HPP_INCLUDED 4159 4160 4161 4162#ifndef CATCH_COMMANDLINE_HPP_INCLUDED 4163#define CATCH_COMMANDLINE_HPP_INCLUDED 4164 4165 4166 4167#ifndef CATCH_CLARA_HPP_INCLUDED 4168#define CATCH_CLARA_HPP_INCLUDED 4169 4170#if defined( __clang__ ) 4171# pragma clang diagnostic push 4172# pragma clang diagnostic ignored "-Wweak-vtables" 4173# pragma clang diagnostic ignored "-Wshadow" 4174# pragma clang diagnostic ignored "-Wdeprecated" 4175#endif 4176 4177#if defined( __GNUC__ ) 4178# pragma GCC diagnostic push 4179# pragma GCC diagnostic ignored "-Wsign-conversion" 4180#endif 4181 4182#ifndef CLARA_CONFIG_OPTIONAL_TYPE 4183# ifdef __has_include 4184# if __has_include( <optional>) && __cplusplus >= 201703L 4185# include <optional> 4186# define CLARA_CONFIG_OPTIONAL_TYPE std::optional 4187# endif 4188# endif 4189#endif 4190 4191 4192#include <cassert> 4193#include <memory> 4194#include <ostream> 4195#include <sstream> 4196#include <string> 4197#include <type_traits> 4198#include <vector> 4199 4200namespace Catch { 4201 namespace Clara { 4202 4203 class Args; 4204 class Parser; 4205 4206 // enum of result types from a parse 4207 enum class ParseResultType { 4208 Matched, 4209 NoMatch, 4210 ShortCircuitAll, 4211 ShortCircuitSame 4212 }; 4213 4214 struct accept_many_t {}; 4215 constexpr accept_many_t accept_many {}; 4216 4217 namespace Detail { 4218 struct fake_arg { 4219 template <typename T> 4220 operator T(); 4221 }; 4222 4223 template <typename F, typename = void> 4224 struct is_unary_function : std::false_type {}; 4225 4226 template <typename F> 4227 struct is_unary_function< 4228 F, 4229 Catch::Detail::void_t<decltype( 4230 std::declval<F>()( fake_arg() ) ) 4231 > 4232 > : std::true_type {}; 4233 4234 // Traits for extracting arg and return type of lambdas (for single 4235 // argument lambdas) 4236 template <typename L> 4237 struct UnaryLambdaTraits 4238 : UnaryLambdaTraits<decltype( &L::operator() )> {}; 4239 4240 template <typename ClassT, typename ReturnT, typename... Args> 4241 struct UnaryLambdaTraits<ReturnT ( ClassT::* )( Args... ) const> { 4242 static const bool isValid = false; 4243 }; 4244 4245 template <typename ClassT, typename ReturnT, typename ArgT> 4246 struct UnaryLambdaTraits<ReturnT ( ClassT::* )( ArgT ) const> { 4247 static const bool isValid = true; 4248 using ArgType = std::remove_const_t<std::remove_reference_t<ArgT>>; 4249 using ReturnType = ReturnT; 4250 }; 4251 4252 class TokenStream; 4253 4254 // Wraps a token coming from a token stream. These may not directly 4255 // correspond to strings as a single string may encode an option + 4256 // its argument if the : or = form is used 4257 enum class TokenType { Option, Argument }; 4258 struct Token { 4259 TokenType type; 4260 StringRef token; 4261 }; 4262 4263 // Abstracts iterators into args as a stream of tokens, with option 4264 // arguments uniformly handled 4265 class TokenStream { 4266 using Iterator = std::vector<StringRef>::const_iterator; 4267 Iterator it; 4268 Iterator itEnd; 4269 std::vector<Token> m_tokenBuffer; 4270 void loadBuffer(); 4271 4272 public: 4273 explicit TokenStream( Args const& args ); 4274 TokenStream( Iterator it, Iterator itEnd ); 4275 4276 explicit operator bool() const { 4277 return !m_tokenBuffer.empty() || it != itEnd; 4278 } 4279 4280 size_t count() const { 4281 return m_tokenBuffer.size() + ( itEnd - it ); 4282 } 4283 4284 Token operator*() const { 4285 assert( !m_tokenBuffer.empty() ); 4286 return m_tokenBuffer.front(); 4287 } 4288 4289 Token const* operator->() const { 4290 assert( !m_tokenBuffer.empty() ); 4291 return &m_tokenBuffer.front(); 4292 } 4293 4294 TokenStream& operator++(); 4295 }; 4296 4297 //! Denotes type of a parsing result 4298 enum class ResultType { 4299 Ok, ///< No errors 4300 LogicError, ///< Error in user-specified arguments for 4301 ///< construction 4302 RuntimeError ///< Error in parsing inputs 4303 }; 4304 4305 class ResultBase { 4306 protected: 4307 ResultBase( ResultType type ): m_type( type ) {} 4308 virtual ~ResultBase(); // = default; 4309 4310 4311 ResultBase(ResultBase const&) = default; 4312 ResultBase& operator=(ResultBase const&) = default; 4313 ResultBase(ResultBase&&) = default; 4314 ResultBase& operator=(ResultBase&&) = default; 4315 4316 virtual void enforceOk() const = 0; 4317 4318 ResultType m_type; 4319 }; 4320 4321 template <typename T> 4322 class ResultValueBase : public ResultBase { 4323 public: 4324 T const& value() const& { 4325 enforceOk(); 4326 return m_value; 4327 } 4328 T&& value() && { 4329 enforceOk(); 4330 return CATCH_MOVE( m_value ); 4331 } 4332 4333 protected: 4334 ResultValueBase( ResultType type ): ResultBase( type ) {} 4335 4336 ResultValueBase( ResultValueBase const& other ): 4337 ResultBase( other ) { 4338 if ( m_type == ResultType::Ok ) 4339 new ( &m_value ) T( other.m_value ); 4340 } 4341 ResultValueBase( ResultValueBase&& other ): 4342 ResultBase( other ) { 4343 if ( m_type == ResultType::Ok ) 4344 new ( &m_value ) T( CATCH_MOVE(other.m_value) ); 4345 } 4346 4347 4348 ResultValueBase( ResultType, T const& value ): 4349 ResultBase( ResultType::Ok ) { 4350 new ( &m_value ) T( value ); 4351 } 4352 ResultValueBase( ResultType, T&& value ): 4353 ResultBase( ResultType::Ok ) { 4354 new ( &m_value ) T( CATCH_MOVE(value) ); 4355 } 4356 4357 ResultValueBase& operator=( ResultValueBase const& other ) { 4358 if ( m_type == ResultType::Ok ) 4359 m_value.~T(); 4360 ResultBase::operator=( other ); 4361 if ( m_type == ResultType::Ok ) 4362 new ( &m_value ) T( other.m_value ); 4363 return *this; 4364 } 4365 ResultValueBase& operator=( ResultValueBase&& other ) { 4366 if ( m_type == ResultType::Ok ) m_value.~T(); 4367 ResultBase::operator=( other ); 4368 if ( m_type == ResultType::Ok ) 4369 new ( &m_value ) T( CATCH_MOVE(other.m_value) ); 4370 return *this; 4371 } 4372 4373 4374 ~ResultValueBase() override { 4375 if ( m_type == ResultType::Ok ) 4376 m_value.~T(); 4377 } 4378 4379 union { 4380 T m_value; 4381 }; 4382 }; 4383 4384 template <> class ResultValueBase<void> : public ResultBase { 4385 protected: 4386 using ResultBase::ResultBase; 4387 }; 4388 4389 template <typename T = void> 4390 class BasicResult : public ResultValueBase<T> { 4391 public: 4392 template <typename U> 4393 explicit BasicResult( BasicResult<U> const& other ): 4394 ResultValueBase<T>( other.type() ), 4395 m_errorMessage( other.errorMessage() ) { 4396 assert( type() != ResultType::Ok ); 4397 } 4398 4399 template <typename U> 4400 static auto ok( U&& value ) -> BasicResult { 4401 return { ResultType::Ok, CATCH_FORWARD(value) }; 4402 } 4403 static auto ok() -> BasicResult { return { ResultType::Ok }; } 4404 static auto logicError( std::string&& message ) 4405 -> BasicResult { 4406 return { ResultType::LogicError, CATCH_MOVE(message) }; 4407 } 4408 static auto runtimeError( std::string&& message ) 4409 -> BasicResult { 4410 return { ResultType::RuntimeError, CATCH_MOVE(message) }; 4411 } 4412 4413 explicit operator bool() const { 4414 return m_type == ResultType::Ok; 4415 } 4416 auto type() const -> ResultType { return m_type; } 4417 auto errorMessage() const -> std::string const& { 4418 return m_errorMessage; 4419 } 4420 4421 protected: 4422 void enforceOk() const override { 4423 4424 // Errors shouldn't reach this point, but if they do 4425 // the actual error message will be in m_errorMessage 4426 assert( m_type != ResultType::LogicError ); 4427 assert( m_type != ResultType::RuntimeError ); 4428 if ( m_type != ResultType::Ok ) 4429 std::abort(); 4430 } 4431 4432 std::string 4433 m_errorMessage; // Only populated if resultType is an error 4434 4435 BasicResult( ResultType type, 4436 std::string&& message ): 4437 ResultValueBase<T>( type ), m_errorMessage( CATCH_MOVE(message) ) { 4438 assert( m_type != ResultType::Ok ); 4439 } 4440 4441 using ResultValueBase<T>::ResultValueBase; 4442 using ResultBase::m_type; 4443 }; 4444 4445 class ParseState { 4446 public: 4447 ParseState( ParseResultType type, 4448 TokenStream remainingTokens ); 4449 4450 ParseResultType type() const { return m_type; } 4451 TokenStream const& remainingTokens() const& { 4452 return m_remainingTokens; 4453 } 4454 TokenStream&& remainingTokens() && { 4455 return CATCH_MOVE( m_remainingTokens ); 4456 } 4457 4458 private: 4459 ParseResultType m_type; 4460 TokenStream m_remainingTokens; 4461 }; 4462 4463 using Result = BasicResult<void>; 4464 using ParserResult = BasicResult<ParseResultType>; 4465 using InternalParseResult = BasicResult<ParseState>; 4466 4467 struct HelpColumns { 4468 std::string left; 4469 StringRef descriptions; 4470 }; 4471 4472 template <typename T> 4473 ParserResult convertInto( std::string const& source, T& target ) { 4474 std::stringstream ss( source ); 4475 ss >> target; 4476 if ( ss.fail() ) { 4477 return ParserResult::runtimeError( 4478 "Unable to convert '" + source + 4479 "' to destination type" ); 4480 } else { 4481 return ParserResult::ok( ParseResultType::Matched ); 4482 } 4483 } 4484 ParserResult convertInto( std::string const& source, 4485 std::string& target ); 4486 ParserResult convertInto( std::string const& source, bool& target ); 4487 4488#ifdef CLARA_CONFIG_OPTIONAL_TYPE 4489 template <typename T> 4490 auto convertInto( std::string const& source, 4491 CLARA_CONFIG_OPTIONAL_TYPE<T>& target ) 4492 -> ParserResult { 4493 T temp; 4494 auto result = convertInto( source, temp ); 4495 if ( result ) 4496 target = CATCH_MOVE( temp ); 4497 return result; 4498 } 4499#endif // CLARA_CONFIG_OPTIONAL_TYPE 4500 4501 struct BoundRef : Catch::Detail::NonCopyable { 4502 virtual ~BoundRef() = default; 4503 virtual bool isContainer() const; 4504 virtual bool isFlag() const; 4505 }; 4506 struct BoundValueRefBase : BoundRef { 4507 virtual auto setValue( std::string const& arg ) 4508 -> ParserResult = 0; 4509 }; 4510 struct BoundFlagRefBase : BoundRef { 4511 virtual auto setFlag( bool flag ) -> ParserResult = 0; 4512 bool isFlag() const override; 4513 }; 4514 4515 template <typename T> struct BoundValueRef : BoundValueRefBase { 4516 T& m_ref; 4517 4518 explicit BoundValueRef( T& ref ): m_ref( ref ) {} 4519 4520 ParserResult setValue( std::string const& arg ) override { 4521 return convertInto( arg, m_ref ); 4522 } 4523 }; 4524 4525 template <typename T> 4526 struct BoundValueRef<std::vector<T>> : BoundValueRefBase { 4527 std::vector<T>& m_ref; 4528 4529 explicit BoundValueRef( std::vector<T>& ref ): m_ref( ref ) {} 4530 4531 auto isContainer() const -> bool override { return true; } 4532 4533 auto setValue( std::string const& arg ) 4534 -> ParserResult override { 4535 T temp; 4536 auto result = convertInto( arg, temp ); 4537 if ( result ) 4538 m_ref.push_back( temp ); 4539 return result; 4540 } 4541 }; 4542 4543 struct BoundFlagRef : BoundFlagRefBase { 4544 bool& m_ref; 4545 4546 explicit BoundFlagRef( bool& ref ): m_ref( ref ) {} 4547 4548 ParserResult setFlag( bool flag ) override; 4549 }; 4550 4551 template <typename ReturnType> struct LambdaInvoker { 4552 static_assert( 4553 std::is_same<ReturnType, ParserResult>::value, 4554 "Lambda must return void or clara::ParserResult" ); 4555 4556 template <typename L, typename ArgType> 4557 static auto invoke( L const& lambda, ArgType const& arg ) 4558 -> ParserResult { 4559 return lambda( arg ); 4560 } 4561 }; 4562 4563 template <> struct LambdaInvoker<void> { 4564 template <typename L, typename ArgType> 4565 static auto invoke( L const& lambda, ArgType const& arg ) 4566 -> ParserResult { 4567 lambda( arg ); 4568 return ParserResult::ok( ParseResultType::Matched ); 4569 } 4570 }; 4571 4572 template <typename ArgType, typename L> 4573 auto invokeLambda( L const& lambda, std::string const& arg ) 4574 -> ParserResult { 4575 ArgType temp{}; 4576 auto result = convertInto( arg, temp ); 4577 return !result ? result 4578 : LambdaInvoker<typename UnaryLambdaTraits< 4579 L>::ReturnType>::invoke( lambda, temp ); 4580 } 4581 4582 template <typename L> struct BoundLambda : BoundValueRefBase { 4583 L m_lambda; 4584 4585 static_assert( 4586 UnaryLambdaTraits<L>::isValid, 4587 "Supplied lambda must take exactly one argument" ); 4588 explicit BoundLambda( L const& lambda ): m_lambda( lambda ) {} 4589 4590 auto setValue( std::string const& arg ) 4591 -> ParserResult override { 4592 return invokeLambda<typename UnaryLambdaTraits<L>::ArgType>( 4593 m_lambda, arg ); 4594 } 4595 }; 4596 4597 template <typename L> struct BoundManyLambda : BoundLambda<L> { 4598 explicit BoundManyLambda( L const& lambda ): BoundLambda<L>( lambda ) {} 4599 bool isContainer() const override { return true; } 4600 }; 4601 4602 template <typename L> struct BoundFlagLambda : BoundFlagRefBase { 4603 L m_lambda; 4604 4605 static_assert( 4606 UnaryLambdaTraits<L>::isValid, 4607 "Supplied lambda must take exactly one argument" ); 4608 static_assert( 4609 std::is_same<typename UnaryLambdaTraits<L>::ArgType, 4610 bool>::value, 4611 "flags must be boolean" ); 4612 4613 explicit BoundFlagLambda( L const& lambda ): 4614 m_lambda( lambda ) {} 4615 4616 auto setFlag( bool flag ) -> ParserResult override { 4617 return LambdaInvoker<typename UnaryLambdaTraits< 4618 L>::ReturnType>::invoke( m_lambda, flag ); 4619 } 4620 }; 4621 4622 enum class Optionality { Optional, Required }; 4623 4624 class ParserBase { 4625 public: 4626 virtual ~ParserBase() = default; 4627 virtual auto validate() const -> Result { return Result::ok(); } 4628 virtual auto parse( std::string const& exeName, 4629 TokenStream tokens ) const 4630 -> InternalParseResult = 0; 4631 virtual size_t cardinality() const; 4632 4633 InternalParseResult parse( Args const& args ) const; 4634 }; 4635 4636 template <typename DerivedT> 4637 class ComposableParserImpl : public ParserBase { 4638 public: 4639 template <typename T> 4640 auto operator|( T const& other ) const -> Parser; 4641 }; 4642 4643 // Common code and state for Args and Opts 4644 template <typename DerivedT> 4645 class ParserRefImpl : public ComposableParserImpl<DerivedT> { 4646 protected: 4647 Optionality m_optionality = Optionality::Optional; 4648 std::shared_ptr<BoundRef> m_ref; 4649 StringRef m_hint; 4650 StringRef m_description; 4651 4652 explicit ParserRefImpl( std::shared_ptr<BoundRef> const& ref ): 4653 m_ref( ref ) {} 4654 4655 public: 4656 template <typename LambdaT> 4657 ParserRefImpl( accept_many_t, 4658 LambdaT const& ref, 4659 StringRef hint ): 4660 m_ref( std::make_shared<BoundManyLambda<LambdaT>>( ref ) ), 4661 m_hint( hint ) {} 4662 4663 template <typename T, 4664 typename = typename std::enable_if_t< 4665 !Detail::is_unary_function<T>::value>> 4666 ParserRefImpl( T& ref, StringRef hint ): 4667 m_ref( std::make_shared<BoundValueRef<T>>( ref ) ), 4668 m_hint( hint ) {} 4669 4670 template <typename LambdaT, 4671 typename = typename std::enable_if_t< 4672 Detail::is_unary_function<LambdaT>::value>> 4673 ParserRefImpl( LambdaT const& ref, StringRef hint ): 4674 m_ref( std::make_shared<BoundLambda<LambdaT>>( ref ) ), 4675 m_hint( hint ) {} 4676 4677 DerivedT& operator()( StringRef description ) & { 4678 m_description = description; 4679 return static_cast<DerivedT&>( *this ); 4680 } 4681 DerivedT&& operator()( StringRef description ) && { 4682 m_description = description; 4683 return static_cast<DerivedT&&>( *this ); 4684 } 4685 4686 auto optional() -> DerivedT& { 4687 m_optionality = Optionality::Optional; 4688 return static_cast<DerivedT&>( *this ); 4689 } 4690 4691 auto required() -> DerivedT& { 4692 m_optionality = Optionality::Required; 4693 return static_cast<DerivedT&>( *this ); 4694 } 4695 4696 auto isOptional() const -> bool { 4697 return m_optionality == Optionality::Optional; 4698 } 4699 4700 auto cardinality() const -> size_t override { 4701 if ( m_ref->isContainer() ) 4702 return 0; 4703 else 4704 return 1; 4705 } 4706 4707 StringRef hint() const { return m_hint; } 4708 }; 4709 4710 } // namespace detail 4711 4712 4713 // A parser for arguments 4714 class Arg : public Detail::ParserRefImpl<Arg> { 4715 public: 4716 using ParserRefImpl::ParserRefImpl; 4717 using ParserBase::parse; 4718 4719 Detail::InternalParseResult 4720 parse(std::string const&, 4721 Detail::TokenStream tokens) const override; 4722 }; 4723 4724 // A parser for options 4725 class Opt : public Detail::ParserRefImpl<Opt> { 4726 protected: 4727 std::vector<StringRef> m_optNames; 4728 4729 public: 4730 template <typename LambdaT> 4731 explicit Opt(LambdaT const& ref) : 4732 ParserRefImpl( 4733 std::make_shared<Detail::BoundFlagLambda<LambdaT>>(ref)) {} 4734 4735 explicit Opt(bool& ref); 4736 4737 template <typename LambdaT, 4738 typename = typename std::enable_if_t< 4739 Detail::is_unary_function<LambdaT>::value>> 4740 Opt( LambdaT const& ref, StringRef hint ): 4741 ParserRefImpl( ref, hint ) {} 4742 4743 template <typename LambdaT> 4744 Opt( accept_many_t, LambdaT const& ref, StringRef hint ): 4745 ParserRefImpl( accept_many, ref, hint ) {} 4746 4747 template <typename T, 4748 typename = typename std::enable_if_t< 4749 !Detail::is_unary_function<T>::value>> 4750 Opt( T& ref, StringRef hint ): 4751 ParserRefImpl( ref, hint ) {} 4752 4753 Opt& operator[]( StringRef optName ) & { 4754 m_optNames.push_back(optName); 4755 return *this; 4756 } 4757 Opt&& operator[]( StringRef optName ) && { 4758 m_optNames.push_back( optName ); 4759 return CATCH_MOVE(*this); 4760 } 4761 4762 Detail::HelpColumns getHelpColumns() const; 4763 4764 bool isMatch(StringRef optToken) const; 4765 4766 using ParserBase::parse; 4767 4768 Detail::InternalParseResult 4769 parse(std::string const&, 4770 Detail::TokenStream tokens) const override; 4771 4772 Detail::Result validate() const override; 4773 }; 4774 4775 // Specifies the name of the executable 4776 class ExeName : public Detail::ComposableParserImpl<ExeName> { 4777 std::shared_ptr<std::string> m_name; 4778 std::shared_ptr<Detail::BoundValueRefBase> m_ref; 4779 4780 public: 4781 ExeName(); 4782 explicit ExeName(std::string& ref); 4783 4784 template <typename LambdaT> 4785 explicit ExeName(LambdaT const& lambda) : ExeName() { 4786 m_ref = std::make_shared<Detail::BoundLambda<LambdaT>>(lambda); 4787 } 4788 4789 // The exe name is not parsed out of the normal tokens, but is 4790 // handled specially 4791 Detail::InternalParseResult 4792 parse(std::string const&, 4793 Detail::TokenStream tokens) const override; 4794 4795 std::string const& name() const { return *m_name; } 4796 Detail::ParserResult set(std::string const& newName); 4797 }; 4798 4799 4800 // A Combined parser 4801 class Parser : Detail::ParserBase { 4802 mutable ExeName m_exeName; 4803 std::vector<Opt> m_options; 4804 std::vector<Arg> m_args; 4805 4806 public: 4807 4808 auto operator|=(ExeName const& exeName) -> Parser& { 4809 m_exeName = exeName; 4810 return *this; 4811 } 4812 4813 auto operator|=(Arg const& arg) -> Parser& { 4814 m_args.push_back(arg); 4815 return *this; 4816 } 4817 4818 friend Parser& operator|=( Parser& p, Opt const& opt ) { 4819 p.m_options.push_back( opt ); 4820 return p; 4821 } 4822 friend Parser& operator|=( Parser& p, Opt&& opt ) { 4823 p.m_options.push_back( CATCH_MOVE(opt) ); 4824 return p; 4825 } 4826 4827 Parser& operator|=(Parser const& other); 4828 4829 template <typename T> 4830 friend Parser operator|( Parser const& p, T&& rhs ) { 4831 Parser temp( p ); 4832 temp |= rhs; 4833 return temp; 4834 } 4835 4836 template <typename T> 4837 friend Parser operator|( Parser&& p, T&& rhs ) { 4838 p |= CATCH_FORWARD(rhs); 4839 return CATCH_MOVE(p); 4840 } 4841 4842 std::vector<Detail::HelpColumns> getHelpColumns() const; 4843 4844 void writeToStream(std::ostream& os) const; 4845 4846 friend auto operator<<(std::ostream& os, Parser const& parser) 4847 -> std::ostream& { 4848 parser.writeToStream(os); 4849 return os; 4850 } 4851 4852 Detail::Result validate() const override; 4853 4854 using ParserBase::parse; 4855 Detail::InternalParseResult 4856 parse(std::string const& exeName, 4857 Detail::TokenStream tokens) const override; 4858 }; 4859 4860 /** 4861 * Wrapper over argc + argv, assumes that the inputs outlive it 4862 */ 4863 class Args { 4864 friend Detail::TokenStream; 4865 StringRef m_exeName; 4866 std::vector<StringRef> m_args; 4867 4868 public: 4869 Args(int argc, char const* const* argv); 4870 // Helper constructor for testing 4871 Args(std::initializer_list<StringRef> args); 4872 4873 StringRef exeName() const { return m_exeName; } 4874 }; 4875 4876 4877 // Convenience wrapper for option parser that specifies the help option 4878 struct Help : Opt { 4879 Help(bool& showHelpFlag); 4880 }; 4881 4882 // Result type for parser operation 4883 using Detail::ParserResult; 4884 4885 namespace Detail { 4886 template <typename DerivedT> 4887 template <typename T> 4888 Parser 4889 ComposableParserImpl<DerivedT>::operator|(T const& other) const { 4890 return Parser() | static_cast<DerivedT const&>(*this) | other; 4891 } 4892 } 4893 4894 } // namespace Clara 4895} // namespace Catch 4896 4897#if defined( __clang__ ) 4898# pragma clang diagnostic pop 4899#endif 4900 4901#if defined( __GNUC__ ) 4902# pragma GCC diagnostic pop 4903#endif 4904 4905#endif // CATCH_CLARA_HPP_INCLUDED 4906 4907namespace Catch { 4908 4909 struct ConfigData; 4910 4911 Clara::Parser makeCommandLineParser( ConfigData& config ); 4912 4913} // end namespace Catch 4914 4915#endif // CATCH_COMMANDLINE_HPP_INCLUDED 4916 4917namespace Catch { 4918 4919 class Session : Detail::NonCopyable { 4920 public: 4921 4922 Session(); 4923 ~Session(); 4924 4925 void showHelp() const; 4926 void libIdentify(); 4927 4928 int applyCommandLine( int argc, char const * const * argv ); 4929 #if defined(CATCH_CONFIG_WCHAR) && defined(_WIN32) && defined(UNICODE) 4930 int applyCommandLine( int argc, wchar_t const * const * argv ); 4931 #endif 4932 4933 void useConfigData( ConfigData const& configData ); 4934 4935 template<typename CharT> 4936 int run(int argc, CharT const * const argv[]) { 4937 if (m_startupExceptions) 4938 return 1; 4939 int returnCode = applyCommandLine(argc, argv); 4940 if (returnCode == 0) 4941 returnCode = run(); 4942 return returnCode; 4943 } 4944 4945 int run(); 4946 4947 Clara::Parser const& cli() const; 4948 void cli( Clara::Parser const& newParser ); 4949 ConfigData& configData(); 4950 Config& config(); 4951 private: 4952 int runInternal(); 4953 4954 Clara::Parser m_cli; 4955 ConfigData m_configData; 4956 Detail::unique_ptr<Config> m_config; 4957 bool m_startupExceptions = false; 4958 }; 4959 4960} // end namespace Catch 4961 4962#endif // CATCH_SESSION_HPP_INCLUDED 4963 4964 4965#ifndef CATCH_TAG_ALIAS_HPP_INCLUDED 4966#define CATCH_TAG_ALIAS_HPP_INCLUDED 4967 4968 4969#include <string> 4970 4971namespace Catch { 4972 4973 struct TagAlias { 4974 TagAlias(std::string const& _tag, SourceLineInfo _lineInfo): 4975 tag(_tag), 4976 lineInfo(_lineInfo) 4977 {} 4978 4979 std::string tag; 4980 SourceLineInfo lineInfo; 4981 }; 4982 4983} // end namespace Catch 4984 4985#endif // CATCH_TAG_ALIAS_HPP_INCLUDED 4986 4987 4988#ifndef CATCH_TAG_ALIAS_AUTOREGISTRAR_HPP_INCLUDED 4989#define CATCH_TAG_ALIAS_AUTOREGISTRAR_HPP_INCLUDED 4990 4991 4992namespace Catch { 4993 4994 struct RegistrarForTagAliases { 4995 RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); 4996 }; 4997 4998} // end namespace Catch 4999 5000#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \ 5001 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 5002 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 5003 namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \ 5004 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 5005 5006#endif // CATCH_TAG_ALIAS_AUTOREGISTRAR_HPP_INCLUDED 5007 5008 5009#ifndef CATCH_TEMPLATE_TEST_MACROS_HPP_INCLUDED 5010#define CATCH_TEMPLATE_TEST_MACROS_HPP_INCLUDED 5011 5012// We need this suppression to leak, because it took until GCC 10 5013// for the front end to handle local suppression via _Pragma properly 5014// inside templates (so `TEMPLATE_TEST_CASE` and co). 5015// **THIS IS DIFFERENT FOR STANDARD TESTS, WHERE GCC 9 IS SUFFICIENT** 5016#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && __GNUC__ < 10 5017#pragma GCC diagnostic ignored "-Wparentheses" 5018#endif 5019 5020 5021 5022 5023#ifndef CATCH_TEST_MACROS_HPP_INCLUDED 5024#define CATCH_TEST_MACROS_HPP_INCLUDED 5025 5026 5027 5028#ifndef CATCH_TEST_MACRO_IMPL_HPP_INCLUDED 5029#define CATCH_TEST_MACRO_IMPL_HPP_INCLUDED 5030 5031 5032 5033#ifndef CATCH_ASSERTION_HANDLER_HPP_INCLUDED 5034#define CATCH_ASSERTION_HANDLER_HPP_INCLUDED 5035 5036 5037 5038#ifndef CATCH_DECOMPOSER_HPP_INCLUDED 5039#define CATCH_DECOMPOSER_HPP_INCLUDED 5040 5041 5042 5043#ifndef CATCH_COMPARE_TRAITS_HPP_INCLUDED 5044#define CATCH_COMPARE_TRAITS_HPP_INCLUDED 5045 5046 5047#include <type_traits> 5048 5049namespace Catch { 5050 namespace Detail { 5051 5052#if defined( __GNUC__ ) && !defined( __clang__ ) 5053# pragma GCC diagnostic push 5054 // GCC likes to complain about comparing bool with 0, in the decltype() 5055 // that defines the comparable traits below. 5056# pragma GCC diagnostic ignored "-Wbool-compare" 5057 // "ordered comparison of pointer with integer zero" same as above, 5058 // but it does not have a separate warning flag to suppress 5059# pragma GCC diagnostic ignored "-Wextra" 5060 // Did you know that comparing floats with `0` directly 5061 // is super-duper dangerous in unevaluated context? 5062# pragma GCC diagnostic ignored "-Wfloat-equal" 5063#endif 5064 5065#if defined( __clang__ ) 5066# pragma clang diagnostic push 5067 // Did you know that comparing floats with `0` directly 5068 // is super-duper dangerous in unevaluated context? 5069# pragma clang diagnostic ignored "-Wfloat-equal" 5070#endif 5071 5072#define CATCH_DEFINE_COMPARABLE_TRAIT( id, op ) \ 5073 template <typename, typename, typename = void> \ 5074 struct is_##id##_comparable : std::false_type {}; \ 5075 template <typename T, typename U> \ 5076 struct is_##id##_comparable< \ 5077 T, \ 5078 U, \ 5079 void_t<decltype( std::declval<T>() op std::declval<U>() )>> \ 5080 : std::true_type {}; \ 5081 template <typename, typename = void> \ 5082 struct is_##id##_0_comparable : std::false_type {}; \ 5083 template <typename T> \ 5084 struct is_##id##_0_comparable<T, \ 5085 void_t<decltype( std::declval<T>() op 0 )>> \ 5086 : std::true_type {}; 5087 5088 // We need all 6 pre-spaceship comparison ops: <, <=, >, >=, ==, != 5089 CATCH_DEFINE_COMPARABLE_TRAIT( lt, < ) 5090 CATCH_DEFINE_COMPARABLE_TRAIT( le, <= ) 5091 CATCH_DEFINE_COMPARABLE_TRAIT( gt, > ) 5092 CATCH_DEFINE_COMPARABLE_TRAIT( ge, >= ) 5093 CATCH_DEFINE_COMPARABLE_TRAIT( eq, == ) 5094 CATCH_DEFINE_COMPARABLE_TRAIT( ne, != ) 5095 5096#undef CATCH_DEFINE_COMPARABLE_TRAIT 5097 5098#if defined( __GNUC__ ) && !defined( __clang__ ) 5099# pragma GCC diagnostic pop 5100#endif 5101#if defined( __clang__ ) 5102# pragma clang diagnostic pop 5103#endif 5104 5105 5106 } // namespace Detail 5107} // namespace Catch 5108 5109#endif // CATCH_COMPARE_TRAITS_HPP_INCLUDED 5110 5111 5112#ifndef CATCH_LOGICAL_TRAITS_HPP_INCLUDED 5113#define CATCH_LOGICAL_TRAITS_HPP_INCLUDED 5114 5115#include <type_traits> 5116 5117namespace Catch { 5118namespace Detail { 5119 5120#if defined( __cpp_lib_logical_traits ) && __cpp_lib_logical_traits >= 201510 5121 5122 using std::conjunction; 5123 using std::disjunction; 5124 using std::negation; 5125 5126#else 5127 5128 template <class...> struct conjunction : std::true_type {}; 5129 template <class B1> struct conjunction<B1> : B1 {}; 5130 template <class B1, class... Bn> 5131 struct conjunction<B1, Bn...> 5132 : std::conditional_t<bool( B1::value ), conjunction<Bn...>, B1> {}; 5133 5134 template <class...> struct disjunction : std::false_type {}; 5135 template <class B1> struct disjunction<B1> : B1 {}; 5136 template <class B1, class... Bn> 5137 struct disjunction<B1, Bn...> 5138 : std::conditional_t<bool( B1::value ), B1, disjunction<Bn...>> {}; 5139 5140 template <class B> 5141 struct negation : std::integral_constant<bool, !bool(B::value)> {}; 5142 5143#endif 5144 5145} // namespace Detail 5146} // namespace Catch 5147 5148#endif // CATCH_LOGICAL_TRAITS_HPP_INCLUDED 5149 5150#include <type_traits> 5151#include <iosfwd> 5152 5153/** \file 5154 * Why does decomposing look the way it does: 5155 * 5156 * Conceptually, decomposing is simple. We change `REQUIRE( a == b )` into 5157 * `Decomposer{} <= a == b`, so that `Decomposer{} <= a` is evaluated first, 5158 * and our custom operator is used for `a == b`, because `a` is transformed 5159 * into `ExprLhs<T&>` and then into `BinaryExpr<T&, U&>`. 5160 * 5161 * In practice, decomposing ends up a mess, because we have to support 5162 * various fun things. 5163 * 5164 * 1) Types that are only comparable with literal 0, and they do this by 5165 * comparing against a magic type with pointer constructor and deleted 5166 * other constructors. Example: `REQUIRE((a <=> b) == 0)` in libstdc++ 5167 * 5168 * 2) Types that are only comparable with literal 0, and they do this by 5169 * comparing against a magic type with consteval integer constructor. 5170 * Example: `REQUIRE((a <=> b) == 0)` in current MSVC STL. 5171 * 5172 * 3) Types that have no linkage, and so we cannot form a reference to 5173 * them. Example: some implementations of traits. 5174 * 5175 * 4) Starting with C++20, when the compiler sees `a == b`, it also uses 5176 * `b == a` when constructing the overload set. For us this means that 5177 * when the compiler handles `ExprLhs<T> == b`, it also tries to resolve 5178 * the overload set for `b == ExprLhs<T>`. 5179 * 5180 * To accomodate these use cases, decomposer ended up rather complex. 5181 * 5182 * 1) These types are handled by adding SFINAE overloads to our comparison 5183 * operators, checking whether `T == U` are comparable with the given 5184 * operator, and if not, whether T (or U) are comparable with literal 0. 5185 * If yes, the overload compares T (or U) with 0 literal inline in the 5186 * definition. 5187 * 5188 * Note that for extra correctness, we check that the other type is 5189 * either an `int` (literal 0 is captured as `int` by templates), or 5190 * a `long` (some platforms use 0L for `NULL` and we want to support 5191 * that for pointer comparisons). 5192 * 5193 * 2) For these types, `is_foo_comparable<T, int>` is true, but letting 5194 * them fall into the overload that actually does `T == int` causes 5195 * compilation error. Handling them requires that the decomposition 5196 * is `constexpr`, so that P2564R3 applies and the `consteval` from 5197 * their accompanying magic type is propagated through the `constexpr` 5198 * call stack. 5199 * 5200 * However this is not enough to handle these types automatically, 5201 * because our default is to capture types by reference, to avoid 5202 * runtime copies. While these references cannot become dangling, 5203 * they outlive the constexpr context and thus the default capture 5204 * path cannot be actually constexpr. 5205 * 5206 * The solution is to capture these types by value, by explicitly 5207 * specializing `Catch::capture_by_value` for them. Catch2 provides 5208 * specialization for `std::foo_ordering`s, but users can specialize 5209 * the trait for their own types as well. 5210 * 5211 * 3) If a type has no linkage, we also cannot capture it by reference. 5212 * The solution is once again to capture them by value. We handle 5213 * the common cases by using `std::is_arithmetic` as the default 5214 * for `Catch::capture_by_value`, but that is only a some-effort 5215 * heuristic. But as with 2), users can specialize `capture_by_value` 5216 * for their own types as needed. 5217 * 5218 * 4) To support C++20 and make the SFINAE on our decomposing operators 5219 * work, the SFINAE has to happen in return type, rather than in 5220 * a template type. This is due to our use of logical type traits 5221 * (`conjunction`/`disjunction`/`negation`), that we use to workaround 5222 * an issue in older (9-) versions of GCC. I still blame C++20 for 5223 * this, because without the comparison order switching, the logical 5224 * traits could still be used in template type. 5225 * 5226 * There are also other side concerns, e.g. supporting both `REQUIRE(a)` 5227 * and `REQUIRE(a == b)`, or making `REQUIRE_THAT(a, IsEqual(b))` slot 5228 * nicely into the same expression handling logic, but these are rather 5229 * straightforward and add only a bit of complexity (e.g. common base 5230 * class for decomposed expressions). 5231 */ 5232 5233#ifdef _MSC_VER 5234#pragma warning(push) 5235#pragma warning(disable:4389) // '==' : signed/unsigned mismatch 5236#pragma warning(disable:4018) // more "signed/unsigned mismatch" 5237#pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform) 5238#pragma warning(disable:4180) // qualifier applied to function type has no meaning 5239#pragma warning(disable:4800) // Forcing result to true or false 5240#endif 5241 5242#ifdef __clang__ 5243# pragma clang diagnostic push 5244# pragma clang diagnostic ignored "-Wsign-compare" 5245# pragma clang diagnostic ignored "-Wnon-virtual-dtor" 5246#elif defined __GNUC__ 5247# pragma GCC diagnostic push 5248# pragma GCC diagnostic ignored "-Wsign-compare" 5249# pragma GCC diagnostic ignored "-Wnon-virtual-dtor" 5250#endif 5251 5252#if defined(CATCH_CPP20_OR_GREATER) && __has_include(<compare>) 5253# include <compare> 5254# if defined( __cpp_lib_three_way_comparison ) && \ 5255 __cpp_lib_three_way_comparison >= 201907L 5256# define CATCH_CONFIG_CPP20_COMPARE_OVERLOADS 5257# endif 5258#endif 5259 5260namespace Catch { 5261 5262 namespace Detail { 5263 // This was added in C++20, but we require only C++14 for now. 5264 template <typename T> 5265 using RemoveCVRef_t = std::remove_cv_t<std::remove_reference_t<T>>; 5266 } 5267 5268 // Note: There is nothing that stops us from extending this, 5269 // e.g. to `std::is_scalar`, but the more encompassing 5270 // traits are usually also more expensive. For now we 5271 // keep this as it used to be and it can be changed later. 5272 template <typename T> 5273 struct capture_by_value 5274 : std::integral_constant<bool, std::is_arithmetic<T>{}> {}; 5275 5276#if defined( CATCH_CONFIG_CPP20_COMPARE_OVERLOADS ) 5277 template <> 5278 struct capture_by_value<std::strong_ordering> : std::true_type {}; 5279 template <> 5280 struct capture_by_value<std::weak_ordering> : std::true_type {}; 5281 template <> 5282 struct capture_by_value<std::partial_ordering> : std::true_type {}; 5283#endif 5284 5285 template <typename T> 5286 struct always_false : std::false_type {}; 5287 5288 class ITransientExpression { 5289 bool m_isBinaryExpression; 5290 bool m_result; 5291 5292 public: 5293 constexpr auto isBinaryExpression() const -> bool { return m_isBinaryExpression; } 5294 constexpr auto getResult() const -> bool { return m_result; } 5295 //! This function **has** to be overriden by the derived class. 5296 virtual void streamReconstructedExpression( std::ostream& os ) const; 5297 5298 constexpr ITransientExpression( bool isBinaryExpression, bool result ) 5299 : m_isBinaryExpression( isBinaryExpression ), 5300 m_result( result ) 5301 {} 5302 5303 ITransientExpression() = default; 5304 ITransientExpression(ITransientExpression const&) = default; 5305 ITransientExpression& operator=(ITransientExpression const&) = default; 5306 5307 friend std::ostream& operator<<(std::ostream& out, ITransientExpression const& expr) { 5308 expr.streamReconstructedExpression(out); 5309 return out; 5310 } 5311 5312 protected: 5313 ~ITransientExpression() = default; 5314 }; 5315 5316 void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ); 5317 5318 template<typename LhsT, typename RhsT> 5319 class BinaryExpr : public ITransientExpression { 5320 LhsT m_lhs; 5321 StringRef m_op; 5322 RhsT m_rhs; 5323 5324 void streamReconstructedExpression( std::ostream &os ) const override { 5325 formatReconstructedExpression 5326 ( os, Catch::Detail::stringify( m_lhs ), m_op, Catch::Detail::stringify( m_rhs ) ); 5327 } 5328 5329 public: 5330 constexpr BinaryExpr( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs ) 5331 : ITransientExpression{ true, comparisonResult }, 5332 m_lhs( lhs ), 5333 m_op( op ), 5334 m_rhs( rhs ) 5335 {} 5336 5337 template<typename T> 5338 auto operator && ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 5339 static_assert(always_false<T>::value, 5340 "chained comparisons are not supported inside assertions, " 5341 "wrap the expression inside parentheses, or decompose it"); 5342 } 5343 5344 template<typename T> 5345 auto operator || ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 5346 static_assert(always_false<T>::value, 5347 "chained comparisons are not supported inside assertions, " 5348 "wrap the expression inside parentheses, or decompose it"); 5349 } 5350 5351 template<typename T> 5352 auto operator == ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 5353 static_assert(always_false<T>::value, 5354 "chained comparisons are not supported inside assertions, " 5355 "wrap the expression inside parentheses, or decompose it"); 5356 } 5357 5358 template<typename T> 5359 auto operator != ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 5360 static_assert(always_false<T>::value, 5361 "chained comparisons are not supported inside assertions, " 5362 "wrap the expression inside parentheses, or decompose it"); 5363 } 5364 5365 template<typename T> 5366 auto operator > ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 5367 static_assert(always_false<T>::value, 5368 "chained comparisons are not supported inside assertions, " 5369 "wrap the expression inside parentheses, or decompose it"); 5370 } 5371 5372 template<typename T> 5373 auto operator < ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 5374 static_assert(always_false<T>::value, 5375 "chained comparisons are not supported inside assertions, " 5376 "wrap the expression inside parentheses, or decompose it"); 5377 } 5378 5379 template<typename T> 5380 auto operator >= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 5381 static_assert(always_false<T>::value, 5382 "chained comparisons are not supported inside assertions, " 5383 "wrap the expression inside parentheses, or decompose it"); 5384 } 5385 5386 template<typename T> 5387 auto operator <= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const { 5388 static_assert(always_false<T>::value, 5389 "chained comparisons are not supported inside assertions, " 5390 "wrap the expression inside parentheses, or decompose it"); 5391 } 5392 }; 5393 5394 template<typename LhsT> 5395 class UnaryExpr : public ITransientExpression { 5396 LhsT m_lhs; 5397 5398 void streamReconstructedExpression( std::ostream &os ) const override { 5399 os << Catch::Detail::stringify( m_lhs ); 5400 } 5401 5402 public: 5403 explicit constexpr UnaryExpr( LhsT lhs ) 5404 : ITransientExpression{ false, static_cast<bool>(lhs) }, 5405 m_lhs( lhs ) 5406 {} 5407 }; 5408 5409 5410 template<typename LhsT> 5411 class ExprLhs { 5412 LhsT m_lhs; 5413 public: 5414 explicit constexpr ExprLhs( LhsT lhs ) : m_lhs( lhs ) {} 5415 5416#define CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR( id, op ) \ 5417 template <typename RhsT> \ 5418 constexpr friend auto operator op( ExprLhs&& lhs, RhsT&& rhs ) \ 5419 -> std::enable_if_t< \ 5420 Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>, \ 5421 Detail::negation<capture_by_value< \ 5422 Detail::RemoveCVRef_t<RhsT>>>>::value, \ 5423 BinaryExpr<LhsT, RhsT const&>> { \ 5424 return { \ 5425 static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \ 5426 } \ 5427 template <typename RhsT> \ 5428 constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \ 5429 -> std::enable_if_t< \ 5430 Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>, \ 5431 capture_by_value<RhsT>>::value, \ 5432 BinaryExpr<LhsT, RhsT>> { \ 5433 return { \ 5434 static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \ 5435 } \ 5436 template <typename RhsT> \ 5437 constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \ 5438 -> std::enable_if_t< \ 5439 Detail::conjunction< \ 5440 Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>, \ 5441 Detail::is_eq_0_comparable<LhsT>, \ 5442 /* We allow long because we want `ptr op NULL` to be accepted */ \ 5443 Detail::disjunction<std::is_same<RhsT, int>, \ 5444 std::is_same<RhsT, long>>>::value, \ 5445 BinaryExpr<LhsT, RhsT>> { \ 5446 if ( rhs != 0 ) { throw_test_failure_exception(); } \ 5447 return { \ 5448 static_cast<bool>( lhs.m_lhs op 0 ), lhs.m_lhs, #op##_sr, rhs }; \ 5449 } \ 5450 template <typename RhsT> \ 5451 constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \ 5452 -> std::enable_if_t< \ 5453 Detail::conjunction< \ 5454 Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>, \ 5455 Detail::is_eq_0_comparable<RhsT>, \ 5456 /* We allow long because we want `ptr op NULL` to be accepted */ \ 5457 Detail::disjunction<std::is_same<LhsT, int>, \ 5458 std::is_same<LhsT, long>>>::value, \ 5459 BinaryExpr<LhsT, RhsT>> { \ 5460 if ( lhs.m_lhs != 0 ) { throw_test_failure_exception(); } \ 5461 return { static_cast<bool>( 0 op rhs ), lhs.m_lhs, #op##_sr, rhs }; \ 5462 } 5463 5464 CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR( eq, == ) 5465 CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR( ne, != ) 5466 5467 #undef CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR 5468 5469 5470#define CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( id, op ) \ 5471 template <typename RhsT> \ 5472 constexpr friend auto operator op( ExprLhs&& lhs, RhsT&& rhs ) \ 5473 -> std::enable_if_t< \ 5474 Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>, \ 5475 Detail::negation<capture_by_value< \ 5476 Detail::RemoveCVRef_t<RhsT>>>>::value, \ 5477 BinaryExpr<LhsT, RhsT const&>> { \ 5478 return { \ 5479 static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \ 5480 } \ 5481 template <typename RhsT> \ 5482 constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \ 5483 -> std::enable_if_t< \ 5484 Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>, \ 5485 capture_by_value<RhsT>>::value, \ 5486 BinaryExpr<LhsT, RhsT>> { \ 5487 return { \ 5488 static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \ 5489 } \ 5490 template <typename RhsT> \ 5491 constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \ 5492 -> std::enable_if_t< \ 5493 Detail::conjunction< \ 5494 Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>, \ 5495 Detail::is_##id##_0_comparable<LhsT>, \ 5496 std::is_same<RhsT, int>>::value, \ 5497 BinaryExpr<LhsT, RhsT>> { \ 5498 if ( rhs != 0 ) { throw_test_failure_exception(); } \ 5499 return { \ 5500 static_cast<bool>( lhs.m_lhs op 0 ), lhs.m_lhs, #op##_sr, rhs }; \ 5501 } \ 5502 template <typename RhsT> \ 5503 constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \ 5504 -> std::enable_if_t< \ 5505 Detail::conjunction< \ 5506 Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>, \ 5507 Detail::is_##id##_0_comparable<RhsT>, \ 5508 std::is_same<LhsT, int>>::value, \ 5509 BinaryExpr<LhsT, RhsT>> { \ 5510 if ( lhs.m_lhs != 0 ) { throw_test_failure_exception(); } \ 5511 return { static_cast<bool>( 0 op rhs ), lhs.m_lhs, #op##_sr, rhs }; \ 5512 } 5513 5514 CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( lt, < ) 5515 CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( le, <= ) 5516 CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( gt, > ) 5517 CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( ge, >= ) 5518 5519 #undef CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR 5520 5521 5522#define CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR( op ) \ 5523 template <typename RhsT> \ 5524 constexpr friend auto operator op( ExprLhs&& lhs, RhsT&& rhs ) \ 5525 -> std::enable_if_t< \ 5526 !capture_by_value<Detail::RemoveCVRef_t<RhsT>>::value, \ 5527 BinaryExpr<LhsT, RhsT const&>> { \ 5528 return { \ 5529 static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \ 5530 } \ 5531 template <typename RhsT> \ 5532 constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \ 5533 -> std::enable_if_t<capture_by_value<RhsT>::value, \ 5534 BinaryExpr<LhsT, RhsT>> { \ 5535 return { \ 5536 static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \ 5537 } 5538 5539 CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR(|) 5540 CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR(&) 5541 CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR(^) 5542 5543 #undef CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR 5544 5545 template<typename RhsT> 5546 friend auto operator && ( ExprLhs &&, RhsT && ) -> BinaryExpr<LhsT, RhsT const&> { 5547 static_assert(always_false<RhsT>::value, 5548 "operator&& is not supported inside assertions, " 5549 "wrap the expression inside parentheses, or decompose it"); 5550 } 5551 5552 template<typename RhsT> 5553 friend auto operator || ( ExprLhs &&, RhsT && ) -> BinaryExpr<LhsT, RhsT const&> { 5554 static_assert(always_false<RhsT>::value, 5555 "operator|| is not supported inside assertions, " 5556 "wrap the expression inside parentheses, or decompose it"); 5557 } 5558 5559 constexpr auto makeUnaryExpr() const -> UnaryExpr<LhsT> { 5560 return UnaryExpr<LhsT>{ m_lhs }; 5561 } 5562 }; 5563 5564 struct Decomposer { 5565 template <typename T, 5566 std::enable_if_t<!capture_by_value<Detail::RemoveCVRef_t<T>>::value, 5567 int> = 0> 5568 constexpr friend auto operator <= ( Decomposer &&, T && lhs ) -> ExprLhs<T const&> { 5569 return ExprLhs<const T&>{ lhs }; 5570 } 5571 5572 template <typename T, 5573 std::enable_if_t<capture_by_value<T>::value, int> = 0> 5574 constexpr friend auto operator <= ( Decomposer &&, T value ) -> ExprLhs<T> { 5575 return ExprLhs<T>{ value }; 5576 } 5577 }; 5578 5579} // end namespace Catch 5580 5581#ifdef _MSC_VER 5582#pragma warning(pop) 5583#endif 5584#ifdef __clang__ 5585# pragma clang diagnostic pop 5586#elif defined __GNUC__ 5587# pragma GCC diagnostic pop 5588#endif 5589 5590#endif // CATCH_DECOMPOSER_HPP_INCLUDED 5591 5592#include <string> 5593 5594namespace Catch { 5595 5596 struct AssertionReaction { 5597 bool shouldDebugBreak = false; 5598 bool shouldThrow = false; 5599 bool shouldSkip = false; 5600 }; 5601 5602 class AssertionHandler { 5603 AssertionInfo m_assertionInfo; 5604 AssertionReaction m_reaction; 5605 bool m_completed = false; 5606 IResultCapture& m_resultCapture; 5607 5608 public: 5609 AssertionHandler 5610 ( StringRef macroName, 5611 SourceLineInfo const& lineInfo, 5612 StringRef capturedExpression, 5613 ResultDisposition::Flags resultDisposition ); 5614 ~AssertionHandler() { 5615 if ( !m_completed ) { 5616 m_resultCapture.handleIncomplete( m_assertionInfo ); 5617 } 5618 } 5619 5620 5621 template<typename T> 5622 void handleExpr( ExprLhs<T> const& expr ) { 5623 handleExpr( expr.makeUnaryExpr() ); 5624 } 5625 void handleExpr( ITransientExpression const& expr ); 5626 5627 void handleMessage(ResultWas::OfType resultType, StringRef message); 5628 5629 void handleExceptionThrownAsExpected(); 5630 void handleUnexpectedExceptionNotThrown(); 5631 void handleExceptionNotThrownAsExpected(); 5632 void handleThrowingCallSkipped(); 5633 void handleUnexpectedInflightException(); 5634 5635 void complete(); 5636 5637 // query 5638 auto allowThrows() const -> bool; 5639 }; 5640 5641 void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str ); 5642 5643} // namespace Catch 5644 5645#endif // CATCH_ASSERTION_HANDLER_HPP_INCLUDED 5646 5647 5648#ifndef CATCH_PREPROCESSOR_INTERNAL_STRINGIFY_HPP_INCLUDED 5649#define CATCH_PREPROCESSOR_INTERNAL_STRINGIFY_HPP_INCLUDED 5650 5651 5652#if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION) 5653 #define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__##_catch_sr 5654#else 5655 #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"_catch_sr 5656#endif 5657 5658#endif // CATCH_PREPROCESSOR_INTERNAL_STRINGIFY_HPP_INCLUDED 5659 5660// We need this suppression to leak, because it took until GCC 10 5661// for the front end to handle local suppression via _Pragma properly 5662#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && __GNUC__ <= 9 5663 #pragma GCC diagnostic ignored "-Wparentheses" 5664#endif 5665 5666#if !defined(CATCH_CONFIG_DISABLE) 5667 5668#if defined(CATCH_CONFIG_FAST_COMPILE) || defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 5669 5670/////////////////////////////////////////////////////////////////////////////// 5671// Another way to speed-up compilation is to omit local try-catch for REQUIRE* 5672// macros. 5673#define INTERNAL_CATCH_TRY 5674#define INTERNAL_CATCH_CATCH( capturer ) 5675 5676#else // CATCH_CONFIG_FAST_COMPILE 5677 5678#define INTERNAL_CATCH_TRY try 5679#define INTERNAL_CATCH_CATCH( handler ) catch(...) { (handler).handleUnexpectedInflightException(); } 5680 5681#endif 5682 5683#define INTERNAL_CATCH_REACT( handler ) handler.complete(); 5684 5685/////////////////////////////////////////////////////////////////////////////// 5686#define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \ 5687 do { /* NOLINT(bugprone-infinite-loop) */ \ 5688 /* The expression should not be evaluated, but warnings should hopefully be checked */ \ 5689 CATCH_INTERNAL_IGNORE_BUT_WARN(__VA_ARGS__); \ 5690 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ 5691 INTERNAL_CATCH_TRY { \ 5692 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 5693 CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ 5694 catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); /* NOLINT(bugprone-chained-comparison) */ \ 5695 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 5696 } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ 5697 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 5698 } while( (void)0, (false) && static_cast<const bool&>( !!(__VA_ARGS__) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look 5699 // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. 5700 5701/////////////////////////////////////////////////////////////////////////////// 5702#define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \ 5703 INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \ 5704 if( Catch::getResultCapture().lastAssertionPassed() ) 5705 5706/////////////////////////////////////////////////////////////////////////////// 5707#define INTERNAL_CATCH_ELSE( macroName, resultDisposition, ... ) \ 5708 INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \ 5709 if( !Catch::getResultCapture().lastAssertionPassed() ) 5710 5711/////////////////////////////////////////////////////////////////////////////// 5712#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \ 5713 do { \ 5714 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ 5715 try { \ 5716 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 5717 CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \ 5718 static_cast<void>(__VA_ARGS__); \ 5719 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 5720 catchAssertionHandler.handleExceptionNotThrownAsExpected(); \ 5721 } \ 5722 catch( ... ) { \ 5723 catchAssertionHandler.handleUnexpectedInflightException(); \ 5724 } \ 5725 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 5726 } while( false ) 5727 5728/////////////////////////////////////////////////////////////////////////////// 5729#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \ 5730 do { \ 5731 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \ 5732 if( catchAssertionHandler.allowThrows() ) \ 5733 try { \ 5734 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 5735 CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT \ 5736 CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \ 5737 static_cast<void>(__VA_ARGS__); \ 5738 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 5739 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 5740 } \ 5741 catch( ... ) { \ 5742 catchAssertionHandler.handleExceptionThrownAsExpected(); \ 5743 } \ 5744 else \ 5745 catchAssertionHandler.handleThrowingCallSkipped(); \ 5746 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 5747 } while( false ) 5748 5749/////////////////////////////////////////////////////////////////////////////// 5750#define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \ 5751 do { \ 5752 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \ 5753 if( catchAssertionHandler.allowThrows() ) \ 5754 try { \ 5755 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 5756 CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT \ 5757 CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \ 5758 static_cast<void>(expr); \ 5759 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 5760 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 5761 } \ 5762 catch( exceptionType const& ) { \ 5763 catchAssertionHandler.handleExceptionThrownAsExpected(); \ 5764 } \ 5765 catch( ... ) { \ 5766 catchAssertionHandler.handleUnexpectedInflightException(); \ 5767 } \ 5768 else \ 5769 catchAssertionHandler.handleThrowingCallSkipped(); \ 5770 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 5771 } while( false ) 5772 5773 5774 5775/////////////////////////////////////////////////////////////////////////////// 5776// Although this is matcher-based, it can be used with just a string 5777#define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \ 5778 do { \ 5779 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ 5780 if( catchAssertionHandler.allowThrows() ) \ 5781 try { \ 5782 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 5783 CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT \ 5784 CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \ 5785 static_cast<void>(__VA_ARGS__); \ 5786 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 5787 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 5788 } \ 5789 catch( ... ) { \ 5790 Catch::handleExceptionMatchExpr( catchAssertionHandler, matcher ); \ 5791 } \ 5792 else \ 5793 catchAssertionHandler.handleThrowingCallSkipped(); \ 5794 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 5795 } while( false ) 5796 5797#endif // CATCH_CONFIG_DISABLE 5798 5799#endif // CATCH_TEST_MACRO_IMPL_HPP_INCLUDED 5800 5801 5802#ifndef CATCH_SECTION_HPP_INCLUDED 5803#define CATCH_SECTION_HPP_INCLUDED 5804 5805 5806 5807 5808/** \file 5809 * Wrapper for the STATIC_ANALYSIS_SUPPORT configuration option 5810 * 5811 * Some of Catch2's macros can be defined differently to work better with 5812 * static analysis tools, like clang-tidy or coverity. 5813 * Currently the main use case is to show that `SECTION`s are executed 5814 * exclusively, and not all in one run of a `TEST_CASE`. 5815 */ 5816 5817#ifndef CATCH_CONFIG_STATIC_ANALYSIS_SUPPORT_HPP_INCLUDED 5818#define CATCH_CONFIG_STATIC_ANALYSIS_SUPPORT_HPP_INCLUDED 5819 5820 5821#if defined(__clang_analyzer__) || defined(__COVERITY__) 5822 #define CATCH_INTERNAL_CONFIG_STATIC_ANALYSIS_SUPPORT 5823#endif 5824 5825#if defined( CATCH_INTERNAL_CONFIG_STATIC_ANALYSIS_SUPPORT ) && \ 5826 !defined( CATCH_CONFIG_NO_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT ) && \ 5827 !defined( CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT ) 5828# define CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT 5829#endif 5830 5831 5832#endif // CATCH_CONFIG_STATIC_ANALYSIS_SUPPORT_HPP_INCLUDED 5833 5834 5835#ifndef CATCH_TIMER_HPP_INCLUDED 5836#define CATCH_TIMER_HPP_INCLUDED 5837 5838#include <cstdint> 5839 5840namespace Catch { 5841 5842 class Timer { 5843 uint64_t m_nanoseconds = 0; 5844 public: 5845 void start(); 5846 auto getElapsedNanoseconds() const -> uint64_t; 5847 auto getElapsedMicroseconds() const -> uint64_t; 5848 auto getElapsedMilliseconds() const -> unsigned int; 5849 auto getElapsedSeconds() const -> double; 5850 }; 5851 5852} // namespace Catch 5853 5854#endif // CATCH_TIMER_HPP_INCLUDED 5855 5856namespace Catch { 5857 5858 class Section : Detail::NonCopyable { 5859 public: 5860 Section( SectionInfo&& info ); 5861 Section( SourceLineInfo const& _lineInfo, 5862 StringRef _name, 5863 const char* const = nullptr ); 5864 ~Section(); 5865 5866 // This indicates whether the section should be executed or not 5867 explicit operator bool() const; 5868 5869 private: 5870 SectionInfo m_info; 5871 5872 Counts m_assertions; 5873 bool m_sectionIncluded; 5874 Timer m_timer; 5875 }; 5876 5877} // end namespace Catch 5878 5879#if !defined(CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT) 5880# define INTERNAL_CATCH_SECTION( ... ) \ 5881 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 5882 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ 5883 if ( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( \ 5884 catch_internal_Section ) = \ 5885 Catch::Section( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \ 5886 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 5887 5888# define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \ 5889 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 5890 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ 5891 if ( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( \ 5892 catch_internal_Section ) = \ 5893 Catch::SectionInfo( \ 5894 CATCH_INTERNAL_LINEINFO, \ 5895 ( Catch::ReusableStringStream() << __VA_ARGS__ ) \ 5896 .str() ) ) \ 5897 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 5898 5899#else 5900 5901// These section definitions imply that at most one section at one level 5902// will be intered (because only one section's __LINE__ can be equal to 5903// the dummy `catchInternalSectionHint` variable from `TEST_CASE`). 5904 5905namespace Catch { 5906 namespace Detail { 5907 // Intentionally without linkage, as it should only be used as a dummy 5908 // symbol for static analysis. 5909 // The arguments are used as a dummy for checking warnings in the passed 5910 // expressions. 5911 int GetNewSectionHint( StringRef, const char* const = nullptr ); 5912 } // namespace Detail 5913} // namespace Catch 5914 5915 5916# define INTERNAL_CATCH_SECTION( ... ) \ 5917 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 5918 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ 5919 CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \ 5920 if ( [[maybe_unused]] const int catchInternalPreviousSectionHint = \ 5921 catchInternalSectionHint, \ 5922 catchInternalSectionHint = \ 5923 Catch::Detail::GetNewSectionHint(__VA_ARGS__); \ 5924 catchInternalPreviousSectionHint == __LINE__ ) \ 5925 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 5926 5927# define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \ 5928 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 5929 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ 5930 CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \ 5931 if ( [[maybe_unused]] const int catchInternalPreviousSectionHint = \ 5932 catchInternalSectionHint, \ 5933 catchInternalSectionHint = Catch::Detail::GetNewSectionHint( \ 5934 ( Catch::ReusableStringStream() << __VA_ARGS__ ).str()); \ 5935 catchInternalPreviousSectionHint == __LINE__ ) \ 5936 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 5937 5938#endif 5939 5940 5941#endif // CATCH_SECTION_HPP_INCLUDED 5942 5943 5944#ifndef CATCH_TEST_REGISTRY_HPP_INCLUDED 5945#define CATCH_TEST_REGISTRY_HPP_INCLUDED 5946 5947 5948 5949#ifndef CATCH_INTERFACES_TEST_INVOKER_HPP_INCLUDED 5950#define CATCH_INTERFACES_TEST_INVOKER_HPP_INCLUDED 5951 5952namespace Catch { 5953 5954 class ITestInvoker { 5955 public: 5956 virtual void invoke() const = 0; 5957 virtual ~ITestInvoker(); // = default 5958 }; 5959 5960} // namespace Catch 5961 5962#endif // CATCH_INTERFACES_TEST_INVOKER_HPP_INCLUDED 5963 5964 5965#ifndef CATCH_PREPROCESSOR_REMOVE_PARENS_HPP_INCLUDED 5966#define CATCH_PREPROCESSOR_REMOVE_PARENS_HPP_INCLUDED 5967 5968#define INTERNAL_CATCH_EXPAND1( param ) INTERNAL_CATCH_EXPAND2( param ) 5969#define INTERNAL_CATCH_EXPAND2( ... ) INTERNAL_CATCH_NO##__VA_ARGS__ 5970#define INTERNAL_CATCH_DEF( ... ) INTERNAL_CATCH_DEF __VA_ARGS__ 5971#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF 5972 5973#define INTERNAL_CATCH_REMOVE_PARENS( ... ) \ 5974 INTERNAL_CATCH_EXPAND1( INTERNAL_CATCH_DEF __VA_ARGS__ ) 5975 5976#endif // CATCH_PREPROCESSOR_REMOVE_PARENS_HPP_INCLUDED 5977 5978// GCC 5 and older do not properly handle disabling unused-variable warning 5979// with a _Pragma. This means that we have to leak the suppression to the 5980// user code as well :-( 5981#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 5 5982#pragma GCC diagnostic ignored "-Wunused-variable" 5983#endif 5984 5985 5986 5987namespace Catch { 5988 5989template<typename C> 5990class TestInvokerAsMethod : public ITestInvoker { 5991 void (C::*m_testAsMethod)(); 5992public: 5993 TestInvokerAsMethod( void (C::*testAsMethod)() ) noexcept : m_testAsMethod( testAsMethod ) {} 5994 5995 void invoke() const override { 5996 C obj; 5997 (obj.*m_testAsMethod)(); 5998 } 5999}; 6000 6001Detail::unique_ptr<ITestInvoker> makeTestInvoker( void(*testAsFunction)() ); 6002 6003template<typename C> 6004Detail::unique_ptr<ITestInvoker> makeTestInvoker( void (C::*testAsMethod)() ) { 6005 return Detail::make_unique<TestInvokerAsMethod<C>>( testAsMethod ); 6006} 6007 6008struct NameAndTags { 6009 constexpr NameAndTags( StringRef name_ = StringRef(), 6010 StringRef tags_ = StringRef() ) noexcept: 6011 name( name_ ), tags( tags_ ) {} 6012 StringRef name; 6013 StringRef tags; 6014}; 6015 6016struct AutoReg : Detail::NonCopyable { 6017 AutoReg( Detail::unique_ptr<ITestInvoker> invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) noexcept; 6018}; 6019 6020} // end namespace Catch 6021 6022#if defined(CATCH_CONFIG_DISABLE) 6023 #define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \ 6024 static inline void TestName() 6025 #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \ 6026 namespace{ \ 6027 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \ 6028 void test(); \ 6029 }; \ 6030 } \ 6031 void TestName::test() 6032#endif 6033 6034 6035#if !defined(CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT) 6036 6037 /////////////////////////////////////////////////////////////////////////////// 6038 #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ 6039 static void TestName(); \ 6040 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 6041 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 6042 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ 6043 namespace{ const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \ 6044 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 6045 static void TestName() 6046 #define INTERNAL_CATCH_TESTCASE( ... ) \ 6047 INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), __VA_ARGS__ ) 6048 6049#else // ^^ !CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT | vv CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT 6050 6051 6052// Dummy registrator for the dumy test case macros 6053namespace Catch { 6054 namespace Detail { 6055 struct DummyUse { 6056 DummyUse( void ( * )( int ), Catch::NameAndTags const& ); 6057 }; 6058 } // namespace Detail 6059} // namespace Catch 6060 6061// Note that both the presence of the argument and its exact name are 6062// necessary for the section support. 6063 6064// We provide a shadowed variable so that a `SECTION` inside non-`TEST_CASE` 6065// tests can compile. The redefined `TEST_CASE` shadows this with param. 6066static int catchInternalSectionHint = 0; 6067 6068# define INTERNAL_CATCH_TESTCASE2( fname, ... ) \ 6069 static void fname( int ); \ 6070 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 6071 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 6072 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ 6073 static const Catch::Detail::DummyUse INTERNAL_CATCH_UNIQUE_NAME( \ 6074 dummyUser )( &(fname), Catch::NameAndTags{ __VA_ARGS__ } ); \ 6075 CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \ 6076 static void fname( [[maybe_unused]] int catchInternalSectionHint ) \ 6077 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 6078# define INTERNAL_CATCH_TESTCASE( ... ) \ 6079 INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( dummyFunction ), __VA_ARGS__ ) 6080 6081 6082#endif // CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT 6083 6084 /////////////////////////////////////////////////////////////////////////////// 6085 #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ 6086 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 6087 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 6088 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ 6089 namespace{ \ 6090 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \ 6091 void test(); \ 6092 }; \ 6093 const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( \ 6094 Catch::makeTestInvoker( &TestName::test ), \ 6095 CATCH_INTERNAL_LINEINFO, \ 6096 #ClassName##_catch_sr, \ 6097 Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ 6098 } \ 6099 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 6100 void TestName::test() 6101 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \ 6102 INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), ClassName, __VA_ARGS__ ) 6103 6104 6105 /////////////////////////////////////////////////////////////////////////////// 6106 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ 6107 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 6108 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 6109 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ 6110 namespace { \ 6111 const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( \ 6112 Catch::makeTestInvoker( &QualifiedMethod ), \ 6113 CATCH_INTERNAL_LINEINFO, \ 6114 "&" #QualifiedMethod##_catch_sr, \ 6115 Catch::NameAndTags{ __VA_ARGS__ } ); \ 6116 } /* NOLINT */ \ 6117 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 6118 6119 6120 /////////////////////////////////////////////////////////////////////////////// 6121 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ 6122 do { \ 6123 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 6124 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 6125 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ 6126 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ 6127 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 6128 } while(false) 6129 6130 6131#endif // CATCH_TEST_REGISTRY_HPP_INCLUDED 6132 6133 6134// All of our user-facing macros support configuration toggle, that 6135// forces them to be defined prefixed with CATCH_. We also like to 6136// support another toggle that can minimize (disable) their implementation. 6137// Given this, we have 4 different configuration options below 6138 6139#if defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE) 6140 6141 #define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 6142 #define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 6143 6144 #define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 6145 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) 6146 #define CATCH_REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 6147 6148 #define CATCH_CHECK( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 6149 #define CATCH_CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 6150 #define CATCH_CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) 6151 #define CATCH_CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) 6152 #define CATCH_CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) 6153 6154 #define CATCH_CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 6155 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) 6156 #define CATCH_CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 6157 6158 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) 6159 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) 6160 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) 6161 #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) 6162 #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) 6163 #define CATCH_DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ ) 6164 #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) 6165 #define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 6166 #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 6167 #define CATCH_SKIP( ... ) INTERNAL_CATCH_MSG( "SKIP", Catch::ResultWas::ExplicitSkip, Catch::ResultDisposition::Normal, __VA_ARGS__ ) 6168 6169 6170 #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE) 6171 #define CATCH_STATIC_REQUIRE( ... ) static_assert( __VA_ARGS__ , #__VA_ARGS__ ); CATCH_SUCCEED( #__VA_ARGS__ ) 6172 #define CATCH_STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); CATCH_SUCCEED( #__VA_ARGS__ ) 6173 #define CATCH_STATIC_CHECK( ... ) static_assert( __VA_ARGS__ , #__VA_ARGS__ ); CATCH_SUCCEED( #__VA_ARGS__ ) 6174 #define CATCH_STATIC_CHECK_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); CATCH_SUCCEED( #__VA_ARGS__ ) 6175 #else 6176 #define CATCH_STATIC_REQUIRE( ... ) CATCH_REQUIRE( __VA_ARGS__ ) 6177 #define CATCH_STATIC_REQUIRE_FALSE( ... ) CATCH_REQUIRE_FALSE( __VA_ARGS__ ) 6178 #define CATCH_STATIC_CHECK( ... ) CATCH_CHECK( __VA_ARGS__ ) 6179 #define CATCH_STATIC_CHECK_FALSE( ... ) CATCH_CHECK_FALSE( __VA_ARGS__ ) 6180 #endif 6181 6182 6183 // "BDD-style" convenience wrappers 6184 #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) 6185 #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) 6186 #define CATCH_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc ) 6187 #define CATCH_AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc ) 6188 #define CATCH_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc ) 6189 #define CATCH_AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc ) 6190 #define CATCH_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc ) 6191 #define CATCH_AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc ) 6192 6193#elif defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE) // ^^ prefixed, implemented | vv prefixed, disabled 6194 6195 #define CATCH_REQUIRE( ... ) (void)(0) 6196 #define CATCH_REQUIRE_FALSE( ... ) (void)(0) 6197 6198 #define CATCH_REQUIRE_THROWS( ... ) (void)(0) 6199 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0) 6200 #define CATCH_REQUIRE_NOTHROW( ... ) (void)(0) 6201 6202 #define CATCH_CHECK( ... ) (void)(0) 6203 #define CATCH_CHECK_FALSE( ... ) (void)(0) 6204 #define CATCH_CHECKED_IF( ... ) if (__VA_ARGS__) 6205 #define CATCH_CHECKED_ELSE( ... ) if (!(__VA_ARGS__)) 6206 #define CATCH_CHECK_NOFAIL( ... ) (void)(0) 6207 6208 #define CATCH_CHECK_THROWS( ... ) (void)(0) 6209 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) (void)(0) 6210 #define CATCH_CHECK_NOTHROW( ... ) (void)(0) 6211 6212 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ )) 6213 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ )) 6214 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) 6215 #define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0) 6216 #define CATCH_SECTION( ... ) 6217 #define CATCH_DYNAMIC_SECTION( ... ) 6218 #define CATCH_FAIL( ... ) (void)(0) 6219 #define CATCH_FAIL_CHECK( ... ) (void)(0) 6220 #define CATCH_SUCCEED( ... ) (void)(0) 6221 #define CATCH_SKIP( ... ) (void)(0) 6222 6223 #define CATCH_STATIC_REQUIRE( ... ) (void)(0) 6224 #define CATCH_STATIC_REQUIRE_FALSE( ... ) (void)(0) 6225 #define CATCH_STATIC_CHECK( ... ) (void)(0) 6226 #define CATCH_STATIC_CHECK_FALSE( ... ) (void)(0) 6227 6228 // "BDD-style" convenience wrappers 6229 #define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ )) 6230 #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), className ) 6231 #define CATCH_GIVEN( desc ) 6232 #define CATCH_AND_GIVEN( desc ) 6233 #define CATCH_WHEN( desc ) 6234 #define CATCH_AND_WHEN( desc ) 6235 #define CATCH_THEN( desc ) 6236 #define CATCH_AND_THEN( desc ) 6237 6238#elif !defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE) // ^^ prefixed, disabled | vv unprefixed, implemented 6239 6240 #define REQUIRE( ... ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 6241 #define REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 6242 6243 #define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 6244 #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) 6245 #define REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 6246 6247 #define CHECK( ... ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 6248 #define CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 6249 #define CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) 6250 #define CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) 6251 #define CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) 6252 6253 #define CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 6254 #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) 6255 #define CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 6256 6257 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) 6258 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) 6259 #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) 6260 #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) 6261 #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) 6262 #define DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ ) 6263 #define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) 6264 #define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 6265 #define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 6266 #define SKIP( ... ) INTERNAL_CATCH_MSG( "SKIP", Catch::ResultWas::ExplicitSkip, Catch::ResultDisposition::Normal, __VA_ARGS__ ) 6267 6268 6269 #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE) 6270 #define STATIC_REQUIRE( ... ) static_assert( __VA_ARGS__, #__VA_ARGS__ ); SUCCEED( #__VA_ARGS__ ) 6271 #define STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); SUCCEED( "!(" #__VA_ARGS__ ")" ) 6272 #define STATIC_CHECK( ... ) static_assert( __VA_ARGS__, #__VA_ARGS__ ); SUCCEED( #__VA_ARGS__ ) 6273 #define STATIC_CHECK_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); SUCCEED( "!(" #__VA_ARGS__ ")" ) 6274 #else 6275 #define STATIC_REQUIRE( ... ) REQUIRE( __VA_ARGS__ ) 6276 #define STATIC_REQUIRE_FALSE( ... ) REQUIRE_FALSE( __VA_ARGS__ ) 6277 #define STATIC_CHECK( ... ) CHECK( __VA_ARGS__ ) 6278 #define STATIC_CHECK_FALSE( ... ) CHECK_FALSE( __VA_ARGS__ ) 6279 #endif 6280 6281 // "BDD-style" convenience wrappers 6282 #define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) 6283 #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) 6284 #define GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc ) 6285 #define AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc ) 6286 #define WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc ) 6287 #define AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc ) 6288 #define THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc ) 6289 #define AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc ) 6290 6291#elif !defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE) // ^^ unprefixed, implemented | vv unprefixed, disabled 6292 6293 #define REQUIRE( ... ) (void)(0) 6294 #define REQUIRE_FALSE( ... ) (void)(0) 6295 6296 #define REQUIRE_THROWS( ... ) (void)(0) 6297 #define REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0) 6298 #define REQUIRE_NOTHROW( ... ) (void)(0) 6299 6300 #define CHECK( ... ) (void)(0) 6301 #define CHECK_FALSE( ... ) (void)(0) 6302 #define CHECKED_IF( ... ) if (__VA_ARGS__) 6303 #define CHECKED_ELSE( ... ) if (!(__VA_ARGS__)) 6304 #define CHECK_NOFAIL( ... ) (void)(0) 6305 6306 #define CHECK_THROWS( ... ) (void)(0) 6307 #define CHECK_THROWS_AS( expr, exceptionType ) (void)(0) 6308 #define CHECK_NOTHROW( ... ) (void)(0) 6309 6310 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), __VA_ARGS__) 6311 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ )) 6312 #define METHOD_AS_TEST_CASE( method, ... ) 6313 #define REGISTER_TEST_CASE( Function, ... ) (void)(0) 6314 #define SECTION( ... ) 6315 #define DYNAMIC_SECTION( ... ) 6316 #define FAIL( ... ) (void)(0) 6317 #define FAIL_CHECK( ... ) (void)(0) 6318 #define SUCCEED( ... ) (void)(0) 6319 #define SKIP( ... ) (void)(0) 6320 6321 #define STATIC_REQUIRE( ... ) (void)(0) 6322 #define STATIC_REQUIRE_FALSE( ... ) (void)(0) 6323 #define STATIC_CHECK( ... ) (void)(0) 6324 #define STATIC_CHECK_FALSE( ... ) (void)(0) 6325 6326 // "BDD-style" convenience wrappers 6327 #define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ) ) 6328 #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), className ) 6329 6330 #define GIVEN( desc ) 6331 #define AND_GIVEN( desc ) 6332 #define WHEN( desc ) 6333 #define AND_WHEN( desc ) 6334 #define THEN( desc ) 6335 #define AND_THEN( desc ) 6336 6337#endif // ^^ unprefixed, disabled 6338 6339// end of user facing macros 6340 6341#endif // CATCH_TEST_MACROS_HPP_INCLUDED 6342 6343 6344#ifndef CATCH_TEMPLATE_TEST_REGISTRY_HPP_INCLUDED 6345#define CATCH_TEMPLATE_TEST_REGISTRY_HPP_INCLUDED 6346 6347 6348 6349#ifndef CATCH_PREPROCESSOR_HPP_INCLUDED 6350#define CATCH_PREPROCESSOR_HPP_INCLUDED 6351 6352 6353#if defined(__GNUC__) 6354// We need to silence "empty __VA_ARGS__ warning", and using just _Pragma does not work 6355#pragma GCC system_header 6356#endif 6357 6358 6359#define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__ 6360#define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__))) 6361#define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__))) 6362#define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__))) 6363#define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__))) 6364#define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__))) 6365 6366#ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 6367#define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__ 6368// MSVC needs more evaluations 6369#define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__))) 6370#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__)) 6371#else 6372#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL5(__VA_ARGS__) 6373#endif 6374 6375#define CATCH_REC_END(...) 6376#define CATCH_REC_OUT 6377 6378#define CATCH_EMPTY() 6379#define CATCH_DEFER(id) id CATCH_EMPTY() 6380 6381#define CATCH_REC_GET_END2() 0, CATCH_REC_END 6382#define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2 6383#define CATCH_REC_GET_END(...) CATCH_REC_GET_END1 6384#define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT 6385#define CATCH_REC_NEXT1(test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0) 6386#define CATCH_REC_NEXT(test, next) CATCH_REC_NEXT1(CATCH_REC_GET_END test, next) 6387 6388#define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) 6389#define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ ) 6390#define CATCH_REC_LIST2(f, x, peek, ...) f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) 6391 6392#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__ ) 6393#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__ ) 6394#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__ ) 6395 6396// Applies the function macro `f` to each of the remaining parameters, inserts commas between the results, 6397// and passes userdata as the first parameter to each invocation, 6398// e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c) 6399#define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) 6400 6401#define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) 6402 6403#define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__) 6404#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 6405#define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__ 6406#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) 6407#else 6408// MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF 6409#define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__) 6410#define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__ 6411#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1) 6412#endif 6413 6414#define INTERNAL_CATCH_MAKE_NAMESPACE2(...) ns_##__VA_ARGS__ 6415#define INTERNAL_CATCH_MAKE_NAMESPACE(name) INTERNAL_CATCH_MAKE_NAMESPACE2(name) 6416 6417#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 6418#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS_GEN(__VA_ARGS__)>()) 6419#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)) 6420#else 6421#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) INTERNAL_CATCH_EXPAND_VARGS(decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS_GEN(__VA_ARGS__)>())) 6422#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))) 6423#endif 6424 6425#define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(...)\ 6426 CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,__VA_ARGS__) 6427 6428#define INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_0) INTERNAL_CATCH_REMOVE_PARENS(_0) 6429#define INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_0, _1) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_1) 6430#define INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_0, _1, _2) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_1, _2) 6431#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) 6432#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) 6433#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) 6434#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) 6435#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) 6436#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) 6437#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) 6438#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) 6439 6440#define INTERNAL_CATCH_VA_NARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N 6441 6442#define INTERNAL_CATCH_TYPE_GEN\ 6443 template<typename...> struct TypeList {};\ 6444 template<typename...Ts>\ 6445 constexpr auto get_wrapper() noexcept -> TypeList<Ts...> { return {}; }\ 6446 template<template<typename...> class...> struct TemplateTypeList{};\ 6447 template<template<typename...> class...Cs>\ 6448 constexpr auto get_wrapper() noexcept -> TemplateTypeList<Cs...> { return {}; }\ 6449 template<typename...>\ 6450 struct append;\ 6451 template<typename...>\ 6452 struct rewrap;\ 6453 template<template<typename...> class, typename...>\ 6454 struct create;\ 6455 template<template<typename...> class, typename>\ 6456 struct convert;\ 6457 \ 6458 template<typename T> \ 6459 struct append<T> { using type = T; };\ 6460 template< template<typename...> class L1, typename...E1, template<typename...> class L2, typename...E2, typename...Rest>\ 6461 struct append<L1<E1...>, L2<E2...>, Rest...> { using type = typename append<L1<E1...,E2...>, Rest...>::type; };\ 6462 template< template<typename...> class L1, typename...E1, typename...Rest>\ 6463 struct append<L1<E1...>, TypeList<mpl_::na>, Rest...> { using type = L1<E1...>; };\ 6464 \ 6465 template< template<typename...> class Container, template<typename...> class List, typename...elems>\ 6466 struct rewrap<TemplateTypeList<Container>, List<elems...>> { using type = TypeList<Container<elems...>>; };\ 6467 template< template<typename...> class Container, template<typename...> class List, class...Elems, typename...Elements>\ 6468 struct rewrap<TemplateTypeList<Container>, List<Elems...>, Elements...> { using type = typename append<TypeList<Container<Elems...>>, typename rewrap<TemplateTypeList<Container>, Elements...>::type>::type; };\ 6469 \ 6470 template<template <typename...> class Final, template< typename...> class...Containers, typename...Types>\ 6471 struct create<Final, TemplateTypeList<Containers...>, TypeList<Types...>> { using type = typename append<Final<>, typename rewrap<TemplateTypeList<Containers>, Types...>::type...>::type; };\ 6472 template<template <typename...> class Final, template <typename...> class List, typename...Ts>\ 6473 struct convert<Final, List<Ts...>> { using type = typename append<Final<>,TypeList<Ts>...>::type; }; 6474 6475#define INTERNAL_CATCH_NTTP_1(signature, ...)\ 6476 template<INTERNAL_CATCH_REMOVE_PARENS(signature)> struct Nttp{};\ 6477 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 6478 constexpr auto get_wrapper() noexcept -> Nttp<__VA_ARGS__> { return {}; } \ 6479 template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...> struct NttpTemplateTypeList{};\ 6480 template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...Cs>\ 6481 constexpr auto get_wrapper() noexcept -> NttpTemplateTypeList<Cs...> { return {}; } \ 6482 \ 6483 template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 6484 struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>> { using type = TypeList<Container<__VA_ARGS__>>; };\ 6485 template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature), typename...Elements>\ 6486 struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>, Elements...> { using type = typename append<TypeList<Container<__VA_ARGS__>>, typename rewrap<NttpTemplateTypeList<Container>, Elements...>::type>::type; };\ 6487 template<template <typename...> class Final, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...Containers, typename...Types>\ 6488 struct create<Final, NttpTemplateTypeList<Containers...>, TypeList<Types...>> { using type = typename append<Final<>, typename rewrap<NttpTemplateTypeList<Containers>, Types...>::type...>::type; }; 6489 6490#define INTERNAL_CATCH_DECLARE_SIG_TEST0(TestName) 6491#define INTERNAL_CATCH_DECLARE_SIG_TEST1(TestName, signature)\ 6492 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 6493 static void TestName() 6494#define INTERNAL_CATCH_DECLARE_SIG_TEST_X(TestName, signature, ...)\ 6495 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 6496 static void TestName() 6497 6498#define INTERNAL_CATCH_DEFINE_SIG_TEST0(TestName) 6499#define INTERNAL_CATCH_DEFINE_SIG_TEST1(TestName, signature)\ 6500 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 6501 static void TestName() 6502#define INTERNAL_CATCH_DEFINE_SIG_TEST_X(TestName, signature,...)\ 6503 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 6504 static void TestName() 6505 6506#define INTERNAL_CATCH_NTTP_REGISTER0(TestFunc, signature)\ 6507 template<typename Type>\ 6508 void reg_test(TypeList<Type>, Catch::NameAndTags nameAndTags)\ 6509 {\ 6510 Catch::AutoReg( Catch::makeTestInvoker(&TestFunc<Type>), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), nameAndTags);\ 6511 } 6512 6513#define INTERNAL_CATCH_NTTP_REGISTER(TestFunc, signature, ...)\ 6514 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 6515 void reg_test(Nttp<__VA_ARGS__>, Catch::NameAndTags nameAndTags)\ 6516 {\ 6517 Catch::AutoReg( Catch::makeTestInvoker(&TestFunc<__VA_ARGS__>), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), nameAndTags);\ 6518 } 6519 6520#define INTERNAL_CATCH_NTTP_REGISTER_METHOD0(TestName, signature, ...)\ 6521 template<typename Type>\ 6522 void reg_test(TypeList<Type>, Catch::StringRef className, Catch::NameAndTags nameAndTags)\ 6523 {\ 6524 Catch::AutoReg( Catch::makeTestInvoker(&TestName<Type>::test), CATCH_INTERNAL_LINEINFO, className, nameAndTags);\ 6525 } 6526 6527#define INTERNAL_CATCH_NTTP_REGISTER_METHOD(TestName, signature, ...)\ 6528 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ 6529 void reg_test(Nttp<__VA_ARGS__>, Catch::StringRef className, Catch::NameAndTags nameAndTags)\ 6530 {\ 6531 Catch::AutoReg( Catch::makeTestInvoker(&TestName<__VA_ARGS__>::test), CATCH_INTERNAL_LINEINFO, className, nameAndTags);\ 6532 } 6533 6534#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0(TestName, ClassName) 6535#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1(TestName, ClassName, signature)\ 6536 template<typename TestType> \ 6537 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName)<TestType> { \ 6538 void test();\ 6539 } 6540 6541#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X(TestName, ClassName, signature, ...)\ 6542 template<INTERNAL_CATCH_REMOVE_PARENS(signature)> \ 6543 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName)<__VA_ARGS__> { \ 6544 void test();\ 6545 } 6546 6547#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0(TestName) 6548#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1(TestName, signature)\ 6549 template<typename TestType> \ 6550 void INTERNAL_CATCH_MAKE_NAMESPACE(TestName)::TestName<TestType>::test() 6551#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X(TestName, signature, ...)\ 6552 template<INTERNAL_CATCH_REMOVE_PARENS(signature)> \ 6553 void INTERNAL_CATCH_MAKE_NAMESPACE(TestName)::TestName<__VA_ARGS__>::test() 6554 6555#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 6556#define INTERNAL_CATCH_NTTP_0 6557#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) 6558#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__) 6559#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__) 6560#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__) 6561#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__) 6562#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__) 6563#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__) 6564#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__) 6565#else 6566#define INTERNAL_CATCH_NTTP_0(signature) 6567#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__)) 6568#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__)) 6569#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__)) 6570#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__)) 6571#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__)) 6572#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__)) 6573#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__)) 6574#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__)) 6575#endif 6576 6577#endif // CATCH_PREPROCESSOR_HPP_INCLUDED 6578 6579 6580// GCC 5 and older do not properly handle disabling unused-variable warning 6581// with a _Pragma. This means that we have to leak the suppression to the 6582// user code as well :-( 6583#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 5 6584#pragma GCC diagnostic ignored "-Wunused-variable" 6585#endif 6586 6587#if defined(CATCH_CONFIG_DISABLE) 6588 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( TestName, TestFunc, Name, Tags, Signature, ... ) \ 6589 INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature)) 6590 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \ 6591 namespace{ \ 6592 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) { \ 6593 INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, INTERNAL_CATCH_REMOVE_PARENS(Signature));\ 6594 } \ 6595 } \ 6596 INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature)) 6597 6598 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 6599 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \ 6600 INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, typename TestType, __VA_ARGS__ ) 6601 #else 6602 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \ 6603 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, typename TestType, __VA_ARGS__ ) ) 6604 #endif 6605 6606 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 6607 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \ 6608 INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, Signature, __VA_ARGS__ ) 6609 #else 6610 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \ 6611 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, Signature, __VA_ARGS__ ) ) 6612 #endif 6613 6614 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 6615 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \ 6616 INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_CLASS_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) 6617 #else 6618 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \ 6619 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_CLASS_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) ) 6620 #endif 6621 6622 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 6623 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \ 6624 INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_CLASS_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) 6625 #else 6626 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \ 6627 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_CLASS_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) ) 6628 #endif 6629#endif 6630 6631 6632 /////////////////////////////////////////////////////////////////////////////// 6633 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_2(TestName, TestFunc, Name, Tags, Signature, ... )\ 6634 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 6635 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 6636 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ 6637 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 6638 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ 6639 CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS \ 6640 INTERNAL_CATCH_DECLARE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature));\ 6641 namespace {\ 6642 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\ 6643 INTERNAL_CATCH_TYPE_GEN\ 6644 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\ 6645 INTERNAL_CATCH_NTTP_REG_GEN(TestFunc,INTERNAL_CATCH_REMOVE_PARENS(Signature))\ 6646 template<typename...Types> \ 6647 struct TestName{\ 6648 TestName(){\ 6649 size_t index = 0; \ 6650 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)}; /* NOLINT(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays,hicpp-avoid-c-arrays) */\ 6651 using expander = size_t[]; /* NOLINT(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays,hicpp-avoid-c-arrays) */\ 6652 (void)expander{(reg_test(Types{}, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };/* NOLINT */ \ 6653 }\ 6654 };\ 6655 static const int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ 6656 TestName<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(__VA_ARGS__)>();\ 6657 return 0;\ 6658 }();\ 6659 }\ 6660 }\ 6661 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 6662 INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc,INTERNAL_CATCH_REMOVE_PARENS(Signature)) 6663 6664#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 6665 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \ 6666 INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, typename TestType, __VA_ARGS__ ) 6667#else 6668 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \ 6669 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, typename TestType, __VA_ARGS__ ) ) 6670#endif 6671 6672#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 6673 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \ 6674 INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, Signature, __VA_ARGS__ ) 6675#else 6676 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \ 6677 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, Signature, __VA_ARGS__ ) ) 6678#endif 6679 6680 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(TestName, TestFuncName, Name, Tags, Signature, TmplTypes, TypesList) \ 6681 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 6682 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 6683 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ 6684 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 6685 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ 6686 CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS \ 6687 template<typename TestType> static void TestFuncName(); \ 6688 namespace {\ 6689 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) { \ 6690 INTERNAL_CATCH_TYPE_GEN \ 6691 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature)) \ 6692 template<typename... Types> \ 6693 struct TestName { \ 6694 void reg_tests() { \ 6695 size_t index = 0; \ 6696 using expander = size_t[]; \ 6697 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\ 6698 constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\ 6699 constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\ 6700 (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 */\ 6701 } \ 6702 }; \ 6703 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \ 6704 using TestInit = typename create<TestName, decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>()), TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(INTERNAL_CATCH_REMOVE_PARENS(TypesList))>>::type; \ 6705 TestInit t; \ 6706 t.reg_tests(); \ 6707 return 0; \ 6708 }(); \ 6709 } \ 6710 } \ 6711 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 6712 template<typename TestType> \ 6713 static void TestFuncName() 6714 6715#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 6716 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\ 6717 INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, typename T,__VA_ARGS__) 6718#else 6719 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\ 6720 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, typename T, __VA_ARGS__ ) ) 6721#endif 6722 6723#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 6724 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\ 6725 INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, Signature, __VA_ARGS__) 6726#else 6727 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\ 6728 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, Signature, __VA_ARGS__ ) ) 6729#endif 6730 6731 #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2(TestName, TestFunc, Name, Tags, TmplList)\ 6732 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 6733 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 6734 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 6735 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ 6736 CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS \ 6737 template<typename TestType> static void TestFunc(); \ 6738 namespace {\ 6739 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\ 6740 INTERNAL_CATCH_TYPE_GEN\ 6741 template<typename... Types> \ 6742 struct TestName { \ 6743 void reg_tests() { \ 6744 size_t index = 0; \ 6745 using expander = size_t[]; \ 6746 (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFunc<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " INTERNAL_CATCH_STRINGIZE(TmplList) " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */\ 6747 } \ 6748 };\ 6749 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \ 6750 using TestInit = typename convert<TestName, TmplList>::type; \ 6751 TestInit t; \ 6752 t.reg_tests(); \ 6753 return 0; \ 6754 }(); \ 6755 }}\ 6756 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 6757 template<typename TestType> \ 6758 static void TestFunc() 6759 6760 #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(Name, Tags, TmplList) \ 6761 INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, TmplList ) 6762 6763 6764 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \ 6765 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 6766 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 6767 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ 6768 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 6769 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ 6770 namespace {\ 6771 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \ 6772 INTERNAL_CATCH_TYPE_GEN\ 6773 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\ 6774 INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, INTERNAL_CATCH_REMOVE_PARENS(Signature));\ 6775 INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))\ 6776 template<typename...Types> \ 6777 struct TestNameClass{\ 6778 TestNameClass(){\ 6779 size_t index = 0; \ 6780 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\ 6781 using expander = size_t[];\ 6782 (void)expander{(reg_test(Types{}, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };/* NOLINT */ \ 6783 }\ 6784 };\ 6785 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ 6786 TestNameClass<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(__VA_ARGS__)>();\ 6787 return 0;\ 6788 }();\ 6789 }\ 6790 }\ 6791 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 6792 INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature)) 6793 6794#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 6795 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \ 6796 INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_CLASS_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) 6797#else 6798 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \ 6799 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_CLASS_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) ) 6800#endif 6801 6802#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 6803 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \ 6804 INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_CLASS_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) 6805#else 6806 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \ 6807 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_CLASS_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) ) 6808#endif 6809 6810 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2(TestNameClass, TestName, ClassName, Name, Tags, Signature, TmplTypes, TypesList)\ 6811 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 6812 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 6813 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ 6814 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 6815 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ 6816 template<typename TestType> \ 6817 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \ 6818 void test();\ 6819 };\ 6820 namespace {\ 6821 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestNameClass) {\ 6822 INTERNAL_CATCH_TYPE_GEN \ 6823 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\ 6824 template<typename...Types>\ 6825 struct TestNameClass{\ 6826 void reg_tests(){\ 6827 std::size_t index = 0;\ 6828 using expander = std::size_t[];\ 6829 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\ 6830 constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\ 6831 constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\ 6832 (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 */ \ 6833 }\ 6834 };\ 6835 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ 6836 using TestInit = typename create<TestNameClass, decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>()), TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(INTERNAL_CATCH_REMOVE_PARENS(TypesList))>>::type;\ 6837 TestInit t;\ 6838 t.reg_tests();\ 6839 return 0;\ 6840 }(); \ 6841 }\ 6842 }\ 6843 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 6844 template<typename TestType> \ 6845 void TestName<TestType>::test() 6846 6847#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 6848 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\ 6849 INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), ClassName, Name, Tags, typename T, __VA_ARGS__ ) 6850#else 6851 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\ 6852 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), ClassName, Name, Tags, typename T,__VA_ARGS__ ) ) 6853#endif 6854 6855#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 6856 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\ 6857 INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), ClassName, Name, Tags, Signature, __VA_ARGS__ ) 6858#else 6859 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\ 6860 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), ClassName, Name, Tags, Signature,__VA_ARGS__ ) ) 6861#endif 6862 6863 #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, TmplList) \ 6864 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 6865 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 6866 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ 6867 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ 6868 CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS \ 6869 template<typename TestType> \ 6870 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \ 6871 void test();\ 6872 };\ 6873 namespace {\ 6874 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \ 6875 INTERNAL_CATCH_TYPE_GEN\ 6876 template<typename...Types>\ 6877 struct TestNameClass{\ 6878 void reg_tests(){\ 6879 size_t index = 0;\ 6880 using expander = size_t[];\ 6881 (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName##_catch_sr, Catch::NameAndTags{ Name " - " INTERNAL_CATCH_STRINGIZE(TmplList) " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */ \ 6882 }\ 6883 };\ 6884 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ 6885 using TestInit = typename convert<TestNameClass, TmplList>::type;\ 6886 TestInit t;\ 6887 t.reg_tests();\ 6888 return 0;\ 6889 }(); \ 6890 }}\ 6891 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 6892 template<typename TestType> \ 6893 void TestName<TestType>::test() 6894 6895#define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD(ClassName, Name, Tags, TmplList) \ 6896 INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), ClassName, Name, Tags, TmplList ) 6897 6898 6899#endif // CATCH_TEMPLATE_TEST_REGISTRY_HPP_INCLUDED 6900 6901 6902#if defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE) 6903 6904 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 6905 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 6906 #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) 6907 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 6908 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) 6909 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) 6910 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) 6911 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) 6912 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) 6913 #define CATCH_TEMPLATE_LIST_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(__VA_ARGS__) 6914 #define CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, __VA_ARGS__ ) 6915 #else 6916 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) ) 6917 #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) ) 6918 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) 6919 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) ) 6920 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) ) 6921 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) ) 6922 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) 6923 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) ) 6924 #define CATCH_TEMPLATE_LIST_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE( __VA_ARGS__ ) ) 6925 #define CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) 6926 #endif 6927 6928#elif defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE) 6929 6930 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 6931 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) 6932 #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) 6933 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__) 6934 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) 6935 #else 6936 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) ) 6937 #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) ) 6938 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__ ) ) 6939 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) ) 6940 #endif 6941 6942 // When disabled, these can be shared between proper preprocessor and MSVC preprocessor 6943 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 6944 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 6945 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 6946 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 6947 #define CATCH_TEMPLATE_LIST_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE(__VA_ARGS__) 6948 #define CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 6949 6950#elif !defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE) 6951 6952 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 6953 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 6954 #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) 6955 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 6956 #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) 6957 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) 6958 #define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) 6959 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) 6960 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) 6961 #define TEMPLATE_LIST_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(__VA_ARGS__) 6962 #define TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, __VA_ARGS__ ) 6963 #else 6964 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) ) 6965 #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) ) 6966 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) 6967 #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) ) 6968 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) ) 6969 #define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) ) 6970 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) 6971 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) ) 6972 #define TEMPLATE_LIST_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE( __VA_ARGS__ ) ) 6973 #define TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) 6974 #endif 6975 6976#elif !defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE) 6977 6978 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 6979 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) 6980 #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) 6981 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__) 6982 #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) 6983 #else 6984 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) ) 6985 #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) ) 6986 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__ ) ) 6987 #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) ) 6988 #endif 6989 6990 // When disabled, these can be shared between proper preprocessor and MSVC preprocessor 6991 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ ) 6992 #define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ ) 6993 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 6994 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 6995 #define TEMPLATE_LIST_TEST_CASE( ... ) TEMPLATE_TEST_CASE(__VA_ARGS__) 6996 #define TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 6997 6998#endif // end of user facing macro declarations 6999 7000 7001#endif // CATCH_TEMPLATE_TEST_MACROS_HPP_INCLUDED 7002 7003 7004#ifndef CATCH_TEST_CASE_INFO_HPP_INCLUDED 7005#define CATCH_TEST_CASE_INFO_HPP_INCLUDED 7006 7007 7008 7009#include <cstdint> 7010#include <string> 7011#include <vector> 7012 7013#ifdef __clang__ 7014#pragma clang diagnostic push 7015#pragma clang diagnostic ignored "-Wpadded" 7016#endif 7017 7018namespace Catch { 7019 7020 /** 7021 * A **view** of a tag string that provides case insensitive comparisons 7022 * 7023 * Note that in Catch2 internals, the square brackets around tags are 7024 * not a part of tag's representation, so e.g. "[cool-tag]" is represented 7025 * as "cool-tag" internally. 7026 */ 7027 struct Tag { 7028 constexpr Tag(StringRef original_): 7029 original(original_) 7030 {} 7031 StringRef original; 7032 7033 friend bool operator< ( Tag const& lhs, Tag const& rhs ); 7034 friend bool operator==( Tag const& lhs, Tag const& rhs ); 7035 }; 7036 7037 class ITestInvoker; 7038 struct NameAndTags; 7039 7040 enum class TestCaseProperties : uint8_t { 7041 None = 0, 7042 IsHidden = 1 << 1, 7043 ShouldFail = 1 << 2, 7044 MayFail = 1 << 3, 7045 Throws = 1 << 4, 7046 NonPortable = 1 << 5, 7047 Benchmark = 1 << 6 7048 }; 7049 7050 /** 7051 * Various metadata about the test case. 7052 * 7053 * A test case is uniquely identified by its (class)name and tags 7054 * combination, with source location being ignored, and other properties 7055 * being determined from tags. 7056 * 7057 * Tags are kept sorted. 7058 */ 7059 struct TestCaseInfo : Detail::NonCopyable { 7060 7061 TestCaseInfo(StringRef _className, 7062 NameAndTags const& _nameAndTags, 7063 SourceLineInfo const& _lineInfo); 7064 7065 bool isHidden() const; 7066 bool throws() const; 7067 bool okToFail() const; 7068 bool expectedToFail() const; 7069 7070 // Adds the tag(s) with test's filename (for the -# flag) 7071 void addFilenameTag(); 7072 7073 //! Orders by name, classname and tags 7074 friend bool operator<( TestCaseInfo const& lhs, 7075 TestCaseInfo const& rhs ); 7076 7077 7078 std::string tagsAsString() const; 7079 7080 std::string name; 7081 StringRef className; 7082 private: 7083 std::string backingTags; 7084 // Internally we copy tags to the backing storage and then add 7085 // refs to this storage to the tags vector. 7086 void internalAppendTag(StringRef tagString); 7087 public: 7088 std::vector<Tag> tags; 7089 SourceLineInfo lineInfo; 7090 TestCaseProperties properties = TestCaseProperties::None; 7091 }; 7092 7093 /** 7094 * Wrapper over the test case information and the test case invoker 7095 * 7096 * Does not own either, and is specifically made to be cheap 7097 * to copy around. 7098 */ 7099 class TestCaseHandle { 7100 TestCaseInfo* m_info; 7101 ITestInvoker* m_invoker; 7102 public: 7103 TestCaseHandle(TestCaseInfo* info, ITestInvoker* invoker) : 7104 m_info(info), m_invoker(invoker) {} 7105 7106 void invoke() const { 7107 m_invoker->invoke(); 7108 } 7109 7110 TestCaseInfo const& getTestCaseInfo() const; 7111 }; 7112 7113 Detail::unique_ptr<TestCaseInfo> 7114 makeTestCaseInfo( StringRef className, 7115 NameAndTags const& nameAndTags, 7116 SourceLineInfo const& lineInfo ); 7117} 7118 7119#ifdef __clang__ 7120#pragma clang diagnostic pop 7121#endif 7122 7123#endif // CATCH_TEST_CASE_INFO_HPP_INCLUDED 7124 7125 7126#ifndef CATCH_TRANSLATE_EXCEPTION_HPP_INCLUDED 7127#define CATCH_TRANSLATE_EXCEPTION_HPP_INCLUDED 7128 7129 7130 7131#ifndef CATCH_INTERFACES_EXCEPTION_HPP_INCLUDED 7132#define CATCH_INTERFACES_EXCEPTION_HPP_INCLUDED 7133 7134 7135#include <string> 7136#include <vector> 7137 7138namespace Catch { 7139 using exceptionTranslateFunction = std::string(*)(); 7140 7141 class IExceptionTranslator; 7142 using ExceptionTranslators = std::vector<Detail::unique_ptr<IExceptionTranslator const>>; 7143 7144 class IExceptionTranslator { 7145 public: 7146 virtual ~IExceptionTranslator(); // = default 7147 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0; 7148 }; 7149 7150 class IExceptionTranslatorRegistry { 7151 public: 7152 virtual ~IExceptionTranslatorRegistry(); // = default 7153 virtual std::string translateActiveException() const = 0; 7154 }; 7155 7156} // namespace Catch 7157 7158#endif // CATCH_INTERFACES_EXCEPTION_HPP_INCLUDED 7159 7160#include <exception> 7161 7162namespace Catch { 7163 namespace Detail { 7164 void registerTranslatorImpl( 7165 Detail::unique_ptr<IExceptionTranslator>&& translator ); 7166 } 7167 7168 class ExceptionTranslatorRegistrar { 7169 template<typename T> 7170 class ExceptionTranslator : public IExceptionTranslator { 7171 public: 7172 7173 ExceptionTranslator( std::string(*translateFunction)( T const& ) ) 7174 : m_translateFunction( translateFunction ) 7175 {} 7176 7177 std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override { 7178#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 7179 try { 7180 if( it == itEnd ) 7181 std::rethrow_exception(std::current_exception()); 7182 else 7183 return (*it)->translate( it+1, itEnd ); 7184 } 7185 catch( T const& ex ) { 7186 return m_translateFunction( ex ); 7187 } 7188#else 7189 return "You should never get here!"; 7190#endif 7191 } 7192 7193 protected: 7194 std::string(*m_translateFunction)( T const& ); 7195 }; 7196 7197 public: 7198 template<typename T> 7199 ExceptionTranslatorRegistrar( std::string(*translateFunction)( T const& ) ) { 7200 Detail::registerTranslatorImpl( 7201 Detail::make_unique<ExceptionTranslator<T>>( 7202 translateFunction ) ); 7203 } 7204 }; 7205 7206} // namespace Catch 7207 7208/////////////////////////////////////////////////////////////////////////////// 7209#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \ 7210 static std::string translatorName( signature ); \ 7211 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 7212 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 7213 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); } \ 7214 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 7215 static std::string translatorName( signature ) 7216 7217#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) 7218 7219#if defined(CATCH_CONFIG_DISABLE) 7220 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( translatorName, signature) \ 7221 static std::string translatorName( signature ) 7222#endif 7223 7224 7225// This macro is always prefixed 7226#if !defined(CATCH_CONFIG_DISABLE) 7227#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) 7228#else 7229#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) 7230#endif 7231 7232 7233#endif // CATCH_TRANSLATE_EXCEPTION_HPP_INCLUDED 7234 7235 7236#ifndef CATCH_VERSION_HPP_INCLUDED 7237#define CATCH_VERSION_HPP_INCLUDED 7238 7239#include <iosfwd> 7240 7241namespace Catch { 7242 7243 // Versioning information 7244 struct Version { 7245 Version( Version const& ) = delete; 7246 Version& operator=( Version const& ) = delete; 7247 Version( unsigned int _majorVersion, 7248 unsigned int _minorVersion, 7249 unsigned int _patchNumber, 7250 char const * const _branchName, 7251 unsigned int _buildNumber ); 7252 7253 unsigned int const majorVersion; 7254 unsigned int const minorVersion; 7255 unsigned int const patchNumber; 7256 7257 // buildNumber is only used if branchName is not null 7258 char const * const branchName; 7259 unsigned int const buildNumber; 7260 7261 friend std::ostream& operator << ( std::ostream& os, Version const& version ); 7262 }; 7263 7264 Version const& libraryVersion(); 7265} 7266 7267#endif // CATCH_VERSION_HPP_INCLUDED 7268 7269 7270#ifndef CATCH_VERSION_MACROS_HPP_INCLUDED 7271#define CATCH_VERSION_MACROS_HPP_INCLUDED 7272 7273#define CATCH_VERSION_MAJOR 3 7274#define CATCH_VERSION_MINOR 6 7275#define CATCH_VERSION_PATCH 0 7276 7277#endif // CATCH_VERSION_MACROS_HPP_INCLUDED 7278 7279 7280/** \file 7281 * This is a convenience header for Catch2's Generator support. It includes 7282 * **all** of Catch2 headers related to generators. 7283 * 7284 * Generally the Catch2 users should use specific includes they need, 7285 * but this header can be used instead for ease-of-experimentation, or 7286 * just plain convenience, at the cost of (significantly) increased 7287 * compilation times. 7288 * 7289 * When a new header is added to either the `generators` folder, 7290 * or to the corresponding internal subfolder, it should be added here. 7291 */ 7292 7293#ifndef CATCH_GENERATORS_ALL_HPP_INCLUDED 7294#define CATCH_GENERATORS_ALL_HPP_INCLUDED 7295 7296 7297 7298#ifndef CATCH_GENERATOR_EXCEPTION_HPP_INCLUDED 7299#define CATCH_GENERATOR_EXCEPTION_HPP_INCLUDED 7300 7301#include <exception> 7302 7303namespace Catch { 7304 7305 // Exception type to be thrown when a Generator runs into an error, 7306 // e.g. it cannot initialize the first return value based on 7307 // runtime information 7308 class GeneratorException : public std::exception { 7309 const char* const m_msg = ""; 7310 7311 public: 7312 GeneratorException(const char* msg): 7313 m_msg(msg) 7314 {} 7315 7316 const char* what() const noexcept override final; 7317 }; 7318 7319} // end namespace Catch 7320 7321#endif // CATCH_GENERATOR_EXCEPTION_HPP_INCLUDED 7322 7323 7324#ifndef CATCH_GENERATORS_HPP_INCLUDED 7325#define CATCH_GENERATORS_HPP_INCLUDED 7326 7327 7328 7329#ifndef CATCH_INTERFACES_GENERATORTRACKER_HPP_INCLUDED 7330#define CATCH_INTERFACES_GENERATORTRACKER_HPP_INCLUDED 7331 7332 7333#include <string> 7334 7335namespace Catch { 7336 7337 namespace Generators { 7338 class GeneratorUntypedBase { 7339 // Caches result from `toStringImpl`, assume that when it is an 7340 // empty string, the cache is invalidated. 7341 mutable std::string m_stringReprCache; 7342 7343 // Counts based on `next` returning true 7344 std::size_t m_currentElementIndex = 0; 7345 7346 /** 7347 * Attempts to move the generator to the next element 7348 * 7349 * Returns true iff the move succeeded (and a valid element 7350 * can be retrieved). 7351 */ 7352 virtual bool next() = 0; 7353 7354 //! Customization point for `currentElementAsString` 7355 virtual std::string stringifyImpl() const = 0; 7356 7357 public: 7358 GeneratorUntypedBase() = default; 7359 // Generation of copy ops is deprecated (and Clang will complain) 7360 // if there is a user destructor defined 7361 GeneratorUntypedBase(GeneratorUntypedBase const&) = default; 7362 GeneratorUntypedBase& operator=(GeneratorUntypedBase const&) = default; 7363 7364 virtual ~GeneratorUntypedBase(); // = default; 7365 7366 /** 7367 * Attempts to move the generator to the next element 7368 * 7369 * Serves as a non-virtual interface to `next`, so that the 7370 * top level interface can provide sanity checking and shared 7371 * features. 7372 * 7373 * As with `next`, returns true iff the move succeeded and 7374 * the generator has new valid element to provide. 7375 */ 7376 bool countedNext(); 7377 7378 std::size_t currentElementIndex() const { return m_currentElementIndex; } 7379 7380 /** 7381 * Returns generator's current element as user-friendly string. 7382 * 7383 * By default returns string equivalent to calling 7384 * `Catch::Detail::stringify` on the current element, but generators 7385 * can customize their implementation as needed. 7386 * 7387 * Not thread-safe due to internal caching. 7388 * 7389 * The returned ref is valid only until the generator instance 7390 * is destructed, or it moves onto the next element, whichever 7391 * comes first. 7392 */ 7393 StringRef currentElementAsString() const; 7394 }; 7395 using GeneratorBasePtr = Catch::Detail::unique_ptr<GeneratorUntypedBase>; 7396 7397 } // namespace Generators 7398 7399 class IGeneratorTracker { 7400 public: 7401 virtual ~IGeneratorTracker(); // = default; 7402 virtual auto hasGenerator() const -> bool = 0; 7403 virtual auto getGenerator() const -> Generators::GeneratorBasePtr const& = 0; 7404 virtual void setGenerator( Generators::GeneratorBasePtr&& generator ) = 0; 7405 }; 7406 7407} // namespace Catch 7408 7409#endif // CATCH_INTERFACES_GENERATORTRACKER_HPP_INCLUDED 7410 7411#include <vector> 7412#include <tuple> 7413 7414namespace Catch { 7415 7416namespace Generators { 7417 7418namespace Detail { 7419 7420 //! Throws GeneratorException with the provided message 7421 [[noreturn]] 7422 void throw_generator_exception(char const * msg); 7423 7424} // end namespace detail 7425 7426 template<typename T> 7427 class IGenerator : public GeneratorUntypedBase { 7428 std::string stringifyImpl() const override { 7429 return ::Catch::Detail::stringify( get() ); 7430 } 7431 7432 public: 7433 // Returns the current element of the generator 7434 // 7435 // \Precondition The generator is either freshly constructed, 7436 // or the last call to `next()` returned true 7437 virtual T const& get() const = 0; 7438 using type = T; 7439 }; 7440 7441 template <typename T> 7442 using GeneratorPtr = Catch::Detail::unique_ptr<IGenerator<T>>; 7443 7444 template <typename T> 7445 class GeneratorWrapper final { 7446 GeneratorPtr<T> m_generator; 7447 public: 7448 //! Takes ownership of the passed pointer. 7449 GeneratorWrapper(IGenerator<T>* generator): 7450 m_generator(generator) {} 7451 GeneratorWrapper(GeneratorPtr<T> generator): 7452 m_generator(CATCH_MOVE(generator)) {} 7453 7454 T const& get() const { 7455 return m_generator->get(); 7456 } 7457 bool next() { 7458 return m_generator->countedNext(); 7459 } 7460 }; 7461 7462 7463 template<typename T> 7464 class SingleValueGenerator final : public IGenerator<T> { 7465 T m_value; 7466 public: 7467 SingleValueGenerator(T const& value) : 7468 m_value(value) 7469 {} 7470 SingleValueGenerator(T&& value): 7471 m_value(CATCH_MOVE(value)) 7472 {} 7473 7474 T const& get() const override { 7475 return m_value; 7476 } 7477 bool next() override { 7478 return false; 7479 } 7480 }; 7481 7482 template<typename T> 7483 class FixedValuesGenerator final : public IGenerator<T> { 7484 static_assert(!std::is_same<T, bool>::value, 7485 "FixedValuesGenerator does not support bools because of std::vector<bool>" 7486 "specialization, use SingleValue Generator instead."); 7487 std::vector<T> m_values; 7488 size_t m_idx = 0; 7489 public: 7490 FixedValuesGenerator( std::initializer_list<T> values ) : m_values( values ) {} 7491 7492 T const& get() const override { 7493 return m_values[m_idx]; 7494 } 7495 bool next() override { 7496 ++m_idx; 7497 return m_idx < m_values.size(); 7498 } 7499 }; 7500 7501 template <typename T, typename DecayedT = std::decay_t<T>> 7502 GeneratorWrapper<DecayedT> value( T&& value ) { 7503 return GeneratorWrapper<DecayedT>( 7504 Catch::Detail::make_unique<SingleValueGenerator<DecayedT>>( 7505 CATCH_FORWARD( value ) ) ); 7506 } 7507 template <typename T> 7508 GeneratorWrapper<T> values(std::initializer_list<T> values) { 7509 return GeneratorWrapper<T>(Catch::Detail::make_unique<FixedValuesGenerator<T>>(values)); 7510 } 7511 7512 template<typename T> 7513 class Generators : public IGenerator<T> { 7514 std::vector<GeneratorWrapper<T>> m_generators; 7515 size_t m_current = 0; 7516 7517 void add_generator( GeneratorWrapper<T>&& generator ) { 7518 m_generators.emplace_back( CATCH_MOVE( generator ) ); 7519 } 7520 void add_generator( T const& val ) { 7521 m_generators.emplace_back( value( val ) ); 7522 } 7523 void add_generator( T&& val ) { 7524 m_generators.emplace_back( value( CATCH_MOVE( val ) ) ); 7525 } 7526 template <typename U> 7527 std::enable_if_t<!std::is_same<std::decay_t<U>, T>::value> 7528 add_generator( U&& val ) { 7529 add_generator( T( CATCH_FORWARD( val ) ) ); 7530 } 7531 7532 template <typename U> void add_generators( U&& valueOrGenerator ) { 7533 add_generator( CATCH_FORWARD( valueOrGenerator ) ); 7534 } 7535 7536 template <typename U, typename... Gs> 7537 void add_generators( U&& valueOrGenerator, Gs&&... moreGenerators ) { 7538 add_generator( CATCH_FORWARD( valueOrGenerator ) ); 7539 add_generators( CATCH_FORWARD( moreGenerators )... ); 7540 } 7541 7542 public: 7543 template <typename... Gs> 7544 Generators(Gs &&... moreGenerators) { 7545 m_generators.reserve(sizeof...(Gs)); 7546 add_generators(CATCH_FORWARD(moreGenerators)...); 7547 } 7548 7549 T const& get() const override { 7550 return m_generators[m_current].get(); 7551 } 7552 7553 bool next() override { 7554 if (m_current >= m_generators.size()) { 7555 return false; 7556 } 7557 const bool current_status = m_generators[m_current].next(); 7558 if (!current_status) { 7559 ++m_current; 7560 } 7561 return m_current < m_generators.size(); 7562 } 7563 }; 7564 7565 7566 template <typename... Ts> 7567 GeneratorWrapper<std::tuple<std::decay_t<Ts>...>> 7568 table( std::initializer_list<std::tuple<std::decay_t<Ts>...>> tuples ) { 7569 return values<std::tuple<Ts...>>( tuples ); 7570 } 7571 7572 // Tag type to signal that a generator sequence should convert arguments to a specific type 7573 template <typename T> 7574 struct as {}; 7575 7576 template<typename T, typename... Gs> 7577 auto makeGenerators( GeneratorWrapper<T>&& generator, Gs &&... moreGenerators ) -> Generators<T> { 7578 return Generators<T>(CATCH_MOVE(generator), CATCH_FORWARD(moreGenerators)...); 7579 } 7580 template<typename T> 7581 auto makeGenerators( GeneratorWrapper<T>&& generator ) -> Generators<T> { 7582 return Generators<T>(CATCH_MOVE(generator)); 7583 } 7584 template<typename T, typename... Gs> 7585 auto makeGenerators( T&& val, Gs &&... moreGenerators ) -> Generators<std::decay_t<T>> { 7586 return makeGenerators( value( CATCH_FORWARD( val ) ), CATCH_FORWARD( moreGenerators )... ); 7587 } 7588 template<typename T, typename U, typename... Gs> 7589 auto makeGenerators( as<T>, U&& val, Gs &&... moreGenerators ) -> Generators<T> { 7590 return makeGenerators( value( T( CATCH_FORWARD( val ) ) ), CATCH_FORWARD( moreGenerators )... ); 7591 } 7592 7593 IGeneratorTracker* acquireGeneratorTracker( StringRef generatorName, 7594 SourceLineInfo const& lineInfo ); 7595 IGeneratorTracker* createGeneratorTracker( StringRef generatorName, 7596 SourceLineInfo lineInfo, 7597 GeneratorBasePtr&& generator ); 7598 7599 template<typename L> 7600 auto generate( StringRef generatorName, SourceLineInfo const& lineInfo, L const& generatorExpression ) -> typename decltype(generatorExpression())::type { 7601 using UnderlyingType = typename decltype(generatorExpression())::type; 7602 7603 IGeneratorTracker* tracker = acquireGeneratorTracker( generatorName, lineInfo ); 7604 // Creation of tracker is delayed after generator creation, so 7605 // that constructing generator can fail without breaking everything. 7606 if (!tracker) { 7607 tracker = createGeneratorTracker( 7608 generatorName, 7609 lineInfo, 7610 Catch::Detail::make_unique<Generators<UnderlyingType>>( 7611 generatorExpression() ) ); 7612 } 7613 7614 auto const& generator = static_cast<IGenerator<UnderlyingType> const&>( *tracker->getGenerator() ); 7615 return generator.get(); 7616 } 7617 7618} // namespace Generators 7619} // namespace Catch 7620 7621#define CATCH_INTERNAL_GENERATOR_STRINGIZE_IMPL( ... ) #__VA_ARGS__##_catch_sr 7622#define CATCH_INTERNAL_GENERATOR_STRINGIZE(...) CATCH_INTERNAL_GENERATOR_STRINGIZE_IMPL(__VA_ARGS__) 7623 7624#define GENERATE( ... ) \ 7625 Catch::Generators::generate( CATCH_INTERNAL_GENERATOR_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \ 7626 CATCH_INTERNAL_LINEINFO, \ 7627 [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace) 7628#define GENERATE_COPY( ... ) \ 7629 Catch::Generators::generate( CATCH_INTERNAL_GENERATOR_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \ 7630 CATCH_INTERNAL_LINEINFO, \ 7631 [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace) 7632#define GENERATE_REF( ... ) \ 7633 Catch::Generators::generate( CATCH_INTERNAL_GENERATOR_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \ 7634 CATCH_INTERNAL_LINEINFO, \ 7635 [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace) 7636 7637#endif // CATCH_GENERATORS_HPP_INCLUDED 7638 7639 7640#ifndef CATCH_GENERATORS_ADAPTERS_HPP_INCLUDED 7641#define CATCH_GENERATORS_ADAPTERS_HPP_INCLUDED 7642 7643 7644#include <cassert> 7645 7646namespace Catch { 7647namespace Generators { 7648 7649 template <typename T> 7650 class TakeGenerator final : public IGenerator<T> { 7651 GeneratorWrapper<T> m_generator; 7652 size_t m_returned = 0; 7653 size_t m_target; 7654 public: 7655 TakeGenerator(size_t target, GeneratorWrapper<T>&& generator): 7656 m_generator(CATCH_MOVE(generator)), 7657 m_target(target) 7658 { 7659 assert(target != 0 && "Empty generators are not allowed"); 7660 } 7661 T const& get() const override { 7662 return m_generator.get(); 7663 } 7664 bool next() override { 7665 ++m_returned; 7666 if (m_returned >= m_target) { 7667 return false; 7668 } 7669 7670 const auto success = m_generator.next(); 7671 // If the underlying generator does not contain enough values 7672 // then we cut short as well 7673 if (!success) { 7674 m_returned = m_target; 7675 } 7676 return success; 7677 } 7678 }; 7679 7680 template <typename T> 7681 GeneratorWrapper<T> take(size_t target, GeneratorWrapper<T>&& generator) { 7682 return GeneratorWrapper<T>(Catch::Detail::make_unique<TakeGenerator<T>>(target, CATCH_MOVE(generator))); 7683 } 7684 7685 7686 template <typename T, typename Predicate> 7687 class FilterGenerator final : public IGenerator<T> { 7688 GeneratorWrapper<T> m_generator; 7689 Predicate m_predicate; 7690 public: 7691 template <typename P = Predicate> 7692 FilterGenerator(P&& pred, GeneratorWrapper<T>&& generator): 7693 m_generator(CATCH_MOVE(generator)), 7694 m_predicate(CATCH_FORWARD(pred)) 7695 { 7696 if (!m_predicate(m_generator.get())) { 7697 // It might happen that there are no values that pass the 7698 // filter. In that case we throw an exception. 7699 auto has_initial_value = next(); 7700 if (!has_initial_value) { 7701 Detail::throw_generator_exception("No valid value found in filtered generator"); 7702 } 7703 } 7704 } 7705 7706 T const& get() const override { 7707 return m_generator.get(); 7708 } 7709 7710 bool next() override { 7711 bool success = m_generator.next(); 7712 if (!success) { 7713 return false; 7714 } 7715 while (!m_predicate(m_generator.get()) && (success = m_generator.next()) == true); 7716 return success; 7717 } 7718 }; 7719 7720 7721 template <typename T, typename Predicate> 7722 GeneratorWrapper<T> filter(Predicate&& pred, GeneratorWrapper<T>&& generator) { 7723 return GeneratorWrapper<T>(Catch::Detail::make_unique<FilterGenerator<T, Predicate>>(CATCH_FORWARD(pred), CATCH_MOVE(generator))); 7724 } 7725 7726 template <typename T> 7727 class RepeatGenerator final : public IGenerator<T> { 7728 static_assert(!std::is_same<T, bool>::value, 7729 "RepeatGenerator currently does not support bools" 7730 "because of std::vector<bool> specialization"); 7731 GeneratorWrapper<T> m_generator; 7732 mutable std::vector<T> m_returned; 7733 size_t m_target_repeats; 7734 size_t m_current_repeat = 0; 7735 size_t m_repeat_index = 0; 7736 public: 7737 RepeatGenerator(size_t repeats, GeneratorWrapper<T>&& generator): 7738 m_generator(CATCH_MOVE(generator)), 7739 m_target_repeats(repeats) 7740 { 7741 assert(m_target_repeats > 0 && "Repeat generator must repeat at least once"); 7742 } 7743 7744 T const& get() const override { 7745 if (m_current_repeat == 0) { 7746 m_returned.push_back(m_generator.get()); 7747 return m_returned.back(); 7748 } 7749 return m_returned[m_repeat_index]; 7750 } 7751 7752 bool next() override { 7753 // There are 2 basic cases: 7754 // 1) We are still reading the generator 7755 // 2) We are reading our own cache 7756 7757 // In the first case, we need to poke the underlying generator. 7758 // If it happily moves, we are left in that state, otherwise it is time to start reading from our cache 7759 if (m_current_repeat == 0) { 7760 const auto success = m_generator.next(); 7761 if (!success) { 7762 ++m_current_repeat; 7763 } 7764 return m_current_repeat < m_target_repeats; 7765 } 7766 7767 // In the second case, we need to move indices forward and check that we haven't run up against the end 7768 ++m_repeat_index; 7769 if (m_repeat_index == m_returned.size()) { 7770 m_repeat_index = 0; 7771 ++m_current_repeat; 7772 } 7773 return m_current_repeat < m_target_repeats; 7774 } 7775 }; 7776 7777 template <typename T> 7778 GeneratorWrapper<T> repeat(size_t repeats, GeneratorWrapper<T>&& generator) { 7779 return GeneratorWrapper<T>(Catch::Detail::make_unique<RepeatGenerator<T>>(repeats, CATCH_MOVE(generator))); 7780 } 7781 7782 template <typename T, typename U, typename Func> 7783 class MapGenerator final : public IGenerator<T> { 7784 // TBD: provide static assert for mapping function, for friendly error message 7785 GeneratorWrapper<U> m_generator; 7786 Func m_function; 7787 // To avoid returning dangling reference, we have to save the values 7788 T m_cache; 7789 public: 7790 template <typename F2 = Func> 7791 MapGenerator(F2&& function, GeneratorWrapper<U>&& generator) : 7792 m_generator(CATCH_MOVE(generator)), 7793 m_function(CATCH_FORWARD(function)), 7794 m_cache(m_function(m_generator.get())) 7795 {} 7796 7797 T const& get() const override { 7798 return m_cache; 7799 } 7800 bool next() override { 7801 const auto success = m_generator.next(); 7802 if (success) { 7803 m_cache = m_function(m_generator.get()); 7804 } 7805 return success; 7806 } 7807 }; 7808 7809 template <typename Func, typename U, typename T = FunctionReturnType<Func, U>> 7810 GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) { 7811 return GeneratorWrapper<T>( 7812 Catch::Detail::make_unique<MapGenerator<T, U, Func>>(CATCH_FORWARD(function), CATCH_MOVE(generator)) 7813 ); 7814 } 7815 7816 template <typename T, typename U, typename Func> 7817 GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) { 7818 return GeneratorWrapper<T>( 7819 Catch::Detail::make_unique<MapGenerator<T, U, Func>>(CATCH_FORWARD(function), CATCH_MOVE(generator)) 7820 ); 7821 } 7822 7823 template <typename T> 7824 class ChunkGenerator final : public IGenerator<std::vector<T>> { 7825 std::vector<T> m_chunk; 7826 size_t m_chunk_size; 7827 GeneratorWrapper<T> m_generator; 7828 bool m_used_up = false; 7829 public: 7830 ChunkGenerator(size_t size, GeneratorWrapper<T> generator) : 7831 m_chunk_size(size), m_generator(CATCH_MOVE(generator)) 7832 { 7833 m_chunk.reserve(m_chunk_size); 7834 if (m_chunk_size != 0) { 7835 m_chunk.push_back(m_generator.get()); 7836 for (size_t i = 1; i < m_chunk_size; ++i) { 7837 if (!m_generator.next()) { 7838 Detail::throw_generator_exception("Not enough values to initialize the first chunk"); 7839 } 7840 m_chunk.push_back(m_generator.get()); 7841 } 7842 } 7843 } 7844 std::vector<T> const& get() const override { 7845 return m_chunk; 7846 } 7847 bool next() override { 7848 m_chunk.clear(); 7849 for (size_t idx = 0; idx < m_chunk_size; ++idx) { 7850 if (!m_generator.next()) { 7851 return false; 7852 } 7853 m_chunk.push_back(m_generator.get()); 7854 } 7855 return true; 7856 } 7857 }; 7858 7859 template <typename T> 7860 GeneratorWrapper<std::vector<T>> chunk(size_t size, GeneratorWrapper<T>&& generator) { 7861 return GeneratorWrapper<std::vector<T>>( 7862 Catch::Detail::make_unique<ChunkGenerator<T>>(size, CATCH_MOVE(generator)) 7863 ); 7864 } 7865 7866} // namespace Generators 7867} // namespace Catch 7868 7869 7870#endif // CATCH_GENERATORS_ADAPTERS_HPP_INCLUDED 7871 7872 7873#ifndef CATCH_GENERATORS_RANDOM_HPP_INCLUDED 7874#define CATCH_GENERATORS_RANDOM_HPP_INCLUDED 7875 7876 7877 7878#ifndef CATCH_RANDOM_NUMBER_GENERATOR_HPP_INCLUDED 7879#define CATCH_RANDOM_NUMBER_GENERATOR_HPP_INCLUDED 7880 7881#include <cstdint> 7882 7883namespace Catch { 7884 7885 // This is a simple implementation of C++11 Uniform Random Number 7886 // Generator. It does not provide all operators, because Catch2 7887 // does not use it, but it should behave as expected inside stdlib's 7888 // distributions. 7889 // The implementation is based on the PCG family (http://pcg-random.org) 7890 class SimplePcg32 { 7891 using state_type = std::uint64_t; 7892 public: 7893 using result_type = std::uint32_t; 7894 static constexpr result_type (min)() { 7895 return 0; 7896 } 7897 static constexpr result_type (max)() { 7898 return static_cast<result_type>(-1); 7899 } 7900 7901 // Provide some default initial state for the default constructor 7902 SimplePcg32():SimplePcg32(0xed743cc4U) {} 7903 7904 explicit SimplePcg32(result_type seed_); 7905 7906 void seed(result_type seed_); 7907 void discard(uint64_t skip); 7908 7909 result_type operator()(); 7910 7911 private: 7912 friend bool operator==(SimplePcg32 const& lhs, SimplePcg32 const& rhs); 7913 friend bool operator!=(SimplePcg32 const& lhs, SimplePcg32 const& rhs); 7914 7915 // In theory we also need operator<< and operator>> 7916 // In practice we do not use them, so we will skip them for now 7917 7918 7919 std::uint64_t m_state; 7920 // This part of the state determines which "stream" of the numbers 7921 // is chosen -- we take it as a constant for Catch2, so we only 7922 // need to deal with seeding the main state. 7923 // Picked by reading 8 bytes from `/dev/random` :-) 7924 static const std::uint64_t s_inc = (0x13ed0cc53f939476ULL << 1ULL) | 1ULL; 7925 }; 7926 7927} // end namespace Catch 7928 7929#endif // CATCH_RANDOM_NUMBER_GENERATOR_HPP_INCLUDED 7930 7931 7932 7933#ifndef CATCH_UNIFORM_INTEGER_DISTRIBUTION_HPP_INCLUDED 7934#define CATCH_UNIFORM_INTEGER_DISTRIBUTION_HPP_INCLUDED 7935 7936 7937 7938 7939#ifndef CATCH_RANDOM_INTEGER_HELPERS_HPP_INCLUDED 7940#define CATCH_RANDOM_INTEGER_HELPERS_HPP_INCLUDED 7941 7942#include <climits> 7943#include <cstddef> 7944#include <cstdint> 7945#include <type_traits> 7946 7947// Note: We use the usual enable-disable-autodetect dance here even though 7948// we do not support these in CMake configuration options (yet?). 7949// It is highly unlikely that we will need to make these actually 7950// user-configurable, but this will make it simpler if weend up needing 7951// it, and it provides an escape hatch to the users who need it. 7952#if defined( __SIZEOF_INT128__ ) 7953# define CATCH_CONFIG_INTERNAL_UINT128 7954// Unlike GCC, MSVC does not polyfill umul as mulh + mul pair on ARM machines. 7955// Currently we do not bother doing this ourselves, but we could if it became 7956// important for perf. 7957#elif defined( _MSC_VER ) && defined( _M_X64 ) 7958# define CATCH_CONFIG_INTERNAL_MSVC_UMUL128 7959#endif 7960 7961#if defined( CATCH_CONFIG_INTERNAL_UINT128 ) && \ 7962 !defined( CATCH_CONFIG_NO_UINT128 ) && \ 7963 !defined( CATCH_CONFIG_UINT128 ) 7964#define CATCH_CONFIG_UINT128 7965#endif 7966 7967#if defined( CATCH_CONFIG_INTERNAL_MSVC_UMUL128 ) && \ 7968 !defined( CATCH_CONFIG_NO_MSVC_UMUL128 ) && \ 7969 !defined( CATCH_CONFIG_MSVC_UMUL128 ) 7970# define CATCH_CONFIG_MSVC_UMUL128 7971# include <intrin.h> 7972#endif 7973 7974 7975namespace Catch { 7976 namespace Detail { 7977 7978 template <std::size_t> 7979 struct SizedUnsignedType; 7980#define SizedUnsignedTypeHelper( TYPE ) \ 7981 template <> \ 7982 struct SizedUnsignedType<sizeof( TYPE )> { \ 7983 using type = TYPE; \ 7984 } 7985 7986 SizedUnsignedTypeHelper( std::uint8_t ); 7987 SizedUnsignedTypeHelper( std::uint16_t ); 7988 SizedUnsignedTypeHelper( std::uint32_t ); 7989 SizedUnsignedTypeHelper( std::uint64_t ); 7990#undef SizedUnsignedTypeHelper 7991 7992 template <std::size_t sz> 7993 using SizedUnsignedType_t = typename SizedUnsignedType<sz>::type; 7994 7995 template <typename T> 7996 using DoubleWidthUnsignedType_t = SizedUnsignedType_t<2 * sizeof( T )>; 7997 7998 template <typename T> 7999 struct ExtendedMultResult { 8000 T upper; 8001 T lower; 8002 bool operator==( ExtendedMultResult const& rhs ) const { 8003 return upper == rhs.upper && lower == rhs.lower; 8004 } 8005 }; 8006 8007 /** 8008 * Returns 128 bit result of lhs * rhs using portable C++ code 8009 * 8010 * This implementation is almost twice as fast as naive long multiplication, 8011 * and unlike intrinsic-based approach, it supports constexpr evaluation. 8012 */ 8013 constexpr ExtendedMultResult<std::uint64_t> 8014 extendedMultPortable(std::uint64_t lhs, std::uint64_t rhs) { 8015#define CarryBits( x ) ( x >> 32 ) 8016#define Digits( x ) ( x & 0xFF'FF'FF'FF ) 8017 std::uint64_t lhs_low = Digits( lhs ); 8018 std::uint64_t rhs_low = Digits( rhs ); 8019 std::uint64_t low_low = ( lhs_low * rhs_low ); 8020 std::uint64_t high_high = CarryBits( lhs ) * CarryBits( rhs ); 8021 8022 // We add in carry bits from low-low already 8023 std::uint64_t high_low = 8024 ( CarryBits( lhs ) * rhs_low ) + CarryBits( low_low ); 8025 // Note that we can add only low bits from high_low, to avoid 8026 // overflow with large inputs 8027 std::uint64_t low_high = 8028 ( lhs_low * CarryBits( rhs ) ) + Digits( high_low ); 8029 8030 return { high_high + CarryBits( high_low ) + CarryBits( low_high ), 8031 ( low_high << 32 ) | Digits( low_low ) }; 8032#undef CarryBits 8033#undef Digits 8034 } 8035 8036 //! Returns 128 bit result of lhs * rhs 8037 inline ExtendedMultResult<std::uint64_t> 8038 extendedMult( std::uint64_t lhs, std::uint64_t rhs ) { 8039#if defined( CATCH_CONFIG_UINT128 ) 8040 auto result = __uint128_t( lhs ) * __uint128_t( rhs ); 8041 return { static_cast<std::uint64_t>( result >> 64 ), 8042 static_cast<std::uint64_t>( result ) }; 8043#elif defined( CATCH_CONFIG_MSVC_UMUL128 ) 8044 std::uint64_t high; 8045 std::uint64_t low = _umul128( lhs, rhs, &high ); 8046 return { high, low }; 8047#else 8048 return extendedMultPortable( lhs, rhs ); 8049#endif 8050 } 8051 8052 8053 template <typename UInt> 8054 constexpr ExtendedMultResult<UInt> extendedMult( UInt lhs, UInt rhs ) { 8055 static_assert( std::is_unsigned<UInt>::value, 8056 "extendedMult can only handle unsigned integers" ); 8057 static_assert( sizeof( UInt ) < sizeof( std::uint64_t ), 8058 "Generic extendedMult can only handle types smaller " 8059 "than uint64_t" ); 8060 using WideType = DoubleWidthUnsignedType_t<UInt>; 8061 8062 auto result = WideType( lhs ) * WideType( rhs ); 8063 return { 8064 static_cast<UInt>( result >> ( CHAR_BIT * sizeof( UInt ) ) ), 8065 static_cast<UInt>( result & UInt( -1 ) ) }; 8066 } 8067 8068 8069 template <typename TargetType, 8070 typename Generator> 8071 std::enable_if_t<sizeof(typename Generator::result_type) >= sizeof(TargetType), 8072 TargetType> fillBitsFrom(Generator& gen) { 8073 using gresult_type = typename Generator::result_type; 8074 static_assert( std::is_unsigned<TargetType>::value, "Only unsigned integers are supported" ); 8075 static_assert( Generator::min() == 0 && 8076 Generator::max() == static_cast<gresult_type>( -1 ), 8077 "Generator must be able to output all numbers in its result type (effectively it must be a random bit generator)" ); 8078 8079 // We want to return the top bits from a generator, as they are 8080 // usually considered higher quality. 8081 constexpr auto generated_bits = sizeof( gresult_type ) * CHAR_BIT; 8082 constexpr auto return_bits = sizeof( TargetType ) * CHAR_BIT; 8083 8084 return static_cast<TargetType>( gen() >> 8085 ( generated_bits - return_bits) ); 8086 } 8087 8088 template <typename TargetType, 8089 typename Generator> 8090 std::enable_if_t<sizeof(typename Generator::result_type) < sizeof(TargetType), 8091 TargetType> fillBitsFrom(Generator& gen) { 8092 using gresult_type = typename Generator::result_type; 8093 static_assert( std::is_unsigned<TargetType>::value, 8094 "Only unsigned integers are supported" ); 8095 static_assert( Generator::min() == 0 && 8096 Generator::max() == static_cast<gresult_type>( -1 ), 8097 "Generator must be able to output all numbers in its result type (effectively it must be a random bit generator)" ); 8098 8099 constexpr auto generated_bits = sizeof( gresult_type ) * CHAR_BIT; 8100 constexpr auto return_bits = sizeof( TargetType ) * CHAR_BIT; 8101 std::size_t filled_bits = 0; 8102 TargetType ret = 0; 8103 do { 8104 ret <<= generated_bits; 8105 ret |= gen(); 8106 filled_bits += generated_bits; 8107 } while ( filled_bits < return_bits ); 8108 8109 return ret; 8110 } 8111 8112 /* 8113 * Transposes numbers into unsigned type while keeping their ordering 8114 * 8115 * This means that signed types are changed so that the ordering is 8116 * [INT_MIN, ..., -1, 0, ..., INT_MAX], rather than order we would 8117 * get by simple casting ([0, ..., INT_MAX, INT_MIN, ..., -1]) 8118 */ 8119 template <typename OriginalType, typename UnsignedType> 8120 std::enable_if_t<std::is_signed<OriginalType>::value, UnsignedType> 8121 transposeToNaturalOrder( UnsignedType in ) { 8122 static_assert( 8123 sizeof( OriginalType ) == sizeof( UnsignedType ), 8124 "reordering requires the same sized types on both sides" ); 8125 static_assert( std::is_unsigned<UnsignedType>::value, 8126 "Input type must be unsigned" ); 8127 // Assuming 2s complement (standardized in current C++), the 8128 // positive and negative numbers are already internally ordered, 8129 // and their difference is in the top bit. Swapping it orders 8130 // them the desired way. 8131 constexpr auto highest_bit = 8132 UnsignedType( 1 ) << ( sizeof( UnsignedType ) * CHAR_BIT - 1 ); 8133 return static_cast<UnsignedType>( in ^ highest_bit ); 8134 } 8135 8136 8137 8138 template <typename OriginalType, 8139 typename UnsignedType> 8140 std::enable_if_t<std::is_unsigned<OriginalType>::value, UnsignedType> 8141 transposeToNaturalOrder(UnsignedType in) { 8142 static_assert( 8143 sizeof( OriginalType ) == sizeof( UnsignedType ), 8144 "reordering requires the same sized types on both sides" ); 8145 static_assert( std::is_unsigned<UnsignedType>::value, "Input type must be unsigned" ); 8146 // No reordering is needed for unsigned -> unsigned 8147 return in; 8148 } 8149 } // namespace Detail 8150} // namespace Catch 8151 8152#endif // CATCH_RANDOM_INTEGER_HELPERS_HPP_INCLUDED 8153 8154namespace Catch { 8155 8156/** 8157 * Implementation of uniform distribution on integers. 8158 * 8159 * Unlike `std::uniform_int_distribution`, this implementation supports 8160 * various 1 byte integral types, including bool (but you should not 8161 * actually use it for bools). 8162 * 8163 * The underlying algorithm is based on the one described in "Fast Random 8164 * Integer Generation in an Interval" by Daniel Lemire, but has been 8165 * optimized under the assumption of reuse of the same distribution object. 8166 */ 8167template <typename IntegerType> 8168class uniform_integer_distribution { 8169 static_assert(std::is_integral<IntegerType>::value, "..."); 8170 8171 using UnsignedIntegerType = Detail::SizedUnsignedType_t<sizeof(IntegerType)>; 8172 8173 // Only the left bound is stored, and we store it converted to its 8174 // unsigned image. This avoids having to do the conversions inside 8175 // the operator(), at the cost of having to do the conversion in 8176 // the a() getter. The right bound is only needed in the b() getter, 8177 // so we recompute it there from other stored data. 8178 UnsignedIntegerType m_a; 8179 8180 // How many different values are there in [a, b]. a == b => 1, can be 0 for distribution over all values in the type. 8181 UnsignedIntegerType m_ab_distance; 8182 8183 // We hoisted this out of the main generation function. Technically, 8184 // this means that using this distribution will be slower than Lemire's 8185 // algorithm if this distribution instance will be used only few times, 8186 // but it will be faster if it is used many times. Since Catch2 uses 8187 // distributions only to implement random generators, we assume that each 8188 // distribution will be reused many times and this is an optimization. 8189 UnsignedIntegerType m_rejection_threshold = 0; 8190 8191 UnsignedIntegerType computeDistance(IntegerType a, IntegerType b) const { 8192 // This overflows and returns 0 if a == 0 and b == TYPE_MAX. 8193 // We handle that later when generating the number. 8194 return transposeTo(b) - transposeTo(a) + 1; 8195 } 8196 8197 static UnsignedIntegerType computeRejectionThreshold(UnsignedIntegerType ab_distance) { 8198 // distance == 0 means that we will return all possible values from 8199 // the type's range, and that we shouldn't reject anything. 8200 if ( ab_distance == 0 ) { return 0; } 8201 return ( ~ab_distance + 1 ) % ab_distance; 8202 } 8203 8204 static UnsignedIntegerType transposeTo(IntegerType in) { 8205 return Detail::transposeToNaturalOrder<IntegerType>( 8206 static_cast<UnsignedIntegerType>( in ) ); 8207 } 8208 static IntegerType transposeBack(UnsignedIntegerType in) { 8209 return static_cast<IntegerType>( 8210 Detail::transposeToNaturalOrder<IntegerType>(in) ); 8211 } 8212 8213public: 8214 using result_type = IntegerType; 8215 8216 uniform_integer_distribution( IntegerType a, IntegerType b ): 8217 m_a( transposeTo(a) ), 8218 m_ab_distance( computeDistance(a, b) ), 8219 m_rejection_threshold( computeRejectionThreshold(m_ab_distance) ) { 8220 assert( a <= b ); 8221 } 8222 8223 template <typename Generator> 8224 result_type operator()( Generator& g ) { 8225 // All possible values of result_type are valid. 8226 if ( m_ab_distance == 0 ) { 8227 return transposeBack( Detail::fillBitsFrom<UnsignedIntegerType>( g ) ); 8228 } 8229 8230 auto random_number = Detail::fillBitsFrom<UnsignedIntegerType>( g ); 8231 auto emul = Detail::extendedMult( random_number, m_ab_distance ); 8232 // Unlike Lemire's algorithm we skip the ab_distance check, since 8233 // we precomputed the rejection threshold, which is always tighter. 8234 while (emul.lower < m_rejection_threshold) { 8235 random_number = Detail::fillBitsFrom<UnsignedIntegerType>( g ); 8236 emul = Detail::extendedMult( random_number, m_ab_distance ); 8237 } 8238 8239 return transposeBack(m_a + emul.upper); 8240 } 8241 8242 result_type a() const { return transposeBack(m_a); } 8243 result_type b() const { return transposeBack(m_ab_distance + m_a - 1); } 8244}; 8245 8246} // end namespace Catch 8247 8248#endif // CATCH_UNIFORM_INTEGER_DISTRIBUTION_HPP_INCLUDED 8249 8250 8251 8252#ifndef CATCH_UNIFORM_FLOATING_POINT_DISTRIBUTION_HPP_INCLUDED 8253#define CATCH_UNIFORM_FLOATING_POINT_DISTRIBUTION_HPP_INCLUDED 8254 8255 8256 8257 8258#ifndef CATCH_RANDOM_FLOATING_POINT_HELPERS_HPP_INCLUDED 8259#define CATCH_RANDOM_FLOATING_POINT_HELPERS_HPP_INCLUDED 8260 8261 8262 8263#ifndef CATCH_POLYFILLS_HPP_INCLUDED 8264#define CATCH_POLYFILLS_HPP_INCLUDED 8265 8266namespace Catch { 8267 8268 bool isnan(float f); 8269 bool isnan(double d); 8270 8271 float nextafter(float x, float y); 8272 double nextafter(double x, double y); 8273 8274} 8275 8276#endif // CATCH_POLYFILLS_HPP_INCLUDED 8277 8278#include <cassert> 8279#include <cmath> 8280#include <cstdint> 8281#include <limits> 8282#include <type_traits> 8283 8284namespace Catch { 8285 8286 namespace Detail { 8287 /** 8288 * Returns the largest magnitude of 1-ULP distance inside the [a, b] range. 8289 * 8290 * Assumes `a < b`. 8291 */ 8292 template <typename FloatType> 8293 FloatType gamma(FloatType a, FloatType b) { 8294 static_assert( std::is_floating_point<FloatType>::value, 8295 "gamma returns the largest ULP magnitude within " 8296 "floating point range [a, b]. This only makes sense " 8297 "for floating point types" ); 8298 assert( a <= b ); 8299 8300 const auto gamma_up = Catch::nextafter( a, std::numeric_limits<FloatType>::infinity() ) - a; 8301 const auto gamma_down = b - Catch::nextafter( b, -std::numeric_limits<FloatType>::infinity() ); 8302 8303 return gamma_up < gamma_down ? gamma_down : gamma_up; 8304 } 8305 8306 template <typename FloatingPoint> 8307 struct DistanceTypePicker; 8308 template <> 8309 struct DistanceTypePicker<float> { 8310 using type = std::uint32_t; 8311 }; 8312 template <> 8313 struct DistanceTypePicker<double> { 8314 using type = std::uint64_t; 8315 }; 8316 8317 template <typename T> 8318 using DistanceType = typename DistanceTypePicker<T>::type; 8319 8320#if defined( __GNUC__ ) || defined( __clang__ ) 8321# pragma GCC diagnostic push 8322# pragma GCC diagnostic ignored "-Wfloat-equal" 8323#endif 8324 /** 8325 * Computes the number of equi-distant floats in [a, b] 8326 * 8327 * Since not every range can be split into equidistant floats 8328 * exactly, we actually compute ceil(b/distance - a/distance), 8329 * because in those cases we want to overcount. 8330 * 8331 * Uses modified Dekker's FastTwoSum algorithm to handle rounding. 8332 */ 8333 template <typename FloatType> 8334 DistanceType<FloatType> 8335 count_equidistant_floats( FloatType a, FloatType b, FloatType distance ) { 8336 assert( a <= b ); 8337 // We get distance as gamma for our uniform float distribution, 8338 // so this will round perfectly. 8339 const auto ag = a / distance; 8340 const auto bg = b / distance; 8341 8342 const auto s = bg - ag; 8343 const auto err = ( std::fabs( a ) <= std::fabs( b ) ) 8344 ? -ag - ( s - bg ) 8345 : bg - ( s + ag ); 8346 const auto ceil_s = static_cast<DistanceType<FloatType>>( std::ceil( s ) ); 8347 8348 return ( ceil_s != s ) ? ceil_s : ceil_s + ( err > 0 ); 8349 } 8350#if defined( __GNUC__ ) || defined( __clang__ ) 8351# pragma GCC diagnostic pop 8352#endif 8353 8354 } 8355 8356} // end namespace Catch 8357 8358#endif // CATCH_RANDOM_FLOATING_POINT_HELPERS_HPP_INCLUDED 8359 8360#include <cmath> 8361#include <type_traits> 8362 8363namespace Catch { 8364 8365 namespace Detail { 8366#if defined( __GNUC__ ) || defined( __clang__ ) 8367# pragma GCC diagnostic push 8368# pragma GCC diagnostic ignored "-Wfloat-equal" 8369#endif 8370 // The issue with overflow only happens with maximal ULP and HUGE 8371 // distance, e.g. when generating numbers in [-inf, inf] for given 8372 // type. So we only check for the largest possible ULP in the 8373 // type, and return something that does not overflow to inf in 1 mult. 8374 constexpr std::uint64_t calculate_max_steps_in_one_go(double gamma) { 8375 if ( gamma == 1.99584030953472e+292 ) { return 9007199254740991; } 8376 return static_cast<std::uint64_t>( -1 ); 8377 } 8378 constexpr std::uint32_t calculate_max_steps_in_one_go(float gamma) { 8379 if ( gamma == 2.028241e+31f ) { return 16777215; } 8380 return static_cast<std::uint32_t>( -1 ); 8381 } 8382#if defined( __GNUC__ ) || defined( __clang__ ) 8383# pragma GCC diagnostic pop 8384#endif 8385 } 8386 8387/** 8388 * Implementation of uniform distribution on floating point numbers. 8389 * 8390 * Note that we support only `float` and `double` types, because these 8391 * usually mean the same thing across different platform. `long double` 8392 * varies wildly by platform and thus we cannot provide reproducible 8393 * implementation. Also note that we don't implement all parts of 8394 * distribution per standard: this distribution is not serializable, nor 8395 * can the range be arbitrarily reset. 8396 * 8397 * The implementation also uses different approach than the one taken by 8398 * `std::uniform_real_distribution`, where instead of generating a number 8399 * between [0, 1) and then multiplying the range bounds with it, we first 8400 * split the [a, b] range into a set of equidistributed floating point 8401 * numbers, and then use uniform int distribution to pick which one to 8402 * return. 8403 * 8404 * This has the advantage of guaranteeing uniformity (the multiplication 8405 * method loses uniformity due to rounding when multiplying floats), except 8406 * for small non-uniformity at one side of the interval, where we have 8407 * to deal with the fact that not every interval is splittable into 8408 * equidistributed floats. 8409 * 8410 * Based on "Drawing random floating-point numbers from an interval" by 8411 * Frederic Goualard. 8412 */ 8413template <typename FloatType> 8414class uniform_floating_point_distribution { 8415 static_assert(std::is_floating_point<FloatType>::value, "..."); 8416 static_assert(!std::is_same<FloatType, long double>::value, 8417 "We do not support long double due to inconsistent behaviour between platforms"); 8418 8419 using WidthType = Detail::DistanceType<FloatType>; 8420 8421 FloatType m_a, m_b; 8422 FloatType m_ulp_magnitude; 8423 WidthType m_floats_in_range; 8424 uniform_integer_distribution<WidthType> m_int_dist; 8425 8426 // In specific cases, we can overflow into `inf` when computing the 8427 // `steps * g` offset. To avoid this, we don't offset by more than this 8428 // in one multiply + addition. 8429 WidthType m_max_steps_in_one_go; 8430 // We don't want to do the magnitude check every call to `operator()` 8431 bool m_a_has_leq_magnitude; 8432 8433public: 8434 using result_type = FloatType; 8435 8436 uniform_floating_point_distribution( FloatType a, FloatType b ): 8437 m_a( a ), 8438 m_b( b ), 8439 m_ulp_magnitude( Detail::gamma( m_a, m_b ) ), 8440 m_floats_in_range( Detail::count_equidistant_floats( m_a, m_b, m_ulp_magnitude ) ), 8441 m_int_dist(0, m_floats_in_range), 8442 m_max_steps_in_one_go( Detail::calculate_max_steps_in_one_go(m_ulp_magnitude)), 8443 m_a_has_leq_magnitude(std::fabs(m_a) <= std::fabs(m_b)) 8444 { 8445 assert( a <= b ); 8446 } 8447 8448 template <typename Generator> 8449 result_type operator()( Generator& g ) { 8450 WidthType steps = m_int_dist( g ); 8451 if ( m_a_has_leq_magnitude ) { 8452 if ( steps == m_floats_in_range ) { return m_a; } 8453 auto b = m_b; 8454 while (steps > m_max_steps_in_one_go) { 8455 b -= m_max_steps_in_one_go * m_ulp_magnitude; 8456 steps -= m_max_steps_in_one_go; 8457 } 8458 return b - steps * m_ulp_magnitude; 8459 } else { 8460 if ( steps == m_floats_in_range ) { return m_b; } 8461 auto a = m_a; 8462 while (steps > m_max_steps_in_one_go) { 8463 a += m_max_steps_in_one_go * m_ulp_magnitude; 8464 steps -= m_max_steps_in_one_go; 8465 } 8466 return a + steps * m_ulp_magnitude; 8467 } 8468 } 8469 8470 result_type a() const { return m_a; } 8471 result_type b() const { return m_b; } 8472}; 8473 8474} // end namespace Catch 8475 8476#endif // CATCH_UNIFORM_FLOATING_POINT_DISTRIBUTION_HPP_INCLUDED 8477 8478namespace Catch { 8479namespace Generators { 8480namespace Detail { 8481 // Returns a suitable seed for a random floating generator based off 8482 // the primary internal rng. It does so by taking current value from 8483 // the rng and returning it as the seed. 8484 std::uint32_t getSeed(); 8485} 8486 8487template <typename Float> 8488class RandomFloatingGenerator final : public IGenerator<Float> { 8489 Catch::SimplePcg32 m_rng; 8490 Catch::uniform_floating_point_distribution<Float> m_dist; 8491 Float m_current_number; 8492public: 8493 RandomFloatingGenerator( Float a, Float b, std::uint32_t seed ): 8494 m_rng(seed), 8495 m_dist(a, b) { 8496 static_cast<void>(next()); 8497 } 8498 8499 Float const& get() const override { 8500 return m_current_number; 8501 } 8502 bool next() override { 8503 m_current_number = m_dist(m_rng); 8504 return true; 8505 } 8506}; 8507 8508template <> 8509class RandomFloatingGenerator<long double> final : public IGenerator<long double> { 8510 // We still rely on <random> for this specialization, but we don't 8511 // want to drag it into the header. 8512 struct PImpl; 8513 Catch::Detail::unique_ptr<PImpl> m_pimpl; 8514 long double m_current_number; 8515 8516public: 8517 RandomFloatingGenerator( long double a, long double b, std::uint32_t seed ); 8518 8519 long double const& get() const override { return m_current_number; } 8520 bool next() override; 8521 8522 ~RandomFloatingGenerator() override; // = default 8523}; 8524 8525template <typename Integer> 8526class RandomIntegerGenerator final : public IGenerator<Integer> { 8527 Catch::SimplePcg32 m_rng; 8528 Catch::uniform_integer_distribution<Integer> m_dist; 8529 Integer m_current_number; 8530public: 8531 RandomIntegerGenerator( Integer a, Integer b, std::uint32_t seed ): 8532 m_rng(seed), 8533 m_dist(a, b) { 8534 static_cast<void>(next()); 8535 } 8536 8537 Integer const& get() const override { 8538 return m_current_number; 8539 } 8540 bool next() override { 8541 m_current_number = m_dist(m_rng); 8542 return true; 8543 } 8544}; 8545 8546template <typename T> 8547std::enable_if_t<std::is_integral<T>::value, GeneratorWrapper<T>> 8548random(T a, T b) { 8549 return GeneratorWrapper<T>( 8550 Catch::Detail::make_unique<RandomIntegerGenerator<T>>(a, b, Detail::getSeed()) 8551 ); 8552} 8553 8554template <typename T> 8555std::enable_if_t<std::is_floating_point<T>::value, 8556GeneratorWrapper<T>> 8557random(T a, T b) { 8558 return GeneratorWrapper<T>( 8559 Catch::Detail::make_unique<RandomFloatingGenerator<T>>(a, b, Detail::getSeed()) 8560 ); 8561} 8562 8563 8564} // namespace Generators 8565} // namespace Catch 8566 8567 8568#endif // CATCH_GENERATORS_RANDOM_HPP_INCLUDED 8569 8570 8571#ifndef CATCH_GENERATORS_RANGE_HPP_INCLUDED 8572#define CATCH_GENERATORS_RANGE_HPP_INCLUDED 8573 8574 8575#include <iterator> 8576#include <type_traits> 8577 8578namespace Catch { 8579namespace Generators { 8580 8581 8582template <typename T> 8583class RangeGenerator final : public IGenerator<T> { 8584 T m_current; 8585 T m_end; 8586 T m_step; 8587 bool m_positive; 8588 8589public: 8590 RangeGenerator(T const& start, T const& end, T const& step): 8591 m_current(start), 8592 m_end(end), 8593 m_step(step), 8594 m_positive(m_step > T(0)) 8595 { 8596 assert(m_current != m_end && "Range start and end cannot be equal"); 8597 assert(m_step != T(0) && "Step size cannot be zero"); 8598 assert(((m_positive && m_current <= m_end) || (!m_positive && m_current >= m_end)) && "Step moves away from end"); 8599 } 8600 8601 RangeGenerator(T const& start, T const& end): 8602 RangeGenerator(start, end, (start < end) ? T(1) : T(-1)) 8603 {} 8604 8605 T const& get() const override { 8606 return m_current; 8607 } 8608 8609 bool next() override { 8610 m_current += m_step; 8611 return (m_positive) ? (m_current < m_end) : (m_current > m_end); 8612 } 8613}; 8614 8615template <typename T> 8616GeneratorWrapper<T> range(T const& start, T const& end, T const& step) { 8617 static_assert(std::is_arithmetic<T>::value && !std::is_same<T, bool>::value, "Type must be numeric"); 8618 return GeneratorWrapper<T>(Catch::Detail::make_unique<RangeGenerator<T>>(start, end, step)); 8619} 8620 8621template <typename T> 8622GeneratorWrapper<T> range(T const& start, T const& end) { 8623 static_assert(std::is_integral<T>::value && !std::is_same<T, bool>::value, "Type must be an integer"); 8624 return GeneratorWrapper<T>(Catch::Detail::make_unique<RangeGenerator<T>>(start, end)); 8625} 8626 8627 8628template <typename T> 8629class IteratorGenerator final : public IGenerator<T> { 8630 static_assert(!std::is_same<T, bool>::value, 8631 "IteratorGenerator currently does not support bools" 8632 "because of std::vector<bool> specialization"); 8633 8634 std::vector<T> m_elems; 8635 size_t m_current = 0; 8636public: 8637 template <typename InputIterator, typename InputSentinel> 8638 IteratorGenerator(InputIterator first, InputSentinel last):m_elems(first, last) { 8639 if (m_elems.empty()) { 8640 Detail::throw_generator_exception("IteratorGenerator received no valid values"); 8641 } 8642 } 8643 8644 T const& get() const override { 8645 return m_elems[m_current]; 8646 } 8647 8648 bool next() override { 8649 ++m_current; 8650 return m_current != m_elems.size(); 8651 } 8652}; 8653 8654template <typename InputIterator, 8655 typename InputSentinel, 8656 typename ResultType = typename std::iterator_traits<InputIterator>::value_type> 8657GeneratorWrapper<ResultType> from_range(InputIterator from, InputSentinel to) { 8658 return GeneratorWrapper<ResultType>(Catch::Detail::make_unique<IteratorGenerator<ResultType>>(from, to)); 8659} 8660 8661template <typename Container> 8662auto from_range(Container const& cnt) { 8663 using std::begin; 8664 using std::end; 8665 return from_range( begin( cnt ), end( cnt ) ); 8666} 8667 8668 8669} // namespace Generators 8670} // namespace Catch 8671 8672 8673#endif // CATCH_GENERATORS_RANGE_HPP_INCLUDED 8674 8675#endif // CATCH_GENERATORS_ALL_HPP_INCLUDED 8676 8677 8678/** \file 8679 * This is a convenience header for Catch2's interfaces. It includes 8680 * **all** of Catch2 headers related to interfaces. 8681 * 8682 * Generally the Catch2 users should use specific includes they need, 8683 * but this header can be used instead for ease-of-experimentation, or 8684 * just plain convenience, at the cost of somewhat increased compilation 8685 * times. 8686 * 8687 * When a new header is added to either the `interfaces` folder, or to 8688 * the corresponding internal subfolder, it should be added here. 8689 */ 8690 8691 8692#ifndef CATCH_INTERFACES_ALL_HPP_INCLUDED 8693#define CATCH_INTERFACES_ALL_HPP_INCLUDED 8694 8695 8696 8697#ifndef CATCH_INTERFACES_REPORTER_HPP_INCLUDED 8698#define CATCH_INTERFACES_REPORTER_HPP_INCLUDED 8699 8700 8701 8702#ifndef CATCH_TEST_RUN_INFO_HPP_INCLUDED 8703#define CATCH_TEST_RUN_INFO_HPP_INCLUDED 8704 8705 8706namespace Catch { 8707 8708 struct TestRunInfo { 8709 constexpr TestRunInfo(StringRef _name) : name(_name) {} 8710 StringRef name; 8711 }; 8712 8713} // end namespace Catch 8714 8715#endif // CATCH_TEST_RUN_INFO_HPP_INCLUDED 8716 8717#include <map> 8718#include <string> 8719#include <vector> 8720#include <iosfwd> 8721 8722namespace Catch { 8723 8724 struct ReporterDescription; 8725 struct ListenerDescription; 8726 struct TagInfo; 8727 struct TestCaseInfo; 8728 class TestCaseHandle; 8729 class IConfig; 8730 class IStream; 8731 enum class ColourMode : std::uint8_t; 8732 8733 struct ReporterConfig { 8734 ReporterConfig( IConfig const* _fullConfig, 8735 Detail::unique_ptr<IStream> _stream, 8736 ColourMode colourMode, 8737 std::map<std::string, std::string> customOptions ); 8738 8739 ReporterConfig( ReporterConfig&& ) = default; 8740 ReporterConfig& operator=( ReporterConfig&& ) = default; 8741 ~ReporterConfig(); // = default 8742 8743 Detail::unique_ptr<IStream> takeStream() &&; 8744 IConfig const* fullConfig() const; 8745 ColourMode colourMode() const; 8746 std::map<std::string, std::string> const& customOptions() const; 8747 8748 private: 8749 Detail::unique_ptr<IStream> m_stream; 8750 IConfig const* m_fullConfig; 8751 ColourMode m_colourMode; 8752 std::map<std::string, std::string> m_customOptions; 8753 }; 8754 8755 struct AssertionStats { 8756 AssertionStats( AssertionResult const& _assertionResult, 8757 std::vector<MessageInfo> const& _infoMessages, 8758 Totals const& _totals ); 8759 8760 AssertionStats( AssertionStats const& ) = default; 8761 AssertionStats( AssertionStats && ) = default; 8762 AssertionStats& operator = ( AssertionStats const& ) = delete; 8763 AssertionStats& operator = ( AssertionStats && ) = delete; 8764 8765 AssertionResult assertionResult; 8766 std::vector<MessageInfo> infoMessages; 8767 Totals totals; 8768 }; 8769 8770 struct SectionStats { 8771 SectionStats( SectionInfo&& _sectionInfo, 8772 Counts const& _assertions, 8773 double _durationInSeconds, 8774 bool _missingAssertions ); 8775 8776 SectionInfo sectionInfo; 8777 Counts assertions; 8778 double durationInSeconds; 8779 bool missingAssertions; 8780 }; 8781 8782 struct TestCaseStats { 8783 TestCaseStats( TestCaseInfo const& _testInfo, 8784 Totals const& _totals, 8785 std::string&& _stdOut, 8786 std::string&& _stdErr, 8787 bool _aborting ); 8788 8789 TestCaseInfo const * testInfo; 8790 Totals totals; 8791 std::string stdOut; 8792 std::string stdErr; 8793 bool aborting; 8794 }; 8795 8796 struct TestRunStats { 8797 TestRunStats( TestRunInfo const& _runInfo, 8798 Totals const& _totals, 8799 bool _aborting ); 8800 8801 TestRunInfo runInfo; 8802 Totals totals; 8803 bool aborting; 8804 }; 8805 8806 //! By setting up its preferences, a reporter can modify Catch2's behaviour 8807 //! in some regards, e.g. it can request Catch2 to capture writes to 8808 //! stdout/stderr during test execution, and pass them to the reporter. 8809 struct ReporterPreferences { 8810 //! Catch2 should redirect writes to stdout and pass them to the 8811 //! reporter 8812 bool shouldRedirectStdOut = false; 8813 //! Catch2 should call `Reporter::assertionEnded` even for passing 8814 //! assertions 8815 bool shouldReportAllAssertions = false; 8816 }; 8817 8818 /** 8819 * The common base for all reporters and event listeners 8820 * 8821 * Implementing classes must also implement: 8822 * 8823 * //! User-friendly description of the reporter/listener type 8824 * static std::string getDescription() 8825 * 8826 * Generally shouldn't be derived from by users of Catch2 directly, 8827 * instead they should derive from one of the utility bases that 8828 * derive from this class. 8829 */ 8830 class IEventListener { 8831 protected: 8832 //! Derived classes can set up their preferences here 8833 ReporterPreferences m_preferences; 8834 //! The test run's config as filled in from CLI and defaults 8835 IConfig const* m_config; 8836 8837 public: 8838 IEventListener( IConfig const* config ): m_config( config ) {} 8839 8840 virtual ~IEventListener(); // = default; 8841 8842 // Implementing class must also provide the following static methods: 8843 // static std::string getDescription(); 8844 8845 ReporterPreferences const& getPreferences() const { 8846 return m_preferences; 8847 } 8848 8849 //! Called when no test cases match provided test spec 8850 virtual void noMatchingTestCases( StringRef unmatchedSpec ) = 0; 8851 //! Called for all invalid test specs from the cli 8852 virtual void reportInvalidTestSpec( StringRef invalidArgument ) = 0; 8853 8854 /** 8855 * Called once in a testing run before tests are started 8856 * 8857 * Not called if tests won't be run (e.g. only listing will happen) 8858 */ 8859 virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; 8860 8861 //! Called _once_ for each TEST_CASE, no matter how many times it is entered 8862 virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; 8863 //! Called _every time_ a TEST_CASE is entered, including repeats (due to sections) 8864 virtual void testCasePartialStarting( TestCaseInfo const& testInfo, uint64_t partNumber ) = 0; 8865 //! Called when a `SECTION` is being entered. Not called for skipped sections 8866 virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; 8867 8868 //! Called when user-code is being probed before the actual benchmark runs 8869 virtual void benchmarkPreparing( StringRef benchmarkName ) = 0; 8870 //! Called after probe but before the user-code is being benchmarked 8871 virtual void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) = 0; 8872 //! Called with the benchmark results if benchmark successfully finishes 8873 virtual void benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) = 0; 8874 //! Called if running the benchmarks fails for any reason 8875 virtual void benchmarkFailed( StringRef benchmarkName ) = 0; 8876 8877 //! Called before assertion success/failure is evaluated 8878 virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; 8879 8880 //! Called after assertion was fully evaluated 8881 virtual void assertionEnded( AssertionStats const& assertionStats ) = 0; 8882 8883 //! Called after a `SECTION` has finished running 8884 virtual void sectionEnded( SectionStats const& sectionStats ) = 0; 8885 //! Called _every time_ a TEST_CASE is entered, including repeats (due to sections) 8886 virtual void testCasePartialEnded(TestCaseStats const& testCaseStats, uint64_t partNumber ) = 0; 8887 //! Called _once_ for each TEST_CASE, no matter how many times it is entered 8888 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; 8889 /** 8890 * Called once after all tests in a testing run are finished 8891 * 8892 * Not called if tests weren't run (e.g. only listings happened) 8893 */ 8894 virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; 8895 8896 /** 8897 * Called with test cases that are skipped due to the test run aborting. 8898 * NOT called for test cases that are explicitly skipped using the `SKIP` macro. 8899 * 8900 * Deprecated - will be removed in the next major release. 8901 */ 8902 virtual void skipTest( TestCaseInfo const& testInfo ) = 0; 8903 8904 //! Called if a fatal error (signal/structured exception) occurred 8905 virtual void fatalErrorEncountered( StringRef error ) = 0; 8906 8907 //! Writes out information about provided reporters using reporter-specific format 8908 virtual void listReporters(std::vector<ReporterDescription> const& descriptions) = 0; 8909 //! Writes out the provided listeners descriptions using reporter-specific format 8910 virtual void listListeners(std::vector<ListenerDescription> const& descriptions) = 0; 8911 //! Writes out information about provided tests using reporter-specific format 8912 virtual void listTests(std::vector<TestCaseHandle> const& tests) = 0; 8913 //! Writes out information about the provided tags using reporter-specific format 8914 virtual void listTags(std::vector<TagInfo> const& tags) = 0; 8915 }; 8916 using IEventListenerPtr = Detail::unique_ptr<IEventListener>; 8917 8918} // end namespace Catch 8919 8920#endif // CATCH_INTERFACES_REPORTER_HPP_INCLUDED 8921 8922 8923#ifndef CATCH_INTERFACES_REPORTER_FACTORY_HPP_INCLUDED 8924#define CATCH_INTERFACES_REPORTER_FACTORY_HPP_INCLUDED 8925 8926 8927#include <string> 8928 8929namespace Catch { 8930 8931 struct ReporterConfig; 8932 class IConfig; 8933 class IEventListener; 8934 using IEventListenerPtr = Detail::unique_ptr<IEventListener>; 8935 8936 8937 class IReporterFactory { 8938 public: 8939 virtual ~IReporterFactory(); // = default 8940 8941 virtual IEventListenerPtr 8942 create( ReporterConfig&& config ) const = 0; 8943 virtual std::string getDescription() const = 0; 8944 }; 8945 using IReporterFactoryPtr = Detail::unique_ptr<IReporterFactory>; 8946 8947 class EventListenerFactory { 8948 public: 8949 virtual ~EventListenerFactory(); // = default 8950 virtual IEventListenerPtr create( IConfig const* config ) const = 0; 8951 //! Return a meaningful name for the listener, e.g. its type name 8952 virtual StringRef getName() const = 0; 8953 //! Return listener's description if available 8954 virtual std::string getDescription() const = 0; 8955 }; 8956} // namespace Catch 8957 8958#endif // CATCH_INTERFACES_REPORTER_FACTORY_HPP_INCLUDED 8959 8960 8961#ifndef CATCH_INTERFACES_TAG_ALIAS_REGISTRY_HPP_INCLUDED 8962#define CATCH_INTERFACES_TAG_ALIAS_REGISTRY_HPP_INCLUDED 8963 8964#include <string> 8965 8966namespace Catch { 8967 8968 struct TagAlias; 8969 8970 class ITagAliasRegistry { 8971 public: 8972 virtual ~ITagAliasRegistry(); // = default 8973 // Nullptr if not present 8974 virtual TagAlias const* find( std::string const& alias ) const = 0; 8975 virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; 8976 8977 static ITagAliasRegistry const& get(); 8978 }; 8979 8980} // end namespace Catch 8981 8982#endif // CATCH_INTERFACES_TAG_ALIAS_REGISTRY_HPP_INCLUDED 8983 8984 8985#ifndef CATCH_INTERFACES_TESTCASE_HPP_INCLUDED 8986#define CATCH_INTERFACES_TESTCASE_HPP_INCLUDED 8987 8988#include <vector> 8989 8990namespace Catch { 8991 8992 struct TestCaseInfo; 8993 class TestCaseHandle; 8994 class IConfig; 8995 8996 class ITestCaseRegistry { 8997 public: 8998 virtual ~ITestCaseRegistry(); // = default 8999 // TODO: this exists only for adding filenames to test cases -- let's expose this in a saner way later 9000 virtual std::vector<TestCaseInfo* > const& getAllInfos() const = 0; 9001 virtual std::vector<TestCaseHandle> const& getAllTests() const = 0; 9002 virtual std::vector<TestCaseHandle> const& getAllTestsSorted( IConfig const& config ) const = 0; 9003 }; 9004 9005} 9006 9007#endif // CATCH_INTERFACES_TESTCASE_HPP_INCLUDED 9008 9009#endif // CATCH_INTERFACES_ALL_HPP_INCLUDED 9010 9011 9012#ifndef CATCH_CASE_INSENSITIVE_COMPARISONS_HPP_INCLUDED 9013#define CATCH_CASE_INSENSITIVE_COMPARISONS_HPP_INCLUDED 9014 9015 9016namespace Catch { 9017 namespace Detail { 9018 //! Provides case-insensitive `op<` semantics when called 9019 struct CaseInsensitiveLess { 9020 bool operator()( StringRef lhs, 9021 StringRef rhs ) const; 9022 }; 9023 9024 //! Provides case-insensitive `op==` semantics when called 9025 struct CaseInsensitiveEqualTo { 9026 bool operator()( StringRef lhs, 9027 StringRef rhs ) const; 9028 }; 9029 9030 } // namespace Detail 9031} // namespace Catch 9032 9033#endif // CATCH_CASE_INSENSITIVE_COMPARISONS_HPP_INCLUDED 9034 9035 9036 9037/** \file 9038 * Wrapper for ANDROID_LOGWRITE configuration option 9039 * 9040 * We want to default to enabling it when compiled for android, but 9041 * users of the library should also be able to disable it if they want 9042 * to. 9043 */ 9044 9045#ifndef CATCH_CONFIG_ANDROID_LOGWRITE_HPP_INCLUDED 9046#define CATCH_CONFIG_ANDROID_LOGWRITE_HPP_INCLUDED 9047 9048 9049#if defined(__ANDROID__) 9050# define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE 9051#endif 9052 9053 9054#if defined( CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE ) && \ 9055 !defined( CATCH_CONFIG_NO_ANDROID_LOGWRITE ) && \ 9056 !defined( CATCH_CONFIG_ANDROID_LOGWRITE ) 9057# define CATCH_CONFIG_ANDROID_LOGWRITE 9058#endif 9059 9060#endif // CATCH_CONFIG_ANDROID_LOGWRITE_HPP_INCLUDED 9061 9062 9063 9064/** \file 9065 * Wrapper for UNCAUGHT_EXCEPTIONS configuration option 9066 * 9067 * For some functionality, Catch2 requires to know whether there is 9068 * an active exception. Because `std::uncaught_exception` is deprecated 9069 * in C++17, we want to use `std::uncaught_exceptions` if possible. 9070 */ 9071 9072#ifndef CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED 9073#define CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED 9074 9075 9076#if defined(_MSC_VER) 9077# if _MSC_VER >= 1900 // Visual Studio 2015 or newer 9078# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS 9079# endif 9080#endif 9081 9082 9083#include <exception> 9084 9085#if defined(__cpp_lib_uncaught_exceptions) \ 9086 && !defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) 9087 9088# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS 9089#endif // __cpp_lib_uncaught_exceptions 9090 9091 9092#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) \ 9093 && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) \ 9094 && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) 9095 9096# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS 9097#endif 9098 9099 9100#endif // CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED 9101 9102 9103#ifndef CATCH_CONSOLE_COLOUR_HPP_INCLUDED 9104#define CATCH_CONSOLE_COLOUR_HPP_INCLUDED 9105 9106 9107#include <iosfwd> 9108#include <cstdint> 9109 9110namespace Catch { 9111 9112 enum class ColourMode : std::uint8_t; 9113 class IStream; 9114 9115 struct Colour { 9116 enum Code { 9117 None = 0, 9118 9119 White, 9120 Red, 9121 Green, 9122 Blue, 9123 Cyan, 9124 Yellow, 9125 Grey, 9126 9127 Bright = 0x10, 9128 9129 BrightRed = Bright | Red, 9130 BrightGreen = Bright | Green, 9131 LightGrey = Bright | Grey, 9132 BrightWhite = Bright | White, 9133 BrightYellow = Bright | Yellow, 9134 9135 // By intention 9136 FileName = LightGrey, 9137 Warning = BrightYellow, 9138 ResultError = BrightRed, 9139 ResultSuccess = BrightGreen, 9140 ResultExpectedFailure = Warning, 9141 9142 Error = BrightRed, 9143 Success = Green, 9144 Skip = LightGrey, 9145 9146 OriginalExpression = Cyan, 9147 ReconstructedExpression = BrightYellow, 9148 9149 SecondaryText = LightGrey, 9150 Headers = White 9151 }; 9152 }; 9153 9154 class ColourImpl { 9155 protected: 9156 //! The associated stream of this ColourImpl instance 9157 IStream* m_stream; 9158 public: 9159 ColourImpl( IStream* stream ): m_stream( stream ) {} 9160 9161 //! RAII wrapper around writing specific colour of text using specific 9162 //! colour impl into a stream. 9163 class ColourGuard { 9164 ColourImpl const* m_colourImpl; 9165 Colour::Code m_code; 9166 bool m_engaged = false; 9167 9168 public: 9169 //! Does **not** engage the guard/start the colour 9170 ColourGuard( Colour::Code code, 9171 ColourImpl const* colour ); 9172 9173 ColourGuard( ColourGuard const& rhs ) = delete; 9174 ColourGuard& operator=( ColourGuard const& rhs ) = delete; 9175 9176 ColourGuard( ColourGuard&& rhs ) noexcept; 9177 ColourGuard& operator=( ColourGuard&& rhs ) noexcept; 9178 9179 //! Removes colour _if_ the guard was engaged 9180 ~ColourGuard(); 9181 9182 /** 9183 * Explicitly engages colour for given stream. 9184 * 9185 * The API based on operator<< should be preferred. 9186 */ 9187 ColourGuard& engage( std::ostream& stream ) &; 9188 /** 9189 * Explicitly engages colour for given stream. 9190 * 9191 * The API based on operator<< should be preferred. 9192 */ 9193 ColourGuard&& engage( std::ostream& stream ) &&; 9194 9195 private: 9196 //! Engages the guard and starts using colour 9197 friend std::ostream& operator<<( std::ostream& lhs, 9198 ColourGuard& guard ) { 9199 guard.engageImpl( lhs ); 9200 return lhs; 9201 } 9202 //! Engages the guard and starts using colour 9203 friend std::ostream& operator<<( std::ostream& lhs, 9204 ColourGuard&& guard) { 9205 guard.engageImpl( lhs ); 9206 return lhs; 9207 } 9208 9209 void engageImpl( std::ostream& stream ); 9210 9211 }; 9212 9213 virtual ~ColourImpl(); // = default 9214 /** 9215 * Creates a guard object for given colour and this colour impl 9216 * 9217 * **Important:** 9218 * the guard starts disengaged, and has to be engaged explicitly. 9219 */ 9220 ColourGuard guardColour( Colour::Code colourCode ); 9221 9222 private: 9223 virtual void use( Colour::Code colourCode ) const = 0; 9224 }; 9225 9226 //! Provides ColourImpl based on global config and target compilation platform 9227 Detail::unique_ptr<ColourImpl> makeColourImpl( ColourMode colourSelection, 9228 IStream* stream ); 9229 9230 //! Checks if specific colour impl has been compiled into the binary 9231 bool isColourImplAvailable( ColourMode colourSelection ); 9232 9233} // end namespace Catch 9234 9235#endif // CATCH_CONSOLE_COLOUR_HPP_INCLUDED 9236 9237 9238#ifndef CATCH_CONSOLE_WIDTH_HPP_INCLUDED 9239#define CATCH_CONSOLE_WIDTH_HPP_INCLUDED 9240 9241// This include must be kept so that user's configured value for CONSOLE_WIDTH 9242// is used before we attempt to provide a default value 9243 9244#ifndef CATCH_CONFIG_CONSOLE_WIDTH 9245#define CATCH_CONFIG_CONSOLE_WIDTH 80 9246#endif 9247 9248#endif // CATCH_CONSOLE_WIDTH_HPP_INCLUDED 9249 9250 9251#ifndef CATCH_CONTAINER_NONMEMBERS_HPP_INCLUDED 9252#define CATCH_CONTAINER_NONMEMBERS_HPP_INCLUDED 9253 9254 9255#include <cstddef> 9256#include <initializer_list> 9257 9258// We want a simple polyfill over `std::empty`, `std::size` and so on 9259// for C++14 or C++ libraries with incomplete support. 9260// We also have to handle that MSVC std lib will happily provide these 9261// under older standards. 9262#if defined(CATCH_CPP17_OR_GREATER) || defined(_MSC_VER) 9263 9264// We are already using this header either way, so there shouldn't 9265// be much additional overhead in including it to get the feature 9266// test macros 9267#include <string> 9268 9269# if !defined(__cpp_lib_nonmember_container_access) 9270# define CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS 9271# endif 9272 9273#else 9274#define CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS 9275#endif 9276 9277 9278 9279namespace Catch { 9280namespace Detail { 9281 9282#if defined(CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS) 9283 template <typename Container> 9284 constexpr auto empty(Container const& cont) -> decltype(cont.empty()) { 9285 return cont.empty(); 9286 } 9287 template <typename T, std::size_t N> 9288 constexpr bool empty(const T (&)[N]) noexcept { 9289 // GCC < 7 does not support the const T(&)[] parameter syntax 9290 // so we have to ignore the length explicitly 9291 (void)N; 9292 return false; 9293 } 9294 template <typename T> 9295 constexpr bool empty(std::initializer_list<T> list) noexcept { 9296 return list.size() > 0; 9297 } 9298 9299 9300 template <typename Container> 9301 constexpr auto size(Container const& cont) -> decltype(cont.size()) { 9302 return cont.size(); 9303 } 9304 template <typename T, std::size_t N> 9305 constexpr std::size_t size(const T(&)[N]) noexcept { 9306 return N; 9307 } 9308#endif // CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS 9309 9310} // end namespace Detail 9311} // end namespace Catch 9312 9313 9314 9315#endif // CATCH_CONTAINER_NONMEMBERS_HPP_INCLUDED 9316 9317 9318#ifndef CATCH_DEBUG_CONSOLE_HPP_INCLUDED 9319#define CATCH_DEBUG_CONSOLE_HPP_INCLUDED 9320 9321#include <string> 9322 9323namespace Catch { 9324 void writeToDebugConsole( std::string const& text ); 9325} 9326 9327#endif // CATCH_DEBUG_CONSOLE_HPP_INCLUDED 9328 9329 9330#ifndef CATCH_DEBUGGER_HPP_INCLUDED 9331#define CATCH_DEBUGGER_HPP_INCLUDED 9332 9333 9334namespace Catch { 9335 bool isDebuggerActive(); 9336} 9337 9338#ifdef CATCH_PLATFORM_MAC 9339 9340 #if defined(__i386__) || defined(__x86_64__) 9341 #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */ 9342 #elif defined(__aarch64__) 9343 #define CATCH_TRAP() __asm__(".inst 0xd43e0000") 9344 #elif defined(__POWERPC__) 9345 #define CATCH_TRAP() __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \ 9346 : : : "memory","r0","r3","r4" ) /* NOLINT */ 9347 #endif 9348 9349#elif defined(CATCH_PLATFORM_IPHONE) 9350 9351 // use inline assembler 9352 #if defined(__i386__) || defined(__x86_64__) 9353 #define CATCH_TRAP() __asm__("int $3") 9354 #elif defined(__aarch64__) 9355 #define CATCH_TRAP() __asm__(".inst 0xd4200000") 9356 #elif defined(__arm__) && !defined(__thumb__) 9357 #define CATCH_TRAP() __asm__(".inst 0xe7f001f0") 9358 #elif defined(__arm__) && defined(__thumb__) 9359 #define CATCH_TRAP() __asm__(".inst 0xde01") 9360 #endif 9361 9362#elif defined(CATCH_PLATFORM_LINUX) 9363 // If we can use inline assembler, do it because this allows us to break 9364 // directly at the location of the failing check instead of breaking inside 9365 // raise() called from it, i.e. one stack frame below. 9366 #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64)) 9367 #define CATCH_TRAP() asm volatile ("int $3") /* NOLINT */ 9368 #else // Fall back to the generic way. 9369 #include <signal.h> 9370 9371 #define CATCH_TRAP() raise(SIGTRAP) 9372 #endif 9373#elif defined(_MSC_VER) 9374 #define CATCH_TRAP() __debugbreak() 9375#elif defined(__MINGW32__) 9376 extern "C" __declspec(dllimport) void __stdcall DebugBreak(); 9377 #define CATCH_TRAP() DebugBreak() 9378#endif 9379 9380#ifndef CATCH_BREAK_INTO_DEBUGGER 9381 #ifdef CATCH_TRAP 9382 #define CATCH_BREAK_INTO_DEBUGGER() []{ if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } }() 9383 #else 9384 #define CATCH_BREAK_INTO_DEBUGGER() []{}() 9385 #endif 9386#endif 9387 9388#endif // CATCH_DEBUGGER_HPP_INCLUDED 9389 9390 9391#ifndef CATCH_ENFORCE_HPP_INCLUDED 9392#define CATCH_ENFORCE_HPP_INCLUDED 9393 9394 9395#include <exception> 9396 9397namespace Catch { 9398#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 9399 template <typename Ex> 9400 [[noreturn]] 9401 void throw_exception(Ex const& e) { 9402 throw e; 9403 } 9404#else // ^^ Exceptions are enabled // Exceptions are disabled vv 9405 [[noreturn]] 9406 void throw_exception(std::exception const& e); 9407#endif 9408 9409 [[noreturn]] 9410 void throw_logic_error(std::string const& msg); 9411 [[noreturn]] 9412 void throw_domain_error(std::string const& msg); 9413 [[noreturn]] 9414 void throw_runtime_error(std::string const& msg); 9415 9416} // namespace Catch; 9417 9418#define CATCH_MAKE_MSG(...) \ 9419 (Catch::ReusableStringStream() << __VA_ARGS__).str() 9420 9421#define CATCH_INTERNAL_ERROR(...) \ 9422 Catch::throw_logic_error(CATCH_MAKE_MSG( CATCH_INTERNAL_LINEINFO << ": Internal Catch2 error: " << __VA_ARGS__)) 9423 9424#define CATCH_ERROR(...) \ 9425 Catch::throw_domain_error(CATCH_MAKE_MSG( __VA_ARGS__ )) 9426 9427#define CATCH_RUNTIME_ERROR(...) \ 9428 Catch::throw_runtime_error(CATCH_MAKE_MSG( __VA_ARGS__ )) 9429 9430#define CATCH_ENFORCE( condition, ... ) \ 9431 do{ if( !(condition) ) CATCH_ERROR( __VA_ARGS__ ); } while(false) 9432 9433 9434#endif // CATCH_ENFORCE_HPP_INCLUDED 9435 9436 9437#ifndef CATCH_ENUM_VALUES_REGISTRY_HPP_INCLUDED 9438#define CATCH_ENUM_VALUES_REGISTRY_HPP_INCLUDED 9439 9440 9441#include <vector> 9442 9443namespace Catch { 9444 9445 namespace Detail { 9446 9447 Catch::Detail::unique_ptr<EnumInfo> makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ); 9448 9449 class EnumValuesRegistry : public IMutableEnumValuesRegistry { 9450 9451 std::vector<Catch::Detail::unique_ptr<EnumInfo>> m_enumInfos; 9452 9453 EnumInfo const& registerEnum( StringRef enumName, StringRef allValueNames, std::vector<int> const& values) override; 9454 }; 9455 9456 std::vector<StringRef> parseEnums( StringRef enums ); 9457 9458 } // Detail 9459 9460} // Catch 9461 9462#endif // CATCH_ENUM_VALUES_REGISTRY_HPP_INCLUDED 9463 9464 9465#ifndef CATCH_ERRNO_GUARD_HPP_INCLUDED 9466#define CATCH_ERRNO_GUARD_HPP_INCLUDED 9467 9468namespace Catch { 9469 9470 //! Simple RAII class that stores the value of `errno` 9471 //! at construction and restores it at destruction. 9472 class ErrnoGuard { 9473 public: 9474 // Keep these outlined to avoid dragging in macros from <cerrno> 9475 9476 ErrnoGuard(); 9477 ~ErrnoGuard(); 9478 private: 9479 int m_oldErrno; 9480 }; 9481 9482} 9483 9484#endif // CATCH_ERRNO_GUARD_HPP_INCLUDED 9485 9486 9487#ifndef CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED 9488#define CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED 9489 9490 9491#include <vector> 9492#include <string> 9493 9494namespace Catch { 9495 9496 class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { 9497 public: 9498 ~ExceptionTranslatorRegistry() override; 9499 void registerTranslator( Detail::unique_ptr<IExceptionTranslator>&& translator ); 9500 std::string translateActiveException() const override; 9501 9502 private: 9503 ExceptionTranslators m_translators; 9504 }; 9505} 9506 9507#endif // CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED 9508 9509 9510#ifndef CATCH_FATAL_CONDITION_HANDLER_HPP_INCLUDED 9511#define CATCH_FATAL_CONDITION_HANDLER_HPP_INCLUDED 9512 9513#include <cassert> 9514 9515namespace Catch { 9516 9517 /** 9518 * Wrapper for platform-specific fatal error (signals/SEH) handlers 9519 * 9520 * Tries to be cooperative with other handlers, and not step over 9521 * other handlers. This means that unknown structured exceptions 9522 * are passed on, previous signal handlers are called, and so on. 9523 * 9524 * Can only be instantiated once, and assumes that once a signal 9525 * is caught, the binary will end up terminating. Thus, there 9526 */ 9527 class FatalConditionHandler { 9528 bool m_started = false; 9529 9530 // Install/disengage implementation for specific platform. 9531 // Should be if-defed to work on current platform, can assume 9532 // engage-disengage 1:1 pairing. 9533 void engage_platform(); 9534 void disengage_platform() noexcept; 9535 public: 9536 // Should also have platform-specific implementations as needed 9537 FatalConditionHandler(); 9538 ~FatalConditionHandler(); 9539 9540 void engage() { 9541 assert(!m_started && "Handler cannot be installed twice."); 9542 m_started = true; 9543 engage_platform(); 9544 } 9545 9546 void disengage() noexcept { 9547 assert(m_started && "Handler cannot be uninstalled without being installed first"); 9548 m_started = false; 9549 disengage_platform(); 9550 } 9551 }; 9552 9553 //! Simple RAII guard for (dis)engaging the FatalConditionHandler 9554 class FatalConditionHandlerGuard { 9555 FatalConditionHandler* m_handler; 9556 public: 9557 FatalConditionHandlerGuard(FatalConditionHandler* handler): 9558 m_handler(handler) { 9559 m_handler->engage(); 9560 } 9561 ~FatalConditionHandlerGuard() { 9562 m_handler->disengage(); 9563 } 9564 }; 9565 9566} // end namespace Catch 9567 9568#endif // CATCH_FATAL_CONDITION_HANDLER_HPP_INCLUDED 9569 9570 9571#ifndef CATCH_FLOATING_POINT_HELPERS_HPP_INCLUDED 9572#define CATCH_FLOATING_POINT_HELPERS_HPP_INCLUDED 9573 9574 9575#include <cassert> 9576#include <cmath> 9577#include <cstdint> 9578#include <utility> 9579#include <limits> 9580 9581namespace Catch { 9582 namespace Detail { 9583 9584 uint32_t convertToBits(float f); 9585 uint64_t convertToBits(double d); 9586 9587 // Used when we know we want == comparison of two doubles 9588 // to centralize warning suppression 9589 bool directCompare( float lhs, float rhs ); 9590 bool directCompare( double lhs, double rhs ); 9591 9592 } // end namespace Detail 9593 9594 9595 9596#if defined( __GNUC__ ) || defined( __clang__ ) 9597# pragma GCC diagnostic push 9598 // We do a bunch of direct compensations of floating point numbers, 9599 // because we know what we are doing and actually do want the direct 9600 // comparison behaviour. 9601# pragma GCC diagnostic ignored "-Wfloat-equal" 9602#endif 9603 9604 /** 9605 * Calculates the ULP distance between two floating point numbers 9606 * 9607 * The ULP distance of two floating point numbers is the count of 9608 * valid floating point numbers representable between them. 9609 * 9610 * There are some exceptions between how this function counts the 9611 * distance, and the interpretation of the standard as implemented. 9612 * by e.g. `nextafter`. For this function it always holds that: 9613 * * `(x == y) => ulpDistance(x, y) == 0` (so `ulpDistance(-0, 0) == 0`) 9614 * * `ulpDistance(maxFinite, INF) == 1` 9615 * * `ulpDistance(x, -x) == 2 * ulpDistance(x, 0)` 9616 * 9617 * \pre `!isnan( lhs )` 9618 * \pre `!isnan( rhs )` 9619 * \pre floating point numbers are represented in IEEE-754 format 9620 */ 9621 template <typename FP> 9622 uint64_t ulpDistance( FP lhs, FP rhs ) { 9623 assert( std::numeric_limits<FP>::is_iec559 && 9624 "ulpDistance assumes IEEE-754 format for floating point types" ); 9625 assert( !Catch::isnan( lhs ) && 9626 "Distance between NaN and number is not meaningful" ); 9627 assert( !Catch::isnan( rhs ) && 9628 "Distance between NaN and number is not meaningful" ); 9629 9630 // We want X == Y to imply 0 ULP distance even if X and Y aren't 9631 // bit-equal (-0 and 0), or X - Y != 0 (same sign infinities). 9632 if ( lhs == rhs ) { return 0; } 9633 9634 // We need a properly typed positive zero for type inference. 9635 static constexpr FP positive_zero{}; 9636 9637 // We want to ensure that +/- 0 is always represented as positive zero 9638 if ( lhs == positive_zero ) { lhs = positive_zero; } 9639 if ( rhs == positive_zero ) { rhs = positive_zero; } 9640 9641 // If arguments have different signs, we can handle them by summing 9642 // how far are they from 0 each. 9643 if ( std::signbit( lhs ) != std::signbit( rhs ) ) { 9644 return ulpDistance( std::abs( lhs ), positive_zero ) + 9645 ulpDistance( std::abs( rhs ), positive_zero ); 9646 } 9647 9648 // When both lhs and rhs are of the same sign, we can just 9649 // read the numbers bitwise as integers, and then subtract them 9650 // (assuming IEEE). 9651 uint64_t lc = Detail::convertToBits( lhs ); 9652 uint64_t rc = Detail::convertToBits( rhs ); 9653 9654 // The ulp distance between two numbers is symmetric, so to avoid 9655 // dealing with overflows we want the bigger converted number on the lhs 9656 if ( lc < rc ) { 9657 std::swap( lc, rc ); 9658 } 9659 9660 return lc - rc; 9661 } 9662 9663#if defined( __GNUC__ ) || defined( __clang__ ) 9664# pragma GCC diagnostic pop 9665#endif 9666 9667 9668} // end namespace Catch 9669 9670#endif // CATCH_FLOATING_POINT_HELPERS_HPP_INCLUDED 9671 9672 9673#ifndef CATCH_GETENV_HPP_INCLUDED 9674#define CATCH_GETENV_HPP_INCLUDED 9675 9676namespace Catch { 9677namespace Detail { 9678 9679 //! Wrapper over `std::getenv` that compiles on UWP (and always returns nullptr there) 9680 char const* getEnv(char const* varName); 9681 9682} 9683} 9684 9685#endif // CATCH_GETENV_HPP_INCLUDED 9686 9687 9688#ifndef CATCH_IS_PERMUTATION_HPP_INCLUDED 9689#define CATCH_IS_PERMUTATION_HPP_INCLUDED 9690 9691#include <algorithm> 9692#include <iterator> 9693 9694namespace Catch { 9695 namespace Detail { 9696 9697 template <typename ForwardIter, 9698 typename Sentinel, 9699 typename T, 9700 typename Comparator> 9701 ForwardIter find_sentinel( ForwardIter start, 9702 Sentinel sentinel, 9703 T const& value, 9704 Comparator cmp ) { 9705 while ( start != sentinel ) { 9706 if ( cmp( *start, value ) ) { break; } 9707 ++start; 9708 } 9709 return start; 9710 } 9711 9712 template <typename ForwardIter, 9713 typename Sentinel, 9714 typename T, 9715 typename Comparator> 9716 std::ptrdiff_t count_sentinel( ForwardIter start, 9717 Sentinel sentinel, 9718 T const& value, 9719 Comparator cmp ) { 9720 std::ptrdiff_t count = 0; 9721 while ( start != sentinel ) { 9722 if ( cmp( *start, value ) ) { ++count; } 9723 ++start; 9724 } 9725 return count; 9726 } 9727 9728 template <typename ForwardIter, typename Sentinel> 9729 std::enable_if_t<!std::is_same<ForwardIter, Sentinel>::value, 9730 std::ptrdiff_t> 9731 sentinel_distance( ForwardIter iter, const Sentinel sentinel ) { 9732 std::ptrdiff_t dist = 0; 9733 while ( iter != sentinel ) { 9734 ++iter; 9735 ++dist; 9736 } 9737 return dist; 9738 } 9739 9740 template <typename ForwardIter> 9741 std::ptrdiff_t sentinel_distance( ForwardIter first, 9742 ForwardIter last ) { 9743 return std::distance( first, last ); 9744 } 9745 9746 template <typename ForwardIter1, 9747 typename Sentinel1, 9748 typename ForwardIter2, 9749 typename Sentinel2, 9750 typename Comparator> 9751 bool check_element_counts( ForwardIter1 first_1, 9752 const Sentinel1 end_1, 9753 ForwardIter2 first_2, 9754 const Sentinel2 end_2, 9755 Comparator cmp ) { 9756 auto cursor = first_1; 9757 while ( cursor != end_1 ) { 9758 if ( find_sentinel( first_1, cursor, *cursor, cmp ) == 9759 cursor ) { 9760 // we haven't checked this element yet 9761 const auto count_in_range_2 = 9762 count_sentinel( first_2, end_2, *cursor, cmp ); 9763 // Not a single instance in 2nd range, so it cannot be a 9764 // permutation of 1st range 9765 if ( count_in_range_2 == 0 ) { return false; } 9766 9767 const auto count_in_range_1 = 9768 count_sentinel( cursor, end_1, *cursor, cmp ); 9769 if ( count_in_range_1 != count_in_range_2 ) { 9770 return false; 9771 } 9772 } 9773 9774 ++cursor; 9775 } 9776 9777 return true; 9778 } 9779 9780 template <typename ForwardIter1, 9781 typename Sentinel1, 9782 typename ForwardIter2, 9783 typename Sentinel2, 9784 typename Comparator> 9785 bool is_permutation( ForwardIter1 first_1, 9786 const Sentinel1 end_1, 9787 ForwardIter2 first_2, 9788 const Sentinel2 end_2, 9789 Comparator cmp ) { 9790 // TODO: no optimization for stronger iterators, because we would also have to constrain on sentinel vs not sentinel types 9791 // TODO: Comparator has to be "both sides", e.g. a == b => b == a 9792 // This skips shared prefix of the two ranges 9793 while (first_1 != end_1 && first_2 != end_2 && cmp(*first_1, *first_2)) { 9794 ++first_1; 9795 ++first_2; 9796 } 9797 9798 // We need to handle case where at least one of the ranges has no more elements 9799 if (first_1 == end_1 || first_2 == end_2) { 9800 return first_1 == end_1 && first_2 == end_2; 9801 } 9802 9803 // pair counting is n**2, so we pay linear walk to compare the sizes first 9804 auto dist_1 = sentinel_distance( first_1, end_1 ); 9805 auto dist_2 = sentinel_distance( first_2, end_2 ); 9806 9807 if (dist_1 != dist_2) { return false; } 9808 9809 // Since we do not try to handle stronger iterators pair (e.g. 9810 // bidir) optimally, the only thing left to do is to check counts in 9811 // the remaining ranges. 9812 return check_element_counts( first_1, end_1, first_2, end_2, cmp ); 9813 } 9814 9815 } // namespace Detail 9816} // namespace Catch 9817 9818#endif // CATCH_IS_PERMUTATION_HPP_INCLUDED 9819 9820 9821#ifndef CATCH_ISTREAM_HPP_INCLUDED 9822#define CATCH_ISTREAM_HPP_INCLUDED 9823 9824 9825#include <iosfwd> 9826#include <cstddef> 9827#include <ostream> 9828#include <string> 9829 9830namespace Catch { 9831 9832 class IStream { 9833 public: 9834 virtual ~IStream(); // = default 9835 virtual std::ostream& stream() = 0; 9836 /** 9837 * Best guess on whether the instance is writing to a console (e.g. via stdout/stderr) 9838 * 9839 * This is useful for e.g. Win32 colour support, because the Win32 9840 * API manipulates console directly, unlike POSIX escape codes, 9841 * that can be written anywhere. 9842 * 9843 * Due to variety of ways to change where the stdout/stderr is 9844 * _actually_ being written, users should always assume that 9845 * the answer might be wrong. 9846 */ 9847 virtual bool isConsole() const { return false; } 9848 }; 9849 9850 /** 9851 * Creates a stream wrapper that writes to specific file. 9852 * 9853 * Also recognizes 4 special filenames 9854 * * `-` for stdout 9855 * * `%stdout` for stdout 9856 * * `%stderr` for stderr 9857 * * `%debug` for platform specific debugging output 9858 * 9859 * \throws if passed an unrecognized %-prefixed stream 9860 */ 9861 auto makeStream( std::string const& filename ) -> Detail::unique_ptr<IStream>; 9862 9863} 9864 9865#endif // CATCH_STREAM_HPP_INCLUDED 9866 9867 9868#ifndef CATCH_JSONWRITER_HPP_INCLUDED 9869#define CATCH_JSONWRITER_HPP_INCLUDED 9870 9871 9872#include <cstdint> 9873#include <sstream> 9874 9875namespace Catch { 9876 class JsonObjectWriter; 9877 class JsonArrayWriter; 9878 9879 struct JsonUtils { 9880 static void indent( std::ostream& os, std::uint64_t level ); 9881 static void appendCommaNewline( std::ostream& os, 9882 bool& should_comma, 9883 std::uint64_t level ); 9884 }; 9885 9886 class JsonValueWriter { 9887 public: 9888 JsonValueWriter( std::ostream& os ); 9889 JsonValueWriter( std::ostream& os, std::uint64_t indent_level ); 9890 9891 JsonObjectWriter writeObject() &&; 9892 JsonArrayWriter writeArray() &&; 9893 9894 template <typename T> 9895 void write( T const& value ) && { 9896 writeImpl( value, !std::is_arithmetic<T>::value ); 9897 } 9898 void write( StringRef value ) &&; 9899 void write( bool value ) &&; 9900 9901 private: 9902 void writeImpl( StringRef value, bool quote ); 9903 9904 // Without this SFINAE, this overload is a better match 9905 // for `std::string`, `char const*`, `char const[N]` args. 9906 // While it would still work, it would cause code bloat 9907 // and multiple iteration over the strings 9908 template <typename T, 9909 typename = typename std::enable_if_t< 9910 !std::is_convertible<T, StringRef>::value>> 9911 void writeImpl( T const& value, bool quote_value ) { 9912 m_sstream << value; 9913 writeImpl( m_sstream.str(), quote_value ); 9914 } 9915 9916 std::ostream& m_os; 9917 std::stringstream m_sstream; 9918 std::uint64_t m_indent_level; 9919 }; 9920 9921 class JsonObjectWriter { 9922 public: 9923 JsonObjectWriter( std::ostream& os ); 9924 JsonObjectWriter( std::ostream& os, std::uint64_t indent_level ); 9925 9926 JsonObjectWriter( JsonObjectWriter&& source ) noexcept; 9927 JsonObjectWriter& operator=( JsonObjectWriter&& source ) = delete; 9928 9929 ~JsonObjectWriter(); 9930 9931 JsonValueWriter write( StringRef key ); 9932 9933 private: 9934 std::ostream& m_os; 9935 std::uint64_t m_indent_level; 9936 bool m_should_comma = false; 9937 bool m_active = true; 9938 }; 9939 9940 class JsonArrayWriter { 9941 public: 9942 JsonArrayWriter( std::ostream& os ); 9943 JsonArrayWriter( std::ostream& os, std::uint64_t indent_level ); 9944 9945 JsonArrayWriter( JsonArrayWriter&& source ) noexcept; 9946 JsonArrayWriter& operator=( JsonArrayWriter&& source ) = delete; 9947 9948 ~JsonArrayWriter(); 9949 9950 JsonObjectWriter writeObject(); 9951 JsonArrayWriter writeArray(); 9952 9953 template <typename T> 9954 JsonArrayWriter& write( T const& value ) { 9955 return writeImpl( value ); 9956 } 9957 9958 JsonArrayWriter& write( bool value ); 9959 9960 private: 9961 template <typename T> 9962 JsonArrayWriter& writeImpl( T const& value ) { 9963 JsonUtils::appendCommaNewline( 9964 m_os, m_should_comma, m_indent_level + 1 ); 9965 JsonValueWriter{ m_os }.write( value ); 9966 9967 return *this; 9968 } 9969 9970 std::ostream& m_os; 9971 std::uint64_t m_indent_level; 9972 bool m_should_comma = false; 9973 bool m_active = true; 9974 }; 9975 9976} // namespace Catch 9977 9978#endif // CATCH_JSONWRITER_HPP_INCLUDED 9979 9980 9981#ifndef CATCH_LEAK_DETECTOR_HPP_INCLUDED 9982#define CATCH_LEAK_DETECTOR_HPP_INCLUDED 9983 9984namespace Catch { 9985 9986 struct LeakDetector { 9987 LeakDetector(); 9988 ~LeakDetector(); 9989 }; 9990 9991} 9992#endif // CATCH_LEAK_DETECTOR_HPP_INCLUDED 9993 9994 9995#ifndef CATCH_LIST_HPP_INCLUDED 9996#define CATCH_LIST_HPP_INCLUDED 9997 9998 9999#include <set> 10000#include <string> 10001 10002 10003namespace Catch { 10004 10005 class IEventListener; 10006 class Config; 10007 10008 10009 struct ReporterDescription { 10010 std::string name, description; 10011 }; 10012 struct ListenerDescription { 10013 StringRef name; 10014 std::string description; 10015 }; 10016 10017 struct TagInfo { 10018 void add(StringRef spelling); 10019 std::string all() const; 10020 10021 std::set<StringRef> spellings; 10022 std::size_t count = 0; 10023 }; 10024 10025 bool list( IEventListener& reporter, Config const& config ); 10026 10027} // end namespace Catch 10028 10029#endif // CATCH_LIST_HPP_INCLUDED 10030 10031 10032#ifndef CATCH_OUTPUT_REDIRECT_HPP_INCLUDED 10033#define CATCH_OUTPUT_REDIRECT_HPP_INCLUDED 10034 10035 10036#include <cstdio> 10037#include <iosfwd> 10038#include <string> 10039 10040namespace Catch { 10041 10042 class RedirectedStream { 10043 std::ostream& m_originalStream; 10044 std::ostream& m_redirectionStream; 10045 std::streambuf* m_prevBuf; 10046 10047 public: 10048 RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream ); 10049 ~RedirectedStream(); 10050 }; 10051 10052 class RedirectedStdOut { 10053 ReusableStringStream m_rss; 10054 RedirectedStream m_cout; 10055 public: 10056 RedirectedStdOut(); 10057 auto str() const -> std::string; 10058 }; 10059 10060 // StdErr has two constituent streams in C++, std::cerr and std::clog 10061 // This means that we need to redirect 2 streams into 1 to keep proper 10062 // order of writes 10063 class RedirectedStdErr { 10064 ReusableStringStream m_rss; 10065 RedirectedStream m_cerr; 10066 RedirectedStream m_clog; 10067 public: 10068 RedirectedStdErr(); 10069 auto str() const -> std::string; 10070 }; 10071 10072 class RedirectedStreams { 10073 public: 10074 RedirectedStreams(RedirectedStreams const&) = delete; 10075 RedirectedStreams& operator=(RedirectedStreams const&) = delete; 10076 RedirectedStreams(RedirectedStreams&&) = delete; 10077 RedirectedStreams& operator=(RedirectedStreams&&) = delete; 10078 10079 RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr); 10080 ~RedirectedStreams(); 10081 private: 10082 std::string& m_redirectedCout; 10083 std::string& m_redirectedCerr; 10084 RedirectedStdOut m_redirectedStdOut; 10085 RedirectedStdErr m_redirectedStdErr; 10086 }; 10087 10088#if defined(CATCH_CONFIG_NEW_CAPTURE) 10089 10090 // Windows's implementation of std::tmpfile is terrible (it tries 10091 // to create a file inside system folder, thus requiring elevated 10092 // privileges for the binary), so we have to use tmpnam(_s) and 10093 // create the file ourselves there. 10094 class TempFile { 10095 public: 10096 TempFile(TempFile const&) = delete; 10097 TempFile& operator=(TempFile const&) = delete; 10098 TempFile(TempFile&&) = delete; 10099 TempFile& operator=(TempFile&&) = delete; 10100 10101 TempFile(); 10102 ~TempFile(); 10103 10104 std::FILE* getFile(); 10105 std::string getContents(); 10106 10107 private: 10108 std::FILE* m_file = nullptr; 10109 #if defined(_MSC_VER) 10110 char m_buffer[L_tmpnam] = { 0 }; 10111 #endif 10112 }; 10113 10114 10115 class OutputRedirect { 10116 public: 10117 OutputRedirect(OutputRedirect const&) = delete; 10118 OutputRedirect& operator=(OutputRedirect const&) = delete; 10119 OutputRedirect(OutputRedirect&&) = delete; 10120 OutputRedirect& operator=(OutputRedirect&&) = delete; 10121 10122 10123 OutputRedirect(std::string& stdout_dest, std::string& stderr_dest); 10124 ~OutputRedirect(); 10125 10126 private: 10127 int m_originalStdout = -1; 10128 int m_originalStderr = -1; 10129 TempFile m_stdoutFile; 10130 TempFile m_stderrFile; 10131 std::string& m_stdoutDest; 10132 std::string& m_stderrDest; 10133 }; 10134 10135#endif 10136 10137} // end namespace Catch 10138 10139#endif // CATCH_OUTPUT_REDIRECT_HPP_INCLUDED 10140 10141 10142#ifndef CATCH_PARSE_NUMBERS_HPP_INCLUDED 10143#define CATCH_PARSE_NUMBERS_HPP_INCLUDED 10144 10145 10146#include <string> 10147 10148namespace Catch { 10149 10150 /** 10151 * Parses unsigned int from the input, using provided base 10152 * 10153 * Effectively a wrapper around std::stoul but with better error checking 10154 * e.g. "-1" is rejected, instead of being parsed as UINT_MAX. 10155 */ 10156 Optional<unsigned int> parseUInt(std::string const& input, int base = 10); 10157} 10158 10159#endif // CATCH_PARSE_NUMBERS_HPP_INCLUDED 10160 10161 10162#ifndef CATCH_REPORTER_REGISTRY_HPP_INCLUDED 10163#define CATCH_REPORTER_REGISTRY_HPP_INCLUDED 10164 10165 10166#include <map> 10167#include <string> 10168#include <vector> 10169 10170namespace Catch { 10171 10172 class IEventListener; 10173 using IEventListenerPtr = Detail::unique_ptr<IEventListener>; 10174 class IReporterFactory; 10175 using IReporterFactoryPtr = Detail::unique_ptr<IReporterFactory>; 10176 struct ReporterConfig; 10177 class EventListenerFactory; 10178 10179 class ReporterRegistry { 10180 struct ReporterRegistryImpl; 10181 Detail::unique_ptr<ReporterRegistryImpl> m_impl; 10182 10183 public: 10184 ReporterRegistry(); 10185 ~ReporterRegistry(); // = default; 10186 10187 IEventListenerPtr create( std::string const& name, 10188 ReporterConfig&& config ) const; 10189 10190 void registerReporter( std::string const& name, 10191 IReporterFactoryPtr factory ); 10192 10193 void 10194 registerListener( Detail::unique_ptr<EventListenerFactory> factory ); 10195 10196 std::map<std::string, 10197 IReporterFactoryPtr, 10198 Detail::CaseInsensitiveLess> const& 10199 getFactories() const; 10200 10201 std::vector<Detail::unique_ptr<EventListenerFactory>> const& 10202 getListeners() const; 10203 }; 10204 10205} // end namespace Catch 10206 10207#endif // CATCH_REPORTER_REGISTRY_HPP_INCLUDED 10208 10209 10210#ifndef CATCH_RUN_CONTEXT_HPP_INCLUDED 10211#define CATCH_RUN_CONTEXT_HPP_INCLUDED 10212 10213 10214 10215#ifndef CATCH_TEST_CASE_TRACKER_HPP_INCLUDED 10216#define CATCH_TEST_CASE_TRACKER_HPP_INCLUDED 10217 10218 10219#include <string> 10220#include <vector> 10221 10222namespace Catch { 10223namespace TestCaseTracking { 10224 10225 struct NameAndLocation { 10226 std::string name; 10227 SourceLineInfo location; 10228 10229 NameAndLocation( std::string&& _name, SourceLineInfo const& _location ); 10230 friend bool operator==(NameAndLocation const& lhs, NameAndLocation const& rhs) { 10231 // This is a very cheap check that should have a very high hit rate. 10232 // If we get to SourceLineInfo::operator==, we will redo it, but the 10233 // cost of repeating is trivial at that point (we will be paying 10234 // multiple strcmp/memcmps at that point). 10235 if ( lhs.location.line != rhs.location.line ) { return false; } 10236 return lhs.name == rhs.name && lhs.location == rhs.location; 10237 } 10238 friend bool operator!=(NameAndLocation const& lhs, 10239 NameAndLocation const& rhs) { 10240 return !( lhs == rhs ); 10241 } 10242 }; 10243 10244 /** 10245 * This is a variant of `NameAndLocation` that does not own the name string 10246 * 10247 * This avoids extra allocations when trying to locate a tracker by its 10248 * name and location, as long as we make sure that trackers only keep 10249 * around the owning variant. 10250 */ 10251 struct NameAndLocationRef { 10252 StringRef name; 10253 SourceLineInfo location; 10254 10255 constexpr NameAndLocationRef( StringRef name_, 10256 SourceLineInfo location_ ): 10257 name( name_ ), location( location_ ) {} 10258 10259 friend bool operator==( NameAndLocation const& lhs, 10260 NameAndLocationRef const& rhs ) { 10261 // This is a very cheap check that should have a very high hit rate. 10262 // If we get to SourceLineInfo::operator==, we will redo it, but the 10263 // cost of repeating is trivial at that point (we will be paying 10264 // multiple strcmp/memcmps at that point). 10265 if ( lhs.location.line != rhs.location.line ) { return false; } 10266 return StringRef( lhs.name ) == rhs.name && 10267 lhs.location == rhs.location; 10268 } 10269 friend bool operator==( NameAndLocationRef const& lhs, 10270 NameAndLocation const& rhs ) { 10271 return rhs == lhs; 10272 } 10273 }; 10274 10275 class ITracker; 10276 10277 using ITrackerPtr = Catch::Detail::unique_ptr<ITracker>; 10278 10279 class ITracker { 10280 NameAndLocation m_nameAndLocation; 10281 10282 using Children = std::vector<ITrackerPtr>; 10283 10284 protected: 10285 enum CycleState { 10286 NotStarted, 10287 Executing, 10288 ExecutingChildren, 10289 NeedsAnotherRun, 10290 CompletedSuccessfully, 10291 Failed 10292 }; 10293 10294 ITracker* m_parent = nullptr; 10295 Children m_children; 10296 CycleState m_runState = NotStarted; 10297 10298 public: 10299 ITracker( NameAndLocation&& nameAndLoc, ITracker* parent ): 10300 m_nameAndLocation( CATCH_MOVE(nameAndLoc) ), 10301 m_parent( parent ) 10302 {} 10303 10304 10305 // static queries 10306 NameAndLocation const& nameAndLocation() const { 10307 return m_nameAndLocation; 10308 } 10309 ITracker* parent() const { 10310 return m_parent; 10311 } 10312 10313 virtual ~ITracker(); // = default 10314 10315 10316 // dynamic queries 10317 10318 //! Returns true if tracker run to completion (successfully or not) 10319 virtual bool isComplete() const = 0; 10320 //! Returns true if tracker run to completion successfully 10321 bool isSuccessfullyCompleted() const { 10322 return m_runState == CompletedSuccessfully; 10323 } 10324 //! Returns true if tracker has started but hasn't been completed 10325 bool isOpen() const; 10326 //! Returns true iff tracker has started 10327 bool hasStarted() const; 10328 10329 // actions 10330 virtual void close() = 0; // Successfully complete 10331 virtual void fail() = 0; 10332 void markAsNeedingAnotherRun(); 10333 10334 //! Register a nested ITracker 10335 void addChild( ITrackerPtr&& child ); 10336 /** 10337 * Returns ptr to specific child if register with this tracker. 10338 * 10339 * Returns nullptr if not found. 10340 */ 10341 ITracker* findChild( NameAndLocationRef const& nameAndLocation ); 10342 //! Have any children been added? 10343 bool hasChildren() const { 10344 return !m_children.empty(); 10345 } 10346 10347 10348 //! Marks tracker as executing a child, doing se recursively up the tree 10349 void openChild(); 10350 10351 /** 10352 * Returns true if the instance is a section tracker 10353 * 10354 * Subclasses should override to true if they are, replaces RTTI 10355 * for internal debug checks. 10356 */ 10357 virtual bool isSectionTracker() const; 10358 /** 10359 * Returns true if the instance is a generator tracker 10360 * 10361 * Subclasses should override to true if they are, replaces RTTI 10362 * for internal debug checks. 10363 */ 10364 virtual bool isGeneratorTracker() const; 10365 }; 10366 10367 class TrackerContext { 10368 10369 enum RunState { 10370 NotStarted, 10371 Executing, 10372 CompletedCycle 10373 }; 10374 10375 ITrackerPtr m_rootTracker; 10376 ITracker* m_currentTracker = nullptr; 10377 RunState m_runState = NotStarted; 10378 10379 public: 10380 10381 ITracker& startRun(); 10382 10383 void startCycle() { 10384 m_currentTracker = m_rootTracker.get(); 10385 m_runState = Executing; 10386 } 10387 void completeCycle(); 10388 10389 bool completedCycle() const; 10390 ITracker& currentTracker() { return *m_currentTracker; } 10391 void setCurrentTracker( ITracker* tracker ); 10392 }; 10393 10394 class TrackerBase : public ITracker { 10395 protected: 10396 10397 TrackerContext& m_ctx; 10398 10399 public: 10400 TrackerBase( NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent ); 10401 10402 bool isComplete() const override; 10403 10404 void open(); 10405 10406 void close() override; 10407 void fail() override; 10408 10409 private: 10410 void moveToParent(); 10411 void moveToThis(); 10412 }; 10413 10414 class SectionTracker : public TrackerBase { 10415 std::vector<StringRef> m_filters; 10416 // Note that lifetime-wise we piggy back off the name stored in the `ITracker` parent`. 10417 // Currently it allocates owns the name, so this is safe. If it is later refactored 10418 // to not own the name, the name still has to outlive the `ITracker` parent, so 10419 // this should still be safe. 10420 StringRef m_trimmed_name; 10421 public: 10422 SectionTracker( NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent ); 10423 10424 bool isSectionTracker() const override; 10425 10426 bool isComplete() const override; 10427 10428 static SectionTracker& acquire( TrackerContext& ctx, NameAndLocationRef const& nameAndLocation ); 10429 10430 void tryOpen(); 10431 10432 void addInitialFilters( std::vector<std::string> const& filters ); 10433 void addNextFilters( std::vector<StringRef> const& filters ); 10434 //! Returns filters active in this tracker 10435 std::vector<StringRef> const& getFilters() const { return m_filters; } 10436 //! Returns whitespace-trimmed name of the tracked section 10437 StringRef trimmedName() const; 10438 }; 10439 10440} // namespace TestCaseTracking 10441 10442using TestCaseTracking::ITracker; 10443using TestCaseTracking::TrackerContext; 10444using TestCaseTracking::SectionTracker; 10445 10446} // namespace Catch 10447 10448#endif // CATCH_TEST_CASE_TRACKER_HPP_INCLUDED 10449 10450#include <string> 10451 10452namespace Catch { 10453 10454 class IGeneratorTracker; 10455 class IConfig; 10456 class IEventListener; 10457 using IEventListenerPtr = Detail::unique_ptr<IEventListener>; 10458 10459 /////////////////////////////////////////////////////////////////////////// 10460 10461 class RunContext final : public IResultCapture { 10462 10463 public: 10464 RunContext( RunContext const& ) = delete; 10465 RunContext& operator =( RunContext const& ) = delete; 10466 10467 explicit RunContext( IConfig const* _config, IEventListenerPtr&& reporter ); 10468 10469 ~RunContext() override; 10470 10471 Totals runTest(TestCaseHandle const& testCase); 10472 10473 public: // IResultCapture 10474 10475 // Assertion handlers 10476 void handleExpr 10477 ( AssertionInfo const& info, 10478 ITransientExpression const& expr, 10479 AssertionReaction& reaction ) override; 10480 void handleMessage 10481 ( AssertionInfo const& info, 10482 ResultWas::OfType resultType, 10483 StringRef message, 10484 AssertionReaction& reaction ) override; 10485 void handleUnexpectedExceptionNotThrown 10486 ( AssertionInfo const& info, 10487 AssertionReaction& reaction ) override; 10488 void handleUnexpectedInflightException 10489 ( AssertionInfo const& info, 10490 std::string&& message, 10491 AssertionReaction& reaction ) override; 10492 void handleIncomplete 10493 ( AssertionInfo const& info ) override; 10494 void handleNonExpr 10495 ( AssertionInfo const &info, 10496 ResultWas::OfType resultType, 10497 AssertionReaction &reaction ) override; 10498 10499 void notifyAssertionStarted( AssertionInfo const& info ) override; 10500 bool sectionStarted( StringRef sectionName, 10501 SourceLineInfo const& sectionLineInfo, 10502 Counts& assertions ) override; 10503 10504 void sectionEnded( SectionEndInfo&& endInfo ) override; 10505 void sectionEndedEarly( SectionEndInfo&& endInfo ) override; 10506 10507 IGeneratorTracker* 10508 acquireGeneratorTracker( StringRef generatorName, 10509 SourceLineInfo const& lineInfo ) override; 10510 IGeneratorTracker* createGeneratorTracker( 10511 StringRef generatorName, 10512 SourceLineInfo lineInfo, 10513 Generators::GeneratorBasePtr&& generator ) override; 10514 10515 10516 void benchmarkPreparing( StringRef name ) override; 10517 void benchmarkStarting( BenchmarkInfo const& info ) override; 10518 void benchmarkEnded( BenchmarkStats<> const& stats ) override; 10519 void benchmarkFailed( StringRef error ) override; 10520 10521 void pushScopedMessage( MessageInfo const& message ) override; 10522 void popScopedMessage( MessageInfo const& message ) override; 10523 10524 void emplaceUnscopedMessage( MessageBuilder&& builder ) override; 10525 10526 std::string getCurrentTestName() const override; 10527 10528 const AssertionResult* getLastResult() const override; 10529 10530 void exceptionEarlyReported() override; 10531 10532 void handleFatalErrorCondition( StringRef message ) override; 10533 10534 bool lastAssertionPassed() override; 10535 10536 void assertionPassed() override; 10537 10538 public: 10539 // !TBD We need to do this another way! 10540 bool aborting() const; 10541 10542 private: 10543 10544 void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ); 10545 void invokeActiveTestCase(); 10546 10547 void resetAssertionInfo(); 10548 bool testForMissingAssertions( Counts& assertions ); 10549 10550 void assertionEnded( AssertionResult&& result ); 10551 void reportExpr 10552 ( AssertionInfo const &info, 10553 ResultWas::OfType resultType, 10554 ITransientExpression const *expr, 10555 bool negated ); 10556 10557 void populateReaction( AssertionReaction& reaction ); 10558 10559 private: 10560 10561 void handleUnfinishedSections(); 10562 10563 TestRunInfo m_runInfo; 10564 TestCaseHandle const* m_activeTestCase = nullptr; 10565 ITracker* m_testCaseTracker = nullptr; 10566 Optional<AssertionResult> m_lastResult; 10567 10568 IConfig const* m_config; 10569 Totals m_totals; 10570 IEventListenerPtr m_reporter; 10571 std::vector<MessageInfo> m_messages; 10572 std::vector<ScopedMessage> m_messageScopes; /* Keeps owners of so-called unscoped messages. */ 10573 AssertionInfo m_lastAssertionInfo; 10574 std::vector<SectionEndInfo> m_unfinishedSections; 10575 std::vector<ITracker*> m_activeSections; 10576 TrackerContext m_trackerContext; 10577 FatalConditionHandler m_fatalConditionhandler; 10578 bool m_lastAssertionPassed = false; 10579 bool m_shouldReportUnexpected = true; 10580 bool m_includeSuccessfulResults; 10581 }; 10582 10583 void seedRng(IConfig const& config); 10584 unsigned int rngSeed(); 10585} // end namespace Catch 10586 10587#endif // CATCH_RUN_CONTEXT_HPP_INCLUDED 10588 10589 10590#ifndef CATCH_SHARDING_HPP_INCLUDED 10591#define CATCH_SHARDING_HPP_INCLUDED 10592 10593#include <cassert> 10594#include <cmath> 10595#include <algorithm> 10596 10597namespace Catch { 10598 10599 template<typename Container> 10600 Container createShard(Container const& container, std::size_t const shardCount, std::size_t const shardIndex) { 10601 assert(shardCount > shardIndex); 10602 10603 if (shardCount == 1) { 10604 return container; 10605 } 10606 10607 const std::size_t totalTestCount = container.size(); 10608 10609 const std::size_t shardSize = totalTestCount / shardCount; 10610 const std::size_t leftoverTests = totalTestCount % shardCount; 10611 10612 const std::size_t startIndex = shardIndex * shardSize + (std::min)(shardIndex, leftoverTests); 10613 const std::size_t endIndex = (shardIndex + 1) * shardSize + (std::min)(shardIndex + 1, leftoverTests); 10614 10615 auto startIterator = std::next(container.begin(), static_cast<std::ptrdiff_t>(startIndex)); 10616 auto endIterator = std::next(container.begin(), static_cast<std::ptrdiff_t>(endIndex)); 10617 10618 return Container(startIterator, endIterator); 10619 } 10620 10621} 10622 10623#endif // CATCH_SHARDING_HPP_INCLUDED 10624 10625 10626#ifndef CATCH_SINGLETONS_HPP_INCLUDED 10627#define CATCH_SINGLETONS_HPP_INCLUDED 10628 10629namespace Catch { 10630 10631 struct ISingleton { 10632 virtual ~ISingleton(); // = default 10633 }; 10634 10635 10636 void addSingleton( ISingleton* singleton ); 10637 void cleanupSingletons(); 10638 10639 10640 template<typename SingletonImplT, typename InterfaceT = SingletonImplT, typename MutableInterfaceT = InterfaceT> 10641 class Singleton : SingletonImplT, public ISingleton { 10642 10643 static auto getInternal() -> Singleton* { 10644 static Singleton* s_instance = nullptr; 10645 if( !s_instance ) { 10646 s_instance = new Singleton; 10647 addSingleton( s_instance ); 10648 } 10649 return s_instance; 10650 } 10651 10652 public: 10653 static auto get() -> InterfaceT const& { 10654 return *getInternal(); 10655 } 10656 static auto getMutable() -> MutableInterfaceT& { 10657 return *getInternal(); 10658 } 10659 }; 10660 10661} // namespace Catch 10662 10663#endif // CATCH_SINGLETONS_HPP_INCLUDED 10664 10665 10666#ifndef CATCH_STARTUP_EXCEPTION_REGISTRY_HPP_INCLUDED 10667#define CATCH_STARTUP_EXCEPTION_REGISTRY_HPP_INCLUDED 10668 10669 10670#include <vector> 10671#include <exception> 10672 10673namespace Catch { 10674 10675 class StartupExceptionRegistry { 10676#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 10677 public: 10678 void add(std::exception_ptr const& exception) noexcept; 10679 std::vector<std::exception_ptr> const& getExceptions() const noexcept; 10680 private: 10681 std::vector<std::exception_ptr> m_exceptions; 10682#endif 10683 }; 10684 10685} // end namespace Catch 10686 10687#endif // CATCH_STARTUP_EXCEPTION_REGISTRY_HPP_INCLUDED 10688 10689 10690 10691#ifndef CATCH_STDSTREAMS_HPP_INCLUDED 10692#define CATCH_STDSTREAMS_HPP_INCLUDED 10693 10694#include <iosfwd> 10695 10696namespace Catch { 10697 10698 std::ostream& cout(); 10699 std::ostream& cerr(); 10700 std::ostream& clog(); 10701 10702} // namespace Catch 10703 10704#endif 10705 10706 10707#ifndef CATCH_STRING_MANIP_HPP_INCLUDED 10708#define CATCH_STRING_MANIP_HPP_INCLUDED 10709 10710 10711#include <cstdint> 10712#include <string> 10713#include <iosfwd> 10714#include <vector> 10715 10716namespace Catch { 10717 10718 bool startsWith( std::string const& s, std::string const& prefix ); 10719 bool startsWith( StringRef s, char prefix ); 10720 bool endsWith( std::string const& s, std::string const& suffix ); 10721 bool endsWith( std::string const& s, char suffix ); 10722 bool contains( std::string const& s, std::string const& infix ); 10723 void toLowerInPlace( std::string& s ); 10724 std::string toLower( std::string const& s ); 10725 char toLower( char c ); 10726 //! Returns a new string without whitespace at the start/end 10727 std::string trim( std::string const& str ); 10728 //! Returns a substring of the original ref without whitespace. Beware lifetimes! 10729 StringRef trim(StringRef ref); 10730 10731 // !!! Be aware, returns refs into original string - make sure original string outlives them 10732 std::vector<StringRef> splitStringRef( StringRef str, char delimiter ); 10733 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ); 10734 10735 /** 10736 * Helper for streaming a "count [maybe-plural-of-label]" human-friendly string 10737 * 10738 * Usage example: 10739 * ```cpp 10740 * std::cout << "Found " << pluralise(count, "error") << '\n'; 10741 * ``` 10742 * 10743 * **Important:** The provided string must outlive the instance 10744 */ 10745 class pluralise { 10746 std::uint64_t m_count; 10747 StringRef m_label; 10748 10749 public: 10750 constexpr pluralise(std::uint64_t count, StringRef label): 10751 m_count(count), 10752 m_label(label) 10753 {} 10754 10755 friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); 10756 }; 10757} 10758 10759#endif // CATCH_STRING_MANIP_HPP_INCLUDED 10760 10761 10762#ifndef CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED 10763#define CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED 10764 10765 10766#include <map> 10767#include <string> 10768 10769namespace Catch { 10770 struct SourceLineInfo; 10771 10772 class TagAliasRegistry : public ITagAliasRegistry { 10773 public: 10774 ~TagAliasRegistry() override; 10775 TagAlias const* find( std::string const& alias ) const override; 10776 std::string expandAliases( std::string const& unexpandedTestSpec ) const override; 10777 void add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ); 10778 10779 private: 10780 std::map<std::string, TagAlias> m_registry; 10781 }; 10782 10783} // end namespace Catch 10784 10785#endif // CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED 10786 10787 10788#ifndef CATCH_TEST_CASE_INFO_HASHER_HPP_INCLUDED 10789#define CATCH_TEST_CASE_INFO_HASHER_HPP_INCLUDED 10790 10791#include <cstdint> 10792 10793namespace Catch { 10794 10795 struct TestCaseInfo; 10796 10797 class TestCaseInfoHasher { 10798 public: 10799 using hash_t = std::uint64_t; 10800 TestCaseInfoHasher( hash_t seed ); 10801 uint32_t operator()( TestCaseInfo const& t ) const; 10802 10803 private: 10804 hash_t m_seed; 10805 }; 10806 10807} // namespace Catch 10808 10809#endif /* CATCH_TEST_CASE_INFO_HASHER_HPP_INCLUDED */ 10810 10811 10812#ifndef CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED 10813#define CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED 10814 10815 10816#include <vector> 10817 10818namespace Catch { 10819 10820 class IConfig; 10821 class ITestInvoker; 10822 class TestCaseHandle; 10823 class TestSpec; 10824 10825 std::vector<TestCaseHandle> sortTests( IConfig const& config, std::vector<TestCaseHandle> const& unsortedTestCases ); 10826 10827 bool isThrowSafe( TestCaseHandle const& testCase, IConfig const& config ); 10828 10829 std::vector<TestCaseHandle> filterTests( std::vector<TestCaseHandle> const& testCases, TestSpec const& testSpec, IConfig const& config ); 10830 std::vector<TestCaseHandle> const& getAllTestCasesSorted( IConfig const& config ); 10831 10832 class TestRegistry : public ITestCaseRegistry { 10833 public: 10834 void registerTest( Detail::unique_ptr<TestCaseInfo> testInfo, Detail::unique_ptr<ITestInvoker> testInvoker ); 10835 10836 std::vector<TestCaseInfo*> const& getAllInfos() const override; 10837 std::vector<TestCaseHandle> const& getAllTests() const override; 10838 std::vector<TestCaseHandle> const& getAllTestsSorted( IConfig const& config ) const override; 10839 10840 ~TestRegistry() override; // = default 10841 10842 private: 10843 std::vector<Detail::unique_ptr<TestCaseInfo>> m_owned_test_infos; 10844 // Keeps a materialized vector for `getAllInfos`. 10845 // We should get rid of that eventually (see interface note) 10846 std::vector<TestCaseInfo*> m_viewed_test_infos; 10847 10848 std::vector<Detail::unique_ptr<ITestInvoker>> m_invokers; 10849 std::vector<TestCaseHandle> m_handles; 10850 mutable TestRunOrder m_currentSortOrder = TestRunOrder::Declared; 10851 mutable std::vector<TestCaseHandle> m_sortedFunctions; 10852 }; 10853 10854 /////////////////////////////////////////////////////////////////////////// 10855 10856 10857} // end namespace Catch 10858 10859 10860#endif // CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED 10861 10862 10863#ifndef CATCH_TEST_SPEC_PARSER_HPP_INCLUDED 10864#define CATCH_TEST_SPEC_PARSER_HPP_INCLUDED 10865 10866#ifdef __clang__ 10867#pragma clang diagnostic push 10868#pragma clang diagnostic ignored "-Wpadded" 10869#endif 10870 10871 10872#include <vector> 10873#include <string> 10874 10875namespace Catch { 10876 10877 class ITagAliasRegistry; 10878 10879 class TestSpecParser { 10880 enum Mode{ None, Name, QuotedName, Tag, EscapedName }; 10881 Mode m_mode = None; 10882 Mode lastMode = None; 10883 bool m_exclusion = false; 10884 std::size_t m_pos = 0; 10885 std::size_t m_realPatternPos = 0; 10886 std::string m_arg; 10887 std::string m_substring; 10888 std::string m_patternName; 10889 std::vector<std::size_t> m_escapeChars; 10890 TestSpec::Filter m_currentFilter; 10891 TestSpec m_testSpec; 10892 ITagAliasRegistry const* m_tagAliases = nullptr; 10893 10894 public: 10895 TestSpecParser( ITagAliasRegistry const& tagAliases ); 10896 10897 TestSpecParser& parse( std::string const& arg ); 10898 TestSpec testSpec(); 10899 10900 private: 10901 bool visitChar( char c ); 10902 void startNewMode( Mode mode ); 10903 bool processNoneChar( char c ); 10904 void processNameChar( char c ); 10905 bool processOtherChar( char c ); 10906 void endMode(); 10907 void escape(); 10908 bool isControlChar( char c ) const; 10909 void saveLastMode(); 10910 void revertBackToLastMode(); 10911 void addFilter(); 10912 bool separate(); 10913 10914 // Handles common preprocessing of the pattern for name/tag patterns 10915 std::string preprocessPattern(); 10916 // Adds the current pattern as a test name 10917 void addNamePattern(); 10918 // Adds the current pattern as a tag 10919 void addTagPattern(); 10920 10921 inline void addCharToPattern(char c) { 10922 m_substring += c; 10923 m_patternName += c; 10924 m_realPatternPos++; 10925 } 10926 10927 }; 10928 10929} // namespace Catch 10930 10931#ifdef __clang__ 10932#pragma clang diagnostic pop 10933#endif 10934 10935#endif // CATCH_TEST_SPEC_PARSER_HPP_INCLUDED 10936 10937 10938#ifndef CATCH_TEXTFLOW_HPP_INCLUDED 10939#define CATCH_TEXTFLOW_HPP_INCLUDED 10940 10941 10942#include <cassert> 10943#include <string> 10944#include <vector> 10945 10946namespace Catch { 10947 namespace TextFlow { 10948 10949 class Columns; 10950 10951 /** 10952 * Abstraction for a string with ansi escape sequences that 10953 * automatically skips over escapes when iterating. Only graphical 10954 * escape sequences are considered. 10955 * 10956 * Internal representation: 10957 * An escape sequence looks like \033[39;49m 10958 * We need bidirectional iteration and the unbound length of escape 10959 * sequences poses a problem for operator-- To make this work we'll 10960 * replace the last `m` with a 0xff (this is a codepoint that won't have 10961 * any utf-8 meaning). 10962 */ 10963 class AnsiSkippingString { 10964 std::string m_string; 10965 std::size_t m_size = 0; 10966 10967 // perform 0xff replacement and calculate m_size 10968 void preprocessString(); 10969 10970 public: 10971 class const_iterator; 10972 using iterator = const_iterator; 10973 // note: must be u-suffixed or this will cause a "truncation of 10974 // constant value" warning on MSVC 10975 static constexpr char sentinel = static_cast<char>( 0xffu ); 10976 10977 explicit AnsiSkippingString( std::string const& text ); 10978 explicit AnsiSkippingString( std::string&& text ); 10979 10980 const_iterator begin() const; 10981 const_iterator end() const; 10982 10983 size_t size() const { return m_size; } 10984 10985 std::string substring( const_iterator begin, 10986 const_iterator end ) const; 10987 }; 10988 10989 class AnsiSkippingString::const_iterator { 10990 friend AnsiSkippingString; 10991 struct EndTag {}; 10992 10993 const std::string* m_string; 10994 std::string::const_iterator m_it; 10995 10996 explicit const_iterator( const std::string& string, EndTag ): 10997 m_string( &string ), m_it( string.end() ) {} 10998 10999 void tryParseAnsiEscapes(); 11000 void advance(); 11001 void unadvance(); 11002 11003 public: 11004 using difference_type = std::ptrdiff_t; 11005 using value_type = char; 11006 using pointer = value_type*; 11007 using reference = value_type&; 11008 using iterator_category = std::bidirectional_iterator_tag; 11009 11010 explicit const_iterator( const std::string& string ): 11011 m_string( &string ), m_it( string.begin() ) { 11012 tryParseAnsiEscapes(); 11013 } 11014 11015 char operator*() const { return *m_it; } 11016 11017 const_iterator& operator++() { 11018 advance(); 11019 return *this; 11020 } 11021 const_iterator operator++( int ) { 11022 iterator prev( *this ); 11023 operator++(); 11024 return prev; 11025 } 11026 const_iterator& operator--() { 11027 unadvance(); 11028 return *this; 11029 } 11030 const_iterator operator--( int ) { 11031 iterator prev( *this ); 11032 operator--(); 11033 return prev; 11034 } 11035 11036 bool operator==( const_iterator const& other ) const { 11037 return m_it == other.m_it; 11038 } 11039 bool operator!=( const_iterator const& other ) const { 11040 return !operator==( other ); 11041 } 11042 bool operator<=( const_iterator const& other ) const { 11043 return m_it <= other.m_it; 11044 } 11045 11046 const_iterator oneBefore() const { 11047 auto it = *this; 11048 return --it; 11049 } 11050 }; 11051 11052 /** 11053 * Represents a column of text with specific width and indentation 11054 * 11055 * When written out to a stream, it will perform linebreaking 11056 * of the provided text so that the written lines fit within 11057 * target width. 11058 */ 11059 class Column { 11060 // String to be written out 11061 AnsiSkippingString m_string; 11062 // Width of the column for linebreaking 11063 size_t m_width = CATCH_CONFIG_CONSOLE_WIDTH - 1; 11064 // Indentation of other lines (including first if initial indent is 11065 // unset) 11066 size_t m_indent = 0; 11067 // Indentation of the first line 11068 size_t m_initialIndent = std::string::npos; 11069 11070 public: 11071 /** 11072 * Iterates "lines" in `Column` and returns them 11073 */ 11074 class const_iterator { 11075 friend Column; 11076 struct EndTag {}; 11077 11078 Column const& m_column; 11079 // Where does the current line start? 11080 AnsiSkippingString::const_iterator m_lineStart; 11081 // How long should the current line be? 11082 AnsiSkippingString::const_iterator m_lineEnd; 11083 // How far have we checked the string to iterate? 11084 AnsiSkippingString::const_iterator m_parsedTo; 11085 // Should a '-' be appended to the line? 11086 bool m_addHyphen = false; 11087 11088 const_iterator( Column const& column, EndTag ): 11089 m_column( column ), 11090 m_lineStart( m_column.m_string.end() ), 11091 m_lineEnd( column.m_string.end() ), 11092 m_parsedTo( column.m_string.end() ) {} 11093 11094 // Calculates the length of the current line 11095 void calcLength(); 11096 11097 // Returns current indentation width 11098 size_t indentSize() const; 11099 11100 // Creates an indented and (optionally) suffixed string from 11101 // current iterator position, indentation and length. 11102 std::string addIndentAndSuffix( 11103 AnsiSkippingString::const_iterator start, 11104 AnsiSkippingString::const_iterator end ) const; 11105 11106 public: 11107 using difference_type = std::ptrdiff_t; 11108 using value_type = std::string; 11109 using pointer = value_type*; 11110 using reference = value_type&; 11111 using iterator_category = std::forward_iterator_tag; 11112 11113 explicit const_iterator( Column const& column ); 11114 11115 std::string operator*() const; 11116 11117 const_iterator& operator++(); 11118 const_iterator operator++( int ); 11119 11120 bool operator==( const_iterator const& other ) const { 11121 return m_lineStart == other.m_lineStart && 11122 &m_column == &other.m_column; 11123 } 11124 bool operator!=( const_iterator const& other ) const { 11125 return !operator==( other ); 11126 } 11127 }; 11128 using iterator = const_iterator; 11129 11130 explicit Column( std::string const& text ): m_string( text ) {} 11131 explicit Column( std::string&& text ): 11132 m_string( CATCH_MOVE( text ) ) {} 11133 11134 Column& width( size_t newWidth ) & { 11135 assert( newWidth > 0 ); 11136 m_width = newWidth; 11137 return *this; 11138 } 11139 Column&& width( size_t newWidth ) && { 11140 assert( newWidth > 0 ); 11141 m_width = newWidth; 11142 return CATCH_MOVE( *this ); 11143 } 11144 Column& indent( size_t newIndent ) & { 11145 m_indent = newIndent; 11146 return *this; 11147 } 11148 Column&& indent( size_t newIndent ) && { 11149 m_indent = newIndent; 11150 return CATCH_MOVE( *this ); 11151 } 11152 Column& initialIndent( size_t newIndent ) & { 11153 m_initialIndent = newIndent; 11154 return *this; 11155 } 11156 Column&& initialIndent( size_t newIndent ) && { 11157 m_initialIndent = newIndent; 11158 return CATCH_MOVE( *this ); 11159 } 11160 11161 size_t width() const { return m_width; } 11162 const_iterator begin() const { return const_iterator( *this ); } 11163 const_iterator end() const { 11164 return { *this, const_iterator::EndTag{} }; 11165 } 11166 11167 friend std::ostream& operator<<( std::ostream& os, 11168 Column const& col ); 11169 11170 friend Columns operator+( Column const& lhs, Column const& rhs ); 11171 friend Columns operator+( Column&& lhs, Column&& rhs ); 11172 }; 11173 11174 //! Creates a column that serves as an empty space of specific width 11175 Column Spacer( size_t spaceWidth ); 11176 11177 class Columns { 11178 std::vector<Column> m_columns; 11179 11180 public: 11181 class iterator { 11182 friend Columns; 11183 struct EndTag {}; 11184 11185 std::vector<Column> const& m_columns; 11186 std::vector<Column::const_iterator> m_iterators; 11187 size_t m_activeIterators; 11188 11189 iterator( Columns const& columns, EndTag ); 11190 11191 public: 11192 using difference_type = std::ptrdiff_t; 11193 using value_type = std::string; 11194 using pointer = value_type*; 11195 using reference = value_type&; 11196 using iterator_category = std::forward_iterator_tag; 11197 11198 explicit iterator( Columns const& columns ); 11199 11200 auto operator==( iterator const& other ) const -> bool { 11201 return m_iterators == other.m_iterators; 11202 } 11203 auto operator!=( iterator const& other ) const -> bool { 11204 return m_iterators != other.m_iterators; 11205 } 11206 std::string operator*() const; 11207 iterator& operator++(); 11208 iterator operator++( int ); 11209 }; 11210 using const_iterator = iterator; 11211 11212 iterator begin() const { return iterator( *this ); } 11213 iterator end() const { return { *this, iterator::EndTag() }; } 11214 11215 friend Columns& operator+=( Columns& lhs, Column const& rhs ); 11216 friend Columns& operator+=( Columns& lhs, Column&& rhs ); 11217 friend Columns operator+( Columns const& lhs, Column const& rhs ); 11218 friend Columns operator+( Columns&& lhs, Column&& rhs ); 11219 11220 friend std::ostream& operator<<( std::ostream& os, 11221 Columns const& cols ); 11222 }; 11223 11224 } // namespace TextFlow 11225} // namespace Catch 11226#endif // CATCH_TEXTFLOW_HPP_INCLUDED 11227 11228 11229#ifndef CATCH_TO_STRING_HPP_INCLUDED 11230#define CATCH_TO_STRING_HPP_INCLUDED 11231 11232#include <string> 11233 11234 11235namespace Catch { 11236 template <typename T> 11237 std::string to_string(T const& t) { 11238#if defined(CATCH_CONFIG_CPP11_TO_STRING) 11239 return std::to_string(t); 11240#else 11241 ReusableStringStream rss; 11242 rss << t; 11243 return rss.str(); 11244#endif 11245 } 11246} // end namespace Catch 11247 11248#endif // CATCH_TO_STRING_HPP_INCLUDED 11249 11250 11251#ifndef CATCH_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED 11252#define CATCH_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED 11253 11254namespace Catch { 11255 bool uncaught_exceptions(); 11256} // end namespace Catch 11257 11258#endif // CATCH_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED 11259 11260 11261#ifndef CATCH_XMLWRITER_HPP_INCLUDED 11262#define CATCH_XMLWRITER_HPP_INCLUDED 11263 11264 11265#include <iosfwd> 11266#include <vector> 11267 11268namespace Catch { 11269 enum class XmlFormatting { 11270 None = 0x00, 11271 Indent = 0x01, 11272 Newline = 0x02, 11273 }; 11274 11275 XmlFormatting operator | (XmlFormatting lhs, XmlFormatting rhs); 11276 XmlFormatting operator & (XmlFormatting lhs, XmlFormatting rhs); 11277 11278 /** 11279 * Helper for XML-encoding text (escaping angle brackets, quotes, etc) 11280 * 11281 * Note: doesn't take ownership of passed strings, and thus the 11282 * encoded string must outlive the encoding instance. 11283 */ 11284 class XmlEncode { 11285 public: 11286 enum ForWhat { ForTextNodes, ForAttributes }; 11287 11288 XmlEncode( StringRef str, ForWhat forWhat = ForTextNodes ); 11289 11290 void encodeTo( std::ostream& os ) const; 11291 11292 friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ); 11293 11294 private: 11295 StringRef m_str; 11296 ForWhat m_forWhat; 11297 }; 11298 11299 class XmlWriter { 11300 public: 11301 11302 class ScopedElement { 11303 public: 11304 ScopedElement( XmlWriter* writer, XmlFormatting fmt ); 11305 11306 ScopedElement( ScopedElement&& other ) noexcept; 11307 ScopedElement& operator=( ScopedElement&& other ) noexcept; 11308 11309 ~ScopedElement(); 11310 11311 ScopedElement& 11312 writeText( StringRef text, 11313 XmlFormatting fmt = XmlFormatting::Newline | 11314 XmlFormatting::Indent ); 11315 11316 ScopedElement& writeAttribute( StringRef name, 11317 StringRef attribute ); 11318 template <typename T, 11319 // Without this SFINAE, this overload is a better match 11320 // for `std::string`, `char const*`, `char const[N]` args. 11321 // While it would still work, it would cause code bloat 11322 // and multiple iteration over the strings 11323 typename = typename std::enable_if_t< 11324 !std::is_convertible<T, StringRef>::value>> 11325 ScopedElement& writeAttribute( StringRef name, 11326 T const& attribute ) { 11327 m_writer->writeAttribute( name, attribute ); 11328 return *this; 11329 } 11330 11331 private: 11332 XmlWriter* m_writer = nullptr; 11333 XmlFormatting m_fmt; 11334 }; 11335 11336 XmlWriter( std::ostream& os ); 11337 ~XmlWriter(); 11338 11339 XmlWriter( XmlWriter const& ) = delete; 11340 XmlWriter& operator=( XmlWriter const& ) = delete; 11341 11342 XmlWriter& startElement( std::string const& name, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); 11343 11344 ScopedElement scopedElement( std::string const& name, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); 11345 11346 XmlWriter& endElement(XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); 11347 11348 //! The attribute content is XML-encoded 11349 XmlWriter& writeAttribute( StringRef name, StringRef attribute ); 11350 11351 //! Writes the attribute as "true/false" 11352 XmlWriter& writeAttribute( StringRef name, bool attribute ); 11353 11354 //! The attribute content is XML-encoded 11355 XmlWriter& writeAttribute( StringRef name, char const* attribute ); 11356 11357 //! The attribute value must provide op<<(ostream&, T). The resulting 11358 //! serialization is XML-encoded 11359 template <typename T, 11360 // Without this SFINAE, this overload is a better match 11361 // for `std::string`, `char const*`, `char const[N]` args. 11362 // While it would still work, it would cause code bloat 11363 // and multiple iteration over the strings 11364 typename = typename std::enable_if_t< 11365 !std::is_convertible<T, StringRef>::value>> 11366 XmlWriter& writeAttribute( StringRef name, T const& attribute ) { 11367 ReusableStringStream rss; 11368 rss << attribute; 11369 return writeAttribute( name, rss.str() ); 11370 } 11371 11372 //! Writes escaped `text` in a element 11373 XmlWriter& writeText( StringRef text, 11374 XmlFormatting fmt = XmlFormatting::Newline | 11375 XmlFormatting::Indent ); 11376 11377 //! Writes XML comment as "<!-- text -->" 11378 XmlWriter& writeComment( StringRef text, 11379 XmlFormatting fmt = XmlFormatting::Newline | 11380 XmlFormatting::Indent ); 11381 11382 void writeStylesheetRef( StringRef url ); 11383 11384 void ensureTagClosed(); 11385 11386 private: 11387 11388 void applyFormatting(XmlFormatting fmt); 11389 11390 void writeDeclaration(); 11391 11392 void newlineIfNecessary(); 11393 11394 bool m_tagIsOpen = false; 11395 bool m_needsNewline = false; 11396 std::vector<std::string> m_tags; 11397 std::string m_indent; 11398 std::ostream& m_os; 11399 }; 11400 11401} 11402 11403#endif // CATCH_XMLWRITER_HPP_INCLUDED 11404 11405 11406/** \file 11407 * This is a convenience header for Catch2's Matcher support. It includes 11408 * **all** of Catch2 headers related to matchers. 11409 * 11410 * Generally the Catch2 users should use specific includes they need, 11411 * but this header can be used instead for ease-of-experimentation, or 11412 * just plain convenience, at the cost of increased compilation times. 11413 * 11414 * When a new header is added to either the `matchers` folder, or to 11415 * the corresponding internal subfolder, it should be added here. 11416 */ 11417 11418#ifndef CATCH_MATCHERS_ALL_HPP_INCLUDED 11419#define CATCH_MATCHERS_ALL_HPP_INCLUDED 11420 11421 11422 11423#ifndef CATCH_MATCHERS_HPP_INCLUDED 11424#define CATCH_MATCHERS_HPP_INCLUDED 11425 11426 11427 11428#ifndef CATCH_MATCHERS_IMPL_HPP_INCLUDED 11429#define CATCH_MATCHERS_IMPL_HPP_INCLUDED 11430 11431 11432#include <string> 11433 11434namespace Catch { 11435 11436#ifdef __clang__ 11437# pragma clang diagnostic push 11438# pragma clang diagnostic ignored "-Wsign-compare" 11439# pragma clang diagnostic ignored "-Wnon-virtual-dtor" 11440#elif defined __GNUC__ 11441# pragma GCC diagnostic push 11442# pragma GCC diagnostic ignored "-Wsign-compare" 11443# pragma GCC diagnostic ignored "-Wnon-virtual-dtor" 11444#endif 11445 11446 template<typename ArgT, typename MatcherT> 11447 class MatchExpr : public ITransientExpression { 11448 ArgT && m_arg; 11449 MatcherT const& m_matcher; 11450 public: 11451 MatchExpr( ArgT && arg, MatcherT const& matcher ) 11452 : ITransientExpression{ true, matcher.match( arg ) }, // not forwarding arg here on purpose 11453 m_arg( CATCH_FORWARD(arg) ), 11454 m_matcher( matcher ) 11455 {} 11456 11457 void streamReconstructedExpression( std::ostream& os ) const override { 11458 os << Catch::Detail::stringify( m_arg ) 11459 << ' ' 11460 << m_matcher.toString(); 11461 } 11462 }; 11463 11464#ifdef __clang__ 11465# pragma clang diagnostic pop 11466#elif defined __GNUC__ 11467# pragma GCC diagnostic pop 11468#endif 11469 11470 11471 namespace Matchers { 11472 template <typename ArgT> 11473 class MatcherBase; 11474 } 11475 11476 using StringMatcher = Matchers::MatcherBase<std::string>; 11477 11478 void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher ); 11479 11480 template<typename ArgT, typename MatcherT> 11481 auto makeMatchExpr( ArgT && arg, MatcherT const& matcher ) -> MatchExpr<ArgT, MatcherT> { 11482 return MatchExpr<ArgT, MatcherT>( CATCH_FORWARD(arg), matcher ); 11483 } 11484 11485} // namespace Catch 11486 11487 11488/////////////////////////////////////////////////////////////////////////////// 11489#define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ 11490 do { \ 11491 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ 11492 INTERNAL_CATCH_TRY { \ 11493 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher ) ); \ 11494 } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ 11495 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 11496 } while( false ) 11497 11498 11499/////////////////////////////////////////////////////////////////////////////// 11500#define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \ 11501 do { \ 11502 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ 11503 if( catchAssertionHandler.allowThrows() ) \ 11504 try { \ 11505 static_cast<void>(__VA_ARGS__ ); \ 11506 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 11507 } \ 11508 catch( exceptionType const& ex ) { \ 11509 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( ex, matcher ) ); \ 11510 } \ 11511 catch( ... ) { \ 11512 catchAssertionHandler.handleUnexpectedInflightException(); \ 11513 } \ 11514 else \ 11515 catchAssertionHandler.handleThrowingCallSkipped(); \ 11516 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 11517 } while( false ) 11518 11519 11520#endif // CATCH_MATCHERS_IMPL_HPP_INCLUDED 11521 11522#include <string> 11523#include <vector> 11524 11525namespace Catch { 11526namespace Matchers { 11527 11528 class MatcherUntypedBase { 11529 public: 11530 MatcherUntypedBase() = default; 11531 11532 MatcherUntypedBase(MatcherUntypedBase const&) = default; 11533 MatcherUntypedBase(MatcherUntypedBase&&) = default; 11534 11535 MatcherUntypedBase& operator = (MatcherUntypedBase const&) = delete; 11536 MatcherUntypedBase& operator = (MatcherUntypedBase&&) = delete; 11537 11538 std::string toString() const; 11539 11540 protected: 11541 virtual ~MatcherUntypedBase(); // = default; 11542 virtual std::string describe() const = 0; 11543 mutable std::string m_cachedToString; 11544 }; 11545 11546 11547 template<typename T> 11548 class MatcherBase : public MatcherUntypedBase { 11549 public: 11550 virtual bool match( T const& arg ) const = 0; 11551 }; 11552 11553 namespace Detail { 11554 11555 template<typename ArgT> 11556 class MatchAllOf final : public MatcherBase<ArgT> { 11557 std::vector<MatcherBase<ArgT> const*> m_matchers; 11558 11559 public: 11560 MatchAllOf() = default; 11561 MatchAllOf(MatchAllOf const&) = delete; 11562 MatchAllOf& operator=(MatchAllOf const&) = delete; 11563 MatchAllOf(MatchAllOf&&) = default; 11564 MatchAllOf& operator=(MatchAllOf&&) = default; 11565 11566 11567 bool match( ArgT const& arg ) const override { 11568 for( auto matcher : m_matchers ) { 11569 if (!matcher->match(arg)) 11570 return false; 11571 } 11572 return true; 11573 } 11574 std::string describe() const override { 11575 std::string description; 11576 description.reserve( 4 + m_matchers.size()*32 ); 11577 description += "( "; 11578 bool first = true; 11579 for( auto matcher : m_matchers ) { 11580 if( first ) 11581 first = false; 11582 else 11583 description += " and "; 11584 description += matcher->toString(); 11585 } 11586 description += " )"; 11587 return description; 11588 } 11589 11590 friend MatchAllOf operator&& (MatchAllOf&& lhs, MatcherBase<ArgT> const& rhs) { 11591 lhs.m_matchers.push_back(&rhs); 11592 return CATCH_MOVE(lhs); 11593 } 11594 friend MatchAllOf operator&& (MatcherBase<ArgT> const& lhs, MatchAllOf&& rhs) { 11595 rhs.m_matchers.insert(rhs.m_matchers.begin(), &lhs); 11596 return CATCH_MOVE(rhs); 11597 } 11598 }; 11599 11600 //! lvalue overload is intentionally deleted, users should 11601 //! not be trying to compose stored composition matchers 11602 template<typename ArgT> 11603 MatchAllOf<ArgT> operator&& (MatchAllOf<ArgT> const& lhs, MatcherBase<ArgT> const& rhs) = delete; 11604 //! lvalue overload is intentionally deleted, users should 11605 //! not be trying to compose stored composition matchers 11606 template<typename ArgT> 11607 MatchAllOf<ArgT> operator&& (MatcherBase<ArgT> const& lhs, MatchAllOf<ArgT> const& rhs) = delete; 11608 11609 template<typename ArgT> 11610 class MatchAnyOf final : public MatcherBase<ArgT> { 11611 std::vector<MatcherBase<ArgT> const*> m_matchers; 11612 public: 11613 MatchAnyOf() = default; 11614 MatchAnyOf(MatchAnyOf const&) = delete; 11615 MatchAnyOf& operator=(MatchAnyOf const&) = delete; 11616 MatchAnyOf(MatchAnyOf&&) = default; 11617 MatchAnyOf& operator=(MatchAnyOf&&) = default; 11618 11619 bool match( ArgT const& arg ) const override { 11620 for( auto matcher : m_matchers ) { 11621 if (matcher->match(arg)) 11622 return true; 11623 } 11624 return false; 11625 } 11626 std::string describe() const override { 11627 std::string description; 11628 description.reserve( 4 + m_matchers.size()*32 ); 11629 description += "( "; 11630 bool first = true; 11631 for( auto matcher : m_matchers ) { 11632 if( first ) 11633 first = false; 11634 else 11635 description += " or "; 11636 description += matcher->toString(); 11637 } 11638 description += " )"; 11639 return description; 11640 } 11641 11642 friend MatchAnyOf operator|| (MatchAnyOf&& lhs, MatcherBase<ArgT> const& rhs) { 11643 lhs.m_matchers.push_back(&rhs); 11644 return CATCH_MOVE(lhs); 11645 } 11646 friend MatchAnyOf operator|| (MatcherBase<ArgT> const& lhs, MatchAnyOf&& rhs) { 11647 rhs.m_matchers.insert(rhs.m_matchers.begin(), &lhs); 11648 return CATCH_MOVE(rhs); 11649 } 11650 }; 11651 11652 //! lvalue overload is intentionally deleted, users should 11653 //! not be trying to compose stored composition matchers 11654 template<typename ArgT> 11655 MatchAnyOf<ArgT> operator|| (MatchAnyOf<ArgT> const& lhs, MatcherBase<ArgT> const& rhs) = delete; 11656 //! lvalue overload is intentionally deleted, users should 11657 //! not be trying to compose stored composition matchers 11658 template<typename ArgT> 11659 MatchAnyOf<ArgT> operator|| (MatcherBase<ArgT> const& lhs, MatchAnyOf<ArgT> const& rhs) = delete; 11660 11661 template<typename ArgT> 11662 class MatchNotOf final : public MatcherBase<ArgT> { 11663 MatcherBase<ArgT> const& m_underlyingMatcher; 11664 11665 public: 11666 explicit MatchNotOf( MatcherBase<ArgT> const& underlyingMatcher ): 11667 m_underlyingMatcher( underlyingMatcher ) 11668 {} 11669 11670 bool match( ArgT const& arg ) const override { 11671 return !m_underlyingMatcher.match( arg ); 11672 } 11673 11674 std::string describe() const override { 11675 return "not " + m_underlyingMatcher.toString(); 11676 } 11677 }; 11678 11679 } // namespace Detail 11680 11681 template <typename T> 11682 Detail::MatchAllOf<T> operator&& (MatcherBase<T> const& lhs, MatcherBase<T> const& rhs) { 11683 return Detail::MatchAllOf<T>{} && lhs && rhs; 11684 } 11685 template <typename T> 11686 Detail::MatchAnyOf<T> operator|| (MatcherBase<T> const& lhs, MatcherBase<T> const& rhs) { 11687 return Detail::MatchAnyOf<T>{} || lhs || rhs; 11688 } 11689 11690 template <typename T> 11691 Detail::MatchNotOf<T> operator! (MatcherBase<T> const& matcher) { 11692 return Detail::MatchNotOf<T>{ matcher }; 11693 } 11694 11695 11696} // namespace Matchers 11697} // namespace Catch 11698 11699 11700#if defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE) 11701 #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) 11702 #define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) 11703 11704 #define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 11705 #define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 11706 11707 #define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) 11708 #define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) 11709 11710#elif defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE) 11711 11712 #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) (void)(0) 11713 #define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) 11714 11715 #define CATCH_CHECK_THROWS_WITH( expr, matcher ) (void)(0) 11716 #define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) 11717 11718 #define CATCH_CHECK_THAT( arg, matcher ) (void)(0) 11719 #define CATCH_REQUIRE_THAT( arg, matcher ) (void)(0) 11720 11721#elif !defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE) 11722 11723 #define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) 11724 #define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) 11725 11726 #define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 11727 #define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 11728 11729 #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) 11730 #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) 11731 11732#elif !defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE) 11733 11734 #define REQUIRE_THROWS_WITH( expr, matcher ) (void)(0) 11735 #define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) 11736 11737 #define CHECK_THROWS_WITH( expr, matcher ) (void)(0) 11738 #define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) 11739 11740 #define CHECK_THAT( arg, matcher ) (void)(0) 11741 #define REQUIRE_THAT( arg, matcher ) (void)(0) 11742 11743#endif // end of user facing macro declarations 11744 11745#endif // CATCH_MATCHERS_HPP_INCLUDED 11746 11747 11748#ifndef CATCH_MATCHERS_CONTAINER_PROPERTIES_HPP_INCLUDED 11749#define CATCH_MATCHERS_CONTAINER_PROPERTIES_HPP_INCLUDED 11750 11751 11752 11753#ifndef CATCH_MATCHERS_TEMPLATED_HPP_INCLUDED 11754#define CATCH_MATCHERS_TEMPLATED_HPP_INCLUDED 11755 11756 11757#include <array> 11758#include <algorithm> 11759#include <string> 11760#include <type_traits> 11761 11762namespace Catch { 11763namespace Matchers { 11764 class MatcherGenericBase : public MatcherUntypedBase { 11765 public: 11766 MatcherGenericBase() = default; 11767 ~MatcherGenericBase() override; // = default; 11768 11769 MatcherGenericBase(MatcherGenericBase const&) = default; 11770 MatcherGenericBase(MatcherGenericBase&&) = default; 11771 11772 MatcherGenericBase& operator=(MatcherGenericBase const&) = delete; 11773 MatcherGenericBase& operator=(MatcherGenericBase&&) = delete; 11774 }; 11775 11776 11777 namespace Detail { 11778 template<std::size_t N, std::size_t M> 11779 std::array<void const*, N + M> array_cat(std::array<void const*, N> && lhs, std::array<void const*, M> && rhs) { 11780 std::array<void const*, N + M> arr{}; 11781 std::copy_n(lhs.begin(), N, arr.begin()); 11782 std::copy_n(rhs.begin(), M, arr.begin() + N); 11783 return arr; 11784 } 11785 11786 template<std::size_t N> 11787 std::array<void const*, N+1> array_cat(std::array<void const*, N> && lhs, void const* rhs) { 11788 std::array<void const*, N+1> arr{}; 11789 std::copy_n(lhs.begin(), N, arr.begin()); 11790 arr[N] = rhs; 11791 return arr; 11792 } 11793 11794 template<std::size_t N> 11795 std::array<void const*, N+1> array_cat(void const* lhs, std::array<void const*, N> && rhs) { 11796 std::array<void const*, N + 1> arr{ {lhs} }; 11797 std::copy_n(rhs.begin(), N, arr.begin() + 1); 11798 return arr; 11799 } 11800 11801 template<typename T> 11802 using is_generic_matcher = std::is_base_of< 11803 Catch::Matchers::MatcherGenericBase, 11804 std::remove_cv_t<std::remove_reference_t<T>> 11805 >; 11806 11807 template<typename... Ts> 11808 using are_generic_matchers = Catch::Detail::conjunction<is_generic_matcher<Ts>...>; 11809 11810 template<typename T> 11811 using is_matcher = std::is_base_of< 11812 Catch::Matchers::MatcherUntypedBase, 11813 std::remove_cv_t<std::remove_reference_t<T>> 11814 >; 11815 11816 11817 template<std::size_t N, typename Arg> 11818 bool match_all_of(Arg&&, std::array<void const*, N> const&, std::index_sequence<>) { 11819 return true; 11820 } 11821 11822 template<typename T, typename... MatcherTs, std::size_t N, typename Arg, std::size_t Idx, std::size_t... Indices> 11823 bool match_all_of(Arg&& arg, std::array<void const*, N> const& matchers, std::index_sequence<Idx, Indices...>) { 11824 return static_cast<T const*>(matchers[Idx])->match(arg) && match_all_of<MatcherTs...>(arg, matchers, std::index_sequence<Indices...>{}); 11825 } 11826 11827 11828 template<std::size_t N, typename Arg> 11829 bool match_any_of(Arg&&, std::array<void const*, N> const&, std::index_sequence<>) { 11830 return false; 11831 } 11832 11833 template<typename T, typename... MatcherTs, std::size_t N, typename Arg, std::size_t Idx, std::size_t... Indices> 11834 bool match_any_of(Arg&& arg, std::array<void const*, N> const& matchers, std::index_sequence<Idx, Indices...>) { 11835 return static_cast<T const*>(matchers[Idx])->match(arg) || match_any_of<MatcherTs...>(arg, matchers, std::index_sequence<Indices...>{}); 11836 } 11837 11838 std::string describe_multi_matcher(StringRef combine, std::string const* descriptions_begin, std::string const* descriptions_end); 11839 11840 template<typename... MatcherTs, std::size_t... Idx> 11841 std::string describe_multi_matcher(StringRef combine, std::array<void const*, sizeof...(MatcherTs)> const& matchers, std::index_sequence<Idx...>) { 11842 std::array<std::string, sizeof...(MatcherTs)> descriptions {{ 11843 static_cast<MatcherTs const*>(matchers[Idx])->toString()... 11844 }}; 11845 11846 return describe_multi_matcher(combine, descriptions.data(), descriptions.data() + descriptions.size()); 11847 } 11848 11849 11850 template<typename... MatcherTs> 11851 class MatchAllOfGeneric final : public MatcherGenericBase { 11852 public: 11853 MatchAllOfGeneric(MatchAllOfGeneric const&) = delete; 11854 MatchAllOfGeneric& operator=(MatchAllOfGeneric const&) = delete; 11855 MatchAllOfGeneric(MatchAllOfGeneric&&) = default; 11856 MatchAllOfGeneric& operator=(MatchAllOfGeneric&&) = default; 11857 11858 MatchAllOfGeneric(MatcherTs const&... matchers) : m_matchers{ {std::addressof(matchers)...} } {} 11859 explicit MatchAllOfGeneric(std::array<void const*, sizeof...(MatcherTs)> matchers) : m_matchers{matchers} {} 11860 11861 template<typename Arg> 11862 bool match(Arg&& arg) const { 11863 return match_all_of<MatcherTs...>(arg, m_matchers, std::index_sequence_for<MatcherTs...>{}); 11864 } 11865 11866 std::string describe() const override { 11867 return describe_multi_matcher<MatcherTs...>(" and "_sr, m_matchers, std::index_sequence_for<MatcherTs...>{}); 11868 } 11869 11870 // Has to be public to enable the concatenating operators 11871 // below, because they are not friend of the RHS, only LHS, 11872 // and thus cannot access private fields of RHS 11873 std::array<void const*, sizeof...( MatcherTs )> m_matchers; 11874 11875 11876 //! Avoids type nesting for `GenericAllOf && GenericAllOf` case 11877 template<typename... MatchersRHS> 11878 friend 11879 MatchAllOfGeneric<MatcherTs..., MatchersRHS...> operator && ( 11880 MatchAllOfGeneric<MatcherTs...>&& lhs, 11881 MatchAllOfGeneric<MatchersRHS...>&& rhs) { 11882 return MatchAllOfGeneric<MatcherTs..., MatchersRHS...>{array_cat(CATCH_MOVE(lhs.m_matchers), CATCH_MOVE(rhs.m_matchers))}; 11883 } 11884 11885 //! Avoids type nesting for `GenericAllOf && some matcher` case 11886 template<typename MatcherRHS> 11887 friend std::enable_if_t<is_matcher<MatcherRHS>::value, 11888 MatchAllOfGeneric<MatcherTs..., MatcherRHS>> operator && ( 11889 MatchAllOfGeneric<MatcherTs...>&& lhs, 11890 MatcherRHS const& rhs) { 11891 return MatchAllOfGeneric<MatcherTs..., MatcherRHS>{array_cat(CATCH_MOVE(lhs.m_matchers), static_cast<void const*>(&rhs))}; 11892 } 11893 11894 //! Avoids type nesting for `some matcher && GenericAllOf` case 11895 template<typename MatcherLHS> 11896 friend std::enable_if_t<is_matcher<MatcherLHS>::value, 11897 MatchAllOfGeneric<MatcherLHS, MatcherTs...>> operator && ( 11898 MatcherLHS const& lhs, 11899 MatchAllOfGeneric<MatcherTs...>&& rhs) { 11900 return MatchAllOfGeneric<MatcherLHS, MatcherTs...>{array_cat(static_cast<void const*>(std::addressof(lhs)), CATCH_MOVE(rhs.m_matchers))}; 11901 } 11902 }; 11903 11904 11905 template<typename... MatcherTs> 11906 class MatchAnyOfGeneric final : public MatcherGenericBase { 11907 public: 11908 MatchAnyOfGeneric(MatchAnyOfGeneric const&) = delete; 11909 MatchAnyOfGeneric& operator=(MatchAnyOfGeneric const&) = delete; 11910 MatchAnyOfGeneric(MatchAnyOfGeneric&&) = default; 11911 MatchAnyOfGeneric& operator=(MatchAnyOfGeneric&&) = default; 11912 11913 MatchAnyOfGeneric(MatcherTs const&... matchers) : m_matchers{ {std::addressof(matchers)...} } {} 11914 explicit MatchAnyOfGeneric(std::array<void const*, sizeof...(MatcherTs)> matchers) : m_matchers{matchers} {} 11915 11916 template<typename Arg> 11917 bool match(Arg&& arg) const { 11918 return match_any_of<MatcherTs...>(arg, m_matchers, std::index_sequence_for<MatcherTs...>{}); 11919 } 11920 11921 std::string describe() const override { 11922 return describe_multi_matcher<MatcherTs...>(" or "_sr, m_matchers, std::index_sequence_for<MatcherTs...>{}); 11923 } 11924 11925 11926 // Has to be public to enable the concatenating operators 11927 // below, because they are not friend of the RHS, only LHS, 11928 // and thus cannot access private fields of RHS 11929 std::array<void const*, sizeof...( MatcherTs )> m_matchers; 11930 11931 //! Avoids type nesting for `GenericAnyOf || GenericAnyOf` case 11932 template<typename... MatchersRHS> 11933 friend MatchAnyOfGeneric<MatcherTs..., MatchersRHS...> operator || ( 11934 MatchAnyOfGeneric<MatcherTs...>&& lhs, 11935 MatchAnyOfGeneric<MatchersRHS...>&& rhs) { 11936 return MatchAnyOfGeneric<MatcherTs..., MatchersRHS...>{array_cat(CATCH_MOVE(lhs.m_matchers), CATCH_MOVE(rhs.m_matchers))}; 11937 } 11938 11939 //! Avoids type nesting for `GenericAnyOf || some matcher` case 11940 template<typename MatcherRHS> 11941 friend std::enable_if_t<is_matcher<MatcherRHS>::value, 11942 MatchAnyOfGeneric<MatcherTs..., MatcherRHS>> operator || ( 11943 MatchAnyOfGeneric<MatcherTs...>&& lhs, 11944 MatcherRHS const& rhs) { 11945 return MatchAnyOfGeneric<MatcherTs..., MatcherRHS>{array_cat(CATCH_MOVE(lhs.m_matchers), static_cast<void const*>(std::addressof(rhs)))}; 11946 } 11947 11948 //! Avoids type nesting for `some matcher || GenericAnyOf` case 11949 template<typename MatcherLHS> 11950 friend std::enable_if_t<is_matcher<MatcherLHS>::value, 11951 MatchAnyOfGeneric<MatcherLHS, MatcherTs...>> operator || ( 11952 MatcherLHS const& lhs, 11953 MatchAnyOfGeneric<MatcherTs...>&& rhs) { 11954 return MatchAnyOfGeneric<MatcherLHS, MatcherTs...>{array_cat(static_cast<void const*>(std::addressof(lhs)), CATCH_MOVE(rhs.m_matchers))}; 11955 } 11956 }; 11957 11958 11959 template<typename MatcherT> 11960 class MatchNotOfGeneric final : public MatcherGenericBase { 11961 MatcherT const& m_matcher; 11962 11963 public: 11964 MatchNotOfGeneric(MatchNotOfGeneric const&) = delete; 11965 MatchNotOfGeneric& operator=(MatchNotOfGeneric const&) = delete; 11966 MatchNotOfGeneric(MatchNotOfGeneric&&) = default; 11967 MatchNotOfGeneric& operator=(MatchNotOfGeneric&&) = default; 11968 11969 explicit MatchNotOfGeneric(MatcherT const& matcher) : m_matcher{matcher} {} 11970 11971 template<typename Arg> 11972 bool match(Arg&& arg) const { 11973 return !m_matcher.match(arg); 11974 } 11975 11976 std::string describe() const override { 11977 return "not " + m_matcher.toString(); 11978 } 11979 11980 //! Negating negation can just unwrap and return underlying matcher 11981 friend MatcherT const& operator ! (MatchNotOfGeneric<MatcherT> const& matcher) { 11982 return matcher.m_matcher; 11983 } 11984 }; 11985 } // namespace Detail 11986 11987 11988 // compose only generic matchers 11989 template<typename MatcherLHS, typename MatcherRHS> 11990 std::enable_if_t<Detail::are_generic_matchers<MatcherLHS, MatcherRHS>::value, Detail::MatchAllOfGeneric<MatcherLHS, MatcherRHS>> 11991 operator && (MatcherLHS const& lhs, MatcherRHS const& rhs) { 11992 return { lhs, rhs }; 11993 } 11994 11995 template<typename MatcherLHS, typename MatcherRHS> 11996 std::enable_if_t<Detail::are_generic_matchers<MatcherLHS, MatcherRHS>::value, Detail::MatchAnyOfGeneric<MatcherLHS, MatcherRHS>> 11997 operator || (MatcherLHS const& lhs, MatcherRHS const& rhs) { 11998 return { lhs, rhs }; 11999 } 12000 12001 //! Wrap provided generic matcher in generic negator 12002 template<typename MatcherT> 12003 std::enable_if_t<Detail::is_generic_matcher<MatcherT>::value, Detail::MatchNotOfGeneric<MatcherT>> 12004 operator ! (MatcherT const& matcher) { 12005 return Detail::MatchNotOfGeneric<MatcherT>{matcher}; 12006 } 12007 12008 12009 // compose mixed generic and non-generic matchers 12010 template<typename MatcherLHS, typename ArgRHS> 12011 std::enable_if_t<Detail::is_generic_matcher<MatcherLHS>::value, Detail::MatchAllOfGeneric<MatcherLHS, MatcherBase<ArgRHS>>> 12012 operator && (MatcherLHS const& lhs, MatcherBase<ArgRHS> const& rhs) { 12013 return { lhs, rhs }; 12014 } 12015 12016 template<typename ArgLHS, typename MatcherRHS> 12017 std::enable_if_t<Detail::is_generic_matcher<MatcherRHS>::value, Detail::MatchAllOfGeneric<MatcherBase<ArgLHS>, MatcherRHS>> 12018 operator && (MatcherBase<ArgLHS> const& lhs, MatcherRHS const& rhs) { 12019 return { lhs, rhs }; 12020 } 12021 12022 template<typename MatcherLHS, typename ArgRHS> 12023 std::enable_if_t<Detail::is_generic_matcher<MatcherLHS>::value, Detail::MatchAnyOfGeneric<MatcherLHS, MatcherBase<ArgRHS>>> 12024 operator || (MatcherLHS const& lhs, MatcherBase<ArgRHS> const& rhs) { 12025 return { lhs, rhs }; 12026 } 12027 12028 template<typename ArgLHS, typename MatcherRHS> 12029 std::enable_if_t<Detail::is_generic_matcher<MatcherRHS>::value, Detail::MatchAnyOfGeneric<MatcherBase<ArgLHS>, MatcherRHS>> 12030 operator || (MatcherBase<ArgLHS> const& lhs, MatcherRHS const& rhs) { 12031 return { lhs, rhs }; 12032 } 12033 12034} // namespace Matchers 12035} // namespace Catch 12036 12037#endif // CATCH_MATCHERS_TEMPLATED_HPP_INCLUDED 12038 12039namespace Catch { 12040 namespace Matchers { 12041 12042 class IsEmptyMatcher final : public MatcherGenericBase { 12043 public: 12044 template <typename RangeLike> 12045 bool match(RangeLike&& rng) const { 12046#if defined(CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS) 12047 using Catch::Detail::empty; 12048#else 12049 using std::empty; 12050#endif 12051 return empty(rng); 12052 } 12053 12054 std::string describe() const override; 12055 }; 12056 12057 class HasSizeMatcher final : public MatcherGenericBase { 12058 std::size_t m_target_size; 12059 public: 12060 explicit HasSizeMatcher(std::size_t target_size): 12061 m_target_size(target_size) 12062 {} 12063 12064 template <typename RangeLike> 12065 bool match(RangeLike&& rng) const { 12066#if defined(CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS) 12067 using Catch::Detail::size; 12068#else 12069 using std::size; 12070#endif 12071 return size(rng) == m_target_size; 12072 } 12073 12074 std::string describe() const override; 12075 }; 12076 12077 template <typename Matcher> 12078 class SizeMatchesMatcher final : public MatcherGenericBase { 12079 Matcher m_matcher; 12080 public: 12081 explicit SizeMatchesMatcher(Matcher m): 12082 m_matcher(CATCH_MOVE(m)) 12083 {} 12084 12085 template <typename RangeLike> 12086 bool match(RangeLike&& rng) const { 12087#if defined(CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS) 12088 using Catch::Detail::size; 12089#else 12090 using std::size; 12091#endif 12092 return m_matcher.match(size(rng)); 12093 } 12094 12095 std::string describe() const override { 12096 return "size matches " + m_matcher.describe(); 12097 } 12098 }; 12099 12100 12101 //! Creates a matcher that accepts empty ranges/containers 12102 IsEmptyMatcher IsEmpty(); 12103 //! Creates a matcher that accepts ranges/containers with specific size 12104 HasSizeMatcher SizeIs(std::size_t sz); 12105 template <typename Matcher> 12106 std::enable_if_t<Detail::is_matcher<Matcher>::value, 12107 SizeMatchesMatcher<Matcher>> SizeIs(Matcher&& m) { 12108 return SizeMatchesMatcher<Matcher>{CATCH_FORWARD(m)}; 12109 } 12110 12111 } // end namespace Matchers 12112} // end namespace Catch 12113 12114#endif // CATCH_MATCHERS_CONTAINER_PROPERTIES_HPP_INCLUDED 12115 12116 12117#ifndef CATCH_MATCHERS_CONTAINS_HPP_INCLUDED 12118#define CATCH_MATCHERS_CONTAINS_HPP_INCLUDED 12119 12120 12121#include <algorithm> 12122#include <functional> 12123 12124namespace Catch { 12125 namespace Matchers { 12126 //! Matcher for checking that an element in range is equal to specific element 12127 template <typename T, typename Equality> 12128 class ContainsElementMatcher final : public MatcherGenericBase { 12129 T m_desired; 12130 Equality m_eq; 12131 public: 12132 template <typename T2, typename Equality2> 12133 ContainsElementMatcher(T2&& target, Equality2&& predicate): 12134 m_desired(CATCH_FORWARD(target)), 12135 m_eq(CATCH_FORWARD(predicate)) 12136 {} 12137 12138 std::string describe() const override { 12139 return "contains element " + Catch::Detail::stringify(m_desired); 12140 } 12141 12142 template <typename RangeLike> 12143 bool match( RangeLike&& rng ) const { 12144 for ( auto&& elem : rng ) { 12145 if ( m_eq( elem, m_desired ) ) { return true; } 12146 } 12147 return false; 12148 } 12149 }; 12150 12151 //! Meta-matcher for checking that an element in a range matches a specific matcher 12152 template <typename Matcher> 12153 class ContainsMatcherMatcher final : public MatcherGenericBase { 12154 Matcher m_matcher; 12155 public: 12156 // Note that we do a copy+move to avoid having to SFINAE this 12157 // constructor (and also avoid some perfect forwarding failure 12158 // cases) 12159 ContainsMatcherMatcher(Matcher matcher): 12160 m_matcher(CATCH_MOVE(matcher)) 12161 {} 12162 12163 template <typename RangeLike> 12164 bool match(RangeLike&& rng) const { 12165 for (auto&& elem : rng) { 12166 if (m_matcher.match(elem)) { 12167 return true; 12168 } 12169 } 12170 return false; 12171 } 12172 12173 std::string describe() const override { 12174 return "contains element matching " + m_matcher.describe(); 12175 } 12176 }; 12177 12178 /** 12179 * Creates a matcher that checks whether a range contains a specific element. 12180 * 12181 * Uses `std::equal_to` to do the comparison 12182 */ 12183 template <typename T> 12184 std::enable_if_t<!Detail::is_matcher<T>::value, 12185 ContainsElementMatcher<T, std::equal_to<>>> Contains(T&& elem) { 12186 return { CATCH_FORWARD(elem), std::equal_to<>{} }; 12187 } 12188 12189 //! Creates a matcher that checks whether a range contains element matching a matcher 12190 template <typename Matcher> 12191 std::enable_if_t<Detail::is_matcher<Matcher>::value, 12192 ContainsMatcherMatcher<Matcher>> Contains(Matcher&& matcher) { 12193 return { CATCH_FORWARD(matcher) }; 12194 } 12195 12196 /** 12197 * Creates a matcher that checks whether a range contains a specific element. 12198 * 12199 * Uses `eq` to do the comparisons, the element is provided on the rhs 12200 */ 12201 template <typename T, typename Equality> 12202 ContainsElementMatcher<T, Equality> Contains(T&& elem, Equality&& eq) { 12203 return { CATCH_FORWARD(elem), CATCH_FORWARD(eq) }; 12204 } 12205 12206 } 12207} 12208 12209#endif // CATCH_MATCHERS_CONTAINS_HPP_INCLUDED 12210 12211 12212#ifndef CATCH_MATCHERS_EXCEPTION_HPP_INCLUDED 12213#define CATCH_MATCHERS_EXCEPTION_HPP_INCLUDED 12214 12215 12216namespace Catch { 12217namespace Matchers { 12218 12219class ExceptionMessageMatcher final : public MatcherBase<std::exception> { 12220 std::string m_message; 12221public: 12222 12223 ExceptionMessageMatcher(std::string const& message): 12224 m_message(message) 12225 {} 12226 12227 bool match(std::exception const& ex) const override; 12228 12229 std::string describe() const override; 12230}; 12231 12232//! Creates a matcher that checks whether a std derived exception has the provided message 12233ExceptionMessageMatcher Message(std::string const& message); 12234 12235template <typename StringMatcherType> 12236class ExceptionMessageMatchesMatcher final 12237 : public MatcherBase<std::exception> { 12238 StringMatcherType m_matcher; 12239 12240public: 12241 ExceptionMessageMatchesMatcher( StringMatcherType matcher ): 12242 m_matcher( CATCH_MOVE( matcher ) ) {} 12243 12244 bool match( std::exception const& ex ) const override { 12245 return m_matcher.match( ex.what() ); 12246 } 12247 12248 std::string describe() const override { 12249 return " matches \"" + m_matcher.describe() + '"'; 12250 } 12251}; 12252 12253//! Creates a matcher that checks whether a message from an std derived 12254//! exception matches a provided matcher 12255template <typename StringMatcherType> 12256ExceptionMessageMatchesMatcher<StringMatcherType> 12257MessageMatches( StringMatcherType&& matcher ) { 12258 return { CATCH_FORWARD( matcher ) }; 12259} 12260 12261} // namespace Matchers 12262} // namespace Catch 12263 12264#endif // CATCH_MATCHERS_EXCEPTION_HPP_INCLUDED 12265 12266 12267#ifndef CATCH_MATCHERS_FLOATING_POINT_HPP_INCLUDED 12268#define CATCH_MATCHERS_FLOATING_POINT_HPP_INCLUDED 12269 12270 12271namespace Catch { 12272namespace Matchers { 12273 12274 namespace Detail { 12275 enum class FloatingPointKind : uint8_t; 12276 } 12277 12278 class WithinAbsMatcher final : public MatcherBase<double> { 12279 public: 12280 WithinAbsMatcher(double target, double margin); 12281 bool match(double const& matchee) const override; 12282 std::string describe() const override; 12283 private: 12284 double m_target; 12285 double m_margin; 12286 }; 12287 12288 //! Creates a matcher that accepts numbers within certain range of target 12289 WithinAbsMatcher WithinAbs( double target, double margin ); 12290 12291 12292 12293 class WithinUlpsMatcher final : public MatcherBase<double> { 12294 public: 12295 WithinUlpsMatcher( double target, 12296 uint64_t ulps, 12297 Detail::FloatingPointKind baseType ); 12298 bool match(double const& matchee) const override; 12299 std::string describe() const override; 12300 private: 12301 double m_target; 12302 uint64_t m_ulps; 12303 Detail::FloatingPointKind m_type; 12304 }; 12305 12306 //! Creates a matcher that accepts doubles within certain ULP range of target 12307 WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff); 12308 //! Creates a matcher that accepts floats within certain ULP range of target 12309 WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff); 12310 12311 12312 12313 // Given IEEE-754 format for floats and doubles, we can assume 12314 // that float -> double promotion is lossless. Given this, we can 12315 // assume that if we do the standard relative comparison of 12316 // |lhs - rhs| <= epsilon * max(fabs(lhs), fabs(rhs)), then we get 12317 // the same result if we do this for floats, as if we do this for 12318 // doubles that were promoted from floats. 12319 class WithinRelMatcher final : public MatcherBase<double> { 12320 public: 12321 WithinRelMatcher( double target, double epsilon ); 12322 bool match(double const& matchee) const override; 12323 std::string describe() const override; 12324 private: 12325 double m_target; 12326 double m_epsilon; 12327 }; 12328 12329 //! Creates a matcher that accepts doubles within certain relative range of target 12330 WithinRelMatcher WithinRel(double target, double eps); 12331 //! Creates a matcher that accepts doubles within 100*DBL_EPS relative range of target 12332 WithinRelMatcher WithinRel(double target); 12333 //! Creates a matcher that accepts doubles within certain relative range of target 12334 WithinRelMatcher WithinRel(float target, float eps); 12335 //! Creates a matcher that accepts floats within 100*FLT_EPS relative range of target 12336 WithinRelMatcher WithinRel(float target); 12337 12338 12339 12340 class IsNaNMatcher final : public MatcherBase<double> { 12341 public: 12342 IsNaNMatcher() = default; 12343 bool match( double const& matchee ) const override; 12344 std::string describe() const override; 12345 }; 12346 12347 IsNaNMatcher IsNaN(); 12348 12349} // namespace Matchers 12350} // namespace Catch 12351 12352#endif // CATCH_MATCHERS_FLOATING_POINT_HPP_INCLUDED 12353 12354 12355#ifndef CATCH_MATCHERS_PREDICATE_HPP_INCLUDED 12356#define CATCH_MATCHERS_PREDICATE_HPP_INCLUDED 12357 12358 12359#include <string> 12360 12361namespace Catch { 12362namespace Matchers { 12363 12364namespace Detail { 12365 std::string finalizeDescription(const std::string& desc); 12366} // namespace Detail 12367 12368template <typename T, typename Predicate> 12369class PredicateMatcher final : public MatcherBase<T> { 12370 Predicate m_predicate; 12371 std::string m_description; 12372public: 12373 12374 PredicateMatcher(Predicate&& elem, std::string const& descr) 12375 :m_predicate(CATCH_FORWARD(elem)), 12376 m_description(Detail::finalizeDescription(descr)) 12377 {} 12378 12379 bool match( T const& item ) const override { 12380 return m_predicate(item); 12381 } 12382 12383 std::string describe() const override { 12384 return m_description; 12385 } 12386}; 12387 12388 /** 12389 * Creates a matcher that calls delegates `match` to the provided predicate. 12390 * 12391 * The user has to explicitly specify the argument type to the matcher 12392 */ 12393 template<typename T, typename Pred> 12394 PredicateMatcher<T, Pred> Predicate(Pred&& predicate, std::string const& description = "") { 12395 static_assert(is_callable<Pred(T)>::value, "Predicate not callable with argument T"); 12396 static_assert(std::is_same<bool, FunctionReturnType<Pred, T>>::value, "Predicate does not return bool"); 12397 return PredicateMatcher<T, Pred>(CATCH_FORWARD(predicate), description); 12398 } 12399 12400} // namespace Matchers 12401} // namespace Catch 12402 12403#endif // CATCH_MATCHERS_PREDICATE_HPP_INCLUDED 12404 12405 12406#ifndef CATCH_MATCHERS_QUANTIFIERS_HPP_INCLUDED 12407#define CATCH_MATCHERS_QUANTIFIERS_HPP_INCLUDED 12408 12409 12410namespace Catch { 12411 namespace Matchers { 12412 // Matcher for checking that all elements in range matches a given matcher. 12413 template <typename Matcher> 12414 class AllMatchMatcher final : public MatcherGenericBase { 12415 Matcher m_matcher; 12416 public: 12417 AllMatchMatcher(Matcher matcher): 12418 m_matcher(CATCH_MOVE(matcher)) 12419 {} 12420 12421 std::string describe() const override { 12422 return "all match " + m_matcher.describe(); 12423 } 12424 12425 template <typename RangeLike> 12426 bool match(RangeLike&& rng) const { 12427 for (auto&& elem : rng) { 12428 if (!m_matcher.match(elem)) { 12429 return false; 12430 } 12431 } 12432 return true; 12433 } 12434 }; 12435 12436 // Matcher for checking that no element in range matches a given matcher. 12437 template <typename Matcher> 12438 class NoneMatchMatcher final : public MatcherGenericBase { 12439 Matcher m_matcher; 12440 public: 12441 NoneMatchMatcher(Matcher matcher): 12442 m_matcher(CATCH_MOVE(matcher)) 12443 {} 12444 12445 std::string describe() const override { 12446 return "none match " + m_matcher.describe(); 12447 } 12448 12449 template <typename RangeLike> 12450 bool match(RangeLike&& rng) const { 12451 for (auto&& elem : rng) { 12452 if (m_matcher.match(elem)) { 12453 return false; 12454 } 12455 } 12456 return true; 12457 } 12458 }; 12459 12460 // Matcher for checking that at least one element in range matches a given matcher. 12461 template <typename Matcher> 12462 class AnyMatchMatcher final : public MatcherGenericBase { 12463 Matcher m_matcher; 12464 public: 12465 AnyMatchMatcher(Matcher matcher): 12466 m_matcher(CATCH_MOVE(matcher)) 12467 {} 12468 12469 std::string describe() const override { 12470 return "any match " + m_matcher.describe(); 12471 } 12472 12473 template <typename RangeLike> 12474 bool match(RangeLike&& rng) const { 12475 for (auto&& elem : rng) { 12476 if (m_matcher.match(elem)) { 12477 return true; 12478 } 12479 } 12480 return false; 12481 } 12482 }; 12483 12484 // Matcher for checking that all elements in range are true. 12485 class AllTrueMatcher final : public MatcherGenericBase { 12486 public: 12487 std::string describe() const override; 12488 12489 template <typename RangeLike> 12490 bool match(RangeLike&& rng) const { 12491 for (auto&& elem : rng) { 12492 if (!elem) { 12493 return false; 12494 } 12495 } 12496 return true; 12497 } 12498 }; 12499 12500 // Matcher for checking that no element in range is true. 12501 class NoneTrueMatcher final : public MatcherGenericBase { 12502 public: 12503 std::string describe() const override; 12504 12505 template <typename RangeLike> 12506 bool match(RangeLike&& rng) const { 12507 for (auto&& elem : rng) { 12508 if (elem) { 12509 return false; 12510 } 12511 } 12512 return true; 12513 } 12514 }; 12515 12516 // Matcher for checking that any element in range is true. 12517 class AnyTrueMatcher final : public MatcherGenericBase { 12518 public: 12519 std::string describe() const override; 12520 12521 template <typename RangeLike> 12522 bool match(RangeLike&& rng) const { 12523 for (auto&& elem : rng) { 12524 if (elem) { 12525 return true; 12526 } 12527 } 12528 return false; 12529 } 12530 }; 12531 12532 // Creates a matcher that checks whether all elements in a range match a matcher 12533 template <typename Matcher> 12534 AllMatchMatcher<Matcher> AllMatch(Matcher&& matcher) { 12535 return { CATCH_FORWARD(matcher) }; 12536 } 12537 12538 // Creates a matcher that checks whether no element in a range matches a matcher. 12539 template <typename Matcher> 12540 NoneMatchMatcher<Matcher> NoneMatch(Matcher&& matcher) { 12541 return { CATCH_FORWARD(matcher) }; 12542 } 12543 12544 // Creates a matcher that checks whether any element in a range matches a matcher. 12545 template <typename Matcher> 12546 AnyMatchMatcher<Matcher> AnyMatch(Matcher&& matcher) { 12547 return { CATCH_FORWARD(matcher) }; 12548 } 12549 12550 // Creates a matcher that checks whether all elements in a range are true 12551 AllTrueMatcher AllTrue(); 12552 12553 // Creates a matcher that checks whether no element in a range is true 12554 NoneTrueMatcher NoneTrue(); 12555 12556 // Creates a matcher that checks whether any element in a range is true 12557 AnyTrueMatcher AnyTrue(); 12558 } 12559} 12560 12561#endif // CATCH_MATCHERS_QUANTIFIERS_HPP_INCLUDED 12562 12563 12564#ifndef CATCH_MATCHERS_RANGE_EQUALS_HPP_INCLUDED 12565#define CATCH_MATCHERS_RANGE_EQUALS_HPP_INCLUDED 12566 12567 12568#include <algorithm> 12569#include <utility> 12570 12571namespace Catch { 12572 namespace Matchers { 12573 12574 /** 12575 * Matcher for checking that an element contains the same 12576 * elements in the same order 12577 */ 12578 template <typename TargetRangeLike, typename Equality> 12579 class RangeEqualsMatcher final : public MatcherGenericBase { 12580 TargetRangeLike m_desired; 12581 Equality m_predicate; 12582 12583 public: 12584 template <typename TargetRangeLike2, typename Equality2> 12585 RangeEqualsMatcher( TargetRangeLike2&& range, 12586 Equality2&& predicate ): 12587 m_desired( CATCH_FORWARD( range ) ), 12588 m_predicate( CATCH_FORWARD( predicate ) ) {} 12589 12590 template <typename RangeLike> 12591 bool match( RangeLike&& rng ) const { 12592 auto rng_start = begin( rng ); 12593 const auto rng_end = end( rng ); 12594 auto target_start = begin( m_desired ); 12595 const auto target_end = end( m_desired ); 12596 12597 while (rng_start != rng_end && target_start != target_end) { 12598 if (!m_predicate(*rng_start, *target_start)) { 12599 return false; 12600 } 12601 ++rng_start; 12602 ++target_start; 12603 } 12604 return rng_start == rng_end && target_start == target_end; 12605 } 12606 12607 std::string describe() const override { 12608 return "elements are " + Catch::Detail::stringify( m_desired ); 12609 } 12610 }; 12611 12612 /** 12613 * Matcher for checking that an element contains the same 12614 * elements (but not necessarily in the same order) 12615 */ 12616 template <typename TargetRangeLike, typename Equality> 12617 class UnorderedRangeEqualsMatcher final : public MatcherGenericBase { 12618 TargetRangeLike m_desired; 12619 Equality m_predicate; 12620 12621 public: 12622 template <typename TargetRangeLike2, typename Equality2> 12623 UnorderedRangeEqualsMatcher( TargetRangeLike2&& range, 12624 Equality2&& predicate ): 12625 m_desired( CATCH_FORWARD( range ) ), 12626 m_predicate( CATCH_FORWARD( predicate ) ) {} 12627 12628 template <typename RangeLike> 12629 bool match( RangeLike&& rng ) const { 12630 using std::begin; 12631 using std::end; 12632 return Catch::Detail::is_permutation( begin( m_desired ), 12633 end( m_desired ), 12634 begin( rng ), 12635 end( rng ), 12636 m_predicate ); 12637 } 12638 12639 std::string describe() const override { 12640 return "unordered elements are " + 12641 ::Catch::Detail::stringify( m_desired ); 12642 } 12643 }; 12644 12645 /** 12646 * Creates a matcher that checks if all elements in a range are equal 12647 * to all elements in another range. 12648 * 12649 * Uses `std::equal_to` to do the comparison 12650 */ 12651 template <typename RangeLike> 12652 std::enable_if_t<!Detail::is_matcher<RangeLike>::value, 12653 RangeEqualsMatcher<RangeLike, std::equal_to<>>> 12654 RangeEquals( RangeLike&& range ) { 12655 return { CATCH_FORWARD( range ), std::equal_to<>{} }; 12656 } 12657 12658 /** 12659 * Creates a matcher that checks if all elements in a range are equal 12660 * to all elements in another range. 12661 * 12662 * Uses to provided predicate `predicate` to do the comparisons 12663 */ 12664 template <typename RangeLike, typename Equality> 12665 RangeEqualsMatcher<RangeLike, Equality> 12666 RangeEquals( RangeLike&& range, Equality&& predicate ) { 12667 return { CATCH_FORWARD( range ), CATCH_FORWARD( predicate ) }; 12668 } 12669 12670 /** 12671 * Creates a matcher that checks if all elements in a range are equal 12672 * to all elements in another range, in some permutation 12673 * 12674 * Uses `std::equal_to` to do the comparison 12675 */ 12676 template <typename RangeLike> 12677 std::enable_if_t< 12678 !Detail::is_matcher<RangeLike>::value, 12679 UnorderedRangeEqualsMatcher<RangeLike, std::equal_to<>>> 12680 UnorderedRangeEquals( RangeLike&& range ) { 12681 return { CATCH_FORWARD( range ), std::equal_to<>{} }; 12682 } 12683 12684 /** 12685 * Creates a matcher that checks if all elements in a range are equal 12686 * to all elements in another range, in some permutation. 12687 * 12688 * Uses to provided predicate `predicate` to do the comparisons 12689 */ 12690 template <typename RangeLike, typename Equality> 12691 UnorderedRangeEqualsMatcher<RangeLike, Equality> 12692 UnorderedRangeEquals( RangeLike&& range, Equality&& predicate ) { 12693 return { CATCH_FORWARD( range ), CATCH_FORWARD( predicate ) }; 12694 } 12695 } // namespace Matchers 12696} // namespace Catch 12697 12698#endif // CATCH_MATCHERS_RANGE_EQUALS_HPP_INCLUDED 12699 12700 12701#ifndef CATCH_MATCHERS_STRING_HPP_INCLUDED 12702#define CATCH_MATCHERS_STRING_HPP_INCLUDED 12703 12704 12705#include <string> 12706 12707namespace Catch { 12708namespace Matchers { 12709 12710 struct CasedString { 12711 CasedString( std::string const& str, CaseSensitive caseSensitivity ); 12712 std::string adjustString( std::string const& str ) const; 12713 StringRef caseSensitivitySuffix() const; 12714 12715 CaseSensitive m_caseSensitivity; 12716 std::string m_str; 12717 }; 12718 12719 class StringMatcherBase : public MatcherBase<std::string> { 12720 protected: 12721 CasedString m_comparator; 12722 StringRef m_operation; 12723 12724 public: 12725 StringMatcherBase( StringRef operation, 12726 CasedString const& comparator ); 12727 std::string describe() const override; 12728 }; 12729 12730 class StringEqualsMatcher final : public StringMatcherBase { 12731 public: 12732 StringEqualsMatcher( CasedString const& comparator ); 12733 bool match( std::string const& source ) const override; 12734 }; 12735 class StringContainsMatcher final : public StringMatcherBase { 12736 public: 12737 StringContainsMatcher( CasedString const& comparator ); 12738 bool match( std::string const& source ) const override; 12739 }; 12740 class StartsWithMatcher final : public StringMatcherBase { 12741 public: 12742 StartsWithMatcher( CasedString const& comparator ); 12743 bool match( std::string const& source ) const override; 12744 }; 12745 class EndsWithMatcher final : public StringMatcherBase { 12746 public: 12747 EndsWithMatcher( CasedString const& comparator ); 12748 bool match( std::string const& source ) const override; 12749 }; 12750 12751 class RegexMatcher final : public MatcherBase<std::string> { 12752 std::string m_regex; 12753 CaseSensitive m_caseSensitivity; 12754 12755 public: 12756 RegexMatcher( std::string regex, CaseSensitive caseSensitivity ); 12757 bool match( std::string const& matchee ) const override; 12758 std::string describe() const override; 12759 }; 12760 12761 //! Creates matcher that accepts strings that are exactly equal to `str` 12762 StringEqualsMatcher Equals( std::string const& str, CaseSensitive caseSensitivity = CaseSensitive::Yes ); 12763 //! Creates matcher that accepts strings that contain `str` 12764 StringContainsMatcher ContainsSubstring( std::string const& str, CaseSensitive caseSensitivity = CaseSensitive::Yes ); 12765 //! Creates matcher that accepts strings that _end_ with `str` 12766 EndsWithMatcher EndsWith( std::string const& str, CaseSensitive caseSensitivity = CaseSensitive::Yes ); 12767 //! Creates matcher that accepts strings that _start_ with `str` 12768 StartsWithMatcher StartsWith( std::string const& str, CaseSensitive caseSensitivity = CaseSensitive::Yes ); 12769 //! Creates matcher that accepts strings matching `regex` 12770 RegexMatcher Matches( std::string const& regex, CaseSensitive caseSensitivity = CaseSensitive::Yes ); 12771 12772} // namespace Matchers 12773} // namespace Catch 12774 12775#endif // CATCH_MATCHERS_STRING_HPP_INCLUDED 12776 12777 12778#ifndef CATCH_MATCHERS_VECTOR_HPP_INCLUDED 12779#define CATCH_MATCHERS_VECTOR_HPP_INCLUDED 12780 12781 12782#include <algorithm> 12783 12784namespace Catch { 12785namespace Matchers { 12786 12787 template<typename T, typename Alloc> 12788 class VectorContainsElementMatcher final : public MatcherBase<std::vector<T, Alloc>> { 12789 T const& m_comparator; 12790 12791 public: 12792 VectorContainsElementMatcher(T const& comparator): 12793 m_comparator(comparator) 12794 {} 12795 12796 bool match(std::vector<T, Alloc> const& v) const override { 12797 for (auto const& el : v) { 12798 if (el == m_comparator) { 12799 return true; 12800 } 12801 } 12802 return false; 12803 } 12804 12805 std::string describe() const override { 12806 return "Contains: " + ::Catch::Detail::stringify( m_comparator ); 12807 } 12808 }; 12809 12810 template<typename T, typename AllocComp, typename AllocMatch> 12811 class ContainsMatcher final : public MatcherBase<std::vector<T, AllocMatch>> { 12812 std::vector<T, AllocComp> const& m_comparator; 12813 12814 public: 12815 ContainsMatcher(std::vector<T, AllocComp> const& comparator): 12816 m_comparator( comparator ) 12817 {} 12818 12819 bool match(std::vector<T, AllocMatch> const& v) const override { 12820 // !TBD: see note in EqualsMatcher 12821 if (m_comparator.size() > v.size()) 12822 return false; 12823 for (auto const& comparator : m_comparator) { 12824 auto present = false; 12825 for (const auto& el : v) { 12826 if (el == comparator) { 12827 present = true; 12828 break; 12829 } 12830 } 12831 if (!present) { 12832 return false; 12833 } 12834 } 12835 return true; 12836 } 12837 std::string describe() const override { 12838 return "Contains: " + ::Catch::Detail::stringify( m_comparator ); 12839 } 12840 }; 12841 12842 template<typename T, typename AllocComp, typename AllocMatch> 12843 class EqualsMatcher final : public MatcherBase<std::vector<T, AllocMatch>> { 12844 std::vector<T, AllocComp> const& m_comparator; 12845 12846 public: 12847 EqualsMatcher(std::vector<T, AllocComp> const& comparator): 12848 m_comparator( comparator ) 12849 {} 12850 12851 bool match(std::vector<T, AllocMatch> const& v) const override { 12852 // !TBD: This currently works if all elements can be compared using != 12853 // - a more general approach would be via a compare template that defaults 12854 // to using !=. but could be specialised for, e.g. std::vector<T> etc 12855 // - then just call that directly 12856 if ( m_comparator.size() != v.size() ) { return false; } 12857 for ( std::size_t i = 0; i < v.size(); ++i ) { 12858 if ( !( m_comparator[i] == v[i] ) ) { return false; } 12859 } 12860 return true; 12861 } 12862 std::string describe() const override { 12863 return "Equals: " + ::Catch::Detail::stringify( m_comparator ); 12864 } 12865 }; 12866 12867 template<typename T, typename AllocComp, typename AllocMatch> 12868 class ApproxMatcher final : public MatcherBase<std::vector<T, AllocMatch>> { 12869 std::vector<T, AllocComp> const& m_comparator; 12870 mutable Catch::Approx approx = Catch::Approx::custom(); 12871 12872 public: 12873 ApproxMatcher(std::vector<T, AllocComp> const& comparator): 12874 m_comparator( comparator ) 12875 {} 12876 12877 bool match(std::vector<T, AllocMatch> const& v) const override { 12878 if (m_comparator.size() != v.size()) 12879 return false; 12880 for (std::size_t i = 0; i < v.size(); ++i) 12881 if (m_comparator[i] != approx(v[i])) 12882 return false; 12883 return true; 12884 } 12885 std::string describe() const override { 12886 return "is approx: " + ::Catch::Detail::stringify( m_comparator ); 12887 } 12888 template <typename = std::enable_if_t<std::is_constructible<double, T>::value>> 12889 ApproxMatcher& epsilon( T const& newEpsilon ) { 12890 approx.epsilon(static_cast<double>(newEpsilon)); 12891 return *this; 12892 } 12893 template <typename = std::enable_if_t<std::is_constructible<double, T>::value>> 12894 ApproxMatcher& margin( T const& newMargin ) { 12895 approx.margin(static_cast<double>(newMargin)); 12896 return *this; 12897 } 12898 template <typename = std::enable_if_t<std::is_constructible<double, T>::value>> 12899 ApproxMatcher& scale( T const& newScale ) { 12900 approx.scale(static_cast<double>(newScale)); 12901 return *this; 12902 } 12903 }; 12904 12905 template<typename T, typename AllocComp, typename AllocMatch> 12906 class UnorderedEqualsMatcher final : public MatcherBase<std::vector<T, AllocMatch>> { 12907 std::vector<T, AllocComp> const& m_target; 12908 12909 public: 12910 UnorderedEqualsMatcher(std::vector<T, AllocComp> const& target): 12911 m_target(target) 12912 {} 12913 bool match(std::vector<T, AllocMatch> const& vec) const override { 12914 if (m_target.size() != vec.size()) { 12915 return false; 12916 } 12917 return std::is_permutation(m_target.begin(), m_target.end(), vec.begin()); 12918 } 12919 12920 std::string describe() const override { 12921 return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target); 12922 } 12923 }; 12924 12925 12926 // The following functions create the actual matcher objects. 12927 // This allows the types to be inferred 12928 12929 //! Creates a matcher that matches vectors that contain all elements in `comparator` 12930 template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp> 12931 ContainsMatcher<T, AllocComp, AllocMatch> Contains( std::vector<T, AllocComp> const& comparator ) { 12932 return ContainsMatcher<T, AllocComp, AllocMatch>(comparator); 12933 } 12934 12935 //! Creates a matcher that matches vectors that contain `comparator` as an element 12936 template<typename T, typename Alloc = std::allocator<T>> 12937 VectorContainsElementMatcher<T, Alloc> VectorContains( T const& comparator ) { 12938 return VectorContainsElementMatcher<T, Alloc>(comparator); 12939 } 12940 12941 //! Creates a matcher that matches vectors that are exactly equal to `comparator` 12942 template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp> 12943 EqualsMatcher<T, AllocComp, AllocMatch> Equals( std::vector<T, AllocComp> const& comparator ) { 12944 return EqualsMatcher<T, AllocComp, AllocMatch>(comparator); 12945 } 12946 12947 //! Creates a matcher that matches vectors that `comparator` as an element 12948 template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp> 12949 ApproxMatcher<T, AllocComp, AllocMatch> Approx( std::vector<T, AllocComp> const& comparator ) { 12950 return ApproxMatcher<T, AllocComp, AllocMatch>(comparator); 12951 } 12952 12953 //! Creates a matcher that matches vectors that is equal to `target` modulo permutation 12954 template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp> 12955 UnorderedEqualsMatcher<T, AllocComp, AllocMatch> UnorderedEquals(std::vector<T, AllocComp> const& target) { 12956 return UnorderedEqualsMatcher<T, AllocComp, AllocMatch>(target); 12957 } 12958 12959} // namespace Matchers 12960} // namespace Catch 12961 12962#endif // CATCH_MATCHERS_VECTOR_HPP_INCLUDED 12963 12964#endif // CATCH_MATCHERS_ALL_HPP_INCLUDED 12965 12966 12967/** \file 12968 * This is a convenience header for Catch2's Reporter support. It includes 12969 * **all** of Catch2 headers related to reporters, including all reporters. 12970 * 12971 * Generally the Catch2 users should use specific includes they need, 12972 * but this header can be used instead for ease-of-experimentation, or 12973 * just plain convenience, at the cost of (significantly) increased 12974 * compilation times. 12975 * 12976 * When a new header (reporter) is added to either the `reporter` folder, 12977 * or to the corresponding internal subfolder, it should be added here. 12978 */ 12979 12980#ifndef CATCH_REPORTERS_ALL_HPP_INCLUDED 12981#define CATCH_REPORTERS_ALL_HPP_INCLUDED 12982 12983 12984 12985#ifndef CATCH_REPORTER_AUTOMAKE_HPP_INCLUDED 12986#define CATCH_REPORTER_AUTOMAKE_HPP_INCLUDED 12987 12988 12989 12990#ifndef CATCH_REPORTER_STREAMING_BASE_HPP_INCLUDED 12991#define CATCH_REPORTER_STREAMING_BASE_HPP_INCLUDED 12992 12993 12994 12995#ifndef CATCH_REPORTER_COMMON_BASE_HPP_INCLUDED 12996#define CATCH_REPORTER_COMMON_BASE_HPP_INCLUDED 12997 12998 12999#include <map> 13000#include <string> 13001 13002namespace Catch { 13003 class ColourImpl; 13004 13005 /** 13006 * This is the base class for all reporters. 13007 * 13008 * If are writing a reporter, you must derive from this type, or one 13009 * of the helper reporter bases that are derived from this type. 13010 * 13011 * ReporterBase centralizes handling of various common tasks in reporters, 13012 * like storing the right stream for the reporters to write to, and 13013 * providing the default implementation of the different listing events. 13014 */ 13015 class ReporterBase : public IEventListener { 13016 protected: 13017 //! The stream wrapper as passed to us by outside code 13018 Detail::unique_ptr<IStream> m_wrapped_stream; 13019 //! Cached output stream from `m_wrapped_stream` to reduce 13020 //! number of indirect calls needed to write output. 13021 std::ostream& m_stream; 13022 //! Colour implementation this reporter was configured for 13023 Detail::unique_ptr<ColourImpl> m_colour; 13024 //! The custom reporter options user passed down to the reporter 13025 std::map<std::string, std::string> m_customOptions; 13026 13027 public: 13028 ReporterBase( ReporterConfig&& config ); 13029 ~ReporterBase() override; // = default; 13030 13031 /** 13032 * Provides a simple default listing of reporters. 13033 * 13034 * Should look roughly like the reporter listing in v2 and earlier 13035 * versions of Catch2. 13036 */ 13037 void listReporters( 13038 std::vector<ReporterDescription> const& descriptions ) override; 13039 /** 13040 * Provides a simple default listing of listeners 13041 * 13042 * Looks similarly to listing of reporters, but with listener type 13043 * instead of reporter name. 13044 */ 13045 void listListeners( 13046 std::vector<ListenerDescription> const& descriptions ) override; 13047 /** 13048 * Provides a simple default listing of tests. 13049 * 13050 * Should look roughly like the test listing in v2 and earlier versions 13051 * of Catch2. Especially supports low-verbosity listing that mimics the 13052 * old `--list-test-names-only` output. 13053 */ 13054 void listTests( std::vector<TestCaseHandle> const& tests ) override; 13055 /** 13056 * Provides a simple default listing of tags. 13057 * 13058 * Should look roughly like the tag listing in v2 and earlier versions 13059 * of Catch2. 13060 */ 13061 void listTags( std::vector<TagInfo> const& tags ) override; 13062 }; 13063} // namespace Catch 13064 13065#endif // CATCH_REPORTER_COMMON_BASE_HPP_INCLUDED 13066 13067#include <vector> 13068 13069namespace Catch { 13070 13071 class StreamingReporterBase : public ReporterBase { 13072 public: 13073 // GCC5 compat: we cannot use inherited constructor, because it 13074 // doesn't implement backport of P0136 13075 StreamingReporterBase(ReporterConfig&& _config): 13076 ReporterBase(CATCH_MOVE(_config)) 13077 {} 13078 ~StreamingReporterBase() override; 13079 13080 void benchmarkPreparing( StringRef ) override {} 13081 void benchmarkStarting( BenchmarkInfo const& ) override {} 13082 void benchmarkEnded( BenchmarkStats<> const& ) override {} 13083 void benchmarkFailed( StringRef ) override {} 13084 13085 void fatalErrorEncountered( StringRef /*error*/ ) override {} 13086 void noMatchingTestCases( StringRef /*unmatchedSpec*/ ) override {} 13087 void reportInvalidTestSpec( StringRef /*invalidArgument*/ ) override {} 13088 13089 void testRunStarting( TestRunInfo const& _testRunInfo ) override; 13090 13091 void testCaseStarting(TestCaseInfo const& _testInfo) override { 13092 currentTestCaseInfo = &_testInfo; 13093 } 13094 void testCasePartialStarting( TestCaseInfo const&, uint64_t ) override {} 13095 void sectionStarting(SectionInfo const& _sectionInfo) override { 13096 m_sectionStack.push_back(_sectionInfo); 13097 } 13098 13099 void assertionStarting( AssertionInfo const& ) override {} 13100 void assertionEnded( AssertionStats const& ) override {} 13101 13102 void sectionEnded(SectionStats const& /* _sectionStats */) override { 13103 m_sectionStack.pop_back(); 13104 } 13105 void testCasePartialEnded( TestCaseStats const&, uint64_t ) override {} 13106 void testCaseEnded(TestCaseStats const& /* _testCaseStats */) override { 13107 currentTestCaseInfo = nullptr; 13108 } 13109 void testRunEnded( TestRunStats const& /* _testRunStats */ ) override; 13110 13111 void skipTest(TestCaseInfo const&) override { 13112 // Don't do anything with this by default. 13113 // It can optionally be overridden in the derived class. 13114 } 13115 13116 protected: 13117 TestRunInfo currentTestRunInfo{ "test run has not started yet"_sr }; 13118 TestCaseInfo const* currentTestCaseInfo = nullptr; 13119 13120 //! Stack of all _active_ sections in the _current_ test case 13121 std::vector<SectionInfo> m_sectionStack; 13122 }; 13123 13124} // end namespace Catch 13125 13126#endif // CATCH_REPORTER_STREAMING_BASE_HPP_INCLUDED 13127 13128#include <string> 13129 13130namespace Catch { 13131 13132 class AutomakeReporter final : public StreamingReporterBase { 13133 public: 13134 // GCC5 compat: we cannot use inherited constructor, because it 13135 // doesn't implement backport of P0136 13136 AutomakeReporter(ReporterConfig&& _config): 13137 StreamingReporterBase(CATCH_MOVE(_config)) 13138 {} 13139 ~AutomakeReporter() override; 13140 13141 static std::string getDescription() { 13142 using namespace std::string_literals; 13143 return "Reports test results in the format of Automake .trs files"s; 13144 } 13145 13146 void testCaseEnded(TestCaseStats const& _testCaseStats) override; 13147 void skipTest(TestCaseInfo const& testInfo) override; 13148 }; 13149 13150} // end namespace Catch 13151 13152#endif // CATCH_REPORTER_AUTOMAKE_HPP_INCLUDED 13153 13154 13155#ifndef CATCH_REPORTER_COMPACT_HPP_INCLUDED 13156#define CATCH_REPORTER_COMPACT_HPP_INCLUDED 13157 13158 13159 13160 13161namespace Catch { 13162 13163 class CompactReporter final : public StreamingReporterBase { 13164 public: 13165 using StreamingReporterBase::StreamingReporterBase; 13166 13167 ~CompactReporter() override; 13168 13169 static std::string getDescription(); 13170 13171 void noMatchingTestCases( StringRef unmatchedSpec ) override; 13172 13173 void testRunStarting( TestRunInfo const& _testInfo ) override; 13174 13175 void assertionEnded(AssertionStats const& _assertionStats) override; 13176 13177 void sectionEnded(SectionStats const& _sectionStats) override; 13178 13179 void testRunEnded(TestRunStats const& _testRunStats) override; 13180 13181 }; 13182 13183} // end namespace Catch 13184 13185#endif // CATCH_REPORTER_COMPACT_HPP_INCLUDED 13186 13187 13188#ifndef CATCH_REPORTER_CONSOLE_HPP_INCLUDED 13189#define CATCH_REPORTER_CONSOLE_HPP_INCLUDED 13190 13191 13192namespace Catch { 13193 // Fwd decls 13194 class TablePrinter; 13195 13196 class ConsoleReporter final : public StreamingReporterBase { 13197 Detail::unique_ptr<TablePrinter> m_tablePrinter; 13198 13199 public: 13200 ConsoleReporter(ReporterConfig&& config); 13201 ~ConsoleReporter() override; 13202 static std::string getDescription(); 13203 13204 void noMatchingTestCases( StringRef unmatchedSpec ) override; 13205 void reportInvalidTestSpec( StringRef arg ) override; 13206 13207 void assertionStarting(AssertionInfo const&) override; 13208 13209 void assertionEnded(AssertionStats const& _assertionStats) override; 13210 13211 void sectionStarting(SectionInfo const& _sectionInfo) override; 13212 void sectionEnded(SectionStats const& _sectionStats) override; 13213 13214 void benchmarkPreparing( StringRef name ) override; 13215 void benchmarkStarting(BenchmarkInfo const& info) override; 13216 void benchmarkEnded(BenchmarkStats<> const& stats) override; 13217 void benchmarkFailed( StringRef error ) override; 13218 13219 void testCaseEnded(TestCaseStats const& _testCaseStats) override; 13220 void testRunEnded(TestRunStats const& _testRunStats) override; 13221 void testRunStarting(TestRunInfo const& _testRunInfo) override; 13222 13223 private: 13224 void lazyPrint(); 13225 13226 void lazyPrintWithoutClosingBenchmarkTable(); 13227 void lazyPrintRunInfo(); 13228 void printTestCaseAndSectionHeader(); 13229 13230 void printClosedHeader(std::string const& _name); 13231 void printOpenHeader(std::string const& _name); 13232 13233 // if string has a : in first line will set indent to follow it on 13234 // subsequent lines 13235 void printHeaderString(std::string const& _string, std::size_t indent = 0); 13236 13237 void printTotalsDivider(Totals const& totals); 13238 13239 bool m_headerPrinted = false; 13240 bool m_testRunInfoPrinted = false; 13241 }; 13242 13243} // end namespace Catch 13244 13245#endif // CATCH_REPORTER_CONSOLE_HPP_INCLUDED 13246 13247 13248#ifndef CATCH_REPORTER_CUMULATIVE_BASE_HPP_INCLUDED 13249#define CATCH_REPORTER_CUMULATIVE_BASE_HPP_INCLUDED 13250 13251 13252#include <string> 13253#include <vector> 13254 13255namespace Catch { 13256 13257 namespace Detail { 13258 13259 //! Represents either an assertion or a benchmark result to be handled by cumulative reporter later 13260 class AssertionOrBenchmarkResult { 13261 // This should really be a variant, but this is much faster 13262 // to write and the data layout here is already terrible 13263 // enough that we do not have to care about the object size. 13264 Optional<AssertionStats> m_assertion; 13265 Optional<BenchmarkStats<>> m_benchmark; 13266 public: 13267 AssertionOrBenchmarkResult(AssertionStats const& assertion); 13268 AssertionOrBenchmarkResult(BenchmarkStats<> const& benchmark); 13269 13270 bool isAssertion() const; 13271 bool isBenchmark() const; 13272 13273 AssertionStats const& asAssertion() const; 13274 BenchmarkStats<> const& asBenchmark() const; 13275 }; 13276 } 13277 13278 /** 13279 * Utility base for reporters that need to handle all results at once 13280 * 13281 * It stores tree of all test cases, sections and assertions, and after the 13282 * test run is finished, calls into `testRunEndedCumulative` to pass the 13283 * control to the deriving class. 13284 * 13285 * If you are deriving from this class and override any testing related 13286 * member functions, you should first call into the base's implementation to 13287 * avoid breaking the tree construction. 13288 * 13289 * Due to the way this base functions, it has to expand assertions up-front, 13290 * even if they are later unused (e.g. because the deriving reporter does 13291 * not report successful assertions, or because the deriving reporter does 13292 * not use assertion expansion at all). Derived classes can use two 13293 * customization points, `m_shouldStoreSuccesfulAssertions` and 13294 * `m_shouldStoreFailedAssertions`, to disable the expansion and gain extra 13295 * performance. **Accessing the assertion expansions if it wasn't stored is 13296 * UB.** 13297 */ 13298 class CumulativeReporterBase : public ReporterBase { 13299 public: 13300 template<typename T, typename ChildNodeT> 13301 struct Node { 13302 explicit Node( T const& _value ) : value( _value ) {} 13303 13304 using ChildNodes = std::vector<Detail::unique_ptr<ChildNodeT>>; 13305 T value; 13306 ChildNodes children; 13307 }; 13308 struct SectionNode { 13309 explicit SectionNode(SectionStats const& _stats) : stats(_stats) {} 13310 13311 bool operator == (SectionNode const& other) const { 13312 return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; 13313 } 13314 13315 bool hasAnyAssertions() const; 13316 13317 SectionStats stats; 13318 std::vector<Detail::unique_ptr<SectionNode>> childSections; 13319 std::vector<Detail::AssertionOrBenchmarkResult> assertionsAndBenchmarks; 13320 std::string stdOut; 13321 std::string stdErr; 13322 }; 13323 13324 13325 using TestCaseNode = Node<TestCaseStats, SectionNode>; 13326 using TestRunNode = Node<TestRunStats, TestCaseNode>; 13327 13328 // GCC5 compat: we cannot use inherited constructor, because it 13329 // doesn't implement backport of P0136 13330 CumulativeReporterBase(ReporterConfig&& _config): 13331 ReporterBase(CATCH_MOVE(_config)) 13332 {} 13333 ~CumulativeReporterBase() override; 13334 13335 void benchmarkPreparing( StringRef ) override {} 13336 void benchmarkStarting( BenchmarkInfo const& ) override {} 13337 void benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) override; 13338 void benchmarkFailed( StringRef ) override {} 13339 13340 void noMatchingTestCases( StringRef ) override {} 13341 void reportInvalidTestSpec( StringRef ) override {} 13342 void fatalErrorEncountered( StringRef /*error*/ ) override {} 13343 13344 void testRunStarting( TestRunInfo const& ) override {} 13345 13346 void testCaseStarting( TestCaseInfo const& ) override {} 13347 void testCasePartialStarting( TestCaseInfo const&, uint64_t ) override {} 13348 void sectionStarting( SectionInfo const& sectionInfo ) override; 13349 13350 void assertionStarting( AssertionInfo const& ) override {} 13351 13352 void assertionEnded( AssertionStats const& assertionStats ) override; 13353 void sectionEnded( SectionStats const& sectionStats ) override; 13354 void testCasePartialEnded( TestCaseStats const&, uint64_t ) override {} 13355 void testCaseEnded( TestCaseStats const& testCaseStats ) override; 13356 void testRunEnded( TestRunStats const& testRunStats ) override; 13357 //! Customization point: called after last test finishes (testRunEnded has been handled) 13358 virtual void testRunEndedCumulative() = 0; 13359 13360 void skipTest(TestCaseInfo const&) override {} 13361 13362 protected: 13363 //! Should the cumulative base store the assertion expansion for successful assertions? 13364 bool m_shouldStoreSuccesfulAssertions = true; 13365 //! Should the cumulative base store the assertion expansion for failed assertions? 13366 bool m_shouldStoreFailedAssertions = true; 13367 13368 // We need lazy construction here. We should probably refactor it 13369 // later, after the events are redone. 13370 //! The root node of the test run tree. 13371 Detail::unique_ptr<TestRunNode> m_testRun; 13372 13373 private: 13374 // Note: We rely on pointer identity being stable, which is why 13375 // we store pointers to the nodes rather than the values. 13376 std::vector<Detail::unique_ptr<TestCaseNode>> m_testCases; 13377 // Root section of the _current_ test case 13378 Detail::unique_ptr<SectionNode> m_rootSection; 13379 // Deepest section of the _current_ test case 13380 SectionNode* m_deepestSection = nullptr; 13381 // Stack of _active_ sections in the _current_ test case 13382 std::vector<SectionNode*> m_sectionStack; 13383 }; 13384 13385} // end namespace Catch 13386 13387#endif // CATCH_REPORTER_CUMULATIVE_BASE_HPP_INCLUDED 13388 13389 13390#ifndef CATCH_REPORTER_EVENT_LISTENER_HPP_INCLUDED 13391#define CATCH_REPORTER_EVENT_LISTENER_HPP_INCLUDED 13392 13393 13394namespace Catch { 13395 13396 /** 13397 * Base class to simplify implementing listeners. 13398 * 13399 * Provides empty default implementation for all IEventListener member 13400 * functions, so that a listener implementation can pick which 13401 * member functions it actually cares about. 13402 */ 13403 class EventListenerBase : public IEventListener { 13404 public: 13405 using IEventListener::IEventListener; 13406 13407 void reportInvalidTestSpec( StringRef unmatchedSpec ) override; 13408 void fatalErrorEncountered( StringRef error ) override; 13409 13410 void benchmarkPreparing( StringRef name ) override; 13411 void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) override; 13412 void benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) override; 13413 void benchmarkFailed( StringRef error ) override; 13414 13415 void assertionStarting( AssertionInfo const& assertionInfo ) override; 13416 void assertionEnded( AssertionStats const& assertionStats ) override; 13417 13418 void listReporters( 13419 std::vector<ReporterDescription> const& descriptions ) override; 13420 void listListeners( 13421 std::vector<ListenerDescription> const& descriptions ) override; 13422 void listTests( std::vector<TestCaseHandle> const& tests ) override; 13423 void listTags( std::vector<TagInfo> const& tagInfos ) override; 13424 13425 void noMatchingTestCases( StringRef unmatchedSpec ) override; 13426 void testRunStarting( TestRunInfo const& testRunInfo ) override; 13427 void testCaseStarting( TestCaseInfo const& testInfo ) override; 13428 void testCasePartialStarting( TestCaseInfo const& testInfo, 13429 uint64_t partNumber ) override; 13430 void sectionStarting( SectionInfo const& sectionInfo ) override; 13431 void sectionEnded( SectionStats const& sectionStats ) override; 13432 void testCasePartialEnded( TestCaseStats const& testCaseStats, 13433 uint64_t partNumber ) override; 13434 void testCaseEnded( TestCaseStats const& testCaseStats ) override; 13435 void testRunEnded( TestRunStats const& testRunStats ) override; 13436 void skipTest( TestCaseInfo const& testInfo ) override; 13437 }; 13438 13439} // end namespace Catch 13440 13441#endif // CATCH_REPORTER_EVENT_LISTENER_HPP_INCLUDED 13442 13443 13444#ifndef CATCH_REPORTER_HELPERS_HPP_INCLUDED 13445#define CATCH_REPORTER_HELPERS_HPP_INCLUDED 13446 13447#include <iosfwd> 13448#include <string> 13449#include <vector> 13450 13451 13452namespace Catch { 13453 13454 class IConfig; 13455 class TestCaseHandle; 13456 class ColourImpl; 13457 13458 // Returns double formatted as %.3f (format expected on output) 13459 std::string getFormattedDuration( double duration ); 13460 13461 //! Should the reporter show duration of test given current configuration? 13462 bool shouldShowDuration( IConfig const& config, double duration ); 13463 13464 std::string serializeFilters( std::vector<std::string> const& filters ); 13465 13466 struct lineOfChars { 13467 char c; 13468 constexpr lineOfChars( char c_ ): c( c_ ) {} 13469 13470 friend std::ostream& operator<<( std::ostream& out, lineOfChars value ); 13471 }; 13472 13473 /** 13474 * Lists reporter descriptions to the provided stream in user-friendly 13475 * format 13476 * 13477 * Used as the default listing implementation by the first party reporter 13478 * bases. The output should be backwards compatible with the output of 13479 * Catch2 v2 binaries. 13480 */ 13481 void 13482 defaultListReporters( std::ostream& out, 13483 std::vector<ReporterDescription> const& descriptions, 13484 Verbosity verbosity ); 13485 13486 /** 13487 * Lists listeners descriptions to the provided stream in user-friendly 13488 * format 13489 */ 13490 void defaultListListeners( std::ostream& out, 13491 std::vector<ListenerDescription> const& descriptions ); 13492 13493 /** 13494 * Lists tag information to the provided stream in user-friendly format 13495 * 13496 * Used as the default listing implementation by the first party reporter 13497 * bases. The output should be backwards compatible with the output of 13498 * Catch2 v2 binaries. 13499 */ 13500 void defaultListTags( std::ostream& out, std::vector<TagInfo> const& tags, bool isFiltered ); 13501 13502 /** 13503 * Lists test case information to the provided stream in user-friendly 13504 * format 13505 * 13506 * Used as the default listing implementation by the first party reporter 13507 * bases. The output is backwards compatible with the output of Catch2 13508 * v2 binaries, and also supports the format specific to the old 13509 * `--list-test-names-only` option, for people who used it in integrations. 13510 */ 13511 void defaultListTests( std::ostream& out, 13512 ColourImpl* streamColour, 13513 std::vector<TestCaseHandle> const& tests, 13514 bool isFiltered, 13515 Verbosity verbosity ); 13516 13517 /** 13518 * Prints test run totals to the provided stream in user-friendly format 13519 * 13520 * Used by the console and compact reporters. 13521 */ 13522 void printTestRunTotals( std::ostream& stream, 13523 ColourImpl& streamColour, 13524 Totals const& totals ); 13525 13526} // end namespace Catch 13527 13528#endif // CATCH_REPORTER_HELPERS_HPP_INCLUDED 13529 13530 13531 13532#ifndef CATCH_REPORTER_JSON_HPP_INCLUDED 13533#define CATCH_REPORTER_JSON_HPP_INCLUDED 13534 13535 13536#include <stack> 13537 13538namespace Catch { 13539 class JsonReporter : public StreamingReporterBase { 13540 public: 13541 JsonReporter( ReporterConfig&& config ); 13542 13543 ~JsonReporter() override; 13544 13545 static std::string getDescription(); 13546 13547 public: // StreamingReporterBase 13548 void testRunStarting( TestRunInfo const& runInfo ) override; 13549 void testRunEnded( TestRunStats const& runStats ) override; 13550 13551 void testCaseStarting( TestCaseInfo const& tcInfo ) override; 13552 void testCaseEnded( TestCaseStats const& tcStats ) override; 13553 13554 void testCasePartialStarting( TestCaseInfo const& tcInfo, 13555 uint64_t index ) override; 13556 void testCasePartialEnded( TestCaseStats const& tcStats, 13557 uint64_t index ) override; 13558 13559 void sectionStarting( SectionInfo const& sectionInfo ) override; 13560 void sectionEnded( SectionStats const& sectionStats ) override; 13561 13562 void assertionStarting( AssertionInfo const& assertionInfo ) override; 13563 void assertionEnded( AssertionStats const& assertionStats ) override; 13564 13565 //void testRunEndedCumulative() override; 13566 13567 void benchmarkPreparing( StringRef name ) override; 13568 void benchmarkStarting( BenchmarkInfo const& ) override; 13569 void benchmarkEnded( BenchmarkStats<> const& ) override; 13570 void benchmarkFailed( StringRef error ) override; 13571 13572 void listReporters( 13573 std::vector<ReporterDescription> const& descriptions ) override; 13574 void listListeners( 13575 std::vector<ListenerDescription> const& descriptions ) override; 13576 void listTests( std::vector<TestCaseHandle> const& tests ) override; 13577 void listTags( std::vector<TagInfo> const& tags ) override; 13578 13579 private: 13580 Timer m_testCaseTimer; 13581 enum class Writer { 13582 Object, 13583 Array 13584 }; 13585 13586 JsonArrayWriter& startArray(); 13587 JsonArrayWriter& startArray( StringRef key ); 13588 13589 JsonObjectWriter& startObject(); 13590 JsonObjectWriter& startObject( StringRef key ); 13591 13592 void endObject(); 13593 void endArray(); 13594 13595 bool isInside( Writer writer ); 13596 13597 void startListing(); 13598 void endListing(); 13599 13600 // Invariant: 13601 // When m_writers is not empty and its top element is 13602 // - Writer::Object, then m_objectWriters is not be empty 13603 // - Writer::Array, then m_arrayWriters shall not be empty 13604 std::stack<JsonObjectWriter> m_objectWriters{}; 13605 std::stack<JsonArrayWriter> m_arrayWriters{}; 13606 std::stack<Writer> m_writers{}; 13607 13608 bool m_startedListing = false; 13609 13610 // std::size_t m_sectionDepth = 0; 13611 // std::size_t m_sectionStarted = 0; 13612 }; 13613} // namespace Catch 13614 13615#endif // CATCH_REPORTER_JSON_HPP_INCLUDED 13616 13617 13618#ifndef CATCH_REPORTER_JUNIT_HPP_INCLUDED 13619#define CATCH_REPORTER_JUNIT_HPP_INCLUDED 13620 13621 13622 13623namespace Catch { 13624 13625 class JunitReporter final : public CumulativeReporterBase { 13626 public: 13627 JunitReporter(ReporterConfig&& _config); 13628 13629 static std::string getDescription(); 13630 13631 void testRunStarting(TestRunInfo const& runInfo) override; 13632 13633 void testCaseStarting(TestCaseInfo const& testCaseInfo) override; 13634 void assertionEnded(AssertionStats const& assertionStats) override; 13635 13636 void testCaseEnded(TestCaseStats const& testCaseStats) override; 13637 13638 void testRunEndedCumulative() override; 13639 13640 private: 13641 void writeRun(TestRunNode const& testRunNode, double suiteTime); 13642 13643 void writeTestCase(TestCaseNode const& testCaseNode); 13644 13645 void writeSection( std::string const& className, 13646 std::string const& rootName, 13647 SectionNode const& sectionNode, 13648 bool testOkToFail ); 13649 13650 void writeAssertions(SectionNode const& sectionNode); 13651 void writeAssertion(AssertionStats const& stats); 13652 13653 XmlWriter xml; 13654 Timer suiteTimer; 13655 std::string stdOutForSuite; 13656 std::string stdErrForSuite; 13657 unsigned int unexpectedExceptions = 0; 13658 bool m_okToFail = false; 13659 }; 13660 13661} // end namespace Catch 13662 13663#endif // CATCH_REPORTER_JUNIT_HPP_INCLUDED 13664 13665 13666#ifndef CATCH_REPORTER_MULTI_HPP_INCLUDED 13667#define CATCH_REPORTER_MULTI_HPP_INCLUDED 13668 13669 13670namespace Catch { 13671 13672 class MultiReporter final : public IEventListener { 13673 /* 13674 * Stores all added reporters and listeners 13675 * 13676 * All Listeners are stored before all reporters, and individual 13677 * listeners/reporters are stored in order of insertion. 13678 */ 13679 std::vector<IEventListenerPtr> m_reporterLikes; 13680 bool m_haveNoncapturingReporters = false; 13681 13682 // Keep track of how many listeners we have already inserted, 13683 // so that we can insert them into the main vector at the right place 13684 size_t m_insertedListeners = 0; 13685 13686 void updatePreferences(IEventListener const& reporterish); 13687 13688 public: 13689 using IEventListener::IEventListener; 13690 13691 void addListener( IEventListenerPtr&& listener ); 13692 void addReporter( IEventListenerPtr&& reporter ); 13693 13694 public: // IEventListener 13695 13696 void noMatchingTestCases( StringRef unmatchedSpec ) override; 13697 void fatalErrorEncountered( StringRef error ) override; 13698 void reportInvalidTestSpec( StringRef arg ) override; 13699 13700 void benchmarkPreparing( StringRef name ) override; 13701 void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) override; 13702 void benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) override; 13703 void benchmarkFailed( StringRef error ) override; 13704 13705 void testRunStarting( TestRunInfo const& testRunInfo ) override; 13706 void testCaseStarting( TestCaseInfo const& testInfo ) override; 13707 void testCasePartialStarting(TestCaseInfo const& testInfo, uint64_t partNumber) override; 13708 void sectionStarting( SectionInfo const& sectionInfo ) override; 13709 void assertionStarting( AssertionInfo const& assertionInfo ) override; 13710 13711 void assertionEnded( AssertionStats const& assertionStats ) override; 13712 void sectionEnded( SectionStats const& sectionStats ) override; 13713 void testCasePartialEnded(TestCaseStats const& testStats, uint64_t partNumber) override; 13714 void testCaseEnded( TestCaseStats const& testCaseStats ) override; 13715 void testRunEnded( TestRunStats const& testRunStats ) override; 13716 13717 void skipTest( TestCaseInfo const& testInfo ) override; 13718 13719 void listReporters(std::vector<ReporterDescription> const& descriptions) override; 13720 void listListeners(std::vector<ListenerDescription> const& descriptions) override; 13721 void listTests(std::vector<TestCaseHandle> const& tests) override; 13722 void listTags(std::vector<TagInfo> const& tags) override; 13723 13724 13725 }; 13726 13727} // end namespace Catch 13728 13729#endif // CATCH_REPORTER_MULTI_HPP_INCLUDED 13730 13731 13732#ifndef CATCH_REPORTER_REGISTRARS_HPP_INCLUDED 13733#define CATCH_REPORTER_REGISTRARS_HPP_INCLUDED 13734 13735 13736#include <type_traits> 13737 13738namespace Catch { 13739 13740 namespace Detail { 13741 13742 template <typename T, typename = void> 13743 struct has_description : std::false_type {}; 13744 13745 template <typename T> 13746 struct has_description< 13747 T, 13748 void_t<decltype( T::getDescription() )>> 13749 : std::true_type {}; 13750 13751 //! Indirection for reporter registration, so that the error handling is 13752 //! independent on the reporter's concrete type 13753 void registerReporterImpl( std::string const& name, 13754 IReporterFactoryPtr reporterPtr ); 13755 //! Actually registers the factory, independent on listener's concrete type 13756 void registerListenerImpl( Detail::unique_ptr<EventListenerFactory> listenerFactory ); 13757 } // namespace Detail 13758 13759 class IEventListener; 13760 using IEventListenerPtr = Detail::unique_ptr<IEventListener>; 13761 13762 template <typename T> 13763 class ReporterFactory : public IReporterFactory { 13764 13765 IEventListenerPtr create( ReporterConfig&& config ) const override { 13766 return Detail::make_unique<T>( CATCH_MOVE(config) ); 13767 } 13768 13769 std::string getDescription() const override { 13770 return T::getDescription(); 13771 } 13772 }; 13773 13774 13775 template<typename T> 13776 class ReporterRegistrar { 13777 public: 13778 explicit ReporterRegistrar( std::string const& name ) { 13779 registerReporterImpl( name, 13780 Detail::make_unique<ReporterFactory<T>>() ); 13781 } 13782 }; 13783 13784 template<typename T> 13785 class ListenerRegistrar { 13786 13787 class TypedListenerFactory : public EventListenerFactory { 13788 StringRef m_listenerName; 13789 13790 std::string getDescriptionImpl( std::true_type ) const { 13791 return T::getDescription(); 13792 } 13793 13794 std::string getDescriptionImpl( std::false_type ) const { 13795 return "(No description provided)"; 13796 } 13797 13798 public: 13799 TypedListenerFactory( StringRef listenerName ): 13800 m_listenerName( listenerName ) {} 13801 13802 IEventListenerPtr create( IConfig const* config ) const override { 13803 return Detail::make_unique<T>( config ); 13804 } 13805 13806 StringRef getName() const override { 13807 return m_listenerName; 13808 } 13809 13810 std::string getDescription() const override { 13811 return getDescriptionImpl( Detail::has_description<T>{} ); 13812 } 13813 }; 13814 13815 public: 13816 ListenerRegistrar(StringRef listenerName) { 13817 registerListenerImpl( Detail::make_unique<TypedListenerFactory>(listenerName) ); 13818 } 13819 }; 13820} 13821 13822#if !defined(CATCH_CONFIG_DISABLE) 13823 13824# define CATCH_REGISTER_REPORTER( name, reporterType ) \ 13825 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 13826 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 13827 namespace { \ 13828 Catch::ReporterRegistrar<reporterType> INTERNAL_CATCH_UNIQUE_NAME( \ 13829 catch_internal_RegistrarFor )( name ); \ 13830 } \ 13831 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 13832 13833# define CATCH_REGISTER_LISTENER( listenerType ) \ 13834 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ 13835 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 13836 namespace { \ 13837 Catch::ListenerRegistrar<listenerType> INTERNAL_CATCH_UNIQUE_NAME( \ 13838 catch_internal_RegistrarFor )( #listenerType##_catch_sr ); \ 13839 } \ 13840 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION 13841 13842#else // CATCH_CONFIG_DISABLE 13843 13844#define CATCH_REGISTER_REPORTER(name, reporterType) 13845#define CATCH_REGISTER_LISTENER(listenerType) 13846 13847#endif // CATCH_CONFIG_DISABLE 13848 13849#endif // CATCH_REPORTER_REGISTRARS_HPP_INCLUDED 13850 13851 13852#ifndef CATCH_REPORTER_SONARQUBE_HPP_INCLUDED 13853#define CATCH_REPORTER_SONARQUBE_HPP_INCLUDED 13854 13855 13856 13857namespace Catch { 13858 13859 class SonarQubeReporter final : public CumulativeReporterBase { 13860 public: 13861 SonarQubeReporter(ReporterConfig&& config) 13862 : CumulativeReporterBase(CATCH_MOVE(config)) 13863 , xml(m_stream) { 13864 m_preferences.shouldRedirectStdOut = true; 13865 m_preferences.shouldReportAllAssertions = true; 13866 m_shouldStoreSuccesfulAssertions = false; 13867 } 13868 13869 static std::string getDescription() { 13870 using namespace std::string_literals; 13871 return "Reports test results in the Generic Test Data SonarQube XML format"s; 13872 } 13873 13874 void testRunStarting( TestRunInfo const& testRunInfo ) override; 13875 13876 void testRunEndedCumulative() override { 13877 writeRun( *m_testRun ); 13878 xml.endElement(); 13879 } 13880 13881 void writeRun( TestRunNode const& runNode ); 13882 13883 void writeTestFile(StringRef filename, std::vector<TestCaseNode const*> const& testCaseNodes); 13884 13885 void writeTestCase(TestCaseNode const& testCaseNode); 13886 13887 void writeSection(std::string const& rootName, SectionNode const& sectionNode, bool okToFail); 13888 13889 void writeAssertions(SectionNode const& sectionNode, bool okToFail); 13890 13891 void writeAssertion(AssertionStats const& stats, bool okToFail); 13892 13893 private: 13894 XmlWriter xml; 13895 }; 13896 13897 13898} // end namespace Catch 13899 13900#endif // CATCH_REPORTER_SONARQUBE_HPP_INCLUDED 13901 13902 13903#ifndef CATCH_REPORTER_TAP_HPP_INCLUDED 13904#define CATCH_REPORTER_TAP_HPP_INCLUDED 13905 13906 13907namespace Catch { 13908 13909 class TAPReporter final : public StreamingReporterBase { 13910 public: 13911 TAPReporter( ReporterConfig&& config ): 13912 StreamingReporterBase( CATCH_MOVE(config) ) { 13913 m_preferences.shouldReportAllAssertions = true; 13914 } 13915 13916 static std::string getDescription() { 13917 using namespace std::string_literals; 13918 return "Reports test results in TAP format, suitable for test harnesses"s; 13919 } 13920 13921 void testRunStarting( TestRunInfo const& testInfo ) override; 13922 13923 void noMatchingTestCases( StringRef unmatchedSpec ) override; 13924 13925 void assertionEnded(AssertionStats const& _assertionStats) override; 13926 13927 void testRunEnded(TestRunStats const& _testRunStats) override; 13928 13929 private: 13930 std::size_t counter = 0; 13931 }; 13932 13933} // end namespace Catch 13934 13935#endif // CATCH_REPORTER_TAP_HPP_INCLUDED 13936 13937 13938#ifndef CATCH_REPORTER_TEAMCITY_HPP_INCLUDED 13939#define CATCH_REPORTER_TEAMCITY_HPP_INCLUDED 13940 13941 13942#include <cstring> 13943 13944#ifdef __clang__ 13945# pragma clang diagnostic push 13946# pragma clang diagnostic ignored "-Wpadded" 13947#endif 13948 13949namespace Catch { 13950 13951 class TeamCityReporter final : public StreamingReporterBase { 13952 public: 13953 TeamCityReporter( ReporterConfig&& _config ) 13954 : StreamingReporterBase( CATCH_MOVE(_config) ) 13955 { 13956 m_preferences.shouldRedirectStdOut = true; 13957 } 13958 13959 ~TeamCityReporter() override; 13960 13961 static std::string getDescription() { 13962 using namespace std::string_literals; 13963 return "Reports test results as TeamCity service messages"s; 13964 } 13965 13966 void testRunStarting( TestRunInfo const& runInfo ) override; 13967 void testRunEnded( TestRunStats const& runStats ) override; 13968 13969 13970 void assertionEnded(AssertionStats const& assertionStats) override; 13971 13972 void sectionStarting(SectionInfo const& sectionInfo) override { 13973 m_headerPrintedForThisSection = false; 13974 StreamingReporterBase::sectionStarting( sectionInfo ); 13975 } 13976 13977 void testCaseStarting(TestCaseInfo const& testInfo) override; 13978 13979 void testCaseEnded(TestCaseStats const& testCaseStats) override; 13980 13981 private: 13982 void printSectionHeader(std::ostream& os); 13983 13984 bool m_headerPrintedForThisSection = false; 13985 Timer m_testTimer; 13986 }; 13987 13988} // end namespace Catch 13989 13990#ifdef __clang__ 13991# pragma clang diagnostic pop 13992#endif 13993 13994#endif // CATCH_REPORTER_TEAMCITY_HPP_INCLUDED 13995 13996 13997#ifndef CATCH_REPORTER_XML_HPP_INCLUDED 13998#define CATCH_REPORTER_XML_HPP_INCLUDED 13999 14000 14001 14002 14003namespace Catch { 14004 class XmlReporter : public StreamingReporterBase { 14005 public: 14006 XmlReporter(ReporterConfig&& _config); 14007 14008 ~XmlReporter() override; 14009 14010 static std::string getDescription(); 14011 14012 virtual std::string getStylesheetRef() const; 14013 14014 void writeSourceInfo(SourceLineInfo const& sourceInfo); 14015 14016 public: // StreamingReporterBase 14017 14018 void testRunStarting(TestRunInfo const& testInfo) override; 14019 14020 void testCaseStarting(TestCaseInfo const& testInfo) override; 14021 14022 void sectionStarting(SectionInfo const& sectionInfo) override; 14023 14024 void assertionStarting(AssertionInfo const&) override; 14025 14026 void assertionEnded(AssertionStats const& assertionStats) override; 14027 14028 void sectionEnded(SectionStats const& sectionStats) override; 14029 14030 void testCaseEnded(TestCaseStats const& testCaseStats) override; 14031 14032 void testRunEnded(TestRunStats const& testRunStats) override; 14033 14034 void benchmarkPreparing( StringRef name ) override; 14035 void benchmarkStarting(BenchmarkInfo const&) override; 14036 void benchmarkEnded(BenchmarkStats<> const&) override; 14037 void benchmarkFailed( StringRef error ) override; 14038 14039 void listReporters(std::vector<ReporterDescription> const& descriptions) override; 14040 void listListeners(std::vector<ListenerDescription> const& descriptions) override; 14041 void listTests(std::vector<TestCaseHandle> const& tests) override; 14042 void listTags(std::vector<TagInfo> const& tags) override; 14043 14044 private: 14045 Timer m_testCaseTimer; 14046 XmlWriter m_xml; 14047 int m_sectionDepth = 0; 14048 }; 14049 14050} // end namespace Catch 14051 14052#endif // CATCH_REPORTER_XML_HPP_INCLUDED 14053 14054#endif // CATCH_REPORTERS_ALL_HPP_INCLUDED 14055 14056#endif // CATCH_ALL_HPP_INCLUDED 14057#endif // CATCH_AMALGAMATED_HPP_INCLUDED