doctest

FORK: The fastest feature-rich C++11/14/17/20 single-header testing framework
git clone https://git.neptards.moe/neptards/doctest.git
Log | Files | Refs | README

doctest.h (318443B)


      1 // ====================================================================== lgtm [cpp/missing-header-guard]
      2 // == DO NOT MODIFY THIS FILE BY HAND - IT IS AUTO GENERATED BY CMAKE! ==
      3 // ======================================================================
      4 //
      5 // doctest.h - the lightest feature-rich C++ single-header testing framework for unit tests and TDD
      6 //
      7 // Copyright (c) 2016-2021 Viktor Kirilov
      8 //
      9 // Distributed under the MIT Software License
     10 // See accompanying file LICENSE.txt or copy at
     11 // https://opensource.org/licenses/MIT
     12 //
     13 // The documentation can be found at the library's page:
     14 // https://github.com/doctest/doctest/blob/master/doc/markdown/readme.md
     15 //
     16 // =================================================================================================
     17 // =================================================================================================
     18 // =================================================================================================
     19 //
     20 // The library is heavily influenced by Catch - https://github.com/catchorg/Catch2
     21 // which uses the Boost Software License - Version 1.0
     22 // see here - https://github.com/catchorg/Catch2/blob/master/LICENSE.txt
     23 //
     24 // The concept of subcases (sections in Catch) and expression decomposition are from there.
     25 // Some parts of the code are taken directly:
     26 // - stringification - the detection of "ostream& operator<<(ostream&, const T&)" and StringMaker<>
     27 // - the Approx() helper class for floating point comparison
     28 // - colors in the console
     29 // - breaking into a debugger
     30 // - signal / SEH handling
     31 // - timer
     32 // - XmlWriter class - thanks to Phil Nash for allowing the direct reuse (AKA copy/paste)
     33 //
     34 // The expression decomposing templates are taken from lest - https://github.com/martinmoene/lest
     35 // which uses the Boost Software License - Version 1.0
     36 // see here - https://github.com/martinmoene/lest/blob/master/LICENSE.txt
     37 //
     38 // =================================================================================================
     39 // =================================================================================================
     40 // =================================================================================================
     41 
     42 #ifndef DOCTEST_LIBRARY_INCLUDED
     43 #define DOCTEST_LIBRARY_INCLUDED
     44 
     45 // =================================================================================================
     46 // == VERSION ======================================================================================
     47 // =================================================================================================
     48 
     49 #define DOCTEST_VERSION_MAJOR 2
     50 #define DOCTEST_VERSION_MINOR 4
     51 #define DOCTEST_VERSION_PATCH 9
     52 
     53 // util we need here
     54 #define DOCTEST_TOSTR_IMPL(x) #x
     55 #define DOCTEST_TOSTR(x) DOCTEST_TOSTR_IMPL(x)
     56 
     57 #define DOCTEST_VERSION_STR                                                                        \
     58     DOCTEST_TOSTR(DOCTEST_VERSION_MAJOR) "."                                                       \
     59     DOCTEST_TOSTR(DOCTEST_VERSION_MINOR) "."                                                       \
     60     DOCTEST_TOSTR(DOCTEST_VERSION_PATCH)
     61 
     62 #define DOCTEST_VERSION                                                                            \
     63     (DOCTEST_VERSION_MAJOR * 10000 + DOCTEST_VERSION_MINOR * 100 + DOCTEST_VERSION_PATCH)
     64 
     65 // =================================================================================================
     66 // == COMPILER VERSION =============================================================================
     67 // =================================================================================================
     68 
     69 // ideas for the version stuff are taken from here: https://github.com/cxxstuff/cxx_detect
     70 
     71 #ifdef _MSC_VER
     72 #define DOCTEST_CPLUSPLUS _MSVC_LANG
     73 #else
     74 #define DOCTEST_CPLUSPLUS __cplusplus
     75 #endif
     76 
     77 #define DOCTEST_COMPILER(MAJOR, MINOR, PATCH) ((MAJOR)*10000000 + (MINOR)*100000 + (PATCH))
     78 
     79 // GCC/Clang and GCC/MSVC are mutually exclusive, but Clang/MSVC are not because of clang-cl...
     80 #if defined(_MSC_VER) && defined(_MSC_FULL_VER)
     81 #if _MSC_VER == _MSC_FULL_VER / 10000
     82 #define DOCTEST_MSVC DOCTEST_COMPILER(_MSC_VER / 100, _MSC_VER % 100, _MSC_FULL_VER % 10000)
     83 #else // MSVC
     84 #define DOCTEST_MSVC                                                                               \
     85     DOCTEST_COMPILER(_MSC_VER / 100, (_MSC_FULL_VER / 100000) % 100, _MSC_FULL_VER % 100000)
     86 #endif // MSVC
     87 #endif // MSVC
     88 #if defined(__clang__) && defined(__clang_minor__)
     89 #define DOCTEST_CLANG DOCTEST_COMPILER(__clang_major__, __clang_minor__, __clang_patchlevel__)
     90 #elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) &&              \
     91         !defined(__INTEL_COMPILER)
     92 #define DOCTEST_GCC DOCTEST_COMPILER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
     93 #endif // GCC
     94 
     95 #ifndef DOCTEST_MSVC
     96 #define DOCTEST_MSVC 0
     97 #endif // DOCTEST_MSVC
     98 #ifndef DOCTEST_CLANG
     99 #define DOCTEST_CLANG 0
    100 #endif // DOCTEST_CLANG
    101 #ifndef DOCTEST_GCC
    102 #define DOCTEST_GCC 0
    103 #endif // DOCTEST_GCC
    104 
    105 // =================================================================================================
    106 // == COMPILER WARNINGS HELPERS ====================================================================
    107 // =================================================================================================
    108 
    109 #if DOCTEST_CLANG
    110 #define DOCTEST_PRAGMA_TO_STR(x) _Pragma(#x)
    111 #define DOCTEST_CLANG_SUPPRESS_WARNING_PUSH _Pragma("clang diagnostic push")
    112 #define DOCTEST_CLANG_SUPPRESS_WARNING(w) DOCTEST_PRAGMA_TO_STR(clang diagnostic ignored w)
    113 #define DOCTEST_CLANG_SUPPRESS_WARNING_POP _Pragma("clang diagnostic pop")
    114 #define DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH(w)                                                \
    115     DOCTEST_CLANG_SUPPRESS_WARNING_PUSH DOCTEST_CLANG_SUPPRESS_WARNING(w)
    116 #else // DOCTEST_CLANG
    117 #define DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
    118 #define DOCTEST_CLANG_SUPPRESS_WARNING(w)
    119 #define DOCTEST_CLANG_SUPPRESS_WARNING_POP
    120 #define DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH(w)
    121 #endif // DOCTEST_CLANG
    122 
    123 #if DOCTEST_GCC
    124 #define DOCTEST_PRAGMA_TO_STR(x) _Pragma(#x)
    125 #define DOCTEST_GCC_SUPPRESS_WARNING_PUSH _Pragma("GCC diagnostic push")
    126 #define DOCTEST_GCC_SUPPRESS_WARNING(w) DOCTEST_PRAGMA_TO_STR(GCC diagnostic ignored w)
    127 #define DOCTEST_GCC_SUPPRESS_WARNING_POP _Pragma("GCC diagnostic pop")
    128 #define DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH(w)                                                  \
    129     DOCTEST_GCC_SUPPRESS_WARNING_PUSH DOCTEST_GCC_SUPPRESS_WARNING(w)
    130 #else // DOCTEST_GCC
    131 #define DOCTEST_GCC_SUPPRESS_WARNING_PUSH
    132 #define DOCTEST_GCC_SUPPRESS_WARNING(w)
    133 #define DOCTEST_GCC_SUPPRESS_WARNING_POP
    134 #define DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH(w)
    135 #endif // DOCTEST_GCC
    136 
    137 #if DOCTEST_MSVC
    138 #define DOCTEST_MSVC_SUPPRESS_WARNING_PUSH __pragma(warning(push))
    139 #define DOCTEST_MSVC_SUPPRESS_WARNING(w) __pragma(warning(disable : w))
    140 #define DOCTEST_MSVC_SUPPRESS_WARNING_POP __pragma(warning(pop))
    141 #define DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(w)                                                 \
    142     DOCTEST_MSVC_SUPPRESS_WARNING_PUSH DOCTEST_MSVC_SUPPRESS_WARNING(w)
    143 #else // DOCTEST_MSVC
    144 #define DOCTEST_MSVC_SUPPRESS_WARNING_PUSH
    145 #define DOCTEST_MSVC_SUPPRESS_WARNING(w)
    146 #define DOCTEST_MSVC_SUPPRESS_WARNING_POP
    147 #define DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(w)
    148 #endif // DOCTEST_MSVC
    149 
    150 // =================================================================================================
    151 // == COMPILER WARNINGS ============================================================================
    152 // =================================================================================================
    153 
    154 // both the header and the implementation suppress all of these,
    155 // so it only makes sense to aggregrate them like so
    156 #define DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH                                                      \
    157     DOCTEST_CLANG_SUPPRESS_WARNING_PUSH                                                            \
    158     DOCTEST_CLANG_SUPPRESS_WARNING("-Wunknown-pragmas")                                            \
    159     DOCTEST_CLANG_SUPPRESS_WARNING("-Wweak-vtables")                                               \
    160     DOCTEST_CLANG_SUPPRESS_WARNING("-Wpadded")                                                     \
    161     DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-prototypes")                                         \
    162     DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat")                                               \
    163     DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic")                                      \
    164                                                                                                    \
    165     DOCTEST_GCC_SUPPRESS_WARNING_PUSH                                                              \
    166     DOCTEST_GCC_SUPPRESS_WARNING("-Wunknown-pragmas")                                              \
    167     DOCTEST_GCC_SUPPRESS_WARNING("-Wpragmas")                                                      \
    168     DOCTEST_GCC_SUPPRESS_WARNING("-Weffc++")                                                       \
    169     DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-overflow")                                              \
    170     DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-aliasing")                                              \
    171     DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-declarations")                                         \
    172     DOCTEST_GCC_SUPPRESS_WARNING("-Wuseless-cast")                                                 \
    173     DOCTEST_GCC_SUPPRESS_WARNING("-Wnoexcept")                                                     \
    174                                                                                                    \
    175     DOCTEST_MSVC_SUPPRESS_WARNING_PUSH                                                             \
    176     /* these 4 also disabled globally via cmake: */                                                \
    177     DOCTEST_MSVC_SUPPRESS_WARNING(4514) /* unreferenced inline function has been removed */        \
    178     DOCTEST_MSVC_SUPPRESS_WARNING(4571) /* SEH related */                                          \
    179     DOCTEST_MSVC_SUPPRESS_WARNING(4710) /* function not inlined */                                 \
    180     DOCTEST_MSVC_SUPPRESS_WARNING(4711) /* function selected for inline expansion*/                \
    181     /* */                                                                                          \
    182     DOCTEST_MSVC_SUPPRESS_WARNING(4616) /* invalid compiler warning */                             \
    183     DOCTEST_MSVC_SUPPRESS_WARNING(4619) /* invalid compiler warning */                             \
    184     DOCTEST_MSVC_SUPPRESS_WARNING(4996) /* The compiler encountered a deprecated declaration */    \
    185     DOCTEST_MSVC_SUPPRESS_WARNING(4706) /* assignment within conditional expression */             \
    186     DOCTEST_MSVC_SUPPRESS_WARNING(4512) /* 'class' : assignment operator could not be generated */ \
    187     DOCTEST_MSVC_SUPPRESS_WARNING(4127) /* conditional expression is constant */                   \
    188     DOCTEST_MSVC_SUPPRESS_WARNING(4820) /* padding */                                              \
    189     DOCTEST_MSVC_SUPPRESS_WARNING(4625) /* copy constructor was implicitly deleted */              \
    190     DOCTEST_MSVC_SUPPRESS_WARNING(4626) /* assignment operator was implicitly deleted */           \
    191     DOCTEST_MSVC_SUPPRESS_WARNING(5027) /* move assignment operator implicitly deleted */          \
    192     DOCTEST_MSVC_SUPPRESS_WARNING(5026) /* move constructor was implicitly deleted */              \
    193     DOCTEST_MSVC_SUPPRESS_WARNING(4640) /* construction of local static object not thread-safe */  \
    194     DOCTEST_MSVC_SUPPRESS_WARNING(5045) /* Spectre mitigation for memory load */                   \
    195     /* static analysis */                                                                          \
    196     DOCTEST_MSVC_SUPPRESS_WARNING(26439) /* Function may not throw. Declare it 'noexcept' */       \
    197     DOCTEST_MSVC_SUPPRESS_WARNING(26495) /* Always initialize a member variable */                 \
    198     DOCTEST_MSVC_SUPPRESS_WARNING(26451) /* Arithmetic overflow ... */                             \
    199     DOCTEST_MSVC_SUPPRESS_WARNING(26444) /* Avoid unnamed objects with custom ctor and dtor... */  \
    200     DOCTEST_MSVC_SUPPRESS_WARNING(26812) /* Prefer 'enum class' over 'enum' */
    201 
    202 #define DOCTEST_SUPPRESS_COMMON_WARNINGS_POP                                                       \
    203     DOCTEST_CLANG_SUPPRESS_WARNING_POP                                                             \
    204     DOCTEST_GCC_SUPPRESS_WARNING_POP                                                               \
    205     DOCTEST_MSVC_SUPPRESS_WARNING_POP
    206 
    207 DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH
    208 
    209 DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
    210 DOCTEST_CLANG_SUPPRESS_WARNING("-Wnon-virtual-dtor")
    211 DOCTEST_CLANG_SUPPRESS_WARNING("-Wdeprecated")
    212 
    213 DOCTEST_GCC_SUPPRESS_WARNING_PUSH
    214 DOCTEST_GCC_SUPPRESS_WARNING("-Wctor-dtor-privacy")
    215 DOCTEST_GCC_SUPPRESS_WARNING("-Wnon-virtual-dtor")
    216 DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-promo")
    217 
    218 DOCTEST_MSVC_SUPPRESS_WARNING_PUSH
    219 DOCTEST_MSVC_SUPPRESS_WARNING(4623) // default constructor was implicitly defined as deleted
    220 
    221 #define DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN                                 \
    222     DOCTEST_MSVC_SUPPRESS_WARNING_PUSH                                                             \
    223     DOCTEST_MSVC_SUPPRESS_WARNING(4548) /* before comma no effect; expected side - effect */       \
    224     DOCTEST_MSVC_SUPPRESS_WARNING(4265) /* virtual functions, but destructor is not virtual */     \
    225     DOCTEST_MSVC_SUPPRESS_WARNING(4986) /* exception specification does not match previous */      \
    226     DOCTEST_MSVC_SUPPRESS_WARNING(4350) /* 'member1' called instead of 'member2' */                \
    227     DOCTEST_MSVC_SUPPRESS_WARNING(4668) /* not defined as a preprocessor macro */                  \
    228     DOCTEST_MSVC_SUPPRESS_WARNING(4365) /* signed/unsigned mismatch */                             \
    229     DOCTEST_MSVC_SUPPRESS_WARNING(4774) /* format string not a string literal */                   \
    230     DOCTEST_MSVC_SUPPRESS_WARNING(4820) /* padding */                                              \
    231     DOCTEST_MSVC_SUPPRESS_WARNING(4625) /* copy constructor was implicitly deleted */              \
    232     DOCTEST_MSVC_SUPPRESS_WARNING(4626) /* assignment operator was implicitly deleted */           \
    233     DOCTEST_MSVC_SUPPRESS_WARNING(5027) /* move assignment operator implicitly deleted */          \
    234     DOCTEST_MSVC_SUPPRESS_WARNING(5026) /* move constructor was implicitly deleted */              \
    235     DOCTEST_MSVC_SUPPRESS_WARNING(4623) /* default constructor was implicitly deleted */           \
    236     DOCTEST_MSVC_SUPPRESS_WARNING(5039) /* pointer to pot. throwing function passed to extern C */ \
    237     DOCTEST_MSVC_SUPPRESS_WARNING(5045) /* Spectre mitigation for memory load */                   \
    238     DOCTEST_MSVC_SUPPRESS_WARNING(5105) /* macro producing 'defined' has undefined behavior */     \
    239     DOCTEST_MSVC_SUPPRESS_WARNING(4738) /* storing float result in memory, loss of performance */
    240 
    241 #define DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END DOCTEST_MSVC_SUPPRESS_WARNING_POP
    242 
    243 // =================================================================================================
    244 // == FEATURE DETECTION ============================================================================
    245 // =================================================================================================
    246 
    247 // general compiler feature support table: https://en.cppreference.com/w/cpp/compiler_support
    248 // MSVC C++11 feature support table: https://msdn.microsoft.com/en-us/library/hh567368.aspx
    249 // GCC C++11 feature support table: https://gcc.gnu.org/projects/cxx-status.html
    250 // MSVC version table:
    251 // https://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B#Internal_version_numbering
    252 // MSVC++ 14.3 (17) _MSC_VER == 1930 (Visual Studio 2022)
    253 // MSVC++ 14.2 (16) _MSC_VER == 1920 (Visual Studio 2019)
    254 // MSVC++ 14.1 (15) _MSC_VER == 1910 (Visual Studio 2017)
    255 // MSVC++ 14.0      _MSC_VER == 1900 (Visual Studio 2015)
    256 // MSVC++ 12.0      _MSC_VER == 1800 (Visual Studio 2013)
    257 // MSVC++ 11.0      _MSC_VER == 1700 (Visual Studio 2012)
    258 // MSVC++ 10.0      _MSC_VER == 1600 (Visual Studio 2010)
    259 // MSVC++ 9.0       _MSC_VER == 1500 (Visual Studio 2008)
    260 // MSVC++ 8.0       _MSC_VER == 1400 (Visual Studio 2005)
    261 
    262 // Universal Windows Platform support
    263 #if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
    264 #define DOCTEST_CONFIG_NO_WINDOWS_SEH
    265 #endif // WINAPI_FAMILY
    266 #if DOCTEST_MSVC && !defined(DOCTEST_CONFIG_WINDOWS_SEH)
    267 #define DOCTEST_CONFIG_WINDOWS_SEH
    268 #endif // MSVC
    269 #if defined(DOCTEST_CONFIG_NO_WINDOWS_SEH) && defined(DOCTEST_CONFIG_WINDOWS_SEH)
    270 #undef DOCTEST_CONFIG_WINDOWS_SEH
    271 #endif // DOCTEST_CONFIG_NO_WINDOWS_SEH
    272 
    273 #if !defined(_WIN32) && !defined(__QNX__) && !defined(DOCTEST_CONFIG_POSIX_SIGNALS) &&             \
    274         !defined(__EMSCRIPTEN__) && !defined(__wasi__)
    275 #define DOCTEST_CONFIG_POSIX_SIGNALS
    276 #endif // _WIN32
    277 #if defined(DOCTEST_CONFIG_NO_POSIX_SIGNALS) && defined(DOCTEST_CONFIG_POSIX_SIGNALS)
    278 #undef DOCTEST_CONFIG_POSIX_SIGNALS
    279 #endif // DOCTEST_CONFIG_NO_POSIX_SIGNALS
    280 
    281 #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
    282 #if !defined(__cpp_exceptions) && !defined(__EXCEPTIONS) && !defined(_CPPUNWIND)                   \
    283         || defined(__wasi__)
    284 #define DOCTEST_CONFIG_NO_EXCEPTIONS
    285 #endif // no exceptions
    286 #endif // DOCTEST_CONFIG_NO_EXCEPTIONS
    287 
    288 #ifdef DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS
    289 #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
    290 #define DOCTEST_CONFIG_NO_EXCEPTIONS
    291 #endif // DOCTEST_CONFIG_NO_EXCEPTIONS
    292 #endif // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS
    293 
    294 #if defined(DOCTEST_CONFIG_NO_EXCEPTIONS) && !defined(DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS)
    295 #define DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
    296 #endif // DOCTEST_CONFIG_NO_EXCEPTIONS && !DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
    297 
    298 #ifdef __wasi__
    299 #define DOCTEST_CONFIG_NO_MULTITHREADING
    300 #endif
    301 
    302 #if defined(DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN) && !defined(DOCTEST_CONFIG_IMPLEMENT)
    303 #define DOCTEST_CONFIG_IMPLEMENT
    304 #endif // DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
    305 
    306 #if defined(_WIN32) || defined(__CYGWIN__)
    307 #if DOCTEST_MSVC
    308 #define DOCTEST_SYMBOL_EXPORT __declspec(dllexport)
    309 #define DOCTEST_SYMBOL_IMPORT __declspec(dllimport)
    310 #else // MSVC
    311 #define DOCTEST_SYMBOL_EXPORT __attribute__((dllexport))
    312 #define DOCTEST_SYMBOL_IMPORT __attribute__((dllimport))
    313 #endif // MSVC
    314 #else  // _WIN32
    315 #define DOCTEST_SYMBOL_EXPORT __attribute__((visibility("default")))
    316 #define DOCTEST_SYMBOL_IMPORT
    317 #endif // _WIN32
    318 
    319 #ifdef DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL
    320 #ifdef DOCTEST_CONFIG_IMPLEMENT
    321 #define DOCTEST_INTERFACE DOCTEST_SYMBOL_EXPORT
    322 #else // DOCTEST_CONFIG_IMPLEMENT
    323 #define DOCTEST_INTERFACE DOCTEST_SYMBOL_IMPORT
    324 #endif // DOCTEST_CONFIG_IMPLEMENT
    325 #else  // DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL
    326 #define DOCTEST_INTERFACE
    327 #endif // DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL
    328 
    329 // needed for extern template instantiations
    330 // see https://github.com/fmtlib/fmt/issues/2228
    331 #if DOCTEST_MSVC
    332 #define DOCTEST_INTERFACE_DECL
    333 #define DOCTEST_INTERFACE_DEF DOCTEST_INTERFACE
    334 #else // DOCTEST_MSVC
    335 #define DOCTEST_INTERFACE_DECL DOCTEST_INTERFACE
    336 #define DOCTEST_INTERFACE_DEF
    337 #endif // DOCTEST_MSVC
    338 
    339 #define DOCTEST_EMPTY
    340 
    341 #if DOCTEST_MSVC
    342 #define DOCTEST_NOINLINE __declspec(noinline)
    343 #define DOCTEST_UNUSED
    344 #define DOCTEST_ALIGNMENT(x)
    345 #elif DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 5, 0)
    346 #define DOCTEST_NOINLINE
    347 #define DOCTEST_UNUSED
    348 #define DOCTEST_ALIGNMENT(x)
    349 #else
    350 #define DOCTEST_NOINLINE __attribute__((noinline))
    351 #define DOCTEST_UNUSED __attribute__((unused))
    352 #define DOCTEST_ALIGNMENT(x) __attribute__((aligned(x)))
    353 #endif
    354 
    355 #ifndef DOCTEST_NORETURN
    356 #if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0))
    357 #define DOCTEST_NORETURN
    358 #else // DOCTEST_MSVC
    359 #define DOCTEST_NORETURN [[noreturn]]
    360 #endif // DOCTEST_MSVC
    361 #endif // DOCTEST_NORETURN
    362 
    363 #ifndef DOCTEST_NOEXCEPT
    364 #if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0))
    365 #define DOCTEST_NOEXCEPT
    366 #else // DOCTEST_MSVC
    367 #define DOCTEST_NOEXCEPT noexcept
    368 #endif // DOCTEST_MSVC
    369 #endif // DOCTEST_NOEXCEPT
    370 
    371 #ifndef DOCTEST_CONSTEXPR
    372 #if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0))
    373 #define DOCTEST_CONSTEXPR const
    374 #define DOCTEST_CONSTEXPR_FUNC inline
    375 #else // DOCTEST_MSVC
    376 #define DOCTEST_CONSTEXPR constexpr
    377 #define DOCTEST_CONSTEXPR_FUNC constexpr
    378 #endif // DOCTEST_MSVC
    379 #endif // DOCTEST_CONSTEXPR
    380 
    381 // =================================================================================================
    382 // == FEATURE DETECTION END ========================================================================
    383 // =================================================================================================
    384 
    385 #define DOCTEST_DECLARE_INTERFACE(name)                                                            \
    386     virtual ~name();                                                                               \
    387     name() = default;                                                                              \
    388     name(const name&) = delete;                                                                    \
    389     name(name&&) = delete;                                                                         \
    390     name& operator=(const name&) = delete;                                                         \
    391     name& operator=(name&&) = delete;
    392 
    393 #define DOCTEST_DEFINE_INTERFACE(name)                                                             \
    394     name::~name() = default;
    395 
    396 // internal macros for string concatenation and anonymous variable name generation
    397 #define DOCTEST_CAT_IMPL(s1, s2) s1##s2
    398 #define DOCTEST_CAT(s1, s2) DOCTEST_CAT_IMPL(s1, s2)
    399 #ifdef __COUNTER__ // not standard and may be missing for some compilers
    400 #define DOCTEST_ANONYMOUS(x) DOCTEST_CAT(x, __COUNTER__)
    401 #else // __COUNTER__
    402 #define DOCTEST_ANONYMOUS(x) DOCTEST_CAT(x, __LINE__)
    403 #endif // __COUNTER__
    404 
    405 #ifndef DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE
    406 #define DOCTEST_REF_WRAP(x) x&
    407 #else // DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE
    408 #define DOCTEST_REF_WRAP(x) x
    409 #endif // DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE
    410 
    411 // not using __APPLE__ because... this is how Catch does it
    412 #ifdef __MAC_OS_X_VERSION_MIN_REQUIRED
    413 #define DOCTEST_PLATFORM_MAC
    414 #elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
    415 #define DOCTEST_PLATFORM_IPHONE
    416 #elif defined(_WIN32)
    417 #define DOCTEST_PLATFORM_WINDOWS
    418 #elif defined(__wasi__)
    419 #define DOCTEST_PLATFORM_WASI
    420 #else // DOCTEST_PLATFORM
    421 #define DOCTEST_PLATFORM_LINUX
    422 #endif // DOCTEST_PLATFORM
    423 
    424 namespace doctest { namespace detail {
    425     static DOCTEST_CONSTEXPR int consume(const int*, int) noexcept { return 0; }
    426 }}
    427 
    428 #define DOCTEST_GLOBAL_NO_WARNINGS(var, ...)                                                         \
    429     DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wglobal-constructors")                                \
    430     static const int var = doctest::detail::consume(&var, __VA_ARGS__);                              \
    431     DOCTEST_CLANG_SUPPRESS_WARNING_POP
    432 
    433 #ifndef DOCTEST_BREAK_INTO_DEBUGGER
    434 // should probably take a look at https://github.com/scottt/debugbreak
    435 #ifdef DOCTEST_PLATFORM_LINUX
    436 #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64))
    437 // Break at the location of the failing check if possible
    438 #define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) // NOLINT(hicpp-no-assembler)
    439 #else
    440 #include <signal.h>
    441 #define DOCTEST_BREAK_INTO_DEBUGGER() raise(SIGTRAP)
    442 #endif
    443 #elif defined(DOCTEST_PLATFORM_MAC)
    444 #if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || defined(__i386)
    445 #define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) // NOLINT(hicpp-no-assembler)
    446 #elif defined(__ppc__) || defined(__ppc64__)
    447 // https://www.cocoawithlove.com/2008/03/break-into-debugger.html
    448 #define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n": : : "memory","r0","r3","r4") // NOLINT(hicpp-no-assembler)
    449 #else
    450 #define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("brk #0"); // NOLINT(hicpp-no-assembler)
    451 #endif
    452 #elif DOCTEST_MSVC
    453 #define DOCTEST_BREAK_INTO_DEBUGGER() __debugbreak()
    454 #elif defined(__MINGW32__)
    455 DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wredundant-decls")
    456 extern "C" __declspec(dllimport) void __stdcall DebugBreak();
    457 DOCTEST_GCC_SUPPRESS_WARNING_POP
    458 #define DOCTEST_BREAK_INTO_DEBUGGER() ::DebugBreak()
    459 #else // linux
    460 #define DOCTEST_BREAK_INTO_DEBUGGER() (static_cast<void>(0))
    461 #endif // linux
    462 #endif // DOCTEST_BREAK_INTO_DEBUGGER
    463 
    464 // this is kept here for backwards compatibility since the config option was changed
    465 #ifdef DOCTEST_CONFIG_USE_IOSFWD
    466 #ifndef DOCTEST_CONFIG_USE_STD_HEADERS
    467 #define DOCTEST_CONFIG_USE_STD_HEADERS
    468 #endif
    469 #endif // DOCTEST_CONFIG_USE_IOSFWD
    470 
    471 // for clang - always include ciso646 (which drags some std stuff) because
    472 // we want to check if we are using libc++ with the _LIBCPP_VERSION macro in
    473 // which case we don't want to forward declare stuff from std - for reference:
    474 // https://github.com/doctest/doctest/issues/126
    475 // https://github.com/doctest/doctest/issues/356
    476 #include <ciso646>
    477 #ifdef _LIBCPP_VERSION
    478 #ifndef DOCTEST_CONFIG_USE_STD_HEADERS
    479 #define DOCTEST_CONFIG_USE_STD_HEADERS
    480 #endif
    481 #endif // _LIBCPP_VERSION
    482 
    483 #ifdef DOCTEST_CONFIG_USE_STD_HEADERS
    484 #ifndef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
    485 #define DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
    486 #endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
    487 DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN
    488 #include <cstddef>
    489 #include <ostream>
    490 #include <istream>
    491 DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END
    492 #else // DOCTEST_CONFIG_USE_STD_HEADERS
    493 
    494 // Forward declaring 'X' in namespace std is not permitted by the C++ Standard.
    495 DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4643)
    496 
    497 namespace std { // NOLINT(cert-dcl58-cpp)
    498 typedef decltype(nullptr) nullptr_t; // NOLINT(modernize-use-using)
    499 typedef decltype(sizeof(void*)) size_t; // NOLINT(modernize-use-using)
    500 template <class charT>
    501 struct char_traits;
    502 template <>
    503 struct char_traits<char>;
    504 template <class charT, class traits>
    505 class basic_ostream; // NOLINT(fuchsia-virtual-inheritance)
    506 typedef basic_ostream<char, char_traits<char>> ostream; // NOLINT(modernize-use-using)
    507 template<class traits>
    508 // NOLINTNEXTLINE
    509 basic_ostream<char, traits>& operator<<(basic_ostream<char, traits>&, const char*);
    510 template <class charT, class traits>
    511 class basic_istream;
    512 typedef basic_istream<char, char_traits<char>> istream; // NOLINT(modernize-use-using)
    513 template <class... Types>
    514 class tuple;
    515 #if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0)
    516 // see this issue on why this is needed: https://github.com/doctest/doctest/issues/183
    517 template <class Ty>
    518 class allocator;
    519 template <class Elem, class Traits, class Alloc>
    520 class basic_string;
    521 using string = basic_string<char, char_traits<char>, allocator<char>>;
    522 #endif // VS 2019
    523 } // namespace std
    524 
    525 DOCTEST_MSVC_SUPPRESS_WARNING_POP
    526 
    527 #endif // DOCTEST_CONFIG_USE_STD_HEADERS
    528 
    529 #ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
    530 #include <type_traits>
    531 #endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
    532 
    533 namespace doctest {
    534 
    535 using std::size_t;
    536 
    537 DOCTEST_INTERFACE extern bool is_running_in_test;
    538 
    539 #ifndef DOCTEST_CONFIG_STRING_SIZE_TYPE
    540 #define DOCTEST_CONFIG_STRING_SIZE_TYPE unsigned
    541 #endif
    542 
    543 // A 24 byte string class (can be as small as 17 for x64 and 13 for x86) that can hold strings with length
    544 // of up to 23 chars on the stack before going on the heap - the last byte of the buffer is used for:
    545 // - "is small" bit - the highest bit - if "0" then it is small - otherwise its "1" (128)
    546 // - if small - capacity left before going on the heap - using the lowest 5 bits
    547 // - if small - 2 bits are left unused - the second and third highest ones
    548 // - if small - acts as a null terminator if strlen() is 23 (24 including the null terminator)
    549 //              and the "is small" bit remains "0" ("as well as the capacity left") so its OK
    550 // Idea taken from this lecture about the string implementation of facebook/folly - fbstring
    551 // https://www.youtube.com/watch?v=kPR8h4-qZdk
    552 // TODO:
    553 // - optimizations - like not deleting memory unnecessarily in operator= and etc.
    554 // - resize/reserve/clear
    555 // - replace
    556 // - back/front
    557 // - iterator stuff
    558 // - find & friends
    559 // - push_back/pop_back
    560 // - assign/insert/erase
    561 // - relational operators as free functions - taking const char* as one of the params
    562 class DOCTEST_INTERFACE String
    563 {
    564 public:
    565     using size_type = DOCTEST_CONFIG_STRING_SIZE_TYPE;
    566 
    567 private:
    568     static DOCTEST_CONSTEXPR size_type len  = 24;      //!OCLINT avoid private static members
    569     static DOCTEST_CONSTEXPR size_type last = len - 1; //!OCLINT avoid private static members
    570 
    571     struct view // len should be more than sizeof(view) - because of the final byte for flags
    572     {
    573         char*    ptr;
    574         size_type size;
    575         size_type capacity;
    576     };
    577 
    578     union
    579     {
    580         char buf[len]; // NOLINT(*-avoid-c-arrays)
    581         view data;
    582     };
    583 
    584     char* allocate(size_type sz);
    585 
    586     bool isOnStack() const noexcept { return (buf[last] & 128) == 0; }
    587     void setOnHeap() noexcept;
    588     void setLast(size_type in = last) noexcept;
    589     void setSize(size_type sz) noexcept;
    590 
    591     void copy(const String& other);
    592 
    593 public:
    594     static DOCTEST_CONSTEXPR size_type npos = static_cast<size_type>(-1);
    595 
    596     String() noexcept;
    597     ~String();
    598 
    599     // cppcheck-suppress noExplicitConstructor
    600     String(const char* in);
    601     String(const char* in, size_type in_size);
    602 
    603     String(std::istream& in, size_type in_size);
    604 
    605     String(const String& other);
    606     String& operator=(const String& other);
    607 
    608     String& operator+=(const String& other);
    609 
    610     String(String&& other) noexcept;
    611     String& operator=(String&& other) noexcept;
    612 
    613     char  operator[](size_type i) const;
    614     char& operator[](size_type i);
    615 
    616     // the only functions I'm willing to leave in the interface - available for inlining
    617     const char* c_str() const { return const_cast<String*>(this)->c_str(); } // NOLINT
    618     char*       c_str() {
    619         if (isOnStack()) {
    620             return reinterpret_cast<char*>(buf);
    621         }
    622         return data.ptr;
    623     }
    624 
    625     size_type size() const;
    626     size_type capacity() const;
    627 
    628     String substr(size_type pos, size_type cnt = npos) &&;
    629     String substr(size_type pos, size_type cnt = npos) const &;
    630 
    631     size_type find(char ch, size_type pos = 0) const;
    632     size_type rfind(char ch, size_type pos = npos) const;
    633 
    634     int compare(const char* other, bool no_case = false) const;
    635     int compare(const String& other, bool no_case = false) const;
    636 
    637 friend DOCTEST_INTERFACE std::ostream& operator<<(std::ostream& s, const String& in);
    638 };
    639 
    640 DOCTEST_INTERFACE String operator+(const String& lhs, const String& rhs);
    641 
    642 DOCTEST_INTERFACE bool operator==(const String& lhs, const String& rhs);
    643 DOCTEST_INTERFACE bool operator!=(const String& lhs, const String& rhs);
    644 DOCTEST_INTERFACE bool operator<(const String& lhs, const String& rhs);
    645 DOCTEST_INTERFACE bool operator>(const String& lhs, const String& rhs);
    646 DOCTEST_INTERFACE bool operator<=(const String& lhs, const String& rhs);
    647 DOCTEST_INTERFACE bool operator>=(const String& lhs, const String& rhs);
    648 
    649 class DOCTEST_INTERFACE Contains {
    650 public:
    651     explicit Contains(const String& string);
    652 
    653     bool checkWith(const String& other) const;
    654 
    655     String string;
    656 };
    657 
    658 DOCTEST_INTERFACE String toString(const Contains& in);
    659 
    660 DOCTEST_INTERFACE bool operator==(const String& lhs, const Contains& rhs);
    661 DOCTEST_INTERFACE bool operator==(const Contains& lhs, const String& rhs);
    662 DOCTEST_INTERFACE bool operator!=(const String& lhs, const Contains& rhs);
    663 DOCTEST_INTERFACE bool operator!=(const Contains& lhs, const String& rhs);
    664 
    665 namespace Color {
    666     enum Enum
    667     {
    668         None = 0,
    669         White,
    670         Red,
    671         Green,
    672         Blue,
    673         Cyan,
    674         Yellow,
    675         Grey,
    676 
    677         Bright = 0x10,
    678 
    679         BrightRed   = Bright | Red,
    680         BrightGreen = Bright | Green,
    681         LightGrey   = Bright | Grey,
    682         BrightWhite = Bright | White
    683     };
    684 
    685     DOCTEST_INTERFACE std::ostream& operator<<(std::ostream& s, Color::Enum code);
    686 } // namespace Color
    687 
    688 namespace assertType {
    689     enum Enum
    690     {
    691         // macro traits
    692 
    693         is_warn    = 1,
    694         is_check   = 2 * is_warn,
    695         is_require = 2 * is_check,
    696 
    697         is_normal      = 2 * is_require,
    698         is_throws      = 2 * is_normal,
    699         is_throws_as   = 2 * is_throws,
    700         is_throws_with = 2 * is_throws_as,
    701         is_nothrow     = 2 * is_throws_with,
    702 
    703         is_false = 2 * is_nothrow,
    704         is_unary = 2 * is_false, // not checked anywhere - used just to distinguish the types
    705 
    706         is_eq = 2 * is_unary,
    707         is_ne = 2 * is_eq,
    708 
    709         is_lt = 2 * is_ne,
    710         is_gt = 2 * is_lt,
    711 
    712         is_ge = 2 * is_gt,
    713         is_le = 2 * is_ge,
    714 
    715         // macro types
    716 
    717         DT_WARN    = is_normal | is_warn,
    718         DT_CHECK   = is_normal | is_check,
    719         DT_REQUIRE = is_normal | is_require,
    720 
    721         DT_WARN_FALSE    = is_normal | is_false | is_warn,
    722         DT_CHECK_FALSE   = is_normal | is_false | is_check,
    723         DT_REQUIRE_FALSE = is_normal | is_false | is_require,
    724 
    725         DT_WARN_THROWS    = is_throws | is_warn,
    726         DT_CHECK_THROWS   = is_throws | is_check,
    727         DT_REQUIRE_THROWS = is_throws | is_require,
    728 
    729         DT_WARN_THROWS_AS    = is_throws_as | is_warn,
    730         DT_CHECK_THROWS_AS   = is_throws_as | is_check,
    731         DT_REQUIRE_THROWS_AS = is_throws_as | is_require,
    732 
    733         DT_WARN_THROWS_WITH    = is_throws_with | is_warn,
    734         DT_CHECK_THROWS_WITH   = is_throws_with | is_check,
    735         DT_REQUIRE_THROWS_WITH = is_throws_with | is_require,
    736 
    737         DT_WARN_THROWS_WITH_AS    = is_throws_with | is_throws_as | is_warn,
    738         DT_CHECK_THROWS_WITH_AS   = is_throws_with | is_throws_as | is_check,
    739         DT_REQUIRE_THROWS_WITH_AS = is_throws_with | is_throws_as | is_require,
    740 
    741         DT_WARN_NOTHROW    = is_nothrow | is_warn,
    742         DT_CHECK_NOTHROW   = is_nothrow | is_check,
    743         DT_REQUIRE_NOTHROW = is_nothrow | is_require,
    744 
    745         DT_WARN_EQ    = is_normal | is_eq | is_warn,
    746         DT_CHECK_EQ   = is_normal | is_eq | is_check,
    747         DT_REQUIRE_EQ = is_normal | is_eq | is_require,
    748 
    749         DT_WARN_NE    = is_normal | is_ne | is_warn,
    750         DT_CHECK_NE   = is_normal | is_ne | is_check,
    751         DT_REQUIRE_NE = is_normal | is_ne | is_require,
    752 
    753         DT_WARN_GT    = is_normal | is_gt | is_warn,
    754         DT_CHECK_GT   = is_normal | is_gt | is_check,
    755         DT_REQUIRE_GT = is_normal | is_gt | is_require,
    756 
    757         DT_WARN_LT    = is_normal | is_lt | is_warn,
    758         DT_CHECK_LT   = is_normal | is_lt | is_check,
    759         DT_REQUIRE_LT = is_normal | is_lt | is_require,
    760 
    761         DT_WARN_GE    = is_normal | is_ge | is_warn,
    762         DT_CHECK_GE   = is_normal | is_ge | is_check,
    763         DT_REQUIRE_GE = is_normal | is_ge | is_require,
    764 
    765         DT_WARN_LE    = is_normal | is_le | is_warn,
    766         DT_CHECK_LE   = is_normal | is_le | is_check,
    767         DT_REQUIRE_LE = is_normal | is_le | is_require,
    768 
    769         DT_WARN_UNARY    = is_normal | is_unary | is_warn,
    770         DT_CHECK_UNARY   = is_normal | is_unary | is_check,
    771         DT_REQUIRE_UNARY = is_normal | is_unary | is_require,
    772 
    773         DT_WARN_UNARY_FALSE    = is_normal | is_false | is_unary | is_warn,
    774         DT_CHECK_UNARY_FALSE   = is_normal | is_false | is_unary | is_check,
    775         DT_REQUIRE_UNARY_FALSE = is_normal | is_false | is_unary | is_require,
    776     };
    777 } // namespace assertType
    778 
    779 DOCTEST_INTERFACE const char* assertString(assertType::Enum at);
    780 DOCTEST_INTERFACE const char* failureString(assertType::Enum at);
    781 DOCTEST_INTERFACE const char* skipPathFromFilename(const char* file);
    782 
    783 struct DOCTEST_INTERFACE TestCaseData
    784 {
    785     String      m_file;       // the file in which the test was registered (using String - see #350)
    786     unsigned    m_line;       // the line where the test was registered
    787     const char* m_name;       // name of the test case
    788     const char* m_test_suite; // the test suite in which the test was added
    789     const char* m_description;
    790     bool        m_skip;
    791     bool        m_no_breaks;
    792     bool        m_no_output;
    793     bool        m_may_fail;
    794     bool        m_should_fail;
    795     int         m_expected_failures;
    796     double      m_timeout;
    797 };
    798 
    799 struct DOCTEST_INTERFACE AssertData
    800 {
    801     // common - for all asserts
    802     const TestCaseData* m_test_case;
    803     assertType::Enum    m_at;
    804     const char*         m_file;
    805     int                 m_line;
    806     const char*         m_expr;
    807     bool                m_failed;
    808 
    809     // exception-related - for all asserts
    810     bool   m_threw;
    811     String m_exception;
    812 
    813     // for normal asserts
    814     String m_decomp;
    815 
    816     // for specific exception-related asserts
    817     bool           m_threw_as;
    818     const char*    m_exception_type;
    819 
    820     class DOCTEST_INTERFACE StringContains {
    821         private:
    822             Contains content;
    823             bool isContains;
    824 
    825         public:
    826             StringContains(const String& str) : content(str), isContains(false) { }
    827             StringContains(Contains cntn) : content(static_cast<Contains&&>(cntn)), isContains(true) { }
    828 
    829             bool check(const String& str) { return isContains ? (content == str) : (content.string == str); }
    830 
    831             operator const String&() const { return content.string; }
    832 
    833             const char* c_str() const { return content.string.c_str(); }
    834     } m_exception_string;
    835 
    836     AssertData(assertType::Enum at, const char* file, int line, const char* expr,
    837         const char* exception_type, const StringContains& exception_string);
    838 };
    839 
    840 struct DOCTEST_INTERFACE MessageData
    841 {
    842     String           m_string;
    843     const char*      m_file;
    844     int              m_line;
    845     assertType::Enum m_severity;
    846 };
    847 
    848 struct DOCTEST_INTERFACE SubcaseSignature
    849 {
    850     String      m_name;
    851     const char* m_file;
    852     int         m_line;
    853 
    854     bool operator==(const SubcaseSignature& other) const;
    855     bool operator<(const SubcaseSignature& other) const;
    856 };
    857 
    858 struct DOCTEST_INTERFACE IContextScope
    859 {
    860     DOCTEST_DECLARE_INTERFACE(IContextScope)
    861     virtual void stringify(std::ostream*) const = 0;
    862 };
    863 
    864 namespace detail {
    865     struct DOCTEST_INTERFACE TestCase;
    866 } // namespace detail
    867 
    868 struct ContextOptions //!OCLINT too many fields
    869 {
    870     std::ostream* cout = nullptr; // stdout stream
    871     String        binary_name;    // the test binary name
    872 
    873     const detail::TestCase* currentTest = nullptr;
    874 
    875     // == parameters from the command line
    876     String   out;       // output filename
    877     String   order_by;  // how tests should be ordered
    878     unsigned rand_seed; // the seed for rand ordering
    879 
    880     unsigned first; // the first (matching) test to be executed
    881     unsigned last;  // the last (matching) test to be executed
    882 
    883     int abort_after;           // stop tests after this many failed assertions
    884     int subcase_filter_levels; // apply the subcase filters for the first N levels
    885 
    886     bool success;              // include successful assertions in output
    887     bool case_sensitive;       // if filtering should be case sensitive
    888     bool exit;                 // if the program should be exited after the tests are ran/whatever
    889     bool duration;             // print the time duration of each test case
    890     bool minimal;              // minimal console output (only test failures)
    891     bool quiet;                // no console output
    892     bool no_throw;             // to skip exceptions-related assertion macros
    893     bool no_exitcode;          // if the framework should return 0 as the exitcode
    894     bool no_run;               // to not run the tests at all (can be done with an "*" exclude)
    895     bool no_intro;             // to not print the intro of the framework
    896     bool no_version;           // to not print the version of the framework
    897     bool no_colors;            // if output to the console should be colorized
    898     bool force_colors;         // forces the use of colors even when a tty cannot be detected
    899     bool no_breaks;            // to not break into the debugger
    900     bool no_skip;              // don't skip test cases which are marked to be skipped
    901     bool gnu_file_line;        // if line numbers should be surrounded with :x: and not (x):
    902     bool no_path_in_filenames; // if the path to files should be removed from the output
    903     bool no_line_numbers;      // if source code line numbers should be omitted from the output
    904     bool no_debug_output;      // no output in the debug console when a debugger is attached
    905     bool no_skipped_summary;   // don't print "skipped" in the summary !!! UNDOCUMENTED !!!
    906     bool no_time_in_output;    // omit any time/timestamps from output !!! UNDOCUMENTED !!!
    907 
    908     bool help;             // to print the help
    909     bool version;          // to print the version
    910     bool count;            // if only the count of matching tests is to be retrieved
    911     bool list_test_cases;  // to list all tests matching the filters
    912     bool list_test_suites; // to list all suites matching the filters
    913     bool list_reporters;   // lists all registered reporters
    914 };
    915 
    916 namespace detail {
    917     namespace types {
    918 #ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
    919         using namespace std;
    920 #else
    921         template <bool COND, typename T = void>
    922         struct enable_if { };
    923 
    924         template <typename T>
    925         struct enable_if<true, T> { using type = T; };
    926 
    927         struct true_type { static DOCTEST_CONSTEXPR bool value = true; };
    928         struct false_type { static DOCTEST_CONSTEXPR bool value = false; };
    929 
    930         template <typename T> struct remove_reference { using type = T; };
    931         template <typename T> struct remove_reference<T&> { using type = T; };
    932         template <typename T> struct remove_reference<T&&> { using type = T; };
    933 
    934         template <typename T> struct is_rvalue_reference : false_type { };
    935         template <typename T> struct is_rvalue_reference<T&&> : true_type { };
    936 
    937         template<typename T> struct remove_const { using type = T; };
    938         template <typename T> struct remove_const<const T> { using type = T; };
    939 
    940         // Compiler intrinsics
    941         template <typename T> struct is_enum { static DOCTEST_CONSTEXPR bool value = __is_enum(T); };
    942         template <typename T> struct underlying_type { using type = __underlying_type(T); };
    943 
    944         template <typename T> struct is_pointer : false_type { };
    945         template <typename T> struct is_pointer<T*> : true_type { };
    946 
    947         template <typename T> struct is_array : false_type { };
    948         // NOLINTNEXTLINE(*-avoid-c-arrays)
    949         template <typename T, size_t SIZE> struct is_array<T[SIZE]> : true_type { };
    950 #endif
    951     }
    952 
    953     // <utility>
    954     template <typename T>
    955     T&& declval();
    956 
    957     template <class T>
    958     DOCTEST_CONSTEXPR_FUNC T&& forward(typename types::remove_reference<T>::type& t) DOCTEST_NOEXCEPT {
    959         return static_cast<T&&>(t);
    960     }
    961 
    962     template <class T>
    963     DOCTEST_CONSTEXPR_FUNC T&& forward(typename types::remove_reference<T>::type&& t) DOCTEST_NOEXCEPT {
    964         return static_cast<T&&>(t);
    965     }
    966 
    967     template <typename T>
    968     struct deferred_false : types::false_type { };
    969 
    970 // MSVS 2015 :(
    971 #if !DOCTEST_CLANG && (defined(_MSC_VER) && _MSC_VER <= 1900)
    972     template <typename T, typename = void>
    973     struct has_global_insertion_operator : types::false_type { };
    974 
    975     template <typename T>
    976     struct has_global_insertion_operator<T, decltype(::operator<<(declval<std::ostream&>(), declval<const T&>()), void())> : types::true_type { };
    977 
    978     template <typename T, typename = void>
    979     struct has_insertion_operator { static DOCTEST_CONSTEXPR bool value = has_global_insertion_operator<T>::value; };
    980 
    981     template <typename T, bool global>
    982     struct insert_hack;
    983 
    984     template <typename T>
    985     struct insert_hack<T, true> {
    986         static void insert(std::ostream& os, const T& t) { ::operator<<(os, t); }
    987     };
    988 
    989     template <typename T>
    990     struct insert_hack<T, false> {
    991         static void insert(std::ostream& os, const T& t) { operator<<(os, t); }
    992     };
    993 
    994     template <typename T>
    995     using insert_hack_t = insert_hack<T, has_global_insertion_operator<T>::value>;
    996 #else
    997     template <typename T, typename = void>
    998     struct has_insertion_operator : types::false_type { };
    999 #endif
   1000 
   1001 template <typename T>
   1002 struct has_insertion_operator<T, decltype(operator<<(declval<std::ostream&>(), declval<const T&>()), void())> : types::true_type { };
   1003 
   1004     DOCTEST_INTERFACE std::ostream* tlssPush();
   1005     DOCTEST_INTERFACE String tlssPop();
   1006 
   1007     template <bool C>
   1008     struct StringMakerBase {
   1009         template <typename T>
   1010         static String convert(const DOCTEST_REF_WRAP(T)) {
   1011 #ifdef DOCTEST_CONFIG_REQUIRE_STRINGIFICATION_FOR_ALL_USED_TYPES
   1012             static_assert(deferred_false<T>::value, "No stringification detected for type T. See string conversion manual");
   1013 #endif
   1014             return "{?}";
   1015         }
   1016     };
   1017 
   1018     template <typename T>
   1019     struct filldata;
   1020 
   1021     template <typename T>
   1022     void filloss(std::ostream* stream, const T& in) {
   1023         filldata<T>::fill(stream, in);
   1024     }
   1025 
   1026     template <typename T, size_t N>
   1027     void filloss(std::ostream* stream, const T (&in)[N]) { // NOLINT(*-avoid-c-arrays)
   1028         // T[N], T(&)[N], T(&&)[N] have same behaviour.
   1029         // Hence remove reference.
   1030         filloss<typename types::remove_reference<decltype(in)>::type>(stream, in);
   1031     }
   1032 
   1033     template <typename T>
   1034     String toStream(const T& in) {
   1035         std::ostream* stream = tlssPush();
   1036         filloss(stream, in);
   1037         return tlssPop();
   1038     }
   1039 
   1040     template <>
   1041     struct StringMakerBase<true> {
   1042         template <typename T>
   1043         static String convert(const DOCTEST_REF_WRAP(T) in) {
   1044             return toStream(in);
   1045         }
   1046     };
   1047 } // namespace detail
   1048 
   1049 template <typename T>
   1050 struct StringMaker : public detail::StringMakerBase<
   1051     detail::has_insertion_operator<T>::value || detail::types::is_pointer<T>::value || detail::types::is_array<T>::value>
   1052 {};
   1053 
   1054 #ifndef DOCTEST_STRINGIFY
   1055 #ifdef DOCTEST_CONFIG_DOUBLE_STRINGIFY
   1056 #define DOCTEST_STRINGIFY(...) toString(toString(__VA_ARGS__))
   1057 #else
   1058 #define DOCTEST_STRINGIFY(...) toString(__VA_ARGS__)
   1059 #endif
   1060 #endif
   1061 
   1062 template <typename T>
   1063 String toString() {
   1064 #if DOCTEST_MSVC >= 0 && DOCTEST_CLANG == 0 && DOCTEST_GCC == 0
   1065     String ret = __FUNCSIG__; // class doctest::String __cdecl doctest::toString<TYPE>(void)
   1066     String::size_type beginPos = ret.find('<');
   1067     return ret.substr(beginPos + 1, ret.size() - beginPos - static_cast<String::size_type>(sizeof(">(void)")));
   1068 #else
   1069     String ret = __PRETTY_FUNCTION__; // doctest::String toString() [with T = TYPE]
   1070     String::size_type begin = ret.find('=') + 2;
   1071     return ret.substr(begin, ret.size() - begin - 1);
   1072 #endif
   1073 }
   1074 
   1075 template <typename T, typename detail::types::enable_if<!detail::types::is_enum<T>::value, bool>::type = true>
   1076 String toString(const DOCTEST_REF_WRAP(T) value) {
   1077     return StringMaker<T>::convert(value);
   1078 }
   1079 
   1080 #ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
   1081 DOCTEST_INTERFACE String toString(const char* in);
   1082 #endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
   1083 
   1084 #if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0)
   1085 // see this issue on why this is needed: https://github.com/doctest/doctest/issues/183
   1086 DOCTEST_INTERFACE String toString(const std::string& in);
   1087 #endif // VS 2019
   1088 
   1089 DOCTEST_INTERFACE String toString(String in);
   1090 
   1091 DOCTEST_INTERFACE String toString(std::nullptr_t);
   1092 
   1093 DOCTEST_INTERFACE String toString(bool in);
   1094 
   1095 DOCTEST_INTERFACE String toString(float in);
   1096 DOCTEST_INTERFACE String toString(double in);
   1097 DOCTEST_INTERFACE String toString(double long in);
   1098 
   1099 DOCTEST_INTERFACE String toString(char in);
   1100 DOCTEST_INTERFACE String toString(char signed in);
   1101 DOCTEST_INTERFACE String toString(char unsigned in);
   1102 DOCTEST_INTERFACE String toString(short in);
   1103 DOCTEST_INTERFACE String toString(short unsigned in);
   1104 DOCTEST_INTERFACE String toString(signed in);
   1105 DOCTEST_INTERFACE String toString(unsigned in);
   1106 DOCTEST_INTERFACE String toString(long in);
   1107 DOCTEST_INTERFACE String toString(long unsigned in);
   1108 DOCTEST_INTERFACE String toString(long long in);
   1109 DOCTEST_INTERFACE String toString(long long unsigned in);
   1110 
   1111 template <typename T, typename detail::types::enable_if<detail::types::is_enum<T>::value, bool>::type = true>
   1112 String toString(const DOCTEST_REF_WRAP(T) value) {
   1113     using UT = typename detail::types::underlying_type<T>::type;
   1114     return (DOCTEST_STRINGIFY(static_cast<UT>(value)));
   1115 }
   1116 
   1117 namespace detail {
   1118     template <typename T>
   1119     struct filldata
   1120     {
   1121         static void fill(std::ostream* stream, const T& in) {
   1122 #if !DOCTEST_CLANG && (defined(_MSC_VER) && _MSC_VER <= 1900)
   1123         insert_hack_t<T>::insert(*stream, in);
   1124 #else
   1125         operator<<(*stream, in);
   1126 #endif
   1127         }
   1128     };
   1129 
   1130 DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4866)
   1131 // NOLINTBEGIN(*-avoid-c-arrays)
   1132     template <typename T, size_t N>
   1133     struct filldata<T[N]> {
   1134         static void fill(std::ostream* stream, const T(&in)[N]) {
   1135             *stream << "[";
   1136             for (size_t i = 0; i < N; i++) {
   1137                 if (i != 0) { *stream << ", "; }
   1138                 *stream << (DOCTEST_STRINGIFY(in[i]));
   1139             }
   1140             *stream << "]";
   1141         }
   1142     };
   1143 // NOLINTEND(*-avoid-c-arrays)
   1144 DOCTEST_MSVC_SUPPRESS_WARNING_POP
   1145 
   1146     // Specialized since we don't want the terminating null byte!
   1147 // NOLINTBEGIN(*-avoid-c-arrays)
   1148     template <size_t N>
   1149     struct filldata<const char[N]> {
   1150         static void fill(std::ostream* stream, const char (&in)[N]) {
   1151             *stream << String(in, in[N - 1] ? N : N - 1);
   1152         } // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
   1153     };
   1154 // NOLINTEND(*-avoid-c-arrays)
   1155 
   1156     template <>
   1157     struct filldata<const void*> {
   1158         static void fill(std::ostream* stream, const void* in);
   1159     };
   1160 
   1161     template <typename T>
   1162     struct filldata<T*> {
   1163         static void fill(std::ostream* stream, const T* in) {
   1164             filldata<const void*>::fill(stream, in);
   1165         }
   1166     };
   1167 }
   1168 
   1169 struct DOCTEST_INTERFACE Approx
   1170 {
   1171     Approx(double value);
   1172 
   1173     Approx operator()(double value) const;
   1174 
   1175 #ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
   1176     template <typename T>
   1177     explicit Approx(const T& value,
   1178                     typename detail::types::enable_if<std::is_constructible<double, T>::value>::type* =
   1179                             static_cast<T*>(nullptr)) {
   1180         *this = static_cast<double>(value);
   1181     }
   1182 #endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
   1183 
   1184     Approx& epsilon(double newEpsilon);
   1185 
   1186 #ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
   1187     template <typename T>
   1188     typename std::enable_if<std::is_constructible<double, T>::value, Approx&>::type epsilon(
   1189             const T& newEpsilon) {
   1190         m_epsilon = static_cast<double>(newEpsilon);
   1191         return *this;
   1192     }
   1193 #endif //  DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
   1194 
   1195     Approx& scale(double newScale);
   1196 
   1197 #ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
   1198     template <typename T>
   1199     typename std::enable_if<std::is_constructible<double, T>::value, Approx&>::type scale(
   1200             const T& newScale) {
   1201         m_scale = static_cast<double>(newScale);
   1202         return *this;
   1203     }
   1204 #endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
   1205 
   1206     // clang-format off
   1207     DOCTEST_INTERFACE friend bool operator==(double lhs, const Approx & rhs);
   1208     DOCTEST_INTERFACE friend bool operator==(const Approx & lhs, double rhs);
   1209     DOCTEST_INTERFACE friend bool operator!=(double lhs, const Approx & rhs);
   1210     DOCTEST_INTERFACE friend bool operator!=(const Approx & lhs, double rhs);
   1211     DOCTEST_INTERFACE friend bool operator<=(double lhs, const Approx & rhs);
   1212     DOCTEST_INTERFACE friend bool operator<=(const Approx & lhs, double rhs);
   1213     DOCTEST_INTERFACE friend bool operator>=(double lhs, const Approx & rhs);
   1214     DOCTEST_INTERFACE friend bool operator>=(const Approx & lhs, double rhs);
   1215     DOCTEST_INTERFACE friend bool operator< (double lhs, const Approx & rhs);
   1216     DOCTEST_INTERFACE friend bool operator< (const Approx & lhs, double rhs);
   1217     DOCTEST_INTERFACE friend bool operator> (double lhs, const Approx & rhs);
   1218     DOCTEST_INTERFACE friend bool operator> (const Approx & lhs, double rhs);
   1219 
   1220 #ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
   1221 #define DOCTEST_APPROX_PREFIX \
   1222     template <typename T> friend typename std::enable_if<std::is_constructible<double, T>::value, bool>::type
   1223 
   1224     DOCTEST_APPROX_PREFIX operator==(const T& lhs, const Approx& rhs) { return operator==(static_cast<double>(lhs), rhs); }
   1225     DOCTEST_APPROX_PREFIX operator==(const Approx& lhs, const T& rhs) { return operator==(rhs, lhs); }
   1226     DOCTEST_APPROX_PREFIX operator!=(const T& lhs, const Approx& rhs) { return !operator==(lhs, rhs); }
   1227     DOCTEST_APPROX_PREFIX operator!=(const Approx& lhs, const T& rhs) { return !operator==(rhs, lhs); }
   1228     DOCTEST_APPROX_PREFIX operator<=(const T& lhs, const Approx& rhs) { return static_cast<double>(lhs) < rhs.m_value || lhs == rhs; }
   1229     DOCTEST_APPROX_PREFIX operator<=(const Approx& lhs, const T& rhs) { return lhs.m_value < static_cast<double>(rhs) || lhs == rhs; }
   1230     DOCTEST_APPROX_PREFIX operator>=(const T& lhs, const Approx& rhs) { return static_cast<double>(lhs) > rhs.m_value || lhs == rhs; }
   1231     DOCTEST_APPROX_PREFIX operator>=(const Approx& lhs, const T& rhs) { return lhs.m_value > static_cast<double>(rhs) || lhs == rhs; }
   1232     DOCTEST_APPROX_PREFIX operator< (const T& lhs, const Approx& rhs) { return static_cast<double>(lhs) < rhs.m_value && lhs != rhs; }
   1233     DOCTEST_APPROX_PREFIX operator< (const Approx& lhs, const T& rhs) { return lhs.m_value < static_cast<double>(rhs) && lhs != rhs; }
   1234     DOCTEST_APPROX_PREFIX operator> (const T& lhs, const Approx& rhs) { return static_cast<double>(lhs) > rhs.m_value && lhs != rhs; }
   1235     DOCTEST_APPROX_PREFIX operator> (const Approx& lhs, const T& rhs) { return lhs.m_value > static_cast<double>(rhs) && lhs != rhs; }
   1236 #undef DOCTEST_APPROX_PREFIX
   1237 #endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
   1238 
   1239     // clang-format on
   1240 
   1241     double m_epsilon;
   1242     double m_scale;
   1243     double m_value;
   1244 };
   1245 
   1246 DOCTEST_INTERFACE String toString(const Approx& in);
   1247 
   1248 DOCTEST_INTERFACE const ContextOptions* getContextOptions();
   1249 
   1250 template <typename F>
   1251 struct DOCTEST_INTERFACE_DECL IsNaN
   1252 {
   1253     F value; bool flipped;
   1254     IsNaN(F f, bool flip = false) : value(f), flipped(flip) { }
   1255     IsNaN<F> operator!() const { return { value, !flipped }; }
   1256     operator bool() const;
   1257 };
   1258 #ifndef __MINGW32__
   1259 extern template struct DOCTEST_INTERFACE_DECL IsNaN<float>;
   1260 extern template struct DOCTEST_INTERFACE_DECL IsNaN<double>;
   1261 extern template struct DOCTEST_INTERFACE_DECL IsNaN<long double>;
   1262 #endif
   1263 DOCTEST_INTERFACE String toString(IsNaN<float> in);
   1264 DOCTEST_INTERFACE String toString(IsNaN<double> in);
   1265 DOCTEST_INTERFACE String toString(IsNaN<double long> in);
   1266 
   1267 #ifndef DOCTEST_CONFIG_DISABLE
   1268 
   1269 namespace detail {
   1270     // clang-format off
   1271 #ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
   1272     template<class T>               struct decay_array       { using type = T; };
   1273     template<class T, unsigned N>   struct decay_array<T[N]> { using type = T*; };
   1274     template<class T>               struct decay_array<T[]>  { using type = T*; };
   1275 
   1276     template<class T>   struct not_char_pointer              { static DOCTEST_CONSTEXPR value = 1; };
   1277     template<>          struct not_char_pointer<char*>       { static DOCTEST_CONSTEXPR value = 0; };
   1278     template<>          struct not_char_pointer<const char*> { static DOCTEST_CONSTEXPR value = 0; };
   1279 
   1280     template<class T> struct can_use_op : public not_char_pointer<typename decay_array<T>::type> {};
   1281 #endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
   1282     // clang-format on
   1283 
   1284     struct DOCTEST_INTERFACE TestFailureException
   1285     {
   1286     };
   1287 
   1288     DOCTEST_INTERFACE bool checkIfShouldThrow(assertType::Enum at);
   1289 
   1290 #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
   1291     DOCTEST_NORETURN
   1292 #endif // DOCTEST_CONFIG_NO_EXCEPTIONS
   1293     DOCTEST_INTERFACE void throwException();
   1294 
   1295     struct DOCTEST_INTERFACE Subcase
   1296     {
   1297         SubcaseSignature m_signature;
   1298         bool             m_entered = false;
   1299 
   1300         Subcase(const String& name, const char* file, int line);
   1301         Subcase(const Subcase&) = delete;
   1302         Subcase(Subcase&&) = delete;
   1303         Subcase& operator=(const Subcase&) = delete;
   1304         Subcase& operator=(Subcase&&) = delete;
   1305         ~Subcase();
   1306 
   1307         operator bool() const;
   1308 
   1309         private:
   1310             bool checkFilters();
   1311     };
   1312 
   1313     template <typename L, typename R>
   1314     String stringifyBinaryExpr(const DOCTEST_REF_WRAP(L) lhs, const char* op,
   1315                                const DOCTEST_REF_WRAP(R) rhs) {
   1316         return (DOCTEST_STRINGIFY(lhs)) + op + (DOCTEST_STRINGIFY(rhs));
   1317     }
   1318 
   1319 #if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0)
   1320 DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-comparison")
   1321 #endif
   1322 
   1323 // This will check if there is any way it could find a operator like member or friend and uses it.
   1324 // If not it doesn't find the operator or if the operator at global scope is defined after
   1325 // this template, the template won't be instantiated due to SFINAE. Once the template is not
   1326 // instantiated it can look for global operator using normal conversions.
   1327 #define SFINAE_OP(ret,op) decltype((void)(doctest::detail::declval<L>() op doctest::detail::declval<R>()),ret{})
   1328 
   1329 #define DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(op, op_str, op_macro)                              \
   1330     template <typename R>                                                                          \
   1331     DOCTEST_NOINLINE SFINAE_OP(Result,op) operator op(R&& rhs) {                                   \
   1332     bool res = op_macro(doctest::detail::forward<const L>(lhs), doctest::detail::forward<R>(rhs)); \
   1333         if(m_at & assertType::is_false)                                                            \
   1334             res = !res;                                                                            \
   1335         if(!res || doctest::getContextOptions()->success)                                          \
   1336             return Result(res, stringifyBinaryExpr(lhs, op_str, rhs));                             \
   1337         return Result(res);                                                                        \
   1338     }
   1339 
   1340     // more checks could be added - like in Catch:
   1341     // https://github.com/catchorg/Catch2/pull/1480/files
   1342     // https://github.com/catchorg/Catch2/pull/1481/files
   1343 #define DOCTEST_FORBIT_EXPRESSION(rt, op)                                                          \
   1344     template <typename R>                                                                          \
   1345     rt& operator op(const R&) {                                                                    \
   1346         static_assert(deferred_false<R>::value,                                                    \
   1347                       "Expression Too Complex Please Rewrite As Binary Comparison!");              \
   1348         return *this;                                                                              \
   1349     }
   1350 
   1351     struct DOCTEST_INTERFACE Result // NOLINT(*-member-init)
   1352     {
   1353         bool   m_passed;
   1354         String m_decomp;
   1355 
   1356         Result() = default; // TODO: Why do we need this? (To remove NOLINT)
   1357         Result(bool passed, const String& decomposition = String());
   1358 
   1359         // forbidding some expressions based on this table: https://en.cppreference.com/w/cpp/language/operator_precedence
   1360         DOCTEST_FORBIT_EXPRESSION(Result, &)
   1361         DOCTEST_FORBIT_EXPRESSION(Result, ^)
   1362         DOCTEST_FORBIT_EXPRESSION(Result, |)
   1363         DOCTEST_FORBIT_EXPRESSION(Result, &&)
   1364         DOCTEST_FORBIT_EXPRESSION(Result, ||)
   1365         DOCTEST_FORBIT_EXPRESSION(Result, ==)
   1366         DOCTEST_FORBIT_EXPRESSION(Result, !=)
   1367         DOCTEST_FORBIT_EXPRESSION(Result, <)
   1368         DOCTEST_FORBIT_EXPRESSION(Result, >)
   1369         DOCTEST_FORBIT_EXPRESSION(Result, <=)
   1370         DOCTEST_FORBIT_EXPRESSION(Result, >=)
   1371         DOCTEST_FORBIT_EXPRESSION(Result, =)
   1372         DOCTEST_FORBIT_EXPRESSION(Result, +=)
   1373         DOCTEST_FORBIT_EXPRESSION(Result, -=)
   1374         DOCTEST_FORBIT_EXPRESSION(Result, *=)
   1375         DOCTEST_FORBIT_EXPRESSION(Result, /=)
   1376         DOCTEST_FORBIT_EXPRESSION(Result, %=)
   1377         DOCTEST_FORBIT_EXPRESSION(Result, <<=)
   1378         DOCTEST_FORBIT_EXPRESSION(Result, >>=)
   1379         DOCTEST_FORBIT_EXPRESSION(Result, &=)
   1380         DOCTEST_FORBIT_EXPRESSION(Result, ^=)
   1381         DOCTEST_FORBIT_EXPRESSION(Result, |=)
   1382     };
   1383 
   1384 #ifndef DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION
   1385 
   1386     DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
   1387     DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-conversion")
   1388     DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-compare")
   1389     //DOCTEST_CLANG_SUPPRESS_WARNING("-Wdouble-promotion")
   1390     //DOCTEST_CLANG_SUPPRESS_WARNING("-Wconversion")
   1391     //DOCTEST_CLANG_SUPPRESS_WARNING("-Wfloat-equal")
   1392 
   1393     DOCTEST_GCC_SUPPRESS_WARNING_PUSH
   1394     DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-conversion")
   1395     DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-compare")
   1396     //DOCTEST_GCC_SUPPRESS_WARNING("-Wdouble-promotion")
   1397     //DOCTEST_GCC_SUPPRESS_WARNING("-Wconversion")
   1398     //DOCTEST_GCC_SUPPRESS_WARNING("-Wfloat-equal")
   1399 
   1400     DOCTEST_MSVC_SUPPRESS_WARNING_PUSH
   1401     // https://stackoverflow.com/questions/39479163 what's the difference between 4018 and 4389
   1402     DOCTEST_MSVC_SUPPRESS_WARNING(4388) // signed/unsigned mismatch
   1403     DOCTEST_MSVC_SUPPRESS_WARNING(4389) // 'operator' : signed/unsigned mismatch
   1404     DOCTEST_MSVC_SUPPRESS_WARNING(4018) // 'expression' : signed/unsigned mismatch
   1405     //DOCTEST_MSVC_SUPPRESS_WARNING(4805) // 'operation' : unsafe mix of type 'type' and type 'type' in operation
   1406 
   1407 #endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION
   1408 
   1409     // clang-format off
   1410 #ifndef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
   1411 #define DOCTEST_COMPARISON_RETURN_TYPE bool
   1412 #else // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
   1413 #define DOCTEST_COMPARISON_RETURN_TYPE typename types::enable_if<can_use_op<L>::value || can_use_op<R>::value, bool>::type
   1414     inline bool eq(const char* lhs, const char* rhs) { return String(lhs) == String(rhs); }
   1415     inline bool ne(const char* lhs, const char* rhs) { return String(lhs) != String(rhs); }
   1416     inline bool lt(const char* lhs, const char* rhs) { return String(lhs) <  String(rhs); }
   1417     inline bool gt(const char* lhs, const char* rhs) { return String(lhs) >  String(rhs); }
   1418     inline bool le(const char* lhs, const char* rhs) { return String(lhs) <= String(rhs); }
   1419     inline bool ge(const char* lhs, const char* rhs) { return String(lhs) >= String(rhs); }
   1420 #endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
   1421     // clang-format on
   1422 
   1423 #define DOCTEST_RELATIONAL_OP(name, op)                                                            \
   1424     template <typename L, typename R>                                                              \
   1425     DOCTEST_COMPARISON_RETURN_TYPE name(const DOCTEST_REF_WRAP(L) lhs,                             \
   1426                                         const DOCTEST_REF_WRAP(R) rhs) {                           \
   1427         return lhs op rhs;                                                                         \
   1428     }
   1429 
   1430     DOCTEST_RELATIONAL_OP(eq, ==)
   1431     DOCTEST_RELATIONAL_OP(ne, !=)
   1432     DOCTEST_RELATIONAL_OP(lt, <)
   1433     DOCTEST_RELATIONAL_OP(gt, >)
   1434     DOCTEST_RELATIONAL_OP(le, <=)
   1435     DOCTEST_RELATIONAL_OP(ge, >=)
   1436 
   1437 #ifndef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
   1438 #define DOCTEST_CMP_EQ(l, r) l == r
   1439 #define DOCTEST_CMP_NE(l, r) l != r
   1440 #define DOCTEST_CMP_GT(l, r) l > r
   1441 #define DOCTEST_CMP_LT(l, r) l < r
   1442 #define DOCTEST_CMP_GE(l, r) l >= r
   1443 #define DOCTEST_CMP_LE(l, r) l <= r
   1444 #else // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
   1445 #define DOCTEST_CMP_EQ(l, r) eq(l, r)
   1446 #define DOCTEST_CMP_NE(l, r) ne(l, r)
   1447 #define DOCTEST_CMP_GT(l, r) gt(l, r)
   1448 #define DOCTEST_CMP_LT(l, r) lt(l, r)
   1449 #define DOCTEST_CMP_GE(l, r) ge(l, r)
   1450 #define DOCTEST_CMP_LE(l, r) le(l, r)
   1451 #endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
   1452 
   1453     template <typename L>
   1454     // cppcheck-suppress copyCtorAndEqOperator
   1455     struct Expression_lhs
   1456     {
   1457         L                lhs;
   1458         assertType::Enum m_at;
   1459 
   1460         explicit Expression_lhs(L&& in, assertType::Enum at)
   1461                 : lhs(static_cast<L&&>(in))
   1462                 , m_at(at) {}
   1463 
   1464         DOCTEST_NOINLINE operator Result() {
   1465 // this is needed only for MSVC 2015
   1466 DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4800) // 'int': forcing value to bool
   1467             bool res = static_cast<bool>(lhs);
   1468 DOCTEST_MSVC_SUPPRESS_WARNING_POP
   1469             if(m_at & assertType::is_false) { //!OCLINT bitwise operator in conditional
   1470                 res = !res;
   1471             }
   1472 
   1473             if(!res || getContextOptions()->success) {
   1474                 return { res, (DOCTEST_STRINGIFY(lhs)) };
   1475             }
   1476             return { res };
   1477         }
   1478 
   1479         /* This is required for user-defined conversions from Expression_lhs to L */
   1480         operator L() const { return lhs; }
   1481 
   1482         // clang-format off
   1483         DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
   1484         DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
   1485         DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>,  " >  ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional
   1486         DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<,  " <  ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional
   1487         DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional
   1488         DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
   1489         // clang-format on
   1490 
   1491         // forbidding some expressions based on this table: https://en.cppreference.com/w/cpp/language/operator_precedence
   1492         DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &)
   1493         DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ^)
   1494         DOCTEST_FORBIT_EXPRESSION(Expression_lhs, |)
   1495         DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &&)
   1496         DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ||)
   1497         DOCTEST_FORBIT_EXPRESSION(Expression_lhs, =)
   1498         DOCTEST_FORBIT_EXPRESSION(Expression_lhs, +=)
   1499         DOCTEST_FORBIT_EXPRESSION(Expression_lhs, -=)
   1500         DOCTEST_FORBIT_EXPRESSION(Expression_lhs, *=)
   1501         DOCTEST_FORBIT_EXPRESSION(Expression_lhs, /=)
   1502         DOCTEST_FORBIT_EXPRESSION(Expression_lhs, %=)
   1503         DOCTEST_FORBIT_EXPRESSION(Expression_lhs, <<=)
   1504         DOCTEST_FORBIT_EXPRESSION(Expression_lhs, >>=)
   1505         DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &=)
   1506         DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ^=)
   1507         DOCTEST_FORBIT_EXPRESSION(Expression_lhs, |=)
   1508         // these 2 are unfortunate because they should be allowed - they have higher precedence over the comparisons, but the
   1509         // ExpressionDecomposer class uses the left shift operator to capture the left operand of the binary expression...
   1510         DOCTEST_FORBIT_EXPRESSION(Expression_lhs, <<)
   1511         DOCTEST_FORBIT_EXPRESSION(Expression_lhs, >>)
   1512     };
   1513 
   1514 #ifndef DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION
   1515 
   1516     DOCTEST_CLANG_SUPPRESS_WARNING_POP
   1517     DOCTEST_MSVC_SUPPRESS_WARNING_POP
   1518     DOCTEST_GCC_SUPPRESS_WARNING_POP
   1519 
   1520 #endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION
   1521 
   1522 #if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0)
   1523 DOCTEST_CLANG_SUPPRESS_WARNING_POP
   1524 #endif
   1525 
   1526     struct DOCTEST_INTERFACE ExpressionDecomposer
   1527     {
   1528         assertType::Enum m_at;
   1529 
   1530         ExpressionDecomposer(assertType::Enum at);
   1531 
   1532         // The right operator for capturing expressions is "<=" instead of "<<" (based on the operator precedence table)
   1533         // but then there will be warnings from GCC about "-Wparentheses" and since "_Pragma()" is problematic this will stay for now...
   1534         // https://github.com/catchorg/Catch2/issues/870
   1535         // https://github.com/catchorg/Catch2/issues/565
   1536         template <typename L>
   1537         Expression_lhs<L> operator<<(L&& operand) {
   1538             return Expression_lhs<L>(static_cast<L&&>(operand), m_at);
   1539         }
   1540 
   1541         template <typename L,typename types::enable_if<!doctest::detail::types::is_rvalue_reference<L>::value,void >::type* = nullptr>
   1542         Expression_lhs<const L&> operator<<(const L &operand) {
   1543             return Expression_lhs<const L&>(operand, m_at);
   1544         }
   1545     };
   1546 
   1547     struct DOCTEST_INTERFACE TestSuite
   1548     {
   1549         const char* m_test_suite = nullptr;
   1550         const char* m_description = nullptr;
   1551         bool        m_skip = false;
   1552         bool        m_no_breaks = false;
   1553         bool        m_no_output = false;
   1554         bool        m_may_fail = false;
   1555         bool        m_should_fail = false;
   1556         int         m_expected_failures = 0;
   1557         double      m_timeout = 0;
   1558 
   1559         TestSuite& operator*(const char* in);
   1560 
   1561         template <typename T>
   1562         TestSuite& operator*(const T& in) {
   1563             in.fill(*this);
   1564             return *this;
   1565         }
   1566     };
   1567 
   1568     using funcType = void (*)();
   1569 
   1570     struct DOCTEST_INTERFACE TestCase : public TestCaseData
   1571     {
   1572         funcType m_test; // a function pointer to the test case
   1573 
   1574         String m_type; // for templated test cases - gets appended to the real name
   1575         int m_template_id; // an ID used to distinguish between the different versions of a templated test case
   1576         String m_full_name; // contains the name (only for templated test cases!) + the template type
   1577 
   1578         TestCase(funcType test, const char* file, unsigned line, const TestSuite& test_suite,
   1579                  const String& type = String(), int template_id = -1);
   1580 
   1581         TestCase(const TestCase& other);
   1582         TestCase(TestCase&&) = delete;
   1583 
   1584         DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(26434) // hides a non-virtual function
   1585         TestCase& operator=(const TestCase& other);
   1586         DOCTEST_MSVC_SUPPRESS_WARNING_POP
   1587 
   1588         TestCase& operator=(TestCase&&) = delete;
   1589 
   1590         TestCase& operator*(const char* in);
   1591 
   1592         template <typename T>
   1593         TestCase& operator*(const T& in) {
   1594             in.fill(*this);
   1595             return *this;
   1596         }
   1597 
   1598         bool operator<(const TestCase& other) const;
   1599 
   1600         ~TestCase() = default;
   1601     };
   1602 
   1603     // forward declarations of functions used by the macros
   1604     DOCTEST_INTERFACE int  regTest(const TestCase& tc);
   1605     DOCTEST_INTERFACE int  setTestSuite(const TestSuite& ts);
   1606     DOCTEST_INTERFACE bool isDebuggerActive();
   1607 
   1608     template<typename T>
   1609     int instantiationHelper(const T&) { return 0; }
   1610 
   1611     namespace binaryAssertComparison {
   1612         enum Enum
   1613         {
   1614             eq = 0,
   1615             ne,
   1616             gt,
   1617             lt,
   1618             ge,
   1619             le
   1620         };
   1621     } // namespace binaryAssertComparison
   1622 
   1623     // clang-format off
   1624     template <int, class L, class R> struct RelationalComparator     { bool operator()(const DOCTEST_REF_WRAP(L),     const DOCTEST_REF_WRAP(R)    ) const { return false;        } };
   1625 
   1626 #define DOCTEST_BINARY_RELATIONAL_OP(n, op) \
   1627     template <class L, class R> struct RelationalComparator<n, L, R> { bool operator()(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) const { return op(lhs, rhs); } };
   1628     // clang-format on
   1629 
   1630     DOCTEST_BINARY_RELATIONAL_OP(0, doctest::detail::eq)
   1631     DOCTEST_BINARY_RELATIONAL_OP(1, doctest::detail::ne)
   1632     DOCTEST_BINARY_RELATIONAL_OP(2, doctest::detail::gt)
   1633     DOCTEST_BINARY_RELATIONAL_OP(3, doctest::detail::lt)
   1634     DOCTEST_BINARY_RELATIONAL_OP(4, doctest::detail::ge)
   1635     DOCTEST_BINARY_RELATIONAL_OP(5, doctest::detail::le)
   1636 
   1637     struct DOCTEST_INTERFACE ResultBuilder : public AssertData
   1638     {
   1639         ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr,
   1640                       const char* exception_type = "", const String& exception_string = "");
   1641 
   1642         ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr,
   1643                       const char* exception_type, const Contains& exception_string);
   1644 
   1645         void setResult(const Result& res);
   1646 
   1647         template <int comparison, typename L, typename R>
   1648         DOCTEST_NOINLINE bool binary_assert(const DOCTEST_REF_WRAP(L) lhs,
   1649                                             const DOCTEST_REF_WRAP(R) rhs) {
   1650             m_failed = !RelationalComparator<comparison, L, R>()(lhs, rhs);
   1651             if (m_failed || getContextOptions()->success) {
   1652                 m_decomp = stringifyBinaryExpr(lhs, ", ", rhs);
   1653             }
   1654             return !m_failed;
   1655         }
   1656 
   1657         template <typename L>
   1658         DOCTEST_NOINLINE bool unary_assert(const DOCTEST_REF_WRAP(L) val) {
   1659             m_failed = !val;
   1660 
   1661             if (m_at & assertType::is_false) { //!OCLINT bitwise operator in conditional
   1662                 m_failed = !m_failed;
   1663             }
   1664 
   1665             if (m_failed || getContextOptions()->success) {
   1666                 m_decomp = (DOCTEST_STRINGIFY(val));
   1667             }
   1668 
   1669             return !m_failed;
   1670         }
   1671 
   1672         void translateException();
   1673 
   1674         bool log();
   1675         void react() const;
   1676     };
   1677 
   1678     namespace assertAction {
   1679         enum Enum
   1680         {
   1681             nothing     = 0,
   1682             dbgbreak    = 1,
   1683             shouldthrow = 2
   1684         };
   1685     } // namespace assertAction
   1686 
   1687     DOCTEST_INTERFACE void failed_out_of_a_testing_context(const AssertData& ad);
   1688 
   1689     DOCTEST_INTERFACE bool decomp_assert(assertType::Enum at, const char* file, int line,
   1690                                          const char* expr, const Result& result);
   1691 
   1692 #define DOCTEST_ASSERT_OUT_OF_TESTS(decomp)                                                        \
   1693     do {                                                                                           \
   1694         if(!is_running_in_test) {                                                                  \
   1695             if(failed) {                                                                           \
   1696                 ResultBuilder rb(at, file, line, expr);                                            \
   1697                 rb.m_failed = failed;                                                              \
   1698                 rb.m_decomp = decomp;                                                              \
   1699                 failed_out_of_a_testing_context(rb);                                               \
   1700                 if(isDebuggerActive() && !getContextOptions()->no_breaks)                          \
   1701                     DOCTEST_BREAK_INTO_DEBUGGER();                                                 \
   1702                 if(checkIfShouldThrow(at))                                                         \
   1703                     throwException();                                                              \
   1704             }                                                                                      \
   1705             return !failed;                                                                        \
   1706         }                                                                                          \
   1707     } while(false)
   1708 
   1709 #define DOCTEST_ASSERT_IN_TESTS(decomp)                                                            \
   1710     ResultBuilder rb(at, file, line, expr);                                                        \
   1711     rb.m_failed = failed;                                                                          \
   1712     if(rb.m_failed || getContextOptions()->success)                                                \
   1713         rb.m_decomp = decomp;                                                                      \
   1714     if(rb.log())                                                                                   \
   1715         DOCTEST_BREAK_INTO_DEBUGGER();                                                             \
   1716     if(rb.m_failed && checkIfShouldThrow(at))                                                      \
   1717     throwException()
   1718 
   1719     template <int comparison, typename L, typename R>
   1720     DOCTEST_NOINLINE bool binary_assert(assertType::Enum at, const char* file, int line,
   1721                                         const char* expr, const DOCTEST_REF_WRAP(L) lhs,
   1722                                         const DOCTEST_REF_WRAP(R) rhs) {
   1723         bool failed = !RelationalComparator<comparison, L, R>()(lhs, rhs);
   1724 
   1725         // ###################################################################################
   1726         // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT
   1727         // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED
   1728         // ###################################################################################
   1729         DOCTEST_ASSERT_OUT_OF_TESTS(stringifyBinaryExpr(lhs, ", ", rhs));
   1730         DOCTEST_ASSERT_IN_TESTS(stringifyBinaryExpr(lhs, ", ", rhs));
   1731         return !failed;
   1732     }
   1733 
   1734     template <typename L>
   1735     DOCTEST_NOINLINE bool unary_assert(assertType::Enum at, const char* file, int line,
   1736                                        const char* expr, const DOCTEST_REF_WRAP(L) val) {
   1737         bool failed = !val;
   1738 
   1739         if(at & assertType::is_false) //!OCLINT bitwise operator in conditional
   1740             failed = !failed;
   1741 
   1742         // ###################################################################################
   1743         // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT
   1744         // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED
   1745         // ###################################################################################
   1746         DOCTEST_ASSERT_OUT_OF_TESTS((DOCTEST_STRINGIFY(val)));
   1747         DOCTEST_ASSERT_IN_TESTS((DOCTEST_STRINGIFY(val)));
   1748         return !failed;
   1749     }
   1750 
   1751     struct DOCTEST_INTERFACE IExceptionTranslator
   1752     {
   1753         DOCTEST_DECLARE_INTERFACE(IExceptionTranslator)
   1754         virtual bool translate(String&) const = 0;
   1755     };
   1756 
   1757     template <typename T>
   1758     class ExceptionTranslator : public IExceptionTranslator //!OCLINT destructor of virtual class
   1759     {
   1760     public:
   1761         explicit ExceptionTranslator(String (*translateFunction)(T))
   1762                 : m_translateFunction(translateFunction) {}
   1763 
   1764         bool translate(String& res) const override {
   1765 #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
   1766             try {
   1767                 throw; // lgtm [cpp/rethrow-no-exception]
   1768                 // cppcheck-suppress catchExceptionByValue
   1769             } catch(const T& ex) {
   1770                 res = m_translateFunction(ex); //!OCLINT parameter reassignment
   1771                 return true;
   1772             } catch(...) {}         //!OCLINT -  empty catch statement
   1773 #endif                              // DOCTEST_CONFIG_NO_EXCEPTIONS
   1774             static_cast<void>(res); // to silence -Wunused-parameter
   1775             return false;
   1776         }
   1777 
   1778     private:
   1779         String (*m_translateFunction)(T);
   1780     };
   1781 
   1782     DOCTEST_INTERFACE void registerExceptionTranslatorImpl(const IExceptionTranslator* et);
   1783 
   1784     // ContextScope base class used to allow implementing methods of ContextScope
   1785     // that don't depend on the template parameter in doctest.cpp.
   1786     struct DOCTEST_INTERFACE ContextScopeBase : public IContextScope {
   1787         ContextScopeBase(const ContextScopeBase&) = delete;
   1788 
   1789         ContextScopeBase& operator=(const ContextScopeBase&) = delete;
   1790         ContextScopeBase& operator=(ContextScopeBase&&) = delete;
   1791 
   1792         ~ContextScopeBase() override = default;
   1793 
   1794     protected:
   1795         ContextScopeBase();
   1796         ContextScopeBase(ContextScopeBase&& other) noexcept;
   1797 
   1798         void destroy();
   1799         bool need_to_destroy{true};
   1800     };
   1801 
   1802     template <typename L> class ContextScope : public ContextScopeBase
   1803     {
   1804         L lambda_;
   1805 
   1806     public:
   1807         explicit ContextScope(const L &lambda) : lambda_(lambda) {}
   1808         explicit ContextScope(L&& lambda) : lambda_(static_cast<L&&>(lambda)) { }
   1809 
   1810         ContextScope(const ContextScope&) = delete;
   1811         ContextScope(ContextScope&&) noexcept = default;
   1812 
   1813         ContextScope& operator=(const ContextScope&) = delete;
   1814         ContextScope& operator=(ContextScope&&) = delete;
   1815 
   1816         void stringify(std::ostream* s) const override { lambda_(s); }
   1817 
   1818         ~ContextScope() override {
   1819             if (need_to_destroy) {
   1820                 destroy();
   1821             }
   1822         }
   1823     };
   1824 
   1825     struct DOCTEST_INTERFACE MessageBuilder : public MessageData
   1826     {
   1827         std::ostream* m_stream;
   1828         bool          logged = false;
   1829 
   1830         MessageBuilder(const char* file, int line, assertType::Enum severity);
   1831 
   1832         MessageBuilder(const MessageBuilder&) = delete;
   1833         MessageBuilder(MessageBuilder&&) = delete;
   1834 
   1835         MessageBuilder& operator=(const MessageBuilder&) = delete;
   1836         MessageBuilder& operator=(MessageBuilder&&) = delete;
   1837 
   1838         ~MessageBuilder();
   1839 
   1840         // the preferred way of chaining parameters for stringification
   1841 DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4866)
   1842         template <typename T>
   1843         MessageBuilder& operator,(const T& in) {
   1844             *m_stream << (DOCTEST_STRINGIFY(in));
   1845             return *this;
   1846         }
   1847 DOCTEST_MSVC_SUPPRESS_WARNING_POP
   1848 
   1849         // kept here just for backwards-compatibility - the comma operator should be preferred now
   1850         template <typename T>
   1851         MessageBuilder& operator<<(const T& in) { return this->operator,(in); }
   1852 
   1853         // the `,` operator has the lowest operator precedence - if `<<` is used by the user then
   1854         // the `,` operator will be called last which is not what we want and thus the `*` operator
   1855         // is used first (has higher operator precedence compared to `<<`) so that we guarantee that
   1856         // an operator of the MessageBuilder class is called first before the rest of the parameters
   1857         template <typename T>
   1858         MessageBuilder& operator*(const T& in) { return this->operator,(in); }
   1859 
   1860         bool log();
   1861         void react();
   1862     };
   1863 
   1864     template <typename L>
   1865     ContextScope<L> MakeContextScope(const L &lambda) {
   1866         return ContextScope<L>(lambda);
   1867     }
   1868 } // namespace detail
   1869 
   1870 #define DOCTEST_DEFINE_DECORATOR(name, type, def)                                                  \
   1871     struct name                                                                                    \
   1872     {                                                                                              \
   1873         type data;                                                                                 \
   1874         name(type in = def)                                                                        \
   1875                 : data(in) {}                                                                      \
   1876         void fill(detail::TestCase& state) const { state.DOCTEST_CAT(m_, name) = data; }           \
   1877         void fill(detail::TestSuite& state) const { state.DOCTEST_CAT(m_, name) = data; }          \
   1878     }
   1879 
   1880 DOCTEST_DEFINE_DECORATOR(test_suite, const char*, "");
   1881 DOCTEST_DEFINE_DECORATOR(description, const char*, "");
   1882 DOCTEST_DEFINE_DECORATOR(skip, bool, true);
   1883 DOCTEST_DEFINE_DECORATOR(no_breaks, bool, true);
   1884 DOCTEST_DEFINE_DECORATOR(no_output, bool, true);
   1885 DOCTEST_DEFINE_DECORATOR(timeout, double, 0);
   1886 DOCTEST_DEFINE_DECORATOR(may_fail, bool, true);
   1887 DOCTEST_DEFINE_DECORATOR(should_fail, bool, true);
   1888 DOCTEST_DEFINE_DECORATOR(expected_failures, int, 0);
   1889 
   1890 template <typename T>
   1891 int registerExceptionTranslator(String (*translateFunction)(T)) {
   1892     DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wexit-time-destructors")
   1893     static detail::ExceptionTranslator<T> exceptionTranslator(translateFunction);
   1894     DOCTEST_CLANG_SUPPRESS_WARNING_POP
   1895     detail::registerExceptionTranslatorImpl(&exceptionTranslator);
   1896     return 0;
   1897 }
   1898 
   1899 } // namespace doctest
   1900 
   1901 // in a separate namespace outside of doctest because the DOCTEST_TEST_SUITE macro
   1902 // introduces an anonymous namespace in which getCurrentTestSuite gets overridden
   1903 namespace doctest_detail_test_suite_ns {
   1904 DOCTEST_INTERFACE doctest::detail::TestSuite& getCurrentTestSuite();
   1905 } // namespace doctest_detail_test_suite_ns
   1906 
   1907 namespace doctest {
   1908 #else  // DOCTEST_CONFIG_DISABLE
   1909 template <typename T>
   1910 int registerExceptionTranslator(String (*)(T)) {
   1911     return 0;
   1912 }
   1913 #endif // DOCTEST_CONFIG_DISABLE
   1914 
   1915 namespace detail {
   1916     using assert_handler = void (*)(const AssertData&);
   1917     struct ContextState;
   1918 } // namespace detail
   1919 
   1920 class DOCTEST_INTERFACE Context
   1921 {
   1922     detail::ContextState* p;
   1923 
   1924     void parseArgs(int argc, const char* const* argv, bool withDefaults = false);
   1925 
   1926 public:
   1927     explicit Context(int argc = 0, const char* const* argv = nullptr);
   1928 
   1929     Context(const Context&) = delete;
   1930     Context(Context&&) = delete;
   1931 
   1932     Context& operator=(const Context&) = delete;
   1933     Context& operator=(Context&&) = delete;
   1934 
   1935     ~Context(); // NOLINT(performance-trivially-destructible)
   1936 
   1937     void applyCommandLine(int argc, const char* const* argv);
   1938 
   1939     void addFilter(const char* filter, const char* value);
   1940     void clearFilters();
   1941     void setOption(const char* option, bool value);
   1942     void setOption(const char* option, int value);
   1943     void setOption(const char* option, const char* value);
   1944 
   1945     bool shouldExit();
   1946 
   1947     void setAsDefaultForAssertsOutOfTestCases();
   1948 
   1949     void setAssertHandler(detail::assert_handler ah);
   1950 
   1951     void setCout(std::ostream* out);
   1952 
   1953     int run();
   1954 };
   1955 
   1956 namespace TestCaseFailureReason {
   1957     enum Enum
   1958     {
   1959         None                     = 0,
   1960         AssertFailure            = 1,   // an assertion has failed in the test case
   1961         Exception                = 2,   // test case threw an exception
   1962         Crash                    = 4,   // a crash...
   1963         TooManyFailedAsserts     = 8,   // the abort-after option
   1964         Timeout                  = 16,  // see the timeout decorator
   1965         ShouldHaveFailedButDidnt = 32,  // see the should_fail decorator
   1966         ShouldHaveFailedAndDid   = 64,  // see the should_fail decorator
   1967         DidntFailExactlyNumTimes = 128, // see the expected_failures decorator
   1968         FailedExactlyNumTimes    = 256, // see the expected_failures decorator
   1969         CouldHaveFailedAndDid    = 512  // see the may_fail decorator
   1970     };
   1971 } // namespace TestCaseFailureReason
   1972 
   1973 struct DOCTEST_INTERFACE CurrentTestCaseStats
   1974 {
   1975     int    numAssertsCurrentTest;
   1976     int    numAssertsFailedCurrentTest;
   1977     double seconds;
   1978     int    failure_flags; // use TestCaseFailureReason::Enum
   1979     bool   testCaseSuccess;
   1980 };
   1981 
   1982 struct DOCTEST_INTERFACE TestCaseException
   1983 {
   1984     String error_string;
   1985     bool   is_crash;
   1986 };
   1987 
   1988 struct DOCTEST_INTERFACE TestRunStats
   1989 {
   1990     unsigned numTestCases;
   1991     unsigned numTestCasesPassingFilters;
   1992     unsigned numTestSuitesPassingFilters;
   1993     unsigned numTestCasesFailed;
   1994     int      numAsserts;
   1995     int      numAssertsFailed;
   1996 };
   1997 
   1998 struct QueryData
   1999 {
   2000     const TestRunStats*  run_stats = nullptr;
   2001     const TestCaseData** data      = nullptr;
   2002     unsigned             num_data  = 0;
   2003 };
   2004 
   2005 struct DOCTEST_INTERFACE IReporter
   2006 {
   2007     // The constructor has to accept "const ContextOptions&" as a single argument
   2008     // which has most of the options for the run + a pointer to the stdout stream
   2009     // Reporter(const ContextOptions& in)
   2010 
   2011     // called when a query should be reported (listing test cases, printing the version, etc.)
   2012     virtual void report_query(const QueryData&) = 0;
   2013 
   2014     // called when the whole test run starts
   2015     virtual void test_run_start() = 0;
   2016     // called when the whole test run ends (caching a pointer to the input doesn't make sense here)
   2017     virtual void test_run_end(const TestRunStats&) = 0;
   2018 
   2019     // called when a test case is started (safe to cache a pointer to the input)
   2020     virtual void test_case_start(const TestCaseData&) = 0;
   2021     // called when a test case is reentered because of unfinished subcases (safe to cache a pointer to the input)
   2022     virtual void test_case_reenter(const TestCaseData&) = 0;
   2023     // called when a test case has ended
   2024     virtual void test_case_end(const CurrentTestCaseStats&) = 0;
   2025 
   2026     // called when an exception is thrown from the test case (or it crashes)
   2027     virtual void test_case_exception(const TestCaseException&) = 0;
   2028 
   2029     // called whenever a subcase is entered (don't cache pointers to the input)
   2030     virtual void subcase_start(const SubcaseSignature&) = 0;
   2031     // called whenever a subcase is exited (don't cache pointers to the input)
   2032     virtual void subcase_end() = 0;
   2033 
   2034     // called for each assert (don't cache pointers to the input)
   2035     virtual void log_assert(const AssertData&) = 0;
   2036     // called for each message (don't cache pointers to the input)
   2037     virtual void log_message(const MessageData&) = 0;
   2038 
   2039     // called when a test case is skipped either because it doesn't pass the filters, has a skip decorator
   2040     // or isn't in the execution range (between first and last) (safe to cache a pointer to the input)
   2041     virtual void test_case_skipped(const TestCaseData&) = 0;
   2042 
   2043     DOCTEST_DECLARE_INTERFACE(IReporter)
   2044 
   2045     // can obtain all currently active contexts and stringify them if one wishes to do so
   2046     static int                         get_num_active_contexts();
   2047     static const IContextScope* const* get_active_contexts();
   2048 
   2049     // can iterate through contexts which have been stringified automatically in their destructors when an exception has been thrown
   2050     static int           get_num_stringified_contexts();
   2051     static const String* get_stringified_contexts();
   2052 };
   2053 
   2054 namespace detail {
   2055     using reporterCreatorFunc =  IReporter* (*)(const ContextOptions&);
   2056 
   2057     DOCTEST_INTERFACE void registerReporterImpl(const char* name, int prio, reporterCreatorFunc c, bool isReporter);
   2058 
   2059     template <typename Reporter>
   2060     IReporter* reporterCreator(const ContextOptions& o) {
   2061         return new Reporter(o);
   2062     }
   2063 } // namespace detail
   2064 
   2065 template <typename Reporter>
   2066 int registerReporter(const char* name, int priority, bool isReporter) {
   2067     detail::registerReporterImpl(name, priority, detail::reporterCreator<Reporter>, isReporter);
   2068     return 0;
   2069 }
   2070 } // namespace doctest
   2071 
   2072 #ifdef DOCTEST_CONFIG_ASSERTS_RETURN_VALUES
   2073 #define DOCTEST_FUNC_EMPTY [] { return false; }()
   2074 #else
   2075 #define DOCTEST_FUNC_EMPTY (void)0
   2076 #endif
   2077 
   2078 // if registering is not disabled
   2079 #ifndef DOCTEST_CONFIG_DISABLE
   2080 
   2081 #ifdef DOCTEST_CONFIG_ASSERTS_RETURN_VALUES
   2082 #define DOCTEST_FUNC_SCOPE_BEGIN [&]
   2083 #define DOCTEST_FUNC_SCOPE_END ()
   2084 #define DOCTEST_FUNC_SCOPE_RET(v) return v
   2085 #else
   2086 #define DOCTEST_FUNC_SCOPE_BEGIN do
   2087 #define DOCTEST_FUNC_SCOPE_END while(false)
   2088 #define DOCTEST_FUNC_SCOPE_RET(v) (void)0
   2089 #endif
   2090 
   2091 // common code in asserts - for convenience
   2092 #define DOCTEST_ASSERT_LOG_REACT_RETURN(b)                                                         \
   2093     if(b.log()) DOCTEST_BREAK_INTO_DEBUGGER();                                                     \
   2094     b.react();                                                                                     \
   2095     DOCTEST_FUNC_SCOPE_RET(!b.m_failed)
   2096 
   2097 #ifdef DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
   2098 #define DOCTEST_WRAP_IN_TRY(x) x;
   2099 #else // DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
   2100 #define DOCTEST_WRAP_IN_TRY(x)                                                                     \
   2101     try {                                                                                          \
   2102         x;                                                                                         \
   2103     } catch(...) { DOCTEST_RB.translateException(); }
   2104 #endif // DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
   2105 
   2106 #ifdef DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS
   2107 #define DOCTEST_CAST_TO_VOID(...)                                                                  \
   2108     DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wuseless-cast")                                       \
   2109     static_cast<void>(__VA_ARGS__);                                                                \
   2110     DOCTEST_GCC_SUPPRESS_WARNING_POP
   2111 #else // DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS
   2112 #define DOCTEST_CAST_TO_VOID(...) __VA_ARGS__;
   2113 #endif // DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS
   2114 
   2115 // registers the test by initializing a dummy var with a function
   2116 #define DOCTEST_REGISTER_FUNCTION(global_prefix, f, decorators)                                    \
   2117     global_prefix DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), /* NOLINT */    \
   2118             doctest::detail::regTest(                                                              \
   2119                     doctest::detail::TestCase(                                                     \
   2120                             f, __FILE__, __LINE__,                                                 \
   2121                             doctest_detail_test_suite_ns::getCurrentTestSuite()) *                 \
   2122                     decorators))
   2123 
   2124 #define DOCTEST_IMPLEMENT_FIXTURE(der, base, func, decorators)                                     \
   2125     namespace { /* NOLINT */                                                                       \
   2126         struct der : public base                                                                   \
   2127         {                                                                                          \
   2128             void f();                                                                              \
   2129         };                                                                                         \
   2130         static inline DOCTEST_NOINLINE void func() {                                               \
   2131             der v;                                                                                 \
   2132             v.f();                                                                                 \
   2133         }                                                                                          \
   2134         DOCTEST_REGISTER_FUNCTION(DOCTEST_EMPTY, func, decorators)                                 \
   2135     }                                                                                              \
   2136     inline DOCTEST_NOINLINE void der::f() // NOLINT(misc-definitions-in-headers)
   2137 
   2138 #define DOCTEST_CREATE_AND_REGISTER_FUNCTION(f, decorators)                                        \
   2139     static void f();                                                                               \
   2140     DOCTEST_REGISTER_FUNCTION(DOCTEST_EMPTY, f, decorators)                                        \
   2141     static void f()
   2142 
   2143 #define DOCTEST_CREATE_AND_REGISTER_FUNCTION_IN_CLASS(f, proxy, decorators)                        \
   2144     static doctest::detail::funcType proxy() { return f; }                                         \
   2145     DOCTEST_REGISTER_FUNCTION(inline, proxy(), decorators)                                         \
   2146     static void f()
   2147 
   2148 // for registering tests
   2149 #define DOCTEST_TEST_CASE(decorators)                                                              \
   2150     DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), decorators)
   2151 
   2152 // for registering tests in classes - requires C++17 for inline variables!
   2153 #if DOCTEST_CPLUSPLUS >= 201703L
   2154 #define DOCTEST_TEST_CASE_CLASS(decorators)                                                        \
   2155     DOCTEST_CREATE_AND_REGISTER_FUNCTION_IN_CLASS(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_),           \
   2156                                                   DOCTEST_ANONYMOUS(DOCTEST_ANON_PROXY_),          \
   2157                                                   decorators)
   2158 #else // DOCTEST_TEST_CASE_CLASS
   2159 #define DOCTEST_TEST_CASE_CLASS(...)                                                               \
   2160     TEST_CASES_CAN_BE_REGISTERED_IN_CLASSES_ONLY_IN_CPP17_MODE_OR_WITH_VS_2017_OR_NEWER
   2161 #endif // DOCTEST_TEST_CASE_CLASS
   2162 
   2163 // for registering tests with a fixture
   2164 #define DOCTEST_TEST_CASE_FIXTURE(c, decorators)                                                   \
   2165     DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(DOCTEST_ANON_CLASS_), c,                           \
   2166                               DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), decorators)
   2167 
   2168 // for converting types to strings without the <typeinfo> header and demangling
   2169 #define DOCTEST_TYPE_TO_STRING_AS(str, ...)                                                        \
   2170     namespace doctest {                                                                            \
   2171         template <>                                                                                \
   2172         inline String toString<__VA_ARGS__>() {                                                    \
   2173             return str;                                                                            \
   2174         }                                                                                          \
   2175     }                                                                                              \
   2176     static_assert(true, "")
   2177 
   2178 #define DOCTEST_TYPE_TO_STRING(...) DOCTEST_TYPE_TO_STRING_AS(#__VA_ARGS__, __VA_ARGS__)
   2179 
   2180 #define DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, iter, func)                                 \
   2181     template <typename T>                                                                          \
   2182     static void func();                                                                            \
   2183     namespace { /* NOLINT */                                                                       \
   2184         template <typename Tuple>                                                                  \
   2185         struct iter;                                                                               \
   2186         template <typename Type, typename... Rest>                                                 \
   2187         struct iter<std::tuple<Type, Rest...>>                                                     \
   2188         {                                                                                          \
   2189             iter(const char* file, unsigned line, int index) {                                     \
   2190                 doctest::detail::regTest(doctest::detail::TestCase(func<Type>, file, line,         \
   2191                                             doctest_detail_test_suite_ns::getCurrentTestSuite(),   \
   2192                                             doctest::toString<Type>(),                             \
   2193                                             int(line) * 1000 + index)                              \
   2194                                          * dec);                                                   \
   2195                 iter<std::tuple<Rest...>>(file, line, index + 1);                                  \
   2196             }                                                                                      \
   2197         };                                                                                         \
   2198         template <>                                                                                \
   2199         struct iter<std::tuple<>>                                                                  \
   2200         {                                                                                          \
   2201             iter(const char*, unsigned, int) {}                                                    \
   2202         };                                                                                         \
   2203     }                                                                                              \
   2204     template <typename T>                                                                          \
   2205     static void func()
   2206 
   2207 #define DOCTEST_TEST_CASE_TEMPLATE_DEFINE(dec, T, id)                                              \
   2208     DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(id, ITERATOR),                      \
   2209                                            DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_))
   2210 
   2211 #define DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, anon, ...)                                 \
   2212     DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_CAT(anon, DUMMY), /* NOLINT(cert-err58-cpp, fuchsia-statically-constructed-objects) */ \
   2213         doctest::detail::instantiationHelper(                                                      \
   2214             DOCTEST_CAT(id, ITERATOR)<__VA_ARGS__>(__FILE__, __LINE__, 0)))
   2215 
   2216 #define DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, ...)                                                 \
   2217     DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), std::tuple<__VA_ARGS__>) \
   2218     static_assert(true, "")
   2219 
   2220 #define DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, ...)                                                  \
   2221     DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), __VA_ARGS__) \
   2222     static_assert(true, "")
   2223 
   2224 #define DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, anon, ...)                                         \
   2225     DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(anon, ITERATOR), anon);             \
   2226     DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(anon, anon, std::tuple<__VA_ARGS__>)               \
   2227     template <typename T>                                                                          \
   2228     static void anon()
   2229 
   2230 #define DOCTEST_TEST_CASE_TEMPLATE(dec, T, ...)                                                    \
   2231     DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), __VA_ARGS__)
   2232 
   2233 // for subcases
   2234 #define DOCTEST_SUBCASE(name)                                                                      \
   2235     if(const doctest::detail::Subcase & DOCTEST_ANONYMOUS(DOCTEST_ANON_SUBCASE_) DOCTEST_UNUSED =  \
   2236                doctest::detail::Subcase(name, __FILE__, __LINE__))
   2237 
   2238 // for grouping tests in test suites by using code blocks
   2239 #define DOCTEST_TEST_SUITE_IMPL(decorators, ns_name)                                               \
   2240     namespace ns_name { namespace doctest_detail_test_suite_ns {                                   \
   2241             static DOCTEST_NOINLINE doctest::detail::TestSuite& getCurrentTestSuite() noexcept {   \
   2242                 DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4640)                                      \
   2243                 DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wexit-time-destructors")                \
   2244                 DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wmissing-field-initializers")             \
   2245                 static doctest::detail::TestSuite data{};                                          \
   2246                 static bool                       inited = false;                                  \
   2247                 DOCTEST_MSVC_SUPPRESS_WARNING_POP                                                  \
   2248                 DOCTEST_CLANG_SUPPRESS_WARNING_POP                                                 \
   2249                 DOCTEST_GCC_SUPPRESS_WARNING_POP                                                   \
   2250                 if(!inited) {                                                                      \
   2251                     data* decorators;                                                              \
   2252                     inited = true;                                                                 \
   2253                 }                                                                                  \
   2254                 return data;                                                                       \
   2255             }                                                                                      \
   2256         }                                                                                          \
   2257     }                                                                                              \
   2258     namespace ns_name
   2259 
   2260 #define DOCTEST_TEST_SUITE(decorators)                                                             \
   2261     DOCTEST_TEST_SUITE_IMPL(decorators, DOCTEST_ANONYMOUS(DOCTEST_ANON_SUITE_))
   2262 
   2263 // for starting a testsuite block
   2264 #define DOCTEST_TEST_SUITE_BEGIN(decorators)                                                       \
   2265     DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), /* NOLINT(cert-err58-cpp) */  \
   2266             doctest::detail::setTestSuite(doctest::detail::TestSuite() * decorators))              \
   2267     static_assert(true, "")
   2268 
   2269 // for ending a testsuite block
   2270 #define DOCTEST_TEST_SUITE_END                                                                     \
   2271     DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), /* NOLINT(cert-err58-cpp) */  \
   2272             doctest::detail::setTestSuite(doctest::detail::TestSuite() * ""))                      \
   2273     using DOCTEST_ANONYMOUS(DOCTEST_ANON_FOR_SEMICOLON_) = int
   2274 
   2275 // for registering exception translators
   2276 #define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR_IMPL(translatorName, signature)                      \
   2277     inline doctest::String translatorName(signature);                                              \
   2278     DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_), /* NOLINT(cert-err58-cpp) */ \
   2279             doctest::registerExceptionTranslator(translatorName))                                  \
   2280     doctest::String translatorName(signature)
   2281 
   2282 #define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature)                                           \
   2283     DOCTEST_REGISTER_EXCEPTION_TRANSLATOR_IMPL(DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_),        \
   2284                                                signature)
   2285 
   2286 // for registering reporters
   2287 #define DOCTEST_REGISTER_REPORTER(name, priority, reporter)                                        \
   2288     DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_REPORTER_), /* NOLINT(cert-err58-cpp) */ \
   2289             doctest::registerReporter<reporter>(name, priority, true))                             \
   2290     static_assert(true, "")
   2291 
   2292 // for registering listeners
   2293 #define DOCTEST_REGISTER_LISTENER(name, priority, reporter)                                        \
   2294     DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_REPORTER_), /* NOLINT(cert-err58-cpp) */ \
   2295             doctest::registerReporter<reporter>(name, priority, false))                            \
   2296     static_assert(true, "")
   2297 
   2298 // clang-format off
   2299 // for logging - disabling formatting because it's important to have these on 2 separate lines - see PR #557
   2300 #define DOCTEST_INFO(...)                                                                          \
   2301     DOCTEST_INFO_IMPL(DOCTEST_ANONYMOUS(DOCTEST_CAPTURE_),                                         \
   2302                       DOCTEST_ANONYMOUS(DOCTEST_CAPTURE_OTHER_),                                   \
   2303                       __VA_ARGS__)
   2304 // clang-format on
   2305 
   2306 #define DOCTEST_INFO_IMPL(mb_name, s_name, ...)                                       \
   2307     auto DOCTEST_ANONYMOUS(DOCTEST_CAPTURE_) = doctest::detail::MakeContextScope(                  \
   2308         [&](std::ostream* s_name) {                                                                \
   2309         doctest::detail::MessageBuilder mb_name(__FILE__, __LINE__, doctest::assertType::is_warn); \
   2310         mb_name.m_stream = s_name;                                                                 \
   2311         mb_name * __VA_ARGS__;                                                                     \
   2312     })
   2313 
   2314 #define DOCTEST_CAPTURE(x) DOCTEST_INFO(#x " := ", x)
   2315 
   2316 #define DOCTEST_ADD_AT_IMPL(type, file, line, mb, ...)                                             \
   2317     DOCTEST_FUNC_SCOPE_BEGIN {                                                                     \
   2318         doctest::detail::MessageBuilder mb(file, line, doctest::assertType::type);                 \
   2319         mb * __VA_ARGS__;                                                                          \
   2320         if(mb.log())                                                                               \
   2321             DOCTEST_BREAK_INTO_DEBUGGER();                                                         \
   2322         mb.react();                                                                                \
   2323     } DOCTEST_FUNC_SCOPE_END
   2324 
   2325 // clang-format off
   2326 #define DOCTEST_ADD_MESSAGE_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_warn, file, line, DOCTEST_ANONYMOUS(DOCTEST_MESSAGE_), __VA_ARGS__)
   2327 #define DOCTEST_ADD_FAIL_CHECK_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_check, file, line, DOCTEST_ANONYMOUS(DOCTEST_MESSAGE_), __VA_ARGS__)
   2328 #define DOCTEST_ADD_FAIL_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_require, file, line, DOCTEST_ANONYMOUS(DOCTEST_MESSAGE_), __VA_ARGS__)
   2329 // clang-format on
   2330 
   2331 #define DOCTEST_MESSAGE(...) DOCTEST_ADD_MESSAGE_AT(__FILE__, __LINE__, __VA_ARGS__)
   2332 #define DOCTEST_FAIL_CHECK(...) DOCTEST_ADD_FAIL_CHECK_AT(__FILE__, __LINE__, __VA_ARGS__)
   2333 #define DOCTEST_FAIL(...) DOCTEST_ADD_FAIL_AT(__FILE__, __LINE__, __VA_ARGS__)
   2334 
   2335 #define DOCTEST_TO_LVALUE(...) __VA_ARGS__ // Not removed to keep backwards compatibility.
   2336 
   2337 #ifndef DOCTEST_CONFIG_SUPER_FAST_ASSERTS
   2338 
   2339 #define DOCTEST_ASSERT_IMPLEMENT_2(assert_type, ...)                                               \
   2340     DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Woverloaded-shift-op-parentheses")                  \
   2341     /* NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) */                                  \
   2342     doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__,          \
   2343                                                __LINE__, #__VA_ARGS__);                            \
   2344     DOCTEST_WRAP_IN_TRY(DOCTEST_RB.setResult(                                                      \
   2345             doctest::detail::ExpressionDecomposer(doctest::assertType::assert_type)                \
   2346             << __VA_ARGS__)) /* NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) */         \
   2347     DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB)                                                    \
   2348     DOCTEST_CLANG_SUPPRESS_WARNING_POP
   2349 
   2350 #define DOCTEST_ASSERT_IMPLEMENT_1(assert_type, ...)                                               \
   2351     DOCTEST_FUNC_SCOPE_BEGIN {                                                                     \
   2352         DOCTEST_ASSERT_IMPLEMENT_2(assert_type, __VA_ARGS__);                                      \
   2353     } DOCTEST_FUNC_SCOPE_END // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
   2354 
   2355 #define DOCTEST_BINARY_ASSERT(assert_type, comp, ...)                                              \
   2356     DOCTEST_FUNC_SCOPE_BEGIN {                                                                     \
   2357         doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__,      \
   2358                                                    __LINE__, #__VA_ARGS__);                        \
   2359         DOCTEST_WRAP_IN_TRY(                                                                       \
   2360                 DOCTEST_RB.binary_assert<doctest::detail::binaryAssertComparison::comp>(           \
   2361                         __VA_ARGS__))                                                              \
   2362         DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB);                                               \
   2363     } DOCTEST_FUNC_SCOPE_END
   2364 
   2365 #define DOCTEST_UNARY_ASSERT(assert_type, ...)                                                     \
   2366     DOCTEST_FUNC_SCOPE_BEGIN {                                                                     \
   2367         doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__,      \
   2368                                                    __LINE__, #__VA_ARGS__);                        \
   2369         DOCTEST_WRAP_IN_TRY(DOCTEST_RB.unary_assert(__VA_ARGS__))                                  \
   2370         DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB);                                               \
   2371     } DOCTEST_FUNC_SCOPE_END
   2372 
   2373 #else // DOCTEST_CONFIG_SUPER_FAST_ASSERTS
   2374 
   2375 // necessary for <ASSERT>_MESSAGE
   2376 #define DOCTEST_ASSERT_IMPLEMENT_2 DOCTEST_ASSERT_IMPLEMENT_1
   2377 
   2378 #define DOCTEST_ASSERT_IMPLEMENT_1(assert_type, ...)                                               \
   2379     DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Woverloaded-shift-op-parentheses")                  \
   2380     doctest::detail::decomp_assert(                                                                \
   2381             doctest::assertType::assert_type, __FILE__, __LINE__, #__VA_ARGS__,                    \
   2382             doctest::detail::ExpressionDecomposer(doctest::assertType::assert_type)                \
   2383                     << __VA_ARGS__) DOCTEST_CLANG_SUPPRESS_WARNING_POP
   2384 
   2385 #define DOCTEST_BINARY_ASSERT(assert_type, comparison, ...)                                        \
   2386     doctest::detail::binary_assert<doctest::detail::binaryAssertComparison::comparison>(           \
   2387             doctest::assertType::assert_type, __FILE__, __LINE__, #__VA_ARGS__, __VA_ARGS__)
   2388 
   2389 #define DOCTEST_UNARY_ASSERT(assert_type, ...)                                                     \
   2390     doctest::detail::unary_assert(doctest::assertType::assert_type, __FILE__, __LINE__,            \
   2391                                   #__VA_ARGS__, __VA_ARGS__)
   2392 
   2393 #endif // DOCTEST_CONFIG_SUPER_FAST_ASSERTS
   2394 
   2395 #define DOCTEST_WARN(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_WARN, __VA_ARGS__)
   2396 #define DOCTEST_CHECK(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_CHECK, __VA_ARGS__)
   2397 #define DOCTEST_REQUIRE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_REQUIRE, __VA_ARGS__)
   2398 #define DOCTEST_WARN_FALSE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_WARN_FALSE, __VA_ARGS__)
   2399 #define DOCTEST_CHECK_FALSE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_CHECK_FALSE, __VA_ARGS__)
   2400 #define DOCTEST_REQUIRE_FALSE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_REQUIRE_FALSE, __VA_ARGS__)
   2401 
   2402 // clang-format off
   2403 #define DOCTEST_WARN_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_WARN, cond); } DOCTEST_FUNC_SCOPE_END
   2404 #define DOCTEST_CHECK_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_CHECK, cond); } DOCTEST_FUNC_SCOPE_END
   2405 #define DOCTEST_REQUIRE_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE, cond); } DOCTEST_FUNC_SCOPE_END
   2406 #define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_WARN_FALSE, cond); } DOCTEST_FUNC_SCOPE_END
   2407 #define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_CHECK_FALSE, cond); } DOCTEST_FUNC_SCOPE_END
   2408 #define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE_FALSE, cond); } DOCTEST_FUNC_SCOPE_END
   2409 // clang-format on
   2410 
   2411 #define DOCTEST_WARN_EQ(...) DOCTEST_BINARY_ASSERT(DT_WARN_EQ, eq, __VA_ARGS__)
   2412 #define DOCTEST_CHECK_EQ(...) DOCTEST_BINARY_ASSERT(DT_CHECK_EQ, eq, __VA_ARGS__)
   2413 #define DOCTEST_REQUIRE_EQ(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_EQ, eq, __VA_ARGS__)
   2414 #define DOCTEST_WARN_NE(...) DOCTEST_BINARY_ASSERT(DT_WARN_NE, ne, __VA_ARGS__)
   2415 #define DOCTEST_CHECK_NE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_NE, ne, __VA_ARGS__)
   2416 #define DOCTEST_REQUIRE_NE(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_NE, ne, __VA_ARGS__)
   2417 #define DOCTEST_WARN_GT(...) DOCTEST_BINARY_ASSERT(DT_WARN_GT, gt, __VA_ARGS__)
   2418 #define DOCTEST_CHECK_GT(...) DOCTEST_BINARY_ASSERT(DT_CHECK_GT, gt, __VA_ARGS__)
   2419 #define DOCTEST_REQUIRE_GT(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_GT, gt, __VA_ARGS__)
   2420 #define DOCTEST_WARN_LT(...) DOCTEST_BINARY_ASSERT(DT_WARN_LT, lt, __VA_ARGS__)
   2421 #define DOCTEST_CHECK_LT(...) DOCTEST_BINARY_ASSERT(DT_CHECK_LT, lt, __VA_ARGS__)
   2422 #define DOCTEST_REQUIRE_LT(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_LT, lt, __VA_ARGS__)
   2423 #define DOCTEST_WARN_GE(...) DOCTEST_BINARY_ASSERT(DT_WARN_GE, ge, __VA_ARGS__)
   2424 #define DOCTEST_CHECK_GE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_GE, ge, __VA_ARGS__)
   2425 #define DOCTEST_REQUIRE_GE(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_GE, ge, __VA_ARGS__)
   2426 #define DOCTEST_WARN_LE(...) DOCTEST_BINARY_ASSERT(DT_WARN_LE, le, __VA_ARGS__)
   2427 #define DOCTEST_CHECK_LE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_LE, le, __VA_ARGS__)
   2428 #define DOCTEST_REQUIRE_LE(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_LE, le, __VA_ARGS__)
   2429 
   2430 #define DOCTEST_WARN_UNARY(...) DOCTEST_UNARY_ASSERT(DT_WARN_UNARY, __VA_ARGS__)
   2431 #define DOCTEST_CHECK_UNARY(...) DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY, __VA_ARGS__)
   2432 #define DOCTEST_REQUIRE_UNARY(...) DOCTEST_UNARY_ASSERT(DT_REQUIRE_UNARY, __VA_ARGS__)
   2433 #define DOCTEST_WARN_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_WARN_UNARY_FALSE, __VA_ARGS__)
   2434 #define DOCTEST_CHECK_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY_FALSE, __VA_ARGS__)
   2435 #define DOCTEST_REQUIRE_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_REQUIRE_UNARY_FALSE, __VA_ARGS__)
   2436 
   2437 #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
   2438 
   2439 #define DOCTEST_ASSERT_THROWS_AS(expr, assert_type, message, ...)                                  \
   2440     DOCTEST_FUNC_SCOPE_BEGIN {                                                                     \
   2441         if(!doctest::getContextOptions()->no_throw) {                                              \
   2442             doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__,  \
   2443                                                        __LINE__, #expr, #__VA_ARGS__, message);    \
   2444             try {                                                                                  \
   2445                 DOCTEST_CAST_TO_VOID(expr)                                                         \
   2446             } catch(const typename doctest::detail::types::remove_const<                           \
   2447                     typename doctest::detail::types::remove_reference<__VA_ARGS__>::type>::type&) {\
   2448                 DOCTEST_RB.translateException();                                                   \
   2449                 DOCTEST_RB.m_threw_as = true;                                                      \
   2450             } catch(...) { DOCTEST_RB.translateException(); }                                      \
   2451             DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB);                                           \
   2452         } else { /* NOLINT(*-else-after-return) */                                                 \
   2453             DOCTEST_FUNC_SCOPE_RET(false);                                                         \
   2454         }                                                                                          \
   2455     } DOCTEST_FUNC_SCOPE_END
   2456 
   2457 #define DOCTEST_ASSERT_THROWS_WITH(expr, expr_str, assert_type, ...)                               \
   2458     DOCTEST_FUNC_SCOPE_BEGIN {                                                                     \
   2459         if(!doctest::getContextOptions()->no_throw) {                                              \
   2460             doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__,  \
   2461                                                        __LINE__, expr_str, "", __VA_ARGS__);       \
   2462             try {                                                                                  \
   2463                 DOCTEST_CAST_TO_VOID(expr)                                                         \
   2464             } catch(...) { DOCTEST_RB.translateException(); }                                      \
   2465             DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB);                                           \
   2466         } else { /* NOLINT(*-else-after-return) */                                                 \
   2467            DOCTEST_FUNC_SCOPE_RET(false);                                                          \
   2468         }                                                                                          \
   2469     } DOCTEST_FUNC_SCOPE_END
   2470 
   2471 #define DOCTEST_ASSERT_NOTHROW(assert_type, ...)                                                   \
   2472     DOCTEST_FUNC_SCOPE_BEGIN {                                                                     \
   2473         doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__,      \
   2474                                                    __LINE__, #__VA_ARGS__);                        \
   2475         try {                                                                                      \
   2476             DOCTEST_CAST_TO_VOID(__VA_ARGS__)                                                      \
   2477         } catch(...) { DOCTEST_RB.translateException(); }                                          \
   2478         DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB);                                               \
   2479     } DOCTEST_FUNC_SCOPE_END
   2480 
   2481 // clang-format off
   2482 #define DOCTEST_WARN_THROWS(...) DOCTEST_ASSERT_THROWS_WITH((__VA_ARGS__), #__VA_ARGS__, DT_WARN_THROWS, "")
   2483 #define DOCTEST_CHECK_THROWS(...) DOCTEST_ASSERT_THROWS_WITH((__VA_ARGS__), #__VA_ARGS__, DT_CHECK_THROWS, "")
   2484 #define DOCTEST_REQUIRE_THROWS(...) DOCTEST_ASSERT_THROWS_WITH((__VA_ARGS__), #__VA_ARGS__, DT_REQUIRE_THROWS, "")
   2485 
   2486 #define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_WARN_THROWS_AS, "", __VA_ARGS__)
   2487 #define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_CHECK_THROWS_AS, "", __VA_ARGS__)
   2488 #define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_REQUIRE_THROWS_AS, "", __VA_ARGS__)
   2489 
   2490 #define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, #expr, DT_WARN_THROWS_WITH, __VA_ARGS__)
   2491 #define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, #expr, DT_CHECK_THROWS_WITH, __VA_ARGS__)
   2492 #define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, #expr, DT_REQUIRE_THROWS_WITH, __VA_ARGS__)
   2493 
   2494 #define DOCTEST_WARN_THROWS_WITH_AS(expr, message, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_WARN_THROWS_WITH_AS, message, __VA_ARGS__)
   2495 #define DOCTEST_CHECK_THROWS_WITH_AS(expr, message, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_CHECK_THROWS_WITH_AS, message, __VA_ARGS__)
   2496 #define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, message, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_REQUIRE_THROWS_WITH_AS, message, __VA_ARGS__)
   2497 
   2498 #define DOCTEST_WARN_NOTHROW(...) DOCTEST_ASSERT_NOTHROW(DT_WARN_NOTHROW, __VA_ARGS__)
   2499 #define DOCTEST_CHECK_NOTHROW(...) DOCTEST_ASSERT_NOTHROW(DT_CHECK_NOTHROW, __VA_ARGS__)
   2500 #define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_ASSERT_NOTHROW(DT_REQUIRE_NOTHROW, __VA_ARGS__)
   2501 
   2502 #define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS(expr); } DOCTEST_FUNC_SCOPE_END
   2503 #define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS(expr); } DOCTEST_FUNC_SCOPE_END
   2504 #define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS(expr); } DOCTEST_FUNC_SCOPE_END
   2505 #define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_AS(expr, ex); } DOCTEST_FUNC_SCOPE_END
   2506 #define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_AS(expr, ex); } DOCTEST_FUNC_SCOPE_END
   2507 #define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_AS(expr, ex); } DOCTEST_FUNC_SCOPE_END
   2508 #define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_WITH(expr, with); } DOCTEST_FUNC_SCOPE_END
   2509 #define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_WITH(expr, with); } DOCTEST_FUNC_SCOPE_END
   2510 #define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_WITH(expr, with); } DOCTEST_FUNC_SCOPE_END
   2511 #define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_WITH_AS(expr, with, ex); } DOCTEST_FUNC_SCOPE_END
   2512 #define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ex); } DOCTEST_FUNC_SCOPE_END
   2513 #define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ex); } DOCTEST_FUNC_SCOPE_END
   2514 #define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_NOTHROW(expr); } DOCTEST_FUNC_SCOPE_END
   2515 #define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_NOTHROW(expr); } DOCTEST_FUNC_SCOPE_END
   2516 #define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_NOTHROW(expr); } DOCTEST_FUNC_SCOPE_END
   2517 // clang-format on
   2518 
   2519 #endif // DOCTEST_CONFIG_NO_EXCEPTIONS
   2520 
   2521 // =================================================================================================
   2522 // == WHAT FOLLOWS IS VERSIONS OF THE MACROS THAT DO NOT DO ANY REGISTERING!                      ==
   2523 // == THIS CAN BE ENABLED BY DEFINING DOCTEST_CONFIG_DISABLE GLOBALLY!                            ==
   2524 // =================================================================================================
   2525 #else // DOCTEST_CONFIG_DISABLE
   2526 
   2527 #define DOCTEST_IMPLEMENT_FIXTURE(der, base, func, name)                                           \
   2528     namespace /* NOLINT */ {                                                                       \
   2529         template <typename DOCTEST_UNUSED_TEMPLATE_TYPE>                                           \
   2530         struct der : public base                                                                   \
   2531         { void f(); };                                                                             \
   2532     }                                                                                              \
   2533     template <typename DOCTEST_UNUSED_TEMPLATE_TYPE>                                               \
   2534     inline void der<DOCTEST_UNUSED_TEMPLATE_TYPE>::f()
   2535 
   2536 #define DOCTEST_CREATE_AND_REGISTER_FUNCTION(f, name)                                              \
   2537     template <typename DOCTEST_UNUSED_TEMPLATE_TYPE>                                               \
   2538     static inline void f()
   2539 
   2540 // for registering tests
   2541 #define DOCTEST_TEST_CASE(name)                                                                    \
   2542     DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name)
   2543 
   2544 // for registering tests in classes
   2545 #define DOCTEST_TEST_CASE_CLASS(name)                                                              \
   2546     DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name)
   2547 
   2548 // for registering tests with a fixture
   2549 #define DOCTEST_TEST_CASE_FIXTURE(x, name)                                                         \
   2550     DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(DOCTEST_ANON_CLASS_), x,                           \
   2551                               DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name)
   2552 
   2553 // for converting types to strings without the <typeinfo> header and demangling
   2554 #define DOCTEST_TYPE_TO_STRING_AS(str, ...) static_assert(true, "")
   2555 #define DOCTEST_TYPE_TO_STRING(...) static_assert(true, "")
   2556 
   2557 // for typed tests
   2558 #define DOCTEST_TEST_CASE_TEMPLATE(name, type, ...)                                                \
   2559     template <typename type>                                                                       \
   2560     inline void DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)()
   2561 
   2562 #define DOCTEST_TEST_CASE_TEMPLATE_DEFINE(name, type, id)                                          \
   2563     template <typename type>                                                                       \
   2564     inline void DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)()
   2565 
   2566 #define DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, ...) static_assert(true, "")
   2567 #define DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, ...) static_assert(true, "")
   2568 
   2569 // for subcases
   2570 #define DOCTEST_SUBCASE(name)
   2571 
   2572 // for a testsuite block
   2573 #define DOCTEST_TEST_SUITE(name) namespace // NOLINT
   2574 
   2575 // for starting a testsuite block
   2576 #define DOCTEST_TEST_SUITE_BEGIN(name) static_assert(true, "")
   2577 
   2578 // for ending a testsuite block
   2579 #define DOCTEST_TEST_SUITE_END using DOCTEST_ANONYMOUS(DOCTEST_ANON_FOR_SEMICOLON_) = int
   2580 
   2581 #define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature)                                           \
   2582     template <typename DOCTEST_UNUSED_TEMPLATE_TYPE>                                               \
   2583     static inline doctest::String DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_)(signature)
   2584 
   2585 #define DOCTEST_REGISTER_REPORTER(name, priority, reporter)
   2586 #define DOCTEST_REGISTER_LISTENER(name, priority, reporter)
   2587 
   2588 #define DOCTEST_INFO(...) (static_cast<void>(0))
   2589 #define DOCTEST_CAPTURE(x) (static_cast<void>(0))
   2590 #define DOCTEST_ADD_MESSAGE_AT(file, line, ...) (static_cast<void>(0))
   2591 #define DOCTEST_ADD_FAIL_CHECK_AT(file, line, ...) (static_cast<void>(0))
   2592 #define DOCTEST_ADD_FAIL_AT(file, line, ...) (static_cast<void>(0))
   2593 #define DOCTEST_MESSAGE(...) (static_cast<void>(0))
   2594 #define DOCTEST_FAIL_CHECK(...) (static_cast<void>(0))
   2595 #define DOCTEST_FAIL(...) (static_cast<void>(0))
   2596 
   2597 #if defined(DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED)                                    \
   2598  && defined(DOCTEST_CONFIG_ASSERTS_RETURN_VALUES)
   2599 
   2600 #define DOCTEST_WARN(...) [&] { return __VA_ARGS__; }()
   2601 #define DOCTEST_CHECK(...) [&] { return __VA_ARGS__; }()
   2602 #define DOCTEST_REQUIRE(...) [&] { return __VA_ARGS__; }()
   2603 #define DOCTEST_WARN_FALSE(...) [&] { return !(__VA_ARGS__); }()
   2604 #define DOCTEST_CHECK_FALSE(...) [&] { return !(__VA_ARGS__); }()
   2605 #define DOCTEST_REQUIRE_FALSE(...) [&] { return !(__VA_ARGS__); }()
   2606 
   2607 #define DOCTEST_WARN_MESSAGE(cond, ...) [&] { return cond; }()
   2608 #define DOCTEST_CHECK_MESSAGE(cond, ...) [&] { return cond; }()
   2609 #define DOCTEST_REQUIRE_MESSAGE(cond, ...) [&] { return cond; }()
   2610 #define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }()
   2611 #define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }()
   2612 #define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }()
   2613 
   2614 namespace doctest {
   2615 namespace detail {
   2616 #define DOCTEST_RELATIONAL_OP(name, op)                                                            \
   2617     template <typename L, typename R>                                                              \
   2618     bool name(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) { return lhs op rhs; }
   2619 
   2620     DOCTEST_RELATIONAL_OP(eq, ==)
   2621     DOCTEST_RELATIONAL_OP(ne, !=)
   2622     DOCTEST_RELATIONAL_OP(lt, <)
   2623     DOCTEST_RELATIONAL_OP(gt, >)
   2624     DOCTEST_RELATIONAL_OP(le, <=)
   2625     DOCTEST_RELATIONAL_OP(ge, >=)
   2626 } // namespace detail
   2627 } // namespace doctest
   2628 
   2629 #define DOCTEST_WARN_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }()
   2630 #define DOCTEST_CHECK_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }()
   2631 #define DOCTEST_REQUIRE_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }()
   2632 #define DOCTEST_WARN_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }()
   2633 #define DOCTEST_CHECK_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }()
   2634 #define DOCTEST_REQUIRE_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }()
   2635 #define DOCTEST_WARN_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }()
   2636 #define DOCTEST_CHECK_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }()
   2637 #define DOCTEST_REQUIRE_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }()
   2638 #define DOCTEST_WARN_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }()
   2639 #define DOCTEST_CHECK_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }()
   2640 #define DOCTEST_REQUIRE_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }()
   2641 #define DOCTEST_WARN_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }()
   2642 #define DOCTEST_CHECK_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }()
   2643 #define DOCTEST_REQUIRE_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }()
   2644 #define DOCTEST_WARN_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }()
   2645 #define DOCTEST_CHECK_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }()
   2646 #define DOCTEST_REQUIRE_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }()
   2647 #define DOCTEST_WARN_UNARY(...) [&] { return __VA_ARGS__; }()
   2648 #define DOCTEST_CHECK_UNARY(...) [&] { return __VA_ARGS__; }()
   2649 #define DOCTEST_REQUIRE_UNARY(...) [&] { return __VA_ARGS__; }()
   2650 #define DOCTEST_WARN_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }()
   2651 #define DOCTEST_CHECK_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }()
   2652 #define DOCTEST_REQUIRE_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }()
   2653 
   2654 #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
   2655 
   2656 #define DOCTEST_WARN_THROWS_WITH(expr, with, ...) [] { static_assert(false, "Exception translation is not available when doctest is disabled."); return false; }()
   2657 #define DOCTEST_CHECK_THROWS_WITH(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,)
   2658 #define DOCTEST_REQUIRE_THROWS_WITH(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,)
   2659 #define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,)
   2660 #define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,)
   2661 #define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,)
   2662 
   2663 #define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,)
   2664 #define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,)
   2665 #define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,)
   2666 #define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,)
   2667 #define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,)
   2668 #define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,)
   2669 
   2670 #define DOCTEST_WARN_THROWS(...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }()
   2671 #define DOCTEST_CHECK_THROWS(...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }()
   2672 #define DOCTEST_REQUIRE_THROWS(...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }()
   2673 #define DOCTEST_WARN_THROWS_AS(expr, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }()
   2674 #define DOCTEST_CHECK_THROWS_AS(expr, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }()
   2675 #define DOCTEST_REQUIRE_THROWS_AS(expr, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }()
   2676 #define DOCTEST_WARN_NOTHROW(...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }()
   2677 #define DOCTEST_CHECK_NOTHROW(...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }()
   2678 #define DOCTEST_REQUIRE_NOTHROW(...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }()
   2679 
   2680 #define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }()
   2681 #define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }()
   2682 #define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }()
   2683 #define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }()
   2684 #define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }()
   2685 #define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }()
   2686 #define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }()
   2687 #define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }()
   2688 #define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }()
   2689 
   2690 #endif // DOCTEST_CONFIG_NO_EXCEPTIONS
   2691 
   2692 #else // DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED
   2693 
   2694 #define DOCTEST_WARN(...) DOCTEST_FUNC_EMPTY
   2695 #define DOCTEST_CHECK(...) DOCTEST_FUNC_EMPTY
   2696 #define DOCTEST_REQUIRE(...) DOCTEST_FUNC_EMPTY
   2697 #define DOCTEST_WARN_FALSE(...) DOCTEST_FUNC_EMPTY
   2698 #define DOCTEST_CHECK_FALSE(...) DOCTEST_FUNC_EMPTY
   2699 #define DOCTEST_REQUIRE_FALSE(...) DOCTEST_FUNC_EMPTY
   2700 
   2701 #define DOCTEST_WARN_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY
   2702 #define DOCTEST_CHECK_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY
   2703 #define DOCTEST_REQUIRE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY
   2704 #define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY
   2705 #define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY
   2706 #define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY
   2707 
   2708 #define DOCTEST_WARN_EQ(...) DOCTEST_FUNC_EMPTY
   2709 #define DOCTEST_CHECK_EQ(...) DOCTEST_FUNC_EMPTY
   2710 #define DOCTEST_REQUIRE_EQ(...) DOCTEST_FUNC_EMPTY
   2711 #define DOCTEST_WARN_NE(...) DOCTEST_FUNC_EMPTY
   2712 #define DOCTEST_CHECK_NE(...) DOCTEST_FUNC_EMPTY
   2713 #define DOCTEST_REQUIRE_NE(...) DOCTEST_FUNC_EMPTY
   2714 #define DOCTEST_WARN_GT(...) DOCTEST_FUNC_EMPTY
   2715 #define DOCTEST_CHECK_GT(...) DOCTEST_FUNC_EMPTY
   2716 #define DOCTEST_REQUIRE_GT(...) DOCTEST_FUNC_EMPTY
   2717 #define DOCTEST_WARN_LT(...) DOCTEST_FUNC_EMPTY
   2718 #define DOCTEST_CHECK_LT(...) DOCTEST_FUNC_EMPTY
   2719 #define DOCTEST_REQUIRE_LT(...) DOCTEST_FUNC_EMPTY
   2720 #define DOCTEST_WARN_GE(...) DOCTEST_FUNC_EMPTY
   2721 #define DOCTEST_CHECK_GE(...) DOCTEST_FUNC_EMPTY
   2722 #define DOCTEST_REQUIRE_GE(...) DOCTEST_FUNC_EMPTY
   2723 #define DOCTEST_WARN_LE(...) DOCTEST_FUNC_EMPTY
   2724 #define DOCTEST_CHECK_LE(...) DOCTEST_FUNC_EMPTY
   2725 #define DOCTEST_REQUIRE_LE(...) DOCTEST_FUNC_EMPTY
   2726 
   2727 #define DOCTEST_WARN_UNARY(...) DOCTEST_FUNC_EMPTY
   2728 #define DOCTEST_CHECK_UNARY(...) DOCTEST_FUNC_EMPTY
   2729 #define DOCTEST_REQUIRE_UNARY(...) DOCTEST_FUNC_EMPTY
   2730 #define DOCTEST_WARN_UNARY_FALSE(...) DOCTEST_FUNC_EMPTY
   2731 #define DOCTEST_CHECK_UNARY_FALSE(...) DOCTEST_FUNC_EMPTY
   2732 #define DOCTEST_REQUIRE_UNARY_FALSE(...) DOCTEST_FUNC_EMPTY
   2733 
   2734 #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
   2735 
   2736 #define DOCTEST_WARN_THROWS(...) DOCTEST_FUNC_EMPTY
   2737 #define DOCTEST_CHECK_THROWS(...) DOCTEST_FUNC_EMPTY
   2738 #define DOCTEST_REQUIRE_THROWS(...) DOCTEST_FUNC_EMPTY
   2739 #define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_FUNC_EMPTY
   2740 #define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_FUNC_EMPTY
   2741 #define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_FUNC_EMPTY
   2742 #define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_FUNC_EMPTY
   2743 #define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_FUNC_EMPTY
   2744 #define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_FUNC_EMPTY
   2745 #define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_FUNC_EMPTY
   2746 #define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) DOCTEST_FUNC_EMPTY
   2747 #define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) DOCTEST_FUNC_EMPTY
   2748 #define DOCTEST_WARN_NOTHROW(...) DOCTEST_FUNC_EMPTY
   2749 #define DOCTEST_CHECK_NOTHROW(...) DOCTEST_FUNC_EMPTY
   2750 #define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_FUNC_EMPTY
   2751 
   2752 #define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY
   2753 #define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY
   2754 #define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY
   2755 #define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_EMPTY
   2756 #define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_EMPTY
   2757 #define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_EMPTY
   2758 #define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_EMPTY
   2759 #define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_EMPTY
   2760 #define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_EMPTY
   2761 #define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_EMPTY
   2762 #define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_EMPTY
   2763 #define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_EMPTY
   2764 #define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY
   2765 #define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY
   2766 #define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY
   2767 
   2768 #endif // DOCTEST_CONFIG_NO_EXCEPTIONS
   2769 
   2770 #endif // DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED
   2771 
   2772 #endif // DOCTEST_CONFIG_DISABLE
   2773 
   2774 #ifdef DOCTEST_CONFIG_NO_EXCEPTIONS
   2775 
   2776 #ifdef DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS
   2777 #define DOCTEST_EXCEPTION_EMPTY_FUNC DOCTEST_FUNC_EMPTY
   2778 #else // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS
   2779 #define DOCTEST_EXCEPTION_EMPTY_FUNC [] { static_assert(false, "Exceptions are disabled! " \
   2780     "Use DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS if you want to compile with exceptions disabled."); return false; }()
   2781 
   2782 #undef DOCTEST_REQUIRE
   2783 #undef DOCTEST_REQUIRE_FALSE
   2784 #undef DOCTEST_REQUIRE_MESSAGE
   2785 #undef DOCTEST_REQUIRE_FALSE_MESSAGE
   2786 #undef DOCTEST_REQUIRE_EQ
   2787 #undef DOCTEST_REQUIRE_NE
   2788 #undef DOCTEST_REQUIRE_GT
   2789 #undef DOCTEST_REQUIRE_LT
   2790 #undef DOCTEST_REQUIRE_GE
   2791 #undef DOCTEST_REQUIRE_LE
   2792 #undef DOCTEST_REQUIRE_UNARY
   2793 #undef DOCTEST_REQUIRE_UNARY_FALSE
   2794 
   2795 #define DOCTEST_REQUIRE DOCTEST_EXCEPTION_EMPTY_FUNC
   2796 #define DOCTEST_REQUIRE_FALSE DOCTEST_EXCEPTION_EMPTY_FUNC
   2797 #define DOCTEST_REQUIRE_MESSAGE DOCTEST_EXCEPTION_EMPTY_FUNC
   2798 #define DOCTEST_REQUIRE_FALSE_MESSAGE DOCTEST_EXCEPTION_EMPTY_FUNC
   2799 #define DOCTEST_REQUIRE_EQ DOCTEST_EXCEPTION_EMPTY_FUNC
   2800 #define DOCTEST_REQUIRE_NE DOCTEST_EXCEPTION_EMPTY_FUNC
   2801 #define DOCTEST_REQUIRE_GT DOCTEST_EXCEPTION_EMPTY_FUNC
   2802 #define DOCTEST_REQUIRE_LT DOCTEST_EXCEPTION_EMPTY_FUNC
   2803 #define DOCTEST_REQUIRE_GE DOCTEST_EXCEPTION_EMPTY_FUNC
   2804 #define DOCTEST_REQUIRE_LE DOCTEST_EXCEPTION_EMPTY_FUNC
   2805 #define DOCTEST_REQUIRE_UNARY DOCTEST_EXCEPTION_EMPTY_FUNC
   2806 #define DOCTEST_REQUIRE_UNARY_FALSE DOCTEST_EXCEPTION_EMPTY_FUNC
   2807 
   2808 #endif // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS
   2809 
   2810 #define DOCTEST_WARN_THROWS(...) DOCTEST_EXCEPTION_EMPTY_FUNC
   2811 #define DOCTEST_CHECK_THROWS(...) DOCTEST_EXCEPTION_EMPTY_FUNC
   2812 #define DOCTEST_REQUIRE_THROWS(...) DOCTEST_EXCEPTION_EMPTY_FUNC
   2813 #define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
   2814 #define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
   2815 #define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
   2816 #define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
   2817 #define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
   2818 #define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
   2819 #define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
   2820 #define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
   2821 #define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
   2822 #define DOCTEST_WARN_NOTHROW(...) DOCTEST_EXCEPTION_EMPTY_FUNC
   2823 #define DOCTEST_CHECK_NOTHROW(...) DOCTEST_EXCEPTION_EMPTY_FUNC
   2824 #define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_EXCEPTION_EMPTY_FUNC
   2825 
   2826 #define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
   2827 #define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
   2828 #define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
   2829 #define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
   2830 #define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
   2831 #define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
   2832 #define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
   2833 #define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
   2834 #define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
   2835 #define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
   2836 #define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
   2837 #define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
   2838 #define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
   2839 #define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
   2840 #define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
   2841 
   2842 #endif // DOCTEST_CONFIG_NO_EXCEPTIONS
   2843 
   2844 // clang-format off
   2845 // KEPT FOR BACKWARDS COMPATIBILITY - FORWARDING TO THE RIGHT MACROS
   2846 #define DOCTEST_FAST_WARN_EQ             DOCTEST_WARN_EQ
   2847 #define DOCTEST_FAST_CHECK_EQ            DOCTEST_CHECK_EQ
   2848 #define DOCTEST_FAST_REQUIRE_EQ          DOCTEST_REQUIRE_EQ
   2849 #define DOCTEST_FAST_WARN_NE             DOCTEST_WARN_NE
   2850 #define DOCTEST_FAST_CHECK_NE            DOCTEST_CHECK_NE
   2851 #define DOCTEST_FAST_REQUIRE_NE          DOCTEST_REQUIRE_NE
   2852 #define DOCTEST_FAST_WARN_GT             DOCTEST_WARN_GT
   2853 #define DOCTEST_FAST_CHECK_GT            DOCTEST_CHECK_GT
   2854 #define DOCTEST_FAST_REQUIRE_GT          DOCTEST_REQUIRE_GT
   2855 #define DOCTEST_FAST_WARN_LT             DOCTEST_WARN_LT
   2856 #define DOCTEST_FAST_CHECK_LT            DOCTEST_CHECK_LT
   2857 #define DOCTEST_FAST_REQUIRE_LT          DOCTEST_REQUIRE_LT
   2858 #define DOCTEST_FAST_WARN_GE             DOCTEST_WARN_GE
   2859 #define DOCTEST_FAST_CHECK_GE            DOCTEST_CHECK_GE
   2860 #define DOCTEST_FAST_REQUIRE_GE          DOCTEST_REQUIRE_GE
   2861 #define DOCTEST_FAST_WARN_LE             DOCTEST_WARN_LE
   2862 #define DOCTEST_FAST_CHECK_LE            DOCTEST_CHECK_LE
   2863 #define DOCTEST_FAST_REQUIRE_LE          DOCTEST_REQUIRE_LE
   2864 
   2865 #define DOCTEST_FAST_WARN_UNARY          DOCTEST_WARN_UNARY
   2866 #define DOCTEST_FAST_CHECK_UNARY         DOCTEST_CHECK_UNARY
   2867 #define DOCTEST_FAST_REQUIRE_UNARY       DOCTEST_REQUIRE_UNARY
   2868 #define DOCTEST_FAST_WARN_UNARY_FALSE    DOCTEST_WARN_UNARY_FALSE
   2869 #define DOCTEST_FAST_CHECK_UNARY_FALSE   DOCTEST_CHECK_UNARY_FALSE
   2870 #define DOCTEST_FAST_REQUIRE_UNARY_FALSE DOCTEST_REQUIRE_UNARY_FALSE
   2871 
   2872 #define DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id,__VA_ARGS__)
   2873 // clang-format on
   2874 
   2875 // BDD style macros
   2876 // clang-format off
   2877 #define DOCTEST_SCENARIO(name) DOCTEST_TEST_CASE("  Scenario: " name)
   2878 #define DOCTEST_SCENARIO_CLASS(name) DOCTEST_TEST_CASE_CLASS("  Scenario: " name)
   2879 #define DOCTEST_SCENARIO_TEMPLATE(name, T, ...)  DOCTEST_TEST_CASE_TEMPLATE("  Scenario: " name, T, __VA_ARGS__)
   2880 #define DOCTEST_SCENARIO_TEMPLATE_DEFINE(name, T, id) DOCTEST_TEST_CASE_TEMPLATE_DEFINE("  Scenario: " name, T, id)
   2881 
   2882 #define DOCTEST_GIVEN(name)     DOCTEST_SUBCASE("   Given: " name)
   2883 #define DOCTEST_WHEN(name)      DOCTEST_SUBCASE("    When: " name)
   2884 #define DOCTEST_AND_WHEN(name)  DOCTEST_SUBCASE("And when: " name)
   2885 #define DOCTEST_THEN(name)      DOCTEST_SUBCASE("    Then: " name)
   2886 #define DOCTEST_AND_THEN(name)  DOCTEST_SUBCASE("     And: " name)
   2887 // clang-format on
   2888 
   2889 // == SHORT VERSIONS OF THE MACROS
   2890 #ifndef DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES
   2891 
   2892 #define TEST_CASE(name) DOCTEST_TEST_CASE(name)
   2893 #define TEST_CASE_CLASS(name) DOCTEST_TEST_CASE_CLASS(name)
   2894 #define TEST_CASE_FIXTURE(x, name) DOCTEST_TEST_CASE_FIXTURE(x, name)
   2895 #define TYPE_TO_STRING_AS(str, ...) DOCTEST_TYPE_TO_STRING_AS(str, __VA_ARGS__)
   2896 #define TYPE_TO_STRING(...) DOCTEST_TYPE_TO_STRING(__VA_ARGS__)
   2897 #define TEST_CASE_TEMPLATE(name, T, ...) DOCTEST_TEST_CASE_TEMPLATE(name, T, __VA_ARGS__)
   2898 #define TEST_CASE_TEMPLATE_DEFINE(name, T, id) DOCTEST_TEST_CASE_TEMPLATE_DEFINE(name, T, id)
   2899 #define TEST_CASE_TEMPLATE_INVOKE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, __VA_ARGS__)
   2900 #define TEST_CASE_TEMPLATE_APPLY(id, ...) DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, __VA_ARGS__)
   2901 #define SUBCASE(name) DOCTEST_SUBCASE(name)
   2902 #define TEST_SUITE(decorators) DOCTEST_TEST_SUITE(decorators)
   2903 #define TEST_SUITE_BEGIN(name) DOCTEST_TEST_SUITE_BEGIN(name)
   2904 #define TEST_SUITE_END DOCTEST_TEST_SUITE_END
   2905 #define REGISTER_EXCEPTION_TRANSLATOR(signature) DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature)
   2906 #define REGISTER_REPORTER(name, priority, reporter) DOCTEST_REGISTER_REPORTER(name, priority, reporter)
   2907 #define REGISTER_LISTENER(name, priority, reporter) DOCTEST_REGISTER_LISTENER(name, priority, reporter)
   2908 #define INFO(...) DOCTEST_INFO(__VA_ARGS__)
   2909 #define CAPTURE(x) DOCTEST_CAPTURE(x)
   2910 #define ADD_MESSAGE_AT(file, line, ...) DOCTEST_ADD_MESSAGE_AT(file, line, __VA_ARGS__)
   2911 #define ADD_FAIL_CHECK_AT(file, line, ...) DOCTEST_ADD_FAIL_CHECK_AT(file, line, __VA_ARGS__)
   2912 #define ADD_FAIL_AT(file, line, ...) DOCTEST_ADD_FAIL_AT(file, line, __VA_ARGS__)
   2913 #define MESSAGE(...) DOCTEST_MESSAGE(__VA_ARGS__)
   2914 #define FAIL_CHECK(...) DOCTEST_FAIL_CHECK(__VA_ARGS__)
   2915 #define FAIL(...) DOCTEST_FAIL(__VA_ARGS__)
   2916 #define TO_LVALUE(...) DOCTEST_TO_LVALUE(__VA_ARGS__)
   2917 
   2918 #define WARN(...) DOCTEST_WARN(__VA_ARGS__)
   2919 #define WARN_FALSE(...) DOCTEST_WARN_FALSE(__VA_ARGS__)
   2920 #define WARN_THROWS(...) DOCTEST_WARN_THROWS(__VA_ARGS__)
   2921 #define WARN_THROWS_AS(expr, ...) DOCTEST_WARN_THROWS_AS(expr, __VA_ARGS__)
   2922 #define WARN_THROWS_WITH(expr, ...) DOCTEST_WARN_THROWS_WITH(expr, __VA_ARGS__)
   2923 #define WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_WARN_THROWS_WITH_AS(expr, with, __VA_ARGS__)
   2924 #define WARN_NOTHROW(...) DOCTEST_WARN_NOTHROW(__VA_ARGS__)
   2925 #define CHECK(...) DOCTEST_CHECK(__VA_ARGS__)
   2926 #define CHECK_FALSE(...) DOCTEST_CHECK_FALSE(__VA_ARGS__)
   2927 #define CHECK_THROWS(...) DOCTEST_CHECK_THROWS(__VA_ARGS__)
   2928 #define CHECK_THROWS_AS(expr, ...) DOCTEST_CHECK_THROWS_AS(expr, __VA_ARGS__)
   2929 #define CHECK_THROWS_WITH(expr, ...) DOCTEST_CHECK_THROWS_WITH(expr, __VA_ARGS__)
   2930 #define CHECK_THROWS_WITH_AS(expr, with, ...) DOCTEST_CHECK_THROWS_WITH_AS(expr, with, __VA_ARGS__)
   2931 #define CHECK_NOTHROW(...) DOCTEST_CHECK_NOTHROW(__VA_ARGS__)
   2932 #define REQUIRE(...) DOCTEST_REQUIRE(__VA_ARGS__)
   2933 #define REQUIRE_FALSE(...) DOCTEST_REQUIRE_FALSE(__VA_ARGS__)
   2934 #define REQUIRE_THROWS(...) DOCTEST_REQUIRE_THROWS(__VA_ARGS__)
   2935 #define REQUIRE_THROWS_AS(expr, ...) DOCTEST_REQUIRE_THROWS_AS(expr, __VA_ARGS__)
   2936 #define REQUIRE_THROWS_WITH(expr, ...) DOCTEST_REQUIRE_THROWS_WITH(expr, __VA_ARGS__)
   2937 #define REQUIRE_THROWS_WITH_AS(expr, with, ...) DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, __VA_ARGS__)
   2938 #define REQUIRE_NOTHROW(...) DOCTEST_REQUIRE_NOTHROW(__VA_ARGS__)
   2939 
   2940 #define WARN_MESSAGE(cond, ...) DOCTEST_WARN_MESSAGE(cond, __VA_ARGS__)
   2941 #define WARN_FALSE_MESSAGE(cond, ...) DOCTEST_WARN_FALSE_MESSAGE(cond, __VA_ARGS__)
   2942 #define WARN_THROWS_MESSAGE(expr, ...) DOCTEST_WARN_THROWS_MESSAGE(expr, __VA_ARGS__)
   2943 #define WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__)
   2944 #define WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__)
   2945 #define WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__)
   2946 #define WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_WARN_NOTHROW_MESSAGE(expr, __VA_ARGS__)
   2947 #define CHECK_MESSAGE(cond, ...) DOCTEST_CHECK_MESSAGE(cond, __VA_ARGS__)
   2948 #define CHECK_FALSE_MESSAGE(cond, ...) DOCTEST_CHECK_FALSE_MESSAGE(cond, __VA_ARGS__)
   2949 #define CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_CHECK_THROWS_MESSAGE(expr, __VA_ARGS__)
   2950 #define CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__)
   2951 #define CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__)
   2952 #define CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__)
   2953 #define CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_CHECK_NOTHROW_MESSAGE(expr, __VA_ARGS__)
   2954 #define REQUIRE_MESSAGE(cond, ...) DOCTEST_REQUIRE_MESSAGE(cond, __VA_ARGS__)
   2955 #define REQUIRE_FALSE_MESSAGE(cond, ...) DOCTEST_REQUIRE_FALSE_MESSAGE(cond, __VA_ARGS__)
   2956 #define REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_REQUIRE_THROWS_MESSAGE(expr, __VA_ARGS__)
   2957 #define REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__)
   2958 #define REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__)
   2959 #define REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__)
   2960 #define REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, __VA_ARGS__)
   2961 
   2962 #define SCENARIO(name) DOCTEST_SCENARIO(name)
   2963 #define SCENARIO_CLASS(name) DOCTEST_SCENARIO_CLASS(name)
   2964 #define SCENARIO_TEMPLATE(name, T, ...) DOCTEST_SCENARIO_TEMPLATE(name, T, __VA_ARGS__)
   2965 #define SCENARIO_TEMPLATE_DEFINE(name, T, id) DOCTEST_SCENARIO_TEMPLATE_DEFINE(name, T, id)
   2966 #define GIVEN(name) DOCTEST_GIVEN(name)
   2967 #define WHEN(name) DOCTEST_WHEN(name)
   2968 #define AND_WHEN(name) DOCTEST_AND_WHEN(name)
   2969 #define THEN(name) DOCTEST_THEN(name)
   2970 #define AND_THEN(name) DOCTEST_AND_THEN(name)
   2971 
   2972 #define WARN_EQ(...) DOCTEST_WARN_EQ(__VA_ARGS__)
   2973 #define CHECK_EQ(...) DOCTEST_CHECK_EQ(__VA_ARGS__)
   2974 #define REQUIRE_EQ(...) DOCTEST_REQUIRE_EQ(__VA_ARGS__)
   2975 #define WARN_NE(...) DOCTEST_WARN_NE(__VA_ARGS__)
   2976 #define CHECK_NE(...) DOCTEST_CHECK_NE(__VA_ARGS__)
   2977 #define REQUIRE_NE(...) DOCTEST_REQUIRE_NE(__VA_ARGS__)
   2978 #define WARN_GT(...) DOCTEST_WARN_GT(__VA_ARGS__)
   2979 #define CHECK_GT(...) DOCTEST_CHECK_GT(__VA_ARGS__)
   2980 #define REQUIRE_GT(...) DOCTEST_REQUIRE_GT(__VA_ARGS__)
   2981 #define WARN_LT(...) DOCTEST_WARN_LT(__VA_ARGS__)
   2982 #define CHECK_LT(...) DOCTEST_CHECK_LT(__VA_ARGS__)
   2983 #define REQUIRE_LT(...) DOCTEST_REQUIRE_LT(__VA_ARGS__)
   2984 #define WARN_GE(...) DOCTEST_WARN_GE(__VA_ARGS__)
   2985 #define CHECK_GE(...) DOCTEST_CHECK_GE(__VA_ARGS__)
   2986 #define REQUIRE_GE(...) DOCTEST_REQUIRE_GE(__VA_ARGS__)
   2987 #define WARN_LE(...) DOCTEST_WARN_LE(__VA_ARGS__)
   2988 #define CHECK_LE(...) DOCTEST_CHECK_LE(__VA_ARGS__)
   2989 #define REQUIRE_LE(...) DOCTEST_REQUIRE_LE(__VA_ARGS__)
   2990 #define WARN_UNARY(...) DOCTEST_WARN_UNARY(__VA_ARGS__)
   2991 #define CHECK_UNARY(...) DOCTEST_CHECK_UNARY(__VA_ARGS__)
   2992 #define REQUIRE_UNARY(...) DOCTEST_REQUIRE_UNARY(__VA_ARGS__)
   2993 #define WARN_UNARY_FALSE(...) DOCTEST_WARN_UNARY_FALSE(__VA_ARGS__)
   2994 #define CHECK_UNARY_FALSE(...) DOCTEST_CHECK_UNARY_FALSE(__VA_ARGS__)
   2995 #define REQUIRE_UNARY_FALSE(...) DOCTEST_REQUIRE_UNARY_FALSE(__VA_ARGS__)
   2996 
   2997 // KEPT FOR BACKWARDS COMPATIBILITY
   2998 #define FAST_WARN_EQ(...) DOCTEST_FAST_WARN_EQ(__VA_ARGS__)
   2999 #define FAST_CHECK_EQ(...) DOCTEST_FAST_CHECK_EQ(__VA_ARGS__)
   3000 #define FAST_REQUIRE_EQ(...) DOCTEST_FAST_REQUIRE_EQ(__VA_ARGS__)
   3001 #define FAST_WARN_NE(...) DOCTEST_FAST_WARN_NE(__VA_ARGS__)
   3002 #define FAST_CHECK_NE(...) DOCTEST_FAST_CHECK_NE(__VA_ARGS__)
   3003 #define FAST_REQUIRE_NE(...) DOCTEST_FAST_REQUIRE_NE(__VA_ARGS__)
   3004 #define FAST_WARN_GT(...) DOCTEST_FAST_WARN_GT(__VA_ARGS__)
   3005 #define FAST_CHECK_GT(...) DOCTEST_FAST_CHECK_GT(__VA_ARGS__)
   3006 #define FAST_REQUIRE_GT(...) DOCTEST_FAST_REQUIRE_GT(__VA_ARGS__)
   3007 #define FAST_WARN_LT(...) DOCTEST_FAST_WARN_LT(__VA_ARGS__)
   3008 #define FAST_CHECK_LT(...) DOCTEST_FAST_CHECK_LT(__VA_ARGS__)
   3009 #define FAST_REQUIRE_LT(...) DOCTEST_FAST_REQUIRE_LT(__VA_ARGS__)
   3010 #define FAST_WARN_GE(...) DOCTEST_FAST_WARN_GE(__VA_ARGS__)
   3011 #define FAST_CHECK_GE(...) DOCTEST_FAST_CHECK_GE(__VA_ARGS__)
   3012 #define FAST_REQUIRE_GE(...) DOCTEST_FAST_REQUIRE_GE(__VA_ARGS__)
   3013 #define FAST_WARN_LE(...) DOCTEST_FAST_WARN_LE(__VA_ARGS__)
   3014 #define FAST_CHECK_LE(...) DOCTEST_FAST_CHECK_LE(__VA_ARGS__)
   3015 #define FAST_REQUIRE_LE(...) DOCTEST_FAST_REQUIRE_LE(__VA_ARGS__)
   3016 
   3017 #define FAST_WARN_UNARY(...) DOCTEST_FAST_WARN_UNARY(__VA_ARGS__)
   3018 #define FAST_CHECK_UNARY(...) DOCTEST_FAST_CHECK_UNARY(__VA_ARGS__)
   3019 #define FAST_REQUIRE_UNARY(...) DOCTEST_FAST_REQUIRE_UNARY(__VA_ARGS__)
   3020 #define FAST_WARN_UNARY_FALSE(...) DOCTEST_FAST_WARN_UNARY_FALSE(__VA_ARGS__)
   3021 #define FAST_CHECK_UNARY_FALSE(...) DOCTEST_FAST_CHECK_UNARY_FALSE(__VA_ARGS__)
   3022 #define FAST_REQUIRE_UNARY_FALSE(...) DOCTEST_FAST_REQUIRE_UNARY_FALSE(__VA_ARGS__)
   3023 
   3024 #define TEST_CASE_TEMPLATE_INSTANTIATE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE(id, __VA_ARGS__)
   3025 
   3026 #endif // DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES
   3027 
   3028 #ifndef DOCTEST_CONFIG_DISABLE
   3029 
   3030 // this is here to clear the 'current test suite' for the current translation unit - at the top
   3031 DOCTEST_TEST_SUITE_END();
   3032 
   3033 #endif // DOCTEST_CONFIG_DISABLE
   3034 
   3035 DOCTEST_CLANG_SUPPRESS_WARNING_POP
   3036 DOCTEST_MSVC_SUPPRESS_WARNING_POP
   3037 DOCTEST_GCC_SUPPRESS_WARNING_POP
   3038 
   3039 DOCTEST_SUPPRESS_COMMON_WARNINGS_POP
   3040 
   3041 #endif // DOCTEST_LIBRARY_INCLUDED
   3042 
   3043 #ifndef DOCTEST_SINGLE_HEADER
   3044 #define DOCTEST_SINGLE_HEADER
   3045 #endif // DOCTEST_SINGLE_HEADER
   3046 
   3047 #if defined(DOCTEST_CONFIG_IMPLEMENT) || !defined(DOCTEST_SINGLE_HEADER)
   3048 
   3049 #ifndef DOCTEST_SINGLE_HEADER
   3050 #include "doctest_fwd.h"
   3051 #endif // DOCTEST_SINGLE_HEADER
   3052 
   3053 DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-macros")
   3054 
   3055 #ifndef DOCTEST_LIBRARY_IMPLEMENTATION
   3056 #define DOCTEST_LIBRARY_IMPLEMENTATION
   3057 
   3058 DOCTEST_CLANG_SUPPRESS_WARNING_POP
   3059 
   3060 DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH
   3061 
   3062 DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
   3063 DOCTEST_CLANG_SUPPRESS_WARNING("-Wglobal-constructors")
   3064 DOCTEST_CLANG_SUPPRESS_WARNING("-Wexit-time-destructors")
   3065 DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-conversion")
   3066 DOCTEST_CLANG_SUPPRESS_WARNING("-Wshorten-64-to-32")
   3067 DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-variable-declarations")
   3068 DOCTEST_CLANG_SUPPRESS_WARNING("-Wswitch")
   3069 DOCTEST_CLANG_SUPPRESS_WARNING("-Wswitch-enum")
   3070 DOCTEST_CLANG_SUPPRESS_WARNING("-Wcovered-switch-default")
   3071 DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-noreturn")
   3072 DOCTEST_CLANG_SUPPRESS_WARNING("-Wdisabled-macro-expansion")
   3073 DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-braces")
   3074 DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-field-initializers")
   3075 DOCTEST_CLANG_SUPPRESS_WARNING("-Wunused-member-function")
   3076 DOCTEST_CLANG_SUPPRESS_WARNING("-Wnonportable-system-include-path")
   3077 
   3078 DOCTEST_GCC_SUPPRESS_WARNING_PUSH
   3079 DOCTEST_GCC_SUPPRESS_WARNING("-Wconversion")
   3080 DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-conversion")
   3081 DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-field-initializers")
   3082 DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-braces")
   3083 DOCTEST_GCC_SUPPRESS_WARNING("-Wswitch")
   3084 DOCTEST_GCC_SUPPRESS_WARNING("-Wswitch-enum")
   3085 DOCTEST_GCC_SUPPRESS_WARNING("-Wswitch-default")
   3086 DOCTEST_GCC_SUPPRESS_WARNING("-Wunsafe-loop-optimizations")
   3087 DOCTEST_GCC_SUPPRESS_WARNING("-Wold-style-cast")
   3088 DOCTEST_GCC_SUPPRESS_WARNING("-Wunused-function")
   3089 DOCTEST_GCC_SUPPRESS_WARNING("-Wmultiple-inheritance")
   3090 DOCTEST_GCC_SUPPRESS_WARNING("-Wsuggest-attribute")
   3091 
   3092 DOCTEST_MSVC_SUPPRESS_WARNING_PUSH
   3093 DOCTEST_MSVC_SUPPRESS_WARNING(4267) // 'var' : conversion from 'x' to 'y', possible loss of data
   3094 DOCTEST_MSVC_SUPPRESS_WARNING(4530) // C++ exception handler used, but unwind semantics not enabled
   3095 DOCTEST_MSVC_SUPPRESS_WARNING(4577) // 'noexcept' used with no exception handling mode specified
   3096 DOCTEST_MSVC_SUPPRESS_WARNING(4774) // format string expected in argument is not a string literal
   3097 DOCTEST_MSVC_SUPPRESS_WARNING(4365) // conversion from 'int' to 'unsigned', signed/unsigned mismatch
   3098 DOCTEST_MSVC_SUPPRESS_WARNING(5039) // pointer to potentially throwing function passed to extern C
   3099 DOCTEST_MSVC_SUPPRESS_WARNING(4800) // forcing value to bool 'true' or 'false' (performance warning)
   3100 DOCTEST_MSVC_SUPPRESS_WARNING(5245) // unreferenced function with internal linkage has been removed
   3101 
   3102 DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN
   3103 
   3104 // required includes - will go only in one translation unit!
   3105 #include <ctime>
   3106 #include <cmath>
   3107 #include <climits>
   3108 // borland (Embarcadero) compiler requires math.h and not cmath - https://github.com/doctest/doctest/pull/37
   3109 #ifdef __BORLANDC__
   3110 #include <math.h>
   3111 #endif // __BORLANDC__
   3112 #include <new>
   3113 #include <cstdio>
   3114 #include <cstdlib>
   3115 #include <cstring>
   3116 #include <limits>
   3117 #include <utility>
   3118 #include <fstream>
   3119 #include <sstream>
   3120 #include <iostream>
   3121 #include <algorithm>
   3122 #include <iomanip>
   3123 #include <vector>
   3124 #ifndef DOCTEST_CONFIG_NO_MULTITHREADING
   3125 #include <atomic>
   3126 #include <mutex>
   3127 #define DOCTEST_DECLARE_MUTEX(name) std::mutex name;
   3128 #define DOCTEST_DECLARE_STATIC_MUTEX(name) static DOCTEST_DECLARE_MUTEX(name)
   3129 #define DOCTEST_LOCK_MUTEX(name) std::lock_guard<std::mutex> DOCTEST_ANONYMOUS(DOCTEST_ANON_LOCK_)(name);
   3130 #else // DOCTEST_CONFIG_NO_MULTITHREADING
   3131 #define DOCTEST_DECLARE_MUTEX(name)
   3132 #define DOCTEST_DECLARE_STATIC_MUTEX(name)
   3133 #define DOCTEST_LOCK_MUTEX(name)
   3134 #endif // DOCTEST_CONFIG_NO_MULTITHREADING
   3135 #include <set>
   3136 #include <map>
   3137 #include <unordered_set>
   3138 #include <exception>
   3139 #include <stdexcept>
   3140 #include <csignal>
   3141 #include <cfloat>
   3142 #include <cctype>
   3143 #include <cstdint>
   3144 #include <string>
   3145 
   3146 #ifdef DOCTEST_PLATFORM_MAC
   3147 #include <sys/types.h>
   3148 #include <unistd.h>
   3149 #include <sys/sysctl.h>
   3150 #endif // DOCTEST_PLATFORM_MAC
   3151 
   3152 #ifdef DOCTEST_PLATFORM_WINDOWS
   3153 
   3154 // defines for a leaner windows.h
   3155 #ifndef WIN32_LEAN_AND_MEAN
   3156 #define WIN32_LEAN_AND_MEAN
   3157 #endif // WIN32_LEAN_AND_MEAN
   3158 #ifndef NOMINMAX
   3159 #define NOMINMAX
   3160 #endif // NOMINMAX
   3161 
   3162 // not sure what AfxWin.h is for - here I do what Catch does
   3163 #ifdef __AFXDLL
   3164 #include <AfxWin.h>
   3165 #else
   3166 #include <windows.h>
   3167 #endif
   3168 #include <io.h>
   3169 
   3170 #else // DOCTEST_PLATFORM_WINDOWS
   3171 
   3172 #include <sys/time.h>
   3173 #include <unistd.h>
   3174 
   3175 #endif // DOCTEST_PLATFORM_WINDOWS
   3176 
   3177 // this is a fix for https://github.com/doctest/doctest/issues/348
   3178 // https://mail.gnome.org/archives/xml/2012-January/msg00000.html
   3179 #if !defined(HAVE_UNISTD_H) && !defined(STDOUT_FILENO)
   3180 #define STDOUT_FILENO fileno(stdout)
   3181 #endif // HAVE_UNISTD_H
   3182 
   3183 DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END
   3184 
   3185 // counts the number of elements in a C array
   3186 #define DOCTEST_COUNTOF(x) (sizeof(x) / sizeof(x[0]))
   3187 
   3188 #ifdef DOCTEST_CONFIG_DISABLE
   3189 #define DOCTEST_BRANCH_ON_DISABLED(if_disabled, if_not_disabled) if_disabled
   3190 #else // DOCTEST_CONFIG_DISABLE
   3191 #define DOCTEST_BRANCH_ON_DISABLED(if_disabled, if_not_disabled) if_not_disabled
   3192 #endif // DOCTEST_CONFIG_DISABLE
   3193 
   3194 #ifndef DOCTEST_CONFIG_OPTIONS_PREFIX
   3195 #define DOCTEST_CONFIG_OPTIONS_PREFIX "dt-"
   3196 #endif
   3197 
   3198 #ifndef DOCTEST_THREAD_LOCAL
   3199 #if defined(DOCTEST_CONFIG_NO_MULTITHREADING) || DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0))
   3200 #define DOCTEST_THREAD_LOCAL
   3201 #else // DOCTEST_MSVC
   3202 #define DOCTEST_THREAD_LOCAL thread_local
   3203 #endif // DOCTEST_MSVC
   3204 #endif // DOCTEST_THREAD_LOCAL
   3205 
   3206 #ifndef DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES
   3207 #define DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES 32
   3208 #endif
   3209 
   3210 #ifndef DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE
   3211 #define DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE 64
   3212 #endif
   3213 
   3214 #ifdef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
   3215 #define DOCTEST_OPTIONS_PREFIX_DISPLAY DOCTEST_CONFIG_OPTIONS_PREFIX
   3216 #else
   3217 #define DOCTEST_OPTIONS_PREFIX_DISPLAY ""
   3218 #endif
   3219 
   3220 #if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
   3221 #define DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS
   3222 #endif
   3223 
   3224 #ifndef DOCTEST_CDECL
   3225 #define DOCTEST_CDECL __cdecl
   3226 #endif
   3227 
   3228 namespace doctest {
   3229 
   3230 bool is_running_in_test = false;
   3231 
   3232 namespace {
   3233     using namespace detail;
   3234 
   3235     template <typename Ex>
   3236     DOCTEST_NORETURN void throw_exception(Ex const& e) {
   3237 #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
   3238         throw e;
   3239 #else  // DOCTEST_CONFIG_NO_EXCEPTIONS
   3240         std::cerr << "doctest will terminate because it needed to throw an exception.\n"
   3241                   << "The message was: " << e.what() << '\n';
   3242         std::terminate();
   3243 #endif // DOCTEST_CONFIG_NO_EXCEPTIONS
   3244     }
   3245 
   3246 #ifndef DOCTEST_INTERNAL_ERROR
   3247 #define DOCTEST_INTERNAL_ERROR(msg)                                                                \
   3248     throw_exception(std::logic_error(                                                              \
   3249             __FILE__ ":" DOCTEST_TOSTR(__LINE__) ": Internal doctest error: " msg))
   3250 #endif // DOCTEST_INTERNAL_ERROR
   3251 
   3252     // case insensitive strcmp
   3253     int stricmp(const char* a, const char* b) {
   3254         for(;; a++, b++) {
   3255             const int d = tolower(*a) - tolower(*b);
   3256             if(d != 0 || !*a)
   3257                 return d;
   3258         }
   3259     }
   3260 
   3261     struct Endianness
   3262     {
   3263         enum Arch
   3264         {
   3265             Big,
   3266             Little
   3267         };
   3268 
   3269         static Arch which() {
   3270             int x = 1;
   3271             // casting any data pointer to char* is allowed
   3272             auto ptr = reinterpret_cast<char*>(&x);
   3273             if(*ptr)
   3274                 return Little;
   3275             return Big;
   3276         }
   3277     };
   3278 } // namespace
   3279 
   3280 namespace detail {
   3281     DOCTEST_THREAD_LOCAL class
   3282     {
   3283         std::vector<std::streampos> stack;
   3284         std::stringstream           ss;
   3285 
   3286     public:
   3287         std::ostream* push() {
   3288             stack.push_back(ss.tellp());
   3289             return &ss;
   3290         }
   3291 
   3292         String pop() {
   3293             if (stack.empty())
   3294                 DOCTEST_INTERNAL_ERROR("TLSS was empty when trying to pop!");
   3295 
   3296             std::streampos pos = stack.back();
   3297             stack.pop_back();
   3298             unsigned sz = static_cast<unsigned>(ss.tellp() - pos);
   3299             ss.rdbuf()->pubseekpos(pos, std::ios::in | std::ios::out);
   3300             return String(ss, sz);
   3301         }
   3302     } g_oss;
   3303 
   3304     std::ostream* tlssPush() {
   3305         return g_oss.push();
   3306     }
   3307 
   3308     String tlssPop() {
   3309         return g_oss.pop();
   3310     }
   3311 
   3312 #ifndef DOCTEST_CONFIG_DISABLE
   3313 
   3314 namespace timer_large_integer
   3315 {
   3316     
   3317 #if defined(DOCTEST_PLATFORM_WINDOWS)
   3318     using type = ULONGLONG;
   3319 #else // DOCTEST_PLATFORM_WINDOWS
   3320     using type = std::uint64_t;
   3321 #endif // DOCTEST_PLATFORM_WINDOWS
   3322 }
   3323 
   3324 using ticks_t = timer_large_integer::type;
   3325 
   3326 #ifdef DOCTEST_CONFIG_GETCURRENTTICKS
   3327     ticks_t getCurrentTicks() { return DOCTEST_CONFIG_GETCURRENTTICKS(); }
   3328 #elif defined(DOCTEST_PLATFORM_WINDOWS)
   3329     ticks_t getCurrentTicks() {
   3330         static LARGE_INTEGER hz = { {0} }, hzo = { {0} };
   3331         if(!hz.QuadPart) {
   3332             QueryPerformanceFrequency(&hz);
   3333             QueryPerformanceCounter(&hzo);
   3334         }
   3335         LARGE_INTEGER t;
   3336         QueryPerformanceCounter(&t);
   3337         return ((t.QuadPart - hzo.QuadPart) * LONGLONG(1000000)) / hz.QuadPart;
   3338     }
   3339 #else  // DOCTEST_PLATFORM_WINDOWS
   3340     ticks_t getCurrentTicks() {
   3341         timeval t;
   3342         gettimeofday(&t, nullptr);
   3343         return static_cast<ticks_t>(t.tv_sec) * 1000000 + static_cast<ticks_t>(t.tv_usec);
   3344     }
   3345 #endif // DOCTEST_PLATFORM_WINDOWS
   3346 
   3347     struct Timer
   3348     {
   3349         void         start() { m_ticks = getCurrentTicks(); }
   3350         unsigned int getElapsedMicroseconds() const {
   3351             return static_cast<unsigned int>(getCurrentTicks() - m_ticks);
   3352         }
   3353         //unsigned int getElapsedMilliseconds() const {
   3354         //    return static_cast<unsigned int>(getElapsedMicroseconds() / 1000);
   3355         //}
   3356         double getElapsedSeconds() const { return static_cast<double>(getCurrentTicks() - m_ticks) / 1000000.0; }
   3357 
   3358     private:
   3359         ticks_t m_ticks = 0;
   3360     };
   3361 
   3362 #ifdef DOCTEST_CONFIG_NO_MULTITHREADING
   3363     template <typename T>
   3364     using Atomic = T;
   3365 #else // DOCTEST_CONFIG_NO_MULTITHREADING
   3366     template <typename T>
   3367     using Atomic = std::atomic<T>;
   3368 #endif // DOCTEST_CONFIG_NO_MULTITHREADING
   3369 
   3370 #if defined(DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS) || defined(DOCTEST_CONFIG_NO_MULTITHREADING)
   3371     template <typename T>
   3372     using MultiLaneAtomic = Atomic<T>;
   3373 #else // DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS
   3374     // Provides a multilane implementation of an atomic variable that supports add, sub, load,
   3375     // store. Instead of using a single atomic variable, this splits up into multiple ones,
   3376     // each sitting on a separate cache line. The goal is to provide a speedup when most
   3377     // operations are modifying. It achieves this with two properties:
   3378     //
   3379     // * Multiple atomics are used, so chance of congestion from the same atomic is reduced.
   3380     // * Each atomic sits on a separate cache line, so false sharing is reduced.
   3381     //
   3382     // The disadvantage is that there is a small overhead due to the use of TLS, and load/store
   3383     // is slower because all atomics have to be accessed.
   3384     template <typename T>
   3385     class MultiLaneAtomic
   3386     {
   3387         struct CacheLineAlignedAtomic
   3388         {
   3389             Atomic<T> atomic{};
   3390             char padding[DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE - sizeof(Atomic<T>)];
   3391         };
   3392         CacheLineAlignedAtomic m_atomics[DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES];
   3393 
   3394         static_assert(sizeof(CacheLineAlignedAtomic) == DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE,
   3395                       "guarantee one atomic takes exactly one cache line");
   3396 
   3397     public:
   3398         T operator++() DOCTEST_NOEXCEPT { return fetch_add(1) + 1; }
   3399 
   3400         T operator++(int) DOCTEST_NOEXCEPT { return fetch_add(1); }
   3401 
   3402         T fetch_add(T arg, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT {
   3403             return myAtomic().fetch_add(arg, order);
   3404         }
   3405 
   3406         T fetch_sub(T arg, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT {
   3407             return myAtomic().fetch_sub(arg, order);
   3408         }
   3409 
   3410         operator T() const DOCTEST_NOEXCEPT { return load(); }
   3411 
   3412         T load(std::memory_order order = std::memory_order_seq_cst) const DOCTEST_NOEXCEPT {
   3413             auto result = T();
   3414             for(auto const& c : m_atomics) {
   3415                 result += c.atomic.load(order);
   3416             }
   3417             return result;
   3418         }
   3419 
   3420         T operator=(T desired) DOCTEST_NOEXCEPT { // lgtm [cpp/assignment-does-not-return-this]
   3421             store(desired);
   3422             return desired;
   3423         }
   3424 
   3425         void store(T desired, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT {
   3426             // first value becomes desired", all others become 0.
   3427             for(auto& c : m_atomics) {
   3428                 c.atomic.store(desired, order);
   3429                 desired = {};
   3430             }
   3431         }
   3432 
   3433     private:
   3434         // Each thread has a different atomic that it operates on. If more than NumLanes threads
   3435         // use this, some will use the same atomic. So performance will degrade a bit, but still
   3436         // everything will work.
   3437         //
   3438         // The logic here is a bit tricky. The call should be as fast as possible, so that there
   3439         // is minimal to no overhead in determining the correct atomic for the current thread.
   3440         //
   3441         // 1. A global static counter laneCounter counts continuously up.
   3442         // 2. Each successive thread will use modulo operation of that counter so it gets an atomic
   3443         //    assigned in a round-robin fashion.
   3444         // 3. This tlsLaneIdx is stored in the thread local data, so it is directly available with
   3445         //    little overhead.
   3446         Atomic<T>& myAtomic() DOCTEST_NOEXCEPT {
   3447             static Atomic<size_t> laneCounter;
   3448             DOCTEST_THREAD_LOCAL size_t tlsLaneIdx =
   3449                     laneCounter++ % DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES;
   3450 
   3451             return m_atomics[tlsLaneIdx].atomic;
   3452         }
   3453     };
   3454 #endif // DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS
   3455 
   3456     // this holds both parameters from the command line and runtime data for tests
   3457     struct ContextState : ContextOptions, TestRunStats, CurrentTestCaseStats
   3458     {
   3459         MultiLaneAtomic<int> numAssertsCurrentTest_atomic;
   3460         MultiLaneAtomic<int> numAssertsFailedCurrentTest_atomic;
   3461 
   3462         std::vector<std::vector<String>> filters = decltype(filters)(9); // 9 different filters
   3463 
   3464         std::vector<IReporter*> reporters_currently_used;
   3465 
   3466         assert_handler ah = nullptr;
   3467 
   3468         Timer timer;
   3469 
   3470         std::vector<String> stringifiedContexts; // logging from INFO() due to an exception
   3471 
   3472         // stuff for subcases
   3473         bool reachedLeaf;
   3474         std::vector<SubcaseSignature> subcaseStack;
   3475         std::vector<SubcaseSignature> nextSubcaseStack;
   3476         std::unordered_set<unsigned long long> fullyTraversedSubcases;
   3477         size_t currentSubcaseDepth;
   3478         Atomic<bool> shouldLogCurrentException;
   3479 
   3480         void resetRunData() {
   3481             numTestCases                = 0;
   3482             numTestCasesPassingFilters  = 0;
   3483             numTestSuitesPassingFilters = 0;
   3484             numTestCasesFailed          = 0;
   3485             numAsserts                  = 0;
   3486             numAssertsFailed            = 0;
   3487             numAssertsCurrentTest       = 0;
   3488             numAssertsFailedCurrentTest = 0;
   3489         }
   3490 
   3491         void finalizeTestCaseData() {
   3492             seconds = timer.getElapsedSeconds();
   3493 
   3494             // update the non-atomic counters
   3495             numAsserts += numAssertsCurrentTest_atomic;
   3496             numAssertsFailed += numAssertsFailedCurrentTest_atomic;
   3497             numAssertsCurrentTest       = numAssertsCurrentTest_atomic;
   3498             numAssertsFailedCurrentTest = numAssertsFailedCurrentTest_atomic;
   3499 
   3500             if(numAssertsFailedCurrentTest)
   3501                 failure_flags |= TestCaseFailureReason::AssertFailure;
   3502 
   3503             if(Approx(currentTest->m_timeout).epsilon(DBL_EPSILON) != 0 &&
   3504                Approx(seconds).epsilon(DBL_EPSILON) > currentTest->m_timeout)
   3505                 failure_flags |= TestCaseFailureReason::Timeout;
   3506 
   3507             if(currentTest->m_should_fail) {
   3508                 if(failure_flags) {
   3509                     failure_flags |= TestCaseFailureReason::ShouldHaveFailedAndDid;
   3510                 } else {
   3511                     failure_flags |= TestCaseFailureReason::ShouldHaveFailedButDidnt;
   3512                 }
   3513             } else if(failure_flags && currentTest->m_may_fail) {
   3514                 failure_flags |= TestCaseFailureReason::CouldHaveFailedAndDid;
   3515             } else if(currentTest->m_expected_failures > 0) {
   3516                 if(numAssertsFailedCurrentTest == currentTest->m_expected_failures) {
   3517                     failure_flags |= TestCaseFailureReason::FailedExactlyNumTimes;
   3518                 } else {
   3519                     failure_flags |= TestCaseFailureReason::DidntFailExactlyNumTimes;
   3520                 }
   3521             }
   3522 
   3523             bool ok_to_fail = (TestCaseFailureReason::ShouldHaveFailedAndDid & failure_flags) ||
   3524                               (TestCaseFailureReason::CouldHaveFailedAndDid & failure_flags) ||
   3525                               (TestCaseFailureReason::FailedExactlyNumTimes & failure_flags);
   3526 
   3527             // if any subcase has failed - the whole test case has failed
   3528             testCaseSuccess = !(failure_flags && !ok_to_fail);
   3529             if(!testCaseSuccess)
   3530                 numTestCasesFailed++;
   3531         }
   3532     };
   3533 
   3534     ContextState* g_cs = nullptr;
   3535 
   3536     // used to avoid locks for the debug output
   3537     // TODO: figure out if this is indeed necessary/correct - seems like either there still
   3538     // could be a race or that there wouldn't be a race even if using the context directly
   3539     DOCTEST_THREAD_LOCAL bool g_no_colors;
   3540 
   3541 #endif // DOCTEST_CONFIG_DISABLE
   3542 } // namespace detail
   3543 
   3544 char* String::allocate(size_type sz) {
   3545     if (sz <= last) {
   3546         buf[sz] = '\0';
   3547         setLast(last - sz);
   3548         return buf;
   3549     } else {
   3550         setOnHeap();
   3551         data.size = sz;
   3552         data.capacity = data.size + 1;
   3553         data.ptr = new char[data.capacity];
   3554         data.ptr[sz] = '\0';
   3555         return data.ptr;
   3556     }
   3557 }
   3558 
   3559 void String::setOnHeap() noexcept { *reinterpret_cast<unsigned char*>(&buf[last]) = 128; }
   3560 void String::setLast(size_type in) noexcept { buf[last] = char(in); }
   3561 void String::setSize(size_type sz) noexcept {
   3562     if (isOnStack()) { buf[sz] = '\0'; setLast(last - sz); }
   3563     else { data.ptr[sz] = '\0'; data.size = sz; }
   3564 }
   3565 
   3566 void String::copy(const String& other) {
   3567     if(other.isOnStack()) {
   3568         memcpy(buf, other.buf, len);
   3569     } else {
   3570         memcpy(allocate(other.data.size), other.data.ptr, other.data.size);
   3571     }
   3572 }
   3573 
   3574 String::String() noexcept {
   3575     buf[0] = '\0';
   3576     setLast();
   3577 }
   3578 
   3579 String::~String() {
   3580     if(!isOnStack())
   3581         delete[] data.ptr;
   3582 } // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
   3583 
   3584 String::String(const char* in)
   3585         : String(in, strlen(in)) {}
   3586 
   3587 String::String(const char* in, size_type in_size) {
   3588     memcpy(allocate(in_size), in, in_size);
   3589 }
   3590 
   3591 String::String(std::istream& in, size_type in_size) {
   3592     in.read(allocate(in_size), in_size);
   3593 }
   3594 
   3595 String::String(const String& other) { copy(other); }
   3596 
   3597 String& String::operator=(const String& other) {
   3598     if(this != &other) {
   3599         if(!isOnStack())
   3600             delete[] data.ptr;
   3601 
   3602         copy(other);
   3603     }
   3604 
   3605     return *this;
   3606 }
   3607 
   3608 String& String::operator+=(const String& other) {
   3609     const size_type my_old_size = size();
   3610     const size_type other_size  = other.size();
   3611     const size_type total_size  = my_old_size + other_size;
   3612     if(isOnStack()) {
   3613         if(total_size < len) {
   3614             // append to the current stack space
   3615             memcpy(buf + my_old_size, other.c_str(), other_size + 1);
   3616             // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
   3617             setLast(last - total_size);
   3618         } else {
   3619             // alloc new chunk
   3620             char* temp = new char[total_size + 1];
   3621             // copy current data to new location before writing in the union
   3622             memcpy(temp, buf, my_old_size); // skip the +1 ('\0') for speed
   3623             // update data in union
   3624             setOnHeap();
   3625             data.size     = total_size;
   3626             data.capacity = data.size + 1;
   3627             data.ptr      = temp;
   3628             // transfer the rest of the data
   3629             memcpy(data.ptr + my_old_size, other.c_str(), other_size + 1);
   3630         }
   3631     } else {
   3632         if(data.capacity > total_size) {
   3633             // append to the current heap block
   3634             data.size = total_size;
   3635             memcpy(data.ptr + my_old_size, other.c_str(), other_size + 1);
   3636         } else {
   3637             // resize
   3638             data.capacity *= 2;
   3639             if(data.capacity <= total_size)
   3640                 data.capacity = total_size + 1;
   3641             // alloc new chunk
   3642             char* temp = new char[data.capacity];
   3643             // copy current data to new location before releasing it
   3644             memcpy(temp, data.ptr, my_old_size); // skip the +1 ('\0') for speed
   3645             // release old chunk
   3646             delete[] data.ptr;
   3647             // update the rest of the union members
   3648             data.size = total_size;
   3649             data.ptr  = temp;
   3650             // transfer the rest of the data
   3651             memcpy(data.ptr + my_old_size, other.c_str(), other_size + 1);
   3652         }
   3653     }
   3654 
   3655     return *this;
   3656 }
   3657 
   3658 String::String(String&& other) noexcept {
   3659     memcpy(buf, other.buf, len);
   3660     other.buf[0] = '\0';
   3661     other.setLast();
   3662 }
   3663 
   3664 String& String::operator=(String&& other) noexcept {
   3665     if(this != &other) {
   3666         if(!isOnStack())
   3667             delete[] data.ptr;
   3668         memcpy(buf, other.buf, len);
   3669         other.buf[0] = '\0';
   3670         other.setLast();
   3671     }
   3672     return *this;
   3673 }
   3674 
   3675 char String::operator[](size_type i) const {
   3676     return const_cast<String*>(this)->operator[](i);
   3677 }
   3678 
   3679 char& String::operator[](size_type i) {
   3680     if(isOnStack())
   3681         return reinterpret_cast<char*>(buf)[i];
   3682     return data.ptr[i];
   3683 }
   3684 
   3685 DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wmaybe-uninitialized")
   3686 String::size_type String::size() const {
   3687     if(isOnStack())
   3688         return last - (size_type(buf[last]) & 31); // using "last" would work only if "len" is 32
   3689     return data.size;
   3690 }
   3691 DOCTEST_GCC_SUPPRESS_WARNING_POP
   3692 
   3693 String::size_type String::capacity() const {
   3694     if(isOnStack())
   3695         return len;
   3696     return data.capacity;
   3697 }
   3698 
   3699 String String::substr(size_type pos, size_type cnt) && {
   3700     cnt = std::min(cnt, size() - 1 - pos);
   3701     char* cptr = c_str();
   3702     memmove(cptr, cptr + pos, cnt);
   3703     setSize(cnt);
   3704     return std::move(*this);
   3705 }
   3706 
   3707 String String::substr(size_type pos, size_type cnt) const & {
   3708     cnt = std::min(cnt, size() - 1 - pos);
   3709     return String{ c_str() + pos, cnt };
   3710 }
   3711 
   3712 String::size_type String::find(char ch, size_type pos) const {
   3713     const char* begin = c_str();
   3714     const char* end = begin + size();
   3715     const char* it = begin + pos;
   3716     for (; it < end && *it != ch; it++);
   3717     if (it < end) { return static_cast<size_type>(it - begin); }
   3718     else { return npos; }
   3719 }
   3720 
   3721 String::size_type String::rfind(char ch, size_type pos) const {
   3722     const char* begin = c_str();
   3723     const char* it = begin + std::min(pos, size() - 1);
   3724     for (; it >= begin && *it != ch; it--);
   3725     if (it >= begin) { return static_cast<size_type>(it - begin); }
   3726     else { return npos; }
   3727 }
   3728 
   3729 int String::compare(const char* other, bool no_case) const {
   3730     if(no_case)
   3731         return doctest::stricmp(c_str(), other);
   3732     return std::strcmp(c_str(), other);
   3733 }
   3734 
   3735 int String::compare(const String& other, bool no_case) const {
   3736     return compare(other.c_str(), no_case);
   3737 }
   3738 
   3739 String operator+(const String& lhs, const String& rhs) { return  String(lhs) += rhs; }
   3740 
   3741 bool operator==(const String& lhs, const String& rhs) { return lhs.compare(rhs) == 0; }
   3742 bool operator!=(const String& lhs, const String& rhs) { return lhs.compare(rhs) != 0; }
   3743 bool operator< (const String& lhs, const String& rhs) { return lhs.compare(rhs) < 0; }
   3744 bool operator> (const String& lhs, const String& rhs) { return lhs.compare(rhs) > 0; }
   3745 bool operator<=(const String& lhs, const String& rhs) { return (lhs != rhs) ? lhs.compare(rhs) < 0 : true; }
   3746 bool operator>=(const String& lhs, const String& rhs) { return (lhs != rhs) ? lhs.compare(rhs) > 0 : true; }
   3747 
   3748 std::ostream& operator<<(std::ostream& s, const String& in) { return s << in.c_str(); }
   3749 
   3750 Contains::Contains(const String& str) : string(str) { }
   3751 
   3752 bool Contains::checkWith(const String& other) const {
   3753     return strstr(other.c_str(), string.c_str()) != nullptr;
   3754 }
   3755 
   3756 String toString(const Contains& in) {
   3757     return "Contains( " + in.string + " )";
   3758 }
   3759 
   3760 bool operator==(const String& lhs, const Contains& rhs) { return rhs.checkWith(lhs); }
   3761 bool operator==(const Contains& lhs, const String& rhs) { return lhs.checkWith(rhs); }
   3762 bool operator!=(const String& lhs, const Contains& rhs) { return !rhs.checkWith(lhs); }
   3763 bool operator!=(const Contains& lhs, const String& rhs) { return !lhs.checkWith(rhs); }
   3764 
   3765 namespace {
   3766     void color_to_stream(std::ostream&, Color::Enum) DOCTEST_BRANCH_ON_DISABLED({}, ;)
   3767 } // namespace
   3768 
   3769 namespace Color {
   3770     std::ostream& operator<<(std::ostream& s, Color::Enum code) {
   3771         color_to_stream(s, code);
   3772         return s;
   3773     }
   3774 } // namespace Color
   3775 
   3776 // clang-format off
   3777 const char* assertString(assertType::Enum at) {
   3778     DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4061) // enum 'x' in switch of enum 'y' is not explicitely handled
   3779     #define DOCTEST_GENERATE_ASSERT_TYPE_CASE(assert_type) case assertType::DT_ ## assert_type: return #assert_type
   3780     #define DOCTEST_GENERATE_ASSERT_TYPE_CASES(assert_type) \
   3781         DOCTEST_GENERATE_ASSERT_TYPE_CASE(WARN_ ## assert_type); \
   3782         DOCTEST_GENERATE_ASSERT_TYPE_CASE(CHECK_ ## assert_type); \
   3783         DOCTEST_GENERATE_ASSERT_TYPE_CASE(REQUIRE_ ## assert_type)
   3784     switch(at) {
   3785         DOCTEST_GENERATE_ASSERT_TYPE_CASE(WARN);
   3786         DOCTEST_GENERATE_ASSERT_TYPE_CASE(CHECK);
   3787         DOCTEST_GENERATE_ASSERT_TYPE_CASE(REQUIRE);
   3788 
   3789         DOCTEST_GENERATE_ASSERT_TYPE_CASES(FALSE);
   3790 
   3791         DOCTEST_GENERATE_ASSERT_TYPE_CASES(THROWS);
   3792 
   3793         DOCTEST_GENERATE_ASSERT_TYPE_CASES(THROWS_AS);
   3794 
   3795         DOCTEST_GENERATE_ASSERT_TYPE_CASES(THROWS_WITH);
   3796 
   3797         DOCTEST_GENERATE_ASSERT_TYPE_CASES(THROWS_WITH_AS);
   3798 
   3799         DOCTEST_GENERATE_ASSERT_TYPE_CASES(NOTHROW);
   3800 
   3801         DOCTEST_GENERATE_ASSERT_TYPE_CASES(EQ);
   3802         DOCTEST_GENERATE_ASSERT_TYPE_CASES(NE);
   3803         DOCTEST_GENERATE_ASSERT_TYPE_CASES(GT);
   3804         DOCTEST_GENERATE_ASSERT_TYPE_CASES(LT);
   3805         DOCTEST_GENERATE_ASSERT_TYPE_CASES(GE);
   3806         DOCTEST_GENERATE_ASSERT_TYPE_CASES(LE);
   3807 
   3808         DOCTEST_GENERATE_ASSERT_TYPE_CASES(UNARY);
   3809         DOCTEST_GENERATE_ASSERT_TYPE_CASES(UNARY_FALSE);
   3810 
   3811         default: DOCTEST_INTERNAL_ERROR("Tried stringifying invalid assert type!");
   3812     }
   3813     DOCTEST_MSVC_SUPPRESS_WARNING_POP
   3814 }
   3815 // clang-format on
   3816 
   3817 const char* failureString(assertType::Enum at) {
   3818     if(at & assertType::is_warn) //!OCLINT bitwise operator in conditional
   3819         return "WARNING";
   3820     if(at & assertType::is_check) //!OCLINT bitwise operator in conditional
   3821         return "ERROR";
   3822     if(at & assertType::is_require) //!OCLINT bitwise operator in conditional
   3823         return "FATAL ERROR";
   3824     return "";
   3825 }
   3826 
   3827 DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wnull-dereference")
   3828 DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wnull-dereference")
   3829 // depending on the current options this will remove the path of filenames
   3830 const char* skipPathFromFilename(const char* file) {
   3831 #ifndef DOCTEST_CONFIG_DISABLE
   3832     if(getContextOptions()->no_path_in_filenames) {
   3833         auto back    = std::strrchr(file, '\\');
   3834         auto forward = std::strrchr(file, '/');
   3835         if(back || forward) {
   3836             if(back > forward)
   3837                 forward = back;
   3838             return forward + 1;
   3839         }
   3840     }
   3841 #endif // DOCTEST_CONFIG_DISABLE
   3842     return file;
   3843 }
   3844 DOCTEST_CLANG_SUPPRESS_WARNING_POP
   3845 DOCTEST_GCC_SUPPRESS_WARNING_POP
   3846 
   3847 bool SubcaseSignature::operator==(const SubcaseSignature& other) const {
   3848     return m_line == other.m_line
   3849         && std::strcmp(m_file, other.m_file) == 0
   3850         && m_name == other.m_name;
   3851 }
   3852 
   3853 bool SubcaseSignature::operator<(const SubcaseSignature& other) const {
   3854     if(m_line != other.m_line)
   3855         return m_line < other.m_line;
   3856     if(std::strcmp(m_file, other.m_file) != 0)
   3857         return std::strcmp(m_file, other.m_file) < 0;
   3858     return m_name.compare(other.m_name) < 0;
   3859 }
   3860 
   3861 DOCTEST_DEFINE_INTERFACE(IContextScope)
   3862 
   3863 namespace detail {
   3864     void filldata<const void*>::fill(std::ostream* stream, const void* in) {
   3865         if (in) { *stream << in; }
   3866         else { *stream << "nullptr"; }
   3867     }
   3868 
   3869     template <typename T>
   3870     String toStreamLit(T t) {
   3871         std::ostream* os = tlssPush();
   3872         os->operator<<(t);
   3873         return tlssPop();
   3874     }
   3875 }
   3876 
   3877 #ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
   3878 String toString(const char* in) { return String("\"") + (in ? in : "{null string}") + "\""; }
   3879 #endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
   3880 
   3881 #if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0)
   3882 // see this issue on why this is needed: https://github.com/doctest/doctest/issues/183
   3883 String toString(const std::string& in) { return in.c_str(); }
   3884 #endif // VS 2019
   3885 
   3886 String toString(String in) { return in; }
   3887 
   3888 String toString(std::nullptr_t) { return "nullptr"; }
   3889 
   3890 String toString(bool in) { return in ? "true" : "false"; }
   3891 
   3892 String toString(float in) { return toStreamLit(in); }
   3893 String toString(double in) { return toStreamLit(in); }
   3894 String toString(double long in) { return toStreamLit(in); }
   3895 
   3896 String toString(char in) { return toStreamLit(static_cast<signed>(in)); }
   3897 String toString(char signed in) { return toStreamLit(static_cast<signed>(in)); }
   3898 String toString(char unsigned in) { return toStreamLit(static_cast<unsigned>(in)); }
   3899 String toString(short in) { return toStreamLit(in); }
   3900 String toString(short unsigned in) { return toStreamLit(in); }
   3901 String toString(signed in) { return toStreamLit(in); }
   3902 String toString(unsigned in) { return toStreamLit(in); }
   3903 String toString(long in) { return toStreamLit(in); }
   3904 String toString(long unsigned in) { return toStreamLit(in); }
   3905 String toString(long long in) { return toStreamLit(in); }
   3906 String toString(long long unsigned in) { return toStreamLit(in); }
   3907 
   3908 Approx::Approx(double value)
   3909         : m_epsilon(static_cast<double>(std::numeric_limits<float>::epsilon()) * 100)
   3910         , m_scale(1.0)
   3911         , m_value(value) {}
   3912 
   3913 Approx Approx::operator()(double value) const {
   3914     Approx approx(value);
   3915     approx.epsilon(m_epsilon);
   3916     approx.scale(m_scale);
   3917     return approx;
   3918 }
   3919 
   3920 Approx& Approx::epsilon(double newEpsilon) {
   3921     m_epsilon = newEpsilon;
   3922     return *this;
   3923 }
   3924 Approx& Approx::scale(double newScale) {
   3925     m_scale = newScale;
   3926     return *this;
   3927 }
   3928 
   3929 bool operator==(double lhs, const Approx& rhs) {
   3930     // Thanks to Richard Harris for his help refining this formula
   3931     return std::fabs(lhs - rhs.m_value) <
   3932            rhs.m_epsilon * (rhs.m_scale + std::max<double>(std::fabs(lhs), std::fabs(rhs.m_value)));
   3933 }
   3934 bool operator==(const Approx& lhs, double rhs) { return operator==(rhs, lhs); }
   3935 bool operator!=(double lhs, const Approx& rhs) { return !operator==(lhs, rhs); }
   3936 bool operator!=(const Approx& lhs, double rhs) { return !operator==(rhs, lhs); }
   3937 bool operator<=(double lhs, const Approx& rhs) { return lhs < rhs.m_value || lhs == rhs; }
   3938 bool operator<=(const Approx& lhs, double rhs) { return lhs.m_value < rhs || lhs == rhs; }
   3939 bool operator>=(double lhs, const Approx& rhs) { return lhs > rhs.m_value || lhs == rhs; }
   3940 bool operator>=(const Approx& lhs, double rhs) { return lhs.m_value > rhs || lhs == rhs; }
   3941 bool operator<(double lhs, const Approx& rhs) { return lhs < rhs.m_value && lhs != rhs; }
   3942 bool operator<(const Approx& lhs, double rhs) { return lhs.m_value < rhs && lhs != rhs; }
   3943 bool operator>(double lhs, const Approx& rhs) { return lhs > rhs.m_value && lhs != rhs; }
   3944 bool operator>(const Approx& lhs, double rhs) { return lhs.m_value > rhs && lhs != rhs; }
   3945 
   3946 String toString(const Approx& in) {
   3947     return "Approx( " + doctest::toString(in.m_value) + " )";
   3948 }
   3949 const ContextOptions* getContextOptions() { return DOCTEST_BRANCH_ON_DISABLED(nullptr, g_cs); }
   3950 
   3951 DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4738)
   3952 template <typename F>
   3953 IsNaN<F>::operator bool() const {
   3954     return std::isnan(value) ^ flipped;
   3955 }
   3956 DOCTEST_MSVC_SUPPRESS_WARNING_POP
   3957 template struct DOCTEST_INTERFACE_DEF IsNaN<float>;
   3958 template struct DOCTEST_INTERFACE_DEF IsNaN<double>;
   3959 template struct DOCTEST_INTERFACE_DEF IsNaN<long double>;
   3960 template <typename F>
   3961 String toString(IsNaN<F> in) { return String(in.flipped ? "! " : "") + "IsNaN( " + doctest::toString(in.value) + " )"; }
   3962 String toString(IsNaN<float> in) { return toString<float>(in); }
   3963 String toString(IsNaN<double> in) { return toString<double>(in); }
   3964 String toString(IsNaN<double long> in) { return toString<double long>(in); }
   3965 
   3966 } // namespace doctest
   3967 
   3968 #ifdef DOCTEST_CONFIG_DISABLE
   3969 namespace doctest {
   3970 Context::Context(int, const char* const*) {}
   3971 Context::~Context() = default;
   3972 void Context::applyCommandLine(int, const char* const*) {}
   3973 void Context::addFilter(const char*, const char*) {}
   3974 void Context::clearFilters() {}
   3975 void Context::setOption(const char*, bool) {}
   3976 void Context::setOption(const char*, int) {}
   3977 void Context::setOption(const char*, const char*) {}
   3978 bool Context::shouldExit() { return false; }
   3979 void Context::setAsDefaultForAssertsOutOfTestCases() {}
   3980 void Context::setAssertHandler(detail::assert_handler) {}
   3981 void Context::setCout(std::ostream*) {}
   3982 int  Context::run() { return 0; }
   3983 
   3984 int                         IReporter::get_num_active_contexts() { return 0; }
   3985 const IContextScope* const* IReporter::get_active_contexts() { return nullptr; }
   3986 int                         IReporter::get_num_stringified_contexts() { return 0; }
   3987 const String*               IReporter::get_stringified_contexts() { return nullptr; }
   3988 
   3989 int registerReporter(const char*, int, IReporter*) { return 0; }
   3990 
   3991 } // namespace doctest
   3992 #else // DOCTEST_CONFIG_DISABLE
   3993 
   3994 #if !defined(DOCTEST_CONFIG_COLORS_NONE)
   3995 #if !defined(DOCTEST_CONFIG_COLORS_WINDOWS) && !defined(DOCTEST_CONFIG_COLORS_ANSI)
   3996 #ifdef DOCTEST_PLATFORM_WINDOWS
   3997 #define DOCTEST_CONFIG_COLORS_WINDOWS
   3998 #else // linux
   3999 #define DOCTEST_CONFIG_COLORS_ANSI
   4000 #endif // platform
   4001 #endif // DOCTEST_CONFIG_COLORS_WINDOWS && DOCTEST_CONFIG_COLORS_ANSI
   4002 #endif // DOCTEST_CONFIG_COLORS_NONE
   4003 
   4004 namespace doctest_detail_test_suite_ns {
   4005 // holds the current test suite
   4006 doctest::detail::TestSuite& getCurrentTestSuite() {
   4007     static doctest::detail::TestSuite data{};
   4008     return data;
   4009 }
   4010 } // namespace doctest_detail_test_suite_ns
   4011 
   4012 namespace doctest {
   4013 namespace {
   4014     // the int (priority) is part of the key for automatic sorting - sadly one can register a
   4015     // reporter with a duplicate name and a different priority but hopefully that won't happen often :|
   4016     using reporterMap = std::map<std::pair<int, String>, reporterCreatorFunc>;
   4017 
   4018     reporterMap& getReporters() {
   4019         static reporterMap data;
   4020         return data;
   4021     }
   4022     reporterMap& getListeners() {
   4023         static reporterMap data;
   4024         return data;
   4025     }
   4026 } // namespace
   4027 namespace detail {
   4028 #define DOCTEST_ITERATE_THROUGH_REPORTERS(function, ...)                                           \
   4029     for(auto& curr_rep : g_cs->reporters_currently_used)                                           \
   4030     curr_rep->function(__VA_ARGS__)
   4031 
   4032     bool checkIfShouldThrow(assertType::Enum at) {
   4033         if(at & assertType::is_require) //!OCLINT bitwise operator in conditional
   4034             return true;
   4035 
   4036         if((at & assertType::is_check) //!OCLINT bitwise operator in conditional
   4037            && getContextOptions()->abort_after > 0 &&
   4038            (g_cs->numAssertsFailed + g_cs->numAssertsFailedCurrentTest_atomic) >=
   4039                    getContextOptions()->abort_after)
   4040             return true;
   4041 
   4042         return false;
   4043     }
   4044 
   4045 #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
   4046     DOCTEST_NORETURN void throwException() {
   4047         g_cs->shouldLogCurrentException = false;
   4048         throw TestFailureException(); // NOLINT(hicpp-exception-baseclass)
   4049     }
   4050 #else // DOCTEST_CONFIG_NO_EXCEPTIONS
   4051     void throwException() {}
   4052 #endif // DOCTEST_CONFIG_NO_EXCEPTIONS
   4053 } // namespace detail
   4054 
   4055 namespace {
   4056     using namespace detail;
   4057     // matching of a string against a wildcard mask (case sensitivity configurable) taken from
   4058     // https://www.codeproject.com/Articles/1088/Wildcard-string-compare-globbing
   4059     int wildcmp(const char* str, const char* wild, bool caseSensitive) {
   4060         const char* cp = str;
   4061         const char* mp = wild;
   4062 
   4063         while((*str) && (*wild != '*')) {
   4064             if((caseSensitive ? (*wild != *str) : (tolower(*wild) != tolower(*str))) &&
   4065                (*wild != '?')) {
   4066                 return 0;
   4067             }
   4068             wild++;
   4069             str++;
   4070         }
   4071 
   4072         while(*str) {
   4073             if(*wild == '*') {
   4074                 if(!*++wild) {
   4075                     return 1;
   4076                 }
   4077                 mp = wild;
   4078                 cp = str + 1;
   4079             } else if((caseSensitive ? (*wild == *str) : (tolower(*wild) == tolower(*str))) ||
   4080                       (*wild == '?')) {
   4081                 wild++;
   4082                 str++;
   4083             } else {
   4084                 wild = mp;   //!OCLINT parameter reassignment
   4085                 str  = cp++; //!OCLINT parameter reassignment
   4086             }
   4087         }
   4088 
   4089         while(*wild == '*') {
   4090             wild++;
   4091         }
   4092         return !*wild;
   4093     }
   4094 
   4095     // checks if the name matches any of the filters (and can be configured what to do when empty)
   4096     bool matchesAny(const char* name, const std::vector<String>& filters, bool matchEmpty,
   4097         bool caseSensitive) {
   4098         if (filters.empty() && matchEmpty)
   4099             return true;
   4100         for (auto& curr : filters)
   4101             if (wildcmp(name, curr.c_str(), caseSensitive))
   4102                 return true;
   4103         return false;
   4104     }
   4105 
   4106     unsigned long long hash(unsigned long long a, unsigned long long b) {
   4107         return (a << 5) + b;
   4108     }
   4109 
   4110     // C string hash function (djb2) - taken from http://www.cse.yorku.ca/~oz/hash.html
   4111     unsigned long long hash(const char* str) {
   4112         unsigned long long hash = 5381;
   4113         char c;
   4114         while ((c = *str++))
   4115             hash = ((hash << 5) + hash) + c; // hash * 33 + c
   4116         return hash;
   4117     }
   4118 
   4119     unsigned long long hash(const SubcaseSignature& sig) {
   4120         return hash(hash(hash(sig.m_file), hash(sig.m_name.c_str())), sig.m_line);
   4121     }
   4122 
   4123     unsigned long long hash(const std::vector<SubcaseSignature>& sigs, size_t count) {
   4124         unsigned long long running = 0;
   4125         auto end = sigs.begin() + count;
   4126         for (auto it = sigs.begin(); it != end; it++) {
   4127             running = hash(running, hash(*it));
   4128         }
   4129         return running;
   4130     }
   4131 
   4132     unsigned long long hash(const std::vector<SubcaseSignature>& sigs) {
   4133         unsigned long long running = 0;
   4134         for (const SubcaseSignature& sig : sigs) {
   4135             running = hash(running, hash(sig));
   4136         }
   4137         return running;
   4138     }
   4139 } // namespace
   4140 namespace detail {
   4141     bool Subcase::checkFilters() {
   4142         if (g_cs->subcaseStack.size() < size_t(g_cs->subcase_filter_levels)) {
   4143             if (!matchesAny(m_signature.m_name.c_str(), g_cs->filters[6], true, g_cs->case_sensitive))
   4144                 return true;
   4145             if (matchesAny(m_signature.m_name.c_str(), g_cs->filters[7], false, g_cs->case_sensitive))
   4146                 return true;
   4147         }
   4148         return false;
   4149     }
   4150 
   4151     Subcase::Subcase(const String& name, const char* file, int line)
   4152             : m_signature({name, file, line}) {
   4153         if (!g_cs->reachedLeaf) {
   4154             if (g_cs->nextSubcaseStack.size() <= g_cs->subcaseStack.size()
   4155                 || g_cs->nextSubcaseStack[g_cs->subcaseStack.size()] == m_signature) {
   4156                 // Going down.
   4157                 if (checkFilters()) { return; }
   4158 
   4159                 g_cs->subcaseStack.push_back(m_signature);
   4160                 g_cs->currentSubcaseDepth++;
   4161                 m_entered = true;
   4162                 DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_start, m_signature);
   4163             }
   4164         } else {
   4165             if (g_cs->subcaseStack[g_cs->currentSubcaseDepth] == m_signature) {
   4166                 // This subcase is reentered via control flow.
   4167                 g_cs->currentSubcaseDepth++;
   4168                 m_entered = true;
   4169                 DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_start, m_signature);
   4170             } else if (g_cs->nextSubcaseStack.size() <= g_cs->currentSubcaseDepth
   4171                     && g_cs->fullyTraversedSubcases.find(hash(hash(g_cs->subcaseStack, g_cs->currentSubcaseDepth), hash(m_signature)))
   4172                     == g_cs->fullyTraversedSubcases.end()) {
   4173                 if (checkFilters()) { return; }
   4174                 // This subcase is part of the one to be executed next.
   4175                 g_cs->nextSubcaseStack.clear();
   4176                 g_cs->nextSubcaseStack.insert(g_cs->nextSubcaseStack.end(),
   4177                     g_cs->subcaseStack.begin(), g_cs->subcaseStack.begin() + g_cs->currentSubcaseDepth);
   4178                 g_cs->nextSubcaseStack.push_back(m_signature);
   4179             }
   4180         }
   4181     }
   4182 
   4183     DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4996) // std::uncaught_exception is deprecated in C++17
   4184     DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
   4185     DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
   4186 
   4187     Subcase::~Subcase() {
   4188         if (m_entered) {
   4189             g_cs->currentSubcaseDepth--;
   4190 
   4191             if (!g_cs->reachedLeaf) {
   4192                 // Leaf.
   4193                 g_cs->fullyTraversedSubcases.insert(hash(g_cs->subcaseStack));
   4194                 g_cs->nextSubcaseStack.clear();
   4195                 g_cs->reachedLeaf = true;
   4196             } else if (g_cs->nextSubcaseStack.empty()) {
   4197                 // All children are finished.
   4198                 g_cs->fullyTraversedSubcases.insert(hash(g_cs->subcaseStack));
   4199             }
   4200 
   4201 #if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200)
   4202             if(std::uncaught_exceptions() > 0
   4203 #else
   4204             if(std::uncaught_exception()
   4205 #endif
   4206                 && g_cs->shouldLogCurrentException) {
   4207                 DOCTEST_ITERATE_THROUGH_REPORTERS(
   4208                         test_case_exception, {"exception thrown in subcase - will translate later "
   4209                                                 "when the whole test case has been exited (cannot "
   4210                                                 "translate while there is an active exception)",
   4211                                                 false});
   4212                 g_cs->shouldLogCurrentException = false;
   4213             }
   4214 
   4215             DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY);
   4216         }
   4217     }
   4218 
   4219     DOCTEST_CLANG_SUPPRESS_WARNING_POP
   4220     DOCTEST_GCC_SUPPRESS_WARNING_POP
   4221     DOCTEST_MSVC_SUPPRESS_WARNING_POP
   4222 
   4223     Subcase::operator bool() const { return m_entered; }
   4224 
   4225     Result::Result(bool passed, const String& decomposition)
   4226             : m_passed(passed)
   4227             , m_decomp(decomposition) {}
   4228 
   4229     ExpressionDecomposer::ExpressionDecomposer(assertType::Enum at)
   4230             : m_at(at) {}
   4231 
   4232     TestSuite& TestSuite::operator*(const char* in) {
   4233         m_test_suite = in;
   4234         return *this;
   4235     }
   4236 
   4237     TestCase::TestCase(funcType test, const char* file, unsigned line, const TestSuite& test_suite,
   4238                        const String& type, int template_id) {
   4239         m_file              = file;
   4240         m_line              = line;
   4241         m_name              = nullptr; // will be later overridden in operator*
   4242         m_test_suite        = test_suite.m_test_suite;
   4243         m_description       = test_suite.m_description;
   4244         m_skip              = test_suite.m_skip;
   4245         m_no_breaks         = test_suite.m_no_breaks;
   4246         m_no_output         = test_suite.m_no_output;
   4247         m_may_fail          = test_suite.m_may_fail;
   4248         m_should_fail       = test_suite.m_should_fail;
   4249         m_expected_failures = test_suite.m_expected_failures;
   4250         m_timeout           = test_suite.m_timeout;
   4251 
   4252         m_test        = test;
   4253         m_type        = type;
   4254         m_template_id = template_id;
   4255     }
   4256 
   4257     TestCase::TestCase(const TestCase& other)
   4258             : TestCaseData() {
   4259         *this = other;
   4260     }
   4261 
   4262     DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(26434) // hides a non-virtual function
   4263     TestCase& TestCase::operator=(const TestCase& other) {
   4264         TestCaseData::operator=(other);
   4265         m_test        = other.m_test;
   4266         m_type        = other.m_type;
   4267         m_template_id = other.m_template_id;
   4268         m_full_name   = other.m_full_name;
   4269 
   4270         if(m_template_id != -1)
   4271             m_name = m_full_name.c_str();
   4272         return *this;
   4273     }
   4274     DOCTEST_MSVC_SUPPRESS_WARNING_POP
   4275 
   4276     TestCase& TestCase::operator*(const char* in) {
   4277         m_name = in;
   4278         // make a new name with an appended type for templated test case
   4279         if(m_template_id != -1) {
   4280             m_full_name = String(m_name) + "<" + m_type + ">";
   4281             // redirect the name to point to the newly constructed full name
   4282             m_name = m_full_name.c_str();
   4283         }
   4284         return *this;
   4285     }
   4286 
   4287     bool TestCase::operator<(const TestCase& other) const {
   4288         // this will be used only to differentiate between test cases - not relevant for sorting
   4289         if(m_line != other.m_line)
   4290             return m_line < other.m_line;
   4291         const int name_cmp = strcmp(m_name, other.m_name);
   4292         if(name_cmp != 0)
   4293             return name_cmp < 0;
   4294         const int file_cmp = m_file.compare(other.m_file);
   4295         if(file_cmp != 0)
   4296             return file_cmp < 0;
   4297         return m_template_id < other.m_template_id;
   4298     }
   4299 
   4300     // all the registered tests
   4301     std::set<TestCase>& getRegisteredTests() {
   4302         static std::set<TestCase> data;
   4303         return data;
   4304     }
   4305 } // namespace detail
   4306 namespace {
   4307     using namespace detail;
   4308     // for sorting tests by file/line
   4309     bool fileOrderComparator(const TestCase* lhs, const TestCase* rhs) {
   4310         // this is needed because MSVC gives different case for drive letters
   4311         // for __FILE__ when evaluated in a header and a source file
   4312         const int res = lhs->m_file.compare(rhs->m_file, bool(DOCTEST_MSVC));
   4313         if(res != 0)
   4314             return res < 0;
   4315         if(lhs->m_line != rhs->m_line)
   4316             return lhs->m_line < rhs->m_line;
   4317         return lhs->m_template_id < rhs->m_template_id;
   4318     }
   4319 
   4320     // for sorting tests by suite/file/line
   4321     bool suiteOrderComparator(const TestCase* lhs, const TestCase* rhs) {
   4322         const int res = std::strcmp(lhs->m_test_suite, rhs->m_test_suite);
   4323         if(res != 0)
   4324             return res < 0;
   4325         return fileOrderComparator(lhs, rhs);
   4326     }
   4327 
   4328     // for sorting tests by name/suite/file/line
   4329     bool nameOrderComparator(const TestCase* lhs, const TestCase* rhs) {
   4330         const int res = std::strcmp(lhs->m_name, rhs->m_name);
   4331         if(res != 0)
   4332             return res < 0;
   4333         return suiteOrderComparator(lhs, rhs);
   4334     }
   4335 
   4336     DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
   4337     void color_to_stream(std::ostream& s, Color::Enum code) {
   4338         static_cast<void>(s);    // for DOCTEST_CONFIG_COLORS_NONE or DOCTEST_CONFIG_COLORS_WINDOWS
   4339         static_cast<void>(code); // for DOCTEST_CONFIG_COLORS_NONE
   4340 #ifdef DOCTEST_CONFIG_COLORS_ANSI
   4341         if(g_no_colors ||
   4342            (isatty(STDOUT_FILENO) == false && getContextOptions()->force_colors == false))
   4343             return;
   4344 
   4345         auto col = "";
   4346         // clang-format off
   4347             switch(code) { //!OCLINT missing break in switch statement / unnecessary default statement in covered switch statement
   4348                 case Color::Red:         col = "[0;31m"; break;
   4349                 case Color::Green:       col = "[0;32m"; break;
   4350                 case Color::Blue:        col = "[0;34m"; break;
   4351                 case Color::Cyan:        col = "[0;36m"; break;
   4352                 case Color::Yellow:      col = "[0;33m"; break;
   4353                 case Color::Grey:        col = "[1;30m"; break;
   4354                 case Color::LightGrey:   col = "[0;37m"; break;
   4355                 case Color::BrightRed:   col = "[1;31m"; break;
   4356                 case Color::BrightGreen: col = "[1;32m"; break;
   4357                 case Color::BrightWhite: col = "[1;37m"; break;
   4358                 case Color::Bright: // invalid
   4359                 case Color::None:
   4360                 case Color::White:
   4361                 default:                 col = "[0m";
   4362             }
   4363         // clang-format on
   4364         s << "\033" << col;
   4365 #endif // DOCTEST_CONFIG_COLORS_ANSI
   4366 
   4367 #ifdef DOCTEST_CONFIG_COLORS_WINDOWS
   4368         if(g_no_colors ||
   4369            (_isatty(_fileno(stdout)) == false && getContextOptions()->force_colors == false))
   4370             return;
   4371 
   4372         static struct ConsoleHelper {
   4373             HANDLE stdoutHandle;
   4374             WORD   origFgAttrs;
   4375             WORD   origBgAttrs;
   4376 
   4377             ConsoleHelper() {
   4378                 stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE);
   4379                 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
   4380                 GetConsoleScreenBufferInfo(stdoutHandle, &csbiInfo);
   4381                 origFgAttrs = csbiInfo.wAttributes & ~(BACKGROUND_GREEN | BACKGROUND_RED |
   4382                     BACKGROUND_BLUE | BACKGROUND_INTENSITY);
   4383                 origBgAttrs = csbiInfo.wAttributes & ~(FOREGROUND_GREEN | FOREGROUND_RED |
   4384                     FOREGROUND_BLUE | FOREGROUND_INTENSITY);
   4385             }
   4386         } ch;
   4387 
   4388 #define DOCTEST_SET_ATTR(x) SetConsoleTextAttribute(ch.stdoutHandle, x | ch.origBgAttrs)
   4389 
   4390         // clang-format off
   4391         switch (code) {
   4392             case Color::White:       DOCTEST_SET_ATTR(FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE); break;
   4393             case Color::Red:         DOCTEST_SET_ATTR(FOREGROUND_RED);                                      break;
   4394             case Color::Green:       DOCTEST_SET_ATTR(FOREGROUND_GREEN);                                    break;
   4395             case Color::Blue:        DOCTEST_SET_ATTR(FOREGROUND_BLUE);                                     break;
   4396             case Color::Cyan:        DOCTEST_SET_ATTR(FOREGROUND_BLUE | FOREGROUND_GREEN);                  break;
   4397             case Color::Yellow:      DOCTEST_SET_ATTR(FOREGROUND_RED | FOREGROUND_GREEN);                   break;
   4398             case Color::Grey:        DOCTEST_SET_ATTR(0);                                                   break;
   4399             case Color::LightGrey:   DOCTEST_SET_ATTR(FOREGROUND_INTENSITY);                                break;
   4400             case Color::BrightRed:   DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_RED);               break;
   4401             case Color::BrightGreen: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_GREEN);             break;
   4402             case Color::BrightWhite: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE); break;
   4403             case Color::None:
   4404             case Color::Bright: // invalid
   4405             default:                 DOCTEST_SET_ATTR(ch.origFgAttrs);
   4406         }
   4407             // clang-format on
   4408 #endif // DOCTEST_CONFIG_COLORS_WINDOWS
   4409     }
   4410     DOCTEST_CLANG_SUPPRESS_WARNING_POP
   4411 
   4412     std::vector<const IExceptionTranslator*>& getExceptionTranslators() {
   4413         static std::vector<const IExceptionTranslator*> data;
   4414         return data;
   4415     }
   4416 
   4417     String translateActiveException() {
   4418 #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
   4419         String res;
   4420         auto&  translators = getExceptionTranslators();
   4421         for(auto& curr : translators)
   4422             if(curr->translate(res))
   4423                 return res;
   4424         // clang-format off
   4425         DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wcatch-value")
   4426         try {
   4427             throw;
   4428         } catch(std::exception& ex) {
   4429             return ex.what();
   4430         } catch(std::string& msg) {
   4431             return msg.c_str();
   4432         } catch(const char* msg) {
   4433             return msg;
   4434         } catch(...) {
   4435             return "unknown exception";
   4436         }
   4437         DOCTEST_GCC_SUPPRESS_WARNING_POP
   4438 // clang-format on
   4439 #else  // DOCTEST_CONFIG_NO_EXCEPTIONS
   4440         return "";
   4441 #endif // DOCTEST_CONFIG_NO_EXCEPTIONS
   4442     }
   4443 } // namespace
   4444 
   4445 namespace detail {
   4446     // used by the macros for registering tests
   4447     int regTest(const TestCase& tc) {
   4448         getRegisteredTests().insert(tc);
   4449         return 0;
   4450     }
   4451 
   4452     // sets the current test suite
   4453     int setTestSuite(const TestSuite& ts) {
   4454         doctest_detail_test_suite_ns::getCurrentTestSuite() = ts;
   4455         return 0;
   4456     }
   4457 
   4458 #ifdef DOCTEST_IS_DEBUGGER_ACTIVE
   4459     bool isDebuggerActive() { return DOCTEST_IS_DEBUGGER_ACTIVE(); }
   4460 #else // DOCTEST_IS_DEBUGGER_ACTIVE
   4461 #ifdef DOCTEST_PLATFORM_LINUX
   4462     class ErrnoGuard {
   4463     public:
   4464         ErrnoGuard() : m_oldErrno(errno) {}
   4465         ~ErrnoGuard() { errno = m_oldErrno; }
   4466     private:
   4467         int m_oldErrno;
   4468     };
   4469     // See the comments in Catch2 for the reasoning behind this implementation:
   4470     // https://github.com/catchorg/Catch2/blob/v2.13.1/include/internal/catch_debugger.cpp#L79-L102
   4471     bool isDebuggerActive() {
   4472         ErrnoGuard guard;
   4473         std::ifstream in("/proc/self/status");
   4474         for(std::string line; std::getline(in, line);) {
   4475             static const int PREFIX_LEN = 11;
   4476             if(line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0) {
   4477                 return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0';
   4478             }
   4479         }
   4480         return false;
   4481     }
   4482 #elif defined(DOCTEST_PLATFORM_MAC)
   4483     // The following function is taken directly from the following technical note:
   4484     // https://developer.apple.com/library/archive/qa/qa1361/_index.html
   4485     // Returns true if the current process is being debugged (either
   4486     // running under the debugger or has a debugger attached post facto).
   4487     bool isDebuggerActive() {
   4488         int        mib[4];
   4489         kinfo_proc info;
   4490         size_t     size;
   4491         // Initialize the flags so that, if sysctl fails for some bizarre
   4492         // reason, we get a predictable result.
   4493         info.kp_proc.p_flag = 0;
   4494         // Initialize mib, which tells sysctl the info we want, in this case
   4495         // we're looking for information about a specific process ID.
   4496         mib[0] = CTL_KERN;
   4497         mib[1] = KERN_PROC;
   4498         mib[2] = KERN_PROC_PID;
   4499         mib[3] = getpid();
   4500         // Call sysctl.
   4501         size = sizeof(info);
   4502         if(sysctl(mib, DOCTEST_COUNTOF(mib), &info, &size, 0, 0) != 0) {
   4503             std::cerr << "\nCall to sysctl failed - unable to determine if debugger is active **\n";
   4504             return false;
   4505         }
   4506         // We're being debugged if the P_TRACED flag is set.
   4507         return ((info.kp_proc.p_flag & P_TRACED) != 0);
   4508     }
   4509 #elif DOCTEST_MSVC || defined(__MINGW32__) || defined(__MINGW64__)
   4510     bool isDebuggerActive() { return ::IsDebuggerPresent() != 0; }
   4511 #else
   4512     bool isDebuggerActive() { return false; }
   4513 #endif // Platform
   4514 #endif // DOCTEST_IS_DEBUGGER_ACTIVE
   4515 
   4516     void registerExceptionTranslatorImpl(const IExceptionTranslator* et) {
   4517         if(std::find(getExceptionTranslators().begin(), getExceptionTranslators().end(), et) ==
   4518            getExceptionTranslators().end())
   4519             getExceptionTranslators().push_back(et);
   4520     }
   4521 
   4522     DOCTEST_THREAD_LOCAL std::vector<IContextScope*> g_infoContexts; // for logging with INFO()
   4523 
   4524     ContextScopeBase::ContextScopeBase() {
   4525         g_infoContexts.push_back(this);
   4526     }
   4527 
   4528     ContextScopeBase::ContextScopeBase(ContextScopeBase&& other) noexcept {
   4529         if (other.need_to_destroy) {
   4530             other.destroy();
   4531         }
   4532         other.need_to_destroy = false;
   4533         g_infoContexts.push_back(this);
   4534     }
   4535 
   4536     DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4996) // std::uncaught_exception is deprecated in C++17
   4537     DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
   4538     DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
   4539 
   4540     // destroy cannot be inlined into the destructor because that would mean calling stringify after
   4541     // ContextScope has been destroyed (base class destructors run after derived class destructors).
   4542     // Instead, ContextScope calls this method directly from its destructor.
   4543     void ContextScopeBase::destroy() {
   4544 #if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200)
   4545         if(std::uncaught_exceptions() > 0) {
   4546 #else
   4547         if(std::uncaught_exception()) {
   4548 #endif
   4549             std::ostringstream s;
   4550             this->stringify(&s);
   4551             g_cs->stringifiedContexts.push_back(s.str().c_str());
   4552         }
   4553         g_infoContexts.pop_back();
   4554     }
   4555 
   4556     DOCTEST_CLANG_SUPPRESS_WARNING_POP
   4557     DOCTEST_GCC_SUPPRESS_WARNING_POP
   4558     DOCTEST_MSVC_SUPPRESS_WARNING_POP
   4559 } // namespace detail
   4560 namespace {
   4561     using namespace detail;
   4562 
   4563 #if !defined(DOCTEST_CONFIG_POSIX_SIGNALS) && !defined(DOCTEST_CONFIG_WINDOWS_SEH)
   4564     struct FatalConditionHandler
   4565     {
   4566         static void reset() {}
   4567         static void allocateAltStackMem() {}
   4568         static void freeAltStackMem() {}
   4569     };
   4570 #else // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH
   4571 
   4572     void reportFatal(const std::string&);
   4573 
   4574 #ifdef DOCTEST_PLATFORM_WINDOWS
   4575 
   4576     struct SignalDefs
   4577     {
   4578         DWORD id;
   4579         const char* name;
   4580     };
   4581     // There is no 1-1 mapping between signals and windows exceptions.
   4582     // Windows can easily distinguish between SO and SigSegV,
   4583     // but SigInt, SigTerm, etc are handled differently.
   4584     SignalDefs signalDefs[] = {
   4585             {static_cast<DWORD>(EXCEPTION_ILLEGAL_INSTRUCTION),
   4586              "SIGILL - Illegal instruction signal"},
   4587             {static_cast<DWORD>(EXCEPTION_STACK_OVERFLOW), "SIGSEGV - Stack overflow"},
   4588             {static_cast<DWORD>(EXCEPTION_ACCESS_VIOLATION),
   4589              "SIGSEGV - Segmentation violation signal"},
   4590             {static_cast<DWORD>(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error"},
   4591     };
   4592 
   4593     struct FatalConditionHandler
   4594     {
   4595         static LONG CALLBACK handleException(PEXCEPTION_POINTERS ExceptionInfo) {
   4596             // Multiple threads may enter this filter/handler at once. We want the error message to be printed on the
   4597             // console just once no matter how many threads have crashed.
   4598             DOCTEST_DECLARE_STATIC_MUTEX(mutex)
   4599             static bool execute = true;
   4600             {
   4601                 DOCTEST_LOCK_MUTEX(mutex)
   4602                 if(execute) {
   4603                     bool reported = false;
   4604                     for(size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) {
   4605                         if(ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) {
   4606                             reportFatal(signalDefs[i].name);
   4607                             reported = true;
   4608                             break;
   4609                         }
   4610                     }
   4611                     if(reported == false)
   4612                         reportFatal("Unhandled SEH exception caught");
   4613                     if(isDebuggerActive() && !g_cs->no_breaks)
   4614                         DOCTEST_BREAK_INTO_DEBUGGER();
   4615                 }
   4616                 execute = false;
   4617             }
   4618             std::exit(EXIT_FAILURE);
   4619         }
   4620 
   4621         static void allocateAltStackMem() {}
   4622         static void freeAltStackMem() {}
   4623 
   4624         FatalConditionHandler() {
   4625             isSet = true;
   4626             // 32k seems enough for doctest to handle stack overflow,
   4627             // but the value was found experimentally, so there is no strong guarantee
   4628             guaranteeSize = 32 * 1024;
   4629             // Register an unhandled exception filter
   4630             previousTop = SetUnhandledExceptionFilter(handleException);
   4631             // Pass in guarantee size to be filled
   4632             SetThreadStackGuarantee(&guaranteeSize);
   4633 
   4634             // On Windows uncaught exceptions from another thread, exceptions from
   4635             // destructors, or calls to std::terminate are not a SEH exception
   4636 
   4637             // The terminal handler gets called when:
   4638             // - std::terminate is called FROM THE TEST RUNNER THREAD
   4639             // - an exception is thrown from a destructor FROM THE TEST RUNNER THREAD
   4640             original_terminate_handler = std::get_terminate();
   4641             std::set_terminate([]() DOCTEST_NOEXCEPT {
   4642                 reportFatal("Terminate handler called");
   4643                 if(isDebuggerActive() && !g_cs->no_breaks)
   4644                     DOCTEST_BREAK_INTO_DEBUGGER();
   4645                 std::exit(EXIT_FAILURE); // explicitly exit - otherwise the SIGABRT handler may be called as well
   4646             });
   4647 
   4648             // SIGABRT is raised when:
   4649             // - std::terminate is called FROM A DIFFERENT THREAD
   4650             // - an exception is thrown from a destructor FROM A DIFFERENT THREAD
   4651             // - an uncaught exception is thrown FROM A DIFFERENT THREAD
   4652             prev_sigabrt_handler = std::signal(SIGABRT, [](int signal) DOCTEST_NOEXCEPT {
   4653                 if(signal == SIGABRT) {
   4654                     reportFatal("SIGABRT - Abort (abnormal termination) signal");
   4655                     if(isDebuggerActive() && !g_cs->no_breaks)
   4656                         DOCTEST_BREAK_INTO_DEBUGGER();
   4657                     std::exit(EXIT_FAILURE);
   4658                 }
   4659             });
   4660 
   4661             // The following settings are taken from google test, and more
   4662             // specifically from UnitTest::Run() inside of gtest.cc
   4663 
   4664             // the user does not want to see pop-up dialogs about crashes
   4665             prev_error_mode_1 = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT |
   4666                                              SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
   4667             // This forces the abort message to go to stderr in all circumstances.
   4668             prev_error_mode_2 = _set_error_mode(_OUT_TO_STDERR);
   4669             // In the debug version, Visual Studio pops up a separate dialog
   4670             // offering a choice to debug the aborted program - we want to disable that.
   4671             prev_abort_behavior = _set_abort_behavior(0x0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
   4672             // In debug mode, the Windows CRT can crash with an assertion over invalid
   4673             // input (e.g. passing an invalid file descriptor). The default handling
   4674             // for these assertions is to pop up a dialog and wait for user input.
   4675             // Instead ask the CRT to dump such assertions to stderr non-interactively.
   4676             prev_report_mode = _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
   4677             prev_report_file = _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
   4678         }
   4679 
   4680         static void reset() {
   4681             if(isSet) {
   4682                 // Unregister handler and restore the old guarantee
   4683                 SetUnhandledExceptionFilter(previousTop);
   4684                 SetThreadStackGuarantee(&guaranteeSize);
   4685                 std::set_terminate(original_terminate_handler);
   4686                 std::signal(SIGABRT, prev_sigabrt_handler);
   4687                 SetErrorMode(prev_error_mode_1);
   4688                 _set_error_mode(prev_error_mode_2);
   4689                 _set_abort_behavior(prev_abort_behavior, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
   4690                 static_cast<void>(_CrtSetReportMode(_CRT_ASSERT, prev_report_mode));
   4691                 static_cast<void>(_CrtSetReportFile(_CRT_ASSERT, prev_report_file));
   4692                 isSet = false;
   4693             }
   4694         }
   4695 
   4696         ~FatalConditionHandler() { reset(); }
   4697 
   4698     private:
   4699         static UINT         prev_error_mode_1;
   4700         static int          prev_error_mode_2;
   4701         static unsigned int prev_abort_behavior;
   4702         static int          prev_report_mode;
   4703         static _HFILE       prev_report_file;
   4704         static void (DOCTEST_CDECL *prev_sigabrt_handler)(int);
   4705         static std::terminate_handler original_terminate_handler;
   4706         static bool isSet;
   4707         static ULONG guaranteeSize;
   4708         static LPTOP_LEVEL_EXCEPTION_FILTER previousTop;
   4709     };
   4710 
   4711     UINT         FatalConditionHandler::prev_error_mode_1;
   4712     int          FatalConditionHandler::prev_error_mode_2;
   4713     unsigned int FatalConditionHandler::prev_abort_behavior;
   4714     int          FatalConditionHandler::prev_report_mode;
   4715     _HFILE       FatalConditionHandler::prev_report_file;
   4716     void (DOCTEST_CDECL *FatalConditionHandler::prev_sigabrt_handler)(int);
   4717     std::terminate_handler FatalConditionHandler::original_terminate_handler;
   4718     bool FatalConditionHandler::isSet = false;
   4719     ULONG FatalConditionHandler::guaranteeSize = 0;
   4720     LPTOP_LEVEL_EXCEPTION_FILTER FatalConditionHandler::previousTop = nullptr;
   4721 
   4722 #else // DOCTEST_PLATFORM_WINDOWS
   4723 
   4724     struct SignalDefs
   4725     {
   4726         int         id;
   4727         const char* name;
   4728     };
   4729     SignalDefs signalDefs[] = {{SIGINT, "SIGINT - Terminal interrupt signal"},
   4730                                {SIGILL, "SIGILL - Illegal instruction signal"},
   4731                                {SIGFPE, "SIGFPE - Floating point error signal"},
   4732                                {SIGSEGV, "SIGSEGV - Segmentation violation signal"},
   4733                                {SIGTERM, "SIGTERM - Termination request signal"},
   4734                                {SIGABRT, "SIGABRT - Abort (abnormal termination) signal"}};
   4735 
   4736     struct FatalConditionHandler
   4737     {
   4738         static bool             isSet;
   4739         static struct sigaction oldSigActions[DOCTEST_COUNTOF(signalDefs)];
   4740         static stack_t          oldSigStack;
   4741         static size_t           altStackSize;
   4742         static char*            altStackMem;
   4743 
   4744         static void handleSignal(int sig) {
   4745             const char* name = "<unknown signal>";
   4746             for(std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) {
   4747                 SignalDefs& def = signalDefs[i];
   4748                 if(sig == def.id) {
   4749                     name = def.name;
   4750                     break;
   4751                 }
   4752             }
   4753             reset();
   4754             reportFatal(name);
   4755             raise(sig);
   4756         }
   4757 
   4758         static void allocateAltStackMem() {
   4759             altStackMem = new char[altStackSize];
   4760         }
   4761 
   4762         static void freeAltStackMem() {
   4763             delete[] altStackMem;
   4764         }
   4765 
   4766         FatalConditionHandler() {
   4767             isSet = true;
   4768             stack_t sigStack;
   4769             sigStack.ss_sp    = altStackMem;
   4770             sigStack.ss_size  = altStackSize;
   4771             sigStack.ss_flags = 0;
   4772             sigaltstack(&sigStack, &oldSigStack);
   4773             struct sigaction sa = {};
   4774             sa.sa_handler       = handleSignal;
   4775             sa.sa_flags         = SA_ONSTACK;
   4776             for(std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) {
   4777                 sigaction(signalDefs[i].id, &sa, &oldSigActions[i]);
   4778             }
   4779         }
   4780 
   4781         ~FatalConditionHandler() { reset(); }
   4782         static void reset() {
   4783             if(isSet) {
   4784                 // Set signals back to previous values -- hopefully nobody overwrote them in the meantime
   4785                 for(std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) {
   4786                     sigaction(signalDefs[i].id, &oldSigActions[i], nullptr);
   4787                 }
   4788                 // Return the old stack
   4789                 sigaltstack(&oldSigStack, nullptr);
   4790                 isSet = false;
   4791             }
   4792         }
   4793     };
   4794 
   4795     bool             FatalConditionHandler::isSet = false;
   4796     struct sigaction FatalConditionHandler::oldSigActions[DOCTEST_COUNTOF(signalDefs)] = {};
   4797     stack_t          FatalConditionHandler::oldSigStack = {};
   4798     size_t           FatalConditionHandler::altStackSize = 4 * SIGSTKSZ;
   4799     char*            FatalConditionHandler::altStackMem = nullptr;
   4800 
   4801 #endif // DOCTEST_PLATFORM_WINDOWS
   4802 #endif // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH
   4803 
   4804 } // namespace
   4805 
   4806 namespace {
   4807     using namespace detail;
   4808 
   4809 #ifdef DOCTEST_PLATFORM_WINDOWS
   4810 #define DOCTEST_OUTPUT_DEBUG_STRING(text) ::OutputDebugStringA(text)
   4811 #else
   4812     // TODO: integration with XCode and other IDEs
   4813 #define DOCTEST_OUTPUT_DEBUG_STRING(text)
   4814 #endif // Platform
   4815 
   4816     void addAssert(assertType::Enum at) {
   4817         if((at & assertType::is_warn) == 0) //!OCLINT bitwise operator in conditional
   4818             g_cs->numAssertsCurrentTest_atomic++;
   4819     }
   4820 
   4821     void addFailedAssert(assertType::Enum at) {
   4822         if((at & assertType::is_warn) == 0) //!OCLINT bitwise operator in conditional
   4823             g_cs->numAssertsFailedCurrentTest_atomic++;
   4824     }
   4825 
   4826 #if defined(DOCTEST_CONFIG_POSIX_SIGNALS) || defined(DOCTEST_CONFIG_WINDOWS_SEH)
   4827     void reportFatal(const std::string& message) {
   4828         g_cs->failure_flags |= TestCaseFailureReason::Crash;
   4829 
   4830         DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_exception, {message.c_str(), true});
   4831 
   4832         while (g_cs->subcaseStack.size()) {
   4833             g_cs->subcaseStack.pop_back();
   4834             DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY);
   4835         }
   4836 
   4837         g_cs->finalizeTestCaseData();
   4838 
   4839         DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_end, *g_cs);
   4840 
   4841         DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_end, *g_cs);
   4842     }
   4843 #endif // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH
   4844 } // namespace
   4845 
   4846 AssertData::AssertData(assertType::Enum at, const char* file, int line, const char* expr,
   4847     const char* exception_type, const StringContains& exception_string)
   4848     : m_test_case(g_cs->currentTest), m_at(at), m_file(file), m_line(line), m_expr(expr),
   4849     m_failed(true), m_threw(false), m_threw_as(false), m_exception_type(exception_type),
   4850     m_exception_string(exception_string) {
   4851 #if DOCTEST_MSVC
   4852     if (m_expr[0] == ' ') // this happens when variadic macros are disabled under MSVC
   4853         ++m_expr;
   4854 #endif // MSVC
   4855 }
   4856 
   4857 namespace detail {
   4858     ResultBuilder::ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr,
   4859                                  const char* exception_type, const String& exception_string)
   4860         : AssertData(at, file, line, expr, exception_type, exception_string) { }
   4861 
   4862     ResultBuilder::ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr,
   4863         const char* exception_type, const Contains& exception_string)
   4864         : AssertData(at, file, line, expr, exception_type, exception_string) { }
   4865 
   4866     void ResultBuilder::setResult(const Result& res) {
   4867         m_decomp = res.m_decomp;
   4868         m_failed = !res.m_passed;
   4869     }
   4870 
   4871     void ResultBuilder::translateException() {
   4872         m_threw     = true;
   4873         m_exception = translateActiveException();
   4874     }
   4875 
   4876     bool ResultBuilder::log() {
   4877         if(m_at & assertType::is_throws) { //!OCLINT bitwise operator in conditional
   4878             m_failed = !m_threw;
   4879         } else if((m_at & assertType::is_throws_as) && (m_at & assertType::is_throws_with)) { //!OCLINT
   4880             m_failed = !m_threw_as || !m_exception_string.check(m_exception);
   4881         } else if(m_at & assertType::is_throws_as) { //!OCLINT bitwise operator in conditional
   4882             m_failed = !m_threw_as;
   4883         } else if(m_at & assertType::is_throws_with) { //!OCLINT bitwise operator in conditional
   4884             m_failed = !m_exception_string.check(m_exception);
   4885         } else if(m_at & assertType::is_nothrow) { //!OCLINT bitwise operator in conditional
   4886             m_failed = m_threw;
   4887         }
   4888 
   4889         if(m_exception.size())
   4890             m_exception = "\"" + m_exception + "\"";
   4891 
   4892         if(is_running_in_test) {
   4893             addAssert(m_at);
   4894             DOCTEST_ITERATE_THROUGH_REPORTERS(log_assert, *this);
   4895 
   4896             if(m_failed)
   4897                 addFailedAssert(m_at);
   4898         } else if(m_failed) {
   4899             failed_out_of_a_testing_context(*this);
   4900         }
   4901 
   4902         return m_failed && isDebuggerActive() && !getContextOptions()->no_breaks &&
   4903             (g_cs->currentTest == nullptr || !g_cs->currentTest->m_no_breaks); // break into debugger
   4904     }
   4905 
   4906     void ResultBuilder::react() const {
   4907         if(m_failed && checkIfShouldThrow(m_at))
   4908             throwException();
   4909     }
   4910 
   4911     void failed_out_of_a_testing_context(const AssertData& ad) {
   4912         if(g_cs->ah)
   4913             g_cs->ah(ad);
   4914         else
   4915             std::abort();
   4916     }
   4917 
   4918     bool decomp_assert(assertType::Enum at, const char* file, int line, const char* expr,
   4919                        const Result& result) {
   4920         bool failed = !result.m_passed;
   4921 
   4922         // ###################################################################################
   4923         // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT
   4924         // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED
   4925         // ###################################################################################
   4926         DOCTEST_ASSERT_OUT_OF_TESTS(result.m_decomp);
   4927         DOCTEST_ASSERT_IN_TESTS(result.m_decomp);
   4928         return !failed;
   4929     }
   4930 
   4931     MessageBuilder::MessageBuilder(const char* file, int line, assertType::Enum severity) {
   4932         m_stream   = tlssPush();
   4933         m_file     = file;
   4934         m_line     = line;
   4935         m_severity = severity;
   4936     }
   4937 
   4938     MessageBuilder::~MessageBuilder() {
   4939         if (!logged)
   4940             tlssPop();
   4941     }
   4942 
   4943     DOCTEST_DEFINE_INTERFACE(IExceptionTranslator)
   4944 
   4945     bool MessageBuilder::log() {
   4946         if (!logged) {
   4947             m_string = tlssPop();
   4948             logged = true;
   4949         }
   4950         
   4951         DOCTEST_ITERATE_THROUGH_REPORTERS(log_message, *this);
   4952 
   4953         const bool isWarn = m_severity & assertType::is_warn;
   4954 
   4955         // warn is just a message in this context so we don't treat it as an assert
   4956         if(!isWarn) {
   4957             addAssert(m_severity);
   4958             addFailedAssert(m_severity);
   4959         }
   4960 
   4961         return isDebuggerActive() && !getContextOptions()->no_breaks && !isWarn &&
   4962             (g_cs->currentTest == nullptr || !g_cs->currentTest->m_no_breaks); // break into debugger
   4963     }
   4964 
   4965     void MessageBuilder::react() {
   4966         if(m_severity & assertType::is_require) //!OCLINT bitwise operator in conditional
   4967             throwException();
   4968     }
   4969 } // namespace detail
   4970 namespace {
   4971     using namespace detail;
   4972 
   4973     // clang-format off
   4974 
   4975 // =================================================================================================
   4976 // The following code has been taken verbatim from Catch2/include/internal/catch_xmlwriter.h/cpp
   4977 // This is done so cherry-picking bug fixes is trivial - even the style/formatting is untouched.
   4978 // =================================================================================================
   4979 
   4980     class XmlEncode {
   4981     public:
   4982         enum ForWhat { ForTextNodes, ForAttributes };
   4983 
   4984         XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes );
   4985 
   4986         void encodeTo( std::ostream& os ) const;
   4987 
   4988         friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode );
   4989 
   4990     private:
   4991         std::string m_str;
   4992         ForWhat m_forWhat;
   4993     };
   4994 
   4995     class XmlWriter {
   4996     public:
   4997 
   4998         class ScopedElement {
   4999         public:
   5000             ScopedElement( XmlWriter* writer );
   5001 
   5002             ScopedElement( ScopedElement&& other ) DOCTEST_NOEXCEPT;
   5003             ScopedElement& operator=( ScopedElement&& other ) DOCTEST_NOEXCEPT;
   5004 
   5005             ~ScopedElement();
   5006 
   5007             ScopedElement& writeText( std::string const& text, bool indent = true );
   5008 
   5009             template<typename T>
   5010             ScopedElement& writeAttribute( std::string const& name, T const& attribute ) {
   5011                 m_writer->writeAttribute( name, attribute );
   5012                 return *this;
   5013             }
   5014 
   5015         private:
   5016             mutable XmlWriter* m_writer = nullptr;
   5017         };
   5018 
   5019         XmlWriter( std::ostream& os = std::cout );
   5020         ~XmlWriter();
   5021 
   5022         XmlWriter( XmlWriter const& ) = delete;
   5023         XmlWriter& operator=( XmlWriter const& ) = delete;
   5024 
   5025         XmlWriter& startElement( std::string const& name );
   5026 
   5027         ScopedElement scopedElement( std::string const& name );
   5028 
   5029         XmlWriter& endElement();
   5030 
   5031         XmlWriter& writeAttribute( std::string const& name, std::string const& attribute );
   5032 
   5033         XmlWriter& writeAttribute( std::string const& name, const char* attribute );
   5034 
   5035         XmlWriter& writeAttribute( std::string const& name, bool attribute );
   5036 
   5037         template<typename T>
   5038         XmlWriter& writeAttribute( std::string const& name, T const& attribute ) {
   5039         std::stringstream rss;
   5040             rss << attribute;
   5041             return writeAttribute( name, rss.str() );
   5042         }
   5043 
   5044         XmlWriter& writeText( std::string const& text, bool indent = true );
   5045 
   5046         //XmlWriter& writeComment( std::string const& text );
   5047 
   5048         //void writeStylesheetRef( std::string const& url );
   5049 
   5050         //XmlWriter& writeBlankLine();
   5051 
   5052         void ensureTagClosed();
   5053 
   5054         void writeDeclaration();
   5055 
   5056     private:
   5057 
   5058         void newlineIfNecessary();
   5059 
   5060         bool m_tagIsOpen = false;
   5061         bool m_needsNewline = false;
   5062         std::vector<std::string> m_tags;
   5063         std::string m_indent;
   5064         std::ostream& m_os;
   5065     };
   5066 
   5067 // =================================================================================================
   5068 // The following code has been taken verbatim from Catch2/include/internal/catch_xmlwriter.h/cpp
   5069 // This is done so cherry-picking bug fixes is trivial - even the style/formatting is untouched.
   5070 // =================================================================================================
   5071 
   5072 using uchar = unsigned char;
   5073 
   5074 namespace {
   5075 
   5076     size_t trailingBytes(unsigned char c) {
   5077         if ((c & 0xE0) == 0xC0) {
   5078             return 2;
   5079         }
   5080         if ((c & 0xF0) == 0xE0) {
   5081             return 3;
   5082         }
   5083         if ((c & 0xF8) == 0xF0) {
   5084             return 4;
   5085         }
   5086         DOCTEST_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered");
   5087     }
   5088 
   5089     uint32_t headerValue(unsigned char c) {
   5090         if ((c & 0xE0) == 0xC0) {
   5091             return c & 0x1F;
   5092         }
   5093         if ((c & 0xF0) == 0xE0) {
   5094             return c & 0x0F;
   5095         }
   5096         if ((c & 0xF8) == 0xF0) {
   5097             return c & 0x07;
   5098         }
   5099         DOCTEST_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered");
   5100     }
   5101 
   5102     void hexEscapeChar(std::ostream& os, unsigned char c) {
   5103         std::ios_base::fmtflags f(os.flags());
   5104         os << "\\x"
   5105             << std::uppercase << std::hex << std::setfill('0') << std::setw(2)
   5106             << static_cast<int>(c);
   5107         os.flags(f);
   5108     }
   5109 
   5110 } // anonymous namespace
   5111 
   5112     XmlEncode::XmlEncode( std::string const& str, ForWhat forWhat )
   5113     :   m_str( str ),
   5114         m_forWhat( forWhat )
   5115     {}
   5116 
   5117     void XmlEncode::encodeTo( std::ostream& os ) const {
   5118         // Apostrophe escaping not necessary if we always use " to write attributes
   5119         // (see: https://www.w3.org/TR/xml/#syntax)
   5120 
   5121         for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) {
   5122             uchar c = m_str[idx];
   5123             switch (c) {
   5124             case '<':   os << "&lt;"; break;
   5125             case '&':   os << "&amp;"; break;
   5126 
   5127             case '>':
   5128                 // See: https://www.w3.org/TR/xml/#syntax
   5129                 if (idx > 2 && m_str[idx - 1] == ']' && m_str[idx - 2] == ']')
   5130                     os << "&gt;";
   5131                 else
   5132                     os << c;
   5133                 break;
   5134 
   5135             case '\"':
   5136                 if (m_forWhat == ForAttributes)
   5137                     os << "&quot;";
   5138                 else
   5139                     os << c;
   5140                 break;
   5141 
   5142             default:
   5143                 // Check for control characters and invalid utf-8
   5144 
   5145                 // Escape control characters in standard ascii
   5146                 // see https://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
   5147                 if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) {
   5148                     hexEscapeChar(os, c);
   5149                     break;
   5150                 }
   5151 
   5152                 // Plain ASCII: Write it to stream
   5153                 if (c < 0x7F) {
   5154                     os << c;
   5155                     break;
   5156                 }
   5157 
   5158                 // UTF-8 territory
   5159                 // Check if the encoding is valid and if it is not, hex escape bytes.
   5160                 // Important: We do not check the exact decoded values for validity, only the encoding format
   5161                 // First check that this bytes is a valid lead byte:
   5162                 // This means that it is not encoded as 1111 1XXX
   5163                 // Or as 10XX XXXX
   5164                 if (c <  0xC0 ||
   5165                     c >= 0xF8) {
   5166                     hexEscapeChar(os, c);
   5167                     break;
   5168                 }
   5169 
   5170                 auto encBytes = trailingBytes(c);
   5171                 // Are there enough bytes left to avoid accessing out-of-bounds memory?
   5172                 if (idx + encBytes - 1 >= m_str.size()) {
   5173                     hexEscapeChar(os, c);
   5174                     break;
   5175                 }
   5176                 // The header is valid, check data
   5177                 // The next encBytes bytes must together be a valid utf-8
   5178                 // This means: bitpattern 10XX XXXX and the extracted value is sane (ish)
   5179                 bool valid = true;
   5180                 uint32_t value = headerValue(c);
   5181                 for (std::size_t n = 1; n < encBytes; ++n) {
   5182                     uchar nc = m_str[idx + n];
   5183                     valid &= ((nc & 0xC0) == 0x80);
   5184                     value = (value << 6) | (nc & 0x3F);
   5185                 }
   5186 
   5187                 if (
   5188                     // Wrong bit pattern of following bytes
   5189                     (!valid) ||
   5190                     // Overlong encodings
   5191                     (value < 0x80) ||
   5192                     (                 value < 0x800   && encBytes > 2) || // removed "0x80 <= value &&" because redundant
   5193                     (0x800 < value && value < 0x10000 && encBytes > 3) ||
   5194                     // Encoded value out of range
   5195                     (value >= 0x110000)
   5196                     ) {
   5197                     hexEscapeChar(os, c);
   5198                     break;
   5199                 }
   5200 
   5201                 // If we got here, this is in fact a valid(ish) utf-8 sequence
   5202                 for (std::size_t n = 0; n < encBytes; ++n) {
   5203                     os << m_str[idx + n];
   5204                 }
   5205                 idx += encBytes - 1;
   5206                 break;
   5207             }
   5208         }
   5209     }
   5210 
   5211     std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) {
   5212         xmlEncode.encodeTo( os );
   5213         return os;
   5214     }
   5215 
   5216     XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer )
   5217     :   m_writer( writer )
   5218     {}
   5219 
   5220     XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) DOCTEST_NOEXCEPT
   5221     :   m_writer( other.m_writer ){
   5222         other.m_writer = nullptr;
   5223     }
   5224     XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) DOCTEST_NOEXCEPT {
   5225         if ( m_writer ) {
   5226             m_writer->endElement();
   5227         }
   5228         m_writer = other.m_writer;
   5229         other.m_writer = nullptr;
   5230         return *this;
   5231     }
   5232 
   5233 
   5234     XmlWriter::ScopedElement::~ScopedElement() {
   5235         if( m_writer )
   5236             m_writer->endElement();
   5237     }
   5238 
   5239     XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText( std::string const& text, bool indent ) {
   5240         m_writer->writeText( text, indent );
   5241         return *this;
   5242     }
   5243 
   5244     XmlWriter::XmlWriter( std::ostream& os ) : m_os( os )
   5245     {
   5246         // writeDeclaration(); // called explicitly by the reporters that use the writer class - see issue #627
   5247     }
   5248 
   5249     XmlWriter::~XmlWriter() {
   5250         while( !m_tags.empty() )
   5251             endElement();
   5252     }
   5253 
   5254     XmlWriter& XmlWriter::startElement( std::string const& name ) {
   5255         ensureTagClosed();
   5256         newlineIfNecessary();
   5257         m_os << m_indent << '<' << name;
   5258         m_tags.push_back( name );
   5259         m_indent += "  ";
   5260         m_tagIsOpen = true;
   5261         return *this;
   5262     }
   5263 
   5264     XmlWriter::ScopedElement XmlWriter::scopedElement( std::string const& name ) {
   5265         ScopedElement scoped( this );
   5266         startElement( name );
   5267         return scoped;
   5268     }
   5269 
   5270     XmlWriter& XmlWriter::endElement() {
   5271         newlineIfNecessary();
   5272         m_indent = m_indent.substr( 0, m_indent.size()-2 );
   5273         if( m_tagIsOpen ) {
   5274             m_os << "/>";
   5275             m_tagIsOpen = false;
   5276         }
   5277         else {
   5278             m_os << m_indent << "</" << m_tags.back() << ">";
   5279         }
   5280         m_os << std::endl;
   5281         m_tags.pop_back();
   5282         return *this;
   5283     }
   5284 
   5285     XmlWriter& XmlWriter::writeAttribute( std::string const& name, std::string const& attribute ) {
   5286         if( !name.empty() && !attribute.empty() )
   5287             m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"';
   5288         return *this;
   5289     }
   5290 
   5291     XmlWriter& XmlWriter::writeAttribute( std::string const& name, const char* attribute ) {
   5292         if( !name.empty() && attribute && attribute[0] != '\0' )
   5293             m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"';
   5294         return *this;
   5295     }
   5296 
   5297     XmlWriter& XmlWriter::writeAttribute( std::string const& name, bool attribute ) {
   5298         m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"';
   5299         return *this;
   5300     }
   5301 
   5302     XmlWriter& XmlWriter::writeText( std::string const& text, bool indent ) {
   5303         if( !text.empty() ){
   5304             bool tagWasOpen = m_tagIsOpen;
   5305             ensureTagClosed();
   5306             if( tagWasOpen && indent )
   5307                 m_os << m_indent;
   5308             m_os << XmlEncode( text );
   5309             m_needsNewline = true;
   5310         }
   5311         return *this;
   5312     }
   5313 
   5314     //XmlWriter& XmlWriter::writeComment( std::string const& text ) {
   5315     //    ensureTagClosed();
   5316     //    m_os << m_indent << "<!--" << text << "-->";
   5317     //    m_needsNewline = true;
   5318     //    return *this;
   5319     //}
   5320 
   5321     //void XmlWriter::writeStylesheetRef( std::string const& url ) {
   5322     //    m_os << "<?xml-stylesheet type=\"text/xsl\" href=\"" << url << "\"?>\n";
   5323     //}
   5324 
   5325     //XmlWriter& XmlWriter::writeBlankLine() {
   5326     //    ensureTagClosed();
   5327     //    m_os << '\n';
   5328     //    return *this;
   5329     //}
   5330 
   5331     void XmlWriter::ensureTagClosed() {
   5332         if( m_tagIsOpen ) {
   5333             m_os << ">" << std::endl;
   5334             m_tagIsOpen = false;
   5335         }
   5336     }
   5337 
   5338     void XmlWriter::writeDeclaration() {
   5339         m_os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
   5340     }
   5341 
   5342     void XmlWriter::newlineIfNecessary() {
   5343         if( m_needsNewline ) {
   5344             m_os << std::endl;
   5345             m_needsNewline = false;
   5346         }
   5347     }
   5348 
   5349 // =================================================================================================
   5350 // End of copy-pasted code from Catch
   5351 // =================================================================================================
   5352 
   5353     // clang-format on
   5354 
   5355     struct XmlReporter : public IReporter
   5356     {
   5357         XmlWriter xml;
   5358         DOCTEST_DECLARE_MUTEX(mutex)
   5359 
   5360         // caching pointers/references to objects of these types - safe to do
   5361         const ContextOptions& opt;
   5362         const TestCaseData*   tc = nullptr;
   5363 
   5364         XmlReporter(const ContextOptions& co)
   5365                 : xml(*co.cout)
   5366                 , opt(co) {}
   5367 
   5368         void log_contexts() {
   5369             int num_contexts = get_num_active_contexts();
   5370             if(num_contexts) {
   5371                 auto              contexts = get_active_contexts();
   5372                 std::stringstream ss;
   5373                 for(int i = 0; i < num_contexts; ++i) {
   5374                     contexts[i]->stringify(&ss);
   5375                     xml.scopedElement("Info").writeText(ss.str());
   5376                     ss.str("");
   5377                 }
   5378             }
   5379         }
   5380 
   5381         unsigned line(unsigned l) const { return opt.no_line_numbers ? 0 : l; }
   5382 
   5383         void test_case_start_impl(const TestCaseData& in) {
   5384             bool open_ts_tag = false;
   5385             if(tc != nullptr) { // we have already opened a test suite
   5386                 if(std::strcmp(tc->m_test_suite, in.m_test_suite) != 0) {
   5387                     xml.endElement();
   5388                     open_ts_tag = true;
   5389                 }
   5390             }
   5391             else {
   5392                 open_ts_tag = true; // first test case ==> first test suite
   5393             }
   5394 
   5395             if(open_ts_tag) {
   5396                 xml.startElement("TestSuite");
   5397                 xml.writeAttribute("name", in.m_test_suite);
   5398             }
   5399 
   5400             tc = &in;
   5401             xml.startElement("TestCase")
   5402                     .writeAttribute("name", in.m_name)
   5403                     .writeAttribute("filename", skipPathFromFilename(in.m_file.c_str()))
   5404                     .writeAttribute("line", line(in.m_line))
   5405                     .writeAttribute("description", in.m_description);
   5406 
   5407             if(Approx(in.m_timeout) != 0)
   5408                 xml.writeAttribute("timeout", in.m_timeout);
   5409             if(in.m_may_fail)
   5410                 xml.writeAttribute("may_fail", true);
   5411             if(in.m_should_fail)
   5412                 xml.writeAttribute("should_fail", true);
   5413         }
   5414 
   5415         // =========================================================================================
   5416         // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE
   5417         // =========================================================================================
   5418 
   5419         void report_query(const QueryData& in) override {
   5420             test_run_start();
   5421             if(opt.list_reporters) {
   5422                 for(auto& curr : getListeners())
   5423                     xml.scopedElement("Listener")
   5424                             .writeAttribute("priority", curr.first.first)
   5425                             .writeAttribute("name", curr.first.second);
   5426                 for(auto& curr : getReporters())
   5427                     xml.scopedElement("Reporter")
   5428                             .writeAttribute("priority", curr.first.first)
   5429                             .writeAttribute("name", curr.first.second);
   5430             } else if(opt.count || opt.list_test_cases) {
   5431                 for(unsigned i = 0; i < in.num_data; ++i) {
   5432                     xml.scopedElement("TestCase").writeAttribute("name", in.data[i]->m_name)
   5433                         .writeAttribute("testsuite", in.data[i]->m_test_suite)
   5434                         .writeAttribute("filename", skipPathFromFilename(in.data[i]->m_file.c_str()))
   5435                         .writeAttribute("line", line(in.data[i]->m_line))
   5436                         .writeAttribute("skipped", in.data[i]->m_skip);
   5437                 }
   5438                 xml.scopedElement("OverallResultsTestCases")
   5439                         .writeAttribute("unskipped", in.run_stats->numTestCasesPassingFilters);
   5440             } else if(opt.list_test_suites) {
   5441                 for(unsigned i = 0; i < in.num_data; ++i)
   5442                     xml.scopedElement("TestSuite").writeAttribute("name", in.data[i]->m_test_suite);
   5443                 xml.scopedElement("OverallResultsTestCases")
   5444                         .writeAttribute("unskipped", in.run_stats->numTestCasesPassingFilters);
   5445                 xml.scopedElement("OverallResultsTestSuites")
   5446                         .writeAttribute("unskipped", in.run_stats->numTestSuitesPassingFilters);
   5447             }
   5448             xml.endElement();
   5449         }
   5450 
   5451         void test_run_start() override {
   5452             xml.writeDeclaration();
   5453 
   5454             // remove .exe extension - mainly to have the same output on UNIX and Windows
   5455             std::string binary_name = skipPathFromFilename(opt.binary_name.c_str());
   5456 #ifdef DOCTEST_PLATFORM_WINDOWS
   5457             if(binary_name.rfind(".exe") != std::string::npos)
   5458                 binary_name = binary_name.substr(0, binary_name.length() - 4);
   5459 #endif // DOCTEST_PLATFORM_WINDOWS
   5460 
   5461             xml.startElement("doctest").writeAttribute("binary", binary_name);
   5462             if(opt.no_version == false)
   5463                 xml.writeAttribute("version", DOCTEST_VERSION_STR);
   5464 
   5465             // only the consequential ones (TODO: filters)
   5466             xml.scopedElement("Options")
   5467                     .writeAttribute("order_by", opt.order_by.c_str())
   5468                     .writeAttribute("rand_seed", opt.rand_seed)
   5469                     .writeAttribute("first", opt.first)
   5470                     .writeAttribute("last", opt.last)
   5471                     .writeAttribute("abort_after", opt.abort_after)
   5472                     .writeAttribute("subcase_filter_levels", opt.subcase_filter_levels)
   5473                     .writeAttribute("case_sensitive", opt.case_sensitive)
   5474                     .writeAttribute("no_throw", opt.no_throw)
   5475                     .writeAttribute("no_skip", opt.no_skip);
   5476         }
   5477 
   5478         void test_run_end(const TestRunStats& p) override {
   5479             if(tc) // the TestSuite tag - only if there has been at least 1 test case
   5480                 xml.endElement();
   5481 
   5482             xml.scopedElement("OverallResultsAsserts")
   5483                     .writeAttribute("successes", p.numAsserts - p.numAssertsFailed)
   5484                     .writeAttribute("failures", p.numAssertsFailed);
   5485 
   5486             xml.startElement("OverallResultsTestCases")
   5487                     .writeAttribute("successes",
   5488                                     p.numTestCasesPassingFilters - p.numTestCasesFailed)
   5489                     .writeAttribute("failures", p.numTestCasesFailed);
   5490             if(opt.no_skipped_summary == false)
   5491                 xml.writeAttribute("skipped", p.numTestCases - p.numTestCasesPassingFilters);
   5492             xml.endElement();
   5493 
   5494             xml.endElement();
   5495         }
   5496 
   5497         void test_case_start(const TestCaseData& in) override {
   5498             test_case_start_impl(in);
   5499             xml.ensureTagClosed();
   5500         }
   5501         
   5502         void test_case_reenter(const TestCaseData&) override {}
   5503 
   5504         void test_case_end(const CurrentTestCaseStats& st) override {
   5505             xml.startElement("OverallResultsAsserts")
   5506                     .writeAttribute("successes",
   5507                                     st.numAssertsCurrentTest - st.numAssertsFailedCurrentTest)
   5508                     .writeAttribute("failures", st.numAssertsFailedCurrentTest)
   5509                     .writeAttribute("test_case_success", st.testCaseSuccess);
   5510             if(opt.duration)
   5511                 xml.writeAttribute("duration", st.seconds);
   5512             if(tc->m_expected_failures)
   5513                 xml.writeAttribute("expected_failures", tc->m_expected_failures);
   5514             xml.endElement();
   5515 
   5516             xml.endElement();
   5517         }
   5518 
   5519         void test_case_exception(const TestCaseException& e) override {
   5520             DOCTEST_LOCK_MUTEX(mutex)
   5521 
   5522             xml.scopedElement("Exception")
   5523                     .writeAttribute("crash", e.is_crash)
   5524                     .writeText(e.error_string.c_str());
   5525         }
   5526 
   5527         void subcase_start(const SubcaseSignature& in) override {
   5528             xml.startElement("SubCase")
   5529                     .writeAttribute("name", in.m_name)
   5530                     .writeAttribute("filename", skipPathFromFilename(in.m_file))
   5531                     .writeAttribute("line", line(in.m_line));
   5532             xml.ensureTagClosed();
   5533         }
   5534 
   5535         void subcase_end() override { xml.endElement(); }
   5536 
   5537         void log_assert(const AssertData& rb) override {
   5538             if(!rb.m_failed && !opt.success)
   5539                 return;
   5540 
   5541             DOCTEST_LOCK_MUTEX(mutex)
   5542 
   5543             xml.startElement("Expression")
   5544                     .writeAttribute("success", !rb.m_failed)
   5545                     .writeAttribute("type", assertString(rb.m_at))
   5546                     .writeAttribute("filename", skipPathFromFilename(rb.m_file))
   5547                     .writeAttribute("line", line(rb.m_line));
   5548 
   5549             xml.scopedElement("Original").writeText(rb.m_expr);
   5550 
   5551             if(rb.m_threw)
   5552                 xml.scopedElement("Exception").writeText(rb.m_exception.c_str());
   5553 
   5554             if(rb.m_at & assertType::is_throws_as)
   5555                 xml.scopedElement("ExpectedException").writeText(rb.m_exception_type);
   5556             if(rb.m_at & assertType::is_throws_with)
   5557                 xml.scopedElement("ExpectedExceptionString").writeText(rb.m_exception_string.c_str());
   5558             if((rb.m_at & assertType::is_normal) && !rb.m_threw)
   5559                 xml.scopedElement("Expanded").writeText(rb.m_decomp.c_str());
   5560 
   5561             log_contexts();
   5562 
   5563             xml.endElement();
   5564         }
   5565 
   5566         void log_message(const MessageData& mb) override {
   5567             DOCTEST_LOCK_MUTEX(mutex)
   5568 
   5569             xml.startElement("Message")
   5570                     .writeAttribute("type", failureString(mb.m_severity))
   5571                     .writeAttribute("filename", skipPathFromFilename(mb.m_file))
   5572                     .writeAttribute("line", line(mb.m_line));
   5573 
   5574             xml.scopedElement("Text").writeText(mb.m_string.c_str());
   5575 
   5576             log_contexts();
   5577 
   5578             xml.endElement();
   5579         }
   5580 
   5581         void test_case_skipped(const TestCaseData& in) override {
   5582             if(opt.no_skipped_summary == false) {
   5583                 test_case_start_impl(in);
   5584                 xml.writeAttribute("skipped", "true");
   5585                 xml.endElement();
   5586             }
   5587         }
   5588     };
   5589 
   5590     DOCTEST_REGISTER_REPORTER("xml", 0, XmlReporter);
   5591 
   5592     void fulltext_log_assert_to_stream(std::ostream& s, const AssertData& rb) {
   5593         if((rb.m_at & (assertType::is_throws_as | assertType::is_throws_with)) ==
   5594             0) //!OCLINT bitwise operator in conditional
   5595             s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << " ) "
   5596                 << Color::None;
   5597 
   5598         if(rb.m_at & assertType::is_throws) { //!OCLINT bitwise operator in conditional
   5599             s << (rb.m_threw ? "threw as expected!" : "did NOT throw at all!") << "\n";
   5600         } else if((rb.m_at & assertType::is_throws_as) &&
   5601                     (rb.m_at & assertType::is_throws_with)) { //!OCLINT
   5602             s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \""
   5603                 << rb.m_exception_string.c_str()
   5604                 << "\", " << rb.m_exception_type << " ) " << Color::None;
   5605             if(rb.m_threw) {
   5606                 if(!rb.m_failed) {
   5607                     s << "threw as expected!\n";
   5608                 } else {
   5609                     s << "threw a DIFFERENT exception! (contents: " << rb.m_exception << ")\n";
   5610                 }
   5611             } else {
   5612                 s << "did NOT throw at all!\n";
   5613             }
   5614         } else if(rb.m_at &
   5615                     assertType::is_throws_as) { //!OCLINT bitwise operator in conditional
   5616             s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", "
   5617                 << rb.m_exception_type << " ) " << Color::None
   5618                 << (rb.m_threw ? (rb.m_threw_as ? "threw as expected!" :
   5619                                                 "threw a DIFFERENT exception: ") :
   5620                                 "did NOT throw at all!")
   5621                 << Color::Cyan << rb.m_exception << "\n";
   5622         } else if(rb.m_at &
   5623                     assertType::is_throws_with) { //!OCLINT bitwise operator in conditional
   5624             s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \""
   5625                 << rb.m_exception_string.c_str()
   5626                 << "\" ) " << Color::None
   5627                 << (rb.m_threw ? (!rb.m_failed ? "threw as expected!" :
   5628                                                 "threw a DIFFERENT exception: ") :
   5629                                 "did NOT throw at all!")
   5630                 << Color::Cyan << rb.m_exception << "\n";
   5631         } else if(rb.m_at & assertType::is_nothrow) { //!OCLINT bitwise operator in conditional
   5632             s << (rb.m_threw ? "THREW exception: " : "didn't throw!") << Color::Cyan
   5633                 << rb.m_exception << "\n";
   5634         } else {
   5635             s << (rb.m_threw ? "THREW exception: " :
   5636                                 (!rb.m_failed ? "is correct!\n" : "is NOT correct!\n"));
   5637             if(rb.m_threw)
   5638                 s << rb.m_exception << "\n";
   5639             else
   5640                 s << "  values: " << assertString(rb.m_at) << "( " << rb.m_decomp << " )\n";
   5641         }
   5642     }
   5643 
   5644     // TODO:
   5645     // - log_message()
   5646     // - respond to queries
   5647     // - honor remaining options
   5648     // - more attributes in tags
   5649     struct JUnitReporter : public IReporter
   5650     {
   5651         XmlWriter xml;
   5652         DOCTEST_DECLARE_MUTEX(mutex)
   5653         Timer timer;
   5654         std::vector<String> deepestSubcaseStackNames;
   5655 
   5656         struct JUnitTestCaseData
   5657         {
   5658             static std::string getCurrentTimestamp() {
   5659                 // Beware, this is not reentrant because of backward compatibility issues
   5660                 // Also, UTC only, again because of backward compatibility (%z is C++11)
   5661                 time_t rawtime;
   5662                 std::time(&rawtime);
   5663                 auto const timeStampSize = sizeof("2017-01-16T17:06:45Z");
   5664 
   5665                 std::tm timeInfo;
   5666 #ifdef DOCTEST_PLATFORM_WINDOWS
   5667                 gmtime_s(&timeInfo, &rawtime);
   5668 #else // DOCTEST_PLATFORM_WINDOWS
   5669                 gmtime_r(&rawtime, &timeInfo);
   5670 #endif // DOCTEST_PLATFORM_WINDOWS
   5671 
   5672                 char timeStamp[timeStampSize];
   5673                 const char* const fmt = "%Y-%m-%dT%H:%M:%SZ";
   5674 
   5675                 std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
   5676                 return std::string(timeStamp);
   5677             }
   5678 
   5679             struct JUnitTestMessage
   5680             {
   5681                 JUnitTestMessage(const std::string& _message, const std::string& _type, const std::string& _details)
   5682                     : message(_message), type(_type), details(_details) {}
   5683 
   5684                 JUnitTestMessage(const std::string& _message, const std::string& _details)
   5685                     : message(_message), type(), details(_details) {}
   5686 
   5687                 std::string message, type, details;
   5688             };
   5689 
   5690             struct JUnitTestCase
   5691             {
   5692                 JUnitTestCase(const std::string& _classname, const std::string& _name)
   5693                     : classname(_classname), name(_name), time(0), failures() {}
   5694 
   5695                 std::string classname, name;
   5696                 double time;
   5697                 std::vector<JUnitTestMessage> failures, errors;
   5698             };
   5699 
   5700             void add(const std::string& classname, const std::string& name) {
   5701                 testcases.emplace_back(classname, name);
   5702             }
   5703 
   5704             void appendSubcaseNamesToLastTestcase(std::vector<String> nameStack) {
   5705                 for(auto& curr: nameStack)
   5706                     if(curr.size())
   5707                         testcases.back().name += std::string("/") + curr.c_str();
   5708             }
   5709 
   5710             void addTime(double time) {
   5711                 if(time < 1e-4)
   5712                     time = 0;
   5713                 testcases.back().time = time;
   5714                 totalSeconds += time;
   5715             }
   5716 
   5717             void addFailure(const std::string& message, const std::string& type, const std::string& details) {
   5718                 testcases.back().failures.emplace_back(message, type, details);
   5719                 ++totalFailures;
   5720             }
   5721 
   5722             void addError(const std::string& message, const std::string& details) {
   5723                 testcases.back().errors.emplace_back(message, details);
   5724                 ++totalErrors;
   5725             }
   5726 
   5727             std::vector<JUnitTestCase> testcases;
   5728             double totalSeconds = 0;
   5729             int totalErrors = 0, totalFailures = 0;
   5730         };
   5731 
   5732         JUnitTestCaseData testCaseData;
   5733 
   5734         // caching pointers/references to objects of these types - safe to do
   5735         const ContextOptions& opt;
   5736         const TestCaseData*   tc = nullptr;
   5737 
   5738         JUnitReporter(const ContextOptions& co)
   5739                 : xml(*co.cout)
   5740                 , opt(co) {}
   5741 
   5742         unsigned line(unsigned l) const { return opt.no_line_numbers ? 0 : l; }
   5743 
   5744         // =========================================================================================
   5745         // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE
   5746         // =========================================================================================
   5747 
   5748         void report_query(const QueryData&) override {
   5749             xml.writeDeclaration();
   5750         }
   5751 
   5752         void test_run_start() override {
   5753             xml.writeDeclaration();
   5754         }
   5755 
   5756         void test_run_end(const TestRunStats& p) override {
   5757             // remove .exe extension - mainly to have the same output on UNIX and Windows
   5758             std::string binary_name = skipPathFromFilename(opt.binary_name.c_str());
   5759 #ifdef DOCTEST_PLATFORM_WINDOWS
   5760             if(binary_name.rfind(".exe") != std::string::npos)
   5761                 binary_name = binary_name.substr(0, binary_name.length() - 4);
   5762 #endif // DOCTEST_PLATFORM_WINDOWS
   5763             xml.startElement("testsuites");
   5764             xml.startElement("testsuite").writeAttribute("name", binary_name)
   5765                     .writeAttribute("errors", testCaseData.totalErrors)
   5766                     .writeAttribute("failures", testCaseData.totalFailures)
   5767                     .writeAttribute("tests", p.numAsserts);
   5768             if(opt.no_time_in_output == false) {
   5769                 xml.writeAttribute("time", testCaseData.totalSeconds);
   5770                 xml.writeAttribute("timestamp", JUnitTestCaseData::getCurrentTimestamp());
   5771             }
   5772             if(opt.no_version == false)
   5773                 xml.writeAttribute("doctest_version", DOCTEST_VERSION_STR);
   5774 
   5775             for(const auto& testCase : testCaseData.testcases) {
   5776                 xml.startElement("testcase")
   5777                     .writeAttribute("classname", testCase.classname)
   5778                     .writeAttribute("name", testCase.name);
   5779                 if(opt.no_time_in_output == false)
   5780                     xml.writeAttribute("time", testCase.time);
   5781                 // This is not ideal, but it should be enough to mimic gtest's junit output.
   5782                 xml.writeAttribute("status", "run");
   5783 
   5784                 for(const auto& failure : testCase.failures) {
   5785                     xml.scopedElement("failure")
   5786                         .writeAttribute("message", failure.message)
   5787                         .writeAttribute("type", failure.type)
   5788                         .writeText(failure.details, false);
   5789                 }
   5790 
   5791                 for(const auto& error : testCase.errors) {
   5792                     xml.scopedElement("error")
   5793                         .writeAttribute("message", error.message)
   5794                         .writeText(error.details);
   5795                 }
   5796 
   5797                 xml.endElement();
   5798             }
   5799             xml.endElement();
   5800             xml.endElement();
   5801         }
   5802 
   5803         void test_case_start(const TestCaseData& in) override {
   5804             testCaseData.add(skipPathFromFilename(in.m_file.c_str()), in.m_name);
   5805             timer.start();
   5806         }
   5807 
   5808         void test_case_reenter(const TestCaseData& in) override {
   5809             testCaseData.addTime(timer.getElapsedSeconds());
   5810             testCaseData.appendSubcaseNamesToLastTestcase(deepestSubcaseStackNames);
   5811             deepestSubcaseStackNames.clear();
   5812 
   5813             timer.start();
   5814             testCaseData.add(skipPathFromFilename(in.m_file.c_str()), in.m_name);
   5815         }
   5816 
   5817         void test_case_end(const CurrentTestCaseStats&) override {
   5818             testCaseData.addTime(timer.getElapsedSeconds());
   5819             testCaseData.appendSubcaseNamesToLastTestcase(deepestSubcaseStackNames);
   5820             deepestSubcaseStackNames.clear();
   5821         }
   5822 
   5823         void test_case_exception(const TestCaseException& e) override {
   5824             DOCTEST_LOCK_MUTEX(mutex)
   5825             testCaseData.addError("exception", e.error_string.c_str());
   5826         }
   5827 
   5828         void subcase_start(const SubcaseSignature& in) override {
   5829             deepestSubcaseStackNames.push_back(in.m_name);
   5830         }
   5831 
   5832         void subcase_end() override {}
   5833 
   5834         void log_assert(const AssertData& rb) override {
   5835             if(!rb.m_failed) // report only failures & ignore the `success` option
   5836                 return;
   5837 
   5838             DOCTEST_LOCK_MUTEX(mutex)
   5839 
   5840             std::ostringstream os;
   5841             os << skipPathFromFilename(rb.m_file) << (opt.gnu_file_line ? ":" : "(")
   5842               << line(rb.m_line) << (opt.gnu_file_line ? ":" : "):") << std::endl;
   5843 
   5844             fulltext_log_assert_to_stream(os, rb);
   5845             log_contexts(os);
   5846             testCaseData.addFailure(rb.m_decomp.c_str(), assertString(rb.m_at), os.str());
   5847         }
   5848 
   5849         void log_message(const MessageData&) override {}
   5850 
   5851         void test_case_skipped(const TestCaseData&) override {}
   5852 
   5853         void log_contexts(std::ostringstream& s) {
   5854             int num_contexts = get_num_active_contexts();
   5855             if(num_contexts) {
   5856                 auto contexts = get_active_contexts();
   5857 
   5858                 s << "  logged: ";
   5859                 for(int i = 0; i < num_contexts; ++i) {
   5860                     s << (i == 0 ? "" : "          ");
   5861                     contexts[i]->stringify(&s);
   5862                     s << std::endl;
   5863                 }
   5864             }
   5865         }
   5866     };
   5867 
   5868     DOCTEST_REGISTER_REPORTER("junit", 0, JUnitReporter);
   5869 
   5870     struct Whitespace
   5871     {
   5872         int nrSpaces;
   5873         explicit Whitespace(int nr)
   5874                 : nrSpaces(nr) {}
   5875     };
   5876 
   5877     std::ostream& operator<<(std::ostream& out, const Whitespace& ws) {
   5878         if(ws.nrSpaces != 0)
   5879             out << std::setw(ws.nrSpaces) << ' ';
   5880         return out;
   5881     }
   5882 
   5883     struct ConsoleReporter : public IReporter
   5884     {
   5885         std::ostream&                 s;
   5886         bool                          hasLoggedCurrentTestStart;
   5887         std::vector<SubcaseSignature> subcasesStack;
   5888         size_t                        currentSubcaseLevel;
   5889         DOCTEST_DECLARE_MUTEX(mutex)
   5890 
   5891         // caching pointers/references to objects of these types - safe to do
   5892         const ContextOptions& opt;
   5893         const TestCaseData*   tc;
   5894 
   5895         ConsoleReporter(const ContextOptions& co)
   5896                 : s(*co.cout)
   5897                 , opt(co) {}
   5898 
   5899         ConsoleReporter(const ContextOptions& co, std::ostream& ostr)
   5900                 : s(ostr)
   5901                 , opt(co) {}
   5902 
   5903         // =========================================================================================
   5904         // WHAT FOLLOWS ARE HELPERS USED BY THE OVERRIDES OF THE VIRTUAL METHODS OF THE INTERFACE
   5905         // =========================================================================================
   5906 
   5907         void separator_to_stream() {
   5908             s << Color::Yellow
   5909               << "==============================================================================="
   5910                  "\n";
   5911         }
   5912 
   5913         const char* getSuccessOrFailString(bool success, assertType::Enum at,
   5914                                            const char* success_str) {
   5915             if(success)
   5916                 return success_str;
   5917             return failureString(at);
   5918         }
   5919 
   5920         Color::Enum getSuccessOrFailColor(bool success, assertType::Enum at) {
   5921             return success ? Color::BrightGreen :
   5922                              (at & assertType::is_warn) ? Color::Yellow : Color::Red;
   5923         }
   5924 
   5925         void successOrFailColoredStringToStream(bool success, assertType::Enum at,
   5926                                                 const char* success_str = "SUCCESS") {
   5927             s << getSuccessOrFailColor(success, at)
   5928               << getSuccessOrFailString(success, at, success_str) << ": ";
   5929         }
   5930 
   5931         void log_contexts() {
   5932             int num_contexts = get_num_active_contexts();
   5933             if(num_contexts) {
   5934                 auto contexts = get_active_contexts();
   5935 
   5936                 s << Color::None << "  logged: ";
   5937                 for(int i = 0; i < num_contexts; ++i) {
   5938                     s << (i == 0 ? "" : "          ");
   5939                     contexts[i]->stringify(&s);
   5940                     s << "\n";
   5941                 }
   5942             }
   5943 
   5944             s << "\n";
   5945         }
   5946 
   5947         // this was requested to be made virtual so users could override it
   5948         virtual void file_line_to_stream(const char* file, int line,
   5949                                         const char* tail = "") {
   5950             s << Color::LightGrey << skipPathFromFilename(file) << (opt.gnu_file_line ? ":" : "(")
   5951             << (opt.no_line_numbers ? 0 : line) // 0 or the real num depending on the option
   5952             << (opt.gnu_file_line ? ":" : "):") << tail;
   5953         }
   5954 
   5955         void logTestStart() {
   5956             if(hasLoggedCurrentTestStart)
   5957                 return;
   5958 
   5959             separator_to_stream();
   5960             file_line_to_stream(tc->m_file.c_str(), tc->m_line, "\n");
   5961             if(tc->m_description)
   5962                 s << Color::Yellow << "DESCRIPTION: " << Color::None << tc->m_description << "\n";
   5963             if(tc->m_test_suite && tc->m_test_suite[0] != '\0')
   5964                 s << Color::Yellow << "TEST SUITE: " << Color::None << tc->m_test_suite << "\n";
   5965             if(strncmp(tc->m_name, "  Scenario:", 11) != 0)
   5966                 s << Color::Yellow << "TEST CASE:  ";
   5967             s << Color::None << tc->m_name << "\n";
   5968 
   5969             for(size_t i = 0; i < currentSubcaseLevel; ++i) {
   5970                 if(subcasesStack[i].m_name[0] != '\0')
   5971                     s << "  " << subcasesStack[i].m_name << "\n";
   5972             }
   5973 
   5974             if(currentSubcaseLevel != subcasesStack.size()) {
   5975                 s << Color::Yellow << "\nDEEPEST SUBCASE STACK REACHED (DIFFERENT FROM THE CURRENT ONE):\n" << Color::None;
   5976                 for(size_t i = 0; i < subcasesStack.size(); ++i) {
   5977                     if(subcasesStack[i].m_name[0] != '\0')
   5978                         s << "  " << subcasesStack[i].m_name << "\n";
   5979                 }
   5980             }
   5981 
   5982             s << "\n";
   5983 
   5984             hasLoggedCurrentTestStart = true;
   5985         }
   5986 
   5987         void printVersion() {
   5988             if(opt.no_version == false)
   5989                 s << Color::Cyan << "[doctest] " << Color::None << "doctest version is \""
   5990                   << DOCTEST_VERSION_STR << "\"\n";
   5991         }
   5992 
   5993         void printIntro() {
   5994             if(opt.no_intro == false) {
   5995                 printVersion();
   5996                 s << Color::Cyan << "[doctest] " << Color::None
   5997                   << "run with \"--" DOCTEST_OPTIONS_PREFIX_DISPLAY "help\" for options\n";
   5998             }
   5999         }
   6000 
   6001         void printHelp() {
   6002             int sizePrefixDisplay = static_cast<int>(strlen(DOCTEST_OPTIONS_PREFIX_DISPLAY));
   6003             printVersion();
   6004             // clang-format off
   6005             s << Color::Cyan << "[doctest]\n" << Color::None;
   6006             s << Color::Cyan << "[doctest] " << Color::None;
   6007             s << "boolean values: \"1/on/yes/true\" or \"0/off/no/false\"\n";
   6008             s << Color::Cyan << "[doctest] " << Color::None;
   6009             s << "filter  values: \"str1,str2,str3\" (comma separated strings)\n";
   6010             s << Color::Cyan << "[doctest]\n" << Color::None;
   6011             s << Color::Cyan << "[doctest] " << Color::None;
   6012             s << "filters use wildcards for matching strings\n";
   6013             s << Color::Cyan << "[doctest] " << Color::None;
   6014             s << "something passes a filter if any of the strings in a filter matches\n";
   6015 #ifndef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
   6016             s << Color::Cyan << "[doctest]\n" << Color::None;
   6017             s << Color::Cyan << "[doctest] " << Color::None;
   6018             s << "ALL FLAGS, OPTIONS AND FILTERS ALSO AVAILABLE WITH A \"" DOCTEST_CONFIG_OPTIONS_PREFIX "\" PREFIX!!!\n";
   6019 #endif
   6020             s << Color::Cyan << "[doctest]\n" << Color::None;
   6021             s << Color::Cyan << "[doctest] " << Color::None;
   6022             s << "Query flags - the program quits after them. Available:\n\n";
   6023             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "?,   --" DOCTEST_OPTIONS_PREFIX_DISPLAY "help, -" DOCTEST_OPTIONS_PREFIX_DISPLAY "h                      "
   6024               << Whitespace(sizePrefixDisplay*0) <<  "prints this message\n";
   6025             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "v,   --" DOCTEST_OPTIONS_PREFIX_DISPLAY "version                       "
   6026               << Whitespace(sizePrefixDisplay*1) << "prints the version\n";
   6027             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "c,   --" DOCTEST_OPTIONS_PREFIX_DISPLAY "count                         "
   6028               << Whitespace(sizePrefixDisplay*1) << "prints the number of matching tests\n";
   6029             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ltc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "list-test-cases               "
   6030               << Whitespace(sizePrefixDisplay*1) << "lists all matching tests by name\n";
   6031             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "lts, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "list-test-suites              "
   6032               << Whitespace(sizePrefixDisplay*1) << "lists all matching test suites\n";
   6033             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "lr,  --" DOCTEST_OPTIONS_PREFIX_DISPLAY "list-reporters                "
   6034               << Whitespace(sizePrefixDisplay*1) << "lists all registered reporters\n\n";
   6035             // ================================================================================== << 79
   6036             s << Color::Cyan << "[doctest] " << Color::None;
   6037             s << "The available <int>/<string> options/filters are:\n\n";
   6038             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "tc,  --" DOCTEST_OPTIONS_PREFIX_DISPLAY "test-case=<filters>           "
   6039               << Whitespace(sizePrefixDisplay*1) << "filters     tests by their name\n";
   6040             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "tce, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "test-case-exclude=<filters>   "
   6041               << Whitespace(sizePrefixDisplay*1) << "filters OUT tests by their name\n";
   6042             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "sf,  --" DOCTEST_OPTIONS_PREFIX_DISPLAY "source-file=<filters>         "
   6043               << Whitespace(sizePrefixDisplay*1) << "filters     tests by their file\n";
   6044             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "sfe, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "source-file-exclude=<filters> "
   6045               << Whitespace(sizePrefixDisplay*1) << "filters OUT tests by their file\n";
   6046             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ts,  --" DOCTEST_OPTIONS_PREFIX_DISPLAY "test-suite=<filters>          "
   6047               << Whitespace(sizePrefixDisplay*1) << "filters     tests by their test suite\n";
   6048             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "tse, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "test-suite-exclude=<filters>  "
   6049               << Whitespace(sizePrefixDisplay*1) << "filters OUT tests by their test suite\n";
   6050             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "sc,  --" DOCTEST_OPTIONS_PREFIX_DISPLAY "subcase=<filters>             "
   6051               << Whitespace(sizePrefixDisplay*1) << "filters     subcases by their name\n";
   6052             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "sce, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "subcase-exclude=<filters>     "
   6053               << Whitespace(sizePrefixDisplay*1) << "filters OUT subcases by their name\n";
   6054             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "r,   --" DOCTEST_OPTIONS_PREFIX_DISPLAY "reporters=<filters>           "
   6055               << Whitespace(sizePrefixDisplay*1) << "reporters to use (console is default)\n";
   6056             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "o,   --" DOCTEST_OPTIONS_PREFIX_DISPLAY "out=<string>                  "
   6057               << Whitespace(sizePrefixDisplay*1) << "output filename\n";
   6058             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ob,  --" DOCTEST_OPTIONS_PREFIX_DISPLAY "order-by=<string>             "
   6059               << Whitespace(sizePrefixDisplay*1) << "how the tests should be ordered\n";
   6060             s << Whitespace(sizePrefixDisplay*3) << "                                       <string> - [file/suite/name/rand/none]\n";
   6061             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "rs,  --" DOCTEST_OPTIONS_PREFIX_DISPLAY "rand-seed=<int>               "
   6062               << Whitespace(sizePrefixDisplay*1) << "seed for random ordering\n";
   6063             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "f,   --" DOCTEST_OPTIONS_PREFIX_DISPLAY "first=<int>                   "
   6064               << Whitespace(sizePrefixDisplay*1) << "the first test passing the filters to\n";
   6065             s << Whitespace(sizePrefixDisplay*3) << "                                       execute - for range-based execution\n";
   6066             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "l,   --" DOCTEST_OPTIONS_PREFIX_DISPLAY "last=<int>                    "
   6067               << Whitespace(sizePrefixDisplay*1) << "the last test passing the filters to\n";
   6068             s << Whitespace(sizePrefixDisplay*3) << "                                       execute - for range-based execution\n";
   6069             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "aa,  --" DOCTEST_OPTIONS_PREFIX_DISPLAY "abort-after=<int>             "
   6070               << Whitespace(sizePrefixDisplay*1) << "stop after <int> failed assertions\n";
   6071             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "scfl,--" DOCTEST_OPTIONS_PREFIX_DISPLAY "subcase-filter-levels=<int>   "
   6072               << Whitespace(sizePrefixDisplay*1) << "apply filters for the first <int> levels\n";
   6073             s << Color::Cyan << "\n[doctest] " << Color::None;
   6074             s << "Bool options - can be used like flags and true is assumed. Available:\n\n";
   6075             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "s,   --" DOCTEST_OPTIONS_PREFIX_DISPLAY "success=<bool>                "
   6076               << Whitespace(sizePrefixDisplay*1) << "include successful assertions in output\n";
   6077             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "cs,  --" DOCTEST_OPTIONS_PREFIX_DISPLAY "case-sensitive=<bool>         "
   6078               << Whitespace(sizePrefixDisplay*1) << "filters being treated as case sensitive\n";
   6079             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "e,   --" DOCTEST_OPTIONS_PREFIX_DISPLAY "exit=<bool>                   "
   6080               << Whitespace(sizePrefixDisplay*1) << "exits after the tests finish\n";
   6081             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "d,   --" DOCTEST_OPTIONS_PREFIX_DISPLAY "duration=<bool>               "
   6082               << Whitespace(sizePrefixDisplay*1) << "prints the time duration of each test\n";
   6083             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "m,   --" DOCTEST_OPTIONS_PREFIX_DISPLAY "minimal=<bool>                "
   6084               << Whitespace(sizePrefixDisplay*1) << "minimal console output (only failures)\n";
   6085             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "q,   --" DOCTEST_OPTIONS_PREFIX_DISPLAY "quiet=<bool>                  "
   6086               << Whitespace(sizePrefixDisplay*1) << "no console output\n";
   6087             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nt,  --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-throw=<bool>               "
   6088               << Whitespace(sizePrefixDisplay*1) << "skips exceptions-related assert checks\n";
   6089             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ne,  --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-exitcode=<bool>            "
   6090               << Whitespace(sizePrefixDisplay*1) << "returns (or exits) always with success\n";
   6091             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nr,  --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-run=<bool>                 "
   6092               << Whitespace(sizePrefixDisplay*1) << "skips all runtime doctest operations\n";
   6093             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ni,  --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-intro=<bool>               "
   6094               << Whitespace(sizePrefixDisplay*1) << "omit the framework intro in the output\n";
   6095             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nv,  --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-version=<bool>             "
   6096               << Whitespace(sizePrefixDisplay*1) << "omit the framework version in the output\n";
   6097             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nc,  --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-colors=<bool>              "
   6098               << Whitespace(sizePrefixDisplay*1) << "disables colors in output\n";
   6099             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "fc,  --" DOCTEST_OPTIONS_PREFIX_DISPLAY "force-colors=<bool>           "
   6100               << Whitespace(sizePrefixDisplay*1) << "use colors even when not in a tty\n";
   6101             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nb,  --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-breaks=<bool>              "
   6102               << Whitespace(sizePrefixDisplay*1) << "disables breakpoints in debuggers\n";
   6103             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ns,  --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-skip=<bool>                "
   6104               << Whitespace(sizePrefixDisplay*1) << "don't skip test cases marked as skip\n";
   6105             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "gfl, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "gnu-file-line=<bool>          "
   6106               << Whitespace(sizePrefixDisplay*1) << ":n: vs (n): for line numbers in output\n";
   6107             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "npf, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-path-filenames=<bool>      "
   6108               << Whitespace(sizePrefixDisplay*1) << "only filenames and no paths in output\n";
   6109             s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nln, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-line-numbers=<bool>        "
   6110               << Whitespace(sizePrefixDisplay*1) << "0 instead of real line numbers in output\n";
   6111             // ================================================================================== << 79
   6112             // clang-format on
   6113 
   6114             s << Color::Cyan << "\n[doctest] " << Color::None;
   6115             s << "for more information visit the project documentation\n\n";
   6116         }
   6117 
   6118         void printRegisteredReporters() {
   6119             printVersion();
   6120             auto printReporters = [this] (const reporterMap& reporters, const char* type) {
   6121                 if(reporters.size()) {
   6122                     s << Color::Cyan << "[doctest] " << Color::None << "listing all registered " << type << "\n";
   6123                     for(auto& curr : reporters)
   6124                         s << "priority: " << std::setw(5) << curr.first.first
   6125                           << " name: " << curr.first.second << "\n";
   6126                 }
   6127             };
   6128             printReporters(getListeners(), "listeners");
   6129             printReporters(getReporters(), "reporters");
   6130         }
   6131 
   6132         // =========================================================================================
   6133         // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE
   6134         // =========================================================================================
   6135 
   6136         void report_query(const QueryData& in) override {
   6137             if(opt.version) {
   6138                 printVersion();
   6139             } else if(opt.help) {
   6140                 printHelp();
   6141             } else if(opt.list_reporters) {
   6142                 printRegisteredReporters();
   6143             } else if(opt.count || opt.list_test_cases) {
   6144                 if(opt.list_test_cases) {
   6145                     s << Color::Cyan << "[doctest] " << Color::None
   6146                       << "listing all test case names\n";
   6147                     separator_to_stream();
   6148                 }
   6149 
   6150                 for(unsigned i = 0; i < in.num_data; ++i)
   6151                     s << Color::None << in.data[i]->m_name << "\n";
   6152 
   6153                 separator_to_stream();
   6154 
   6155                 s << Color::Cyan << "[doctest] " << Color::None
   6156                   << "unskipped test cases passing the current filters: "
   6157                   << g_cs->numTestCasesPassingFilters << "\n";
   6158 
   6159             } else if(opt.list_test_suites) {
   6160                 s << Color::Cyan << "[doctest] " << Color::None << "listing all test suites\n";
   6161                 separator_to_stream();
   6162 
   6163                 for(unsigned i = 0; i < in.num_data; ++i)
   6164                     s << Color::None << in.data[i]->m_test_suite << "\n";
   6165 
   6166                 separator_to_stream();
   6167 
   6168                 s << Color::Cyan << "[doctest] " << Color::None
   6169                   << "unskipped test cases passing the current filters: "
   6170                   << g_cs->numTestCasesPassingFilters << "\n";
   6171                 s << Color::Cyan << "[doctest] " << Color::None
   6172                   << "test suites with unskipped test cases passing the current filters: "
   6173                   << g_cs->numTestSuitesPassingFilters << "\n";
   6174             }
   6175         }
   6176 
   6177         void test_run_start() override {
   6178             if(!opt.minimal)
   6179                 printIntro();
   6180         }
   6181 
   6182         void test_run_end(const TestRunStats& p) override {
   6183             if(opt.minimal && p.numTestCasesFailed == 0)
   6184                 return;
   6185 
   6186             separator_to_stream();
   6187             s << std::dec;
   6188 
   6189             auto totwidth = int(std::ceil(log10((std::max(p.numTestCasesPassingFilters, static_cast<unsigned>(p.numAsserts))) + 1)));
   6190             auto passwidth = int(std::ceil(log10((std::max(p.numTestCasesPassingFilters - p.numTestCasesFailed, static_cast<unsigned>(p.numAsserts - p.numAssertsFailed))) + 1)));
   6191             auto failwidth = int(std::ceil(log10((std::max(p.numTestCasesFailed, static_cast<unsigned>(p.numAssertsFailed))) + 1)));
   6192             const bool anythingFailed = p.numTestCasesFailed > 0 || p.numAssertsFailed > 0;
   6193             s << Color::Cyan << "[doctest] " << Color::None << "test cases: " << std::setw(totwidth)
   6194               << p.numTestCasesPassingFilters << " | "
   6195               << ((p.numTestCasesPassingFilters == 0 || anythingFailed) ? Color::None :
   6196                                                                           Color::Green)
   6197               << std::setw(passwidth) << p.numTestCasesPassingFilters - p.numTestCasesFailed << " passed"
   6198               << Color::None << " | " << (p.numTestCasesFailed > 0 ? Color::Red : Color::None)
   6199               << std::setw(failwidth) << p.numTestCasesFailed << " failed" << Color::None << " |";
   6200             if(opt.no_skipped_summary == false) {
   6201                 const int numSkipped = p.numTestCases - p.numTestCasesPassingFilters;
   6202                 s << " " << (numSkipped == 0 ? Color::None : Color::Yellow) << numSkipped
   6203                   << " skipped" << Color::None;
   6204             }
   6205             s << "\n";
   6206             s << Color::Cyan << "[doctest] " << Color::None << "assertions: " << std::setw(totwidth)
   6207               << p.numAsserts << " | "
   6208               << ((p.numAsserts == 0 || anythingFailed) ? Color::None : Color::Green)
   6209               << std::setw(passwidth) << (p.numAsserts - p.numAssertsFailed) << " passed" << Color::None
   6210               << " | " << (p.numAssertsFailed > 0 ? Color::Red : Color::None) << std::setw(failwidth)
   6211               << p.numAssertsFailed << " failed" << Color::None << " |\n";
   6212             s << Color::Cyan << "[doctest] " << Color::None
   6213               << "Status: " << (p.numTestCasesFailed > 0 ? Color::Red : Color::Green)
   6214               << ((p.numTestCasesFailed > 0) ? "FAILURE!" : "SUCCESS!") << Color::None << std::endl;
   6215         }
   6216 
   6217         void test_case_start(const TestCaseData& in) override {
   6218             hasLoggedCurrentTestStart = false;
   6219             tc                        = &in;
   6220             subcasesStack.clear();
   6221             currentSubcaseLevel = 0;
   6222         }
   6223         
   6224         void test_case_reenter(const TestCaseData&) override {
   6225             subcasesStack.clear();
   6226         }
   6227 
   6228         void test_case_end(const CurrentTestCaseStats& st) override {
   6229             if(tc->m_no_output)
   6230                 return;
   6231 
   6232             // log the preamble of the test case only if there is something
   6233             // else to print - something other than that an assert has failed
   6234             if(opt.duration ||
   6235                (st.failure_flags && st.failure_flags != static_cast<int>(TestCaseFailureReason::AssertFailure)))
   6236                 logTestStart();
   6237 
   6238             if(opt.duration)
   6239                 s << Color::None << std::setprecision(6) << std::fixed << st.seconds
   6240                   << " s: " << tc->m_name << "\n";
   6241 
   6242             if(st.failure_flags & TestCaseFailureReason::Timeout)
   6243                 s << Color::Red << "Test case exceeded time limit of " << std::setprecision(6)
   6244                   << std::fixed << tc->m_timeout << "!\n";
   6245 
   6246             if(st.failure_flags & TestCaseFailureReason::ShouldHaveFailedButDidnt) {
   6247                 s << Color::Red << "Should have failed but didn't! Marking it as failed!\n";
   6248             } else if(st.failure_flags & TestCaseFailureReason::ShouldHaveFailedAndDid) {
   6249                 s << Color::Yellow << "Failed as expected so marking it as not failed\n";
   6250             } else if(st.failure_flags & TestCaseFailureReason::CouldHaveFailedAndDid) {
   6251                 s << Color::Yellow << "Allowed to fail so marking it as not failed\n";
   6252             } else if(st.failure_flags & TestCaseFailureReason::DidntFailExactlyNumTimes) {
   6253                 s << Color::Red << "Didn't fail exactly " << tc->m_expected_failures
   6254                   << " times so marking it as failed!\n";
   6255             } else if(st.failure_flags & TestCaseFailureReason::FailedExactlyNumTimes) {
   6256                 s << Color::Yellow << "Failed exactly " << tc->m_expected_failures
   6257                   << " times as expected so marking it as not failed!\n";
   6258             }
   6259             if(st.failure_flags & TestCaseFailureReason::TooManyFailedAsserts) {
   6260                 s << Color::Red << "Aborting - too many failed asserts!\n";
   6261             }
   6262             s << Color::None; // lgtm [cpp/useless-expression]
   6263         }
   6264 
   6265         void test_case_exception(const TestCaseException& e) override {
   6266             DOCTEST_LOCK_MUTEX(mutex)
   6267             if(tc->m_no_output)
   6268                 return;
   6269 
   6270             logTestStart();
   6271 
   6272             file_line_to_stream(tc->m_file.c_str(), tc->m_line, " ");
   6273             successOrFailColoredStringToStream(false, e.is_crash ? assertType::is_require :
   6274                                                                    assertType::is_check);
   6275             s << Color::Red << (e.is_crash ? "test case CRASHED: " : "test case THREW exception: ")
   6276               << Color::Cyan << e.error_string << "\n";
   6277 
   6278             int num_stringified_contexts = get_num_stringified_contexts();
   6279             if(num_stringified_contexts) {
   6280                 auto stringified_contexts = get_stringified_contexts();
   6281                 s << Color::None << "  logged: ";
   6282                 for(int i = num_stringified_contexts; i > 0; --i) {
   6283                     s << (i == num_stringified_contexts ? "" : "          ")
   6284                       << stringified_contexts[i - 1] << "\n";
   6285                 }
   6286             }
   6287             s << "\n" << Color::None;
   6288         }
   6289 
   6290         void subcase_start(const SubcaseSignature& subc) override {
   6291             subcasesStack.push_back(subc);
   6292             ++currentSubcaseLevel;
   6293             hasLoggedCurrentTestStart = false;
   6294         }
   6295 
   6296         void subcase_end() override {
   6297             --currentSubcaseLevel;
   6298             hasLoggedCurrentTestStart = false;
   6299         }
   6300 
   6301         void log_assert(const AssertData& rb) override {
   6302             if((!rb.m_failed && !opt.success) || tc->m_no_output)
   6303                 return;
   6304 
   6305             DOCTEST_LOCK_MUTEX(mutex)
   6306 
   6307             logTestStart();
   6308 
   6309             file_line_to_stream(rb.m_file, rb.m_line, " ");
   6310             successOrFailColoredStringToStream(!rb.m_failed, rb.m_at);
   6311 
   6312             fulltext_log_assert_to_stream(s, rb);
   6313 
   6314             log_contexts();
   6315         }
   6316 
   6317         void log_message(const MessageData& mb) override {
   6318             if(tc->m_no_output)
   6319                 return;
   6320 
   6321             DOCTEST_LOCK_MUTEX(mutex)
   6322 
   6323             logTestStart();
   6324 
   6325             file_line_to_stream(mb.m_file, mb.m_line, " ");
   6326             s << getSuccessOrFailColor(false, mb.m_severity)
   6327               << getSuccessOrFailString(mb.m_severity & assertType::is_warn, mb.m_severity,
   6328                                         "MESSAGE") << ": ";
   6329             s << Color::None << mb.m_string << "\n";
   6330             log_contexts();
   6331         }
   6332 
   6333         void test_case_skipped(const TestCaseData&) override {}
   6334     };
   6335 
   6336     DOCTEST_REGISTER_REPORTER("console", 0, ConsoleReporter);
   6337 
   6338 #ifdef DOCTEST_PLATFORM_WINDOWS
   6339     struct DebugOutputWindowReporter : public ConsoleReporter
   6340     {
   6341         DOCTEST_THREAD_LOCAL static std::ostringstream oss;
   6342 
   6343         DebugOutputWindowReporter(const ContextOptions& co)
   6344                 : ConsoleReporter(co, oss) {}
   6345 
   6346 #define DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(func, type, arg)                                    \
   6347     void func(type arg) override {                                                                 \
   6348         bool with_col = g_no_colors;                                                               \
   6349         g_no_colors   = false;                                                                     \
   6350         ConsoleReporter::func(arg);                                                                \
   6351         if(oss.tellp() != std::streampos{}) {                                                      \
   6352             DOCTEST_OUTPUT_DEBUG_STRING(oss.str().c_str());                                        \
   6353             oss.str("");                                                                           \
   6354         }                                                                                          \
   6355         g_no_colors = with_col;                                                                    \
   6356     }
   6357 
   6358         DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_run_start, DOCTEST_EMPTY, DOCTEST_EMPTY)
   6359         DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_run_end, const TestRunStats&, in)
   6360         DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_start, const TestCaseData&, in)
   6361         DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_reenter, const TestCaseData&, in)
   6362         DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_end, const CurrentTestCaseStats&, in)
   6363         DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_exception, const TestCaseException&, in)
   6364         DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(subcase_start, const SubcaseSignature&, in)
   6365         DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(subcase_end, DOCTEST_EMPTY, DOCTEST_EMPTY)
   6366         DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(log_assert, const AssertData&, in)
   6367         DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(log_message, const MessageData&, in)
   6368         DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_skipped, const TestCaseData&, in)
   6369     };
   6370 
   6371     DOCTEST_THREAD_LOCAL std::ostringstream DebugOutputWindowReporter::oss;
   6372 #endif // DOCTEST_PLATFORM_WINDOWS
   6373 
   6374     // the implementation of parseOption()
   6375     bool parseOptionImpl(int argc, const char* const* argv, const char* pattern, String* value) {
   6376         // going from the end to the beginning and stopping on the first occurrence from the end
   6377         for(int i = argc; i > 0; --i) {
   6378             auto index = i - 1;
   6379             auto temp = std::strstr(argv[index], pattern);
   6380             if(temp && (value || strlen(temp) == strlen(pattern))) { //!OCLINT prefer early exits and continue
   6381                 // eliminate matches in which the chars before the option are not '-'
   6382                 bool noBadCharsFound = true;
   6383                 auto curr            = argv[index];
   6384                 while(curr != temp) {
   6385                     if(*curr++ != '-') {
   6386                         noBadCharsFound = false;
   6387                         break;
   6388                     }
   6389                 }
   6390                 if(noBadCharsFound && argv[index][0] == '-') {
   6391                     if(value) {
   6392                         // parsing the value of an option
   6393                         temp += strlen(pattern);
   6394                         const unsigned len = strlen(temp);
   6395                         if(len) {
   6396                             *value = temp;
   6397                             return true;
   6398                         }
   6399                     } else {
   6400                         // just a flag - no value
   6401                         return true;
   6402                     }
   6403                 }
   6404             }
   6405         }
   6406         return false;
   6407     }
   6408 
   6409     // parses an option and returns the string after the '=' character
   6410     bool parseOption(int argc, const char* const* argv, const char* pattern, String* value = nullptr,
   6411                      const String& defaultVal = String()) {
   6412         if(value)
   6413             *value = defaultVal;
   6414 #ifndef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
   6415         // offset (normally 3 for "dt-") to skip prefix
   6416         if(parseOptionImpl(argc, argv, pattern + strlen(DOCTEST_CONFIG_OPTIONS_PREFIX), value))
   6417             return true;
   6418 #endif // DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
   6419         return parseOptionImpl(argc, argv, pattern, value);
   6420     }
   6421 
   6422     // locates a flag on the command line
   6423     bool parseFlag(int argc, const char* const* argv, const char* pattern) {
   6424         return parseOption(argc, argv, pattern);
   6425     }
   6426 
   6427     // parses a comma separated list of words after a pattern in one of the arguments in argv
   6428     bool parseCommaSepArgs(int argc, const char* const* argv, const char* pattern,
   6429                            std::vector<String>& res) {
   6430         String filtersString;
   6431         if(parseOption(argc, argv, pattern, &filtersString)) {
   6432             // tokenize with "," as a separator, unless escaped with backslash
   6433             std::ostringstream s;
   6434             auto flush = [&s, &res]() {
   6435                 auto string = s.str();
   6436                 if(string.size() > 0) {
   6437                     res.push_back(string.c_str());
   6438                 }
   6439                 s.str("");
   6440             };
   6441 
   6442             bool seenBackslash = false;
   6443             const char* current = filtersString.c_str();
   6444             const char* end = current + strlen(current);
   6445             while(current != end) {
   6446                 char character = *current++;
   6447                 if(seenBackslash) {
   6448                     seenBackslash = false;
   6449                     if(character == ',' || character == '\\') {
   6450                         s.put(character);
   6451                         continue;
   6452                     }
   6453                     s.put('\\');
   6454                 }
   6455                 if(character == '\\') {
   6456                     seenBackslash = true;
   6457                 } else if(character == ',') {
   6458                     flush();
   6459                 } else {
   6460                     s.put(character);
   6461                 }
   6462             }
   6463 
   6464             if(seenBackslash) {
   6465                 s.put('\\');
   6466             }
   6467             flush();
   6468             return true;
   6469         }
   6470         return false;
   6471     }
   6472 
   6473     enum optionType
   6474     {
   6475         option_bool,
   6476         option_int
   6477     };
   6478 
   6479     // parses an int/bool option from the command line
   6480     bool parseIntOption(int argc, const char* const* argv, const char* pattern, optionType type,
   6481                         int& res) {
   6482         String parsedValue;
   6483         if(!parseOption(argc, argv, pattern, &parsedValue))
   6484             return false;
   6485 
   6486         if(type) {
   6487             // integer
   6488             // TODO: change this to use std::stoi or something else! currently it uses undefined behavior - assumes '0' on failed parse...
   6489             int theInt = std::atoi(parsedValue.c_str());
   6490             if (theInt != 0) {
   6491                 res = theInt; //!OCLINT parameter reassignment
   6492                 return true;
   6493             }
   6494         } else {
   6495             // boolean
   6496             const char positive[][5] = { "1", "true", "on", "yes" };  // 5 - strlen("true") + 1
   6497             const char negative[][6] = { "0", "false", "off", "no" }; // 6 - strlen("false") + 1
   6498 
   6499             // if the value matches any of the positive/negative possibilities
   6500             for (unsigned i = 0; i < 4; i++) {
   6501                 if (parsedValue.compare(positive[i], true) == 0) {
   6502                     res = 1; //!OCLINT parameter reassignment
   6503                     return true;
   6504                 }
   6505                 if (parsedValue.compare(negative[i], true) == 0) {
   6506                     res = 0; //!OCLINT parameter reassignment
   6507                     return true;
   6508                 }
   6509             }
   6510         }
   6511         return false;
   6512     }
   6513 } // namespace
   6514 
   6515 Context::Context(int argc, const char* const* argv)
   6516         : p(new detail::ContextState) {
   6517     parseArgs(argc, argv, true);
   6518     if(argc)
   6519         p->binary_name = argv[0];
   6520 }
   6521 
   6522 Context::~Context() {
   6523     if(g_cs == p)
   6524         g_cs = nullptr;
   6525     delete p;
   6526 }
   6527 
   6528 void Context::applyCommandLine(int argc, const char* const* argv) {
   6529     parseArgs(argc, argv);
   6530     if(argc)
   6531         p->binary_name = argv[0];
   6532 }
   6533 
   6534 // parses args
   6535 void Context::parseArgs(int argc, const char* const* argv, bool withDefaults) {
   6536     using namespace detail;
   6537 
   6538     // clang-format off
   6539     parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "source-file=",        p->filters[0]);
   6540     parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "sf=",                 p->filters[0]);
   6541     parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "source-file-exclude=",p->filters[1]);
   6542     parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "sfe=",                p->filters[1]);
   6543     parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "test-suite=",         p->filters[2]);
   6544     parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "ts=",                 p->filters[2]);
   6545     parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "test-suite-exclude=", p->filters[3]);
   6546     parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "tse=",                p->filters[3]);
   6547     parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "test-case=",          p->filters[4]);
   6548     parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "tc=",                 p->filters[4]);
   6549     parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "test-case-exclude=",  p->filters[5]);
   6550     parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "tce=",                p->filters[5]);
   6551     parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "subcase=",            p->filters[6]);
   6552     parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "sc=",                 p->filters[6]);
   6553     parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "subcase-exclude=",    p->filters[7]);
   6554     parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "sce=",                p->filters[7]);
   6555     parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "reporters=",          p->filters[8]);
   6556     parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "r=",                  p->filters[8]);
   6557     // clang-format on
   6558 
   6559     int    intRes = 0;
   6560     String strRes;
   6561 
   6562 #define DOCTEST_PARSE_AS_BOOL_OR_FLAG(name, sname, var, default)                                   \
   6563     if(parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", option_bool, intRes) ||  \
   6564        parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", option_bool, intRes))   \
   6565         p->var = static_cast<bool>(intRes);                                                        \
   6566     else if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name) ||                           \
   6567             parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname))                            \
   6568         p->var = true;                                                                             \
   6569     else if(withDefaults)                                                                          \
   6570     p->var = default
   6571 
   6572 #define DOCTEST_PARSE_INT_OPTION(name, sname, var, default)                                        \
   6573     if(parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", option_int, intRes) ||   \
   6574        parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", option_int, intRes))    \
   6575         p->var = intRes;                                                                           \
   6576     else if(withDefaults)                                                                          \
   6577     p->var = default
   6578 
   6579 #define DOCTEST_PARSE_STR_OPTION(name, sname, var, default)                                        \
   6580     if(parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", &strRes, default) ||        \
   6581        parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", &strRes, default) ||       \
   6582        withDefaults)                                                                               \
   6583     p->var = strRes
   6584 
   6585     // clang-format off
   6586     DOCTEST_PARSE_STR_OPTION("out", "o", out, "");
   6587     DOCTEST_PARSE_STR_OPTION("order-by", "ob", order_by, "file");
   6588     DOCTEST_PARSE_INT_OPTION("rand-seed", "rs", rand_seed, 0);
   6589 
   6590     DOCTEST_PARSE_INT_OPTION("first", "f", first, 0);
   6591     DOCTEST_PARSE_INT_OPTION("last", "l", last, UINT_MAX);
   6592 
   6593     DOCTEST_PARSE_INT_OPTION("abort-after", "aa", abort_after, 0);
   6594     DOCTEST_PARSE_INT_OPTION("subcase-filter-levels", "scfl", subcase_filter_levels, INT_MAX);
   6595 
   6596     DOCTEST_PARSE_AS_BOOL_OR_FLAG("success", "s", success, false);
   6597     DOCTEST_PARSE_AS_BOOL_OR_FLAG("case-sensitive", "cs", case_sensitive, false);
   6598     DOCTEST_PARSE_AS_BOOL_OR_FLAG("exit", "e", exit, false);
   6599     DOCTEST_PARSE_AS_BOOL_OR_FLAG("duration", "d", duration, false);
   6600     DOCTEST_PARSE_AS_BOOL_OR_FLAG("minimal", "m", minimal, false);
   6601     DOCTEST_PARSE_AS_BOOL_OR_FLAG("quiet", "q", quiet, false);
   6602     DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-throw", "nt", no_throw, false);
   6603     DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-exitcode", "ne", no_exitcode, false);
   6604     DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-run", "nr", no_run, false);
   6605     DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-intro", "ni", no_intro, false);
   6606     DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-version", "nv", no_version, false);
   6607     DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-colors", "nc", no_colors, false);
   6608     DOCTEST_PARSE_AS_BOOL_OR_FLAG("force-colors", "fc", force_colors, false);
   6609     DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-breaks", "nb", no_breaks, false);
   6610     DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-skip", "ns", no_skip, false);
   6611     DOCTEST_PARSE_AS_BOOL_OR_FLAG("gnu-file-line", "gfl", gnu_file_line, !bool(DOCTEST_MSVC));
   6612     DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-path-filenames", "npf", no_path_in_filenames, false);
   6613     DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-line-numbers", "nln", no_line_numbers, false);
   6614     DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-debug-output", "ndo", no_debug_output, false);
   6615     DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-skipped-summary", "nss", no_skipped_summary, false);
   6616     DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-time-in-output", "ntio", no_time_in_output, false);
   6617     // clang-format on
   6618 
   6619     if(withDefaults) {
   6620         p->help             = false;
   6621         p->version          = false;
   6622         p->count            = false;
   6623         p->list_test_cases  = false;
   6624         p->list_test_suites = false;
   6625         p->list_reporters   = false;
   6626     }
   6627     if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "help") ||
   6628        parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "h") ||
   6629        parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "?")) {
   6630         p->help = true;
   6631         p->exit = true;
   6632     }
   6633     if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "version") ||
   6634        parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "v")) {
   6635         p->version = true;
   6636         p->exit    = true;
   6637     }
   6638     if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "count") ||
   6639        parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "c")) {
   6640         p->count = true;
   6641         p->exit  = true;
   6642     }
   6643     if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "list-test-cases") ||
   6644        parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "ltc")) {
   6645         p->list_test_cases = true;
   6646         p->exit            = true;
   6647     }
   6648     if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "list-test-suites") ||
   6649        parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "lts")) {
   6650         p->list_test_suites = true;
   6651         p->exit             = true;
   6652     }
   6653     if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "list-reporters") ||
   6654        parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "lr")) {
   6655         p->list_reporters = true;
   6656         p->exit           = true;
   6657     }
   6658 }
   6659 
   6660 // allows the user to add procedurally to the filters from the command line
   6661 void Context::addFilter(const char* filter, const char* value) { setOption(filter, value); }
   6662 
   6663 // allows the user to clear all filters from the command line
   6664 void Context::clearFilters() {
   6665     for(auto& curr : p->filters)
   6666         curr.clear();
   6667 }
   6668 
   6669 // allows the user to override procedurally the bool options from the command line
   6670 void Context::setOption(const char* option, bool value) {
   6671     setOption(option, value ? "true" : "false");
   6672 }
   6673 
   6674 // allows the user to override procedurally the int options from the command line
   6675 void Context::setOption(const char* option, int value) {
   6676     setOption(option, toString(value).c_str());
   6677 }
   6678 
   6679 // allows the user to override procedurally the string options from the command line
   6680 void Context::setOption(const char* option, const char* value) {
   6681     auto argv   = String("-") + option + "=" + value;
   6682     auto lvalue = argv.c_str();
   6683     parseArgs(1, &lvalue);
   6684 }
   6685 
   6686 // users should query this in their main() and exit the program if true
   6687 bool Context::shouldExit() { return p->exit; }
   6688 
   6689 void Context::setAsDefaultForAssertsOutOfTestCases() { g_cs = p; }
   6690 
   6691 void Context::setAssertHandler(detail::assert_handler ah) { p->ah = ah; }
   6692 
   6693 void Context::setCout(std::ostream* out) { p->cout = out; }
   6694 
   6695 static class DiscardOStream : public std::ostream
   6696 {
   6697 private:
   6698     class : public std::streambuf
   6699     {
   6700     private:
   6701         // allowing some buffering decreases the amount of calls to overflow
   6702         char buf[1024];
   6703 
   6704     protected:
   6705         std::streamsize xsputn(const char_type*, std::streamsize count) override { return count; }
   6706 
   6707         int_type overflow(int_type ch) override {
   6708             setp(std::begin(buf), std::end(buf));
   6709             return traits_type::not_eof(ch);
   6710         }
   6711     } discardBuf;
   6712 
   6713 public:
   6714     DiscardOStream()
   6715             : std::ostream(&discardBuf) {}
   6716 } discardOut;
   6717 
   6718 // the main function that does all the filtering and test running
   6719 int Context::run() {
   6720     using namespace detail;
   6721 
   6722     // save the old context state in case such was setup - for using asserts out of a testing context
   6723     auto old_cs = g_cs;
   6724     // this is the current contest
   6725     g_cs               = p;
   6726     is_running_in_test = true;
   6727 
   6728     g_no_colors = p->no_colors;
   6729     p->resetRunData();
   6730 
   6731     std::fstream fstr;
   6732     if(p->cout == nullptr) {
   6733         if(p->quiet) {
   6734             p->cout = &discardOut;
   6735         } else if(p->out.size()) {
   6736             // to a file if specified
   6737             fstr.open(p->out.c_str(), std::fstream::out);
   6738             p->cout = &fstr;
   6739         } else {
   6740             // stdout by default
   6741             p->cout = &std::cout;
   6742         }
   6743     }
   6744 
   6745     FatalConditionHandler::allocateAltStackMem();
   6746 
   6747     auto cleanup_and_return = [&]() {
   6748         FatalConditionHandler::freeAltStackMem();
   6749 
   6750         if(fstr.is_open())
   6751             fstr.close();
   6752 
   6753         // restore context
   6754         g_cs               = old_cs;
   6755         is_running_in_test = false;
   6756 
   6757         // we have to free the reporters which were allocated when the run started
   6758         for(auto& curr : p->reporters_currently_used)
   6759             delete curr;
   6760         p->reporters_currently_used.clear();
   6761 
   6762         if(p->numTestCasesFailed && !p->no_exitcode)
   6763             return EXIT_FAILURE;
   6764         return EXIT_SUCCESS;
   6765     };
   6766 
   6767     // setup default reporter if none is given through the command line
   6768     if(p->filters[8].empty())
   6769         p->filters[8].push_back("console");
   6770 
   6771     // check to see if any of the registered reporters has been selected
   6772     for(auto& curr : getReporters()) {
   6773         if(matchesAny(curr.first.second.c_str(), p->filters[8], false, p->case_sensitive))
   6774             p->reporters_currently_used.push_back(curr.second(*g_cs));
   6775     }
   6776 
   6777     // TODO: check if there is nothing in reporters_currently_used
   6778 
   6779     // prepend all listeners
   6780     for(auto& curr : getListeners())
   6781         p->reporters_currently_used.insert(p->reporters_currently_used.begin(), curr.second(*g_cs));
   6782 
   6783 #ifdef DOCTEST_PLATFORM_WINDOWS
   6784     if(isDebuggerActive() && p->no_debug_output == false)
   6785         p->reporters_currently_used.push_back(new DebugOutputWindowReporter(*g_cs));
   6786 #endif // DOCTEST_PLATFORM_WINDOWS
   6787 
   6788     // handle version, help and no_run
   6789     if(p->no_run || p->version || p->help || p->list_reporters) {
   6790         DOCTEST_ITERATE_THROUGH_REPORTERS(report_query, QueryData());
   6791 
   6792         return cleanup_and_return();
   6793     }
   6794 
   6795     std::vector<const TestCase*> testArray;
   6796     for(auto& curr : getRegisteredTests())
   6797         testArray.push_back(&curr);
   6798     p->numTestCases = testArray.size();
   6799 
   6800     // sort the collected records
   6801     if(!testArray.empty()) {
   6802         if(p->order_by.compare("file", true) == 0) {
   6803             std::sort(testArray.begin(), testArray.end(), fileOrderComparator);
   6804         } else if(p->order_by.compare("suite", true) == 0) {
   6805             std::sort(testArray.begin(), testArray.end(), suiteOrderComparator);
   6806         } else if(p->order_by.compare("name", true) == 0) {
   6807             std::sort(testArray.begin(), testArray.end(), nameOrderComparator);
   6808         } else if(p->order_by.compare("rand", true) == 0) {
   6809             std::srand(p->rand_seed);
   6810 
   6811             // random_shuffle implementation
   6812             const auto first = &testArray[0];
   6813             for(size_t i = testArray.size() - 1; i > 0; --i) {
   6814                 int idxToSwap = std::rand() % (i + 1);
   6815 
   6816                 const auto temp = first[i];
   6817 
   6818                 first[i]         = first[idxToSwap];
   6819                 first[idxToSwap] = temp;
   6820             }
   6821         } else if(p->order_by.compare("none", true) == 0) {
   6822             // means no sorting - beneficial for death tests which call into the executable
   6823             // with a specific test case in mind - we don't want to slow down the startup times
   6824         }
   6825     }
   6826 
   6827     std::set<String> testSuitesPassingFilt;
   6828 
   6829     bool                             query_mode = p->count || p->list_test_cases || p->list_test_suites;
   6830     std::vector<const TestCaseData*> queryResults;
   6831 
   6832     if(!query_mode)
   6833         DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_start, DOCTEST_EMPTY);
   6834 
   6835     // invoke the registered functions if they match the filter criteria (or just count them)
   6836     for(auto& curr : testArray) {
   6837         const auto& tc = *curr;
   6838 
   6839         bool skip_me = false;
   6840         if(tc.m_skip && !p->no_skip)
   6841             skip_me = true;
   6842 
   6843         if(!matchesAny(tc.m_file.c_str(), p->filters[0], true, p->case_sensitive))
   6844             skip_me = true;
   6845         if(matchesAny(tc.m_file.c_str(), p->filters[1], false, p->case_sensitive))
   6846             skip_me = true;
   6847         if(!matchesAny(tc.m_test_suite, p->filters[2], true, p->case_sensitive))
   6848             skip_me = true;
   6849         if(matchesAny(tc.m_test_suite, p->filters[3], false, p->case_sensitive))
   6850             skip_me = true;
   6851         if(!matchesAny(tc.m_name, p->filters[4], true, p->case_sensitive))
   6852             skip_me = true;
   6853         if(matchesAny(tc.m_name, p->filters[5], false, p->case_sensitive))
   6854             skip_me = true;
   6855 
   6856         if(!skip_me)
   6857             p->numTestCasesPassingFilters++;
   6858 
   6859         // skip the test if it is not in the execution range
   6860         if((p->last < p->numTestCasesPassingFilters && p->first <= p->last) ||
   6861            (p->first > p->numTestCasesPassingFilters))
   6862             skip_me = true;
   6863 
   6864         if(skip_me) {
   6865             if(!query_mode)
   6866                 DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_skipped, tc);
   6867             continue;
   6868         }
   6869 
   6870         // do not execute the test if we are to only count the number of filter passing tests
   6871         if(p->count)
   6872             continue;
   6873 
   6874         // print the name of the test and don't execute it
   6875         if(p->list_test_cases) {
   6876             queryResults.push_back(&tc);
   6877             continue;
   6878         }
   6879 
   6880         // print the name of the test suite if not done already and don't execute it
   6881         if(p->list_test_suites) {
   6882             if((testSuitesPassingFilt.count(tc.m_test_suite) == 0) && tc.m_test_suite[0] != '\0') {
   6883                 queryResults.push_back(&tc);
   6884                 testSuitesPassingFilt.insert(tc.m_test_suite);
   6885                 p->numTestSuitesPassingFilters++;
   6886             }
   6887             continue;
   6888         }
   6889 
   6890         // execute the test if it passes all the filtering
   6891         {
   6892             p->currentTest = &tc;
   6893 
   6894             p->failure_flags = TestCaseFailureReason::None;
   6895             p->seconds       = 0;
   6896 
   6897             // reset atomic counters
   6898             p->numAssertsFailedCurrentTest_atomic = 0;
   6899             p->numAssertsCurrentTest_atomic       = 0;
   6900 
   6901             p->fullyTraversedSubcases.clear();
   6902 
   6903             DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_start, tc);
   6904 
   6905             p->timer.start();
   6906             
   6907             bool run_test = true;
   6908 
   6909             do {
   6910                 // reset some of the fields for subcases (except for the set of fully passed ones)
   6911                 p->reachedLeaf = false;
   6912                 // May not be empty if previous subcase exited via exception.
   6913                 p->subcaseStack.clear();
   6914                 p->currentSubcaseDepth = 0;
   6915 
   6916                 p->shouldLogCurrentException = true;
   6917 
   6918                 // reset stuff for logging with INFO()
   6919                 p->stringifiedContexts.clear();
   6920 
   6921 #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
   6922                 try {
   6923 #endif // DOCTEST_CONFIG_NO_EXCEPTIONS
   6924 // MSVC 2015 diagnoses fatalConditionHandler as unused (because reset() is a static method)
   6925 DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4101) // unreferenced local variable
   6926                     FatalConditionHandler fatalConditionHandler; // Handle signals
   6927                     // execute the test
   6928                     tc.m_test();
   6929                     fatalConditionHandler.reset();
   6930 DOCTEST_MSVC_SUPPRESS_WARNING_POP
   6931 #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
   6932                 } catch(const TestFailureException&) {
   6933                     p->failure_flags |= TestCaseFailureReason::AssertFailure;
   6934                 } catch(...) {
   6935                     DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_exception,
   6936                                                       {translateActiveException(), false});
   6937                     p->failure_flags |= TestCaseFailureReason::Exception;
   6938                 }
   6939 #endif // DOCTEST_CONFIG_NO_EXCEPTIONS
   6940 
   6941                 // exit this loop if enough assertions have failed - even if there are more subcases
   6942                 if(p->abort_after > 0 &&
   6943                    p->numAssertsFailed + p->numAssertsFailedCurrentTest_atomic >= p->abort_after) {
   6944                     run_test = false;
   6945                     p->failure_flags |= TestCaseFailureReason::TooManyFailedAsserts;
   6946                 }
   6947                 
   6948                 if(!p->nextSubcaseStack.empty() && run_test)
   6949                     DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_reenter, tc);
   6950                 if(p->nextSubcaseStack.empty())
   6951                     run_test = false;
   6952             } while(run_test);
   6953 
   6954             p->finalizeTestCaseData();
   6955 
   6956             DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_end, *g_cs);
   6957 
   6958             p->currentTest = nullptr;
   6959 
   6960             // stop executing tests if enough assertions have failed
   6961             if(p->abort_after > 0 && p->numAssertsFailed >= p->abort_after)
   6962                 break;
   6963         }
   6964     }
   6965 
   6966     if(!query_mode) {
   6967         DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_end, *g_cs);
   6968     } else {
   6969         QueryData qdata;
   6970         qdata.run_stats = g_cs;
   6971         qdata.data      = queryResults.data();
   6972         qdata.num_data  = unsigned(queryResults.size());
   6973         DOCTEST_ITERATE_THROUGH_REPORTERS(report_query, qdata);
   6974     }
   6975 
   6976     return cleanup_and_return();
   6977 }
   6978 
   6979 DOCTEST_DEFINE_INTERFACE(IReporter)
   6980 
   6981 int IReporter::get_num_active_contexts() { return detail::g_infoContexts.size(); }
   6982 const IContextScope* const* IReporter::get_active_contexts() {
   6983     return get_num_active_contexts() ? &detail::g_infoContexts[0] : nullptr;
   6984 }
   6985 
   6986 int IReporter::get_num_stringified_contexts() { return detail::g_cs->stringifiedContexts.size(); }
   6987 const String* IReporter::get_stringified_contexts() {
   6988     return get_num_stringified_contexts() ? &detail::g_cs->stringifiedContexts[0] : nullptr;
   6989 }
   6990 
   6991 namespace detail {
   6992     void registerReporterImpl(const char* name, int priority, reporterCreatorFunc c, bool isReporter) {
   6993         if(isReporter)
   6994             getReporters().insert(reporterMap::value_type(reporterMap::key_type(priority, name), c));
   6995         else
   6996             getListeners().insert(reporterMap::value_type(reporterMap::key_type(priority, name), c));
   6997     }
   6998 } // namespace detail
   6999 
   7000 } // namespace doctest
   7001 
   7002 #endif // DOCTEST_CONFIG_DISABLE
   7003 
   7004 #ifdef DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
   7005 DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4007) // 'function' : must be 'attribute' - see issue #182
   7006 int main(int argc, char** argv) { return doctest::Context(argc, argv).run(); }
   7007 DOCTEST_MSVC_SUPPRESS_WARNING_POP
   7008 #endif // DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
   7009 
   7010 DOCTEST_CLANG_SUPPRESS_WARNING_POP
   7011 DOCTEST_MSVC_SUPPRESS_WARNING_POP
   7012 DOCTEST_GCC_SUPPRESS_WARNING_POP
   7013 
   7014 DOCTEST_SUPPRESS_COMMON_WARNINGS_POP
   7015 
   7016 #endif // DOCTEST_LIBRARY_IMPLEMENTATION
   7017 #endif // DOCTEST_CONFIG_IMPLEMENT