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