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