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