1 // ======================================================================
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 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/philsquared/Catch
21 // which uses the Boost Software License - Version 1.0
22 // see here - https://github.com/philsquared/Catch/blob/master/LICENSE_1_0.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 //
31 // The expression decomposing templates are taken from lest - https://github.com/martinmoene/lest
32 // which uses the Boost Software License - Version 1.0
33 // see here - https://github.com/martinmoene/lest/blob/master/LICENSE_1_0.txt
34 //
35 // =================================================================================================
36 // =================================================================================================
37 // =================================================================================================
38 
39 // Suppress this globally (without push/pop) - there is no way to silence it in the
40 // expression decomposition macros _Pragma() in macros doesn't work for the c++ front-end of g++
41 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55578
42 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69543
43 // Also the warning is completely worthless nowadays - http://stackoverflow.com/questions/14016993
44 #if defined(__GNUC__) && !defined(__clang__)
45 #pragma GCC diagnostic ignored "-Waggregate-return"
46 #endif
47 
48 #if defined(__clang__)
49 #pragma clang diagnostic push
50 #pragma clang diagnostic ignored "-Wunknown-pragmas"
51 #pragma clang diagnostic ignored "-Wpadded"
52 #pragma clang diagnostic ignored "-Wmissing-prototypes"
53 #pragma clang diagnostic ignored "-Wshorten-64-to-32"
54 #pragma clang diagnostic ignored "-Wunused-local-typedef"
55 #endif // __clang__
56 
57 #if defined(__GNUC__) && !defined(__clang__)
58 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6)
59 #pragma GCC diagnostic push
60 #endif // > gcc 4.6
61 #pragma GCC diagnostic ignored "-Wunknown-pragmas"
62 #pragma GCC diagnostic ignored "-Weffc++"
63 #pragma GCC diagnostic ignored "-Wstrict-overflow"
64 #pragma GCC diagnostic ignored "-Wmissing-declarations"
65 #pragma GCC diagnostic ignored "-Winline"
66 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6)
67 #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
68 #endif // > gcc 4.6
69 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 7)
70 #pragma GCC diagnostic ignored "-Wunused-local-typedefs"
71 #endif // > gcc 4.7
72 #if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ > 3)
73 #pragma GCC diagnostic ignored "-Wuseless-cast"
74 #endif // > gcc 5.3
75 #endif // __GNUC__
76 
77 #ifdef _MSC_VER
78 #pragma warning(push)
79 #pragma warning(disable : 4996) // The compiler encountered a deprecated declaration
80 #pragma warning(disable : 4706) // assignment within conditional expression
81 #pragma warning(disable : 4512) // 'class' : assignment operator could not be generated
82 #pragma warning(disable : 4127) // conditional expression is constant
83 #endif                          // _MSC_VER
84 
85 #ifndef DOCTEST_LIBRARY_INCLUDED
86 #define DOCTEST_LIBRARY_INCLUDED
87 
88 #define DOCTEST_VERSION_MAJOR 1
89 #define DOCTEST_VERSION_MINOR 1
90 #define DOCTEST_VERSION_PATCH 2
91 #define DOCTEST_VERSION_STR "1.1.2"
92 
93 #define DOCTEST_VERSION                                                                            \
94     (DOCTEST_VERSION_MAJOR * 10000 + DOCTEST_VERSION_MINOR * 100 + DOCTEST_VERSION_PATCH)
95 
96 // =================================================================================================
97 // == MODERN C++ FEATURE DETECTION =================================================================
98 // =================================================================================================
99 
100 #if __cplusplus >= 201103L
101 #ifndef DOCTEST_CONFIG_WITH_NULLPTR
102 #define DOCTEST_CONFIG_WITH_NULLPTR
103 #endif // DOCTEST_CONFIG_WITH_NULLPTR
104 #ifndef DOCTEST_CONFIG_WITH_LONG_LONG
105 #define DOCTEST_CONFIG_WITH_LONG_LONG
106 #endif // DOCTEST_CONFIG_WITH_LONG_LONG
107 #ifndef DOCTEST_CONFIG_WITH_STATIC_ASSERT
108 #define DOCTEST_CONFIG_WITH_STATIC_ASSERT
109 #endif // DOCTEST_CONFIG_WITH_STATIC_ASSERT
110 #endif // __cplusplus >= 201103L
111 
112 // nullptr
113 
114 #ifndef DOCTEST_CONFIG_WITH_NULLPTR
115 #ifdef __clang__
116 #if __has_feature(cxx_nullptr)
117 #define DOCTEST_CONFIG_WITH_NULLPTR
118 #endif // __has_feature(cxx_nullptr)
119 #endif // __clang__
120 
121 #if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
122 #define DOCTEST_CONFIG_WITH_NULLPTR
123 #endif // __GNUC__
124 
125 #if defined(_MSC_VER) && (_MSC_VER >= 1600) // MSVC 2010
126 #define DOCTEST_CONFIG_WITH_NULLPTR
127 #endif // _MSC_VER
128 #endif // DOCTEST_CONFIG_WITH_NULLPTR
129 
130 #if defined(DOCTEST_CONFIG_NO_NULLPTR) && defined(DOCTEST_CONFIG_WITH_NULLPTR)
131 #undef DOCTEST_CONFIG_WITH_NULLPTR
132 #endif // DOCTEST_CONFIG_NO_NULLPTR
133 
134 // long long
135 
136 #ifndef DOCTEST_CONFIG_WITH_LONG_LONG
137 #if !defined(DOCTEST_CONFIG_WITH_LONG_LONG) && defined(_MSC_VER) && (_MSC_VER >= 1400)
138 #define DOCTEST_CONFIG_WITH_LONG_LONG
139 #endif // _MSC_VER
140 #endif // DOCTEST_CONFIG_WITH_LONG_LONG
141 
142 #if defined(DOCTEST_CONFIG_NO_LONG_LONG) && defined(DOCTEST_CONFIG_WITH_LONG_LONG)
143 #undef DOCTEST_CONFIG_WITH_LONG_LONG
144 #endif // DOCTEST_CONFIG_NO_LONG_LONG
145 
146 // static_assert
147 
148 #ifndef DOCTEST_CONFIG_WITH_STATIC_ASSERT
149 #ifdef __clang__
150 #if __has_feature(cxx_static_assert)
151 #define DOCTEST_CONFIG_WITH_STATIC_ASSERT
152 #endif // __has_feature(cxx_static_assert)
153 #endif // __clang__
154 
155 #if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ >= 3 && defined(__GXX_EXPERIMENTAL_CXX0X__)
156 #define DOCTEST_CONFIG_WITH_STATIC_ASSERT
157 #endif // __GNUC__
158 
159 #if defined(_MSC_VER) && (_MSC_VER >= 1600) // MSVC 2010
160 #define DOCTEST_CONFIG_WITH_STATIC_ASSERT
161 #endif // _MSC_VER
162 #endif // DOCTEST_CONFIG_WITH_STATIC_ASSERT
163 
164 #if defined(DOCTEST_CONFIG_NO_STATIC_ASSERT) && defined(DOCTEST_CONFIG_WITH_STATIC_ASSERT)
165 #undef DOCTEST_CONFIG_WITH_STATIC_ASSERT
166 #endif // DOCTEST_CONFIG_NO_STATIC_ASSERT
167 
168 #if defined(DOCTEST_CONFIG_WITH_NULLPTR) || defined(DOCTEST_CONFIG_WITH_LONG_LONG) ||              \
169         defined(DOCTEST_CONFIG_WITH_STATIC_ASSERT)
170 #define DOCTEST_NO_CPP11_COMPAT
171 #endif // c++11 stuff
172 
173 #if defined(__clang__) && defined(DOCTEST_NO_CPP11_COMPAT)
174 #pragma clang diagnostic ignored "-Wc++98-compat"
175 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
176 #endif // __clang__ && DOCTEST_NO_CPP11_COMPAT
177 
178 // =================================================================================================
179 // == MODERN C++ FEATURE DETECTION END =============================================================
180 // =================================================================================================
181 
182 // internal macros for string concatenation and anonymous variable name generation
183 #define DOCTEST_CAT_IMPL(s1, s2) s1##s2
184 #define DOCTEST_CAT(s1, s2) DOCTEST_CAT_IMPL(s1, s2)
185 #ifdef __COUNTER__ // not standard and may be missing for some compilers
186 #define DOCTEST_ANONYMOUS(x) DOCTEST_CAT(x, __COUNTER__)
187 #else // __COUNTER__
188 #define DOCTEST_ANONYMOUS(x) DOCTEST_CAT(x, __LINE__)
189 #endif // __COUNTER__
190 
191 // macro for making a string out of an identifier
192 #define DOCTEST_TOSTR_IMPL(x) #x
193 #define DOCTEST_TOSTR(x) DOCTEST_TOSTR_IMPL(x)
194 
195 // for concatenating literals and making the result a string
196 #define DOCTEST_STR_CONCAT_TOSTR(s1, s2) DOCTEST_TOSTR(s1) DOCTEST_TOSTR(s2)
197 
198 // counts the number of elements in a C string
199 #define DOCTEST_COUNTOF(x) (sizeof(x) / sizeof(x[0]))
200 
201 #ifndef DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE
202 #define DOCTEST_REF_WRAP(x) x&
203 #else // DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE
204 #define DOCTEST_REF_WRAP(x) x
205 #endif // DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE
206 
207 // not using __APPLE__ because... this is how Catch does it
208 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
209 #define DOCTEST_PLATFORM_MAC
210 #elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
211 #define DOCTEST_PLATFORM_IPHONE
212 #elif defined(_WIN32) || defined(_MSC_VER)
213 #define DOCTEST_PLATFORM_WINDOWS
214 #else
215 #define DOCTEST_PLATFORM_LINUX
216 #endif
217 
218 #define DOCTEST_GCS() (*doctest::detail::getTestsContextState())
219 
220 // should probably take a look at https://github.com/scottt/debugbreak
221 #ifdef DOCTEST_PLATFORM_MAC
222 // The following code snippet based on:
223 // http://cocoawithlove.com/2008/03/break-into-debugger.html
224 #if defined(__ppc64__) || defined(__ppc__)
225 #define DOCTEST_BREAK_INTO_DEBUGGER()                                                              \
226     __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" : : : "memory", "r0", "r3", "r4")
227 #else // __ppc64__ || __ppc__
228 #define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :)
229 #endif // __ppc64__ || __ppc__
230 #elif defined(_MSC_VER)
231 #define DOCTEST_BREAK_INTO_DEBUGGER() __debugbreak()
232 #elif defined(__MINGW32__)
233 extern "C" __declspec(dllimport) void __stdcall DebugBreak();
234 #define DOCTEST_BREAK_INTO_DEBUGGER() ::DebugBreak()
235 #else // linux
236 #define DOCTEST_BREAK_INTO_DEBUGGER() ((void)0)
237 #endif // linux
238 
239 #define DOCTEST_BREAK_INTO_DEBUGGER_CHECKED()                                                      \
240     if(doctest::detail::isDebuggerActive() && !DOCTEST_GCS().no_breaks)                            \
241         DOCTEST_BREAK_INTO_DEBUGGER();
242 
243 #ifdef __clang__
244 // to detect if libc++ is being used with clang (the _LIBCPP_VERSION identifier)
245 #include <ciso646>
246 #endif // __clang__
247 
248 #ifdef _LIBCPP_VERSION
249 // not forward declaring ostream for libc++ because I had some problems (inline namespaces vs c++98)
250 // so the <iosfwd> header is used - also it is very light and doesn't drag a ton of stuff
251 #include <iosfwd>
252 #else // _LIBCPP_VERSION
253 #ifndef DOCTEST_CONFIG_USE_IOSFWD
254 namespace std
255 {
256 template <class charT>
257 struct char_traits;
258 template <>
259 struct char_traits<char>;
260 template <class charT, class traits>
261 class basic_ostream;
262 typedef basic_ostream<char, char_traits<char> > ostream;
263 }
264 #else // DOCTEST_CONFIG_USE_IOSFWD
265 #include <iosfwd>
266 #endif // DOCTEST_CONFIG_USE_IOSFWD
267 #endif // _LIBCPP_VERSION
268 
269 // static assert macro - because of the c++98 support requires that the message is an
270 // identifier (no spaces and not a C string) - example without quotes: I_am_a_message
271 // taken from here: http://stackoverflow.com/a/1980156/3162383
272 #ifdef DOCTEST_CONFIG_WITH_STATIC_ASSERT
273 #define DOCTEST_STATIC_ASSERT(expression, message) static_assert(expression, #message)
274 #else // DOCTEST_CONFIG_WITH_STATIC_ASSERT
275 #define DOCTEST_STATIC_ASSERT(expression, message)                                                 \
276     struct DOCTEST_CAT(__static_assertion_at_line_, __LINE__)                                      \
277     {                                                                                              \
278         doctest::detail::static_assert_impl::StaticAssertion<static_cast<bool>((expression))>      \
279                 DOCTEST_CAT(DOCTEST_CAT(DOCTEST_CAT(STATIC_ASSERTION_FAILED_AT_LINE_, __LINE__),   \
280                                         _),                                                        \
281                             message);                                                              \
282     };                                                                                             \
283     typedef doctest::detail::static_assert_impl::StaticAssertionTest<sizeof(                       \
284             DOCTEST_CAT(__static_assertion_at_line_, __LINE__))>                                   \
285             DOCTEST_CAT(__static_assertion_test_at_line_, __LINE__)
286 #endif // DOCTEST_CONFIG_WITH_STATIC_ASSERT
287 
288 #ifdef DOCTEST_CONFIG_WITH_NULLPTR
289 #ifdef _LIBCPP_VERSION
290 #include <cstddef>
291 #else  // _LIBCPP_VERSION
292 namespace std
293 { typedef decltype(nullptr) nullptr_t; }
294 #endif // _LIBCPP_VERSION
295 #endif // DOCTEST_CONFIG_WITH_NULLPTR
296 
297 namespace doctest
298 {
299 class String
300 {
301     char* m_str;
302 
303     void copy(const String& other);
304 
305 public:
306     String(const char* in = "");
307     String(const String& other);
308     ~String();
309 
310     String& operator=(const String& other);
311 
312     String operator+(const String& other) const;
313     String& operator+=(const String& other);
314 
315     char& operator[](unsigned pos) { return m_str[pos]; }
316     const char& operator[](unsigned pos) const { return m_str[pos]; }
317 
318     char*       c_str() { return m_str; }
319     const char* c_str() const { return m_str; }
320 
321     unsigned size() const;
322     unsigned length() const;
323 
324     int compare(const char* other, bool no_case = false) const;
325     int compare(const String& other, bool no_case = false) const;
326 };
327 
328 // clang-format off
329 inline bool operator==(const String& lhs, const String& rhs) { return lhs.compare(rhs) == 0; }
330 inline bool operator!=(const String& lhs, const String& rhs) { return lhs.compare(rhs) != 0; }
331 inline bool operator< (const String& lhs, const String& rhs) { return lhs.compare(rhs) < 0; }
332 inline bool operator> (const String& lhs, const String& rhs) { return lhs.compare(rhs) > 0; }
333 inline bool operator<=(const String& lhs, const String& rhs) { return (lhs != rhs) ? lhs.compare(rhs) < 0 : true; }
334 inline bool operator>=(const String& lhs, const String& rhs) { return (lhs != rhs) ? lhs.compare(rhs) > 0 : true; }
335 // clang-format on
336 
337 std::ostream& operator<<(std::ostream& stream, const String& in);
338 
339 namespace detail
340 {
341 #ifndef DOCTEST_CONFIG_WITH_STATIC_ASSERT
342     namespace static_assert_impl
343     {
344         template <bool>
345         struct StaticAssertion;
346 
347         template <>
348         struct StaticAssertion<true>
349         {};
350 
351         template <int i>
352         struct StaticAssertionTest
353         {};
354     }  // namespace static_assert_impl
355 #endif // DOCTEST_CONFIG_WITH_STATIC_ASSERT
356 
357     template <typename T>
358     struct deferred_false
359     { static const bool value = false; };
360 
361     namespace has_insertion_operator_impl
362     {
363         typedef char no;
364         typedef char yes[2];
365 
366         struct any_t
367         {
368             template <typename T>
369             any_t(const DOCTEST_REF_WRAP(T));
370         };
371 
372         yes& testStreamable(std::ostream&);
373         no   testStreamable(no);
374 
375         no operator<<(const std::ostream&, const any_t&);
376 
377         template <typename T>
378         struct has_insertion_operator
379         {
380             static std::ostream& s;
381             static const DOCTEST_REF_WRAP(T) t;
382             static const bool value = sizeof(testStreamable(s << t)) == sizeof(yes);
383         };
384     } // namespace has_insertion_operator_impl
385 
386     template <typename T>
387     struct has_insertion_operator : has_insertion_operator_impl::has_insertion_operator<T>
388     {};
389 
390     std::ostream* createStream();
391     String        getStreamResult(std::ostream*);
392     void          freeStream(std::ostream*);
393 
394     template <bool C>
395     struct StringMakerBase
396     {
397         template <typename T>
398         static String convert(const DOCTEST_REF_WRAP(T)) {
399             return "{?}";
400         }
401     };
402 
403     template <>
404     struct StringMakerBase<true>
405     {
406         template <typename T>
407         static String convert(const DOCTEST_REF_WRAP(T) in) {
408             std::ostream* stream = createStream();
409             *stream << in;
410             String result = getStreamResult(stream);
411             freeStream(stream);
412             return result;
413         }
414     };
415 
416     String rawMemoryToString(const void* object, unsigned size);
417 
418     template <typename T>
419     String rawMemoryToString(const DOCTEST_REF_WRAP(T) object) {
420         return rawMemoryToString(&object, sizeof(object));
421     }
422 } // namespace detail
423 
424 template <typename T>
425 struct StringMaker : detail::StringMakerBase<detail::has_insertion_operator<T>::value>
426 {};
427 
428 template <typename T>
429 struct StringMaker<T*>
430 {
431     template <typename U>
432     static String convert(U* p) {
433         if(!p)
434             return "NULL";
435         else
436             return detail::rawMemoryToString(p);
437     }
438 };
439 
440 template <typename R, typename C>
441 struct StringMaker<R C::*>
442 {
443     static String convert(R C::*p) {
444         if(!p)
445             return "NULL";
446         else
447             return detail::rawMemoryToString(p);
448     }
449 };
450 
451 template <typename T>
452 String toString(const DOCTEST_REF_WRAP(T) value) {
453     return StringMaker<T>::convert(value);
454 }
455 
456 #ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
457 String toString(char* in);
458 String toString(const char* in);
459 #endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
460 String toString(bool in);
461 String toString(float in);
462 String toString(double in);
463 String toString(double long in);
464 
465 String toString(char in);
466 String toString(char unsigned in);
467 String toString(int short in);
468 String toString(int short unsigned in);
469 String toString(int in);
470 String toString(int unsigned in);
471 String toString(int long in);
472 String toString(int long unsigned in);
473 
474 #ifdef DOCTEST_CONFIG_WITH_LONG_LONG
475 String toString(int long long in);
476 String toString(int long long unsigned in);
477 #endif // DOCTEST_CONFIG_WITH_LONG_LONG
478 
479 #ifdef DOCTEST_CONFIG_WITH_NULLPTR
480 String toString(std::nullptr_t in);
481 #endif // DOCTEST_CONFIG_WITH_NULLPTR
482 
483 class Approx
484 {
485 public:
486     explicit Approx(double value);
487 
488     Approx(Approx const& other)
489             : m_epsilon(other.m_epsilon)
490             , m_scale(other.m_scale)
491             , m_value(other.m_value) {}
492 
493     Approx operator()(double value) {
494         Approx approx(value);
495         approx.epsilon(m_epsilon);
496         approx.scale(m_scale);
497         return approx;
498     }
499 
500     friend bool operator==(double lhs, Approx const& rhs);
501     friend bool operator==(Approx const& lhs, double rhs) { return operator==(rhs, lhs); }
502     friend bool operator!=(double lhs, Approx const& rhs) { return !operator==(lhs, rhs); }
503     friend bool operator!=(Approx const& lhs, double rhs) { return !operator==(rhs, lhs); }
504 
505     Approx& epsilon(double newEpsilon) {
506         m_epsilon = newEpsilon;
507         return *this;
508     }
509 
510     Approx& scale(double newScale) {
511         m_scale = newScale;
512         return *this;
513     }
514 
515     String toString() const;
516 
517 private:
518     double m_epsilon;
519     double m_scale;
520     double m_value;
521 };
522 
523 template <>
524 inline String toString<Approx>(const DOCTEST_REF_WRAP(Approx) value) {
525     return value.toString();
526 }
527 
528 #if !defined(DOCTEST_CONFIG_DISABLE)
529 
530 namespace detail
531 {
532     // the function type this library works with
533     typedef void (*funcType)(void);
534 
535     namespace assertType
536     {
537         enum Enum
538         {
539             // macro traits
540 
541             is_warn    = 1,
542             is_check   = 2,
543             is_require = 4,
544 
545             is_throws    = 8,
546             is_throws_as = 16,
547             is_nothrow   = 32,
548 
549             is_fast  = 64, // not checked anywhere - used just to distinguish the types
550             is_false = 128,
551             is_unary = 256,
552 
553             is_eq = 512,
554             is_ne = 1024,
555 
556             is_lt = 2048,
557             is_gt = 4096,
558 
559             is_ge = 8192,
560             is_le = 16384,
561 
562             // macro types
563 
564             DT_WARN    = is_warn,
565             DT_CHECK   = is_check,
566             DT_REQUIRE = is_require,
567 
568             DT_WARN_FALSE    = is_false | is_warn,
569             DT_CHECK_FALSE   = is_false | is_check,
570             DT_REQUIRE_FALSE = is_false | is_require,
571 
572             DT_WARN_THROWS    = is_throws | is_warn,
573             DT_CHECK_THROWS   = is_throws | is_check,
574             DT_REQUIRE_THROWS = is_throws | is_require,
575 
576             DT_WARN_THROWS_AS    = is_throws_as | is_warn,
577             DT_CHECK_THROWS_AS   = is_throws_as | is_check,
578             DT_REQUIRE_THROWS_AS = is_throws_as | is_require,
579 
580             DT_WARN_NOTHROW    = is_nothrow | is_warn,
581             DT_CHECK_NOTHROW   = is_nothrow | is_check,
582             DT_REQUIRE_NOTHROW = is_nothrow | is_require,
583 
584             DT_WARN_EQ    = is_eq | is_warn,
585             DT_CHECK_EQ   = is_eq | is_check,
586             DT_REQUIRE_EQ = is_eq | is_require,
587 
588             DT_WARN_NE    = is_ne | is_warn,
589             DT_CHECK_NE   = is_ne | is_check,
590             DT_REQUIRE_NE = is_ne | is_require,
591 
592             DT_WARN_GT    = is_gt | is_warn,
593             DT_CHECK_GT   = is_gt | is_check,
594             DT_REQUIRE_GT = is_gt | is_require,
595 
596             DT_WARN_LT    = is_lt | is_warn,
597             DT_CHECK_LT   = is_lt | is_check,
598             DT_REQUIRE_LT = is_lt | is_require,
599 
600             DT_WARN_GE    = is_ge | is_warn,
601             DT_CHECK_GE   = is_ge | is_check,
602             DT_REQUIRE_GE = is_ge | is_require,
603 
604             DT_WARN_LE    = is_le | is_warn,
605             DT_CHECK_LE   = is_le | is_check,
606             DT_REQUIRE_LE = is_le | is_require,
607 
608             DT_WARN_UNARY    = is_unary | is_warn,
609             DT_CHECK_UNARY   = is_unary | is_check,
610             DT_REQUIRE_UNARY = is_unary | is_require,
611 
612             DT_WARN_UNARY_FALSE    = is_false | is_unary | is_warn,
613             DT_CHECK_UNARY_FALSE   = is_false | is_unary | is_check,
614             DT_REQUIRE_UNARY_FALSE = is_false | is_unary | is_require,
615 
616             DT_FAST_WARN_EQ    = is_fast | is_eq | is_warn,
617             DT_FAST_CHECK_EQ   = is_fast | is_eq | is_check,
618             DT_FAST_REQUIRE_EQ = is_fast | is_eq | is_require,
619 
620             DT_FAST_WARN_NE    = is_fast | is_ne | is_warn,
621             DT_FAST_CHECK_NE   = is_fast | is_ne | is_check,
622             DT_FAST_REQUIRE_NE = is_fast | is_ne | is_require,
623 
624             DT_FAST_WARN_GT    = is_fast | is_gt | is_warn,
625             DT_FAST_CHECK_GT   = is_fast | is_gt | is_check,
626             DT_FAST_REQUIRE_GT = is_fast | is_gt | is_require,
627 
628             DT_FAST_WARN_LT    = is_fast | is_lt | is_warn,
629             DT_FAST_CHECK_LT   = is_fast | is_lt | is_check,
630             DT_FAST_REQUIRE_LT = is_fast | is_lt | is_require,
631 
632             DT_FAST_WARN_GE    = is_fast | is_ge | is_warn,
633             DT_FAST_CHECK_GE   = is_fast | is_ge | is_check,
634             DT_FAST_REQUIRE_GE = is_fast | is_ge | is_require,
635 
636             DT_FAST_WARN_LE    = is_fast | is_le | is_warn,
637             DT_FAST_CHECK_LE   = is_fast | is_le | is_check,
638             DT_FAST_REQUIRE_LE = is_fast | is_le | is_require,
639 
640             DT_FAST_WARN_UNARY    = is_fast | is_unary | is_warn,
641             DT_FAST_CHECK_UNARY   = is_fast | is_unary | is_check,
642             DT_FAST_REQUIRE_UNARY = is_fast | is_unary | is_require,
643 
644             DT_FAST_WARN_UNARY_FALSE    = is_fast | is_false | is_unary | is_warn,
645             DT_FAST_CHECK_UNARY_FALSE   = is_fast | is_false | is_unary | is_check,
646             DT_FAST_REQUIRE_UNARY_FALSE = is_fast | is_false | is_unary | is_require
647         };
648     } // namespace assertType
649 
650     const char* getAssertString(assertType::Enum val);
651 
652     // clang-format off
653     template<class T>               struct decay_array       { typedef T type; };
654     template<class T, unsigned N>   struct decay_array<T[N]> { typedef T* type; };
655     template<class T>               struct decay_array<T[]>  { typedef T* type; };
656 
657     template<class T>   struct not_char_pointer              { enum { value = true }; };
658     template<>          struct not_char_pointer<char*>       { enum { value = false }; };
659     template<>          struct not_char_pointer<const char*> { enum { value = false }; };
660 
661     template<class T> struct can_use_op : not_char_pointer<typename decay_array<T>::type> {};
662 
663     template<bool, class = void> struct enable_if {};
664     template<class T> struct enable_if<true, T> { typedef T type; };
665     // clang-format on
666 
667     struct TestFailureException
668     {};
669 
670     bool checkIfShouldThrow(assertType::Enum assert_type);
671     void fastAssertThrowIfFlagSet(int flags);
672     void throwException();
673     bool always_false();
674 
675     // a struct defining a registered test callback
676     struct TestData
677     {
678         // not used for determining uniqueness
679         const char* m_suite; // the test suite in which the test was added
680         const char* m_name;  // name of the test function
681         funcType    m_f;     // a function pointer to the test function
682 
683         // fields by which uniqueness of test cases shall be determined
684         const char* m_file; // the file in which the test was registered
685         unsigned    m_line; // the line where the test was registered
686 
687         TestData(const char* suite, const char* name, funcType f, const char* file, unsigned line)
688                 : m_suite(suite)
689                 , m_name(name)
690                 , m_f(f)
691                 , m_file(file)
692                 , m_line(line) {}
693 
694         bool operator<(const TestData& other) const;
695     };
696 
697     struct SubcaseSignature
698     {
699         const char* m_name;
700         const char* m_file;
701         int         m_line;
702 
703         SubcaseSignature(const char* name, const char* file, int line)
704                 : m_name(name)
705                 , m_file(file)
706                 , m_line(line) {}
707 
708         bool operator<(const SubcaseSignature& other) const;
709     };
710 
711     struct Subcase
712     {
713         SubcaseSignature m_signature;
714         bool             m_entered;
715 
716         Subcase(const char* name, const char* file, int line);
717         Subcase(const Subcase& other);
718         ~Subcase();
719 
720         operator bool() const { return m_entered; }
721     };
722 
723     template <typename L, typename R>
724     String stringifyBinaryExpr(const DOCTEST_REF_WRAP(L) lhs, const char* op,
725                                const DOCTEST_REF_WRAP(R) rhs) {
726         return toString(lhs) + op + toString(rhs);
727     }
728 
729     struct Result
730     {
731         bool   m_passed;
732         String m_decomposition;
733 
734 // to fix gcc 4.7 "-Winline" warnings
735 #if defined(__GNUC__) && !defined(__clang__)
736         __attribute__((noinline))
737 #endif
738         ~Result() {
739         }
740 
741         Result(bool passed = false, const String& decomposition = String())
742                 : m_passed(passed)
743                 , m_decomposition(decomposition) {}
744 
745         Result(const Result& other)
746                 : m_passed(other.m_passed)
747                 , m_decomposition(other.m_decomposition) {}
748 
749 // to fix gcc 4.7 "-Winline" warnings
750 #if defined(__GNUC__) && !defined(__clang__)
751         __attribute__((noinline))
752 #endif
753         Result&
754         operator=(const Result& other) {
755             m_passed        = other.m_passed;
756             m_decomposition = other.m_decomposition;
757 
758             return *this;
759         }
760 
761         operator bool() { return !m_passed; }
762 
763         void invert() { m_passed = !m_passed; }
764 
765         // clang-format off
766         // forbidding some expressions based on this table: http://en.cppreference.com/w/cpp/language/operator_precedence
767         template <typename R> Result operator&  (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
768         template <typename R> Result operator^  (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
769         template <typename R> Result operator|  (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
770         template <typename R> Result operator&& (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
771         template <typename R> Result operator|| (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
772         template <typename R> Result operator== (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
773         template <typename R> Result operator!= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
774         template <typename R> Result operator<  (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
775         template <typename R> Result operator>  (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
776         template <typename R> Result operator<= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
777         template <typename R> Result operator>= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
778         template <typename R> Result operator=  (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
779         template <typename R> Result operator+= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
780         template <typename R> Result operator-= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
781         template <typename R> Result operator*= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
782         template <typename R> Result operator/= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
783         template <typename R> Result operator%= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
784         template <typename R> Result operator<<=(const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
785         template <typename R> Result operator>>=(const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
786         template <typename R> Result operator&= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
787         template <typename R> Result operator^= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
788         template <typename R> Result operator|= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
789         // clang-format on
790     };
791 
792 #ifndef DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION
793 
794 #if defined(__clang__)
795 #pragma clang diagnostic push
796 #pragma clang diagnostic ignored "-Wsign-conversion"
797 #pragma clang diagnostic ignored "-Wsign-compare"
798 #pragma clang diagnostic ignored "-Wdouble-promotion"
799 //#pragma clang diagnostic ignored "-Wconversion"
800 //#pragma clang diagnostic ignored "-Wfloat-equal"
801 #endif // __clang__
802 
803 #if defined(__GNUC__) && !defined(__clang__)
804 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6)
805 #pragma GCC diagnostic push
806 #endif // > gcc 4.6
807 #pragma GCC diagnostic ignored "-Wsign-conversion"
808 #pragma GCC diagnostic ignored "-Wsign-compare"
809 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5)
810 #pragma GCC diagnostic ignored "-Wdouble-promotion"
811 #endif // > gcc 4.5
812 //#pragma GCC diagnostic ignored "-Wconversion"
813 //#pragma GCC diagnostic ignored "-Wfloat-equal"
814 #endif // __GNUC__
815 
816 #ifdef _MSC_VER
817 #pragma warning(push)
818 // http://stackoverflow.com/questions/39479163 what's the difference between C4018 and C4389
819 #pragma warning(disable : 4389) // 'operator' : signed/unsigned mismatch
820 #pragma warning(disable : 4018) // 'expression' : signed/unsigned mismatch
821 //#pragma warning(disable : 4805) // 'operation' : unsafe mix of type 'type' and type 'type' in operation
822 #endif // _MSC_VER
823 
824 #endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION
825 
826 // clang-format off
827 #ifndef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
828 #define DOCTEST_COMPARISON_RETURN_TYPE bool
829 #else // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
830 #define DOCTEST_COMPARISON_RETURN_TYPE typename enable_if<can_use_op<L>::value || can_use_op<R>::value, bool>::type
831     inline bool eq(const char* lhs, const char* rhs) { return String(lhs) == String(rhs); }
832     inline bool ne(const char* lhs, const char* rhs) { return String(lhs) != String(rhs); }
833     inline bool lt(const char* lhs, const char* rhs) { return String(lhs) <  String(rhs); }
834     inline bool gt(const char* lhs, const char* rhs) { return String(lhs) >  String(rhs); }
835     inline bool le(const char* lhs, const char* rhs) { return String(lhs) <= String(rhs); }
836     inline bool ge(const char* lhs, const char* rhs) { return String(lhs) >= String(rhs); }
837 #endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
838 
839     template <typename L, typename R> DOCTEST_COMPARISON_RETURN_TYPE eq(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) { return lhs == rhs; }
840     template <typename L, typename R> DOCTEST_COMPARISON_RETURN_TYPE ne(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) { return lhs != rhs; }
841     template <typename L, typename R> DOCTEST_COMPARISON_RETURN_TYPE lt(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) { return lhs <  rhs; }
842     template <typename L, typename R> DOCTEST_COMPARISON_RETURN_TYPE gt(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) { return lhs >  rhs; }
843     template <typename L, typename R> DOCTEST_COMPARISON_RETURN_TYPE le(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) { return lhs <= rhs; }
844     template <typename L, typename R> DOCTEST_COMPARISON_RETURN_TYPE ge(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) { return lhs >= rhs; }
845     // clang-format on
846 
847     template <typename L>
848     struct Expression_lhs
849     {
850         L lhs;
851 
852         Expression_lhs(L in)
853                 : lhs(in) {}
854 
855         Expression_lhs(const Expression_lhs& other)
856                 : lhs(other.lhs) {}
857 
858         operator Result() { return Result(!!lhs, toString(lhs)); }
859 
860 // clang-format off
861 #ifndef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
862         template <typename R> Result operator==(const DOCTEST_REF_WRAP(R) rhs) { return Result(lhs == rhs, stringifyBinaryExpr(lhs, " == ", rhs)); }
863         template <typename R> Result operator!=(const DOCTEST_REF_WRAP(R) rhs) { return Result(lhs != rhs, stringifyBinaryExpr(lhs, " != ", rhs)); }
864         template <typename R> Result operator< (const DOCTEST_REF_WRAP(R) rhs) { return Result(lhs <  rhs, stringifyBinaryExpr(lhs, " < " , rhs)); }
865         template <typename R> Result operator<=(const DOCTEST_REF_WRAP(R) rhs) { return Result(lhs <= rhs, stringifyBinaryExpr(lhs, " <= ", rhs)); }
866         template <typename R> Result operator> (const DOCTEST_REF_WRAP(R) rhs) { return Result(lhs >  rhs, stringifyBinaryExpr(lhs, " > " , rhs)); }
867         template <typename R> Result operator>=(const DOCTEST_REF_WRAP(R) rhs) { return Result(lhs >= rhs, stringifyBinaryExpr(lhs, " >= ", rhs)); }
868 #else  // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
869         template <typename R> Result operator==(const DOCTEST_REF_WRAP(R) rhs) { return Result(eq(lhs, rhs), stringifyBinaryExpr(lhs, " == ", rhs)); }
870         template <typename R> Result operator!=(const DOCTEST_REF_WRAP(R) rhs) { return Result(ne(lhs, rhs), stringifyBinaryExpr(lhs, " != ", rhs)); }
871         template <typename R> Result operator< (const DOCTEST_REF_WRAP(R) rhs) { return Result(lt(lhs, rhs), stringifyBinaryExpr(lhs, " < " , rhs)); }
872         template <typename R> Result operator<=(const DOCTEST_REF_WRAP(R) rhs) { return Result(le(lhs, rhs), stringifyBinaryExpr(lhs, " <= ", rhs)); }
873         template <typename R> Result operator> (const DOCTEST_REF_WRAP(R) rhs) { return Result(gt(lhs, rhs), stringifyBinaryExpr(lhs, " > " , rhs)); }
874         template <typename R> Result operator>=(const DOCTEST_REF_WRAP(R) rhs) { return Result(ge(lhs, rhs), stringifyBinaryExpr(lhs, " >= ", rhs)); }
875 #endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
876         // clang-format on
877 
878         // clang-format off
879         // forbidding some expressions based on this table: http://en.cppreference.com/w/cpp/language/operator_precedence
880         template <typename R> int operator&  (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
881         template <typename R> int operator^  (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
882         template <typename R> int operator|  (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
883         template <typename R> int operator&& (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
884         template <typename R> int operator|| (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
885         template <typename R> int operator=  (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
886         template <typename R> int operator+= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
887         template <typename R> int operator-= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
888         template <typename R> int operator*= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
889         template <typename R> int operator/= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
890         template <typename R> int operator%= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
891         template <typename R> int operator<<=(const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
892         template <typename R> int operator>>=(const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
893         template <typename R> int operator&= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
894         template <typename R> int operator^= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
895         template <typename R> int operator|= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
896         // these 2 are unfortunate because they should be allowed - they have higher precedence over the comparisons, but the
897         // ExpressionDecomposer class uses the left shift operator to capture the left operand of the binary expression...
898         template <typename R> int operator<< (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Please_Surround_The_Left_Shift_Operation_With_Parenthesis); return int(); }
899         template <typename R> int operator>> (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Please_Surround_The_Right_Shift_Operation_With_Parenthesis); return int(); }
900         // clang-format on
901     };
902 
903 #ifndef DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION
904 
905 #if defined(__clang__)
906 #pragma clang diagnostic pop
907 #endif // __clang__
908 
909 #if defined(__GNUC__) && !defined(__clang__)
910 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6)
911 #pragma GCC diagnostic pop
912 #endif // > gcc 4.6
913 #endif // __GNUC__
914 
915 #ifdef _MSC_VER
916 #pragma warning(pop)
917 #endif // _MSC_VER
918 
919 #endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION
920 
921     struct ExpressionDecomposer
922     {
923         template <typename L>
924         Expression_lhs<const DOCTEST_REF_WRAP(L)> operator<<(const DOCTEST_REF_WRAP(L) operand) {
925             return Expression_lhs<const DOCTEST_REF_WRAP(L)>(operand);
926         }
927     };
928 
929     // forward declarations of functions used by the macros
930     int regTest(void (*f)(void), unsigned line, const char* file, const char* name);
931     int setTestSuiteName(const char* name);
932 
933     void addFailedAssert(assertType::Enum assert_type);
934 
935     void logTestStart(const char* name, const char* file, unsigned line);
936     void logTestEnd();
937 
938     void logTestCrashed();
939 
940     void logAssert(bool passed, const char* decomposition, bool threw, const char* expr,
941                    assertType::Enum assert_type, const char* file, int line);
942 
943     void logAssertThrows(bool threw, const char* expr, assertType::Enum assert_type,
944                          const char* file, int line);
945 
946     void logAssertThrowsAs(bool threw, bool threw_as, const char* as, const char* expr,
947                            assertType::Enum assert_type, const char* file, int line);
948 
949     void logAssertNothrow(bool threw, const char* expr, assertType::Enum assert_type,
950                           const char* file, int line);
951 
952     bool isDebuggerActive();
953     void writeToDebugConsole(const String&);
954 
955     struct TestAccessibleContextState
956     {
957         bool            success;   // include successful assertions in output
958         bool            no_throw;  // to skip exceptions-related assertion macros
959         bool            no_breaks; // to not break into the debugger
960         const TestData* currentTest;
961         bool            hasLoggedCurrentTestStart;
962         int             numAssertionsForCurrentTestcase;
963     };
964 
965     struct ContextState;
966 
967     TestAccessibleContextState* getTestsContextState();
968 
969     namespace binaryAssertComparison
970     {
971         enum Enum
972         {
973             eq = 0,
974             ne,
975             gt,
976             lt,
977             ge,
978             le
979         };
980     } // namespace binaryAssertComparison
981 
982     // clang-format off
983     template <int, class L, class R> struct RelationalComparator     { bool operator()(const DOCTEST_REF_WRAP(L),     const DOCTEST_REF_WRAP(R)    ) const { return false;        } };
984     template <class L, class R> struct RelationalComparator<0, L, R> { bool operator()(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) const { return eq(lhs, rhs); } };
985     template <class L, class R> struct RelationalComparator<1, L, R> { bool operator()(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) const { return ne(lhs, rhs); } };
986     template <class L, class R> struct RelationalComparator<2, L, R> { bool operator()(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) const { return gt(lhs, rhs); } };
987     template <class L, class R> struct RelationalComparator<3, L, R> { bool operator()(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) const { return lt(lhs, rhs); } };
988     template <class L, class R> struct RelationalComparator<4, L, R> { bool operator()(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) const { return ge(lhs, rhs); } };
989     template <class L, class R> struct RelationalComparator<5, L, R> { bool operator()(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) const { return le(lhs, rhs); } };
990     // clang-format on
991 
992     struct ResultBuilder
993     {
994         assertType::Enum m_assert_type;
995         const char*      m_file;
996         int              m_line;
997         const char*      m_expr;
998         const char*      m_exception_type;
999 
1000         Result m_result;
1001         bool   m_threw;
1002         bool   m_threw_as;
1003         bool   m_failed;
1004 
1005         ResultBuilder(assertType::Enum assert_type, const char* file, int line, const char* expr,
1006                       const char* exception_type = "");
1007 
1008 // to fix gcc 4.7 "-Winline" warnings
1009 #if defined(__GNUC__) && !defined(__clang__)
1010         __attribute__((noinline))
1011 #endif
1012         ~ResultBuilder() {
1013         }
1014 
1015         void setResult(const Result& res) { m_result = res; }
1016 
1017         template <int comparison, typename L, typename R>
1018         void          binary_assert(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) {
1019             m_result.m_passed        = RelationalComparator<comparison, L, R>()(lhs, rhs);
1020             m_result.m_decomposition = stringifyBinaryExpr(lhs, ", ", rhs);
1021         }
1022 
1023         template <typename L>
1024         void unary_assert(const DOCTEST_REF_WRAP(L) val) {
1025             m_result.m_passed        = !!val;
1026             m_result.m_decomposition = toString(val);
1027         }
1028 
1029         bool log();
1030         void react() const;
1031     };
1032 
1033     namespace assertAction
1034     {
1035         enum Enum
1036         {
1037             nothing     = 0,
1038             dbgbreak    = 1,
1039             shouldthrow = 2
1040         };
1041     } // namespace assertAction
1042 
1043     template <int comparison, typename L, typename R>
1044     int fast_binary_assert(assertType::Enum assert_type, const char* file, int line,
1045                            const char* lhs_str, const char* rhs_str, const DOCTEST_REF_WRAP(L) lhs,
1046                            const DOCTEST_REF_WRAP(R) rhs) {
1047         String        expr     = String(lhs_str) + ", " + rhs_str;
1048         const char*   expr_str = expr.c_str();
1049         ResultBuilder rb(assert_type, file, line, expr_str);
1050 
1051         rb.m_result.m_passed        = RelationalComparator<comparison, L, R>()(lhs, rhs);
1052         rb.m_result.m_decomposition = stringifyBinaryExpr(lhs, ", ", rhs);
1053 
1054         int res = 0;
1055 
1056         if(rb.log())
1057             res |= assertAction::dbgbreak;
1058 
1059         if(rb.m_failed && checkIfShouldThrow(assert_type))
1060             res |= assertAction::shouldthrow;
1061 
1062 #ifdef DOCTEST_CONFIG_SUPER_FAST_ASSERTS
1063         // #########################################################################################
1064         // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK TO SEE THE FAILING ASSERTION
1065         // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED
1066         // #########################################################################################
1067         if(res & assertAction::dbgbreak)
1068             DOCTEST_BREAK_INTO_DEBUGGER();
1069         fastAssertThrowIfFlagSet(res);
1070 #endif // DOCTEST_CONFIG_SUPER_FAST_ASSERTS
1071 
1072         return res;
1073     }
1074 
1075     template <typename L>
1076     int fast_unary_assert(assertType::Enum assert_type, const char* file, int line,
1077                           const char* val_str, const DOCTEST_REF_WRAP(L) val) {
1078         ResultBuilder rb(assert_type, file, line, val_str);
1079 
1080         rb.m_result.m_passed        = !!val;
1081         rb.m_result.m_decomposition = toString(val);
1082 
1083         int res = 0;
1084 
1085         if(rb.log())
1086             res |= assertAction::dbgbreak;
1087 
1088         if(rb.m_failed && checkIfShouldThrow(assert_type))
1089             res |= assertAction::shouldthrow;
1090 
1091 #ifdef DOCTEST_CONFIG_SUPER_FAST_ASSERTS
1092         // #########################################################################################
1093         // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK TO SEE THE FAILING ASSERTION
1094         // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED
1095         // #########################################################################################
1096         if(res & assertAction::dbgbreak)
1097             DOCTEST_BREAK_INTO_DEBUGGER();
1098         fastAssertThrowIfFlagSet(res);
1099 #endif // DOCTEST_CONFIG_SUPER_FAST_ASSERTS
1100 
1101         return res;
1102     }
1103 } // namespace detail
1104 
1105 #endif // DOCTEST_CONFIG_DISABLE
1106 
1107 class Context
1108 {
1109 #if !defined(DOCTEST_CONFIG_DISABLE)
1110     detail::ContextState* p;
1111 
1112     void parseArgs(int argc, const char* const* argv, bool withDefaults = false);
1113 
1114 #endif // DOCTEST_CONFIG_DISABLE
1115 
1116 public:
1117     Context(int argc = 0, const char* const* argv = 0);
1118 
1119 // to fix gcc 4.7 "-Winline" warnings
1120 #if defined(__GNUC__) && !defined(__clang__)
1121     __attribute__((noinline))
1122 #endif
1123     ~Context();
1124 
1125     void applyCommandLine(int argc, const char* const* argv);
1126 
1127     void addFilter(const char* filter, const char* value);
1128     void clearFilters();
1129     void setOption(const char* option, int value);
1130     void setOption(const char* option, const char* value);
1131 
1132     bool shouldExit();
1133 
1134     int run();
1135 };
1136 
1137 } // namespace doctest
1138 
1139 // if registering is not disabled
1140 #if !defined(DOCTEST_CONFIG_DISABLE)
1141 
1142 // registers the test by initializing a dummy var with a function
1143 #if defined(__GNUC__) && !defined(__clang__)
1144 #define DOCTEST_REGISTER_FUNCTION(f, name)                                                         \
1145     static int DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_) __attribute__((unused)) =                     \
1146             doctest::detail::regTest(f, __LINE__, __FILE__, name);
1147 #elif defined(__clang__)
1148 #define DOCTEST_REGISTER_FUNCTION(f, name)                                                         \
1149     _Pragma("clang diagnostic push")                                                               \
1150             _Pragma("clang diagnostic ignored \"-Wglobal-constructors\"") static int               \
1151                     DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_) =                                        \
1152                             doctest::detail::regTest(f, __LINE__, __FILE__, name);                 \
1153     _Pragma("clang diagnostic pop")
1154 #else // MSVC
1155 #define DOCTEST_REGISTER_FUNCTION(f, name)                                                         \
1156     static int DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_) =                                             \
1157             doctest::detail::regTest(f, __LINE__, __FILE__, name);
1158 #endif // MSVC
1159 
1160 #define DOCTEST_IMPLEMENT_FIXTURE(der, base, func, name)                                           \
1161     namespace                                                                                      \
1162     {                                                                                              \
1163         struct der : base                                                                          \
1164         { void f(); };                                                                             \
1165         static void func() {                                                                       \
1166             der v;                                                                                 \
1167             v.f();                                                                                 \
1168         }                                                                                          \
1169         DOCTEST_REGISTER_FUNCTION(func, name)                                                      \
1170     }                                                                                              \
1171     inline void der::f()
1172 
1173 #define DOCTEST_CREATE_AND_REGISTER_FUNCTION(f, name)                                              \
1174     static void f();                                                                               \
1175     DOCTEST_REGISTER_FUNCTION(f, name)                                                             \
1176     inline void f()
1177 
1178 // for registering tests
1179 #define DOCTEST_TEST_CASE(name)                                                                    \
1180     DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), name)
1181 
1182 // for registering tests with a fixture
1183 #define DOCTEST_TEST_CASE_FIXTURE(c, name)                                                         \
1184     DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(_DOCTEST_ANON_CLASS_), c,                          \
1185                               DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), name)
1186 
1187 // for subcases
1188 #if defined(__GNUC__)
1189 #define DOCTEST_SUBCASE(name)                                                                      \
1190     if(const doctest::detail::Subcase & DOCTEST_ANONYMOUS(_DOCTEST_ANON_SUBCASE_)                  \
1191                                                 __attribute__((unused)) =                          \
1192                doctest::detail::Subcase(name, __FILE__, __LINE__))
1193 #else // __GNUC__
1194 #define DOCTEST_SUBCASE(name)                                                                      \
1195     if(const doctest::detail::Subcase & DOCTEST_ANONYMOUS(_DOCTEST_ANON_SUBCASE_) =                \
1196                doctest::detail::Subcase(name, __FILE__, __LINE__))
1197 #endif // __GNUC__
1198 
1199 // for starting a testsuite block
1200 #if defined(__GNUC__) && !defined(__clang__)
1201 #define DOCTEST_TEST_SUITE(name)                                                                   \
1202     static int DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_) __attribute__((unused)) =                     \
1203             doctest::detail::setTestSuiteName(name);                                               \
1204     typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
1205 #elif defined(__clang__)
1206 #define DOCTEST_TEST_SUITE(name)                                                                   \
1207     _Pragma("clang diagnostic push")                                                               \
1208             _Pragma("clang diagnostic ignored \"-Wglobal-constructors\"") static int               \
1209                     DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_) =                                        \
1210                             doctest::detail::setTestSuiteName(name);                               \
1211     _Pragma("clang diagnostic pop") typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
1212 #else // MSVC
1213 #define DOCTEST_TEST_SUITE(name)                                                                   \
1214     static int  DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_) = doctest::detail::setTestSuiteName(name);   \
1215     typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
1216 #endif // MSVC
1217 
1218 // for ending a testsuite block
1219 #if defined(__GNUC__) && !defined(__clang__)
1220 #define DOCTEST_TEST_SUITE_END                                                                     \
1221     static int DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_) __attribute__((unused)) =                     \
1222             doctest::detail::setTestSuiteName("");                                                 \
1223     typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
1224 #elif defined(__clang__)
1225 #define DOCTEST_TEST_SUITE_END                                                                                                 \
1226     _Pragma("clang diagnostic push")                                                                                           \
1227             _Pragma("clang diagnostic ignored \"-Wglobal-constructors\"") static int                                           \
1228                                                 DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_) = doctest::detail::setTestSuiteName(""); \
1229     _Pragma("clang diagnostic pop") typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
1230 #else // MSVC
1231 #define DOCTEST_TEST_SUITE_END                                                                     \
1232     static int  DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_) = doctest::detail::setTestSuiteName("");     \
1233     typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
1234 #endif // MSVC
1235 
1236 #define DOCTEST_ASSERT_LOG_AND_REACT(rb)                                                           \
1237     if(rb.log())                                                                                   \
1238         DOCTEST_BREAK_INTO_DEBUGGER();                                                             \
1239     rb.react()
1240 
1241 #define DOCTEST_ASSERT_IMPLEMENT(expr, assert_type)                                                \
1242     doctest::detail::ResultBuilder _DOCTEST_RB(doctest::detail::assertType::assert_type, __FILE__, \
1243                                                __LINE__, #expr);                                   \
1244     try {                                                                                          \
1245         _DOCTEST_RB.setResult(doctest::detail::ExpressionDecomposer() << expr);                    \
1246     } catch(...) { _DOCTEST_RB.m_threw = true; }                                                   \
1247     DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB);
1248 
1249 #if defined(__clang__)
1250 #define DOCTEST_ASSERT_PROXY(expr, assert_type)                                                    \
1251     do {                                                                                           \
1252         _Pragma("clang diagnostic push")                                                           \
1253                 _Pragma("clang diagnostic ignored \"-Woverloaded-shift-op-parentheses\"")          \
1254                         DOCTEST_ASSERT_IMPLEMENT(expr, assert_type)                                \
1255                                 _Pragma("clang diagnostic pop")                                    \
1256     } while(doctest::detail::always_false())
1257 #else // __clang__
1258 #define DOCTEST_ASSERT_PROXY(expr, assert_type)                                                    \
1259     do {                                                                                           \
1260         DOCTEST_ASSERT_IMPLEMENT(expr, assert_type)                                                \
1261     } while(doctest::detail::always_false())
1262 #endif // __clang__
1263 
1264 #define DOCTEST_WARN(expr) DOCTEST_ASSERT_PROXY(expr, DT_WARN)
1265 #define DOCTEST_CHECK(expr) DOCTEST_ASSERT_PROXY(expr, DT_CHECK)
1266 #define DOCTEST_REQUIRE(expr) DOCTEST_ASSERT_PROXY(expr, DT_REQUIRE)
1267 
1268 #define DOCTEST_WARN_FALSE(expr) DOCTEST_ASSERT_PROXY(expr, DT_WARN_FALSE)
1269 #define DOCTEST_CHECK_FALSE(expr) DOCTEST_ASSERT_PROXY(expr, DT_CHECK_FALSE)
1270 #define DOCTEST_REQUIRE_FALSE(expr) DOCTEST_ASSERT_PROXY(expr, DT_REQUIRE_FALSE)
1271 
1272 #define DOCTEST_ASSERT_THROWS(expr, assert_type)                                                   \
1273     do {                                                                                           \
1274         if(!DOCTEST_GCS().no_throw) {                                                              \
1275             doctest::detail::ResultBuilder _DOCTEST_RB(doctest::detail::assertType::assert_type,   \
1276                                                        __FILE__, __LINE__, #expr);                 \
1277             try {                                                                                  \
1278                 expr;                                                                              \
1279             } catch(...) { _DOCTEST_RB.m_threw = true; }                                           \
1280             DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB);                                             \
1281         }                                                                                          \
1282     } while(doctest::detail::always_false())
1283 
1284 #define DOCTEST_ASSERT_THROWS_AS(expr, as, assert_type)                                            \
1285     do {                                                                                           \
1286         if(!DOCTEST_GCS().no_throw) {                                                              \
1287             doctest::detail::ResultBuilder _DOCTEST_RB(doctest::detail::assertType::assert_type,   \
1288                                                        __FILE__, __LINE__, #expr, #as);            \
1289             try {                                                                                  \
1290                 expr;                                                                              \
1291             } catch(as) {                                                                          \
1292                 _DOCTEST_RB.m_threw    = true;                                                     \
1293                 _DOCTEST_RB.m_threw_as = true;                                                     \
1294             } catch(...) { _DOCTEST_RB.m_threw = true; }                                           \
1295             DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB);                                             \
1296         }                                                                                          \
1297     } while(doctest::detail::always_false())
1298 
1299 #define DOCTEST_ASSERT_NOTHROW(expr, assert_type)                                                  \
1300     do {                                                                                           \
1301         if(!DOCTEST_GCS().no_throw) {                                                              \
1302             doctest::detail::ResultBuilder _DOCTEST_RB(doctest::detail::assertType::assert_type,   \
1303                                                        __FILE__, __LINE__, #expr);                 \
1304             try {                                                                                  \
1305                 expr;                                                                              \
1306             } catch(...) { _DOCTEST_RB.m_threw = true; }                                           \
1307             DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB);                                             \
1308         }                                                                                          \
1309     } while(doctest::detail::always_false())
1310 
1311 #define DOCTEST_WARN_THROWS(expr) DOCTEST_ASSERT_THROWS(expr, DT_WARN_THROWS)
1312 #define DOCTEST_CHECK_THROWS(expr) DOCTEST_ASSERT_THROWS(expr, DT_CHECK_THROWS)
1313 #define DOCTEST_REQUIRE_THROWS(expr) DOCTEST_ASSERT_THROWS(expr, DT_REQUIRE_THROWS)
1314 
1315 #define DOCTEST_WARN_THROWS_AS(expr, ex) DOCTEST_ASSERT_THROWS_AS(expr, ex, DT_WARN_THROWS_AS)
1316 #define DOCTEST_CHECK_THROWS_AS(expr, ex) DOCTEST_ASSERT_THROWS_AS(expr, ex, DT_CHECK_THROWS_AS)
1317 #define DOCTEST_REQUIRE_THROWS_AS(expr, ex) DOCTEST_ASSERT_THROWS_AS(expr, ex, DT_REQUIRE_THROWS_AS)
1318 
1319 #define DOCTEST_WARN_NOTHROW(expr) DOCTEST_ASSERT_NOTHROW(expr, DT_WARN_NOTHROW)
1320 #define DOCTEST_CHECK_NOTHROW(expr) DOCTEST_ASSERT_NOTHROW(expr, DT_CHECK_NOTHROW)
1321 #define DOCTEST_REQUIRE_NOTHROW(expr) DOCTEST_ASSERT_NOTHROW(expr, DT_REQUIRE_NOTHROW)
1322 
1323 #define DOCTEST_BINARY_ASSERT(assert_type, lhs, rhs, comp)                                         \
1324     do {                                                                                           \
1325         doctest::detail::ResultBuilder _DOCTEST_RB(doctest::detail::assertType::assert_type,       \
1326                                                    __FILE__, __LINE__, #lhs ", " #rhs);            \
1327         try {                                                                                      \
1328             _DOCTEST_RB.binary_assert<doctest::detail::binaryAssertComparison::comp>(lhs, rhs);    \
1329         } catch(...) { _DOCTEST_RB.m_threw = true; }                                               \
1330         DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB);                                                 \
1331     } while(doctest::detail::always_false())
1332 
1333 #define DOCTEST_UNARY_ASSERT(assert_type, val)                                                     \
1334     do {                                                                                           \
1335         doctest::detail::ResultBuilder _DOCTEST_RB(doctest::detail::assertType::assert_type,       \
1336                                                    __FILE__, __LINE__, #val);                      \
1337         try {                                                                                      \
1338             _DOCTEST_RB.unary_assert(val);                                                         \
1339         } catch(...) { _DOCTEST_RB.m_threw = true; }                                               \
1340         DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB);                                                 \
1341     } while(doctest::detail::always_false())
1342 
1343 #define DOCTEST_WARN_EQ(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_WARN_EQ, lhs, rhs, eq)
1344 #define DOCTEST_CHECK_EQ(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_CHECK_EQ, lhs, rhs, eq)
1345 #define DOCTEST_REQUIRE_EQ(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_REQUIRE_EQ, lhs, rhs, eq)
1346 #define DOCTEST_WARN_NE(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_WARN_NE, lhs, rhs, ne)
1347 #define DOCTEST_CHECK_NE(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_CHECK_NE, lhs, rhs, ne)
1348 #define DOCTEST_REQUIRE_NE(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_REQUIRE_NE, lhs, rhs, ne)
1349 #define DOCTEST_WARN_GT(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_WARN_GT, lhs, rhs, gt)
1350 #define DOCTEST_CHECK_GT(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_CHECK_GT, lhs, rhs, gt)
1351 #define DOCTEST_REQUIRE_GT(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_REQUIRE_GT, lhs, rhs, gt)
1352 #define DOCTEST_WARN_LT(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_WARN_LT, lhs, rhs, lt)
1353 #define DOCTEST_CHECK_LT(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_CHECK_LT, lhs, rhs, lt)
1354 #define DOCTEST_REQUIRE_LT(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_REQUIRE_LT, lhs, rhs, lt)
1355 #define DOCTEST_WARN_GE(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_WARN_GE, lhs, rhs, ge)
1356 #define DOCTEST_CHECK_GE(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_CHECK_GE, lhs, rhs, ge)
1357 #define DOCTEST_REQUIRE_GE(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_REQUIRE_GE, lhs, rhs, ge)
1358 #define DOCTEST_WARN_LE(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_WARN_LE, lhs, rhs, le)
1359 #define DOCTEST_CHECK_LE(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_CHECK_LE, lhs, rhs, le)
1360 #define DOCTEST_REQUIRE_LE(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_REQUIRE_LE, lhs, rhs, le)
1361 
1362 #define DOCTEST_WARN_UNARY(v) DOCTEST_UNARY_ASSERT(DT_WARN_UNARY, v)
1363 #define DOCTEST_CHECK_UNARY(v) DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY, v)
1364 #define DOCTEST_REQUIRE_UNARY(v) DOCTEST_UNARY_ASSERT(DT_REQUIRE_UNARY, v)
1365 #define DOCTEST_WARN_UNARY_FALSE(v) DOCTEST_UNARY_ASSERT(DT_WARN_UNARY_FALSE, v)
1366 #define DOCTEST_CHECK_UNARY_FALSE(v) DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY_FALSE, v)
1367 #define DOCTEST_REQUIRE_UNARY_FALSE(v) DOCTEST_UNARY_ASSERT(DT_REQUIRE_UNARY_FALSE, v)
1368 
1369 #ifndef DOCTEST_CONFIG_SUPER_FAST_ASSERTS
1370 
1371 #define DOCTEST_FAST_BINARY_ASSERT(assert_type, lhs, rhs, comparison)                              \
1372     do {                                                                                           \
1373         int _DOCTEST_FAST_RES = doctest::detail::fast_binary_assert<                               \
1374                 doctest::detail::binaryAssertComparison::comparison>(                              \
1375                 doctest::detail::assertType::assert_type, __FILE__, __LINE__, #lhs, #rhs, lhs,     \
1376                 rhs);                                                                              \
1377         if(_DOCTEST_FAST_RES & doctest::detail::assertAction::dbgbreak)                            \
1378             DOCTEST_BREAK_INTO_DEBUGGER();                                                         \
1379         doctest::detail::fastAssertThrowIfFlagSet(_DOCTEST_FAST_RES);                              \
1380     } while(doctest::detail::always_false())
1381 
1382 #define DOCTEST_FAST_UNARY_ASSERT(assert_type, val)                                                \
1383     do {                                                                                           \
1384         int _DOCTEST_FAST_RES = doctest::detail::fast_unary_assert(                                \
1385                 doctest::detail::assertType::assert_type, __FILE__, __LINE__, #val, val);          \
1386         if(_DOCTEST_FAST_RES & doctest::detail::assertAction::dbgbreak)                            \
1387             DOCTEST_BREAK_INTO_DEBUGGER();                                                         \
1388         doctest::detail::fastAssertThrowIfFlagSet(_DOCTEST_FAST_RES);                              \
1389     } while(doctest::detail::always_false())
1390 
1391 #else // DOCTEST_CONFIG_SUPER_FAST_ASSERTS
1392 
1393 #define DOCTEST_FAST_BINARY_ASSERT(assert_type, lhs, rhs, comparison)                              \
1394     doctest::detail::fast_binary_assert<doctest::detail::binaryAssertComparison::comparison>(      \
1395             doctest::detail::assertType::assert_type, __FILE__, __LINE__, #lhs, #rhs, lhs, rhs)
1396 
1397 #define DOCTEST_FAST_UNARY_ASSERT(assert_type, val)                                                \
1398     doctest::detail::fast_unary_assert(doctest::detail::assertType::assert_type, __FILE__,         \
1399                                        __LINE__, #val, val)
1400 
1401 #endif // DOCTEST_CONFIG_SUPER_FAST_ASSERTS
1402 
1403 #define DOCTEST_FAST_WARN_EQ(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_WARN_EQ, l, r, eq)
1404 #define DOCTEST_FAST_CHECK_EQ(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_CHECK_EQ, l, r, eq)
1405 #define DOCTEST_FAST_REQUIRE_EQ(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_REQUIRE_EQ, l, r, eq)
1406 #define DOCTEST_FAST_WARN_NE(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_WARN_NE, l, r, ne)
1407 #define DOCTEST_FAST_CHECK_NE(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_CHECK_NE, l, r, ne)
1408 #define DOCTEST_FAST_REQUIRE_NE(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_REQUIRE_NE, l, r, ne)
1409 #define DOCTEST_FAST_WARN_GT(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_WARN_GT, l, r, gt)
1410 #define DOCTEST_FAST_CHECK_GT(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_CHECK_GT, l, r, gt)
1411 #define DOCTEST_FAST_REQUIRE_GT(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_REQUIRE_GT, l, r, gt)
1412 #define DOCTEST_FAST_WARN_LT(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_WARN_LT, l, r, lt)
1413 #define DOCTEST_FAST_CHECK_LT(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_CHECK_LT, l, r, lt)
1414 #define DOCTEST_FAST_REQUIRE_LT(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_REQUIRE_LT, l, r, lt)
1415 #define DOCTEST_FAST_WARN_GE(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_WARN_GE, l, r, ge)
1416 #define DOCTEST_FAST_CHECK_GE(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_CHECK_GE, l, r, ge)
1417 #define DOCTEST_FAST_REQUIRE_GE(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_REQUIRE_GE, l, r, ge)
1418 #define DOCTEST_FAST_WARN_LE(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_WARN_LE, l, r, le)
1419 #define DOCTEST_FAST_CHECK_LE(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_CHECK_LE, l, r, le)
1420 #define DOCTEST_FAST_REQUIRE_LE(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_REQUIRE_LE, l, r, le)
1421 
1422 #define DOCTEST_FAST_WARN_UNARY(v) DOCTEST_FAST_UNARY_ASSERT(DT_FAST_WARN_UNARY, v)
1423 #define DOCTEST_FAST_CHECK_UNARY(v) DOCTEST_FAST_UNARY_ASSERT(DT_FAST_CHECK_UNARY, v)
1424 #define DOCTEST_FAST_REQUIRE_UNARY(v) DOCTEST_FAST_UNARY_ASSERT(DT_FAST_REQUIRE_UNARY, v)
1425 #define DOCTEST_FAST_WARN_UNARY_FALSE(v) DOCTEST_FAST_UNARY_ASSERT(DT_FAST_WARN_UNARY_FALSE, v)
1426 #define DOCTEST_FAST_CHECK_UNARY_FALSE(v) DOCTEST_FAST_UNARY_ASSERT(DT_FAST_CHECK_UNARY_FALSE, v)
1427 #define DOCTEST_FAST_REQUIRE_UNARY_FALSE(v)                                                        \
1428     DOCTEST_FAST_UNARY_ASSERT(DT_FAST_REQUIRE_UNARY_FALSE, v)
1429 
1430 // =================================================================================================
1431 // == WHAT FOLLOWS IS VERSIONS OF THE MACROS THAT DO NOT DO ANY REGISTERING!                      ==
1432 // == THIS CAN BE ENABLED BY DEFINING DOCTEST_CONFIG_DISABLE GLOBALLY!                            ==
1433 // =================================================================================================
1434 #else // DOCTEST_CONFIG_DISABLE
1435 
1436 #define DOCTEST_IMPLEMENT_FIXTURE(der, base, func, name)                                           \
1437     namespace                                                                                      \
1438     {                                                                                              \
1439         template <typename T>                                                                      \
1440         struct der : base                                                                          \
1441         { void f(); };                                                                             \
1442     }                                                                                              \
1443     template <typename T>                                                                          \
1444     inline void der<T>::f()
1445 
1446 #define DOCTEST_CREATE_AND_REGISTER_FUNCTION(f, name)                                              \
1447     template <typename T>                                                                          \
1448     static inline void f()
1449 
1450 // for registering tests
1451 #define DOCTEST_TEST_CASE(name)                                                                    \
1452     DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), name)
1453 
1454 // for registering tests with a fixture
1455 #define DOCTEST_TEST_CASE_FIXTURE(x, name)                                                         \
1456     DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(_DOCTEST_ANON_CLASS_), x,                          \
1457                               DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), name)
1458 
1459 // for subcases
1460 #define DOCTEST_SUBCASE(name)
1461 
1462 // for starting a testsuite block
1463 #define DOCTEST_TEST_SUITE(name) typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
1464 
1465 // for ending a testsuite block
1466 #define DOCTEST_TEST_SUITE_END typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
1467 
1468 #define DOCTEST_WARN(expr) ((void)0)
1469 #define DOCTEST_WARN_FALSE(expr) ((void)0)
1470 #define DOCTEST_WARN_THROWS(expr) ((void)0)
1471 #define DOCTEST_WARN_THROWS_AS(expr, ex) ((void)0)
1472 #define DOCTEST_WARN_NOTHROW(expr) ((void)0)
1473 #define DOCTEST_CHECK(expr) ((void)0)
1474 #define DOCTEST_CHECK_FALSE(expr) ((void)0)
1475 #define DOCTEST_CHECK_THROWS(expr) ((void)0)
1476 #define DOCTEST_CHECK_THROWS_AS(expr, ex) ((void)0)
1477 #define DOCTEST_CHECK_NOTHROW(expr) ((void)0)
1478 #define DOCTEST_REQUIRE(expr) ((void)0)
1479 #define DOCTEST_REQUIRE_FALSE(expr) ((void)0)
1480 #define DOCTEST_REQUIRE_THROWS(expr) ((void)0)
1481 #define DOCTEST_REQUIRE_THROWS_AS(expr, ex) ((void)0)
1482 #define DOCTEST_REQUIRE_NOTHROW(expr) ((void)0)
1483 
1484 #define DOCTEST_WARN_EQ(lhs, rhs) ((void)0)
1485 #define DOCTEST_CHECK_EQ(lhs, rhs) ((void)0)
1486 #define DOCTEST_REQUIRE_EQ(lhs, rhs) ((void)0)
1487 #define DOCTEST_WARN_NE(lhs, rhs) ((void)0)
1488 #define DOCTEST_CHECK_NE(lhs, rhs) ((void)0)
1489 #define DOCTEST_REQUIRE_NE(lhs, rhs) ((void)0)
1490 #define DOCTEST_WARN_GT(lhs, rhs) ((void)0)
1491 #define DOCTEST_CHECK_GT(lhs, rhs) ((void)0)
1492 #define DOCTEST_REQUIRE_GT(lhs, rhs) ((void)0)
1493 #define DOCTEST_WARN_LT(lhs, rhs) ((void)0)
1494 #define DOCTEST_CHECK_LT(lhs, rhs) ((void)0)
1495 #define DOCTEST_REQUIRE_LT(lhs, rhs) ((void)0)
1496 #define DOCTEST_WARN_GE(lhs, rhs) ((void)0)
1497 #define DOCTEST_CHECK_GE(lhs, rhs) ((void)0)
1498 #define DOCTEST_REQUIRE_GE(lhs, rhs) ((void)0)
1499 #define DOCTEST_WARN_LE(lhs, rhs) ((void)0)
1500 #define DOCTEST_CHECK_LE(lhs, rhs) ((void)0)
1501 #define DOCTEST_REQUIRE_LE(lhs, rhs) ((void)0)
1502 
1503 #define DOCTEST_WARN_UNARY(val) ((void)0)
1504 #define DOCTEST_CHECK_UNARY(val) ((void)0)
1505 #define DOCTEST_REQUIRE_UNARY(val) ((void)0)
1506 #define DOCTEST_WARN_UNARY_FALSE(val) ((void)0)
1507 #define DOCTEST_CHECK_UNARY_FALSE(val) ((void)0)
1508 #define DOCTEST_REQUIRE_UNARY_FALSE(val) ((void)0)
1509 
1510 #define DOCTEST_FAST_WARN_EQ(lhs, rhs) ((void)0)
1511 #define DOCTEST_FAST_CHECK_EQ(lhs, rhs) ((void)0)
1512 #define DOCTEST_FAST_REQUIRE_EQ(lhs, rhs) ((void)0)
1513 #define DOCTEST_FAST_WARN_NE(lhs, rhs) ((void)0)
1514 #define DOCTEST_FAST_CHECK_NE(lhs, rhs) ((void)0)
1515 #define DOCTEST_FAST_REQUIRE_NE(lhs, rhs) ((void)0)
1516 #define DOCTEST_FAST_WARN_GT(lhs, rhs) ((void)0)
1517 #define DOCTEST_FAST_CHECK_GT(lhs, rhs) ((void)0)
1518 #define DOCTEST_FAST_REQUIRE_GT(lhs, rhs) ((void)0)
1519 #define DOCTEST_FAST_WARN_LT(lhs, rhs) ((void)0)
1520 #define DOCTEST_FAST_CHECK_LT(lhs, rhs) ((void)0)
1521 #define DOCTEST_FAST_REQUIRE_LT(lhs, rhs) ((void)0)
1522 #define DOCTEST_FAST_WARN_GE(lhs, rhs) ((void)0)
1523 #define DOCTEST_FAST_CHECK_GE(lhs, rhs) ((void)0)
1524 #define DOCTEST_FAST_REQUIRE_GE(lhs, rhs) ((void)0)
1525 #define DOCTEST_FAST_WARN_LE(lhs, rhs) ((void)0)
1526 #define DOCTEST_FAST_CHECK_LE(lhs, rhs) ((void)0)
1527 #define DOCTEST_FAST_REQUIRE_LE(lhs, rhs) ((void)0)
1528 
1529 #define DOCTEST_FAST_WARN_UNARY(val) ((void)0)
1530 #define DOCTEST_FAST_CHECK_UNARY(val) ((void)0)
1531 #define DOCTEST_FAST_REQUIRE_UNARY(val) ((void)0)
1532 #define DOCTEST_FAST_WARN_UNARY_FALSE(val) ((void)0)
1533 #define DOCTEST_FAST_CHECK_UNARY_FALSE(val) ((void)0)
1534 #define DOCTEST_FAST_REQUIRE_UNARY_FALSE(val) ((void)0)
1535 
1536 #endif // DOCTEST_CONFIG_DISABLE
1537 
1538 // BDD style macros
1539 // clang-format off
1540 #define DOCTEST_SCENARIO(name)  TEST_CASE("  Scenario: " name)
1541 #define DOCTEST_GIVEN(name)     SUBCASE("   Given: " name)
1542 #define DOCTEST_WHEN(name)      SUBCASE("    When: " name)
1543 #define DOCTEST_AND_WHEN(name)  SUBCASE("And when: " name)
1544 #define DOCTEST_THEN(name)      SUBCASE("    Then: " name)
1545 #define DOCTEST_AND_THEN(name)  SUBCASE("     And: " name)
1546 // clang-format on
1547 
1548 // == SHORT VERSIONS OF THE MACROS
1549 #if !defined(DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES)
1550 
1551 #define TEST_CASE DOCTEST_TEST_CASE
1552 #define TEST_CASE_FIXTURE DOCTEST_TEST_CASE_FIXTURE
1553 #define SUBCASE DOCTEST_SUBCASE
1554 #define TEST_SUITE DOCTEST_TEST_SUITE
1555 #define TEST_SUITE_END DOCTEST_TEST_SUITE_END
1556 #define WARN DOCTEST_WARN
1557 #define WARN_FALSE DOCTEST_WARN_FALSE
1558 #define WARN_THROWS DOCTEST_WARN_THROWS
1559 #define WARN_THROWS_AS DOCTEST_WARN_THROWS_AS
1560 #define WARN_NOTHROW DOCTEST_WARN_NOTHROW
1561 #define CHECK DOCTEST_CHECK
1562 #define CHECK_FALSE DOCTEST_CHECK_FALSE
1563 #define CHECK_THROWS DOCTEST_CHECK_THROWS
1564 #define CHECK_THROWS_AS DOCTEST_CHECK_THROWS_AS
1565 #define CHECK_NOTHROW DOCTEST_CHECK_NOTHROW
1566 #define REQUIRE DOCTEST_REQUIRE
1567 #define REQUIRE_FALSE DOCTEST_REQUIRE_FALSE
1568 #define REQUIRE_THROWS DOCTEST_REQUIRE_THROWS
1569 #define REQUIRE_THROWS_AS DOCTEST_REQUIRE_THROWS_AS
1570 #define REQUIRE_NOTHROW DOCTEST_REQUIRE_NOTHROW
1571 
1572 #define SCENARIO DOCTEST_SCENARIO
1573 #define GIVEN DOCTEST_GIVEN
1574 #define WHEN DOCTEST_WHEN
1575 #define AND_WHEN DOCTEST_AND_WHEN
1576 #define THEN DOCTEST_THEN
1577 #define AND_THEN DOCTEST_AND_THEN
1578 
1579 #define WARN_EQ DOCTEST_WARN_EQ
1580 #define CHECK_EQ DOCTEST_CHECK_EQ
1581 #define REQUIRE_EQ DOCTEST_REQUIRE_EQ
1582 #define WARN_NE DOCTEST_WARN_NE
1583 #define CHECK_NE DOCTEST_CHECK_NE
1584 #define REQUIRE_NE DOCTEST_REQUIRE_NE
1585 #define WARN_GT DOCTEST_WARN_GT
1586 #define CHECK_GT DOCTEST_CHECK_GT
1587 #define REQUIRE_GT DOCTEST_REQUIRE_GT
1588 #define WARN_LT DOCTEST_WARN_LT
1589 #define CHECK_LT DOCTEST_CHECK_LT
1590 #define REQUIRE_LT DOCTEST_REQUIRE_LT
1591 #define WARN_GE DOCTEST_WARN_GE
1592 #define CHECK_GE DOCTEST_CHECK_GE
1593 #define REQUIRE_GE DOCTEST_REQUIRE_GE
1594 #define WARN_LE DOCTEST_WARN_LE
1595 #define CHECK_LE DOCTEST_CHECK_LE
1596 #define REQUIRE_LE DOCTEST_REQUIRE_LE
1597 #define WARN_UNARY DOCTEST_WARN_UNARY
1598 #define CHECK_UNARY DOCTEST_CHECK_UNARY
1599 #define REQUIRE_UNARY DOCTEST_REQUIRE_UNARY
1600 #define WARN_UNARY_FALSE DOCTEST_WARN_UNARY_FALSE
1601 #define CHECK_UNARY_FALSE DOCTEST_CHECK_UNARY_FALSE
1602 #define REQUIRE_UNARY_FALSE DOCTEST_REQUIRE_UNARY_FALSE
1603 
1604 #define FAST_WARN_EQ DOCTEST_FAST_WARN_EQ
1605 #define FAST_CHECK_EQ DOCTEST_FAST_CHECK_EQ
1606 #define FAST_REQUIRE_EQ DOCTEST_FAST_REQUIRE_EQ
1607 #define FAST_WARN_NE DOCTEST_FAST_WARN_NE
1608 #define FAST_CHECK_NE DOCTEST_FAST_CHECK_NE
1609 #define FAST_REQUIRE_NE DOCTEST_FAST_REQUIRE_NE
1610 #define FAST_WARN_GT DOCTEST_FAST_WARN_GT
1611 #define FAST_CHECK_GT DOCTEST_FAST_CHECK_GT
1612 #define FAST_REQUIRE_GT DOCTEST_FAST_REQUIRE_GT
1613 #define FAST_WARN_LT DOCTEST_FAST_WARN_LT
1614 #define FAST_CHECK_LT DOCTEST_FAST_CHECK_LT
1615 #define FAST_REQUIRE_LT DOCTEST_FAST_REQUIRE_LT
1616 #define FAST_WARN_GE DOCTEST_FAST_WARN_GE
1617 #define FAST_CHECK_GE DOCTEST_FAST_CHECK_GE
1618 #define FAST_REQUIRE_GE DOCTEST_FAST_REQUIRE_GE
1619 #define FAST_WARN_LE DOCTEST_FAST_WARN_LE
1620 #define FAST_CHECK_LE DOCTEST_FAST_CHECK_LE
1621 #define FAST_REQUIRE_LE DOCTEST_FAST_REQUIRE_LE
1622 #define FAST_WARN_UNARY DOCTEST_FAST_WARN_UNARY
1623 #define FAST_CHECK_UNARY DOCTEST_FAST_CHECK_UNARY
1624 #define FAST_REQUIRE_UNARY DOCTEST_FAST_REQUIRE_UNARY
1625 #define FAST_WARN_UNARY_FALSE DOCTEST_FAST_WARN_UNARY_FALSE
1626 #define FAST_CHECK_UNARY_FALSE DOCTEST_FAST_CHECK_UNARY_FALSE
1627 #define FAST_REQUIRE_UNARY_FALSE DOCTEST_FAST_REQUIRE_UNARY_FALSE
1628 
1629 #endif // DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES
1630 
1631 // this is here to clear the 'current test suite' for the current translation unit - at the top
1632 DOCTEST_TEST_SUITE_END();
1633 
1634 #endif // DOCTEST_LIBRARY_INCLUDED
1635 
1636 #if defined(__clang__)
1637 #pragma clang diagnostic pop
1638 #endif // __clang__
1639 
1640 #if defined(__GNUC__) && !defined(__clang__)
1641 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6)
1642 #pragma GCC diagnostic pop
1643 #endif // > gcc 4.6
1644 #endif // __GNUC__
1645 
1646 #ifdef _MSC_VER
1647 #pragma warning(pop)
1648 #endif // _MSC_VER
1649 
1650 #ifndef DOCTEST_SINGLE_HEADER
1651 #define DOCTEST_SINGLE_HEADER
1652 #endif // DOCTEST_SINGLE_HEADER
1653 
1654 #if defined(__clang__)
1655 #pragma clang diagnostic push
1656 #pragma clang diagnostic ignored "-Wunknown-pragmas"
1657 #pragma clang diagnostic ignored "-Wpadded"
1658 #pragma clang diagnostic ignored "-Wglobal-constructors"
1659 #pragma clang diagnostic ignored "-Wexit-time-destructors"
1660 #pragma clang diagnostic ignored "-Wmissing-prototypes"
1661 #pragma clang diagnostic ignored "-Wsign-conversion"
1662 #pragma clang diagnostic ignored "-Wshorten-64-to-32"
1663 #pragma clang diagnostic ignored "-Wmissing-variable-declarations"
1664 #pragma clang diagnostic ignored "-Wswitch"
1665 #pragma clang diagnostic ignored "-Wswitch-enum"
1666 #pragma clang diagnostic ignored "-Wcovered-switch-default"
1667 #pragma clang diagnostic ignored "-Wmissing-noreturn"
1668 #pragma clang diagnostic ignored "-Wunused-local-typedef"
1669 #endif // __clang__
1670 
1671 #if defined(__GNUC__) && !defined(__clang__)
1672 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6)
1673 #pragma GCC diagnostic push
1674 #endif // > gcc 4.6
1675 #pragma GCC diagnostic ignored "-Wunknown-pragmas"
1676 #pragma GCC diagnostic ignored "-Wconversion"
1677 #pragma GCC diagnostic ignored "-Weffc++"
1678 #pragma GCC diagnostic ignored "-Wsign-conversion"
1679 #pragma GCC diagnostic ignored "-Wstrict-overflow"
1680 #pragma GCC diagnostic ignored "-Wmissing-declarations"
1681 #pragma GCC diagnostic ignored "-Winline"
1682 #pragma GCC diagnostic ignored "-Wswitch"
1683 #pragma GCC diagnostic ignored "-Wswitch-enum"
1684 #pragma GCC diagnostic ignored "-Wswitch-default"
1685 #pragma GCC diagnostic ignored "-Wunsafe-loop-optimizations"
1686 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6)
1687 #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
1688 #endif // > gcc 4.6
1689 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 7)
1690 #pragma GCC diagnostic ignored "-Wunused-local-typedefs"
1691 #endif // > gcc 4.7
1692 #if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ > 3)
1693 #pragma GCC diagnostic ignored "-Wuseless-cast"
1694 #endif // > gcc 5.3
1695 #endif // __GNUC__
1696 
1697 #ifdef _MSC_VER
1698 #pragma warning(push)
1699 #pragma warning(disable : 4996) // The compiler encountered a deprecated declaration
1700 #pragma warning(disable : 4267) // 'var' : conversion from 'size_t' to 'type', possible loss of data
1701 #pragma warning(disable : 4706) // assignment within conditional expression
1702 #pragma warning(disable : 4512) // 'class' : assignment operator could not be generated
1703 #pragma warning(disable : 4127) // conditional expression is constant
1704 #endif                          // _MSC_VER
1705 
1706 #if defined(DOCTEST_CONFIG_IMPLEMENT) || defined(DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN) ||            \
1707         !defined(DOCTEST_SINGLE_HEADER)
1708 #ifndef DOCTEST_LIBRARY_IMPLEMENTATION
1709 #define DOCTEST_LIBRARY_IMPLEMENTATION
1710 
1711 #ifndef DOCTEST_SINGLE_HEADER
1712 #include "doctest_fwd.h"
1713 #endif // DOCTEST_SINGLE_HEADER
1714 
1715 #if defined(__clang__) && defined(DOCTEST_NO_CPP11_COMPAT)
1716 #pragma clang diagnostic ignored "-Wc++98-compat"
1717 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
1718 #endif // __clang__ && DOCTEST_NO_CPP11_COMPAT
1719 
1720 // snprintf() not in the C++98 standard
1721 #ifdef _MSC_VER
1722 #define DOCTEST_SNPRINTF _snprintf
1723 #else
1724 #define DOCTEST_SNPRINTF snprintf
1725 #endif
1726 
1727 #define DOCTEST_LOG_START()                                                                        \
1728     do {                                                                                           \
1729         if(!DOCTEST_GCS().hasLoggedCurrentTestStart) {                                             \
1730             doctest::detail::logTestStart(DOCTEST_GCS().currentTest->m_name,                       \
1731                                           DOCTEST_GCS().currentTest->m_file,                       \
1732                                           DOCTEST_GCS().currentTest->m_line);                      \
1733             DOCTEST_GCS().hasLoggedCurrentTestStart = true;                                        \
1734         }                                                                                          \
1735     } while(doctest::detail::always_false())
1736 
1737 // required includes - will go only in one translation unit!
1738 #include <ctime>
1739 #include <cmath>
1740 // borland (Embarcadero) compiler requires math.h and not cmath - https://github.com/onqtam/doctest/pull/37
1741 #ifdef __BORLANDC__
1742 #include <math.h>
1743 #endif // __BORLANDC__
1744 #include <new>
1745 #include <cstdio>
1746 #include <cstdlib>
1747 #include <cstring>
1748 #include <limits>
1749 #include <utility>
1750 #include <sstream>
1751 #include <iomanip>
1752 #include <vector>
1753 #include <set>
1754 
1755 namespace doctest
1756 {
1757 namespace detail
1758 {
1759     // not using std::strlen() because of valgrind errors when optimizations are turned on
1760     // 'Invalid read of size 4' when the test suite len (with '\0') is not a multiple of 4
1761     // for details see http://stackoverflow.com/questions/35671155
1762     size_t my_strlen(const char* in) {
1763         const char* temp = in;
1764         while(temp && *temp)
1765             ++temp;
1766         return temp - in;
1767     }
1768 
1769     template <typename T>
1770     T my_max(const T& lhs, const T& rhs) {
1771         return lhs > rhs ? lhs : rhs;
1772     }
1773 
1774     // case insensitive strcmp
1775     int stricmp(char const* a, char const* b) {
1776         for(;; a++, b++) {
1777             int d = tolower(*a) - tolower(*b);
1778             if(d != 0 || !*a)
1779                 return d;
1780         }
1781     }
1782 
1783     template <typename T>
1784     String fpToString(T value, int precision) {
1785         std::ostringstream oss;
1786         oss << std::setprecision(precision) << std::fixed << value;
1787         std::string d = oss.str();
1788         size_t      i = d.find_last_not_of('0');
1789         if(i != std::string::npos && i != d.size() - 1) {
1790             if(d[i] == '.')
1791                 i++;
1792             d = d.substr(0, i + 1);
1793         }
1794         return d.c_str();
1795     }
1796 
1797     struct Endianness
1798     {
1799         enum Arch
1800         {
1801             Big,
1802             Little
1803         };
1804 
1805         static Arch which() {
1806             union _
1807             {
1808                 int  asInt;
1809                 char asChar[sizeof(int)];
1810             } u;
1811 
1812             u.asInt = 1;
1813             return (u.asChar[sizeof(int) - 1] == 1) ? Big : Little;
1814         }
1815     };
1816 
1817     String rawMemoryToString(const void* object, unsigned size) {
1818         // Reverse order for little endian architectures
1819         int i = 0, end = static_cast<int>(size), inc = 1;
1820         if(Endianness::which() == Endianness::Little) {
1821             i   = end - 1;
1822             end = inc = -1;
1823         }
1824 
1825         unsigned char const* bytes = static_cast<unsigned char const*>(object);
1826         std::ostringstream   os;
1827         os << "0x" << std::setfill('0') << std::hex;
1828         for(; i != end; i += inc)
1829             os << std::setw(2) << static_cast<unsigned>(bytes[i]);
1830         return os.str().c_str();
1831     }
1832 
1833     std::ostream* createStream() { return new std::ostringstream(); }
1834     String getStreamResult(std::ostream* in) {
1835         return static_cast<std::ostringstream*>(in)->str().c_str();
1836     }
1837     void freeStream(std::ostream* in) { delete in; }
1838 
1839 #ifndef DOCTEST_CONFIG_DISABLE
1840 
1841     // this holds both parameters for the command line and runtime data for tests
1842     struct ContextState : TestAccessibleContextState
1843     {
1844         // == parameters from the command line
1845 
1846         std::vector<std::vector<String> > filters;
1847 
1848         String   order_by;  // how tests should be ordered
1849         unsigned rand_seed; // the seed for rand ordering
1850 
1851         unsigned first; // the first (matching) test to be executed
1852         unsigned last;  // the last (matching) test to be executed
1853 
1854         int  abort_after;    // stop tests after this many failed assertions
1855         bool case_sensitive; // if filtering should be case sensitive
1856         bool exit;           // if the program should be exited after the tests are ran/whatever
1857         bool no_exitcode;    // if the framework should return 0 as the exitcode
1858         bool no_run;         // to not run the tests at all (can be done with an "*" exclude)
1859         bool no_colors;      // if output to the console should be colorized
1860         bool no_path_in_filenames; // if the path to files should be removed from the output
1861 
1862         bool help;             // to print the help
1863         bool version;          // to print the version
1864         bool count;            // if only the count of matching tests is to be retreived
1865         bool list_test_cases;  // to list all tests matching the filters
1866         bool list_test_suites; // to list all suites matching the filters
1867 
1868         // == data for the tests being ran
1869 
1870         int numAssertions;
1871         int numFailedAssertions;
1872         int numFailedAssertionsForCurrentTestcase;
1873 
1874         // stuff for subcases
1875         std::set<SubcaseSignature> subcasesPassed;
1876         std::set<int>              subcasesEnteredLevels;
1877         std::vector<Subcase>       subcasesStack;
1878         int                        subcasesCurrentLevel;
1879         bool                       subcasesHasSkipped;
1880 
1881         void resetRunData() {
1882             numAssertions       = 0;
1883             numFailedAssertions = 0;
1884         }
1885 
1886         ContextState()
1887                 : filters(6) // 6 different filters total
1888         {
1889             resetRunData();
1890         }
1891     };
1892 
1893     ContextState*& getContextState();
1894 #endif // DOCTEST_CONFIG_DISABLE
1895 } // namespace detail
1896 
1897 String::String(const char* in)
1898         : m_str(static_cast<char*>(malloc(detail::my_strlen(in) + 1))) {
1899     if(in)
1900         strcpy(m_str, in);
1901     else
1902         m_str[0] = '\0';
1903 }
1904 
1905 String::String(const String& other)
1906         : m_str(0) {
1907     copy(other);
1908 }
1909 
1910 void String::copy(const String& other) {
1911     if(m_str)
1912         free(m_str);
1913     m_str = static_cast<char*>(malloc(detail::my_strlen(other.m_str) + 1));
1914     strcpy(m_str, other.m_str);
1915 }
1916 
1917 String::~String() { free(m_str); }
1918 
1919 String& String::operator=(const String& other) {
1920     if(this != &other)
1921         copy(other);
1922     return *this;
1923 }
1924 
1925 String String::operator+(const String& other) const { return String(m_str) += other; }
1926 
1927 String& String::operator+=(const String& other) {
1928     using namespace detail;
1929     if(other.m_str != 0) {
1930         char* newStr = static_cast<char*>(malloc(my_strlen(m_str) + my_strlen(other.m_str) + 1));
1931         strcpy(newStr, m_str);
1932         strcpy(newStr + my_strlen(m_str), other.m_str);
1933         free(m_str);
1934         m_str = newStr;
1935     }
1936     return *this;
1937 }
1938 
1939 unsigned String::size() const { return m_str ? detail::my_strlen(m_str) : 0; }
1940 unsigned String::length() const { return size(); }
1941 
1942 int String::compare(const char* other, bool no_case) const {
1943     if(no_case)
1944         return detail::stricmp(m_str, other);
1945     return strcmp(m_str, other);
1946 }
1947 
1948 int String::compare(const String& other, bool no_case) const {
1949     if(no_case)
1950         return detail::stricmp(m_str, other.m_str);
1951     return strcmp(m_str, other.m_str);
1952 }
1953 
1954 std::ostream& operator<<(std::ostream& stream, const String& in) {
1955     stream << in.c_str();
1956     return stream;
1957 }
1958 
1959 Approx::Approx(double value)
1960         : m_epsilon(static_cast<double>(std::numeric_limits<float>::epsilon()) * 100)
1961         , m_scale(1.0)
1962         , m_value(value) {}
1963 
1964 bool operator==(double lhs, Approx const& rhs) {
1965     // Thanks to Richard Harris for his help refining this formula
1966     return fabs(lhs - rhs.m_value) <
1967            rhs.m_epsilon * (rhs.m_scale + detail::my_max(fabs(lhs), fabs(rhs.m_value)));
1968 }
1969 
1970 String Approx::toString() const { return String("Approx( ") + doctest::toString(m_value) + " )"; }
1971 
1972 #ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
1973 String toString(char* in) { return toString(static_cast<const char*>(in)); }
1974 String toString(const char* in) { return String("\"") + (in ? in : "{null string}") + "\""; }
1975 #endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
1976 String toString(bool in) { return in ? "true" : "false"; }
1977 String toString(float in) { return detail::fpToString(in, 5) + "f"; }
1978 String toString(double in) { return detail::fpToString(in, 10); }
1979 String toString(double long in) { return detail::fpToString(in, 15); }
1980 
1981 String toString(char in) {
1982     char buf[64];
1983     sprintf(buf, "%d", in);
1984     return buf;
1985 }
1986 
1987 String toString(char unsigned in) {
1988     char buf[64];
1989     sprintf(buf, "%ud", in);
1990     return buf;
1991 }
1992 
1993 String toString(int short in) {
1994     char buf[64];
1995     sprintf(buf, "%d", in);
1996     return buf;
1997 }
1998 
1999 String toString(int short unsigned in) {
2000     char buf[64];
2001     sprintf(buf, "%u", in);
2002     return buf;
2003 }
2004 
2005 String toString(int in) {
2006     char buf[64];
2007     sprintf(buf, "%d", in);
2008     return buf;
2009 }
2010 
2011 String toString(int unsigned in) {
2012     char buf[64];
2013     sprintf(buf, "%u", in);
2014     return buf;
2015 }
2016 
2017 String toString(int long in) {
2018     char buf[64];
2019     sprintf(buf, "%ld", in);
2020     return buf;
2021 }
2022 
2023 String toString(int long unsigned in) {
2024     char buf[64];
2025     sprintf(buf, "%lu", in);
2026     return buf;
2027 }
2028 
2029 #ifdef DOCTEST_CONFIG_WITH_LONG_LONG
2030 String toString(int long long in) {
2031     char buf[64];
2032     sprintf(buf, "%lld", in);
2033     return buf;
2034 }
2035 String toString(int long long unsigned in) {
2036     char buf[64];
2037     sprintf(buf, "%llu", in);
2038     return buf;
2039 }
2040 #endif // DOCTEST_CONFIG_WITH_LONG_LONG
2041 
2042 #ifdef DOCTEST_CONFIG_WITH_NULLPTR
2043 String toString(std::nullptr_t) { return "nullptr"; }
2044 #endif // DOCTEST_CONFIG_WITH_NULLPTR
2045 
2046 } // namespace doctest
2047 
2048 #if defined(DOCTEST_CONFIG_DISABLE)
2049 namespace doctest
2050 {
2051 Context::Context(int, const char* const*) {}
2052 Context::~Context() {}
2053 void Context::applyCommandLine(int, const char* const*) {}
2054 void Context::addFilter(const char*, const char*) {}
2055 void Context::clearFilters() {}
2056 void Context::setOption(const char*, int) {}
2057 void Context::setOption(const char*, const char*) {}
2058 bool Context::shouldExit() { return false; }
2059 int  Context::run() { return 0; }
2060 } // namespace doctest
2061 #else // DOCTEST_CONFIG_DISABLE
2062 
2063 #if !defined(DOCTEST_CONFIG_COLORS_NONE)
2064 #if !defined(DOCTEST_CONFIG_COLORS_WINDOWS) && !defined(DOCTEST_CONFIG_COLORS_ANSI)
2065 #ifdef DOCTEST_PLATFORM_WINDOWS
2066 #define DOCTEST_CONFIG_COLORS_WINDOWS
2067 #else // linux
2068 #define DOCTEST_CONFIG_COLORS_ANSI
2069 #endif // platform
2070 #endif // DOCTEST_CONFIG_COLORS_WINDOWS && DOCTEST_CONFIG_COLORS_ANSI
2071 #endif // DOCTEST_CONFIG_COLORS_NONE
2072 
2073 #define DOCTEST_PRINTF_COLORED(buffer, color)                                                      \
2074     do {                                                                                           \
2075         if(buffer[0] != 0) {                                                                       \
2076             doctest::detail::Color col(color);                                                     \
2077             printf("%s", buffer);                                                                  \
2078         }                                                                                          \
2079     } while(doctest::detail::always_false())
2080 
2081 // the buffer size used for snprintf() calls
2082 #if !defined(DOCTEST_SNPRINTF_BUFFER_LENGTH)
2083 #define DOCTEST_SNPRINTF_BUFFER_LENGTH 1024
2084 #endif // DOCTEST_SNPRINTF_BUFFER_LENGTH
2085 
2086 #if defined(_MSC_VER) || defined(__MINGW32__)
2087 #if defined(_MSC_VER) && _MSC_VER >= 1700
2088 #define DOCTEST_WINDOWS_SAL_IN_OPT _In_opt_
2089 #else // _MSC_VER
2090 #define DOCTEST_WINDOWS_SAL_IN_OPT
2091 #endif // _MSC_VER
2092 extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA(
2093         DOCTEST_WINDOWS_SAL_IN_OPT const char*);
2094 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
2095 #endif // _MSC_VER || __MINGW32__
2096 
2097 #ifdef DOCTEST_CONFIG_COLORS_ANSI
2098 #include <unistd.h>
2099 #endif // DOCTEST_CONFIG_COLORS_ANSI
2100 
2101 #ifdef DOCTEST_CONFIG_COLORS_WINDOWS
2102 
2103 // defines for a leaner windows.h
2104 #ifndef WIN32_MEAN_AND_LEAN
2105 #define WIN32_MEAN_AND_LEAN
2106 #endif // WIN32_MEAN_AND_LEAN
2107 #ifndef VC_EXTRA_LEAN
2108 #define VC_EXTRA_LEAN
2109 #endif // VC_EXTRA_LEAN
2110 #ifndef NOMINMAX
2111 #define NOMINMAX
2112 #endif // NOMINMAX
2113 
2114 // not sure what AfxWin.h is for - here I do what Catch does
2115 #ifdef __AFXDLL
2116 #include <AfxWin.h>
2117 #else
2118 #include <windows.h>
2119 #endif
2120 
2121 #endif // DOCTEST_CONFIG_COLORS_WINDOWS
2122 
2123 namespace doctest
2124 {
2125 namespace detail
2126 {
2127     bool TestData::operator<(const TestData& other) const {
2128         if(m_line != other.m_line)
2129             return m_line < other.m_line;
2130         return strcmp(m_file, other.m_file) < 0;
2131     }
2132 
2133     const char* getAssertString(assertType::Enum val) {
2134         switch(val) {
2135             // clang-format off
2136             case assertType::DT_WARN                    : return "WARN";
2137             case assertType::DT_CHECK                   : return "CHECK";
2138             case assertType::DT_REQUIRE                 : return "REQUIRE";
2139 
2140             case assertType::DT_WARN_FALSE              : return "WARN_FALSE";
2141             case assertType::DT_CHECK_FALSE             : return "CHECK_FALSE";
2142             case assertType::DT_REQUIRE_FALSE           : return "REQUIRE_FALSE";
2143 
2144             case assertType::DT_WARN_THROWS             : return "WARN_THROWS";
2145             case assertType::DT_CHECK_THROWS            : return "CHECK_THROWS";
2146             case assertType::DT_REQUIRE_THROWS          : return "REQUIRE_THROWS";
2147 
2148             case assertType::DT_WARN_THROWS_AS          : return "WARN_THROWS_AS";
2149             case assertType::DT_CHECK_THROWS_AS         : return "CHECK_THROWS_AS";
2150             case assertType::DT_REQUIRE_THROWS_AS       : return "REQUIRE_THROWS_AS";
2151 
2152             case assertType::DT_WARN_NOTHROW            : return "WARN_NOTHROW";
2153             case assertType::DT_CHECK_NOTHROW           : return "CHECK_NOTHROW";
2154             case assertType::DT_REQUIRE_NOTHROW         : return "REQUIRE_NOTHROW";
2155 
2156             case assertType::DT_WARN_EQ                 : return "WARN_EQ";
2157             case assertType::DT_CHECK_EQ                : return "CHECK_EQ";
2158             case assertType::DT_REQUIRE_EQ              : return "REQUIRE_EQ";
2159             case assertType::DT_WARN_NE                 : return "WARN_NE";
2160             case assertType::DT_CHECK_NE                : return "CHECK_NE";
2161             case assertType::DT_REQUIRE_NE              : return "REQUIRE_NE";
2162             case assertType::DT_WARN_GT                 : return "WARN_GT";
2163             case assertType::DT_CHECK_GT                : return "CHECK_GT";
2164             case assertType::DT_REQUIRE_GT              : return "REQUIRE_GT";
2165             case assertType::DT_WARN_LT                 : return "WARN_LT";
2166             case assertType::DT_CHECK_LT                : return "CHECK_LT";
2167             case assertType::DT_REQUIRE_LT              : return "REQUIRE_LT";
2168             case assertType::DT_WARN_GE                 : return "WARN_GE";
2169             case assertType::DT_CHECK_GE                : return "CHECK_GE";
2170             case assertType::DT_REQUIRE_GE              : return "REQUIRE_GE";
2171             case assertType::DT_WARN_LE                 : return "WARN_LE";
2172             case assertType::DT_CHECK_LE                : return "CHECK_LE";
2173             case assertType::DT_REQUIRE_LE              : return "REQUIRE_LE";
2174 
2175             case assertType::DT_WARN_UNARY              : return "WARN_UNARY";
2176             case assertType::DT_CHECK_UNARY             : return "CHECK_UNARY";
2177             case assertType::DT_REQUIRE_UNARY           : return "REQUIRE_UNARY";
2178             case assertType::DT_WARN_UNARY_FALSE        : return "WARN_UNARY_FALSE";
2179             case assertType::DT_CHECK_UNARY_FALSE       : return "CHECK_UNARY_FALSE";
2180             case assertType::DT_REQUIRE_UNARY_FALSE     : return "REQUIRE_UNARY_FALSE";
2181 
2182             case assertType::DT_FAST_WARN_EQ            : return "FAST_WARN_EQ";
2183             case assertType::DT_FAST_CHECK_EQ           : return "FAST_CHECK_EQ";
2184             case assertType::DT_FAST_REQUIRE_EQ         : return "FAST_REQUIRE_EQ";
2185             case assertType::DT_FAST_WARN_NE            : return "FAST_WARN_NE";
2186             case assertType::DT_FAST_CHECK_NE           : return "FAST_CHECK_NE";
2187             case assertType::DT_FAST_REQUIRE_NE         : return "FAST_REQUIRE_NE";
2188             case assertType::DT_FAST_WARN_GT            : return "FAST_WARN_GT";
2189             case assertType::DT_FAST_CHECK_GT           : return "FAST_CHECK_GT";
2190             case assertType::DT_FAST_REQUIRE_GT         : return "FAST_REQUIRE_GT";
2191             case assertType::DT_FAST_WARN_LT            : return "FAST_WARN_LT";
2192             case assertType::DT_FAST_CHECK_LT           : return "FAST_CHECK_LT";
2193             case assertType::DT_FAST_REQUIRE_LT         : return "FAST_REQUIRE_LT";
2194             case assertType::DT_FAST_WARN_GE            : return "FAST_WARN_GE";
2195             case assertType::DT_FAST_CHECK_GE           : return "FAST_CHECK_GE";
2196             case assertType::DT_FAST_REQUIRE_GE         : return "FAST_REQUIRE_GE";
2197             case assertType::DT_FAST_WARN_LE            : return "FAST_WARN_LE";
2198             case assertType::DT_FAST_CHECK_LE           : return "FAST_CHECK_LE";
2199             case assertType::DT_FAST_REQUIRE_LE         : return "FAST_REQUIRE_LE";
2200 
2201             case assertType::DT_FAST_WARN_UNARY         : return "FAST_WARN_UNARY";
2202             case assertType::DT_FAST_CHECK_UNARY        : return "FAST_CHECK_UNARY";
2203             case assertType::DT_FAST_REQUIRE_UNARY      : return "FAST_REQUIRE_UNARY";
2204             case assertType::DT_FAST_WARN_UNARY_FALSE   : return "FAST_WARN_UNARY_FALSE";
2205             case assertType::DT_FAST_CHECK_UNARY_FALSE  : return "FAST_CHECK_UNARY_FALSE";
2206             case assertType::DT_FAST_REQUIRE_UNARY_FALSE: return "FAST_REQUIRE_UNARY_FALSE";
2207                 // clang-format on
2208         }
2209         return "";
2210     }
2211 
2212     bool checkIfShouldThrow(assertType::Enum assert_type) {
2213         if(assert_type & assertType::is_require)
2214             return true;
2215 
2216         if((assert_type & assertType::is_check) && getContextState()->abort_after > 0) {
2217             if(getContextState()->numFailedAssertions >= getContextState()->abort_after)
2218                 return true;
2219         }
2220 
2221         return false;
2222     }
2223     void fastAssertThrowIfFlagSet(int flags) {
2224         if(flags & assertAction::shouldthrow)
2225             throwException();
2226     }
2227     void throwException() { throw TestFailureException(); }
2228     bool always_false() { return false; }
2229 
2230     // lowers ascii letters
2231     char tolower(const char c) { return ((c >= 'A' && c <= 'Z') ? static_cast<char>(c + 32) : c); }
2232 
2233     // matching of a string against a wildcard mask (case sensitivity configurable) taken from
2234     // http://www.emoticode.net/c/simple-wildcard-string-compare-globbing-function.html
2235     int wildcmp(const char* str, const char* wild, bool caseSensitive) {
2236         const char* cp = 0;
2237         const char* mp = 0;
2238 
2239         // rolled my own tolower() to not include more headers
2240         while((*str) && (*wild != '*')) {
2241             if((caseSensitive ? (*wild != *str) : (tolower(*wild) != tolower(*str))) &&
2242                (*wild != '?')) {
2243                 return 0;
2244             }
2245             wild++;
2246             str++;
2247         }
2248 
2249         while(*str) {
2250             if(*wild == '*') {
2251                 if(!*++wild) {
2252                     return 1;
2253                 }
2254                 mp = wild;
2255                 cp = str + 1;
2256             } else if((caseSensitive ? (*wild == *str) : (tolower(*wild) == tolower(*str))) ||
2257                       (*wild == '?')) {
2258                 wild++;
2259                 str++;
2260             } else {
2261                 wild = mp;
2262                 str  = cp++;
2263             }
2264         }
2265 
2266         while(*wild == '*') {
2267             wild++;
2268         }
2269         return !*wild;
2270     }
2271 
2272     //// C string hash function (djb2) - taken from http://www.cse.yorku.ca/~oz/hash.html
2273     //unsigned hashStr(unsigned const char* str) {
2274     //    unsigned long hash = 5381;
2275     //    char          c;
2276     //    while((c = *str++))
2277     //        hash = ((hash << 5) + hash) + c; // hash * 33 + c
2278     //    return hash;
2279     //}
2280 
2281     // checks if the name matches any of the filters (and can be configured what to do when empty)
2282     int matchesAny(const char* name, std::vector<String> filters, int matchEmpty,
2283                    bool caseSensitive) {
2284         if(filters.size() == 0 && matchEmpty)
2285             return 1;
2286         for(unsigned i = 0; i < filters.size(); ++i)
2287             if(wildcmp(name, filters[i].c_str(), caseSensitive))
2288                 return 1;
2289         return 0;
2290     }
2291 
2292     // the current ContextState with which tests are being executed
2293     ContextState*& getContextState() {
2294         static ContextState* data = 0;
2295         return data;
2296     }
2297 
2298     TestAccessibleContextState* getTestsContextState() { return getContextState(); }
2299 
2300     bool SubcaseSignature::operator<(const SubcaseSignature& other) const {
2301         if(m_line != other.m_line)
2302             return m_line < other.m_line;
2303         if(strcmp(m_file, other.m_file) != 0)
2304             return strcmp(m_file, other.m_file) < 0;
2305         return strcmp(m_name, other.m_name) < 0;
2306     }
2307 
2308     Subcase::Subcase(const char* name, const char* file, int line)
2309             : m_signature(name, file, line)
2310             , m_entered(false) {
2311         ContextState* s = getContextState();
2312 
2313         // if we have already completed it
2314         if(s->subcasesPassed.count(m_signature) != 0)
2315             return;
2316 
2317         // if a Subcase on the same level has already been entered
2318         if(s->subcasesEnteredLevels.count(s->subcasesCurrentLevel) != 0) {
2319             s->subcasesHasSkipped = true;
2320             return;
2321         }
2322 
2323         s->subcasesStack.push_back(*this);
2324         if(s->hasLoggedCurrentTestStart)
2325             logTestEnd();
2326         s->hasLoggedCurrentTestStart = false;
2327 
2328         s->subcasesEnteredLevels.insert(s->subcasesCurrentLevel++);
2329         m_entered = true;
2330     }
2331 
2332     Subcase::Subcase(const Subcase& other)
2333             : m_signature(other.m_signature.m_name, other.m_signature.m_file,
2334                           other.m_signature.m_line)
2335             , m_entered(other.m_entered) {}
2336 
2337     Subcase::~Subcase() {
2338         if(m_entered) {
2339             ContextState* s = getContextState();
2340 
2341             s->subcasesCurrentLevel--;
2342             // only mark the subcase as passed if no subcases have been skipped
2343             if(s->subcasesHasSkipped == false)
2344                 s->subcasesPassed.insert(m_signature);
2345 
2346             if(s->subcasesStack.size() > 0)
2347                 s->subcasesStack.pop_back();
2348             if(s->hasLoggedCurrentTestStart)
2349                 logTestEnd();
2350             s->hasLoggedCurrentTestStart = false;
2351         }
2352     }
2353 
2354     // for sorting tests by file/line
2355     int fileOrderComparator(const void* a, const void* b) {
2356         const TestData* lhs = *static_cast<TestData* const*>(a);
2357         const TestData* rhs = *static_cast<TestData* const*>(b);
2358 #ifdef _MSC_VER
2359         // this is needed because MSVC gives different case for drive letters
2360         // for __FILE__ when evaluated in a header and a source file
2361         int res = stricmp(lhs->m_file, rhs->m_file);
2362 #else  // _MSC_VER
2363         int res = strcmp(lhs->m_file, rhs->m_file);
2364 #endif // _MSC_VER
2365         if(res != 0)
2366             return res;
2367         return static_cast<int>(lhs->m_line - rhs->m_line);
2368     }
2369 
2370     // for sorting tests by suite/file/line
2371     int suiteOrderComparator(const void* a, const void* b) {
2372         const TestData* lhs = *static_cast<TestData* const*>(a);
2373         const TestData* rhs = *static_cast<TestData* const*>(b);
2374 
2375         int res = strcmp(lhs->m_suite, rhs->m_suite);
2376         if(res != 0)
2377             return res;
2378         return fileOrderComparator(a, b);
2379     }
2380 
2381     // for sorting tests by name/suite/file/line
2382     int nameOrderComparator(const void* a, const void* b) {
2383         const TestData* lhs = *static_cast<TestData* const*>(a);
2384         const TestData* rhs = *static_cast<TestData* const*>(b);
2385 
2386         int res = strcmp(lhs->m_name, rhs->m_name);
2387         if(res != 0)
2388             return res;
2389         return suiteOrderComparator(a, b);
2390     }
2391 
2392     // holds the current test suite
2393     const char*& getCurrentTestSuite() {
2394         static const char* data = 0;
2395         return data;
2396     }
2397 
2398     // sets the current test suite
2399     int setTestSuiteName(const char* name) {
2400         getCurrentTestSuite() = name;
2401         return 0;
2402     }
2403 
2404     // all the registered tests
2405     std::set<TestData>& getRegisteredTests() {
2406         static std::set<TestData> data;
2407         return data;
2408     }
2409 
2410     // used by the macros for registering tests
2411     int regTest(funcType f, unsigned line, const char* file, const char* name) {
2412         getRegisteredTests().insert(TestData(getCurrentTestSuite(), name, f, file, line));
2413         return 0;
2414     }
2415 
2416     struct Color
2417     {
2418         enum Code
2419         {
2420             None = 0,
2421             White,
2422             Red,
2423             Green,
2424             Blue,
2425             Cyan,
2426             Yellow,
2427             Grey,
2428 
2429             Bright = 0x10,
2430 
2431             BrightRed   = Bright | Red,
2432             BrightGreen = Bright | Green,
2433             LightGrey   = Bright | Grey,
2434             BrightWhite = Bright | White
2435         };
2436         Color(Code code) { use(code); }
2437         ~Color() { use(None); }
2438 
2439         void use(Code code);
2440 
2441     private:
2442         Color(Color const& other);
2443     };
2444 
2445     void Color::use(Code
2446 #ifndef DOCTEST_CONFIG_COLORS_NONE
2447                             code
2448 #endif // DOCTEST_CONFIG_COLORS_NONE
2449                     ) {
2450         ContextState* p = getContextState();
2451         if(p->no_colors)
2452             return;
2453 #ifdef DOCTEST_CONFIG_COLORS_ANSI
2454         if(isatty(STDOUT_FILENO)) {
2455             const char* col = "";
2456             // clang-format off
2457             switch(code) {
2458                 case Color::Red:         col = "[0;31m"; break;
2459                 case Color::Green:       col = "[0;32m"; break;
2460                 case Color::Blue:        col = "[0;34m"; break;
2461                 case Color::Cyan:        col = "[0;36m"; break;
2462                 case Color::Yellow:      col = "[0;33m"; break;
2463                 case Color::Grey:        col = "[1;30m"; break;
2464                 case Color::LightGrey:   col = "[0;37m"; break;
2465                 case Color::BrightRed:   col = "[1;31m"; break;
2466                 case Color::BrightGreen: col = "[1;32m"; break;
2467                 case Color::BrightWhite: col = "[1;37m"; break;
2468                 case Color::Bright: // invalid
2469                 case Color::None:
2470                 case Color::White:
2471                 default:                 col = "[0m";
2472             }
2473             // clang-format on
2474             printf("\033%s", col);
2475         }
2476 #endif // DOCTEST_CONFIG_COLORS_ANSI
2477 
2478 #ifdef DOCTEST_CONFIG_COLORS_WINDOWS
2479         static HANDLE stdoutHandle(GetStdHandle(STD_OUTPUT_HANDLE));
2480         static WORD   originalForegroundAttributes;
2481         static WORD   originalBackgroundAttributes;
2482         static bool   attrsInitted = false;
2483         if(!attrsInitted) {
2484             attrsInitted = true;
2485             CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
2486             GetConsoleScreenBufferInfo(stdoutHandle, &csbiInfo);
2487             originalForegroundAttributes =
2488                     csbiInfo.wAttributes &
2489                     ~(BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY);
2490             originalBackgroundAttributes =
2491                     csbiInfo.wAttributes &
2492                     ~(FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
2493         }
2494 
2495 #define DOCTEST_SET_ATTR(x) SetConsoleTextAttribute(stdoutHandle, x | originalBackgroundAttributes)
2496 
2497         // clang-format off
2498         switch (code) {
2499             case Color::White:       DOCTEST_SET_ATTR(FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE); break;
2500             case Color::Red:         DOCTEST_SET_ATTR(FOREGROUND_RED);                                      break;
2501             case Color::Green:       DOCTEST_SET_ATTR(FOREGROUND_GREEN);                                    break;
2502             case Color::Blue:        DOCTEST_SET_ATTR(FOREGROUND_BLUE);                                     break;
2503             case Color::Cyan:        DOCTEST_SET_ATTR(FOREGROUND_BLUE | FOREGROUND_GREEN);                  break;
2504             case Color::Yellow:      DOCTEST_SET_ATTR(FOREGROUND_RED | FOREGROUND_GREEN);                   break;
2505             case Color::Grey:        DOCTEST_SET_ATTR(0);                                                   break;
2506             case Color::LightGrey:   DOCTEST_SET_ATTR(FOREGROUND_INTENSITY);                                break;
2507             case Color::BrightRed:   DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_RED);               break;
2508             case Color::BrightGreen: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_GREEN);             break;
2509             case Color::BrightWhite: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE); break;
2510             case Color::None:
2511             case Color::Bright: // invalid
2512             default:                 DOCTEST_SET_ATTR(originalForegroundAttributes);
2513         }
2514 // clang-format on
2515 #undef DOCTEST_SET_ATTR
2516 #endif // DOCTEST_CONFIG_COLORS_WINDOWS
2517     }
2518 
2519     // this is needed because MSVC does not permit mixing 2 exception handling schemes in a function
2520     int callTestFunc(funcType f) {
2521         int res = EXIT_SUCCESS;
2522         try {
2523             f();
2524             if(getContextState()->numFailedAssertionsForCurrentTestcase)
2525                 res = EXIT_FAILURE;
2526         } catch(const TestFailureException&) { res = EXIT_FAILURE; } catch(...) {
2527             DOCTEST_LOG_START();
2528             logTestCrashed();
2529             res = EXIT_FAILURE;
2530         }
2531         return res;
2532     }
2533 
2534     // depending on the current options this will remove the path of filenames
2535     const char* fileForOutput(const char* file) {
2536         if(getContextState()->no_path_in_filenames) {
2537             const char* back    = strrchr(file, '\\');
2538             const char* forward = strrchr(file, '/');
2539             if(back || forward) {
2540                 if(back > forward)
2541                     forward = back;
2542                 return forward + 1;
2543             }
2544         }
2545         return file;
2546     }
2547 
2548 #ifdef DOCTEST_PLATFORM_MAC
2549 #include <sys/types.h>
2550 #include <unistd.h>
2551 #include <sys/sysctl.h>
2552     // The following function is taken directly from the following technical note:
2553     // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
2554     // Returns true if the current process is being debugged (either
2555     // running under the debugger or has a debugger attached post facto).
2556     bool isDebuggerActive() {
2557         int               mib[4];
2558         struct kinfo_proc info;
2559         size_t            size;
2560         // Initialize the flags so that, if sysctl fails for some bizarre
2561         // reason, we get a predictable result.
2562         info.kp_proc.p_flag = 0;
2563         // Initialize mib, which tells sysctl the info we want, in this case
2564         // we're looking for information about a specific process ID.
2565         mib[0] = CTL_KERN;
2566         mib[1] = KERN_PROC;
2567         mib[2] = KERN_PROC_PID;
2568         mib[3] = getpid();
2569         // Call sysctl.
2570         size = sizeof(info);
2571         if(sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, 0, 0) != 0) {
2572             fprintf(stderr, "\n** Call to sysctl failed - unable to determine if debugger is "
2573                             "active **\n\n");
2574             return false;
2575         }
2576         // We're being debugged if the P_TRACED flag is set.
2577         return ((info.kp_proc.p_flag & P_TRACED) != 0);
2578     }
2579 #elif defined(_MSC_VER) || defined(__MINGW32__)
2580     bool    isDebuggerActive() { return ::IsDebuggerPresent() != 0; }
2581 #else
2582     bool isDebuggerActive() { return false; }
2583 #endif // Platform
2584 
2585 #ifdef DOCTEST_PLATFORM_WINDOWS
2586     void myOutputDebugString(const String& text) { ::OutputDebugStringA(text.c_str()); }
2587 #else
2588     // TODO: integration with XCode and other IDEs
2589     void myOutputDebugString(const String&) {}
2590 #endif // Platform
2591 
2592     const char* getSeparator() {
2593         return "===============================================================================\n";
2594     }
2595 
2596     void printToDebugConsole(const String& text) {
2597         if(isDebuggerActive())
2598             myOutputDebugString(text.c_str());
2599     }
2600 
2601     void addFailedAssert(assertType::Enum assert_type) {
2602         if((assert_type & assertType::is_warn) == 0) {
2603             getContextState()->numFailedAssertionsForCurrentTestcase++;
2604             getContextState()->numFailedAssertions++;
2605         }
2606     }
2607 
2608     void logTestStart(const char* name, const char* file, unsigned line) {
2609         const char* newLine = "\n";
2610 
2611         char loc[DOCTEST_SNPRINTF_BUFFER_LENGTH];
2612         DOCTEST_SNPRINTF(loc, DOCTEST_COUNTOF(loc), "%s(%d)\n", fileForOutput(file), line);
2613 
2614         char msg[DOCTEST_SNPRINTF_BUFFER_LENGTH];
2615         DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), "%s\n", name);
2616 
2617         DOCTEST_PRINTF_COLORED(getSeparator(), Color::Yellow);
2618         DOCTEST_PRINTF_COLORED(loc, Color::LightGrey);
2619         DOCTEST_PRINTF_COLORED(msg, Color::None);
2620 
2621         String                subcaseStuff  = "";
2622         std::vector<Subcase>& subcasesStack = getContextState()->subcasesStack;
2623         for(unsigned i = 0; i < subcasesStack.size(); ++i) {
2624             char subcase[DOCTEST_SNPRINTF_BUFFER_LENGTH];
2625             DOCTEST_SNPRINTF(subcase, DOCTEST_COUNTOF(loc), "  %s\n",
2626                              subcasesStack[i].m_signature.m_name);
2627             DOCTEST_PRINTF_COLORED(subcase, Color::None);
2628             subcaseStuff += subcase;
2629         }
2630 
2631         DOCTEST_PRINTF_COLORED(newLine, Color::None);
2632 
2633         printToDebugConsole(String(getSeparator()) + loc + msg + subcaseStuff.c_str() + newLine);
2634     }
2635 
2636     void logTestEnd() {}
2637 
2638     void logTestCrashed() {
2639         char msg[DOCTEST_SNPRINTF_BUFFER_LENGTH];
2640 
2641         DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), "TEST CASE FAILED! (threw exception)\n\n");
2642 
2643         DOCTEST_PRINTF_COLORED(msg, Color::Red);
2644 
2645         printToDebugConsole(String(msg));
2646     }
2647 
2648     void logAssert(bool passed, const char* decomposition, bool threw, const char* expr,
2649                    assertType::Enum assert_type, const char* file, int line) {
2650         char loc[DOCTEST_SNPRINTF_BUFFER_LENGTH];
2651         DOCTEST_SNPRINTF(loc, DOCTEST_COUNTOF(loc), "%s(%d)", fileForOutput(file), line);
2652 
2653         char msg[DOCTEST_SNPRINTF_BUFFER_LENGTH];
2654         if(passed)
2655             DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), " PASSED!\n");
2656         else
2657             DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), " FAILED! %s\n",
2658                              (threw ? "(threw exception)" : ""));
2659 
2660         char info1[DOCTEST_SNPRINTF_BUFFER_LENGTH];
2661         DOCTEST_SNPRINTF(info1, DOCTEST_COUNTOF(info1), "  %s( %s )\n",
2662                          getAssertString(assert_type), expr);
2663 
2664         char info2[DOCTEST_SNPRINTF_BUFFER_LENGTH];
2665         char info3[DOCTEST_SNPRINTF_BUFFER_LENGTH];
2666         info2[0] = 0;
2667         info3[0] = 0;
2668         if(!threw) {
2669             DOCTEST_SNPRINTF(info2, DOCTEST_COUNTOF(info2), "with expansion:\n");
2670             DOCTEST_SNPRINTF(info3, DOCTEST_COUNTOF(info3), "  %s( %s )\n",
2671                              getAssertString(assert_type), decomposition);
2672         }
2673 
2674         DOCTEST_PRINTF_COLORED(loc, Color::LightGrey);
2675         DOCTEST_PRINTF_COLORED(msg, passed ? Color::BrightGreen : Color::Red);
2676         DOCTEST_PRINTF_COLORED(info1, Color::Cyan);
2677         DOCTEST_PRINTF_COLORED(info2, Color::None);
2678         DOCTEST_PRINTF_COLORED(info3, Color::Cyan);
2679         DOCTEST_PRINTF_COLORED("\n", Color::None);
2680 
2681         printToDebugConsole(String(loc) + msg + info1 + info2 + info3 + "\n");
2682     }
2683 
2684     void logAssertThrows(bool threw, const char* expr, assertType::Enum assert_type,
2685                          const char* file, int line) {
2686         char loc[DOCTEST_SNPRINTF_BUFFER_LENGTH];
2687         DOCTEST_SNPRINTF(loc, DOCTEST_COUNTOF(loc), "%s(%d)", fileForOutput(file), line);
2688 
2689         char msg[DOCTEST_SNPRINTF_BUFFER_LENGTH];
2690         if(threw)
2691             DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), " PASSED!\n");
2692         else
2693             DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), " FAILED!\n");
2694 
2695         char info1[DOCTEST_SNPRINTF_BUFFER_LENGTH];
2696         DOCTEST_SNPRINTF(info1, DOCTEST_COUNTOF(info1), "  %s( %s )\n\n",
2697                          getAssertString(assert_type), expr);
2698 
2699         DOCTEST_PRINTF_COLORED(loc, Color::LightGrey);
2700         DOCTEST_PRINTF_COLORED(msg, threw ? Color::BrightGreen : Color::Red);
2701         DOCTEST_PRINTF_COLORED(info1, Color::Cyan);
2702 
2703         printToDebugConsole(String(loc) + msg + info1);
2704     }
2705 
2706     void logAssertThrowsAs(bool threw, bool threw_as, const char* as, const char* expr,
2707                            assertType::Enum assert_type, const char* file, int line) {
2708         char loc[DOCTEST_SNPRINTF_BUFFER_LENGTH];
2709         DOCTEST_SNPRINTF(loc, DOCTEST_COUNTOF(loc), "%s(%d)", fileForOutput(file), line);
2710 
2711         char msg[DOCTEST_SNPRINTF_BUFFER_LENGTH];
2712         if(threw_as)
2713             DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), " PASSED!\n");
2714         else
2715             DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), " FAILED! %s\n",
2716                              (threw ? "(threw something else)" : "(didn't throw at all)"));
2717 
2718         char info1[DOCTEST_SNPRINTF_BUFFER_LENGTH];
2719         DOCTEST_SNPRINTF(info1, DOCTEST_COUNTOF(info1), "  %s( %s, %s )\n\n",
2720                          getAssertString(assert_type), expr, as);
2721 
2722         DOCTEST_PRINTF_COLORED(loc, Color::LightGrey);
2723         DOCTEST_PRINTF_COLORED(msg, threw_as ? Color::BrightGreen : Color::Red);
2724         DOCTEST_PRINTF_COLORED(info1, Color::Cyan);
2725 
2726         printToDebugConsole(String(loc) + msg + info1);
2727     }
2728 
2729     void logAssertNothrow(bool threw, const char* expr, assertType::Enum assert_type,
2730                           const char* file, int line) {
2731         char loc[DOCTEST_SNPRINTF_BUFFER_LENGTH];
2732         DOCTEST_SNPRINTF(loc, DOCTEST_COUNTOF(loc), "%s(%d)", fileForOutput(file), line);
2733 
2734         char msg[DOCTEST_SNPRINTF_BUFFER_LENGTH];
2735         if(!threw)
2736             DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), " PASSED!\n");
2737         else
2738             DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), " FAILED!\n");
2739 
2740         char info1[DOCTEST_SNPRINTF_BUFFER_LENGTH];
2741         DOCTEST_SNPRINTF(info1, DOCTEST_COUNTOF(info1), "  %s( %s )\n\n",
2742                          getAssertString(assert_type), expr);
2743 
2744         DOCTEST_PRINTF_COLORED(loc, Color::LightGrey);
2745         DOCTEST_PRINTF_COLORED(msg, !threw ? Color::BrightGreen : Color::Red);
2746         DOCTEST_PRINTF_COLORED(info1, Color::Cyan);
2747 
2748         printToDebugConsole(String(loc) + msg + info1);
2749     }
2750 
2751     ResultBuilder::ResultBuilder(assertType::Enum assert_type, const char* file, int line,
2752                                  const char* expr, const char* exception_type)
2753             : m_assert_type(assert_type)
2754             , m_file(file)
2755             , m_line(line)
2756             , m_expr(expr)
2757             , m_exception_type(exception_type)
2758             , m_threw(false)
2759             , m_threw_as(false)
2760             , m_failed(false) {}
2761 
2762     bool ResultBuilder::log() {
2763         if((m_assert_type & assertType::is_warn) == 0)
2764             DOCTEST_GCS().numAssertionsForCurrentTestcase++;
2765 
2766         if(m_assert_type & assertType::is_false) {
2767             m_result.invert();
2768             m_failed = m_result;
2769         } else if(m_assert_type & assertType::is_throws) {
2770             m_failed = !m_threw;
2771         } else if(m_assert_type & assertType::is_throws_as) {
2772             m_failed = !m_threw_as;
2773         } else if(m_assert_type & assertType::is_nothrow) {
2774             m_failed = m_threw;
2775         } else {
2776             m_failed = m_result;
2777         }
2778 
2779         if(m_failed || DOCTEST_GCS().success) {
2780             DOCTEST_LOG_START();
2781 
2782             if(m_assert_type & assertType::is_throws) {
2783                 logAssertThrows(m_threw, m_expr, m_assert_type, m_file, m_line);
2784             } else if(m_assert_type & assertType::is_throws_as) {
2785                 logAssertThrowsAs(m_threw, m_threw_as, m_exception_type, m_expr, m_assert_type,
2786                                   m_file, m_line);
2787             } else if(m_assert_type & assertType::is_nothrow) {
2788                 logAssertNothrow(m_threw, m_expr, m_assert_type, m_file, m_line);
2789             } else {
2790                 logAssert(m_result.m_passed, m_result.m_decomposition.c_str(), m_threw, m_expr,
2791                           m_assert_type, m_file, m_line);
2792             }
2793         }
2794 
2795         if(m_failed) {
2796             addFailedAssert(m_assert_type);
2797             if(isDebuggerActive() && !DOCTEST_GCS().no_breaks)
2798                 return true; // should break into the debugger
2799         }
2800         return false;
2801     }
2802 
2803     void ResultBuilder::react() const {
2804         if(m_failed && checkIfShouldThrow(m_assert_type))
2805             throwException();
2806     }
2807 
2808     // the implementation of parseFlag()
2809     bool parseFlagImpl(int argc, const char* const* argv, const char* pattern) {
2810         for(int i = argc - 1; i >= 0; --i) {
2811             const char* temp = strstr(argv[i], pattern);
2812             if(temp && my_strlen(temp) == my_strlen(pattern)) {
2813                 // eliminate strings in which the chars before the option are not '-'
2814                 bool noBadCharsFound = true;
2815                 while(temp != argv[i]) {
2816                     if(*--temp != '-') {
2817                         noBadCharsFound = false;
2818                         break;
2819                     }
2820                 }
2821                 if(noBadCharsFound && argv[i][0] == '-')
2822                     return true;
2823             }
2824         }
2825         return false;
2826     }
2827 
2828     // locates a flag on the command line
2829     bool parseFlag(int argc, const char* const* argv, const char* pattern) {
2830 #ifndef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
2831         if(!parseFlagImpl(argc, argv, pattern))
2832             return parseFlagImpl(argc, argv, pattern + 3); // 3 for "dt-"
2833         return true;
2834 #else  // DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
2835         return parseFlagImpl(argc, argv, pattern);
2836 #endif // DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
2837     }
2838 
2839     // the implementation of parseOption()
2840     bool parseOptionImpl(int argc, const char* const* argv, const char* pattern, String& res) {
2841         for(int i = argc - 1; i >= 0; --i) {
2842             const char* temp = strstr(argv[i], pattern);
2843             if(temp) {
2844                 // eliminate matches in which the chars before the option are not '-'
2845                 bool        noBadCharsFound = true;
2846                 const char* curr            = argv[i];
2847                 while(curr != temp) {
2848                     if(*curr++ != '-') {
2849                         noBadCharsFound = false;
2850                         break;
2851                     }
2852                 }
2853                 if(noBadCharsFound && argv[i][0] == '-') {
2854                     temp += my_strlen(pattern);
2855                     unsigned len = my_strlen(temp);
2856                     if(len) {
2857                         res = temp;
2858                         return true;
2859                     }
2860                 }
2861             }
2862         }
2863         return false;
2864     }
2865 
2866     // parses an option and returns the string after the '=' character
2867     bool parseOption(int argc, const char* const* argv, const char* pattern, String& res,
2868                      const String& defaultVal = String()) {
2869         res = defaultVal;
2870 #ifndef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
2871         if(!parseOptionImpl(argc, argv, pattern, res))
2872             return parseOptionImpl(argc, argv, pattern + 3, res); // 3 for "dt-"
2873         return true;
2874 #else // DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
2875         return parseOptionImpl(argc, argv, pattern, res);
2876 #endif // DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
2877     }
2878 
2879     // parses a comma separated list of words after a pattern in one of the arguments in argv
2880     bool parseCommaSepArgs(int argc, const char* const* argv, const char* pattern,
2881                            std::vector<String>& res) {
2882         String filtersString;
2883         if(parseOption(argc, argv, pattern, filtersString)) {
2884             // tokenize with "," as a separator
2885             char* pch = strtok(filtersString.c_str(), ","); // modifies the string
2886             while(pch != 0) {
2887                 if(my_strlen(pch))
2888                     res.push_back(pch);
2889                 pch = strtok(0, ","); // uses the strtok() internal state to go to the next token
2890             }
2891             return true;
2892         }
2893         return false;
2894     }
2895 
2896     enum optionType
2897     {
2898         option_bool,
2899         option_int
2900     };
2901 
2902     // parses an int/bool option from the command line
2903     bool parseIntOption(int argc, const char* const* argv, const char* pattern, optionType type,
2904                         int& res) {
2905         String parsedValue;
2906         if(parseOption(argc, argv, pattern, parsedValue)) {
2907             if(type == 0) {
2908                 // boolean
2909                 const char positive[][5] = {"1", "true", "on", "yes"};  // 5 - strlen("true") + 1
2910                 const char negative[][6] = {"0", "false", "off", "no"}; // 6 - strlen("false") + 1
2911 
2912                 // if the value matches any of the positive/negative possibilities
2913                 for(unsigned i = 0; i < 4; i++) {
2914                     if(parsedValue.compare(positive[i], true) == 0) {
2915                         res = 1;
2916                         return true;
2917                     }
2918                     if(parsedValue.compare(negative[i], true) == 0) {
2919                         res = 0;
2920                         return true;
2921                     }
2922                 }
2923             } else {
2924                 // integer
2925                 int theInt = atoi(parsedValue.c_str());
2926                 if(theInt != 0) {
2927                     res = theInt;
2928                     return true;
2929                 }
2930             }
2931         }
2932         return false;
2933     }
2934 
2935     void printVersion() {
2936         DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
2937         printf("doctest version is \"%s\"\n", DOCTEST_VERSION_STR);
2938     }
2939 
2940     void printHelp() {
2941         printVersion();
2942         DOCTEST_PRINTF_COLORED("[doctest]\n", Color::Cyan);
2943         DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
2944         printf("boolean values: \"1/on/yes/true\" or \"0/off/no/false\"\n");
2945         DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
2946         printf("filter  values: \"str1,str2,str3\" (comma separated strings)\n");
2947         DOCTEST_PRINTF_COLORED("[doctest]\n", Color::Cyan);
2948         DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
2949         printf("filters use wildcards for matching strings\n");
2950         DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
2951         printf("something passes a filter if any of the strings in a filter matches\n");
2952         DOCTEST_PRINTF_COLORED("[doctest]\n", Color::Cyan);
2953         DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
2954         printf("ALL FLAGS, OPTIONS AND FILTERS ALSO AVAILABLE WITH A \"dt-\" PREFIX!!!\n");
2955         DOCTEST_PRINTF_COLORED("[doctest]\n", Color::Cyan);
2956         DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
2957         printf("Query flags - the program quits after them. Available:\n\n");
2958         printf(" -?,   --help, -h                      prints this message\n");
2959         printf(" -v,   --version                       prints the version\n");
2960         printf(" -c,   --count                         prints the number of matching tests\n");
2961         printf(" -ltc, --list-test-cases               lists all matching tests by name\n");
2962         printf(" -lts, --list-test-suites              lists all matching test suites\n\n");
2963         // ==================================================================================== << 79
2964         DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
2965         printf("The available <int>/<string> options/filters are:\n\n");
2966         printf(" -tc,  --test-case=<filters>           filters     tests by their name\n");
2967         printf(" -tce, --test-case-exclude=<filters>   filters OUT tests by their name\n");
2968         printf(" -sf,  --source-file=<filters>         filters     tests by their file\n");
2969         printf(" -sfe, --source-file-exclude=<filters> filters OUT tests by their file\n");
2970         printf(" -ts,  --test-suite=<filters>          filters     tests by their test suite\n");
2971         printf(" -tse, --test-suite-exclude=<filters>  filters OUT tests by their test suite\n");
2972         printf(" -ob,  --order-by=<string>             how the tests should be ordered\n");
2973         printf("                                       <string> - by [file/suite/name/rand]\n");
2974         printf(" -rs,  --rand-seed=<int>               seed for random ordering\n");
2975         printf(" -f,   --first=<int>                   the first test passing the filters to\n");
2976         printf("                                       execute - for range-based execution\n");
2977         printf(" -l,   --last=<int>                    the last test passing the filters to\n");
2978         printf("                                       execute - for range-based execution\n");
2979         printf(" -aa,  --abort-after=<int>             stop after <int> failed assertions\n\n");
2980         DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
2981         printf("Bool options - can be used like flags and true is assumed. Available:\n\n");
2982         printf(" -s,   --success=<bool>                include successful assertions in output\n");
2983         printf(" -cs,  --case-sensitive=<bool>         filters being treated as case sensitive\n");
2984         printf(" -e,   --exit=<bool>                   exits after the tests finish\n");
2985         printf(" -nt,  --no-throw=<bool>               skips exceptions-related assert checks\n");
2986         printf(" -ne,  --no-exitcode=<bool>            returns (or exits) always with success\n");
2987         printf(" -nr,  --no-run=<bool>                 skips all runtime doctest operations\n");
2988         printf(" -nc,  --no-colors=<bool>              disables colors in output\n");
2989         printf(" -nb,  --no-breaks=<bool>              disables breakpoints in debuggers\n");
2990         printf(" -npf, --no-path-filenames=<bool>      only filenames and no paths in output\n\n");
2991         // ==================================================================================== << 79
2992 
2993         DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
2994         printf("for more information visit the project documentation\n\n");
2995     }
2996 } // namespace detail
2997 
2998 Context::Context(int argc, const char* const* argv)
2999         : p(new detail::ContextState) {
3000     parseArgs(argc, argv, true);
3001 }
3002 
3003 Context::~Context() { delete p; }
3004 
3005 void Context::applyCommandLine(int argc, const char* const* argv) { parseArgs(argc, argv); }
3006 
3007 // parses args
3008 void Context::parseArgs(int argc, const char* const* argv, bool withDefaults) {
3009     using namespace detail;
3010 
3011     // clang-format off
3012     parseCommaSepArgs(argc, argv, "dt-source-file=",        p->filters[0]);
3013     parseCommaSepArgs(argc, argv, "dt-sf=",                 p->filters[0]);
3014     parseCommaSepArgs(argc, argv, "dt-source-file-exclude=",p->filters[1]);
3015     parseCommaSepArgs(argc, argv, "dt-sfe=",                p->filters[1]);
3016     parseCommaSepArgs(argc, argv, "dt-test-suite=",         p->filters[2]);
3017     parseCommaSepArgs(argc, argv, "dt-ts=",                 p->filters[2]);
3018     parseCommaSepArgs(argc, argv, "dt-test-suite-exclude=", p->filters[3]);
3019     parseCommaSepArgs(argc, argv, "dt-tse=",                p->filters[3]);
3020     parseCommaSepArgs(argc, argv, "dt-test-case=",          p->filters[4]);
3021     parseCommaSepArgs(argc, argv, "dt-tc=",                 p->filters[4]);
3022     parseCommaSepArgs(argc, argv, "dt-test-case-exclude=",  p->filters[5]);
3023     parseCommaSepArgs(argc, argv, "dt-tce=",                p->filters[5]);
3024     // clang-format on
3025 
3026     int    intRes = 0;
3027     String strRes;
3028 
3029 #define DOCTEST_PARSE_AS_BOOL_OR_FLAG(name, sname, var, default)                                   \
3030     if(parseIntOption(argc, argv, DOCTEST_STR_CONCAT_TOSTR(name, =), option_bool, intRes) ||       \
3031        parseIntOption(argc, argv, DOCTEST_STR_CONCAT_TOSTR(sname, =), option_bool, intRes))        \
3032         p->var = !!intRes;                                                                         \
3033     else if(parseFlag(argc, argv, #name) || parseFlag(argc, argv, #sname))                         \
3034         p->var = 1;                                                                                \
3035     else if(withDefaults)                                                                          \
3036     p->var = default
3037 
3038 #define DOCTEST_PARSE_INT_OPTION(name, sname, var, default)                                        \
3039     if(parseIntOption(argc, argv, DOCTEST_STR_CONCAT_TOSTR(name, =), option_int, intRes) ||        \
3040        parseIntOption(argc, argv, DOCTEST_STR_CONCAT_TOSTR(sname, =), option_int, intRes))         \
3041         p->var = intRes;                                                                           \
3042     else if(withDefaults)                                                                          \
3043     p->var = default
3044 
3045 #define DOCTEST_PARSE_STR_OPTION(name, sname, var, default)                                        \
3046     if(parseOption(argc, argv, DOCTEST_STR_CONCAT_TOSTR(name, =), strRes, default) ||              \
3047        parseOption(argc, argv, DOCTEST_STR_CONCAT_TOSTR(sname, =), strRes, default) ||             \
3048        withDefaults)                                                                               \
3049     p->var = strRes
3050 
3051     // clang-format off
3052     DOCTEST_PARSE_STR_OPTION(dt-order-by, dt-ob, order_by, "file");
3053     DOCTEST_PARSE_INT_OPTION(dt-rand-seed, dt-rs, rand_seed, 0);
3054 
3055     DOCTEST_PARSE_INT_OPTION(dt-first, dt-f, first, 1);
3056     DOCTEST_PARSE_INT_OPTION(dt-last, dt-l, last, 0);
3057 
3058     DOCTEST_PARSE_INT_OPTION(dt-abort-after, dt-aa, abort_after, 0);
3059 
3060     DOCTEST_PARSE_AS_BOOL_OR_FLAG(dt-success, dt-s, success, 0);
3061     DOCTEST_PARSE_AS_BOOL_OR_FLAG(dt-case-sensitive, dt-cs, case_sensitive, 0);
3062     DOCTEST_PARSE_AS_BOOL_OR_FLAG(dt-exit, dt-e, exit, 0);
3063     DOCTEST_PARSE_AS_BOOL_OR_FLAG(dt-no-throw, dt-nt, no_throw, 0);
3064     DOCTEST_PARSE_AS_BOOL_OR_FLAG(dt-no-exitcode, dt-ne, no_exitcode, 0);
3065     DOCTEST_PARSE_AS_BOOL_OR_FLAG(dt-no-run, dt-nr, no_run, 0);
3066     DOCTEST_PARSE_AS_BOOL_OR_FLAG(dt-no-colors, dt-nc, no_colors, 0);
3067     DOCTEST_PARSE_AS_BOOL_OR_FLAG(dt-no-breaks, dt-nb, no_breaks, 0);
3068     DOCTEST_PARSE_AS_BOOL_OR_FLAG(dt-no-path-filenames, dt-npf, no_path_in_filenames, 0);
3069 // clang-format on
3070 
3071 #undef DOCTEST_PARSE_STR_OPTION
3072 #undef DOCTEST_PARSE_INT_OPTION
3073 #undef DOCTEST_PARSE_AS_BOOL_OR_FLAG
3074 
3075     if(withDefaults) {
3076         p->help             = false;
3077         p->version          = false;
3078         p->count            = false;
3079         p->list_test_cases  = false;
3080         p->list_test_suites = false;
3081     }
3082     if(parseFlag(argc, argv, "dt-help") || parseFlag(argc, argv, "dt-h") ||
3083        parseFlag(argc, argv, "dt-?")) {
3084         p->help = true;
3085         p->exit = true;
3086     }
3087     if(parseFlag(argc, argv, "dt-version") || parseFlag(argc, argv, "dt-v")) {
3088         p->version = true;
3089         p->exit    = true;
3090     }
3091     if(parseFlag(argc, argv, "dt-count") || parseFlag(argc, argv, "dt-c")) {
3092         p->count = true;
3093         p->exit  = true;
3094     }
3095     if(parseFlag(argc, argv, "dt-list-test-cases") || parseFlag(argc, argv, "dt-ltc")) {
3096         p->list_test_cases = true;
3097         p->exit            = true;
3098     }
3099     if(parseFlag(argc, argv, "dt-list-test-suites") || parseFlag(argc, argv, "dt-lts")) {
3100         p->list_test_suites = true;
3101         p->exit             = true;
3102     }
3103 }
3104 
3105 // allows the user to add procedurally to the filters from the command line
3106 void Context::addFilter(const char* filter, const char* value) { setOption(filter, value); }
3107 
3108 // allows the user to clear all filters from the command line
3109 void Context::clearFilters() {
3110     for(unsigned i = 0; i < p->filters.size(); ++i)
3111         p->filters[i].clear();
3112 }
3113 
3114 // allows the user to override procedurally the int/bool options from the command line
3115 void Context::setOption(const char* option, int value) {
3116     setOption(option, toString(value).c_str());
3117 }
3118 
3119 // allows the user to override procedurally the string options from the command line
3120 void Context::setOption(const char* option, const char* value) {
3121     String      argv   = String("-") + option + "=" + value;
3122     const char* lvalue = argv.c_str();
3123     parseArgs(1, &lvalue);
3124 }
3125 
3126 // users should query this in their main() and exit the program if true
3127 bool Context::shouldExit() { return p->exit; }
3128 
3129 // the main function that does all the filtering and test running
3130 int Context::run() {
3131     using namespace detail;
3132 
3133     getContextState() = p;
3134     p->resetRunData();
3135 
3136     // handle version, help and no_run
3137     if(p->no_run || p->version || p->help) {
3138         if(p->version)
3139             printVersion();
3140         if(p->help)
3141             printHelp();
3142 
3143         getContextState() = 0;
3144 
3145         return EXIT_SUCCESS;
3146     }
3147 
3148     printVersion();
3149     DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
3150     printf("run with \"--help\" for options\n");
3151 
3152     unsigned i = 0; // counter used for loops - here for VC6
3153 
3154     std::set<TestData>& registeredTests = getRegisteredTests();
3155 
3156     std::vector<const TestData*> testArray;
3157     for(std::set<TestData>::iterator it = registeredTests.begin(); it != registeredTests.end();
3158         ++it)
3159         testArray.push_back(&(*it));
3160 
3161     // sort the collected records
3162     if(testArray.size() > 0) {
3163         if(p->order_by.compare("file", true) == 0) {
3164             qsort(&testArray[0], testArray.size(), sizeof(TestData*), fileOrderComparator);
3165         } else if(p->order_by.compare("suite", true) == 0) {
3166             qsort(&testArray[0], testArray.size(), sizeof(TestData*), suiteOrderComparator);
3167         } else if(p->order_by.compare("name", true) == 0) {
3168             qsort(&testArray[0], testArray.size(), sizeof(TestData*), nameOrderComparator);
3169         } else if(p->order_by.compare("rand", true) == 0) {
3170             srand(p->rand_seed);
3171 
3172             // random_shuffle implementation
3173             const TestData** first = &testArray[0];
3174             for(i = testArray.size() - 1; i > 0; --i) {
3175                 int idxToSwap = rand() % (i + 1);
3176 
3177                 const TestData* temp = first[i];
3178 
3179                 first[i]         = first[idxToSwap];
3180                 first[idxToSwap] = temp;
3181             }
3182         }
3183     }
3184 
3185     if(p->list_test_cases) {
3186         DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
3187         printf("listing all test case names\n");
3188     }
3189 
3190     std::set<String> testSuitesPassingFilters;
3191     if(p->list_test_suites) {
3192         DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
3193         printf("listing all test suites\n");
3194     }
3195 
3196     unsigned numTestsPassingFilters = 0;
3197     unsigned numFailed              = 0;
3198     // invoke the registered functions if they match the filter criteria (or just count them)
3199     for(i = 0; i < testArray.size(); i++) {
3200         const TestData& data = *testArray[i];
3201         if(!matchesAny(data.m_file, p->filters[0], 1, p->case_sensitive))
3202             continue;
3203         if(matchesAny(data.m_file, p->filters[1], 0, p->case_sensitive))
3204             continue;
3205         if(!matchesAny(data.m_suite, p->filters[2], 1, p->case_sensitive))
3206             continue;
3207         if(matchesAny(data.m_suite, p->filters[3], 0, p->case_sensitive))
3208             continue;
3209         if(!matchesAny(data.m_name, p->filters[4], 1, p->case_sensitive))
3210             continue;
3211         if(matchesAny(data.m_name, p->filters[5], 0, p->case_sensitive))
3212             continue;
3213 
3214         numTestsPassingFilters++;
3215 
3216         // do not execute the test if we are to only count the number of filter passing tests
3217         if(p->count)
3218             continue;
3219 
3220         // print the name of the test and don't execute it
3221         if(p->list_test_cases) {
3222             printf("%s\n", data.m_name);
3223             continue;
3224         }
3225 
3226         // print the name of the test suite if not done already and don't execute it
3227         if(p->list_test_suites) {
3228             if(testSuitesPassingFilters.count(data.m_suite) == 0) {
3229                 printf("%s\n", data.m_suite);
3230                 testSuitesPassingFilters.insert(data.m_suite);
3231             }
3232             continue;
3233         }
3234 
3235         // skip the test if it is not in the execution range
3236         if((p->last < numTestsPassingFilters && p->first <= p->last) ||
3237            (p->first > numTestsPassingFilters))
3238             continue;
3239 
3240         // execute the test if it passes all the filtering
3241         {
3242 #ifdef _MSC_VER
3243 //__try {
3244 #endif // _MSC_VER
3245 
3246             p->currentTest = &data;
3247 
3248             // if logging successful tests - force the start log
3249             p->hasLoggedCurrentTestStart = false;
3250             if(p->success)
3251                 DOCTEST_LOG_START();
3252 
3253             unsigned didFail = 0;
3254             p->subcasesPassed.clear();
3255             do {
3256                 // reset the assertion state
3257                 p->numAssertionsForCurrentTestcase       = 0;
3258                 p->numFailedAssertionsForCurrentTestcase = 0;
3259 
3260                 // reset some of the fields for subcases (except for the set of fully passed ones)
3261                 p->subcasesHasSkipped   = false;
3262                 p->subcasesCurrentLevel = 0;
3263                 p->subcasesEnteredLevels.clear();
3264 
3265                 // execute the test
3266                 didFail += callTestFunc(data.m_f);
3267                 p->numAssertions += p->numAssertionsForCurrentTestcase;
3268 
3269                 // exit this loop if enough assertions have failed
3270                 if(p->abort_after > 0 && p->numFailedAssertions >= p->abort_after)
3271                     p->subcasesHasSkipped = false;
3272 
3273                 // if the start has been logged
3274                 if(p->hasLoggedCurrentTestStart)
3275                     logTestEnd();
3276                 p->hasLoggedCurrentTestStart = false;
3277 
3278             } while(p->subcasesHasSkipped == true);
3279 
3280             if(didFail > 0)
3281                 numFailed++;
3282 
3283             // stop executing tests if enough assertions have failed
3284             if(p->abort_after > 0 && p->numFailedAssertions >= p->abort_after)
3285                 break;
3286 
3287 #ifdef _MSC_VER
3288 //} __except(1) {
3289 //    printf("Unknown SEH exception caught!\n");
3290 //    numFailed++;
3291 //}
3292 #endif // _MSC_VER
3293         }
3294     }
3295 
3296     DOCTEST_PRINTF_COLORED(getSeparator(), numFailed > 0 ? Color::Red : Color::Green);
3297     if(p->count || p->list_test_cases || p->list_test_suites) {
3298         DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
3299         printf("number of tests passing the current filters: %d\n", numTestsPassingFilters);
3300     } else {
3301         char buff[DOCTEST_SNPRINTF_BUFFER_LENGTH];
3302 
3303         DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
3304 
3305         DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), "test cases: %4d", numTestsPassingFilters);
3306         DOCTEST_PRINTF_COLORED(buff, Color::None);
3307         DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), " | ");
3308         DOCTEST_PRINTF_COLORED(buff, Color::None);
3309         DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), "%4d passed",
3310                          numTestsPassingFilters - numFailed);
3311         DOCTEST_PRINTF_COLORED(buff, numFailed > 0 ? Color::None : Color::Green);
3312         DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), " | ");
3313         DOCTEST_PRINTF_COLORED(buff, Color::None);
3314         DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), "%4d failed", numFailed);
3315         DOCTEST_PRINTF_COLORED(buff, numFailed > 0 ? Color::Red : Color::None);
3316 
3317         DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), " | ");
3318         DOCTEST_PRINTF_COLORED(buff, Color::None);
3319         DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), "%4d skipped\n",
3320                          static_cast<unsigned>(testArray.size()) - numTestsPassingFilters);
3321         DOCTEST_PRINTF_COLORED(buff, Color::None);
3322 
3323         DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
3324 
3325         DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), "assertions: %4d", p->numAssertions);
3326         DOCTEST_PRINTF_COLORED(buff, Color::None);
3327         DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), " | ");
3328         DOCTEST_PRINTF_COLORED(buff, Color::None);
3329         DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), "%4d passed",
3330                          p->numAssertions - p->numFailedAssertions);
3331         DOCTEST_PRINTF_COLORED(buff, numFailed > 0 ? Color::None : Color::Green);
3332         DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), " | ");
3333         DOCTEST_PRINTF_COLORED(buff, Color::None);
3334         DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), "%4d failed", p->numFailedAssertions);
3335         DOCTEST_PRINTF_COLORED(buff, p->numFailedAssertions > 0 ? Color::Red : Color::None);
3336 
3337         DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), " |\n");
3338         DOCTEST_PRINTF_COLORED(buff, Color::None);
3339     }
3340 
3341     // remove any coloring
3342     DOCTEST_PRINTF_COLORED("", Color::None);
3343 
3344     getContextState() = 0;
3345 
3346     if(numFailed && !p->no_exitcode)
3347         return EXIT_FAILURE;
3348     return EXIT_SUCCESS;
3349 }
3350 } // namespace doctest
3351 
3352 #endif // DOCTEST_CONFIG_DISABLE
3353 #endif // DOCTEST_LIBRARY_IMPLEMENTATION
3354 #endif // DOCTEST_CONFIG_IMPLEMENT
3355 
3356 // == THIS SUPPLIES A MAIN FUNCTION AND SHOULD BE DONE ONLY IN ONE TRANSLATION UNIT
3357 #if defined(DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN) && !defined(DOCTEST_MAIN_CONFIGURED)
3358 #define DOCTEST_MAIN_CONFIGURED
3359 int main(int argc, char** argv) { return doctest::Context(argc, argv).run(); }
3360 #endif // DOCTEST_MAIN_CONFIGURED
3361 
3362 #if defined(__clang__)
3363 #pragma clang diagnostic pop
3364 #endif // __clang__
3365 
3366 #if defined(__GNUC__) && !defined(__clang__)
3367 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6)
3368 #pragma GCC diagnostic pop
3369 #endif // > gcc 4.6
3370 #endif // __GNUC__
3371 
3372 #ifdef _MSC_VER
3373 #pragma warning(pop)
3374 #endif // _MSC_VER
3375