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