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