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