File indexing completed on 2024-04-28 17:00:09

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