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