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