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