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