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