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