annotate tests/doctest/doctest.h @ 115:54c657d621dd

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