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