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