summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDidier Raboud <odyx@debian.org>2019-09-20 16:40:05 +0200
committerDidier Raboud <odyx@debian.org>2019-09-20 16:40:05 +0200
commit1bbb4b65471f3a31fdb3ccfe0af8c432d8e58534 (patch)
treeca524a7d30afa5fbbe7eee7c3e325b1e30c15f2a
parent0be6c56e62ea4d5f9e8827696c8a26f026f908cc (diff)
git-debrebase convert-from-dgit-view: drop upstream changes from breakwater
Drop upstream changes, and delete debian/patches, as part of converting to git-debrebase format. Upstream changes will appear as commits. [git-debrebase convert-from-dgit-view drop-patches]
-rw-r--r--debian/patches/0001-Make-sure-to-use-the-system-s-doctest.patch3491
-rw-r--r--debian/patches/0002-Make-the-build-reproducible.patch23
-rw-r--r--debian/patches/series2
-rw-r--r--doc/doxygen.cfg.in2
-rw-r--r--test/doctest.h3461
-rw-r--r--test/test.cpp2
6 files changed, 3463 insertions, 3518 deletions
diff --git a/debian/patches/0001-Make-sure-to-use-the-system-s-doctest.patch b/debian/patches/0001-Make-sure-to-use-the-system-s-doctest.patch
deleted file mode 100644
index 11e5951..0000000
--- a/debian/patches/0001-Make-sure-to-use-the-system-s-doctest.patch
+++ /dev/null
@@ -1,3491 +0,0 @@
-From 51b7a810a1670b6511dc062bd159ed86faf6f875 Mon Sep 17 00:00:00 2001
-From: Didier Raboud <odyx@debian.org>
-Date: Fri, 20 Oct 2017 10:25:24 +0200
-Subject: Make sure to use the system's doctest
-
----
- test/doctest.h | 3461 --------------------------------------------------------
- test/test.cpp | 2 +-
- 2 files changed, 1 insertion(+), 3462 deletions(-)
- delete mode 100644 test/doctest.h
-
-diff --git a/test/doctest.h b/test/doctest.h
-deleted file mode 100644
-index fe0a601..0000000
---- a/test/doctest.h
-+++ /dev/null
-@@ -1,3461 +0,0 @@
--// ======================================================================
--// == DO NOT MODIFY THIS FILE BY HAND - IT IS AUTO GENERATED BY CMAKE! ==
--// ======================================================================
--//
--// doctest.h - the lightest feature-rich C++ single-header testing framework for unit tests and TDD
--//
--// Copyright (c) 2016 Viktor Kirilov
--//
--// Distributed under the MIT Software License
--// See accompanying file LICENSE.txt or copy at
--// https://opensource.org/licenses/MIT
--//
--// The documentation can be found at the library's page:
--// https://github.com/onqtam/doctest/blob/master/doc/markdown/readme.md
--//
--// =================================================================================================
--// =================================================================================================
--// =================================================================================================
--//
--// The library is heavily influenced by Catch - https://github.com/philsquared/Catch
--// which uses the Boost Software License - Version 1.0
--// see here - https://github.com/philsquared/Catch/blob/master/LICENSE_1_0.txt
--//
--// The concept of subcases (sections in Catch) and expression decomposition are from there.
--// Some parts of the code are taken directly:
--// - stringification - the detection of "ostream& operator<<(ostream&, const T&)" and StringMaker<>
--// - the Approx() helper class for floating point comparison
--// - colors in the console
--// - breaking into a debugger
--//
--// The expression decomposing templates are taken from lest - https://github.com/martinmoene/lest
--// which uses the Boost Software License - Version 1.0
--// see here - https://github.com/martinmoene/lest/blob/master/LICENSE_1_0.txt
--//
--// =================================================================================================
--// =================================================================================================
--// =================================================================================================
--
--// Suppress this globally (without push/pop) - there is no way to silence it in the
--// expression decomposition macros _Pragma() in macros doesn't work for the c++ front-end of g++
--// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55578
--// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69543
--// Also the warning is completely worthless nowadays - http://stackoverflow.com/questions/14016993
--#if defined(__GNUC__) && !defined(__clang__)
--#pragma GCC diagnostic ignored "-Waggregate-return"
--#endif
--
--#if defined(__clang__)
--#pragma clang diagnostic push
--#pragma clang diagnostic ignored "-Wunknown-pragmas"
--#pragma clang diagnostic ignored "-Wpadded"
--#pragma clang diagnostic ignored "-Wmissing-prototypes"
--#pragma clang diagnostic ignored "-Wshorten-64-to-32"
--#pragma clang diagnostic ignored "-Wunused-local-typedef"
--#endif // __clang__
--
--#if defined(__GNUC__) && !defined(__clang__)
--#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6)
--#pragma GCC diagnostic push
--#endif // > gcc 4.6
--#pragma GCC diagnostic ignored "-Wunknown-pragmas"
--#pragma GCC diagnostic ignored "-Weffc++"
--#pragma GCC diagnostic ignored "-Wstrict-overflow"
--#pragma GCC diagnostic ignored "-Wmissing-declarations"
--#pragma GCC diagnostic ignored "-Winline"
--#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6)
--#pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
--#endif // > gcc 4.6
--#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 7)
--#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
--#endif // > gcc 4.7
--#if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ > 3)
--#pragma GCC diagnostic ignored "-Wuseless-cast"
--#endif // > gcc 5.3
--#endif // __GNUC__
--
--#ifdef _MSC_VER
--#pragma warning(push)
--#pragma warning(disable : 4996) // The compiler encountered a deprecated declaration
--#pragma warning(disable : 4706) // assignment within conditional expression
--#pragma warning(disable : 4512) // 'class' : assignment operator could not be generated
--#pragma warning(disable : 4127) // conditional expression is constant
--#endif // _MSC_VER
--
--#ifndef DOCTEST_LIBRARY_INCLUDED
--#define DOCTEST_LIBRARY_INCLUDED
--
--#define DOCTEST_VERSION_MAJOR 1
--#define DOCTEST_VERSION_MINOR 1
--#define DOCTEST_VERSION_PATCH 3
--#define DOCTEST_VERSION_STR "1.1.3"
--
--#define DOCTEST_VERSION \
-- (DOCTEST_VERSION_MAJOR * 10000 + DOCTEST_VERSION_MINOR * 100 + DOCTEST_VERSION_PATCH)
--
--// =================================================================================================
--// == MODERN C++ FEATURE DETECTION =================================================================
--// =================================================================================================
--
--#if __cplusplus >= 201103L
--#ifndef DOCTEST_CONFIG_WITH_NULLPTR
--#define DOCTEST_CONFIG_WITH_NULLPTR
--#endif // DOCTEST_CONFIG_WITH_NULLPTR
--#ifndef DOCTEST_CONFIG_WITH_LONG_LONG
--#define DOCTEST_CONFIG_WITH_LONG_LONG
--#endif // DOCTEST_CONFIG_WITH_LONG_LONG
--#ifndef DOCTEST_CONFIG_WITH_STATIC_ASSERT
--#define DOCTEST_CONFIG_WITH_STATIC_ASSERT
--#endif // DOCTEST_CONFIG_WITH_STATIC_ASSERT
--#endif // __cplusplus >= 201103L
--
--// nullptr
--
--#ifndef DOCTEST_CONFIG_WITH_NULLPTR
--#ifdef __clang__
--#if __has_feature(cxx_nullptr)
--#define DOCTEST_CONFIG_WITH_NULLPTR
--#endif // __has_feature(cxx_nullptr)
--#endif // __clang__
--
--#if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
--#define DOCTEST_CONFIG_WITH_NULLPTR
--#endif // __GNUC__
--
--#if defined(_MSC_VER) && (_MSC_VER >= 1600) // MSVC 2010
--#define DOCTEST_CONFIG_WITH_NULLPTR
--#endif // _MSC_VER
--#endif // DOCTEST_CONFIG_WITH_NULLPTR
--
--#if defined(DOCTEST_CONFIG_NO_NULLPTR) && defined(DOCTEST_CONFIG_WITH_NULLPTR)
--#undef DOCTEST_CONFIG_WITH_NULLPTR
--#endif // DOCTEST_CONFIG_NO_NULLPTR
--
--// long long
--
--#ifndef DOCTEST_CONFIG_WITH_LONG_LONG
--#if !defined(DOCTEST_CONFIG_WITH_LONG_LONG) && defined(_MSC_VER) && (_MSC_VER >= 1400)
--#define DOCTEST_CONFIG_WITH_LONG_LONG
--#endif // _MSC_VER
--#endif // DOCTEST_CONFIG_WITH_LONG_LONG
--
--#if defined(DOCTEST_CONFIG_NO_LONG_LONG) && defined(DOCTEST_CONFIG_WITH_LONG_LONG)
--#undef DOCTEST_CONFIG_WITH_LONG_LONG
--#endif // DOCTEST_CONFIG_NO_LONG_LONG
--
--// static_assert
--
--#ifndef DOCTEST_CONFIG_WITH_STATIC_ASSERT
--#ifdef __clang__
--#if __has_feature(cxx_static_assert)
--#define DOCTEST_CONFIG_WITH_STATIC_ASSERT
--#endif // __has_feature(cxx_static_assert)
--#endif // __clang__
--
--#if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ >= 3 && defined(__GXX_EXPERIMENTAL_CXX0X__)
--#define DOCTEST_CONFIG_WITH_STATIC_ASSERT
--#endif // __GNUC__
--
--#if defined(_MSC_VER) && (_MSC_VER >= 1600) // MSVC 2010
--#define DOCTEST_CONFIG_WITH_STATIC_ASSERT
--#endif // _MSC_VER
--#endif // DOCTEST_CONFIG_WITH_STATIC_ASSERT
--
--#if defined(DOCTEST_CONFIG_NO_STATIC_ASSERT) && defined(DOCTEST_CONFIG_WITH_STATIC_ASSERT)
--#undef DOCTEST_CONFIG_WITH_STATIC_ASSERT
--#endif // DOCTEST_CONFIG_NO_STATIC_ASSERT
--
--#if defined(DOCTEST_CONFIG_WITH_NULLPTR) || defined(DOCTEST_CONFIG_WITH_LONG_LONG) || \
-- defined(DOCTEST_CONFIG_WITH_STATIC_ASSERT)
--#define DOCTEST_NO_CPP11_COMPAT
--#endif // c++11 stuff
--
--#if defined(__clang__) && defined(DOCTEST_NO_CPP11_COMPAT)
--#pragma clang diagnostic ignored "-Wc++98-compat"
--#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
--#endif // __clang__ && DOCTEST_NO_CPP11_COMPAT
--
--#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
--#if defined(__GNUC__) && !defined(__EXCEPTIONS)
--#define DOCTEST_CONFIG_NO_EXCEPTIONS
--#endif // clang and gcc
--// in MSVC _HAS_EXCEPTIONS is defined in a header instead of as a project define
--// so we can't do the automatic detection for MSVC without including some header
--#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
--
--#if defined(DOCTEST_CONFIG_NO_EXCEPTIONS) && !defined(DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS)
--#define DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
--#endif // DOCTEST_CONFIG_NO_EXCEPTIONS && !DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
--
--// =================================================================================================
--// == MODERN C++ FEATURE DETECTION END =============================================================
--// =================================================================================================
--
--// internal macros for string concatenation and anonymous variable name generation
--#define DOCTEST_CAT_IMPL(s1, s2) s1##s2
--#define DOCTEST_CAT(s1, s2) DOCTEST_CAT_IMPL(s1, s2)
--#ifdef __COUNTER__ // not standard and may be missing for some compilers
--#define DOCTEST_ANONYMOUS(x) DOCTEST_CAT(x, __COUNTER__)
--#else // __COUNTER__
--#define DOCTEST_ANONYMOUS(x) DOCTEST_CAT(x, __LINE__)
--#endif // __COUNTER__
--
--// macro for making a string out of an identifier
--#define DOCTEST_TOSTR_IMPL(x) #x
--#define DOCTEST_TOSTR(x) DOCTEST_TOSTR_IMPL(x)
--
--// for concatenating literals and making the result a string
--#define DOCTEST_STR_CONCAT_TOSTR(s1, s2) DOCTEST_TOSTR(s1) DOCTEST_TOSTR(s2)
--
--// counts the number of elements in a C string
--#define DOCTEST_COUNTOF(x) (sizeof(x) / sizeof(x[0]))
--
--#ifndef DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE
--#define DOCTEST_REF_WRAP(x) x&
--#else // DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE
--#define DOCTEST_REF_WRAP(x) x
--#endif // DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE
--
--// not using __APPLE__ because... this is how Catch does it
--#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
--#define DOCTEST_PLATFORM_MAC
--#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
--#define DOCTEST_PLATFORM_IPHONE
--#elif defined(_WIN32) || defined(_MSC_VER)
--#define DOCTEST_PLATFORM_WINDOWS
--#else
--#define DOCTEST_PLATFORM_LINUX
--#endif
--
--#define DOCTEST_GCS() (*doctest::detail::getTestsContextState())
--
--// should probably take a look at https://github.com/scottt/debugbreak
--#ifdef DOCTEST_PLATFORM_MAC
--// The following code snippet based on:
--// http://cocoawithlove.com/2008/03/break-into-debugger.html
--#if defined(__ppc64__) || defined(__ppc__)
--#define DOCTEST_BREAK_INTO_DEBUGGER() \
-- __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" : : : "memory", "r0", "r3", "r4")
--#else // __ppc64__ || __ppc__
--#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :)
--#endif // __ppc64__ || __ppc__
--#elif defined(_MSC_VER)
--#define DOCTEST_BREAK_INTO_DEBUGGER() __debugbreak()
--#elif defined(__MINGW32__)
--extern "C" __declspec(dllimport) void __stdcall DebugBreak();
--#define DOCTEST_BREAK_INTO_DEBUGGER() ::DebugBreak()
--#else // linux
--#define DOCTEST_BREAK_INTO_DEBUGGER() ((void)0)
--#endif // linux
--
--#define DOCTEST_BREAK_INTO_DEBUGGER_CHECKED() \
-- if(doctest::detail::isDebuggerActive() && !DOCTEST_GCS().no_breaks) \
-- DOCTEST_BREAK_INTO_DEBUGGER();
--
--#ifdef __clang__
--// to detect if libc++ is being used with clang (the _LIBCPP_VERSION identifier)
--#include <ciso646>
--#endif // __clang__
--
--#ifdef _LIBCPP_VERSION
--// not forward declaring ostream for libc++ because I had some problems (inline namespaces vs c++98)
--// so the <iosfwd> header is used - also it is very light and doesn't drag a ton of stuff
--#include <iosfwd>
--#else // _LIBCPP_VERSION
--#ifndef DOCTEST_CONFIG_USE_IOSFWD
--namespace std
--{
--template <class charT>
--struct char_traits;
--template <>
--struct char_traits<char>;
--template <class charT, class traits>
--class basic_ostream;
--typedef basic_ostream<char, char_traits<char> > ostream;
--}
--#else // DOCTEST_CONFIG_USE_IOSFWD
--#include <iosfwd>
--#endif // DOCTEST_CONFIG_USE_IOSFWD
--#endif // _LIBCPP_VERSION
--
--// static assert macro - because of the c++98 support requires that the message is an
--// identifier (no spaces and not a C string) - example without quotes: I_am_a_message
--// taken from here: http://stackoverflow.com/a/1980156/3162383
--#ifdef DOCTEST_CONFIG_WITH_STATIC_ASSERT
--#define DOCTEST_STATIC_ASSERT(expression, message) static_assert(expression, #message)
--#else // DOCTEST_CONFIG_WITH_STATIC_ASSERT
--#define DOCTEST_STATIC_ASSERT(expression, message) \
-- struct DOCTEST_CAT(__static_assertion_at_line_, __LINE__) \
-- { \
-- doctest::detail::static_assert_impl::StaticAssertion<static_cast<bool>((expression))> \
-- DOCTEST_CAT(DOCTEST_CAT(DOCTEST_CAT(STATIC_ASSERTION_FAILED_AT_LINE_, __LINE__), \
-- _), \
-- message); \
-- }; \
-- typedef doctest::detail::static_assert_impl::StaticAssertionTest<sizeof( \
-- DOCTEST_CAT(__static_assertion_at_line_, __LINE__))> \
-- DOCTEST_CAT(__static_assertion_test_at_line_, __LINE__)
--#endif // DOCTEST_CONFIG_WITH_STATIC_ASSERT
--
--#ifdef DOCTEST_CONFIG_WITH_NULLPTR
--#ifdef _LIBCPP_VERSION
--#include <cstddef>
--#else // _LIBCPP_VERSION
--namespace std
--{ typedef decltype(nullptr) nullptr_t; }
--#endif // _LIBCPP_VERSION
--#endif // DOCTEST_CONFIG_WITH_NULLPTR
--
--namespace doctest
--{
--class String
--{
-- char* m_str;
--
-- void copy(const String& other);
--
--public:
-- String(const char* in = "");
-- String(const String& other);
-- ~String();
--
-- String& operator=(const String& other);
--
-- String operator+(const String& other) const;
-- String& operator+=(const String& other);
--
-- char& operator[](unsigned pos) { return m_str[pos]; }
-- const char& operator[](unsigned pos) const { return m_str[pos]; }
--
-- char* c_str() { return m_str; }
-- const char* c_str() const { return m_str; }
--
-- unsigned size() const;
-- unsigned length() const;
--
-- int compare(const char* other, bool no_case = false) const;
-- int compare(const String& other, bool no_case = false) const;
--};
--
--// clang-format off
--inline bool operator==(const String& lhs, const String& rhs) { return lhs.compare(rhs) == 0; }
--inline bool operator!=(const String& lhs, const String& rhs) { return lhs.compare(rhs) != 0; }
--inline bool operator< (const String& lhs, const String& rhs) { return lhs.compare(rhs) < 0; }
--inline bool operator> (const String& lhs, const String& rhs) { return lhs.compare(rhs) > 0; }
--inline bool operator<=(const String& lhs, const String& rhs) { return (lhs != rhs) ? lhs.compare(rhs) < 0 : true; }
--inline bool operator>=(const String& lhs, const String& rhs) { return (lhs != rhs) ? lhs.compare(rhs) > 0 : true; }
--// clang-format on
--
--std::ostream& operator<<(std::ostream& stream, const String& in);
--
--namespace detail
--{
--#ifndef DOCTEST_CONFIG_WITH_STATIC_ASSERT
-- namespace static_assert_impl
-- {
-- template <bool>
-- struct StaticAssertion;
--
-- template <>
-- struct StaticAssertion<true>
-- {};
--
-- template <int i>
-- struct StaticAssertionTest
-- {};
-- } // namespace static_assert_impl
--#endif // DOCTEST_CONFIG_WITH_STATIC_ASSERT
--
-- template <typename T>
-- struct deferred_false
-- { static const bool value = false; };
--
-- namespace has_insertion_operator_impl
-- {
-- typedef char no;
-- typedef char yes[2];
--
-- struct any_t
-- {
-- template <typename T>
-- any_t(const DOCTEST_REF_WRAP(T));
-- };
--
-- yes& testStreamable(std::ostream&);
-- no testStreamable(no);
--
-- no operator<<(const std::ostream&, const any_t&);
--
-- template <typename T>
-- struct has_insertion_operator
-- {
-- static std::ostream& s;
-- static const DOCTEST_REF_WRAP(T) t;
-- static const bool value = sizeof(testStreamable(s << t)) == sizeof(yes);
-- };
-- } // namespace has_insertion_operator_impl
--
-- template <typename T>
-- struct has_insertion_operator : has_insertion_operator_impl::has_insertion_operator<T>
-- {};
--
-- std::ostream* createStream();
-- String getStreamResult(std::ostream*);
-- void freeStream(std::ostream*);
--
-- template <bool C>
-- struct StringMakerBase
-- {
-- template <typename T>
-- static String convert(const DOCTEST_REF_WRAP(T)) {
-- return "{?}";
-- }
-- };
--
-- template <>
-- struct StringMakerBase<true>
-- {
-- template <typename T>
-- static String convert(const DOCTEST_REF_WRAP(T) in) {
-- std::ostream* stream = createStream();
-- *stream << in;
-- String result = getStreamResult(stream);
-- freeStream(stream);
-- return result;
-- }
-- };
--
-- String rawMemoryToString(const void* object, unsigned size);
--
-- template <typename T>
-- String rawMemoryToString(const DOCTEST_REF_WRAP(T) object) {
-- return rawMemoryToString(&object, sizeof(object));
-- }
--} // namespace detail
--
--template <typename T>
--struct StringMaker : detail::StringMakerBase<detail::has_insertion_operator<T>::value>
--{};
--
--template <typename T>
--struct StringMaker<T*>
--{
-- template <typename U>
-- static String convert(U* p) {
-- if(!p)
-- return "NULL";
-- else
-- return detail::rawMemoryToString(p);
-- }
--};
--
--template <typename R, typename C>
--struct StringMaker<R C::*>
--{
-- static String convert(R C::*p) {
-- if(!p)
-- return "NULL";
-- else
-- return detail::rawMemoryToString(p);
-- }
--};
--
--template <typename T>
--String toString(const DOCTEST_REF_WRAP(T) value) {
-- return StringMaker<T>::convert(value);
--}
--
--#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
--String toString(char* in);
--String toString(const char* in);
--#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
--String toString(bool in);
--String toString(float in);
--String toString(double in);
--String toString(double long in);
--
--String toString(char in);
--String toString(char unsigned in);
--String toString(int short in);
--String toString(int short unsigned in);
--String toString(int in);
--String toString(int unsigned in);
--String toString(int long in);
--String toString(int long unsigned in);
--
--#ifdef DOCTEST_CONFIG_WITH_LONG_LONG
--String toString(int long long in);
--String toString(int long long unsigned in);
--#endif // DOCTEST_CONFIG_WITH_LONG_LONG
--
--#ifdef DOCTEST_CONFIG_WITH_NULLPTR
--String toString(std::nullptr_t in);
--#endif // DOCTEST_CONFIG_WITH_NULLPTR
--
--class Approx
--{
--public:
-- explicit Approx(double value);
--
-- Approx(Approx const& other)
-- : m_epsilon(other.m_epsilon)
-- , m_scale(other.m_scale)
-- , m_value(other.m_value) {}
--
-- Approx operator()(double value) {
-- Approx approx(value);
-- approx.epsilon(m_epsilon);
-- approx.scale(m_scale);
-- return approx;
-- }
--
-- friend bool operator==(double lhs, Approx const& rhs);
-- friend bool operator==(Approx const& lhs, double rhs) { return operator==(rhs, lhs); }
-- friend bool operator!=(double lhs, Approx const& rhs) { return !operator==(lhs, rhs); }
-- friend bool operator!=(Approx const& lhs, double rhs) { return !operator==(rhs, lhs); }
--
-- Approx& epsilon(double newEpsilon) {
-- m_epsilon = newEpsilon;
-- return *this;
-- }
--
-- Approx& scale(double newScale) {
-- m_scale = newScale;
-- return *this;
-- }
--
-- String toString() const;
--
--private:
-- double m_epsilon;
-- double m_scale;
-- double m_value;
--};
--
--template <>
--inline String toString<Approx>(const DOCTEST_REF_WRAP(Approx) value) {
-- return value.toString();
--}
--
--#if !defined(DOCTEST_CONFIG_DISABLE)
--
--namespace detail
--{
-- // the function type this library works with
-- typedef void (*funcType)(void);
--
-- namespace assertType
-- {
-- enum Enum
-- {
-- // macro traits
--
-- is_warn = 1,
-- is_check = 2,
-- is_require = 4,
--
-- is_throws = 8,
-- is_throws_as = 16,
-- is_nothrow = 32,
--
-- is_fast = 64, // not checked anywhere - used just to distinguish the types
-- is_false = 128,
-- is_unary = 256,
--
-- is_eq = 512,
-- is_ne = 1024,
--
-- is_lt = 2048,
-- is_gt = 4096,
--
-- is_ge = 8192,
-- is_le = 16384,
--
-- // macro types
--
-- DT_WARN = is_warn,
-- DT_CHECK = is_check,
-- DT_REQUIRE = is_require,
--
-- DT_WARN_FALSE = is_false | is_warn,
-- DT_CHECK_FALSE = is_false | is_check,
-- DT_REQUIRE_FALSE = is_false | is_require,
--
-- DT_WARN_THROWS = is_throws | is_warn,
-- DT_CHECK_THROWS = is_throws | is_check,
-- DT_REQUIRE_THROWS = is_throws | is_require,
--
-- DT_WARN_THROWS_AS = is_throws_as | is_warn,
-- DT_CHECK_THROWS_AS = is_throws_as | is_check,
-- DT_REQUIRE_THROWS_AS = is_throws_as | is_require,
--
-- DT_WARN_NOTHROW = is_nothrow | is_warn,
-- DT_CHECK_NOTHROW = is_nothrow | is_check,
-- DT_REQUIRE_NOTHROW = is_nothrow | is_require,
--
-- DT_WARN_EQ = is_eq | is_warn,
-- DT_CHECK_EQ = is_eq | is_check,
-- DT_REQUIRE_EQ = is_eq | is_require,
--
-- DT_WARN_NE = is_ne | is_warn,
-- DT_CHECK_NE = is_ne | is_check,
-- DT_REQUIRE_NE = is_ne | is_require,
--
-- DT_WARN_GT = is_gt | is_warn,
-- DT_CHECK_GT = is_gt | is_check,
-- DT_REQUIRE_GT = is_gt | is_require,
--
-- DT_WARN_LT = is_lt | is_warn,
-- DT_CHECK_LT = is_lt | is_check,
-- DT_REQUIRE_LT = is_lt | is_require,
--
-- DT_WARN_GE = is_ge | is_warn,
-- DT_CHECK_GE = is_ge | is_check,
-- DT_REQUIRE_GE = is_ge | is_require,
--
-- DT_WARN_LE = is_le | is_warn,
-- DT_CHECK_LE = is_le | is_check,
-- DT_REQUIRE_LE = is_le | is_require,
--
-- DT_WARN_UNARY = is_unary | is_warn,
-- DT_CHECK_UNARY = is_unary | is_check,
-- DT_REQUIRE_UNARY = is_unary | is_require,
--
-- DT_WARN_UNARY_FALSE = is_false | is_unary | is_warn,
-- DT_CHECK_UNARY_FALSE = is_false | is_unary | is_check,
-- DT_REQUIRE_UNARY_FALSE = is_false | is_unary | is_require,
--
-- DT_FAST_WARN_EQ = is_fast | is_eq | is_warn,
-- DT_FAST_CHECK_EQ = is_fast | is_eq | is_check,
-- DT_FAST_REQUIRE_EQ = is_fast | is_eq | is_require,
--
-- DT_FAST_WARN_NE = is_fast | is_ne | is_warn,
-- DT_FAST_CHECK_NE = is_fast | is_ne | is_check,
-- DT_FAST_REQUIRE_NE = is_fast | is_ne | is_require,
--
-- DT_FAST_WARN_GT = is_fast | is_gt | is_warn,
-- DT_FAST_CHECK_GT = is_fast | is_gt | is_check,
-- DT_FAST_REQUIRE_GT = is_fast | is_gt | is_require,
--
-- DT_FAST_WARN_LT = is_fast | is_lt | is_warn,
-- DT_FAST_CHECK_LT = is_fast | is_lt | is_check,
-- DT_FAST_REQUIRE_LT = is_fast | is_lt | is_require,
--
-- DT_FAST_WARN_GE = is_fast | is_ge | is_warn,
-- DT_FAST_CHECK_GE = is_fast | is_ge | is_check,
-- DT_FAST_REQUIRE_GE = is_fast | is_ge | is_require,
--
-- DT_FAST_WARN_LE = is_fast | is_le | is_warn,
-- DT_FAST_CHECK_LE = is_fast | is_le | is_check,
-- DT_FAST_REQUIRE_LE = is_fast | is_le | is_require,
--
-- DT_FAST_WARN_UNARY = is_fast | is_unary | is_warn,
-- DT_FAST_CHECK_UNARY = is_fast | is_unary | is_check,
-- DT_FAST_REQUIRE_UNARY = is_fast | is_unary | is_require,
--
-- DT_FAST_WARN_UNARY_FALSE = is_fast | is_false | is_unary | is_warn,
-- DT_FAST_CHECK_UNARY_FALSE = is_fast | is_false | is_unary | is_check,
-- DT_FAST_REQUIRE_UNARY_FALSE = is_fast | is_false | is_unary | is_require
-- };
-- } // namespace assertType
--
-- const char* getAssertString(assertType::Enum val);
--
-- // clang-format off
-- template<class T> struct decay_array { typedef T type; };
-- template<class T, unsigned N> struct decay_array<T[N]> { typedef T* type; };
-- template<class T> struct decay_array<T[]> { typedef T* type; };
--
-- template<class T> struct not_char_pointer { enum { value = true }; };
-- template<> struct not_char_pointer<char*> { enum { value = false }; };
-- template<> struct not_char_pointer<const char*> { enum { value = false }; };
--
-- template<class T> struct can_use_op : not_char_pointer<typename decay_array<T>::type> {};
--
-- template<bool, class = void> struct enable_if {};
-- template<class T> struct enable_if<true, T> { typedef T type; };
-- // clang-format on
--
-- struct TestFailureException
-- {};
--
-- bool checkIfShouldThrow(assertType::Enum assert_type);
-- void fastAssertThrowIfFlagSet(int flags);
-- void throwException();
-- bool always_false();
--
-- // a struct defining a registered test callback
-- struct TestData
-- {
-- // not used for determining uniqueness
-- const char* m_suite; // the test suite in which the test was added
-- const char* m_name; // name of the test function
-- funcType m_f; // a function pointer to the test function
--
-- // fields by which uniqueness of test cases shall be determined
-- const char* m_file; // the file in which the test was registered
-- unsigned m_line; // the line where the test was registered
--
-- TestData(const char* suite, const char* name, funcType f, const char* file, unsigned line)
-- : m_suite(suite)
-- , m_name(name)
-- , m_f(f)
-- , m_file(file)
-- , m_line(line) {}
--
-- bool operator<(const TestData& other) const;
-- };
--
-- struct SubcaseSignature
-- {
-- const char* m_name;
-- const char* m_file;
-- int m_line;
--
-- SubcaseSignature(const char* name, const char* file, int line)
-- : m_name(name)
-- , m_file(file)
-- , m_line(line) {}
--
-- bool operator<(const SubcaseSignature& other) const;
-- };
--
-- struct Subcase
-- {
-- SubcaseSignature m_signature;
-- bool m_entered;
--
-- Subcase(const char* name, const char* file, int line);
-- Subcase(const Subcase& other);
-- ~Subcase();
--
-- operator bool() const { return m_entered; }
-- };
--
-- template <typename L, typename R>
-- String stringifyBinaryExpr(const DOCTEST_REF_WRAP(L) lhs, const char* op,
-- const DOCTEST_REF_WRAP(R) rhs) {
-- return toString(lhs) + op + toString(rhs);
-- }
--
-- struct Result
-- {
-- bool m_passed;
-- String m_decomposition;
--
--// to fix gcc 4.7 "-Winline" warnings
--#if defined(__GNUC__) && !defined(__clang__)
-- __attribute__((noinline))
--#endif
-- ~Result() {
-- }
--
-- Result(bool passed = false, const String& decomposition = String())
-- : m_passed(passed)
-- , m_decomposition(decomposition) {}
--
-- Result(const Result& other)
-- : m_passed(other.m_passed)
-- , m_decomposition(other.m_decomposition) {}
--
--// to fix gcc 4.7 "-Winline" warnings
--#if defined(__GNUC__) && !defined(__clang__)
-- __attribute__((noinline))
--#endif
-- Result&
-- operator=(const Result& other) {
-- m_passed = other.m_passed;
-- m_decomposition = other.m_decomposition;
--
-- return *this;
-- }
--
-- operator bool() { return !m_passed; }
--
-- void invert() { m_passed = !m_passed; }
--
-- // clang-format off
-- // forbidding some expressions based on this table: http://en.cppreference.com/w/cpp/language/operator_precedence
-- template <typename R> Result operator& (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
-- template <typename R> Result operator^ (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
-- template <typename R> Result operator| (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
-- template <typename R> Result operator&& (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
-- template <typename R> Result operator|| (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
-- template <typename R> Result operator== (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
-- template <typename R> Result operator!= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
-- template <typename R> Result operator< (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
-- template <typename R> Result operator> (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
-- template <typename R> Result operator<= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
-- template <typename R> Result operator>= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
-- template <typename R> Result operator= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
-- template <typename R> Result operator+= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
-- template <typename R> Result operator-= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
-- template <typename R> Result operator*= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
-- template <typename R> Result operator/= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
-- template <typename R> Result operator%= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
-- template <typename R> Result operator<<=(const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
-- template <typename R> Result operator>>=(const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
-- template <typename R> Result operator&= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
-- template <typename R> Result operator^= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
-- template <typename R> Result operator|= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
-- // clang-format on
-- };
--
--#ifndef DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION
--
--#if defined(__clang__)
--#pragma clang diagnostic push
--#pragma clang diagnostic ignored "-Wsign-conversion"
--#pragma clang diagnostic ignored "-Wsign-compare"
--#pragma clang diagnostic ignored "-Wdouble-promotion"
--//#pragma clang diagnostic ignored "-Wconversion"
--//#pragma clang diagnostic ignored "-Wfloat-equal"
--#endif // __clang__
--
--#if defined(__GNUC__) && !defined(__clang__)
--#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6)
--#pragma GCC diagnostic push
--#endif // > gcc 4.6
--#pragma GCC diagnostic ignored "-Wsign-conversion"
--#pragma GCC diagnostic ignored "-Wsign-compare"
--#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5)
--#pragma GCC diagnostic ignored "-Wdouble-promotion"
--#endif // > gcc 4.5
--//#pragma GCC diagnostic ignored "-Wconversion"
--//#pragma GCC diagnostic ignored "-Wfloat-equal"
--#endif // __GNUC__
--
--#ifdef _MSC_VER
--#pragma warning(push)
--// http://stackoverflow.com/questions/39479163 what's the difference between C4018 and C4389
--#pragma warning(disable : 4389) // 'operator' : signed/unsigned mismatch
--#pragma warning(disable : 4018) // 'expression' : signed/unsigned mismatch
--//#pragma warning(disable : 4805) // 'operation' : unsafe mix of type 'type' and type 'type' in operation
--#endif // _MSC_VER
--
--#endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION
--
--// clang-format off
--#ifndef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
--#define DOCTEST_COMPARISON_RETURN_TYPE bool
--#else // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
--#define DOCTEST_COMPARISON_RETURN_TYPE typename enable_if<can_use_op<L>::value || can_use_op<R>::value, bool>::type
-- inline bool eq(const char* lhs, const char* rhs) { return String(lhs) == String(rhs); }
-- inline bool ne(const char* lhs, const char* rhs) { return String(lhs) != String(rhs); }
-- inline bool lt(const char* lhs, const char* rhs) { return String(lhs) < String(rhs); }
-- inline bool gt(const char* lhs, const char* rhs) { return String(lhs) > String(rhs); }
-- inline bool le(const char* lhs, const char* rhs) { return String(lhs) <= String(rhs); }
-- inline bool ge(const char* lhs, const char* rhs) { return String(lhs) >= String(rhs); }
--#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
--
-- 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; }
-- 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; }
-- 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; }
-- 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; }
-- 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; }
-- 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; }
-- // clang-format on
--
-- template <typename L>
-- struct Expression_lhs
-- {
-- L lhs;
--
-- Expression_lhs(L in)
-- : lhs(in) {}
--
-- Expression_lhs(const Expression_lhs& other)
-- : lhs(other.lhs) {}
--
-- operator Result() { return Result(!!lhs, toString(lhs)); }
--
--// clang-format off
--#ifndef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
-- template <typename R> Result operator==(const DOCTEST_REF_WRAP(R) rhs) { return Result(lhs == rhs, stringifyBinaryExpr(lhs, " == ", rhs)); }
-- template <typename R> Result operator!=(const DOCTEST_REF_WRAP(R) rhs) { return Result(lhs != rhs, stringifyBinaryExpr(lhs, " != ", rhs)); }
-- template <typename R> Result operator< (const DOCTEST_REF_WRAP(R) rhs) { return Result(lhs < rhs, stringifyBinaryExpr(lhs, " < " , rhs)); }
-- template <typename R> Result operator<=(const DOCTEST_REF_WRAP(R) rhs) { return Result(lhs <= rhs, stringifyBinaryExpr(lhs, " <= ", rhs)); }
-- template <typename R> Result operator> (const DOCTEST_REF_WRAP(R) rhs) { return Result(lhs > rhs, stringifyBinaryExpr(lhs, " > " , rhs)); }
-- template <typename R> Result operator>=(const DOCTEST_REF_WRAP(R) rhs) { return Result(lhs >= rhs, stringifyBinaryExpr(lhs, " >= ", rhs)); }
--#else // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
-- template <typename R> Result operator==(const DOCTEST_REF_WRAP(R) rhs) { return Result(eq(lhs, rhs), stringifyBinaryExpr(lhs, " == ", rhs)); }
-- template <typename R> Result operator!=(const DOCTEST_REF_WRAP(R) rhs) { return Result(ne(lhs, rhs), stringifyBinaryExpr(lhs, " != ", rhs)); }
-- template <typename R> Result operator< (const DOCTEST_REF_WRAP(R) rhs) { return Result(lt(lhs, rhs), stringifyBinaryExpr(lhs, " < " , rhs)); }
-- template <typename R> Result operator<=(const DOCTEST_REF_WRAP(R) rhs) { return Result(le(lhs, rhs), stringifyBinaryExpr(lhs, " <= ", rhs)); }
-- template <typename R> Result operator> (const DOCTEST_REF_WRAP(R) rhs) { return Result(gt(lhs, rhs), stringifyBinaryExpr(lhs, " > " , rhs)); }
-- template <typename R> Result operator>=(const DOCTEST_REF_WRAP(R) rhs) { return Result(ge(lhs, rhs), stringifyBinaryExpr(lhs, " >= ", rhs)); }
--#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
-- // clang-format on
--
-- // clang-format off
-- // forbidding some expressions based on this table: http://en.cppreference.com/w/cpp/language/operator_precedence
-- template <typename R> int operator& (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
-- template <typename R> int operator^ (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
-- template <typename R> int operator| (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
-- template <typename R> int operator&& (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
-- template <typename R> int operator|| (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
-- template <typename R> int operator= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
-- template <typename R> int operator+= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
-- template <typename R> int operator-= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
-- template <typename R> int operator*= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
-- template <typename R> int operator/= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
-- template <typename R> int operator%= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
-- template <typename R> int operator<<=(const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
-- template <typename R> int operator>>=(const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
-- template <typename R> int operator&= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
-- template <typename R> int operator^= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
-- template <typename R> int operator|= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
-- // these 2 are unfortunate because they should be allowed - they have higher precedence over the comparisons, but the
-- // ExpressionDecomposer class uses the left shift operator to capture the left operand of the binary expression...
-- template <typename R> int operator<< (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Please_Surround_The_Left_Shift_Operation_With_Parenthesis); return int(); }
-- template <typename R> int operator>> (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Please_Surround_The_Right_Shift_Operation_With_Parenthesis); return int(); }
-- // clang-format on
-- };
--
--#ifndef DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION
--
--#if defined(__clang__)
--#pragma clang diagnostic pop
--#endif // __clang__
--
--#if defined(__GNUC__) && !defined(__clang__)
--#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6)
--#pragma GCC diagnostic pop
--#endif // > gcc 4.6
--#endif // __GNUC__
--
--#ifdef _MSC_VER
--#pragma warning(pop)
--#endif // _MSC_VER
--
--#endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION
--
-- struct ExpressionDecomposer
-- {
-- template <typename L>
-- Expression_lhs<const DOCTEST_REF_WRAP(L)> operator<<(const DOCTEST_REF_WRAP(L) operand) {
-- return Expression_lhs<const DOCTEST_REF_WRAP(L)>(operand);
-- }
-- };
--
-- // forward declarations of functions used by the macros
-- int regTest(void (*f)(void), unsigned line, const char* file, const char* name);
-- int setTestSuiteName(const char* name);
--
-- void addFailedAssert(assertType::Enum assert_type);
--
-- void logTestStart(const char* name, const char* file, unsigned line);
-- void logTestEnd();
--
-- void logTestCrashed();
--
-- void logAssert(bool passed, const char* decomposition, bool threw, const char* expr,
-- assertType::Enum assert_type, const char* file, int line);
--
-- void logAssertThrows(bool threw, const char* expr, assertType::Enum assert_type,
-- const char* file, int line);
--
-- void logAssertThrowsAs(bool threw, bool threw_as, const char* as, const char* expr,
-- assertType::Enum assert_type, const char* file, int line);
--
-- void logAssertNothrow(bool threw, const char* expr, assertType::Enum assert_type,
-- const char* file, int line);
--
-- bool isDebuggerActive();
-- void writeToDebugConsole(const String&);
--
-- struct TestAccessibleContextState
-- {
-- bool success; // include successful assertions in output
-- bool no_throw; // to skip exceptions-related assertion macros
-- bool no_breaks; // to not break into the debugger
-- const TestData* currentTest;
-- bool hasLoggedCurrentTestStart;
-- int numAssertionsForCurrentTestcase;
-- };
--
-- struct ContextState;
--
-- TestAccessibleContextState* getTestsContextState();
--
-- namespace binaryAssertComparison
-- {
-- enum Enum
-- {
-- eq = 0,
-- ne,
-- gt,
-- lt,
-- ge,
-- le
-- };
-- } // namespace binaryAssertComparison
--
-- // clang-format off
-- template <int, class L, class R> struct RelationalComparator { bool operator()(const DOCTEST_REF_WRAP(L), const DOCTEST_REF_WRAP(R) ) const { return false; } };
-- 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); } };
-- 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); } };
-- 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); } };
-- 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); } };
-- 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); } };
-- 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); } };
-- // clang-format on
--
-- struct ResultBuilder
-- {
-- assertType::Enum m_assert_type;
-- const char* m_file;
-- int m_line;
-- const char* m_expr;
-- const char* m_exception_type;
--
-- Result m_result;
-- bool m_threw;
-- bool m_threw_as;
-- bool m_failed;
--
-- ResultBuilder(assertType::Enum assert_type, const char* file, int line, const char* expr,
-- const char* exception_type = "");
--
--// to fix gcc 4.7 "-Winline" warnings
--#if defined(__GNUC__) && !defined(__clang__)
-- __attribute__((noinline))
--#endif
-- ~ResultBuilder() {
-- }
--
-- void setResult(const Result& res) { m_result = res; }
--
-- template <int comparison, typename L, typename R>
-- void binary_assert(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) {
-- m_result.m_passed = RelationalComparator<comparison, L, R>()(lhs, rhs);
-- m_result.m_decomposition = stringifyBinaryExpr(lhs, ", ", rhs);
-- }
--
-- template <typename L>
-- void unary_assert(const DOCTEST_REF_WRAP(L) val) {
-- m_result.m_passed = !!val;
-- m_result.m_decomposition = toString(val);
-- }
--
-- bool log();
-- void react() const;
-- };
--
-- namespace assertAction
-- {
-- enum Enum
-- {
-- nothing = 0,
-- dbgbreak = 1,
-- shouldthrow = 2
-- };
-- } // namespace assertAction
--
-- template <int comparison, typename L, typename R>
-- int fast_binary_assert(assertType::Enum assert_type, const char* file, int line,
-- const char* lhs_str, const char* rhs_str, const DOCTEST_REF_WRAP(L) lhs,
-- const DOCTEST_REF_WRAP(R) rhs) {
-- String expr = String(lhs_str) + ", " + rhs_str;
-- const char* expr_str = expr.c_str();
-- ResultBuilder rb(assert_type, file, line, expr_str);
--
-- rb.m_result.m_passed = RelationalComparator<comparison, L, R>()(lhs, rhs);
-- rb.m_result.m_decomposition = stringifyBinaryExpr(lhs, ", ", rhs);
--
-- int res = 0;
--
-- if(rb.log())
-- res |= assertAction::dbgbreak;
--
-- if(rb.m_failed && checkIfShouldThrow(assert_type))
-- res |= assertAction::shouldthrow;
--
--#ifdef DOCTEST_CONFIG_SUPER_FAST_ASSERTS
-- // #########################################################################################
-- // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK TO SEE THE FAILING ASSERTION
-- // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED
-- // #########################################################################################
-- if(res & assertAction::dbgbreak)
-- DOCTEST_BREAK_INTO_DEBUGGER();
-- fastAssertThrowIfFlagSet(res);
--#endif // DOCTEST_CONFIG_SUPER_FAST_ASSERTS
--
-- return res;
-- }
--
-- template <typename L>
-- int fast_unary_assert(assertType::Enum assert_type, const char* file, int line,
-- const char* val_str, const DOCTEST_REF_WRAP(L) val) {
-- ResultBuilder rb(assert_type, file, line, val_str);
--
-- rb.m_result.m_passed = !!val;
-- rb.m_result.m_decomposition = toString(val);
--
-- int res = 0;
--
-- if(rb.log())
-- res |= assertAction::dbgbreak;
--
-- if(rb.m_failed && checkIfShouldThrow(assert_type))
-- res |= assertAction::shouldthrow;
--
--#ifdef DOCTEST_CONFIG_SUPER_FAST_ASSERTS
-- // #########################################################################################
-- // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK TO SEE THE FAILING ASSERTION
-- // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED
-- // #########################################################################################
-- if(res & assertAction::dbgbreak)
-- DOCTEST_BREAK_INTO_DEBUGGER();
-- fastAssertThrowIfFlagSet(res);
--#endif // DOCTEST_CONFIG_SUPER_FAST_ASSERTS
--
-- return res;
-- }
--} // namespace detail
--
--#endif // DOCTEST_CONFIG_DISABLE
--
--class Context
--{
--#if !defined(DOCTEST_CONFIG_DISABLE)
-- detail::ContextState* p;
--
-- void parseArgs(int argc, const char* const* argv, bool withDefaults = false);
--
--#endif // DOCTEST_CONFIG_DISABLE
--
--public:
-- Context(int argc = 0, const char* const* argv = 0);
--
--// to fix gcc 4.7 "-Winline" warnings
--#if defined(__GNUC__) && !defined(__clang__)
-- __attribute__((noinline))
--#endif
-- ~Context();
--
-- void applyCommandLine(int argc, const char* const* argv);
--
-- void addFilter(const char* filter, const char* value);
-- void clearFilters();
-- void setOption(const char* option, int value);
-- void setOption(const char* option, const char* value);
--
-- bool shouldExit();
--
-- int run();
--};
--
--} // namespace doctest
--
--// if registering is not disabled
--#if !defined(DOCTEST_CONFIG_DISABLE)
--
--// registers the test by initializing a dummy var with a function
--#if defined(__GNUC__) && !defined(__clang__)
--#define DOCTEST_REGISTER_FUNCTION(f, name) \
-- static int DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_) __attribute__((unused)) = \
-- doctest::detail::regTest(f, __LINE__, __FILE__, name);
--#elif defined(__clang__)
--#define DOCTEST_REGISTER_FUNCTION(f, name) \
-- _Pragma("clang diagnostic push") \
-- _Pragma("clang diagnostic ignored \"-Wglobal-constructors\"") static int \
-- DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_) = \
-- doctest::detail::regTest(f, __LINE__, __FILE__, name); \
-- _Pragma("clang diagnostic pop")
--#else // MSVC
--#define DOCTEST_REGISTER_FUNCTION(f, name) \
-- static int DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_) = \
-- doctest::detail::regTest(f, __LINE__, __FILE__, name);
--#endif // MSVC
--
--#define DOCTEST_IMPLEMENT_FIXTURE(der, base, func, name) \
-- namespace \
-- { \
-- struct der : base \
-- { void f(); }; \
-- static void func() { \
-- der v; \
-- v.f(); \
-- } \
-- DOCTEST_REGISTER_FUNCTION(func, name) \
-- } \
-- inline void der::f()
--
--#define DOCTEST_CREATE_AND_REGISTER_FUNCTION(f, name) \
-- static void f(); \
-- DOCTEST_REGISTER_FUNCTION(f, name) \
-- inline void f()
--
--// for registering tests
--#define DOCTEST_TEST_CASE(name) \
-- DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), name)
--
--// for registering tests with a fixture
--#define DOCTEST_TEST_CASE_FIXTURE(c, name) \
-- DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(_DOCTEST_ANON_CLASS_), c, \
-- DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), name)
--
--// for subcases
--#if defined(__GNUC__)
--#define DOCTEST_SUBCASE(name) \
-- if(const doctest::detail::Subcase & DOCTEST_ANONYMOUS(_DOCTEST_ANON_SUBCASE_) \
-- __attribute__((unused)) = \
-- doctest::detail::Subcase(name, __FILE__, __LINE__))
--#else // __GNUC__
--#define DOCTEST_SUBCASE(name) \
-- if(const doctest::detail::Subcase & DOCTEST_ANONYMOUS(_DOCTEST_ANON_SUBCASE_) = \
-- doctest::detail::Subcase(name, __FILE__, __LINE__))
--#endif // __GNUC__
--
--// for starting a testsuite block
--#if defined(__GNUC__) && !defined(__clang__)
--#define DOCTEST_TEST_SUITE(name) \
-- static int DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_) __attribute__((unused)) = \
-- doctest::detail::setTestSuiteName(name); \
-- typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
--#elif defined(__clang__)
--#define DOCTEST_TEST_SUITE(name) \
-- _Pragma("clang diagnostic push") \
-- _Pragma("clang diagnostic ignored \"-Wglobal-constructors\"") static int \
-- DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_) = \
-- doctest::detail::setTestSuiteName(name); \
-- _Pragma("clang diagnostic pop") typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
--#else // MSVC
--#define DOCTEST_TEST_SUITE(name) \
-- static int DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_) = doctest::detail::setTestSuiteName(name); \
-- typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
--#endif // MSVC
--
--// for ending a testsuite block
--#if defined(__GNUC__) && !defined(__clang__)
--#define DOCTEST_TEST_SUITE_END \
-- static int DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_) __attribute__((unused)) = \
-- doctest::detail::setTestSuiteName(""); \
-- typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
--#elif defined(__clang__)
--#define DOCTEST_TEST_SUITE_END \
-- _Pragma("clang diagnostic push") \
-- _Pragma("clang diagnostic ignored \"-Wglobal-constructors\"") static int \
-- DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_) = doctest::detail::setTestSuiteName(""); \
-- _Pragma("clang diagnostic pop") typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
--#else // MSVC
--#define DOCTEST_TEST_SUITE_END \
-- static int DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_) = doctest::detail::setTestSuiteName(""); \
-- typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
--#endif // MSVC
--
--#define DOCTEST_ASSERT_LOG_AND_REACT(rb) \
-- if(rb.log()) \
-- DOCTEST_BREAK_INTO_DEBUGGER(); \
-- rb.react()
--
--#ifdef DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
--#define DOCTEST_WRAP_IN_TRY(x) x;
--#else // DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
--#define DOCTEST_WRAP_IN_TRY(x) \
-- try { \
-- x; \
-- } catch(...) { _DOCTEST_RB.m_threw = true; }
--#endif // DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
--
--#define DOCTEST_ASSERT_IMPLEMENT(expr, assert_type) \
-- doctest::detail::ResultBuilder _DOCTEST_RB(doctest::detail::assertType::assert_type, __FILE__, \
-- __LINE__, #expr); \
-- DOCTEST_WRAP_IN_TRY(_DOCTEST_RB.setResult(doctest::detail::ExpressionDecomposer() << expr)) \
-- DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB);
--
--#if defined(__clang__)
--#define DOCTEST_ASSERT_PROXY(expr, assert_type) \
-- do { \
-- _Pragma("clang diagnostic push") \
-- _Pragma("clang diagnostic ignored \"-Woverloaded-shift-op-parentheses\"") \
-- DOCTEST_ASSERT_IMPLEMENT(expr, assert_type) \
-- _Pragma("clang diagnostic pop") \
-- } while(doctest::detail::always_false())
--#else // __clang__
--#define DOCTEST_ASSERT_PROXY(expr, assert_type) \
-- do { \
-- DOCTEST_ASSERT_IMPLEMENT(expr, assert_type) \
-- } while(doctest::detail::always_false())
--#endif // __clang__
--
--#define DOCTEST_WARN(expr) DOCTEST_ASSERT_PROXY(expr, DT_WARN)
--#define DOCTEST_CHECK(expr) DOCTEST_ASSERT_PROXY(expr, DT_CHECK)
--#define DOCTEST_REQUIRE(expr) DOCTEST_ASSERT_PROXY(expr, DT_REQUIRE)
--
--#define DOCTEST_WARN_FALSE(expr) DOCTEST_ASSERT_PROXY(expr, DT_WARN_FALSE)
--#define DOCTEST_CHECK_FALSE(expr) DOCTEST_ASSERT_PROXY(expr, DT_CHECK_FALSE)
--#define DOCTEST_REQUIRE_FALSE(expr) DOCTEST_ASSERT_PROXY(expr, DT_REQUIRE_FALSE)
--
--#define DOCTEST_ASSERT_THROWS(expr, assert_type) \
-- do { \
-- if(!DOCTEST_GCS().no_throw) { \
-- doctest::detail::ResultBuilder _DOCTEST_RB(doctest::detail::assertType::assert_type, \
-- __FILE__, __LINE__, #expr); \
-- try { \
-- expr; \
-- } catch(...) { _DOCTEST_RB.m_threw = true; } \
-- DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \
-- } \
-- } while(doctest::detail::always_false())
--
--#define DOCTEST_ASSERT_THROWS_AS(expr, as, assert_type) \
-- do { \
-- if(!DOCTEST_GCS().no_throw) { \
-- doctest::detail::ResultBuilder _DOCTEST_RB(doctest::detail::assertType::assert_type, \
-- __FILE__, __LINE__, #expr, #as); \
-- try { \
-- expr; \
-- } catch(as) { \
-- _DOCTEST_RB.m_threw = true; \
-- _DOCTEST_RB.m_threw_as = true; \
-- } catch(...) { _DOCTEST_RB.m_threw = true; } \
-- DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \
-- } \
-- } while(doctest::detail::always_false())
--
--#define DOCTEST_ASSERT_NOTHROW(expr, assert_type) \
-- do { \
-- if(!DOCTEST_GCS().no_throw) { \
-- doctest::detail::ResultBuilder _DOCTEST_RB(doctest::detail::assertType::assert_type, \
-- __FILE__, __LINE__, #expr); \
-- try { \
-- expr; \
-- } catch(...) { _DOCTEST_RB.m_threw = true; } \
-- DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \
-- } \
-- } while(doctest::detail::always_false())
--
--#define DOCTEST_WARN_THROWS(expr) DOCTEST_ASSERT_THROWS(expr, DT_WARN_THROWS)
--#define DOCTEST_CHECK_THROWS(expr) DOCTEST_ASSERT_THROWS(expr, DT_CHECK_THROWS)
--#define DOCTEST_REQUIRE_THROWS(expr) DOCTEST_ASSERT_THROWS(expr, DT_REQUIRE_THROWS)
--
--#define DOCTEST_WARN_THROWS_AS(expr, ex) DOCTEST_ASSERT_THROWS_AS(expr, ex, DT_WARN_THROWS_AS)
--#define DOCTEST_CHECK_THROWS_AS(expr, ex) DOCTEST_ASSERT_THROWS_AS(expr, ex, DT_CHECK_THROWS_AS)
--#define DOCTEST_REQUIRE_THROWS_AS(expr, ex) DOCTEST_ASSERT_THROWS_AS(expr, ex, DT_REQUIRE_THROWS_AS)
--
--#define DOCTEST_WARN_NOTHROW(expr) DOCTEST_ASSERT_NOTHROW(expr, DT_WARN_NOTHROW)
--#define DOCTEST_CHECK_NOTHROW(expr) DOCTEST_ASSERT_NOTHROW(expr, DT_CHECK_NOTHROW)
--#define DOCTEST_REQUIRE_NOTHROW(expr) DOCTEST_ASSERT_NOTHROW(expr, DT_REQUIRE_NOTHROW)
--
--#define DOCTEST_BINARY_ASSERT(assert_type, lhs, rhs, comp) \
-- do { \
-- doctest::detail::ResultBuilder _DOCTEST_RB(doctest::detail::assertType::assert_type, \
-- __FILE__, __LINE__, #lhs ", " #rhs); \
-- DOCTEST_WRAP_IN_TRY( \
-- _DOCTEST_RB.binary_assert<doctest::detail::binaryAssertComparison::comp>(lhs, \
-- rhs)) \
-- DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \
-- } while(doctest::detail::always_false())
--
--#define DOCTEST_UNARY_ASSERT(assert_type, val) \
-- do { \
-- doctest::detail::ResultBuilder _DOCTEST_RB(doctest::detail::assertType::assert_type, \
-- __FILE__, __LINE__, #val); \
-- DOCTEST_WRAP_IN_TRY(_DOCTEST_RB.unary_assert(val)) \
-- DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \
-- } while(doctest::detail::always_false())
--
--#define DOCTEST_WARN_EQ(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_WARN_EQ, lhs, rhs, eq)
--#define DOCTEST_CHECK_EQ(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_CHECK_EQ, lhs, rhs, eq)
--#define DOCTEST_REQUIRE_EQ(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_REQUIRE_EQ, lhs, rhs, eq)
--#define DOCTEST_WARN_NE(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_WARN_NE, lhs, rhs, ne)
--#define DOCTEST_CHECK_NE(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_CHECK_NE, lhs, rhs, ne)
--#define DOCTEST_REQUIRE_NE(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_REQUIRE_NE, lhs, rhs, ne)
--#define DOCTEST_WARN_GT(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_WARN_GT, lhs, rhs, gt)
--#define DOCTEST_CHECK_GT(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_CHECK_GT, lhs, rhs, gt)
--#define DOCTEST_REQUIRE_GT(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_REQUIRE_GT, lhs, rhs, gt)
--#define DOCTEST_WARN_LT(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_WARN_LT, lhs, rhs, lt)
--#define DOCTEST_CHECK_LT(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_CHECK_LT, lhs, rhs, lt)
--#define DOCTEST_REQUIRE_LT(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_REQUIRE_LT, lhs, rhs, lt)
--#define DOCTEST_WARN_GE(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_WARN_GE, lhs, rhs, ge)
--#define DOCTEST_CHECK_GE(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_CHECK_GE, lhs, rhs, ge)
--#define DOCTEST_REQUIRE_GE(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_REQUIRE_GE, lhs, rhs, ge)
--#define DOCTEST_WARN_LE(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_WARN_LE, lhs, rhs, le)
--#define DOCTEST_CHECK_LE(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_CHECK_LE, lhs, rhs, le)
--#define DOCTEST_REQUIRE_LE(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_REQUIRE_LE, lhs, rhs, le)
--
--#define DOCTEST_WARN_UNARY(v) DOCTEST_UNARY_ASSERT(DT_WARN_UNARY, v)
--#define DOCTEST_CHECK_UNARY(v) DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY, v)
--#define DOCTEST_REQUIRE_UNARY(v) DOCTEST_UNARY_ASSERT(DT_REQUIRE_UNARY, v)
--#define DOCTEST_WARN_UNARY_FALSE(v) DOCTEST_UNARY_ASSERT(DT_WARN_UNARY_FALSE, v)
--#define DOCTEST_CHECK_UNARY_FALSE(v) DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY_FALSE, v)
--#define DOCTEST_REQUIRE_UNARY_FALSE(v) DOCTEST_UNARY_ASSERT(DT_REQUIRE_UNARY_FALSE, v)
--
--#ifndef DOCTEST_CONFIG_SUPER_FAST_ASSERTS
--
--#define DOCTEST_FAST_BINARY_ASSERT(assert_type, lhs, rhs, comparison) \
-- do { \
-- int _DOCTEST_FAST_RES = doctest::detail::fast_binary_assert< \
-- doctest::detail::binaryAssertComparison::comparison>( \
-- doctest::detail::assertType::assert_type, __FILE__, __LINE__, #lhs, #rhs, lhs, \
-- rhs); \
-- if(_DOCTEST_FAST_RES & doctest::detail::assertAction::dbgbreak) \
-- DOCTEST_BREAK_INTO_DEBUGGER(); \
-- doctest::detail::fastAssertThrowIfFlagSet(_DOCTEST_FAST_RES); \
-- } while(doctest::detail::always_false())
--
--#define DOCTEST_FAST_UNARY_ASSERT(assert_type, val) \
-- do { \
-- int _DOCTEST_FAST_RES = doctest::detail::fast_unary_assert( \
-- doctest::detail::assertType::assert_type, __FILE__, __LINE__, #val, val); \
-- if(_DOCTEST_FAST_RES & doctest::detail::assertAction::dbgbreak) \
-- DOCTEST_BREAK_INTO_DEBUGGER(); \
-- doctest::detail::fastAssertThrowIfFlagSet(_DOCTEST_FAST_RES); \
-- } while(doctest::detail::always_false())
--
--#else // DOCTEST_CONFIG_SUPER_FAST_ASSERTS
--
--#define DOCTEST_FAST_BINARY_ASSERT(assert_type, lhs, rhs, comparison) \
-- doctest::detail::fast_binary_assert<doctest::detail::binaryAssertComparison::comparison>( \
-- doctest::detail::assertType::assert_type, __FILE__, __LINE__, #lhs, #rhs, lhs, rhs)
--
--#define DOCTEST_FAST_UNARY_ASSERT(assert_type, val) \
-- doctest::detail::fast_unary_assert(doctest::detail::assertType::assert_type, __FILE__, \
-- __LINE__, #val, val)
--
--#endif // DOCTEST_CONFIG_SUPER_FAST_ASSERTS
--
--#define DOCTEST_FAST_WARN_EQ(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_WARN_EQ, l, r, eq)
--#define DOCTEST_FAST_CHECK_EQ(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_CHECK_EQ, l, r, eq)
--#define DOCTEST_FAST_REQUIRE_EQ(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_REQUIRE_EQ, l, r, eq)
--#define DOCTEST_FAST_WARN_NE(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_WARN_NE, l, r, ne)
--#define DOCTEST_FAST_CHECK_NE(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_CHECK_NE, l, r, ne)
--#define DOCTEST_FAST_REQUIRE_NE(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_REQUIRE_NE, l, r, ne)
--#define DOCTEST_FAST_WARN_GT(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_WARN_GT, l, r, gt)
--#define DOCTEST_FAST_CHECK_GT(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_CHECK_GT, l, r, gt)
--#define DOCTEST_FAST_REQUIRE_GT(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_REQUIRE_GT, l, r, gt)
--#define DOCTEST_FAST_WARN_LT(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_WARN_LT, l, r, lt)
--#define DOCTEST_FAST_CHECK_LT(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_CHECK_LT, l, r, lt)
--#define DOCTEST_FAST_REQUIRE_LT(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_REQUIRE_LT, l, r, lt)
--#define DOCTEST_FAST_WARN_GE(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_WARN_GE, l, r, ge)
--#define DOCTEST_FAST_CHECK_GE(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_CHECK_GE, l, r, ge)
--#define DOCTEST_FAST_REQUIRE_GE(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_REQUIRE_GE, l, r, ge)
--#define DOCTEST_FAST_WARN_LE(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_WARN_LE, l, r, le)
--#define DOCTEST_FAST_CHECK_LE(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_CHECK_LE, l, r, le)
--#define DOCTEST_FAST_REQUIRE_LE(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_REQUIRE_LE, l, r, le)
--
--#define DOCTEST_FAST_WARN_UNARY(v) DOCTEST_FAST_UNARY_ASSERT(DT_FAST_WARN_UNARY, v)
--#define DOCTEST_FAST_CHECK_UNARY(v) DOCTEST_FAST_UNARY_ASSERT(DT_FAST_CHECK_UNARY, v)
--#define DOCTEST_FAST_REQUIRE_UNARY(v) DOCTEST_FAST_UNARY_ASSERT(DT_FAST_REQUIRE_UNARY, v)
--#define DOCTEST_FAST_WARN_UNARY_FALSE(v) DOCTEST_FAST_UNARY_ASSERT(DT_FAST_WARN_UNARY_FALSE, v)
--#define DOCTEST_FAST_CHECK_UNARY_FALSE(v) DOCTEST_FAST_UNARY_ASSERT(DT_FAST_CHECK_UNARY_FALSE, v)
--#define DOCTEST_FAST_REQUIRE_UNARY_FALSE(v) \
-- DOCTEST_FAST_UNARY_ASSERT(DT_FAST_REQUIRE_UNARY_FALSE, v)
--
--
--
--// OMGOMGOMG trqbva da napravq teq da sa no-op - a ne prosto da ne gi undef-vam
--
--
--
--#ifdef DOCTEST_CONFIG_NO_EXCEPTIONS
--
--#undef DOCTEST_WARN_THROWS
--#undef DOCTEST_CHECK_THROWS
--#undef DOCTEST_REQUIRE_THROWS
--#undef DOCTEST_WARN_THROWS_AS
--#undef DOCTEST_CHECK_THROWS_AS
--#undef DOCTEST_REQUIRE_THROWS_AS
--#undef DOCTEST_WARN_NOTHROW
--#undef DOCTEST_CHECK_NOTHROW
--#undef DOCTEST_REQUIRE_NOTHROW
--
--#ifdef DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS
--
--#define DOCTEST_WARN_THROWS(expr) ((void)0)
--#define DOCTEST_WARN_THROWS_AS(expr, ex) ((void)0)
--#define DOCTEST_WARN_NOTHROW(expr) ((void)0)
--#define DOCTEST_CHECK_THROWS(expr) ((void)0)
--#define DOCTEST_CHECK_THROWS_AS(expr, ex) ((void)0)
--#define DOCTEST_CHECK_NOTHROW(expr) ((void)0)
--#define DOCTEST_REQUIRE_THROWS(expr) ((void)0)
--#define DOCTEST_REQUIRE_THROWS_AS(expr, ex) ((void)0)
--#define DOCTEST_REQUIRE_NOTHROW(expr) ((void)0)
--
--#else // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS
--
--#undef DOCTEST_REQUIRE
--#undef DOCTEST_REQUIRE_FALSE
--#undef DOCTEST_REQUIRE_EQ
--#undef DOCTEST_REQUIRE_NE
--#undef DOCTEST_REQUIRE_GT
--#undef DOCTEST_REQUIRE_LT
--#undef DOCTEST_REQUIRE_GE
--#undef DOCTEST_REQUIRE_LE
--#undef DOCTEST_REQUIRE_UNARY
--#undef DOCTEST_REQUIRE_UNARY_FALSE
--#undef DOCTEST_FAST_REQUIRE_EQ
--#undef DOCTEST_FAST_REQUIRE_NE
--#undef DOCTEST_FAST_REQUIRE_GT
--#undef DOCTEST_FAST_REQUIRE_LT
--#undef DOCTEST_FAST_REQUIRE_GE
--#undef DOCTEST_FAST_REQUIRE_LE
--#undef DOCTEST_FAST_REQUIRE_UNARY
--#undef DOCTEST_FAST_REQUIRE_UNARY_FALSE
--
--#endif // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS
--
--#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
--
--// =================================================================================================
--// == WHAT FOLLOWS IS VERSIONS OF THE MACROS THAT DO NOT DO ANY REGISTERING! ==
--// == THIS CAN BE ENABLED BY DEFINING DOCTEST_CONFIG_DISABLE GLOBALLY! ==
--// =================================================================================================
--#else // DOCTEST_CONFIG_DISABLE
--
--#define DOCTEST_IMPLEMENT_FIXTURE(der, base, func, name) \
-- namespace \
-- { \
-- template <typename T> \
-- struct der : base \
-- { void f(); }; \
-- } \
-- template <typename T> \
-- inline void der<T>::f()
--
--#define DOCTEST_CREATE_AND_REGISTER_FUNCTION(f, name) \
-- template <typename T> \
-- static inline void f()
--
--// for registering tests
--#define DOCTEST_TEST_CASE(name) \
-- DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), name)
--
--// for registering tests with a fixture
--#define DOCTEST_TEST_CASE_FIXTURE(x, name) \
-- DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(_DOCTEST_ANON_CLASS_), x, \
-- DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), name)
--
--// for subcases
--#define DOCTEST_SUBCASE(name)
--
--// for starting a testsuite block
--#define DOCTEST_TEST_SUITE(name) typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
--
--// for ending a testsuite block
--#define DOCTEST_TEST_SUITE_END typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
--
--#define DOCTEST_WARN(expr) ((void)0)
--#define DOCTEST_WARN_FALSE(expr) ((void)0)
--#define DOCTEST_WARN_THROWS(expr) ((void)0)
--#define DOCTEST_WARN_THROWS_AS(expr, ex) ((void)0)
--#define DOCTEST_WARN_NOTHROW(expr) ((void)0)
--#define DOCTEST_CHECK(expr) ((void)0)
--#define DOCTEST_CHECK_FALSE(expr) ((void)0)
--#define DOCTEST_CHECK_THROWS(expr) ((void)0)
--#define DOCTEST_CHECK_THROWS_AS(expr, ex) ((void)0)
--#define DOCTEST_CHECK_NOTHROW(expr) ((void)0)
--#define DOCTEST_REQUIRE(expr) ((void)0)
--#define DOCTEST_REQUIRE_FALSE(expr) ((void)0)
--#define DOCTEST_REQUIRE_THROWS(expr) ((void)0)
--#define DOCTEST_REQUIRE_THROWS_AS(expr, ex) ((void)0)
--#define DOCTEST_REQUIRE_NOTHROW(expr) ((void)0)
--
--#define DOCTEST_WARN_EQ(lhs, rhs) ((void)0)
--#define DOCTEST_CHECK_EQ(lhs, rhs) ((void)0)
--#define DOCTEST_REQUIRE_EQ(lhs, rhs) ((void)0)
--#define DOCTEST_WARN_NE(lhs, rhs) ((void)0)
--#define DOCTEST_CHECK_NE(lhs, rhs) ((void)0)
--#define DOCTEST_REQUIRE_NE(lhs, rhs) ((void)0)
--#define DOCTEST_WARN_GT(lhs, rhs) ((void)0)
--#define DOCTEST_CHECK_GT(lhs, rhs) ((void)0)
--#define DOCTEST_REQUIRE_GT(lhs, rhs) ((void)0)
--#define DOCTEST_WARN_LT(lhs, rhs) ((void)0)
--#define DOCTEST_CHECK_LT(lhs, rhs) ((void)0)
--#define DOCTEST_REQUIRE_LT(lhs, rhs) ((void)0)
--#define DOCTEST_WARN_GE(lhs, rhs) ((void)0)
--#define DOCTEST_CHECK_GE(lhs, rhs) ((void)0)
--#define DOCTEST_REQUIRE_GE(lhs, rhs) ((void)0)
--#define DOCTEST_WARN_LE(lhs, rhs) ((void)0)
--#define DOCTEST_CHECK_LE(lhs, rhs) ((void)0)
--#define DOCTEST_REQUIRE_LE(lhs, rhs) ((void)0)
--
--#define DOCTEST_WARN_UNARY(val) ((void)0)
--#define DOCTEST_CHECK_UNARY(val) ((void)0)
--#define DOCTEST_REQUIRE_UNARY(val) ((void)0)
--#define DOCTEST_WARN_UNARY_FALSE(val) ((void)0)
--#define DOCTEST_CHECK_UNARY_FALSE(val) ((void)0)
--#define DOCTEST_REQUIRE_UNARY_FALSE(val) ((void)0)
--
--#define DOCTEST_FAST_WARN_EQ(lhs, rhs) ((void)0)
--#define DOCTEST_FAST_CHECK_EQ(lhs, rhs) ((void)0)
--#define DOCTEST_FAST_REQUIRE_EQ(lhs, rhs) ((void)0)
--#define DOCTEST_FAST_WARN_NE(lhs, rhs) ((void)0)
--#define DOCTEST_FAST_CHECK_NE(lhs, rhs) ((void)0)
--#define DOCTEST_FAST_REQUIRE_NE(lhs, rhs) ((void)0)
--#define DOCTEST_FAST_WARN_GT(lhs, rhs) ((void)0)
--#define DOCTEST_FAST_CHECK_GT(lhs, rhs) ((void)0)
--#define DOCTEST_FAST_REQUIRE_GT(lhs, rhs) ((void)0)
--#define DOCTEST_FAST_WARN_LT(lhs, rhs) ((void)0)
--#define DOCTEST_FAST_CHECK_LT(lhs, rhs) ((void)0)
--#define DOCTEST_FAST_REQUIRE_LT(lhs, rhs) ((void)0)
--#define DOCTEST_FAST_WARN_GE(lhs, rhs) ((void)0)
--#define DOCTEST_FAST_CHECK_GE(lhs, rhs) ((void)0)
--#define DOCTEST_FAST_REQUIRE_GE(lhs, rhs) ((void)0)
--#define DOCTEST_FAST_WARN_LE(lhs, rhs) ((void)0)
--#define DOCTEST_FAST_CHECK_LE(lhs, rhs) ((void)0)
--#define DOCTEST_FAST_REQUIRE_LE(lhs, rhs) ((void)0)
--
--#define DOCTEST_FAST_WARN_UNARY(val) ((void)0)
--#define DOCTEST_FAST_CHECK_UNARY(val) ((void)0)
--#define DOCTEST_FAST_REQUIRE_UNARY(val) ((void)0)
--#define DOCTEST_FAST_WARN_UNARY_FALSE(val) ((void)0)
--#define DOCTEST_FAST_CHECK_UNARY_FALSE(val) ((void)0)
--#define DOCTEST_FAST_REQUIRE_UNARY_FALSE(val) ((void)0)
--
--#endif // DOCTEST_CONFIG_DISABLE
--
--// BDD style macros
--// clang-format off
--#define DOCTEST_SCENARIO(name) TEST_CASE(" Scenario: " name)
--#define DOCTEST_GIVEN(name) SUBCASE(" Given: " name)
--#define DOCTEST_WHEN(name) SUBCASE(" When: " name)
--#define DOCTEST_AND_WHEN(name) SUBCASE("And when: " name)
--#define DOCTEST_THEN(name) SUBCASE(" Then: " name)
--#define DOCTEST_AND_THEN(name) SUBCASE(" And: " name)
--// clang-format on
--
--// == SHORT VERSIONS OF THE MACROS
--#if !defined(DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES)
--
--#define TEST_CASE DOCTEST_TEST_CASE
--#define TEST_CASE_FIXTURE DOCTEST_TEST_CASE_FIXTURE
--#define SUBCASE DOCTEST_SUBCASE
--#define TEST_SUITE DOCTEST_TEST_SUITE
--#define TEST_SUITE_END DOCTEST_TEST_SUITE_END
--#define WARN DOCTEST_WARN
--#define WARN_FALSE DOCTEST_WARN_FALSE
--#define WARN_THROWS DOCTEST_WARN_THROWS
--#define WARN_THROWS_AS DOCTEST_WARN_THROWS_AS
--#define WARN_NOTHROW DOCTEST_WARN_NOTHROW
--#define CHECK DOCTEST_CHECK
--#define CHECK_FALSE DOCTEST_CHECK_FALSE
--#define CHECK_THROWS DOCTEST_CHECK_THROWS
--#define CHECK_THROWS_AS DOCTEST_CHECK_THROWS_AS
--#define CHECK_NOTHROW DOCTEST_CHECK_NOTHROW
--#define REQUIRE DOCTEST_REQUIRE
--#define REQUIRE_FALSE DOCTEST_REQUIRE_FALSE
--#define REQUIRE_THROWS DOCTEST_REQUIRE_THROWS
--#define REQUIRE_THROWS_AS DOCTEST_REQUIRE_THROWS_AS
--#define REQUIRE_NOTHROW DOCTEST_REQUIRE_NOTHROW
--
--#define SCENARIO DOCTEST_SCENARIO
--#define GIVEN DOCTEST_GIVEN
--#define WHEN DOCTEST_WHEN
--#define AND_WHEN DOCTEST_AND_WHEN
--#define THEN DOCTEST_THEN
--#define AND_THEN DOCTEST_AND_THEN
--
--#define WARN_EQ DOCTEST_WARN_EQ
--#define CHECK_EQ DOCTEST_CHECK_EQ
--#define REQUIRE_EQ DOCTEST_REQUIRE_EQ
--#define WARN_NE DOCTEST_WARN_NE
--#define CHECK_NE DOCTEST_CHECK_NE
--#define REQUIRE_NE DOCTEST_REQUIRE_NE
--#define WARN_GT DOCTEST_WARN_GT
--#define CHECK_GT DOCTEST_CHECK_GT
--#define REQUIRE_GT DOCTEST_REQUIRE_GT
--#define WARN_LT DOCTEST_WARN_LT
--#define CHECK_LT DOCTEST_CHECK_LT
--#define REQUIRE_LT DOCTEST_REQUIRE_LT
--#define WARN_GE DOCTEST_WARN_GE
--#define CHECK_GE DOCTEST_CHECK_GE
--#define REQUIRE_GE DOCTEST_REQUIRE_GE
--#define WARN_LE DOCTEST_WARN_LE
--#define CHECK_LE DOCTEST_CHECK_LE
--#define REQUIRE_LE DOCTEST_REQUIRE_LE
--#define WARN_UNARY DOCTEST_WARN_UNARY
--#define CHECK_UNARY DOCTEST_CHECK_UNARY
--#define REQUIRE_UNARY DOCTEST_REQUIRE_UNARY
--#define WARN_UNARY_FALSE DOCTEST_WARN_UNARY_FALSE
--#define CHECK_UNARY_FALSE DOCTEST_CHECK_UNARY_FALSE
--#define REQUIRE_UNARY_FALSE DOCTEST_REQUIRE_UNARY_FALSE
--
--#define FAST_WARN_EQ DOCTEST_FAST_WARN_EQ
--#define FAST_CHECK_EQ DOCTEST_FAST_CHECK_EQ
--#define FAST_REQUIRE_EQ DOCTEST_FAST_REQUIRE_EQ
--#define FAST_WARN_NE DOCTEST_FAST_WARN_NE
--#define FAST_CHECK_NE DOCTEST_FAST_CHECK_NE
--#define FAST_REQUIRE_NE DOCTEST_FAST_REQUIRE_NE
--#define FAST_WARN_GT DOCTEST_FAST_WARN_GT
--#define FAST_CHECK_GT DOCTEST_FAST_CHECK_GT
--#define FAST_REQUIRE_GT DOCTEST_FAST_REQUIRE_GT
--#define FAST_WARN_LT DOCTEST_FAST_WARN_LT
--#define FAST_CHECK_LT DOCTEST_FAST_CHECK_LT
--#define FAST_REQUIRE_LT DOCTEST_FAST_REQUIRE_LT
--#define FAST_WARN_GE DOCTEST_FAST_WARN_GE
--#define FAST_CHECK_GE DOCTEST_FAST_CHECK_GE
--#define FAST_REQUIRE_GE DOCTEST_FAST_REQUIRE_GE
--#define FAST_WARN_LE DOCTEST_FAST_WARN_LE
--#define FAST_CHECK_LE DOCTEST_FAST_CHECK_LE
--#define FAST_REQUIRE_LE DOCTEST_FAST_REQUIRE_LE
--#define FAST_WARN_UNARY DOCTEST_FAST_WARN_UNARY
--#define FAST_CHECK_UNARY DOCTEST_FAST_CHECK_UNARY
--#define FAST_REQUIRE_UNARY DOCTEST_FAST_REQUIRE_UNARY
--#define FAST_WARN_UNARY_FALSE DOCTEST_FAST_WARN_UNARY_FALSE
--#define FAST_CHECK_UNARY_FALSE DOCTEST_FAST_CHECK_UNARY_FALSE
--#define FAST_REQUIRE_UNARY_FALSE DOCTEST_FAST_REQUIRE_UNARY_FALSE
--
--#endif // DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES
--
--// this is here to clear the 'current test suite' for the current translation unit - at the top
--DOCTEST_TEST_SUITE_END();
--
--#endif // DOCTEST_LIBRARY_INCLUDED
--
--#if defined(__clang__)
--#pragma clang diagnostic pop
--#endif // __clang__
--
--#if defined(__GNUC__) && !defined(__clang__)
--#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6)
--#pragma GCC diagnostic pop
--#endif // > gcc 4.6
--#endif // __GNUC__
--
--#ifdef _MSC_VER
--#pragma warning(pop)
--#endif // _MSC_VER
--
--#ifndef DOCTEST_SINGLE_HEADER
--#define DOCTEST_SINGLE_HEADER
--#endif // DOCTEST_SINGLE_HEADER
--
--#if defined(__clang__)
--#pragma clang diagnostic push
--#pragma clang diagnostic ignored "-Wunknown-pragmas"
--#pragma clang diagnostic ignored "-Wpadded"
--#pragma clang diagnostic ignored "-Wglobal-constructors"
--#pragma clang diagnostic ignored "-Wexit-time-destructors"
--#pragma clang diagnostic ignored "-Wmissing-prototypes"
--#pragma clang diagnostic ignored "-Wsign-conversion"
--#pragma clang diagnostic ignored "-Wshorten-64-to-32"
--#pragma clang diagnostic ignored "-Wmissing-variable-declarations"
--#pragma clang diagnostic ignored "-Wswitch"
--#pragma clang diagnostic ignored "-Wswitch-enum"
--#pragma clang diagnostic ignored "-Wcovered-switch-default"
--#pragma clang diagnostic ignored "-Wmissing-noreturn"
--#pragma clang diagnostic ignored "-Wunused-local-typedef"
--#endif // __clang__
--
--#if defined(__GNUC__) && !defined(__clang__)
--#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6)
--#pragma GCC diagnostic push
--#endif // > gcc 4.6
--#pragma GCC diagnostic ignored "-Wunknown-pragmas"
--#pragma GCC diagnostic ignored "-Wconversion"
--#pragma GCC diagnostic ignored "-Weffc++"
--#pragma GCC diagnostic ignored "-Wsign-conversion"
--#pragma GCC diagnostic ignored "-Wstrict-overflow"
--#pragma GCC diagnostic ignored "-Wmissing-declarations"
--#pragma GCC diagnostic ignored "-Winline"
--#pragma GCC diagnostic ignored "-Wswitch"
--#pragma GCC diagnostic ignored "-Wswitch-enum"
--#pragma GCC diagnostic ignored "-Wswitch-default"
--#pragma GCC diagnostic ignored "-Wunsafe-loop-optimizations"
--#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6)
--#pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
--#endif // > gcc 4.6
--#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 7)
--#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
--#endif // > gcc 4.7
--#if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ > 3)
--#pragma GCC diagnostic ignored "-Wuseless-cast"
--#endif // > gcc 5.3
--#endif // __GNUC__
--
--#ifdef _MSC_VER
--#pragma warning(push)
--#pragma warning(disable : 4996) // The compiler encountered a deprecated declaration
--#pragma warning(disable : 4267) // 'var' : conversion from 'size_t' to 'type', possible loss of data
--#pragma warning(disable : 4706) // assignment within conditional expression
--#pragma warning(disable : 4512) // 'class' : assignment operator could not be generated
--#pragma warning(disable : 4127) // conditional expression is constant
--#pragma warning(disable : 4530) // C++ exception handler used, but unwind semantics are not enabled
--#pragma warning(disable : 4577) // 'noexcept' used with no exception handling mode specified
--#endif // _MSC_VER
--
--#if defined(DOCTEST_CONFIG_IMPLEMENT) || defined(DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN) || \
-- !defined(DOCTEST_SINGLE_HEADER)
--#ifndef DOCTEST_LIBRARY_IMPLEMENTATION
--#define DOCTEST_LIBRARY_IMPLEMENTATION
--
--#ifndef DOCTEST_SINGLE_HEADER
--#include "doctest_fwd.h"
--#endif // DOCTEST_SINGLE_HEADER
--
--#if defined(__clang__) && defined(DOCTEST_NO_CPP11_COMPAT)
--#pragma clang diagnostic ignored "-Wc++98-compat"
--#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
--#endif // __clang__ && DOCTEST_NO_CPP11_COMPAT
--
--// snprintf() not in the C++98 standard
--#ifdef _MSC_VER
--#define DOCTEST_SNPRINTF _snprintf
--#else
--#define DOCTEST_SNPRINTF snprintf
--#endif
--
--#define DOCTEST_LOG_START() \
-- do { \
-- if(!DOCTEST_GCS().hasLoggedCurrentTestStart) { \
-- doctest::detail::logTestStart(DOCTEST_GCS().currentTest->m_name, \
-- DOCTEST_GCS().currentTest->m_file, \
-- DOCTEST_GCS().currentTest->m_line); \
-- DOCTEST_GCS().hasLoggedCurrentTestStart = true; \
-- } \
-- } while(doctest::detail::always_false())
--
--// required includes - will go only in one translation unit!
--#include <ctime>
--#include <cmath>
--// borland (Embarcadero) compiler requires math.h and not cmath - https://github.com/onqtam/doctest/pull/37
--#ifdef __BORLANDC__
--#include <math.h>
--#endif // __BORLANDC__
--#include <new>
--#include <cstdio>
--#include <cstdlib>
--#include <cstring>
--#include <limits>
--#include <utility>
--#include <sstream>
--#include <iomanip>
--#include <vector>
--#include <set>
--
--namespace doctest
--{
--namespace detail
--{
-- // not using std::strlen() because of valgrind errors when optimizations are turned on
-- // 'Invalid read of size 4' when the test suite len (with '\0') is not a multiple of 4
-- // for details see http://stackoverflow.com/questions/35671155
-- size_t my_strlen(const char* in) {
-- const char* temp = in;
-- while(temp && *temp)
-- ++temp;
-- return temp - in;
-- }
--
-- template <typename T>
-- T my_max(const T& lhs, const T& rhs) {
-- return lhs > rhs ? lhs : rhs;
-- }
--
-- // case insensitive strcmp
-- int stricmp(char const* a, char const* b) {
-- for(;; a++, b++) {
-- int d = tolower(*a) - tolower(*b);
-- if(d != 0 || !*a)
-- return d;
-- }
-- }
--
-- template <typename T>
-- String fpToString(T value, int precision) {
-- std::ostringstream oss;
-- oss << std::setprecision(precision) << std::fixed << value;
-- std::string d = oss.str();
-- size_t i = d.find_last_not_of('0');
-- if(i != std::string::npos && i != d.size() - 1) {
-- if(d[i] == '.')
-- i++;
-- d = d.substr(0, i + 1);
-- }
-- return d.c_str();
-- }
--
-- struct Endianness
-- {
-- enum Arch
-- {
-- Big,
-- Little
-- };
--
-- static Arch which() {
-- union _
-- {
-- int asInt;
-- char asChar[sizeof(int)];
-- } u;
--
-- u.asInt = 1;
-- return (u.asChar[sizeof(int) - 1] == 1) ? Big : Little;
-- }
-- };
--
-- String rawMemoryToString(const void* object, unsigned size) {
-- // Reverse order for little endian architectures
-- int i = 0, end = static_cast<int>(size), inc = 1;
-- if(Endianness::which() == Endianness::Little) {
-- i = end - 1;
-- end = inc = -1;
-- }
--
-- unsigned char const* bytes = static_cast<unsigned char const*>(object);
-- std::ostringstream os;
-- os << "0x" << std::setfill('0') << std::hex;
-- for(; i != end; i += inc)
-- os << std::setw(2) << static_cast<unsigned>(bytes[i]);
-- return os.str().c_str();
-- }
--
-- std::ostream* createStream() { return new std::ostringstream(); }
-- String getStreamResult(std::ostream* in) {
-- return static_cast<std::ostringstream*>(in)->str().c_str();
-- }
-- void freeStream(std::ostream* in) { delete in; }
--
--#ifndef DOCTEST_CONFIG_DISABLE
--
-- // this holds both parameters for the command line and runtime data for tests
-- struct ContextState : TestAccessibleContextState
-- {
-- // == parameters from the command line
--
-- std::vector<std::vector<String> > filters;
--
-- String order_by; // how tests should be ordered
-- unsigned rand_seed; // the seed for rand ordering
--
-- unsigned first; // the first (matching) test to be executed
-- unsigned last; // the last (matching) test to be executed
--
-- int abort_after; // stop tests after this many failed assertions
-- bool case_sensitive; // if filtering should be case sensitive
-- bool exit; // if the program should be exited after the tests are ran/whatever
-- bool no_exitcode; // if the framework should return 0 as the exitcode
-- bool no_run; // to not run the tests at all (can be done with an "*" exclude)
-- bool no_version; // to not print the version of the framework
-- bool no_colors; // if output to the console should be colorized
-- bool no_path_in_filenames; // if the path to files should be removed from the output
--
-- bool help; // to print the help
-- bool version; // to print the version
-- bool count; // if only the count of matching tests is to be retreived
-- bool list_test_cases; // to list all tests matching the filters
-- bool list_test_suites; // to list all suites matching the filters
--
-- // == data for the tests being ran
--
-- int numAssertions;
-- int numFailedAssertions;
-- int numFailedAssertionsForCurrentTestcase;
--
-- // stuff for subcases
-- std::set<SubcaseSignature> subcasesPassed;
-- std::set<int> subcasesEnteredLevels;
-- std::vector<Subcase> subcasesStack;
-- int subcasesCurrentLevel;
-- bool subcasesHasSkipped;
--
-- void resetRunData() {
-- numAssertions = 0;
-- numFailedAssertions = 0;
-- }
--
-- ContextState()
-- : filters(6) // 6 different filters total
-- {
-- resetRunData();
-- }
-- };
--
-- ContextState*& getContextState();
--#endif // DOCTEST_CONFIG_DISABLE
--} // namespace detail
--
--String::String(const char* in)
-- : m_str(static_cast<char*>(malloc(detail::my_strlen(in) + 1))) {
-- if(in)
-- strcpy(m_str, in);
-- else
-- m_str[0] = '\0';
--}
--
--String::String(const String& other)
-- : m_str(0) {
-- copy(other);
--}
--
--void String::copy(const String& other) {
-- if(m_str)
-- free(m_str);
-- m_str = static_cast<char*>(malloc(detail::my_strlen(other.m_str) + 1));
-- strcpy(m_str, other.m_str);
--}
--
--String::~String() { free(m_str); }
--
--String& String::operator=(const String& other) {
-- if(this != &other)
-- copy(other);
-- return *this;
--}
--
--String String::operator+(const String& other) const { return String(m_str) += other; }
--
--String& String::operator+=(const String& other) {
-- using namespace detail;
-- if(other.m_str != 0) {
-- char* newStr = static_cast<char*>(malloc(my_strlen(m_str) + my_strlen(other.m_str) + 1));
-- strcpy(newStr, m_str);
-- strcpy(newStr + my_strlen(m_str), other.m_str);
-- free(m_str);
-- m_str = newStr;
-- }
-- return *this;
--}
--
--unsigned String::size() const { return m_str ? detail::my_strlen(m_str) : 0; }
--unsigned String::length() const { return size(); }
--
--int String::compare(const char* other, bool no_case) const {
-- if(no_case)
-- return detail::stricmp(m_str, other);
-- return strcmp(m_str, other);
--}
--
--int String::compare(const String& other, bool no_case) const {
-- if(no_case)
-- return detail::stricmp(m_str, other.m_str);
-- return strcmp(m_str, other.m_str);
--}
--
--std::ostream& operator<<(std::ostream& stream, const String& in) {
-- stream << in.c_str();
-- return stream;
--}
--
--Approx::Approx(double value)
-- : m_epsilon(static_cast<double>(std::numeric_limits<float>::epsilon()) * 100)
-- , m_scale(1.0)
-- , m_value(value) {}
--
--bool operator==(double lhs, Approx const& rhs) {
-- // Thanks to Richard Harris for his help refining this formula
-- return fabs(lhs - rhs.m_value) <
-- rhs.m_epsilon * (rhs.m_scale + detail::my_max(fabs(lhs), fabs(rhs.m_value)));
--}
--
--String Approx::toString() const { return String("Approx( ") + doctest::toString(m_value) + " )"; }
--
--#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
--String toString(char* in) { return toString(static_cast<const char*>(in)); }
--String toString(const char* in) { return String("\"") + (in ? in : "{null string}") + "\""; }
--#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
--String toString(bool in) { return in ? "true" : "false"; }
--String toString(float in) { return detail::fpToString(in, 5) + "f"; }
--String toString(double in) { return detail::fpToString(in, 10); }
--String toString(double long in) { return detail::fpToString(in, 15); }
--
--String toString(char in) {
-- char buf[64];
-- sprintf(buf, "%d", in);
-- return buf;
--}
--
--String toString(char unsigned in) {
-- char buf[64];
-- sprintf(buf, "%ud", in);
-- return buf;
--}
--
--String toString(int short in) {
-- char buf[64];
-- sprintf(buf, "%d", in);
-- return buf;
--}
--
--String toString(int short unsigned in) {
-- char buf[64];
-- sprintf(buf, "%u", in);
-- return buf;
--}
--
--String toString(int in) {
-- char buf[64];
-- sprintf(buf, "%d", in);
-- return buf;
--}
--
--String toString(int unsigned in) {
-- char buf[64];
-- sprintf(buf, "%u", in);
-- return buf;
--}
--
--String toString(int long in) {
-- char buf[64];
-- sprintf(buf, "%ld", in);
-- return buf;
--}
--
--String toString(int long unsigned in) {
-- char buf[64];
-- sprintf(buf, "%lu", in);
-- return buf;
--}
--
--#ifdef DOCTEST_CONFIG_WITH_LONG_LONG
--String toString(int long long in) {
-- char buf[64];
-- sprintf(buf, "%lld", in);
-- return buf;
--}
--String toString(int long long unsigned in) {
-- char buf[64];
-- sprintf(buf, "%llu", in);
-- return buf;
--}
--#endif // DOCTEST_CONFIG_WITH_LONG_LONG
--
--#ifdef DOCTEST_CONFIG_WITH_NULLPTR
--String toString(std::nullptr_t) { return "nullptr"; }
--#endif // DOCTEST_CONFIG_WITH_NULLPTR
--
--} // namespace doctest
--
--#if defined(DOCTEST_CONFIG_DISABLE)
--namespace doctest
--{
--Context::Context(int, const char* const*) {}
--Context::~Context() {}
--void Context::applyCommandLine(int, const char* const*) {}
--void Context::addFilter(const char*, const char*) {}
--void Context::clearFilters() {}
--void Context::setOption(const char*, int) {}
--void Context::setOption(const char*, const char*) {}
--bool Context::shouldExit() { return false; }
--int Context::run() { return 0; }
--} // namespace doctest
--#else // DOCTEST_CONFIG_DISABLE
--
--#if !defined(DOCTEST_CONFIG_COLORS_NONE)
--#if !defined(DOCTEST_CONFIG_COLORS_WINDOWS) && !defined(DOCTEST_CONFIG_COLORS_ANSI)
--#ifdef DOCTEST_PLATFORM_WINDOWS
--#define DOCTEST_CONFIG_COLORS_WINDOWS
--#else // linux
--#define DOCTEST_CONFIG_COLORS_ANSI
--#endif // platform
--#endif // DOCTEST_CONFIG_COLORS_WINDOWS && DOCTEST_CONFIG_COLORS_ANSI
--#endif // DOCTEST_CONFIG_COLORS_NONE
--
--#define DOCTEST_PRINTF_COLORED(buffer, color) \
-- do { \
-- if(buffer[0] != 0) { \
-- doctest::detail::Color col(color); \
-- printf("%s", buffer); \
-- } \
-- } while(doctest::detail::always_false())
--
--// the buffer size used for snprintf() calls
--#if !defined(DOCTEST_SNPRINTF_BUFFER_LENGTH)
--#define DOCTEST_SNPRINTF_BUFFER_LENGTH 1024
--#endif // DOCTEST_SNPRINTF_BUFFER_LENGTH
--
--#if defined(_MSC_VER) || defined(__MINGW32__)
--#if defined(_MSC_VER) && _MSC_VER >= 1700
--#define DOCTEST_WINDOWS_SAL_IN_OPT _In_opt_
--#else // _MSC_VER
--#define DOCTEST_WINDOWS_SAL_IN_OPT
--#endif // _MSC_VER
--extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA(
-- DOCTEST_WINDOWS_SAL_IN_OPT const char*);
--extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
--#endif // _MSC_VER || __MINGW32__
--
--#ifdef DOCTEST_CONFIG_COLORS_ANSI
--#include <unistd.h>
--#endif // DOCTEST_CONFIG_COLORS_ANSI
--
--#ifdef DOCTEST_CONFIG_COLORS_WINDOWS
--
--// defines for a leaner windows.h
--#ifndef WIN32_MEAN_AND_LEAN
--#define WIN32_MEAN_AND_LEAN
--#endif // WIN32_MEAN_AND_LEAN
--#ifndef VC_EXTRA_LEAN
--#define VC_EXTRA_LEAN
--#endif // VC_EXTRA_LEAN
--#ifndef NOMINMAX
--#define NOMINMAX
--#endif // NOMINMAX
--
--// not sure what AfxWin.h is for - here I do what Catch does
--#ifdef __AFXDLL
--#include <AfxWin.h>
--#else
--#include <windows.h>
--#endif
--
--#endif // DOCTEST_CONFIG_COLORS_WINDOWS
--
--namespace doctest
--{
--namespace detail
--{
-- bool TestData::operator<(const TestData& other) const {
-- if(m_line != other.m_line)
-- return m_line < other.m_line;
-- return strcmp(m_file, other.m_file) < 0;
-- }
--
-- const char* getAssertString(assertType::Enum val) {
-- switch(val) {
-- // clang-format off
-- case assertType::DT_WARN : return "WARN";
-- case assertType::DT_CHECK : return "CHECK";
-- case assertType::DT_REQUIRE : return "REQUIRE";
--
-- case assertType::DT_WARN_FALSE : return "WARN_FALSE";
-- case assertType::DT_CHECK_FALSE : return "CHECK_FALSE";
-- case assertType::DT_REQUIRE_FALSE : return "REQUIRE_FALSE";
--
-- case assertType::DT_WARN_THROWS : return "WARN_THROWS";
-- case assertType::DT_CHECK_THROWS : return "CHECK_THROWS";
-- case assertType::DT_REQUIRE_THROWS : return "REQUIRE_THROWS";
--
-- case assertType::DT_WARN_THROWS_AS : return "WARN_THROWS_AS";
-- case assertType::DT_CHECK_THROWS_AS : return "CHECK_THROWS_AS";
-- case assertType::DT_REQUIRE_THROWS_AS : return "REQUIRE_THROWS_AS";
--
-- case assertType::DT_WARN_NOTHROW : return "WARN_NOTHROW";
-- case assertType::DT_CHECK_NOTHROW : return "CHECK_NOTHROW";
-- case assertType::DT_REQUIRE_NOTHROW : return "REQUIRE_NOTHROW";
--
-- case assertType::DT_WARN_EQ : return "WARN_EQ";
-- case assertType::DT_CHECK_EQ : return "CHECK_EQ";
-- case assertType::DT_REQUIRE_EQ : return "REQUIRE_EQ";
-- case assertType::DT_WARN_NE : return "WARN_NE";
-- case assertType::DT_CHECK_NE : return "CHECK_NE";
-- case assertType::DT_REQUIRE_NE : return "REQUIRE_NE";
-- case assertType::DT_WARN_GT : return "WARN_GT";
-- case assertType::DT_CHECK_GT : return "CHECK_GT";
-- case assertType::DT_REQUIRE_GT : return "REQUIRE_GT";
-- case assertType::DT_WARN_LT : return "WARN_LT";
-- case assertType::DT_CHECK_LT : return "CHECK_LT";
-- case assertType::DT_REQUIRE_LT : return "REQUIRE_LT";
-- case assertType::DT_WARN_GE : return "WARN_GE";
-- case assertType::DT_CHECK_GE : return "CHECK_GE";
-- case assertType::DT_REQUIRE_GE : return "REQUIRE_GE";
-- case assertType::DT_WARN_LE : return "WARN_LE";
-- case assertType::DT_CHECK_LE : return "CHECK_LE";
-- case assertType::DT_REQUIRE_LE : return "REQUIRE_LE";
--
-- case assertType::DT_WARN_UNARY : return "WARN_UNARY";
-- case assertType::DT_CHECK_UNARY : return "CHECK_UNARY";
-- case assertType::DT_REQUIRE_UNARY : return "REQUIRE_UNARY";
-- case assertType::DT_WARN_UNARY_FALSE : return "WARN_UNARY_FALSE";
-- case assertType::DT_CHECK_UNARY_FALSE : return "CHECK_UNARY_FALSE";
-- case assertType::DT_REQUIRE_UNARY_FALSE : return "REQUIRE_UNARY_FALSE";
--
-- case assertType::DT_FAST_WARN_EQ : return "FAST_WARN_EQ";
-- case assertType::DT_FAST_CHECK_EQ : return "FAST_CHECK_EQ";
-- case assertType::DT_FAST_REQUIRE_EQ : return "FAST_REQUIRE_EQ";
-- case assertType::DT_FAST_WARN_NE : return "FAST_WARN_NE";
-- case assertType::DT_FAST_CHECK_NE : return "FAST_CHECK_NE";
-- case assertType::DT_FAST_REQUIRE_NE : return "FAST_REQUIRE_NE";
-- case assertType::DT_FAST_WARN_GT : return "FAST_WARN_GT";
-- case assertType::DT_FAST_CHECK_GT : return "FAST_CHECK_GT";
-- case assertType::DT_FAST_REQUIRE_GT : return "FAST_REQUIRE_GT";
-- case assertType::DT_FAST_WARN_LT : return "FAST_WARN_LT";
-- case assertType::DT_FAST_CHECK_LT : return "FAST_CHECK_LT";
-- case assertType::DT_FAST_REQUIRE_LT : return "FAST_REQUIRE_LT";
-- case assertType::DT_FAST_WARN_GE : return "FAST_WARN_GE";
-- case assertType::DT_FAST_CHECK_GE : return "FAST_CHECK_GE";
-- case assertType::DT_FAST_REQUIRE_GE : return "FAST_REQUIRE_GE";
-- case assertType::DT_FAST_WARN_LE : return "FAST_WARN_LE";
-- case assertType::DT_FAST_CHECK_LE : return "FAST_CHECK_LE";
-- case assertType::DT_FAST_REQUIRE_LE : return "FAST_REQUIRE_LE";
--
-- case assertType::DT_FAST_WARN_UNARY : return "FAST_WARN_UNARY";
-- case assertType::DT_FAST_CHECK_UNARY : return "FAST_CHECK_UNARY";
-- case assertType::DT_FAST_REQUIRE_UNARY : return "FAST_REQUIRE_UNARY";
-- case assertType::DT_FAST_WARN_UNARY_FALSE : return "FAST_WARN_UNARY_FALSE";
-- case assertType::DT_FAST_CHECK_UNARY_FALSE : return "FAST_CHECK_UNARY_FALSE";
-- case assertType::DT_FAST_REQUIRE_UNARY_FALSE: return "FAST_REQUIRE_UNARY_FALSE";
-- // clang-format on
-- }
-- return "";
-- }
--
-- bool checkIfShouldThrow(assertType::Enum assert_type) {
-- if(assert_type & assertType::is_require)
-- return true;
--
-- if((assert_type & assertType::is_check) && getContextState()->abort_after > 0) {
-- if(getContextState()->numFailedAssertions >= getContextState()->abort_after)
-- return true;
-- }
--
-- return false;
-- }
-- void fastAssertThrowIfFlagSet(int flags) {
-- if(flags & assertAction::shouldthrow)
-- throwException();
-- }
-- void throwException() {
--#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
-- throw TestFailureException();
--#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
-- }
-- bool always_false() { return false; }
--
-- // lowers ascii letters
-- char tolower(const char c) { return ((c >= 'A' && c <= 'Z') ? static_cast<char>(c + 32) : c); }
--
-- // matching of a string against a wildcard mask (case sensitivity configurable) taken from
-- // http://www.emoticode.net/c/simple-wildcard-string-compare-globbing-function.html
-- int wildcmp(const char* str, const char* wild, bool caseSensitive) {
-- const char* cp = 0;
-- const char* mp = 0;
--
-- // rolled my own tolower() to not include more headers
-- while((*str) && (*wild != '*')) {
-- if((caseSensitive ? (*wild != *str) : (tolower(*wild) != tolower(*str))) &&
-- (*wild != '?')) {
-- return 0;
-- }
-- wild++;
-- str++;
-- }
--
-- while(*str) {
-- if(*wild == '*') {
-- if(!*++wild) {
-- return 1;
-- }
-- mp = wild;
-- cp = str + 1;
-- } else if((caseSensitive ? (*wild == *str) : (tolower(*wild) == tolower(*str))) ||
-- (*wild == '?')) {
-- wild++;
-- str++;
-- } else {
-- wild = mp;
-- str = cp++;
-- }
-- }
--
-- while(*wild == '*') {
-- wild++;
-- }
-- return !*wild;
-- }
--
-- //// C string hash function (djb2) - taken from http://www.cse.yorku.ca/~oz/hash.html
-- //unsigned hashStr(unsigned const char* str) {
-- // unsigned long hash = 5381;
-- // char c;
-- // while((c = *str++))
-- // hash = ((hash << 5) + hash) + c; // hash * 33 + c
-- // return hash;
-- //}
--
-- // checks if the name matches any of the filters (and can be configured what to do when empty)
-- int matchesAny(const char* name, std::vector<String> filters, int matchEmpty,
-- bool caseSensitive) {
-- if(filters.size() == 0 && matchEmpty)
-- return 1;
-- for(unsigned i = 0; i < filters.size(); ++i)
-- if(wildcmp(name, filters[i].c_str(), caseSensitive))
-- return 1;
-- return 0;
-- }
--
-- // the current ContextState with which tests are being executed
-- ContextState*& getContextState() {
-- static ContextState* data = 0;
-- return data;
-- }
--
-- TestAccessibleContextState* getTestsContextState() { return getContextState(); }
--
-- bool SubcaseSignature::operator<(const SubcaseSignature& other) const {
-- if(m_line != other.m_line)
-- return m_line < other.m_line;
-- if(strcmp(m_file, other.m_file) != 0)
-- return strcmp(m_file, other.m_file) < 0;
-- return strcmp(m_name, other.m_name) < 0;
-- }
--
-- Subcase::Subcase(const char* name, const char* file, int line)
-- : m_signature(name, file, line)
-- , m_entered(false) {
-- ContextState* s = getContextState();
--
-- // if we have already completed it
-- if(s->subcasesPassed.count(m_signature) != 0)
-- return;
--
-- // if a Subcase on the same level has already been entered
-- if(s->subcasesEnteredLevels.count(s->subcasesCurrentLevel) != 0) {
-- s->subcasesHasSkipped = true;
-- return;
-- }
--
-- s->subcasesStack.push_back(*this);
-- if(s->hasLoggedCurrentTestStart)
-- logTestEnd();
-- s->hasLoggedCurrentTestStart = false;
--
-- s->subcasesEnteredLevels.insert(s->subcasesCurrentLevel++);
-- m_entered = true;
-- }
--
-- Subcase::Subcase(const Subcase& other)
-- : m_signature(other.m_signature.m_name, other.m_signature.m_file,
-- other.m_signature.m_line)
-- , m_entered(other.m_entered) {}
--
-- Subcase::~Subcase() {
-- if(m_entered) {
-- ContextState* s = getContextState();
--
-- s->subcasesCurrentLevel--;
-- // only mark the subcase as passed if no subcases have been skipped
-- if(s->subcasesHasSkipped == false)
-- s->subcasesPassed.insert(m_signature);
--
-- if(s->subcasesStack.size() > 0)
-- s->subcasesStack.pop_back();
-- if(s->hasLoggedCurrentTestStart)
-- logTestEnd();
-- s->hasLoggedCurrentTestStart = false;
-- }
-- }
--
-- // for sorting tests by file/line
-- int fileOrderComparator(const void* a, const void* b) {
-- const TestData* lhs = *static_cast<TestData* const*>(a);
-- const TestData* rhs = *static_cast<TestData* const*>(b);
--#ifdef _MSC_VER
-- // this is needed because MSVC gives different case for drive letters
-- // for __FILE__ when evaluated in a header and a source file
-- int res = stricmp(lhs->m_file, rhs->m_file);
--#else // _MSC_VER
-- int res = strcmp(lhs->m_file, rhs->m_file);
--#endif // _MSC_VER
-- if(res != 0)
-- return res;
-- return static_cast<int>(lhs->m_line - rhs->m_line);
-- }
--
-- // for sorting tests by suite/file/line
-- int suiteOrderComparator(const void* a, const void* b) {
-- const TestData* lhs = *static_cast<TestData* const*>(a);
-- const TestData* rhs = *static_cast<TestData* const*>(b);
--
-- int res = strcmp(lhs->m_suite, rhs->m_suite);
-- if(res != 0)
-- return res;
-- return fileOrderComparator(a, b);
-- }
--
-- // for sorting tests by name/suite/file/line
-- int nameOrderComparator(const void* a, const void* b) {
-- const TestData* lhs = *static_cast<TestData* const*>(a);
-- const TestData* rhs = *static_cast<TestData* const*>(b);
--
-- int res = strcmp(lhs->m_name, rhs->m_name);
-- if(res != 0)
-- return res;
-- return suiteOrderComparator(a, b);
-- }
--
-- // holds the current test suite
-- const char*& getCurrentTestSuite() {
-- static const char* data = 0;
-- return data;
-- }
--
-- // sets the current test suite
-- int setTestSuiteName(const char* name) {
-- getCurrentTestSuite() = name;
-- return 0;
-- }
--
-- // all the registered tests
-- std::set<TestData>& getRegisteredTests() {
-- static std::set<TestData> data;
-- return data;
-- }
--
-- // used by the macros for registering tests
-- int regTest(funcType f, unsigned line, const char* file, const char* name) {
-- getRegisteredTests().insert(TestData(getCurrentTestSuite(), name, f, file, line));
-- return 0;
-- }
--
-- struct Color
-- {
-- enum Code
-- {
-- None = 0,
-- White,
-- Red,
-- Green,
-- Blue,
-- Cyan,
-- Yellow,
-- Grey,
--
-- Bright = 0x10,
--
-- BrightRed = Bright | Red,
-- BrightGreen = Bright | Green,
-- LightGrey = Bright | Grey,
-- BrightWhite = Bright | White
-- };
-- Color(Code code) { use(code); }
-- ~Color() { use(None); }
--
-- void use(Code code);
--
-- private:
-- Color(Color const& other);
-- };
--
-- void Color::use(Code
--#ifndef DOCTEST_CONFIG_COLORS_NONE
-- code
--#endif // DOCTEST_CONFIG_COLORS_NONE
-- ) {
-- ContextState* p = getContextState();
-- if(p->no_colors)
-- return;
--#ifdef DOCTEST_CONFIG_COLORS_ANSI
-- if(isatty(STDOUT_FILENO)) {
-- const char* col = "";
-- // clang-format off
-- switch(code) {
-- case Color::Red: col = "[0;31m"; break;
-- case Color::Green: col = "[0;32m"; break;
-- case Color::Blue: col = "[0;34m"; break;
-- case Color::Cyan: col = "[0;36m"; break;
-- case Color::Yellow: col = "[0;33m"; break;
-- case Color::Grey: col = "[1;30m"; break;
-- case Color::LightGrey: col = "[0;37m"; break;
-- case Color::BrightRed: col = "[1;31m"; break;
-- case Color::BrightGreen: col = "[1;32m"; break;
-- case Color::BrightWhite: col = "[1;37m"; break;
-- case Color::Bright: // invalid
-- case Color::None:
-- case Color::White:
-- default: col = "[0m";
-- }
-- // clang-format on
-- printf("\033%s", col);
-- }
--#endif // DOCTEST_CONFIG_COLORS_ANSI
--
--#ifdef DOCTEST_CONFIG_COLORS_WINDOWS
-- static HANDLE stdoutHandle(GetStdHandle(STD_OUTPUT_HANDLE));
-- static WORD originalForegroundAttributes;
-- static WORD originalBackgroundAttributes;
-- static bool attrsInitted = false;
-- if(!attrsInitted) {
-- attrsInitted = true;
-- CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
-- GetConsoleScreenBufferInfo(stdoutHandle, &csbiInfo);
-- originalForegroundAttributes =
-- csbiInfo.wAttributes &
-- ~(BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY);
-- originalBackgroundAttributes =
-- csbiInfo.wAttributes &
-- ~(FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
-- }
--
--#define DOCTEST_SET_ATTR(x) SetConsoleTextAttribute(stdoutHandle, x | originalBackgroundAttributes)
--
-- // clang-format off
-- switch (code) {
-- case Color::White: DOCTEST_SET_ATTR(FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE); break;
-- case Color::Red: DOCTEST_SET_ATTR(FOREGROUND_RED); break;
-- case Color::Green: DOCTEST_SET_ATTR(FOREGROUND_GREEN); break;
-- case Color::Blue: DOCTEST_SET_ATTR(FOREGROUND_BLUE); break;
-- case Color::Cyan: DOCTEST_SET_ATTR(FOREGROUND_BLUE | FOREGROUND_GREEN); break;
-- case Color::Yellow: DOCTEST_SET_ATTR(FOREGROUND_RED | FOREGROUND_GREEN); break;
-- case Color::Grey: DOCTEST_SET_ATTR(0); break;
-- case Color::LightGrey: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY); break;
-- case Color::BrightRed: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_RED); break;
-- case Color::BrightGreen: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_GREEN); break;
-- case Color::BrightWhite: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE); break;
-- case Color::None:
-- case Color::Bright: // invalid
-- default: DOCTEST_SET_ATTR(originalForegroundAttributes);
-- }
--// clang-format on
--#undef DOCTEST_SET_ATTR
--#endif // DOCTEST_CONFIG_COLORS_WINDOWS
-- }
--
-- // this is needed because MSVC does not permit mixing 2 exception handling schemes in a function
-- int callTestFunc(funcType f) {
-- int res = EXIT_SUCCESS;
--#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
-- try {
--#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
-- f();
-- if(getContextState()->numFailedAssertionsForCurrentTestcase)
-- res = EXIT_FAILURE;
--#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
-- } catch(const TestFailureException&) { res = EXIT_FAILURE; } catch(...) {
-- DOCTEST_LOG_START();
-- logTestCrashed();
-- res = EXIT_FAILURE;
-- }
--#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
-- return res;
-- }
--
-- // depending on the current options this will remove the path of filenames
-- const char* fileForOutput(const char* file) {
-- if(getContextState()->no_path_in_filenames) {
-- const char* back = strrchr(file, '\\');
-- const char* forward = strrchr(file, '/');
-- if(back || forward) {
-- if(back > forward)
-- forward = back;
-- return forward + 1;
-- }
-- }
-- return file;
-- }
--
--#ifdef DOCTEST_PLATFORM_MAC
--#include <sys/types.h>
--#include <unistd.h>
--#include <sys/sysctl.h>
-- // The following function is taken directly from the following technical note:
-- // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
-- // Returns true if the current process is being debugged (either
-- // running under the debugger or has a debugger attached post facto).
-- bool isDebuggerActive() {
-- int mib[4];
-- struct kinfo_proc info;
-- size_t size;
-- // Initialize the flags so that, if sysctl fails for some bizarre
-- // reason, we get a predictable result.
-- info.kp_proc.p_flag = 0;
-- // Initialize mib, which tells sysctl the info we want, in this case
-- // we're looking for information about a specific process ID.
-- mib[0] = CTL_KERN;
-- mib[1] = KERN_PROC;
-- mib[2] = KERN_PROC_PID;
-- mib[3] = getpid();
-- // Call sysctl.
-- size = sizeof(info);
-- if(sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, 0, 0) != 0) {
-- fprintf(stderr, "\n** Call to sysctl failed - unable to determine if debugger is "
-- "active **\n\n");
-- return false;
-- }
-- // We're being debugged if the P_TRACED flag is set.
-- return ((info.kp_proc.p_flag & P_TRACED) != 0);
-- }
--#elif defined(_MSC_VER) || defined(__MINGW32__)
-- bool isDebuggerActive() { return ::IsDebuggerPresent() != 0; }
--#else
-- bool isDebuggerActive() { return false; }
--#endif // Platform
--
--#ifdef DOCTEST_PLATFORM_WINDOWS
-- void myOutputDebugString(const String& text) { ::OutputDebugStringA(text.c_str()); }
--#else
-- // TODO: integration with XCode and other IDEs
-- void myOutputDebugString(const String&) {}
--#endif // Platform
--
-- const char* getSeparator() {
-- return "===============================================================================\n";
-- }
--
-- void printToDebugConsole(const String& text) {
-- if(isDebuggerActive())
-- myOutputDebugString(text.c_str());
-- }
--
-- void addFailedAssert(assertType::Enum assert_type) {
-- if((assert_type & assertType::is_warn) == 0) {
-- getContextState()->numFailedAssertionsForCurrentTestcase++;
-- getContextState()->numFailedAssertions++;
-- }
-- }
--
-- void logTestStart(const char* name, const char* file, unsigned line) {
-- const char* newLine = "\n";
--
-- char loc[DOCTEST_SNPRINTF_BUFFER_LENGTH];
-- DOCTEST_SNPRINTF(loc, DOCTEST_COUNTOF(loc), "%s(%d)\n", fileForOutput(file), line);
--
-- char msg[DOCTEST_SNPRINTF_BUFFER_LENGTH];
-- DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), "%s\n", name);
--
-- DOCTEST_PRINTF_COLORED(getSeparator(), Color::Yellow);
-- DOCTEST_PRINTF_COLORED(loc, Color::LightGrey);
-- DOCTEST_PRINTF_COLORED(msg, Color::None);
--
-- String subcaseStuff = "";
-- std::vector<Subcase>& subcasesStack = getContextState()->subcasesStack;
-- for(unsigned i = 0; i < subcasesStack.size(); ++i) {
-- char subcase[DOCTEST_SNPRINTF_BUFFER_LENGTH];
-- DOCTEST_SNPRINTF(subcase, DOCTEST_COUNTOF(loc), " %s\n",
-- subcasesStack[i].m_signature.m_name);
-- DOCTEST_PRINTF_COLORED(subcase, Color::None);
-- subcaseStuff += subcase;
-- }
--
-- DOCTEST_PRINTF_COLORED(newLine, Color::None);
--
-- printToDebugConsole(String(getSeparator()) + loc + msg + subcaseStuff.c_str() + newLine);
-- }
--
-- void logTestEnd() {}
--
-- void logTestCrashed() {
-- char msg[DOCTEST_SNPRINTF_BUFFER_LENGTH];
--
-- DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), "TEST CASE FAILED! (threw exception)\n\n");
--
-- DOCTEST_PRINTF_COLORED(msg, Color::Red);
--
-- printToDebugConsole(String(msg));
-- }
--
-- void logAssert(bool passed, const char* decomposition, bool threw, const char* expr,
-- assertType::Enum assert_type, const char* file, int line) {
-- char loc[DOCTEST_SNPRINTF_BUFFER_LENGTH];
-- DOCTEST_SNPRINTF(loc, DOCTEST_COUNTOF(loc), "%s(%d)", fileForOutput(file), line);
--
-- char msg[DOCTEST_SNPRINTF_BUFFER_LENGTH];
-- if(passed)
-- DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), " PASSED!\n");
-- else
-- DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), " FAILED! %s\n",
-- (threw ? "(threw exception)" : ""));
--
-- char info1[DOCTEST_SNPRINTF_BUFFER_LENGTH];
-- DOCTEST_SNPRINTF(info1, DOCTEST_COUNTOF(info1), " %s( %s )\n",
-- getAssertString(assert_type), expr);
--
-- char info2[DOCTEST_SNPRINTF_BUFFER_LENGTH];
-- char info3[DOCTEST_SNPRINTF_BUFFER_LENGTH];
-- info2[0] = 0;
-- info3[0] = 0;
-- if(!threw) {
-- DOCTEST_SNPRINTF(info2, DOCTEST_COUNTOF(info2), "with expansion:\n");
-- DOCTEST_SNPRINTF(info3, DOCTEST_COUNTOF(info3), " %s( %s )\n",
-- getAssertString(assert_type), decomposition);
-- }
--
-- DOCTEST_PRINTF_COLORED(loc, Color::LightGrey);
-- DOCTEST_PRINTF_COLORED(msg, passed ? Color::BrightGreen : Color::Red);
-- DOCTEST_PRINTF_COLORED(info1, Color::Cyan);
-- DOCTEST_PRINTF_COLORED(info2, Color::None);
-- DOCTEST_PRINTF_COLORED(info3, Color::Cyan);
-- DOCTEST_PRINTF_COLORED("\n", Color::None);
--
-- printToDebugConsole(String(loc) + msg + info1 + info2 + info3 + "\n");
-- }
--
-- void logAssertThrows(bool threw, const char* expr, assertType::Enum assert_type,
-- const char* file, int line) {
-- char loc[DOCTEST_SNPRINTF_BUFFER_LENGTH];
-- DOCTEST_SNPRINTF(loc, DOCTEST_COUNTOF(loc), "%s(%d)", fileForOutput(file), line);
--
-- char msg[DOCTEST_SNPRINTF_BUFFER_LENGTH];
-- if(threw)
-- DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), " PASSED!\n");
-- else
-- DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), " FAILED!\n");
--
-- char info1[DOCTEST_SNPRINTF_BUFFER_LENGTH];
-- DOCTEST_SNPRINTF(info1, DOCTEST_COUNTOF(info1), " %s( %s )\n\n",
-- getAssertString(assert_type), expr);
--
-- DOCTEST_PRINTF_COLORED(loc, Color::LightGrey);
-- DOCTEST_PRINTF_COLORED(msg, threw ? Color::BrightGreen : Color::Red);
-- DOCTEST_PRINTF_COLORED(info1, Color::Cyan);
--
-- printToDebugConsole(String(loc) + msg + info1);
-- }
--
-- void logAssertThrowsAs(bool threw, bool threw_as, const char* as, const char* expr,
-- assertType::Enum assert_type, const char* file, int line) {
-- char loc[DOCTEST_SNPRINTF_BUFFER_LENGTH];
-- DOCTEST_SNPRINTF(loc, DOCTEST_COUNTOF(loc), "%s(%d)", fileForOutput(file), line);
--
-- char msg[DOCTEST_SNPRINTF_BUFFER_LENGTH];
-- if(threw_as)
-- DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), " PASSED!\n");
-- else
-- DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), " FAILED! %s\n",
-- (threw ? "(threw something else)" : "(didn't throw at all)"));
--
-- char info1[DOCTEST_SNPRINTF_BUFFER_LENGTH];
-- DOCTEST_SNPRINTF(info1, DOCTEST_COUNTOF(info1), " %s( %s, %s )\n\n",
-- getAssertString(assert_type), expr, as);
--
-- DOCTEST_PRINTF_COLORED(loc, Color::LightGrey);
-- DOCTEST_PRINTF_COLORED(msg, threw_as ? Color::BrightGreen : Color::Red);
-- DOCTEST_PRINTF_COLORED(info1, Color::Cyan);
--
-- printToDebugConsole(String(loc) + msg + info1);
-- }
--
-- void logAssertNothrow(bool threw, const char* expr, assertType::Enum assert_type,
-- const char* file, int line) {
-- char loc[DOCTEST_SNPRINTF_BUFFER_LENGTH];
-- DOCTEST_SNPRINTF(loc, DOCTEST_COUNTOF(loc), "%s(%d)", fileForOutput(file), line);
--
-- char msg[DOCTEST_SNPRINTF_BUFFER_LENGTH];
-- if(!threw)
-- DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), " PASSED!\n");
-- else
-- DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), " FAILED!\n");
--
-- char info1[DOCTEST_SNPRINTF_BUFFER_LENGTH];
-- DOCTEST_SNPRINTF(info1, DOCTEST_COUNTOF(info1), " %s( %s )\n\n",
-- getAssertString(assert_type), expr);
--
-- DOCTEST_PRINTF_COLORED(loc, Color::LightGrey);
-- DOCTEST_PRINTF_COLORED(msg, !threw ? Color::BrightGreen : Color::Red);
-- DOCTEST_PRINTF_COLORED(info1, Color::Cyan);
--
-- printToDebugConsole(String(loc) + msg + info1);
-- }
--
-- ResultBuilder::ResultBuilder(assertType::Enum assert_type, const char* file, int line,
-- const char* expr, const char* exception_type)
-- : m_assert_type(assert_type)
-- , m_file(file)
-- , m_line(line)
-- , m_expr(expr)
-- , m_exception_type(exception_type)
-- , m_threw(false)
-- , m_threw_as(false)
-- , m_failed(false) {}
--
-- bool ResultBuilder::log() {
-- if((m_assert_type & assertType::is_warn) == 0)
-- DOCTEST_GCS().numAssertionsForCurrentTestcase++;
--
-- if(m_assert_type & assertType::is_false) {
-- m_result.invert();
-- m_failed = m_result;
-- } else if(m_assert_type & assertType::is_throws) {
-- m_failed = !m_threw;
-- } else if(m_assert_type & assertType::is_throws_as) {
-- m_failed = !m_threw_as;
-- } else if(m_assert_type & assertType::is_nothrow) {
-- m_failed = m_threw;
-- } else {
-- m_failed = m_result;
-- }
--
-- if(m_failed || DOCTEST_GCS().success) {
-- DOCTEST_LOG_START();
--
-- if(m_assert_type & assertType::is_throws) {
-- logAssertThrows(m_threw, m_expr, m_assert_type, m_file, m_line);
-- } else if(m_assert_type & assertType::is_throws_as) {
-- logAssertThrowsAs(m_threw, m_threw_as, m_exception_type, m_expr, m_assert_type,
-- m_file, m_line);
-- } else if(m_assert_type & assertType::is_nothrow) {
-- logAssertNothrow(m_threw, m_expr, m_assert_type, m_file, m_line);
-- } else {
-- logAssert(m_result.m_passed, m_result.m_decomposition.c_str(), m_threw, m_expr,
-- m_assert_type, m_file, m_line);
-- }
-- }
--
-- if(m_failed) {
-- addFailedAssert(m_assert_type);
-- if(isDebuggerActive() && !DOCTEST_GCS().no_breaks)
-- return true; // should break into the debugger
-- }
-- return false;
-- }
--
-- void ResultBuilder::react() const {
-- if(m_failed && checkIfShouldThrow(m_assert_type))
-- throwException();
-- }
--
-- // the implementation of parseFlag()
-- bool parseFlagImpl(int argc, const char* const* argv, const char* pattern) {
-- for(int i = argc - 1; i >= 0; --i) {
-- const char* temp = strstr(argv[i], pattern);
-- if(temp && my_strlen(temp) == my_strlen(pattern)) {
-- // eliminate strings in which the chars before the option are not '-'
-- bool noBadCharsFound = true;
-- while(temp != argv[i]) {
-- if(*--temp != '-') {
-- noBadCharsFound = false;
-- break;
-- }
-- }
-- if(noBadCharsFound && argv[i][0] == '-')
-- return true;
-- }
-- }
-- return false;
-- }
--
-- // locates a flag on the command line
-- bool parseFlag(int argc, const char* const* argv, const char* pattern) {
--#ifndef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
-- if(!parseFlagImpl(argc, argv, pattern))
-- return parseFlagImpl(argc, argv, pattern + 3); // 3 for "dt-"
-- return true;
--#else // DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
-- return parseFlagImpl(argc, argv, pattern);
--#endif // DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
-- }
--
-- // the implementation of parseOption()
-- bool parseOptionImpl(int argc, const char* const* argv, const char* pattern, String& res) {
-- for(int i = argc - 1; i >= 0; --i) {
-- const char* temp = strstr(argv[i], pattern);
-- if(temp) {
-- // eliminate matches in which the chars before the option are not '-'
-- bool noBadCharsFound = true;
-- const char* curr = argv[i];
-- while(curr != temp) {
-- if(*curr++ != '-') {
-- noBadCharsFound = false;
-- break;
-- }
-- }
-- if(noBadCharsFound && argv[i][0] == '-') {
-- temp += my_strlen(pattern);
-- unsigned len = my_strlen(temp);
-- if(len) {
-- res = temp;
-- return true;
-- }
-- }
-- }
-- }
-- return false;
-- }
--
-- // parses an option and returns the string after the '=' character
-- bool parseOption(int argc, const char* const* argv, const char* pattern, String& res,
-- const String& defaultVal = String()) {
-- res = defaultVal;
--#ifndef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
-- if(!parseOptionImpl(argc, argv, pattern, res))
-- return parseOptionImpl(argc, argv, pattern + 3, res); // 3 for "dt-"
-- return true;
--#else // DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
-- return parseOptionImpl(argc, argv, pattern, res);
--#endif // DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
-- }
--
-- // parses a comma separated list of words after a pattern in one of the arguments in argv
-- bool parseCommaSepArgs(int argc, const char* const* argv, const char* pattern,
-- std::vector<String>& res) {
-- String filtersString;
-- if(parseOption(argc, argv, pattern, filtersString)) {
-- // tokenize with "," as a separator
-- char* pch = strtok(filtersString.c_str(), ","); // modifies the string
-- while(pch != 0) {
-- if(my_strlen(pch))
-- res.push_back(pch);
-- pch = strtok(0, ","); // uses the strtok() internal state to go to the next token
-- }
-- return true;
-- }
-- return false;
-- }
--
-- enum optionType
-- {
-- option_bool,
-- option_int
-- };
--
-- // parses an int/bool option from the command line
-- bool parseIntOption(int argc, const char* const* argv, const char* pattern, optionType type,
-- int& res) {
-- String parsedValue;
-- if(parseOption(argc, argv, pattern, parsedValue)) {
-- if(type == 0) {
-- // boolean
-- const char positive[][5] = {"1", "true", "on", "yes"}; // 5 - strlen("true") + 1
-- const char negative[][6] = {"0", "false", "off", "no"}; // 6 - strlen("false") + 1
--
-- // if the value matches any of the positive/negative possibilities
-- for(unsigned i = 0; i < 4; i++) {
-- if(parsedValue.compare(positive[i], true) == 0) {
-- res = 1;
-- return true;
-- }
-- if(parsedValue.compare(negative[i], true) == 0) {
-- res = 0;
-- return true;
-- }
-- }
-- } else {
-- // integer
-- int theInt = atoi(parsedValue.c_str());
-- if(theInt != 0) {
-- res = theInt;
-- return true;
-- }
-- }
-- }
-- return false;
-- }
--
-- void printVersion() {
-- if(getContextState()->no_version == false) {
-- DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
-- printf("doctest version is \"%s\"\n", DOCTEST_VERSION_STR);
-- }
-- }
--
-- void printHelp() {
-- printVersion();
-- DOCTEST_PRINTF_COLORED("[doctest]\n", Color::Cyan);
-- DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
-- printf("boolean values: \"1/on/yes/true\" or \"0/off/no/false\"\n");
-- DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
-- printf("filter values: \"str1,str2,str3\" (comma separated strings)\n");
-- DOCTEST_PRINTF_COLORED("[doctest]\n", Color::Cyan);
-- DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
-- printf("filters use wildcards for matching strings\n");
-- DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
-- printf("something passes a filter if any of the strings in a filter matches\n");
-- DOCTEST_PRINTF_COLORED("[doctest]\n", Color::Cyan);
-- DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
-- printf("ALL FLAGS, OPTIONS AND FILTERS ALSO AVAILABLE WITH A \"dt-\" PREFIX!!!\n");
-- DOCTEST_PRINTF_COLORED("[doctest]\n", Color::Cyan);
-- DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
-- printf("Query flags - the program quits after them. Available:\n\n");
-- printf(" -?, --help, -h prints this message\n");
-- printf(" -v, --version prints the version\n");
-- printf(" -c, --count prints the number of matching tests\n");
-- printf(" -ltc, --list-test-cases lists all matching tests by name\n");
-- printf(" -lts, --list-test-suites lists all matching test suites\n\n");
-- // ==================================================================================== << 79
-- DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
-- printf("The available <int>/<string> options/filters are:\n\n");
-- printf(" -tc, --test-case=<filters> filters tests by their name\n");
-- printf(" -tce, --test-case-exclude=<filters> filters OUT tests by their name\n");
-- printf(" -sf, --source-file=<filters> filters tests by their file\n");
-- printf(" -sfe, --source-file-exclude=<filters> filters OUT tests by their file\n");
-- printf(" -ts, --test-suite=<filters> filters tests by their test suite\n");
-- printf(" -tse, --test-suite-exclude=<filters> filters OUT tests by their test suite\n");
-- printf(" -ob, --order-by=<string> how the tests should be ordered\n");
-- printf(" <string> - by [file/suite/name/rand]\n");
-- printf(" -rs, --rand-seed=<int> seed for random ordering\n");
-- printf(" -f, --first=<int> the first test passing the filters to\n");
-- printf(" execute - for range-based execution\n");
-- printf(" -l, --last=<int> the last test passing the filters to\n");
-- printf(" execute - for range-based execution\n");
-- printf(" -aa, --abort-after=<int> stop after <int> failed assertions\n\n");
-- DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
-- printf("Bool options - can be used like flags and true is assumed. Available:\n\n");
-- printf(" -s, --success=<bool> include successful assertions in output\n");
-- printf(" -cs, --case-sensitive=<bool> filters being treated as case sensitive\n");
-- printf(" -e, --exit=<bool> exits after the tests finish\n");
-- printf(" -nt, --no-throw=<bool> skips exceptions-related assert checks\n");
-- printf(" -ne, --no-exitcode=<bool> returns (or exits) always with success\n");
-- printf(" -nr, --no-run=<bool> skips all runtime doctest operations\n");
-- printf(" -nv, --no-version=<bool> omit the framework version in the output\n");
-- printf(" -nc, --no-colors=<bool> disables colors in output\n");
-- printf(" -nb, --no-breaks=<bool> disables breakpoints in debuggers\n");
-- printf(" -npf, --no-path-filenames=<bool> only filenames and no paths in output\n\n");
-- // ==================================================================================== << 79
--
-- DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
-- printf("for more information visit the project documentation\n\n");
-- }
--} // namespace detail
--
--Context::Context(int argc, const char* const* argv)
-- : p(new detail::ContextState) {
-- parseArgs(argc, argv, true);
--}
--
--Context::~Context() { delete p; }
--
--void Context::applyCommandLine(int argc, const char* const* argv) { parseArgs(argc, argv); }
--
--// parses args
--void Context::parseArgs(int argc, const char* const* argv, bool withDefaults) {
-- using namespace detail;
--
-- // clang-format off
-- parseCommaSepArgs(argc, argv, "dt-source-file=", p->filters[0]);
-- parseCommaSepArgs(argc, argv, "dt-sf=", p->filters[0]);
-- parseCommaSepArgs(argc, argv, "dt-source-file-exclude=",p->filters[1]);
-- parseCommaSepArgs(argc, argv, "dt-sfe=", p->filters[1]);
-- parseCommaSepArgs(argc, argv, "dt-test-suite=", p->filters[2]);
-- parseCommaSepArgs(argc, argv, "dt-ts=", p->filters[2]);
-- parseCommaSepArgs(argc, argv, "dt-test-suite-exclude=", p->filters[3]);
-- parseCommaSepArgs(argc, argv, "dt-tse=", p->filters[3]);
-- parseCommaSepArgs(argc, argv, "dt-test-case=", p->filters[4]);
-- parseCommaSepArgs(argc, argv, "dt-tc=", p->filters[4]);
-- parseCommaSepArgs(argc, argv, "dt-test-case-exclude=", p->filters[5]);
-- parseCommaSepArgs(argc, argv, "dt-tce=", p->filters[5]);
-- // clang-format on
--
-- int intRes = 0;
-- String strRes;
--
--#define DOCTEST_PARSE_AS_BOOL_OR_FLAG(name, sname, var, default) \
-- if(parseIntOption(argc, argv, DOCTEST_STR_CONCAT_TOSTR(name, =), option_bool, intRes) || \
-- parseIntOption(argc, argv, DOCTEST_STR_CONCAT_TOSTR(sname, =), option_bool, intRes)) \
-- p->var = !!intRes; \
-- else if(parseFlag(argc, argv, #name) || parseFlag(argc, argv, #sname)) \
-- p->var = 1; \
-- else if(withDefaults) \
-- p->var = default
--
--#define DOCTEST_PARSE_INT_OPTION(name, sname, var, default) \
-- if(parseIntOption(argc, argv, DOCTEST_STR_CONCAT_TOSTR(name, =), option_int, intRes) || \
-- parseIntOption(argc, argv, DOCTEST_STR_CONCAT_TOSTR(sname, =), option_int, intRes)) \
-- p->var = intRes; \
-- else if(withDefaults) \
-- p->var = default
--
--#define DOCTEST_PARSE_STR_OPTION(name, sname, var, default) \
-- if(parseOption(argc, argv, DOCTEST_STR_CONCAT_TOSTR(name, =), strRes, default) || \
-- parseOption(argc, argv, DOCTEST_STR_CONCAT_TOSTR(sname, =), strRes, default) || \
-- withDefaults) \
-- p->var = strRes
--
-- // clang-format off
-- DOCTEST_PARSE_STR_OPTION(dt-order-by, dt-ob, order_by, "file");
-- DOCTEST_PARSE_INT_OPTION(dt-rand-seed, dt-rs, rand_seed, 0);
--
-- DOCTEST_PARSE_INT_OPTION(dt-first, dt-f, first, 1);
-- DOCTEST_PARSE_INT_OPTION(dt-last, dt-l, last, 0);
--
-- DOCTEST_PARSE_INT_OPTION(dt-abort-after, dt-aa, abort_after, 0);
--
-- DOCTEST_PARSE_AS_BOOL_OR_FLAG(dt-success, dt-s, success, 0);
-- DOCTEST_PARSE_AS_BOOL_OR_FLAG(dt-case-sensitive, dt-cs, case_sensitive, 0);
-- DOCTEST_PARSE_AS_BOOL_OR_FLAG(dt-exit, dt-e, exit, 0);
-- DOCTEST_PARSE_AS_BOOL_OR_FLAG(dt-no-throw, dt-nt, no_throw, 0);
-- DOCTEST_PARSE_AS_BOOL_OR_FLAG(dt-no-exitcode, dt-ne, no_exitcode, 0);
-- DOCTEST_PARSE_AS_BOOL_OR_FLAG(dt-no-run, dt-nr, no_run, 0);
-- DOCTEST_PARSE_AS_BOOL_OR_FLAG(dt-no-version, dt-nv, no_version, 0);
-- DOCTEST_PARSE_AS_BOOL_OR_FLAG(dt-no-colors, dt-nc, no_colors, 0);
-- DOCTEST_PARSE_AS_BOOL_OR_FLAG(dt-no-breaks, dt-nb, no_breaks, 0);
-- DOCTEST_PARSE_AS_BOOL_OR_FLAG(dt-no-path-filenames, dt-npf, no_path_in_filenames, 0);
--// clang-format on
--
--#undef DOCTEST_PARSE_STR_OPTION
--#undef DOCTEST_PARSE_INT_OPTION
--#undef DOCTEST_PARSE_AS_BOOL_OR_FLAG
--
-- if(withDefaults) {
-- p->help = false;
-- p->version = false;
-- p->count = false;
-- p->list_test_cases = false;
-- p->list_test_suites = false;
-- }
-- if(parseFlag(argc, argv, "dt-help") || parseFlag(argc, argv, "dt-h") ||
-- parseFlag(argc, argv, "dt-?")) {
-- p->help = true;
-- p->exit = true;
-- }
-- if(parseFlag(argc, argv, "dt-version") || parseFlag(argc, argv, "dt-v")) {
-- p->version = true;
-- p->exit = true;
-- }
-- if(parseFlag(argc, argv, "dt-count") || parseFlag(argc, argv, "dt-c")) {
-- p->count = true;
-- p->exit = true;
-- }
-- if(parseFlag(argc, argv, "dt-list-test-cases") || parseFlag(argc, argv, "dt-ltc")) {
-- p->list_test_cases = true;
-- p->exit = true;
-- }
-- if(parseFlag(argc, argv, "dt-list-test-suites") || parseFlag(argc, argv, "dt-lts")) {
-- p->list_test_suites = true;
-- p->exit = true;
-- }
--}
--
--// allows the user to add procedurally to the filters from the command line
--void Context::addFilter(const char* filter, const char* value) { setOption(filter, value); }
--
--// allows the user to clear all filters from the command line
--void Context::clearFilters() {
-- for(unsigned i = 0; i < p->filters.size(); ++i)
-- p->filters[i].clear();
--}
--
--// allows the user to override procedurally the int/bool options from the command line
--void Context::setOption(const char* option, int value) {
-- setOption(option, toString(value).c_str());
--}
--
--// allows the user to override procedurally the string options from the command line
--void Context::setOption(const char* option, const char* value) {
-- String argv = String("-") + option + "=" + value;
-- const char* lvalue = argv.c_str();
-- parseArgs(1, &lvalue);
--}
--
--// users should query this in their main() and exit the program if true
--bool Context::shouldExit() { return p->exit; }
--
--// the main function that does all the filtering and test running
--int Context::run() {
-- using namespace detail;
--
-- getContextState() = p;
-- p->resetRunData();
--
-- // handle version, help and no_run
-- if(p->no_run || p->version || p->help) {
-- if(p->version)
-- printVersion();
-- if(p->help)
-- printHelp();
--
-- getContextState() = 0;
--
-- return EXIT_SUCCESS;
-- }
--
-- printVersion();
-- DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
-- printf("run with \"--help\" for options\n");
--
-- unsigned i = 0; // counter used for loops - here for VC6
--
-- std::set<TestData>& registeredTests = getRegisteredTests();
--
-- std::vector<const TestData*> testArray;
-- for(std::set<TestData>::iterator it = registeredTests.begin(); it != registeredTests.end();
-- ++it)
-- testArray.push_back(&(*it));
--
-- // sort the collected records
-- if(testArray.size() > 0) {
-- if(p->order_by.compare("file", true) == 0) {
-- qsort(&testArray[0], testArray.size(), sizeof(TestData*), fileOrderComparator);
-- } else if(p->order_by.compare("suite", true) == 0) {
-- qsort(&testArray[0], testArray.size(), sizeof(TestData*), suiteOrderComparator);
-- } else if(p->order_by.compare("name", true) == 0) {
-- qsort(&testArray[0], testArray.size(), sizeof(TestData*), nameOrderComparator);
-- } else if(p->order_by.compare("rand", true) == 0) {
-- srand(p->rand_seed);
--
-- // random_shuffle implementation
-- const TestData** first = &testArray[0];
-- for(i = testArray.size() - 1; i > 0; --i) {
-- int idxToSwap = rand() % (i + 1);
--
-- const TestData* temp = first[i];
--
-- first[i] = first[idxToSwap];
-- first[idxToSwap] = temp;
-- }
-- }
-- }
--
-- if(p->list_test_cases) {
-- DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
-- printf("listing all test case names\n");
-- }
--
-- std::set<String> testSuitesPassingFilters;
-- if(p->list_test_suites) {
-- DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
-- printf("listing all test suites\n");
-- }
--
-- unsigned numTestsPassingFilters = 0;
-- unsigned numFailed = 0;
-- // invoke the registered functions if they match the filter criteria (or just count them)
-- for(i = 0; i < testArray.size(); i++) {
-- const TestData& data = *testArray[i];
-- if(!matchesAny(data.m_file, p->filters[0], 1, p->case_sensitive))
-- continue;
-- if(matchesAny(data.m_file, p->filters[1], 0, p->case_sensitive))
-- continue;
-- if(!matchesAny(data.m_suite, p->filters[2], 1, p->case_sensitive))
-- continue;
-- if(matchesAny(data.m_suite, p->filters[3], 0, p->case_sensitive))
-- continue;
-- if(!matchesAny(data.m_name, p->filters[4], 1, p->case_sensitive))
-- continue;
-- if(matchesAny(data.m_name, p->filters[5], 0, p->case_sensitive))
-- continue;
--
-- numTestsPassingFilters++;
--
-- // do not execute the test if we are to only count the number of filter passing tests
-- if(p->count)
-- continue;
--
-- // print the name of the test and don't execute it
-- if(p->list_test_cases) {
-- printf("%s\n", data.m_name);
-- continue;
-- }
--
-- // print the name of the test suite if not done already and don't execute it
-- if(p->list_test_suites) {
-- if(testSuitesPassingFilters.count(data.m_suite) == 0) {
-- printf("%s\n", data.m_suite);
-- testSuitesPassingFilters.insert(data.m_suite);
-- }
-- continue;
-- }
--
-- // skip the test if it is not in the execution range
-- if((p->last < numTestsPassingFilters && p->first <= p->last) ||
-- (p->first > numTestsPassingFilters))
-- continue;
--
-- // execute the test if it passes all the filtering
-- {
--#ifdef _MSC_VER
--//__try {
--#endif // _MSC_VER
--
-- p->currentTest = &data;
--
-- // if logging successful tests - force the start log
-- p->hasLoggedCurrentTestStart = false;
-- if(p->success)
-- DOCTEST_LOG_START();
--
-- unsigned didFail = 0;
-- p->subcasesPassed.clear();
-- do {
-- // reset the assertion state
-- p->numAssertionsForCurrentTestcase = 0;
-- p->numFailedAssertionsForCurrentTestcase = 0;
--
-- // reset some of the fields for subcases (except for the set of fully passed ones)
-- p->subcasesHasSkipped = false;
-- p->subcasesCurrentLevel = 0;
-- p->subcasesEnteredLevels.clear();
--
-- // execute the test
-- didFail += callTestFunc(data.m_f);
-- p->numAssertions += p->numAssertionsForCurrentTestcase;
--
-- // exit this loop if enough assertions have failed
-- if(p->abort_after > 0 && p->numFailedAssertions >= p->abort_after)
-- p->subcasesHasSkipped = false;
--
-- // if the start has been logged
-- if(p->hasLoggedCurrentTestStart)
-- logTestEnd();
-- p->hasLoggedCurrentTestStart = false;
--
-- } while(p->subcasesHasSkipped == true);
--
-- if(didFail > 0)
-- numFailed++;
--
-- // stop executing tests if enough assertions have failed
-- if(p->abort_after > 0 && p->numFailedAssertions >= p->abort_after)
-- break;
--
--#ifdef _MSC_VER
--//} __except(1) {
--// printf("Unknown SEH exception caught!\n");
--// numFailed++;
--//}
--#endif // _MSC_VER
-- }
-- }
--
-- DOCTEST_PRINTF_COLORED(getSeparator(), numFailed > 0 ? Color::Red : Color::Green);
-- if(p->count || p->list_test_cases || p->list_test_suites) {
-- DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
-- printf("number of tests passing the current filters: %d\n", numTestsPassingFilters);
-- } else {
-- char buff[DOCTEST_SNPRINTF_BUFFER_LENGTH];
--
-- DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
--
-- DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), "test cases: %4d", numTestsPassingFilters);
-- DOCTEST_PRINTF_COLORED(buff, Color::None);
-- DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), " | ");
-- DOCTEST_PRINTF_COLORED(buff, Color::None);
-- DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), "%4d passed",
-- numTestsPassingFilters - numFailed);
-- DOCTEST_PRINTF_COLORED(buff, numFailed > 0 ? Color::None : Color::Green);
-- DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), " | ");
-- DOCTEST_PRINTF_COLORED(buff, Color::None);
-- DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), "%4d failed", numFailed);
-- DOCTEST_PRINTF_COLORED(buff, numFailed > 0 ? Color::Red : Color::None);
--
-- DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), " | ");
-- DOCTEST_PRINTF_COLORED(buff, Color::None);
-- DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), "%4d skipped\n",
-- static_cast<unsigned>(testArray.size()) - numTestsPassingFilters);
-- DOCTEST_PRINTF_COLORED(buff, Color::None);
--
-- DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
--
-- DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), "assertions: %4d", p->numAssertions);
-- DOCTEST_PRINTF_COLORED(buff, Color::None);
-- DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), " | ");
-- DOCTEST_PRINTF_COLORED(buff, Color::None);
-- DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), "%4d passed",
-- p->numAssertions - p->numFailedAssertions);
-- DOCTEST_PRINTF_COLORED(buff, numFailed > 0 ? Color::None : Color::Green);
-- DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), " | ");
-- DOCTEST_PRINTF_COLORED(buff, Color::None);
-- DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), "%4d failed", p->numFailedAssertions);
-- DOCTEST_PRINTF_COLORED(buff, p->numFailedAssertions > 0 ? Color::Red : Color::None);
--
-- DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), " |\n");
-- DOCTEST_PRINTF_COLORED(buff, Color::None);
-- }
--
-- // remove any coloring
-- DOCTEST_PRINTF_COLORED("", Color::None);
--
-- getContextState() = 0;
--
-- if(numFailed && !p->no_exitcode)
-- return EXIT_FAILURE;
-- return EXIT_SUCCESS;
--}
--} // namespace doctest
--
--#endif // DOCTEST_CONFIG_DISABLE
--#endif // DOCTEST_LIBRARY_IMPLEMENTATION
--#endif // DOCTEST_CONFIG_IMPLEMENT
--
--// == THIS SUPPLIES A MAIN FUNCTION AND SHOULD BE DONE ONLY IN ONE TRANSLATION UNIT
--#if defined(DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN) && !defined(DOCTEST_MAIN_CONFIGURED)
--#define DOCTEST_MAIN_CONFIGURED
--int main(int argc, char** argv) { return doctest::Context(argc, argv).run(); }
--#endif // DOCTEST_MAIN_CONFIGURED
--
--#if defined(__clang__)
--#pragma clang diagnostic pop
--#endif // __clang__
--
--#if defined(__GNUC__) && !defined(__clang__)
--#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6)
--#pragma GCC diagnostic pop
--#endif // > gcc 4.6
--#endif // __GNUC__
--
--#ifdef _MSC_VER
--#pragma warning(pop)
--#endif // _MSC_VER
-diff --git a/test/test.cpp b/test/test.cpp
-index d68b8af..354f209 100644
---- a/test/test.cpp
-+++ b/test/test.cpp
-@@ -1,7 +1,7 @@
- #include "../include/argagg/argagg.hpp"
-
- #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
--#include "doctest.h"
-+#include "doctest/doctest.h"
-
- #include <cstring>
- #include <iostream>
diff --git a/debian/patches/0002-Make-the-build-reproducible.patch b/debian/patches/0002-Make-the-build-reproducible.patch
deleted file mode 100644
index c360d54..0000000
--- a/debian/patches/0002-Make-the-build-reproducible.patch
+++ /dev/null
@@ -1,23 +0,0 @@
-From aab16b5aaba58aaa431f9e40f77c814a4369904e Mon Sep 17 00:00:00 2001
-From: Chris Lamb <lamby@debian.org>
-Date: Mon, 23 Oct 2017 08:06:28 +0200
-Subject: Make the build reproducible
-
-Closes: #879569
----
- doc/doxygen.cfg.in | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/doc/doxygen.cfg.in b/doc/doxygen.cfg.in
-index 129d32c..7fa0a3e 100644
---- a/doc/doxygen.cfg.in
-+++ b/doc/doxygen.cfg.in
-@@ -14,7 +14,7 @@ REPEAT_BRIEF = YES
- ABBREVIATE_BRIEF =
- ALWAYS_DETAILED_SEC = NO
- INLINE_INHERITED_MEMB = NO
--FULL_PATH_NAMES = YES
-+FULL_PATH_NAMES = NO
- STRIP_FROM_PATH =
- STRIP_FROM_INC_PATH =
- SHORT_NAMES = NO
diff --git a/debian/patches/series b/debian/patches/series
deleted file mode 100644
index fa163d1..0000000
--- a/debian/patches/series
+++ /dev/null
@@ -1,2 +0,0 @@
-0001-Make-sure-to-use-the-system-s-doctest.patch
-0002-Make-the-build-reproducible.patch
diff --git a/doc/doxygen.cfg.in b/doc/doxygen.cfg.in
index 7fa0a3e..129d32c 100644
--- a/doc/doxygen.cfg.in
+++ b/doc/doxygen.cfg.in
@@ -14,7 +14,7 @@ REPEAT_BRIEF = YES
ABBREVIATE_BRIEF =
ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = NO
-FULL_PATH_NAMES = NO
+FULL_PATH_NAMES = YES
STRIP_FROM_PATH =
STRIP_FROM_INC_PATH =
SHORT_NAMES = NO
diff --git a/test/doctest.h b/test/doctest.h
new file mode 100644
index 0000000..fe0a601
--- /dev/null
+++ b/test/doctest.h
@@ -0,0 +1,3461 @@
+// ======================================================================
+// == DO NOT MODIFY THIS FILE BY HAND - IT IS AUTO GENERATED BY CMAKE! ==
+// ======================================================================
+//
+// doctest.h - the lightest feature-rich C++ single-header testing framework for unit tests and TDD
+//
+// Copyright (c) 2016 Viktor Kirilov
+//
+// Distributed under the MIT Software License
+// See accompanying file LICENSE.txt or copy at
+// https://opensource.org/licenses/MIT
+//
+// The documentation can be found at the library's page:
+// https://github.com/onqtam/doctest/blob/master/doc/markdown/readme.md
+//
+// =================================================================================================
+// =================================================================================================
+// =================================================================================================
+//
+// The library is heavily influenced by Catch - https://github.com/philsquared/Catch
+// which uses the Boost Software License - Version 1.0
+// see here - https://github.com/philsquared/Catch/blob/master/LICENSE_1_0.txt
+//
+// The concept of subcases (sections in Catch) and expression decomposition are from there.
+// Some parts of the code are taken directly:
+// - stringification - the detection of "ostream& operator<<(ostream&, const T&)" and StringMaker<>
+// - the Approx() helper class for floating point comparison
+// - colors in the console
+// - breaking into a debugger
+//
+// The expression decomposing templates are taken from lest - https://github.com/martinmoene/lest
+// which uses the Boost Software License - Version 1.0
+// see here - https://github.com/martinmoene/lest/blob/master/LICENSE_1_0.txt
+//
+// =================================================================================================
+// =================================================================================================
+// =================================================================================================
+
+// Suppress this globally (without push/pop) - there is no way to silence it in the
+// expression decomposition macros _Pragma() in macros doesn't work for the c++ front-end of g++
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55578
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69543
+// Also the warning is completely worthless nowadays - http://stackoverflow.com/questions/14016993
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic ignored "-Waggregate-return"
+#endif
+
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunknown-pragmas"
+#pragma clang diagnostic ignored "-Wpadded"
+#pragma clang diagnostic ignored "-Wmissing-prototypes"
+#pragma clang diagnostic ignored "-Wshorten-64-to-32"
+#pragma clang diagnostic ignored "-Wunused-local-typedef"
+#endif // __clang__
+
+#if defined(__GNUC__) && !defined(__clang__)
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6)
+#pragma GCC diagnostic push
+#endif // > gcc 4.6
+#pragma GCC diagnostic ignored "-Wunknown-pragmas"
+#pragma GCC diagnostic ignored "-Weffc++"
+#pragma GCC diagnostic ignored "-Wstrict-overflow"
+#pragma GCC diagnostic ignored "-Wmissing-declarations"
+#pragma GCC diagnostic ignored "-Winline"
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6)
+#pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
+#endif // > gcc 4.6
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 7)
+#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
+#endif // > gcc 4.7
+#if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ > 3)
+#pragma GCC diagnostic ignored "-Wuseless-cast"
+#endif // > gcc 5.3
+#endif // __GNUC__
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 4996) // The compiler encountered a deprecated declaration
+#pragma warning(disable : 4706) // assignment within conditional expression
+#pragma warning(disable : 4512) // 'class' : assignment operator could not be generated
+#pragma warning(disable : 4127) // conditional expression is constant
+#endif // _MSC_VER
+
+#ifndef DOCTEST_LIBRARY_INCLUDED
+#define DOCTEST_LIBRARY_INCLUDED
+
+#define DOCTEST_VERSION_MAJOR 1
+#define DOCTEST_VERSION_MINOR 1
+#define DOCTEST_VERSION_PATCH 3
+#define DOCTEST_VERSION_STR "1.1.3"
+
+#define DOCTEST_VERSION \
+ (DOCTEST_VERSION_MAJOR * 10000 + DOCTEST_VERSION_MINOR * 100 + DOCTEST_VERSION_PATCH)
+
+// =================================================================================================
+// == MODERN C++ FEATURE DETECTION =================================================================
+// =================================================================================================
+
+#if __cplusplus >= 201103L
+#ifndef DOCTEST_CONFIG_WITH_NULLPTR
+#define DOCTEST_CONFIG_WITH_NULLPTR
+#endif // DOCTEST_CONFIG_WITH_NULLPTR
+#ifndef DOCTEST_CONFIG_WITH_LONG_LONG
+#define DOCTEST_CONFIG_WITH_LONG_LONG
+#endif // DOCTEST_CONFIG_WITH_LONG_LONG
+#ifndef DOCTEST_CONFIG_WITH_STATIC_ASSERT
+#define DOCTEST_CONFIG_WITH_STATIC_ASSERT
+#endif // DOCTEST_CONFIG_WITH_STATIC_ASSERT
+#endif // __cplusplus >= 201103L
+
+// nullptr
+
+#ifndef DOCTEST_CONFIG_WITH_NULLPTR
+#ifdef __clang__
+#if __has_feature(cxx_nullptr)
+#define DOCTEST_CONFIG_WITH_NULLPTR
+#endif // __has_feature(cxx_nullptr)
+#endif // __clang__
+
+#if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
+#define DOCTEST_CONFIG_WITH_NULLPTR
+#endif // __GNUC__
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1600) // MSVC 2010
+#define DOCTEST_CONFIG_WITH_NULLPTR
+#endif // _MSC_VER
+#endif // DOCTEST_CONFIG_WITH_NULLPTR
+
+#if defined(DOCTEST_CONFIG_NO_NULLPTR) && defined(DOCTEST_CONFIG_WITH_NULLPTR)
+#undef DOCTEST_CONFIG_WITH_NULLPTR
+#endif // DOCTEST_CONFIG_NO_NULLPTR
+
+// long long
+
+#ifndef DOCTEST_CONFIG_WITH_LONG_LONG
+#if !defined(DOCTEST_CONFIG_WITH_LONG_LONG) && defined(_MSC_VER) && (_MSC_VER >= 1400)
+#define DOCTEST_CONFIG_WITH_LONG_LONG
+#endif // _MSC_VER
+#endif // DOCTEST_CONFIG_WITH_LONG_LONG
+
+#if defined(DOCTEST_CONFIG_NO_LONG_LONG) && defined(DOCTEST_CONFIG_WITH_LONG_LONG)
+#undef DOCTEST_CONFIG_WITH_LONG_LONG
+#endif // DOCTEST_CONFIG_NO_LONG_LONG
+
+// static_assert
+
+#ifndef DOCTEST_CONFIG_WITH_STATIC_ASSERT
+#ifdef __clang__
+#if __has_feature(cxx_static_assert)
+#define DOCTEST_CONFIG_WITH_STATIC_ASSERT
+#endif // __has_feature(cxx_static_assert)
+#endif // __clang__
+
+#if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ >= 3 && defined(__GXX_EXPERIMENTAL_CXX0X__)
+#define DOCTEST_CONFIG_WITH_STATIC_ASSERT
+#endif // __GNUC__
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1600) // MSVC 2010
+#define DOCTEST_CONFIG_WITH_STATIC_ASSERT
+#endif // _MSC_VER
+#endif // DOCTEST_CONFIG_WITH_STATIC_ASSERT
+
+#if defined(DOCTEST_CONFIG_NO_STATIC_ASSERT) && defined(DOCTEST_CONFIG_WITH_STATIC_ASSERT)
+#undef DOCTEST_CONFIG_WITH_STATIC_ASSERT
+#endif // DOCTEST_CONFIG_NO_STATIC_ASSERT
+
+#if defined(DOCTEST_CONFIG_WITH_NULLPTR) || defined(DOCTEST_CONFIG_WITH_LONG_LONG) || \
+ defined(DOCTEST_CONFIG_WITH_STATIC_ASSERT)
+#define DOCTEST_NO_CPP11_COMPAT
+#endif // c++11 stuff
+
+#if defined(__clang__) && defined(DOCTEST_NO_CPP11_COMPAT)
+#pragma clang diagnostic ignored "-Wc++98-compat"
+#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
+#endif // __clang__ && DOCTEST_NO_CPP11_COMPAT
+
+#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
+#if defined(__GNUC__) && !defined(__EXCEPTIONS)
+#define DOCTEST_CONFIG_NO_EXCEPTIONS
+#endif // clang and gcc
+// in MSVC _HAS_EXCEPTIONS is defined in a header instead of as a project define
+// so we can't do the automatic detection for MSVC without including some header
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
+
+#if defined(DOCTEST_CONFIG_NO_EXCEPTIONS) && !defined(DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS)
+#define DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS && !DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
+
+// =================================================================================================
+// == MODERN C++ FEATURE DETECTION END =============================================================
+// =================================================================================================
+
+// internal macros for string concatenation and anonymous variable name generation
+#define DOCTEST_CAT_IMPL(s1, s2) s1##s2
+#define DOCTEST_CAT(s1, s2) DOCTEST_CAT_IMPL(s1, s2)
+#ifdef __COUNTER__ // not standard and may be missing for some compilers
+#define DOCTEST_ANONYMOUS(x) DOCTEST_CAT(x, __COUNTER__)
+#else // __COUNTER__
+#define DOCTEST_ANONYMOUS(x) DOCTEST_CAT(x, __LINE__)
+#endif // __COUNTER__
+
+// macro for making a string out of an identifier
+#define DOCTEST_TOSTR_IMPL(x) #x
+#define DOCTEST_TOSTR(x) DOCTEST_TOSTR_IMPL(x)
+
+// for concatenating literals and making the result a string
+#define DOCTEST_STR_CONCAT_TOSTR(s1, s2) DOCTEST_TOSTR(s1) DOCTEST_TOSTR(s2)
+
+// counts the number of elements in a C string
+#define DOCTEST_COUNTOF(x) (sizeof(x) / sizeof(x[0]))
+
+#ifndef DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE
+#define DOCTEST_REF_WRAP(x) x&
+#else // DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE
+#define DOCTEST_REF_WRAP(x) x
+#endif // DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE
+
+// not using __APPLE__ because... this is how Catch does it
+#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
+#define DOCTEST_PLATFORM_MAC
+#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
+#define DOCTEST_PLATFORM_IPHONE
+#elif defined(_WIN32) || defined(_MSC_VER)
+#define DOCTEST_PLATFORM_WINDOWS
+#else
+#define DOCTEST_PLATFORM_LINUX
+#endif
+
+#define DOCTEST_GCS() (*doctest::detail::getTestsContextState())
+
+// should probably take a look at https://github.com/scottt/debugbreak
+#ifdef DOCTEST_PLATFORM_MAC
+// The following code snippet based on:
+// http://cocoawithlove.com/2008/03/break-into-debugger.html
+#if defined(__ppc64__) || defined(__ppc__)
+#define DOCTEST_BREAK_INTO_DEBUGGER() \
+ __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" : : : "memory", "r0", "r3", "r4")
+#else // __ppc64__ || __ppc__
+#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :)
+#endif // __ppc64__ || __ppc__
+#elif defined(_MSC_VER)
+#define DOCTEST_BREAK_INTO_DEBUGGER() __debugbreak()
+#elif defined(__MINGW32__)
+extern "C" __declspec(dllimport) void __stdcall DebugBreak();
+#define DOCTEST_BREAK_INTO_DEBUGGER() ::DebugBreak()
+#else // linux
+#define DOCTEST_BREAK_INTO_DEBUGGER() ((void)0)
+#endif // linux
+
+#define DOCTEST_BREAK_INTO_DEBUGGER_CHECKED() \
+ if(doctest::detail::isDebuggerActive() && !DOCTEST_GCS().no_breaks) \
+ DOCTEST_BREAK_INTO_DEBUGGER();
+
+#ifdef __clang__
+// to detect if libc++ is being used with clang (the _LIBCPP_VERSION identifier)
+#include <ciso646>
+#endif // __clang__
+
+#ifdef _LIBCPP_VERSION
+// not forward declaring ostream for libc++ because I had some problems (inline namespaces vs c++98)
+// so the <iosfwd> header is used - also it is very light and doesn't drag a ton of stuff
+#include <iosfwd>
+#else // _LIBCPP_VERSION
+#ifndef DOCTEST_CONFIG_USE_IOSFWD
+namespace std
+{
+template <class charT>
+struct char_traits;
+template <>
+struct char_traits<char>;
+template <class charT, class traits>
+class basic_ostream;
+typedef basic_ostream<char, char_traits<char> > ostream;
+}
+#else // DOCTEST_CONFIG_USE_IOSFWD
+#include <iosfwd>
+#endif // DOCTEST_CONFIG_USE_IOSFWD
+#endif // _LIBCPP_VERSION
+
+// static assert macro - because of the c++98 support requires that the message is an
+// identifier (no spaces and not a C string) - example without quotes: I_am_a_message
+// taken from here: http://stackoverflow.com/a/1980156/3162383
+#ifdef DOCTEST_CONFIG_WITH_STATIC_ASSERT
+#define DOCTEST_STATIC_ASSERT(expression, message) static_assert(expression, #message)
+#else // DOCTEST_CONFIG_WITH_STATIC_ASSERT
+#define DOCTEST_STATIC_ASSERT(expression, message) \
+ struct DOCTEST_CAT(__static_assertion_at_line_, __LINE__) \
+ { \
+ doctest::detail::static_assert_impl::StaticAssertion<static_cast<bool>((expression))> \
+ DOCTEST_CAT(DOCTEST_CAT(DOCTEST_CAT(STATIC_ASSERTION_FAILED_AT_LINE_, __LINE__), \
+ _), \
+ message); \
+ }; \
+ typedef doctest::detail::static_assert_impl::StaticAssertionTest<sizeof( \
+ DOCTEST_CAT(__static_assertion_at_line_, __LINE__))> \
+ DOCTEST_CAT(__static_assertion_test_at_line_, __LINE__)
+#endif // DOCTEST_CONFIG_WITH_STATIC_ASSERT
+
+#ifdef DOCTEST_CONFIG_WITH_NULLPTR
+#ifdef _LIBCPP_VERSION
+#include <cstddef>
+#else // _LIBCPP_VERSION
+namespace std
+{ typedef decltype(nullptr) nullptr_t; }
+#endif // _LIBCPP_VERSION
+#endif // DOCTEST_CONFIG_WITH_NULLPTR
+
+namespace doctest
+{
+class String
+{
+ char* m_str;
+
+ void copy(const String& other);
+
+public:
+ String(const char* in = "");
+ String(const String& other);
+ ~String();
+
+ String& operator=(const String& other);
+
+ String operator+(const String& other) const;
+ String& operator+=(const String& other);
+
+ char& operator[](unsigned pos) { return m_str[pos]; }
+ const char& operator[](unsigned pos) const { return m_str[pos]; }
+
+ char* c_str() { return m_str; }
+ const char* c_str() const { return m_str; }
+
+ unsigned size() const;
+ unsigned length() const;
+
+ int compare(const char* other, bool no_case = false) const;
+ int compare(const String& other, bool no_case = false) const;
+};
+
+// clang-format off
+inline bool operator==(const String& lhs, const String& rhs) { return lhs.compare(rhs) == 0; }
+inline bool operator!=(const String& lhs, const String& rhs) { return lhs.compare(rhs) != 0; }
+inline bool operator< (const String& lhs, const String& rhs) { return lhs.compare(rhs) < 0; }
+inline bool operator> (const String& lhs, const String& rhs) { return lhs.compare(rhs) > 0; }
+inline bool operator<=(const String& lhs, const String& rhs) { return (lhs != rhs) ? lhs.compare(rhs) < 0 : true; }
+inline bool operator>=(const String& lhs, const String& rhs) { return (lhs != rhs) ? lhs.compare(rhs) > 0 : true; }
+// clang-format on
+
+std::ostream& operator<<(std::ostream& stream, const String& in);
+
+namespace detail
+{
+#ifndef DOCTEST_CONFIG_WITH_STATIC_ASSERT
+ namespace static_assert_impl
+ {
+ template <bool>
+ struct StaticAssertion;
+
+ template <>
+ struct StaticAssertion<true>
+ {};
+
+ template <int i>
+ struct StaticAssertionTest
+ {};
+ } // namespace static_assert_impl
+#endif // DOCTEST_CONFIG_WITH_STATIC_ASSERT
+
+ template <typename T>
+ struct deferred_false
+ { static const bool value = false; };
+
+ namespace has_insertion_operator_impl
+ {
+ typedef char no;
+ typedef char yes[2];
+
+ struct any_t
+ {
+ template <typename T>
+ any_t(const DOCTEST_REF_WRAP(T));
+ };
+
+ yes& testStreamable(std::ostream&);
+ no testStreamable(no);
+
+ no operator<<(const std::ostream&, const any_t&);
+
+ template <typename T>
+ struct has_insertion_operator
+ {
+ static std::ostream& s;
+ static const DOCTEST_REF_WRAP(T) t;
+ static const bool value = sizeof(testStreamable(s << t)) == sizeof(yes);
+ };
+ } // namespace has_insertion_operator_impl
+
+ template <typename T>
+ struct has_insertion_operator : has_insertion_operator_impl::has_insertion_operator<T>
+ {};
+
+ std::ostream* createStream();
+ String getStreamResult(std::ostream*);
+ void freeStream(std::ostream*);
+
+ template <bool C>
+ struct StringMakerBase
+ {
+ template <typename T>
+ static String convert(const DOCTEST_REF_WRAP(T)) {
+ return "{?}";
+ }
+ };
+
+ template <>
+ struct StringMakerBase<true>
+ {
+ template <typename T>
+ static String convert(const DOCTEST_REF_WRAP(T) in) {
+ std::ostream* stream = createStream();
+ *stream << in;
+ String result = getStreamResult(stream);
+ freeStream(stream);
+ return result;
+ }
+ };
+
+ String rawMemoryToString(const void* object, unsigned size);
+
+ template <typename T>
+ String rawMemoryToString(const DOCTEST_REF_WRAP(T) object) {
+ return rawMemoryToString(&object, sizeof(object));
+ }
+} // namespace detail
+
+template <typename T>
+struct StringMaker : detail::StringMakerBase<detail::has_insertion_operator<T>::value>
+{};
+
+template <typename T>
+struct StringMaker<T*>
+{
+ template <typename U>
+ static String convert(U* p) {
+ if(!p)
+ return "NULL";
+ else
+ return detail::rawMemoryToString(p);
+ }
+};
+
+template <typename R, typename C>
+struct StringMaker<R C::*>
+{
+ static String convert(R C::*p) {
+ if(!p)
+ return "NULL";
+ else
+ return detail::rawMemoryToString(p);
+ }
+};
+
+template <typename T>
+String toString(const DOCTEST_REF_WRAP(T) value) {
+ return StringMaker<T>::convert(value);
+}
+
+#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+String toString(char* in);
+String toString(const char* in);
+#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+String toString(bool in);
+String toString(float in);
+String toString(double in);
+String toString(double long in);
+
+String toString(char in);
+String toString(char unsigned in);
+String toString(int short in);
+String toString(int short unsigned in);
+String toString(int in);
+String toString(int unsigned in);
+String toString(int long in);
+String toString(int long unsigned in);
+
+#ifdef DOCTEST_CONFIG_WITH_LONG_LONG
+String toString(int long long in);
+String toString(int long long unsigned in);
+#endif // DOCTEST_CONFIG_WITH_LONG_LONG
+
+#ifdef DOCTEST_CONFIG_WITH_NULLPTR
+String toString(std::nullptr_t in);
+#endif // DOCTEST_CONFIG_WITH_NULLPTR
+
+class Approx
+{
+public:
+ explicit Approx(double value);
+
+ Approx(Approx const& other)
+ : m_epsilon(other.m_epsilon)
+ , m_scale(other.m_scale)
+ , m_value(other.m_value) {}
+
+ Approx operator()(double value) {
+ Approx approx(value);
+ approx.epsilon(m_epsilon);
+ approx.scale(m_scale);
+ return approx;
+ }
+
+ friend bool operator==(double lhs, Approx const& rhs);
+ friend bool operator==(Approx const& lhs, double rhs) { return operator==(rhs, lhs); }
+ friend bool operator!=(double lhs, Approx const& rhs) { return !operator==(lhs, rhs); }
+ friend bool operator!=(Approx const& lhs, double rhs) { return !operator==(rhs, lhs); }
+
+ Approx& epsilon(double newEpsilon) {
+ m_epsilon = newEpsilon;
+ return *this;
+ }
+
+ Approx& scale(double newScale) {
+ m_scale = newScale;
+ return *this;
+ }
+
+ String toString() const;
+
+private:
+ double m_epsilon;
+ double m_scale;
+ double m_value;
+};
+
+template <>
+inline String toString<Approx>(const DOCTEST_REF_WRAP(Approx) value) {
+ return value.toString();
+}
+
+#if !defined(DOCTEST_CONFIG_DISABLE)
+
+namespace detail
+{
+ // the function type this library works with
+ typedef void (*funcType)(void);
+
+ namespace assertType
+ {
+ enum Enum
+ {
+ // macro traits
+
+ is_warn = 1,
+ is_check = 2,
+ is_require = 4,
+
+ is_throws = 8,
+ is_throws_as = 16,
+ is_nothrow = 32,
+
+ is_fast = 64, // not checked anywhere - used just to distinguish the types
+ is_false = 128,
+ is_unary = 256,
+
+ is_eq = 512,
+ is_ne = 1024,
+
+ is_lt = 2048,
+ is_gt = 4096,
+
+ is_ge = 8192,
+ is_le = 16384,
+
+ // macro types
+
+ DT_WARN = is_warn,
+ DT_CHECK = is_check,
+ DT_REQUIRE = is_require,
+
+ DT_WARN_FALSE = is_false | is_warn,
+ DT_CHECK_FALSE = is_false | is_check,
+ DT_REQUIRE_FALSE = is_false | is_require,
+
+ DT_WARN_THROWS = is_throws | is_warn,
+ DT_CHECK_THROWS = is_throws | is_check,
+ DT_REQUIRE_THROWS = is_throws | is_require,
+
+ DT_WARN_THROWS_AS = is_throws_as | is_warn,
+ DT_CHECK_THROWS_AS = is_throws_as | is_check,
+ DT_REQUIRE_THROWS_AS = is_throws_as | is_require,
+
+ DT_WARN_NOTHROW = is_nothrow | is_warn,
+ DT_CHECK_NOTHROW = is_nothrow | is_check,
+ DT_REQUIRE_NOTHROW = is_nothrow | is_require,
+
+ DT_WARN_EQ = is_eq | is_warn,
+ DT_CHECK_EQ = is_eq | is_check,
+ DT_REQUIRE_EQ = is_eq | is_require,
+
+ DT_WARN_NE = is_ne | is_warn,
+ DT_CHECK_NE = is_ne | is_check,
+ DT_REQUIRE_NE = is_ne | is_require,
+
+ DT_WARN_GT = is_gt | is_warn,
+ DT_CHECK_GT = is_gt | is_check,
+ DT_REQUIRE_GT = is_gt | is_require,
+
+ DT_WARN_LT = is_lt | is_warn,
+ DT_CHECK_LT = is_lt | is_check,
+ DT_REQUIRE_LT = is_lt | is_require,
+
+ DT_WARN_GE = is_ge | is_warn,
+ DT_CHECK_GE = is_ge | is_check,
+ DT_REQUIRE_GE = is_ge | is_require,
+
+ DT_WARN_LE = is_le | is_warn,
+ DT_CHECK_LE = is_le | is_check,
+ DT_REQUIRE_LE = is_le | is_require,
+
+ DT_WARN_UNARY = is_unary | is_warn,
+ DT_CHECK_UNARY = is_unary | is_check,
+ DT_REQUIRE_UNARY = is_unary | is_require,
+
+ DT_WARN_UNARY_FALSE = is_false | is_unary | is_warn,
+ DT_CHECK_UNARY_FALSE = is_false | is_unary | is_check,
+ DT_REQUIRE_UNARY_FALSE = is_false | is_unary | is_require,
+
+ DT_FAST_WARN_EQ = is_fast | is_eq | is_warn,
+ DT_FAST_CHECK_EQ = is_fast | is_eq | is_check,
+ DT_FAST_REQUIRE_EQ = is_fast | is_eq | is_require,
+
+ DT_FAST_WARN_NE = is_fast | is_ne | is_warn,
+ DT_FAST_CHECK_NE = is_fast | is_ne | is_check,
+ DT_FAST_REQUIRE_NE = is_fast | is_ne | is_require,
+
+ DT_FAST_WARN_GT = is_fast | is_gt | is_warn,
+ DT_FAST_CHECK_GT = is_fast | is_gt | is_check,
+ DT_FAST_REQUIRE_GT = is_fast | is_gt | is_require,
+
+ DT_FAST_WARN_LT = is_fast | is_lt | is_warn,
+ DT_FAST_CHECK_LT = is_fast | is_lt | is_check,
+ DT_FAST_REQUIRE_LT = is_fast | is_lt | is_require,
+
+ DT_FAST_WARN_GE = is_fast | is_ge | is_warn,
+ DT_FAST_CHECK_GE = is_fast | is_ge | is_check,
+ DT_FAST_REQUIRE_GE = is_fast | is_ge | is_require,
+
+ DT_FAST_WARN_LE = is_fast | is_le | is_warn,
+ DT_FAST_CHECK_LE = is_fast | is_le | is_check,
+ DT_FAST_REQUIRE_LE = is_fast | is_le | is_require,
+
+ DT_FAST_WARN_UNARY = is_fast | is_unary | is_warn,
+ DT_FAST_CHECK_UNARY = is_fast | is_unary | is_check,
+ DT_FAST_REQUIRE_UNARY = is_fast | is_unary | is_require,
+
+ DT_FAST_WARN_UNARY_FALSE = is_fast | is_false | is_unary | is_warn,
+ DT_FAST_CHECK_UNARY_FALSE = is_fast | is_false | is_unary | is_check,
+ DT_FAST_REQUIRE_UNARY_FALSE = is_fast | is_false | is_unary | is_require
+ };
+ } // namespace assertType
+
+ const char* getAssertString(assertType::Enum val);
+
+ // clang-format off
+ template<class T> struct decay_array { typedef T type; };
+ template<class T, unsigned N> struct decay_array<T[N]> { typedef T* type; };
+ template<class T> struct decay_array<T[]> { typedef T* type; };
+
+ template<class T> struct not_char_pointer { enum { value = true }; };
+ template<> struct not_char_pointer<char*> { enum { value = false }; };
+ template<> struct not_char_pointer<const char*> { enum { value = false }; };
+
+ template<class T> struct can_use_op : not_char_pointer<typename decay_array<T>::type> {};
+
+ template<bool, class = void> struct enable_if {};
+ template<class T> struct enable_if<true, T> { typedef T type; };
+ // clang-format on
+
+ struct TestFailureException
+ {};
+
+ bool checkIfShouldThrow(assertType::Enum assert_type);
+ void fastAssertThrowIfFlagSet(int flags);
+ void throwException();
+ bool always_false();
+
+ // a struct defining a registered test callback
+ struct TestData
+ {
+ // not used for determining uniqueness
+ const char* m_suite; // the test suite in which the test was added
+ const char* m_name; // name of the test function
+ funcType m_f; // a function pointer to the test function
+
+ // fields by which uniqueness of test cases shall be determined
+ const char* m_file; // the file in which the test was registered
+ unsigned m_line; // the line where the test was registered
+
+ TestData(const char* suite, const char* name, funcType f, const char* file, unsigned line)
+ : m_suite(suite)
+ , m_name(name)
+ , m_f(f)
+ , m_file(file)
+ , m_line(line) {}
+
+ bool operator<(const TestData& other) const;
+ };
+
+ struct SubcaseSignature
+ {
+ const char* m_name;
+ const char* m_file;
+ int m_line;
+
+ SubcaseSignature(const char* name, const char* file, int line)
+ : m_name(name)
+ , m_file(file)
+ , m_line(line) {}
+
+ bool operator<(const SubcaseSignature& other) const;
+ };
+
+ struct Subcase
+ {
+ SubcaseSignature m_signature;
+ bool m_entered;
+
+ Subcase(const char* name, const char* file, int line);
+ Subcase(const Subcase& other);
+ ~Subcase();
+
+ operator bool() const { return m_entered; }
+ };
+
+ template <typename L, typename R>
+ String stringifyBinaryExpr(const DOCTEST_REF_WRAP(L) lhs, const char* op,
+ const DOCTEST_REF_WRAP(R) rhs) {
+ return toString(lhs) + op + toString(rhs);
+ }
+
+ struct Result
+ {
+ bool m_passed;
+ String m_decomposition;
+
+// to fix gcc 4.7 "-Winline" warnings
+#if defined(__GNUC__) && !defined(__clang__)
+ __attribute__((noinline))
+#endif
+ ~Result() {
+ }
+
+ Result(bool passed = false, const String& decomposition = String())
+ : m_passed(passed)
+ , m_decomposition(decomposition) {}
+
+ Result(const Result& other)
+ : m_passed(other.m_passed)
+ , m_decomposition(other.m_decomposition) {}
+
+// to fix gcc 4.7 "-Winline" warnings
+#if defined(__GNUC__) && !defined(__clang__)
+ __attribute__((noinline))
+#endif
+ Result&
+ operator=(const Result& other) {
+ m_passed = other.m_passed;
+ m_decomposition = other.m_decomposition;
+
+ return *this;
+ }
+
+ operator bool() { return !m_passed; }
+
+ void invert() { m_passed = !m_passed; }
+
+ // clang-format off
+ // forbidding some expressions based on this table: http://en.cppreference.com/w/cpp/language/operator_precedence
+ template <typename R> Result operator& (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
+ template <typename R> Result operator^ (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
+ template <typename R> Result operator| (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
+ template <typename R> Result operator&& (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
+ template <typename R> Result operator|| (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
+ template <typename R> Result operator== (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
+ template <typename R> Result operator!= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
+ template <typename R> Result operator< (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
+ template <typename R> Result operator> (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
+ template <typename R> Result operator<= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
+ template <typename R> Result operator>= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
+ template <typename R> Result operator= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
+ template <typename R> Result operator+= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
+ template <typename R> Result operator-= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
+ template <typename R> Result operator*= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
+ template <typename R> Result operator/= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
+ template <typename R> Result operator%= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
+ template <typename R> Result operator<<=(const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
+ template <typename R> Result operator>>=(const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
+ template <typename R> Result operator&= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
+ template <typename R> Result operator^= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
+ template <typename R> Result operator|= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); }
+ // clang-format on
+ };
+
+#ifndef DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION
+
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wsign-conversion"
+#pragma clang diagnostic ignored "-Wsign-compare"
+#pragma clang diagnostic ignored "-Wdouble-promotion"
+//#pragma clang diagnostic ignored "-Wconversion"
+//#pragma clang diagnostic ignored "-Wfloat-equal"
+#endif // __clang__
+
+#if defined(__GNUC__) && !defined(__clang__)
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6)
+#pragma GCC diagnostic push
+#endif // > gcc 4.6
+#pragma GCC diagnostic ignored "-Wsign-conversion"
+#pragma GCC diagnostic ignored "-Wsign-compare"
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5)
+#pragma GCC diagnostic ignored "-Wdouble-promotion"
+#endif // > gcc 4.5
+//#pragma GCC diagnostic ignored "-Wconversion"
+//#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif // __GNUC__
+
+#ifdef _MSC_VER
+#pragma warning(push)
+// http://stackoverflow.com/questions/39479163 what's the difference between C4018 and C4389
+#pragma warning(disable : 4389) // 'operator' : signed/unsigned mismatch
+#pragma warning(disable : 4018) // 'expression' : signed/unsigned mismatch
+//#pragma warning(disable : 4805) // 'operation' : unsafe mix of type 'type' and type 'type' in operation
+#endif // _MSC_VER
+
+#endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION
+
+// clang-format off
+#ifndef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+#define DOCTEST_COMPARISON_RETURN_TYPE bool
+#else // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+#define DOCTEST_COMPARISON_RETURN_TYPE typename enable_if<can_use_op<L>::value || can_use_op<R>::value, bool>::type
+ inline bool eq(const char* lhs, const char* rhs) { return String(lhs) == String(rhs); }
+ inline bool ne(const char* lhs, const char* rhs) { return String(lhs) != String(rhs); }
+ inline bool lt(const char* lhs, const char* rhs) { return String(lhs) < String(rhs); }
+ inline bool gt(const char* lhs, const char* rhs) { return String(lhs) > String(rhs); }
+ inline bool le(const char* lhs, const char* rhs) { return String(lhs) <= String(rhs); }
+ inline bool ge(const char* lhs, const char* rhs) { return String(lhs) >= String(rhs); }
+#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+
+ 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; }
+ 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; }
+ 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; }
+ 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; }
+ 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; }
+ 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; }
+ // clang-format on
+
+ template <typename L>
+ struct Expression_lhs
+ {
+ L lhs;
+
+ Expression_lhs(L in)
+ : lhs(in) {}
+
+ Expression_lhs(const Expression_lhs& other)
+ : lhs(other.lhs) {}
+
+ operator Result() { return Result(!!lhs, toString(lhs)); }
+
+// clang-format off
+#ifndef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+ template <typename R> Result operator==(const DOCTEST_REF_WRAP(R) rhs) { return Result(lhs == rhs, stringifyBinaryExpr(lhs, " == ", rhs)); }
+ template <typename R> Result operator!=(const DOCTEST_REF_WRAP(R) rhs) { return Result(lhs != rhs, stringifyBinaryExpr(lhs, " != ", rhs)); }
+ template <typename R> Result operator< (const DOCTEST_REF_WRAP(R) rhs) { return Result(lhs < rhs, stringifyBinaryExpr(lhs, " < " , rhs)); }
+ template <typename R> Result operator<=(const DOCTEST_REF_WRAP(R) rhs) { return Result(lhs <= rhs, stringifyBinaryExpr(lhs, " <= ", rhs)); }
+ template <typename R> Result operator> (const DOCTEST_REF_WRAP(R) rhs) { return Result(lhs > rhs, stringifyBinaryExpr(lhs, " > " , rhs)); }
+ template <typename R> Result operator>=(const DOCTEST_REF_WRAP(R) rhs) { return Result(lhs >= rhs, stringifyBinaryExpr(lhs, " >= ", rhs)); }
+#else // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+ template <typename R> Result operator==(const DOCTEST_REF_WRAP(R) rhs) { return Result(eq(lhs, rhs), stringifyBinaryExpr(lhs, " == ", rhs)); }
+ template <typename R> Result operator!=(const DOCTEST_REF_WRAP(R) rhs) { return Result(ne(lhs, rhs), stringifyBinaryExpr(lhs, " != ", rhs)); }
+ template <typename R> Result operator< (const DOCTEST_REF_WRAP(R) rhs) { return Result(lt(lhs, rhs), stringifyBinaryExpr(lhs, " < " , rhs)); }
+ template <typename R> Result operator<=(const DOCTEST_REF_WRAP(R) rhs) { return Result(le(lhs, rhs), stringifyBinaryExpr(lhs, " <= ", rhs)); }
+ template <typename R> Result operator> (const DOCTEST_REF_WRAP(R) rhs) { return Result(gt(lhs, rhs), stringifyBinaryExpr(lhs, " > " , rhs)); }
+ template <typename R> Result operator>=(const DOCTEST_REF_WRAP(R) rhs) { return Result(ge(lhs, rhs), stringifyBinaryExpr(lhs, " >= ", rhs)); }
+#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+ // clang-format on
+
+ // clang-format off
+ // forbidding some expressions based on this table: http://en.cppreference.com/w/cpp/language/operator_precedence
+ template <typename R> int operator& (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
+ template <typename R> int operator^ (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
+ template <typename R> int operator| (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
+ template <typename R> int operator&& (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
+ template <typename R> int operator|| (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
+ template <typename R> int operator= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
+ template <typename R> int operator+= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
+ template <typename R> int operator-= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
+ template <typename R> int operator*= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
+ template <typename R> int operator/= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
+ template <typename R> int operator%= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
+ template <typename R> int operator<<=(const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
+ template <typename R> int operator>>=(const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
+ template <typename R> int operator&= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
+ template <typename R> int operator^= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
+ template <typename R> int operator|= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); }
+ // these 2 are unfortunate because they should be allowed - they have higher precedence over the comparisons, but the
+ // ExpressionDecomposer class uses the left shift operator to capture the left operand of the binary expression...
+ template <typename R> int operator<< (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Please_Surround_The_Left_Shift_Operation_With_Parenthesis); return int(); }
+ template <typename R> int operator>> (const R&) { DOCTEST_STATIC_ASSERT(deferred_false<R>::value, Please_Surround_The_Right_Shift_Operation_With_Parenthesis); return int(); }
+ // clang-format on
+ };
+
+#ifndef DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION
+
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif // __clang__
+
+#if defined(__GNUC__) && !defined(__clang__)
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6)
+#pragma GCC diagnostic pop
+#endif // > gcc 4.6
+#endif // __GNUC__
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif // _MSC_VER
+
+#endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION
+
+ struct ExpressionDecomposer
+ {
+ template <typename L>
+ Expression_lhs<const DOCTEST_REF_WRAP(L)> operator<<(const DOCTEST_REF_WRAP(L) operand) {
+ return Expression_lhs<const DOCTEST_REF_WRAP(L)>(operand);
+ }
+ };
+
+ // forward declarations of functions used by the macros
+ int regTest(void (*f)(void), unsigned line, const char* file, const char* name);
+ int setTestSuiteName(const char* name);
+
+ void addFailedAssert(assertType::Enum assert_type);
+
+ void logTestStart(const char* name, const char* file, unsigned line);
+ void logTestEnd();
+
+ void logTestCrashed();
+
+ void logAssert(bool passed, const char* decomposition, bool threw, const char* expr,
+ assertType::Enum assert_type, const char* file, int line);
+
+ void logAssertThrows(bool threw, const char* expr, assertType::Enum assert_type,
+ const char* file, int line);
+
+ void logAssertThrowsAs(bool threw, bool threw_as, const char* as, const char* expr,
+ assertType::Enum assert_type, const char* file, int line);
+
+ void logAssertNothrow(bool threw, const char* expr, assertType::Enum assert_type,
+ const char* file, int line);
+
+ bool isDebuggerActive();
+ void writeToDebugConsole(const String&);
+
+ struct TestAccessibleContextState
+ {
+ bool success; // include successful assertions in output
+ bool no_throw; // to skip exceptions-related assertion macros
+ bool no_breaks; // to not break into the debugger
+ const TestData* currentTest;
+ bool hasLoggedCurrentTestStart;
+ int numAssertionsForCurrentTestcase;
+ };
+
+ struct ContextState;
+
+ TestAccessibleContextState* getTestsContextState();
+
+ namespace binaryAssertComparison
+ {
+ enum Enum
+ {
+ eq = 0,
+ ne,
+ gt,
+ lt,
+ ge,
+ le
+ };
+ } // namespace binaryAssertComparison
+
+ // clang-format off
+ template <int, class L, class R> struct RelationalComparator { bool operator()(const DOCTEST_REF_WRAP(L), const DOCTEST_REF_WRAP(R) ) const { return false; } };
+ 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); } };
+ 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); } };
+ 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); } };
+ 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); } };
+ 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); } };
+ 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); } };
+ // clang-format on
+
+ struct ResultBuilder
+ {
+ assertType::Enum m_assert_type;
+ const char* m_file;
+ int m_line;
+ const char* m_expr;
+ const char* m_exception_type;
+
+ Result m_result;
+ bool m_threw;
+ bool m_threw_as;
+ bool m_failed;
+
+ ResultBuilder(assertType::Enum assert_type, const char* file, int line, const char* expr,
+ const char* exception_type = "");
+
+// to fix gcc 4.7 "-Winline" warnings
+#if defined(__GNUC__) && !defined(__clang__)
+ __attribute__((noinline))
+#endif
+ ~ResultBuilder() {
+ }
+
+ void setResult(const Result& res) { m_result = res; }
+
+ template <int comparison, typename L, typename R>
+ void binary_assert(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) {
+ m_result.m_passed = RelationalComparator<comparison, L, R>()(lhs, rhs);
+ m_result.m_decomposition = stringifyBinaryExpr(lhs, ", ", rhs);
+ }
+
+ template <typename L>
+ void unary_assert(const DOCTEST_REF_WRAP(L) val) {
+ m_result.m_passed = !!val;
+ m_result.m_decomposition = toString(val);
+ }
+
+ bool log();
+ void react() const;
+ };
+
+ namespace assertAction
+ {
+ enum Enum
+ {
+ nothing = 0,
+ dbgbreak = 1,
+ shouldthrow = 2
+ };
+ } // namespace assertAction
+
+ template <int comparison, typename L, typename R>
+ int fast_binary_assert(assertType::Enum assert_type, const char* file, int line,
+ const char* lhs_str, const char* rhs_str, const DOCTEST_REF_WRAP(L) lhs,
+ const DOCTEST_REF_WRAP(R) rhs) {
+ String expr = String(lhs_str) + ", " + rhs_str;
+ const char* expr_str = expr.c_str();
+ ResultBuilder rb(assert_type, file, line, expr_str);
+
+ rb.m_result.m_passed = RelationalComparator<comparison, L, R>()(lhs, rhs);
+ rb.m_result.m_decomposition = stringifyBinaryExpr(lhs, ", ", rhs);
+
+ int res = 0;
+
+ if(rb.log())
+ res |= assertAction::dbgbreak;
+
+ if(rb.m_failed && checkIfShouldThrow(assert_type))
+ res |= assertAction::shouldthrow;
+
+#ifdef DOCTEST_CONFIG_SUPER_FAST_ASSERTS
+ // #########################################################################################
+ // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK TO SEE THE FAILING ASSERTION
+ // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED
+ // #########################################################################################
+ if(res & assertAction::dbgbreak)
+ DOCTEST_BREAK_INTO_DEBUGGER();
+ fastAssertThrowIfFlagSet(res);
+#endif // DOCTEST_CONFIG_SUPER_FAST_ASSERTS
+
+ return res;
+ }
+
+ template <typename L>
+ int fast_unary_assert(assertType::Enum assert_type, const char* file, int line,
+ const char* val_str, const DOCTEST_REF_WRAP(L) val) {
+ ResultBuilder rb(assert_type, file, line, val_str);
+
+ rb.m_result.m_passed = !!val;
+ rb.m_result.m_decomposition = toString(val);
+
+ int res = 0;
+
+ if(rb.log())
+ res |= assertAction::dbgbreak;
+
+ if(rb.m_failed && checkIfShouldThrow(assert_type))
+ res |= assertAction::shouldthrow;
+
+#ifdef DOCTEST_CONFIG_SUPER_FAST_ASSERTS
+ // #########################################################################################
+ // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK TO SEE THE FAILING ASSERTION
+ // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED
+ // #########################################################################################
+ if(res & assertAction::dbgbreak)
+ DOCTEST_BREAK_INTO_DEBUGGER();
+ fastAssertThrowIfFlagSet(res);
+#endif // DOCTEST_CONFIG_SUPER_FAST_ASSERTS
+
+ return res;
+ }
+} // namespace detail
+
+#endif // DOCTEST_CONFIG_DISABLE
+
+class Context
+{
+#if !defined(DOCTEST_CONFIG_DISABLE)
+ detail::ContextState* p;
+
+ void parseArgs(int argc, const char* const* argv, bool withDefaults = false);
+
+#endif // DOCTEST_CONFIG_DISABLE
+
+public:
+ Context(int argc = 0, const char* const* argv = 0);
+
+// to fix gcc 4.7 "-Winline" warnings
+#if defined(__GNUC__) && !defined(__clang__)
+ __attribute__((noinline))
+#endif
+ ~Context();
+
+ void applyCommandLine(int argc, const char* const* argv);
+
+ void addFilter(const char* filter, const char* value);
+ void clearFilters();
+ void setOption(const char* option, int value);
+ void setOption(const char* option, const char* value);
+
+ bool shouldExit();
+
+ int run();
+};
+
+} // namespace doctest
+
+// if registering is not disabled
+#if !defined(DOCTEST_CONFIG_DISABLE)
+
+// registers the test by initializing a dummy var with a function
+#if defined(__GNUC__) && !defined(__clang__)
+#define DOCTEST_REGISTER_FUNCTION(f, name) \
+ static int DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_) __attribute__((unused)) = \
+ doctest::detail::regTest(f, __LINE__, __FILE__, name);
+#elif defined(__clang__)
+#define DOCTEST_REGISTER_FUNCTION(f, name) \
+ _Pragma("clang diagnostic push") \
+ _Pragma("clang diagnostic ignored \"-Wglobal-constructors\"") static int \
+ DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_) = \
+ doctest::detail::regTest(f, __LINE__, __FILE__, name); \
+ _Pragma("clang diagnostic pop")
+#else // MSVC
+#define DOCTEST_REGISTER_FUNCTION(f, name) \
+ static int DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_) = \
+ doctest::detail::regTest(f, __LINE__, __FILE__, name);
+#endif // MSVC
+
+#define DOCTEST_IMPLEMENT_FIXTURE(der, base, func, name) \
+ namespace \
+ { \
+ struct der : base \
+ { void f(); }; \
+ static void func() { \
+ der v; \
+ v.f(); \
+ } \
+ DOCTEST_REGISTER_FUNCTION(func, name) \
+ } \
+ inline void der::f()
+
+#define DOCTEST_CREATE_AND_REGISTER_FUNCTION(f, name) \
+ static void f(); \
+ DOCTEST_REGISTER_FUNCTION(f, name) \
+ inline void f()
+
+// for registering tests
+#define DOCTEST_TEST_CASE(name) \
+ DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), name)
+
+// for registering tests with a fixture
+#define DOCTEST_TEST_CASE_FIXTURE(c, name) \
+ DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(_DOCTEST_ANON_CLASS_), c, \
+ DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), name)
+
+// for subcases
+#if defined(__GNUC__)
+#define DOCTEST_SUBCASE(name) \
+ if(const doctest::detail::Subcase & DOCTEST_ANONYMOUS(_DOCTEST_ANON_SUBCASE_) \
+ __attribute__((unused)) = \
+ doctest::detail::Subcase(name, __FILE__, __LINE__))
+#else // __GNUC__
+#define DOCTEST_SUBCASE(name) \
+ if(const doctest::detail::Subcase & DOCTEST_ANONYMOUS(_DOCTEST_ANON_SUBCASE_) = \
+ doctest::detail::Subcase(name, __FILE__, __LINE__))
+#endif // __GNUC__
+
+// for starting a testsuite block
+#if defined(__GNUC__) && !defined(__clang__)
+#define DOCTEST_TEST_SUITE(name) \
+ static int DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_) __attribute__((unused)) = \
+ doctest::detail::setTestSuiteName(name); \
+ typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
+#elif defined(__clang__)
+#define DOCTEST_TEST_SUITE(name) \
+ _Pragma("clang diagnostic push") \
+ _Pragma("clang diagnostic ignored \"-Wglobal-constructors\"") static int \
+ DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_) = \
+ doctest::detail::setTestSuiteName(name); \
+ _Pragma("clang diagnostic pop") typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
+#else // MSVC
+#define DOCTEST_TEST_SUITE(name) \
+ static int DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_) = doctest::detail::setTestSuiteName(name); \
+ typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
+#endif // MSVC
+
+// for ending a testsuite block
+#if defined(__GNUC__) && !defined(__clang__)
+#define DOCTEST_TEST_SUITE_END \
+ static int DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_) __attribute__((unused)) = \
+ doctest::detail::setTestSuiteName(""); \
+ typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
+#elif defined(__clang__)
+#define DOCTEST_TEST_SUITE_END \
+ _Pragma("clang diagnostic push") \
+ _Pragma("clang diagnostic ignored \"-Wglobal-constructors\"") static int \
+ DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_) = doctest::detail::setTestSuiteName(""); \
+ _Pragma("clang diagnostic pop") typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
+#else // MSVC
+#define DOCTEST_TEST_SUITE_END \
+ static int DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_) = doctest::detail::setTestSuiteName(""); \
+ typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
+#endif // MSVC
+
+#define DOCTEST_ASSERT_LOG_AND_REACT(rb) \
+ if(rb.log()) \
+ DOCTEST_BREAK_INTO_DEBUGGER(); \
+ rb.react()
+
+#ifdef DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
+#define DOCTEST_WRAP_IN_TRY(x) x;
+#else // DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
+#define DOCTEST_WRAP_IN_TRY(x) \
+ try { \
+ x; \
+ } catch(...) { _DOCTEST_RB.m_threw = true; }
+#endif // DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
+
+#define DOCTEST_ASSERT_IMPLEMENT(expr, assert_type) \
+ doctest::detail::ResultBuilder _DOCTEST_RB(doctest::detail::assertType::assert_type, __FILE__, \
+ __LINE__, #expr); \
+ DOCTEST_WRAP_IN_TRY(_DOCTEST_RB.setResult(doctest::detail::ExpressionDecomposer() << expr)) \
+ DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB);
+
+#if defined(__clang__)
+#define DOCTEST_ASSERT_PROXY(expr, assert_type) \
+ do { \
+ _Pragma("clang diagnostic push") \
+ _Pragma("clang diagnostic ignored \"-Woverloaded-shift-op-parentheses\"") \
+ DOCTEST_ASSERT_IMPLEMENT(expr, assert_type) \
+ _Pragma("clang diagnostic pop") \
+ } while(doctest::detail::always_false())
+#else // __clang__
+#define DOCTEST_ASSERT_PROXY(expr, assert_type) \
+ do { \
+ DOCTEST_ASSERT_IMPLEMENT(expr, assert_type) \
+ } while(doctest::detail::always_false())
+#endif // __clang__
+
+#define DOCTEST_WARN(expr) DOCTEST_ASSERT_PROXY(expr, DT_WARN)
+#define DOCTEST_CHECK(expr) DOCTEST_ASSERT_PROXY(expr, DT_CHECK)
+#define DOCTEST_REQUIRE(expr) DOCTEST_ASSERT_PROXY(expr, DT_REQUIRE)
+
+#define DOCTEST_WARN_FALSE(expr) DOCTEST_ASSERT_PROXY(expr, DT_WARN_FALSE)
+#define DOCTEST_CHECK_FALSE(expr) DOCTEST_ASSERT_PROXY(expr, DT_CHECK_FALSE)
+#define DOCTEST_REQUIRE_FALSE(expr) DOCTEST_ASSERT_PROXY(expr, DT_REQUIRE_FALSE)
+
+#define DOCTEST_ASSERT_THROWS(expr, assert_type) \
+ do { \
+ if(!DOCTEST_GCS().no_throw) { \
+ doctest::detail::ResultBuilder _DOCTEST_RB(doctest::detail::assertType::assert_type, \
+ __FILE__, __LINE__, #expr); \
+ try { \
+ expr; \
+ } catch(...) { _DOCTEST_RB.m_threw = true; } \
+ DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \
+ } \
+ } while(doctest::detail::always_false())
+
+#define DOCTEST_ASSERT_THROWS_AS(expr, as, assert_type) \
+ do { \
+ if(!DOCTEST_GCS().no_throw) { \
+ doctest::detail::ResultBuilder _DOCTEST_RB(doctest::detail::assertType::assert_type, \
+ __FILE__, __LINE__, #expr, #as); \
+ try { \
+ expr; \
+ } catch(as) { \
+ _DOCTEST_RB.m_threw = true; \
+ _DOCTEST_RB.m_threw_as = true; \
+ } catch(...) { _DOCTEST_RB.m_threw = true; } \
+ DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \
+ } \
+ } while(doctest::detail::always_false())
+
+#define DOCTEST_ASSERT_NOTHROW(expr, assert_type) \
+ do { \
+ if(!DOCTEST_GCS().no_throw) { \
+ doctest::detail::ResultBuilder _DOCTEST_RB(doctest::detail::assertType::assert_type, \
+ __FILE__, __LINE__, #expr); \
+ try { \
+ expr; \
+ } catch(...) { _DOCTEST_RB.m_threw = true; } \
+ DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \
+ } \
+ } while(doctest::detail::always_false())
+
+#define DOCTEST_WARN_THROWS(expr) DOCTEST_ASSERT_THROWS(expr, DT_WARN_THROWS)
+#define DOCTEST_CHECK_THROWS(expr) DOCTEST_ASSERT_THROWS(expr, DT_CHECK_THROWS)
+#define DOCTEST_REQUIRE_THROWS(expr) DOCTEST_ASSERT_THROWS(expr, DT_REQUIRE_THROWS)
+
+#define DOCTEST_WARN_THROWS_AS(expr, ex) DOCTEST_ASSERT_THROWS_AS(expr, ex, DT_WARN_THROWS_AS)
+#define DOCTEST_CHECK_THROWS_AS(expr, ex) DOCTEST_ASSERT_THROWS_AS(expr, ex, DT_CHECK_THROWS_AS)
+#define DOCTEST_REQUIRE_THROWS_AS(expr, ex) DOCTEST_ASSERT_THROWS_AS(expr, ex, DT_REQUIRE_THROWS_AS)
+
+#define DOCTEST_WARN_NOTHROW(expr) DOCTEST_ASSERT_NOTHROW(expr, DT_WARN_NOTHROW)
+#define DOCTEST_CHECK_NOTHROW(expr) DOCTEST_ASSERT_NOTHROW(expr, DT_CHECK_NOTHROW)
+#define DOCTEST_REQUIRE_NOTHROW(expr) DOCTEST_ASSERT_NOTHROW(expr, DT_REQUIRE_NOTHROW)
+
+#define DOCTEST_BINARY_ASSERT(assert_type, lhs, rhs, comp) \
+ do { \
+ doctest::detail::ResultBuilder _DOCTEST_RB(doctest::detail::assertType::assert_type, \
+ __FILE__, __LINE__, #lhs ", " #rhs); \
+ DOCTEST_WRAP_IN_TRY( \
+ _DOCTEST_RB.binary_assert<doctest::detail::binaryAssertComparison::comp>(lhs, \
+ rhs)) \
+ DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \
+ } while(doctest::detail::always_false())
+
+#define DOCTEST_UNARY_ASSERT(assert_type, val) \
+ do { \
+ doctest::detail::ResultBuilder _DOCTEST_RB(doctest::detail::assertType::assert_type, \
+ __FILE__, __LINE__, #val); \
+ DOCTEST_WRAP_IN_TRY(_DOCTEST_RB.unary_assert(val)) \
+ DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \
+ } while(doctest::detail::always_false())
+
+#define DOCTEST_WARN_EQ(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_WARN_EQ, lhs, rhs, eq)
+#define DOCTEST_CHECK_EQ(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_CHECK_EQ, lhs, rhs, eq)
+#define DOCTEST_REQUIRE_EQ(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_REQUIRE_EQ, lhs, rhs, eq)
+#define DOCTEST_WARN_NE(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_WARN_NE, lhs, rhs, ne)
+#define DOCTEST_CHECK_NE(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_CHECK_NE, lhs, rhs, ne)
+#define DOCTEST_REQUIRE_NE(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_REQUIRE_NE, lhs, rhs, ne)
+#define DOCTEST_WARN_GT(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_WARN_GT, lhs, rhs, gt)
+#define DOCTEST_CHECK_GT(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_CHECK_GT, lhs, rhs, gt)
+#define DOCTEST_REQUIRE_GT(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_REQUIRE_GT, lhs, rhs, gt)
+#define DOCTEST_WARN_LT(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_WARN_LT, lhs, rhs, lt)
+#define DOCTEST_CHECK_LT(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_CHECK_LT, lhs, rhs, lt)
+#define DOCTEST_REQUIRE_LT(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_REQUIRE_LT, lhs, rhs, lt)
+#define DOCTEST_WARN_GE(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_WARN_GE, lhs, rhs, ge)
+#define DOCTEST_CHECK_GE(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_CHECK_GE, lhs, rhs, ge)
+#define DOCTEST_REQUIRE_GE(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_REQUIRE_GE, lhs, rhs, ge)
+#define DOCTEST_WARN_LE(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_WARN_LE, lhs, rhs, le)
+#define DOCTEST_CHECK_LE(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_CHECK_LE, lhs, rhs, le)
+#define DOCTEST_REQUIRE_LE(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_REQUIRE_LE, lhs, rhs, le)
+
+#define DOCTEST_WARN_UNARY(v) DOCTEST_UNARY_ASSERT(DT_WARN_UNARY, v)
+#define DOCTEST_CHECK_UNARY(v) DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY, v)
+#define DOCTEST_REQUIRE_UNARY(v) DOCTEST_UNARY_ASSERT(DT_REQUIRE_UNARY, v)
+#define DOCTEST_WARN_UNARY_FALSE(v) DOCTEST_UNARY_ASSERT(DT_WARN_UNARY_FALSE, v)
+#define DOCTEST_CHECK_UNARY_FALSE(v) DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY_FALSE, v)
+#define DOCTEST_REQUIRE_UNARY_FALSE(v) DOCTEST_UNARY_ASSERT(DT_REQUIRE_UNARY_FALSE, v)
+
+#ifndef DOCTEST_CONFIG_SUPER_FAST_ASSERTS
+
+#define DOCTEST_FAST_BINARY_ASSERT(assert_type, lhs, rhs, comparison) \
+ do { \
+ int _DOCTEST_FAST_RES = doctest::detail::fast_binary_assert< \
+ doctest::detail::binaryAssertComparison::comparison>( \
+ doctest::detail::assertType::assert_type, __FILE__, __LINE__, #lhs, #rhs, lhs, \
+ rhs); \
+ if(_DOCTEST_FAST_RES & doctest::detail::assertAction::dbgbreak) \
+ DOCTEST_BREAK_INTO_DEBUGGER(); \
+ doctest::detail::fastAssertThrowIfFlagSet(_DOCTEST_FAST_RES); \
+ } while(doctest::detail::always_false())
+
+#define DOCTEST_FAST_UNARY_ASSERT(assert_type, val) \
+ do { \
+ int _DOCTEST_FAST_RES = doctest::detail::fast_unary_assert( \
+ doctest::detail::assertType::assert_type, __FILE__, __LINE__, #val, val); \
+ if(_DOCTEST_FAST_RES & doctest::detail::assertAction::dbgbreak) \
+ DOCTEST_BREAK_INTO_DEBUGGER(); \
+ doctest::detail::fastAssertThrowIfFlagSet(_DOCTEST_FAST_RES); \
+ } while(doctest::detail::always_false())
+
+#else // DOCTEST_CONFIG_SUPER_FAST_ASSERTS
+
+#define DOCTEST_FAST_BINARY_ASSERT(assert_type, lhs, rhs, comparison) \
+ doctest::detail::fast_binary_assert<doctest::detail::binaryAssertComparison::comparison>( \
+ doctest::detail::assertType::assert_type, __FILE__, __LINE__, #lhs, #rhs, lhs, rhs)
+
+#define DOCTEST_FAST_UNARY_ASSERT(assert_type, val) \
+ doctest::detail::fast_unary_assert(doctest::detail::assertType::assert_type, __FILE__, \
+ __LINE__, #val, val)
+
+#endif // DOCTEST_CONFIG_SUPER_FAST_ASSERTS
+
+#define DOCTEST_FAST_WARN_EQ(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_WARN_EQ, l, r, eq)
+#define DOCTEST_FAST_CHECK_EQ(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_CHECK_EQ, l, r, eq)
+#define DOCTEST_FAST_REQUIRE_EQ(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_REQUIRE_EQ, l, r, eq)
+#define DOCTEST_FAST_WARN_NE(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_WARN_NE, l, r, ne)
+#define DOCTEST_FAST_CHECK_NE(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_CHECK_NE, l, r, ne)
+#define DOCTEST_FAST_REQUIRE_NE(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_REQUIRE_NE, l, r, ne)
+#define DOCTEST_FAST_WARN_GT(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_WARN_GT, l, r, gt)
+#define DOCTEST_FAST_CHECK_GT(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_CHECK_GT, l, r, gt)
+#define DOCTEST_FAST_REQUIRE_GT(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_REQUIRE_GT, l, r, gt)
+#define DOCTEST_FAST_WARN_LT(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_WARN_LT, l, r, lt)
+#define DOCTEST_FAST_CHECK_LT(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_CHECK_LT, l, r, lt)
+#define DOCTEST_FAST_REQUIRE_LT(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_REQUIRE_LT, l, r, lt)
+#define DOCTEST_FAST_WARN_GE(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_WARN_GE, l, r, ge)
+#define DOCTEST_FAST_CHECK_GE(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_CHECK_GE, l, r, ge)
+#define DOCTEST_FAST_REQUIRE_GE(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_REQUIRE_GE, l, r, ge)
+#define DOCTEST_FAST_WARN_LE(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_WARN_LE, l, r, le)
+#define DOCTEST_FAST_CHECK_LE(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_CHECK_LE, l, r, le)
+#define DOCTEST_FAST_REQUIRE_LE(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_REQUIRE_LE, l, r, le)
+
+#define DOCTEST_FAST_WARN_UNARY(v) DOCTEST_FAST_UNARY_ASSERT(DT_FAST_WARN_UNARY, v)
+#define DOCTEST_FAST_CHECK_UNARY(v) DOCTEST_FAST_UNARY_ASSERT(DT_FAST_CHECK_UNARY, v)
+#define DOCTEST_FAST_REQUIRE_UNARY(v) DOCTEST_FAST_UNARY_ASSERT(DT_FAST_REQUIRE_UNARY, v)
+#define DOCTEST_FAST_WARN_UNARY_FALSE(v) DOCTEST_FAST_UNARY_ASSERT(DT_FAST_WARN_UNARY_FALSE, v)
+#define DOCTEST_FAST_CHECK_UNARY_FALSE(v) DOCTEST_FAST_UNARY_ASSERT(DT_FAST_CHECK_UNARY_FALSE, v)
+#define DOCTEST_FAST_REQUIRE_UNARY_FALSE(v) \
+ DOCTEST_FAST_UNARY_ASSERT(DT_FAST_REQUIRE_UNARY_FALSE, v)
+
+
+
+// OMGOMGOMG trqbva da napravq teq da sa no-op - a ne prosto da ne gi undef-vam
+
+
+
+#ifdef DOCTEST_CONFIG_NO_EXCEPTIONS
+
+#undef DOCTEST_WARN_THROWS
+#undef DOCTEST_CHECK_THROWS
+#undef DOCTEST_REQUIRE_THROWS
+#undef DOCTEST_WARN_THROWS_AS
+#undef DOCTEST_CHECK_THROWS_AS
+#undef DOCTEST_REQUIRE_THROWS_AS
+#undef DOCTEST_WARN_NOTHROW
+#undef DOCTEST_CHECK_NOTHROW
+#undef DOCTEST_REQUIRE_NOTHROW
+
+#ifdef DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS
+
+#define DOCTEST_WARN_THROWS(expr) ((void)0)
+#define DOCTEST_WARN_THROWS_AS(expr, ex) ((void)0)
+#define DOCTEST_WARN_NOTHROW(expr) ((void)0)
+#define DOCTEST_CHECK_THROWS(expr) ((void)0)
+#define DOCTEST_CHECK_THROWS_AS(expr, ex) ((void)0)
+#define DOCTEST_CHECK_NOTHROW(expr) ((void)0)
+#define DOCTEST_REQUIRE_THROWS(expr) ((void)0)
+#define DOCTEST_REQUIRE_THROWS_AS(expr, ex) ((void)0)
+#define DOCTEST_REQUIRE_NOTHROW(expr) ((void)0)
+
+#else // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS
+
+#undef DOCTEST_REQUIRE
+#undef DOCTEST_REQUIRE_FALSE
+#undef DOCTEST_REQUIRE_EQ
+#undef DOCTEST_REQUIRE_NE
+#undef DOCTEST_REQUIRE_GT
+#undef DOCTEST_REQUIRE_LT
+#undef DOCTEST_REQUIRE_GE
+#undef DOCTEST_REQUIRE_LE
+#undef DOCTEST_REQUIRE_UNARY
+#undef DOCTEST_REQUIRE_UNARY_FALSE
+#undef DOCTEST_FAST_REQUIRE_EQ
+#undef DOCTEST_FAST_REQUIRE_NE
+#undef DOCTEST_FAST_REQUIRE_GT
+#undef DOCTEST_FAST_REQUIRE_LT
+#undef DOCTEST_FAST_REQUIRE_GE
+#undef DOCTEST_FAST_REQUIRE_LE
+#undef DOCTEST_FAST_REQUIRE_UNARY
+#undef DOCTEST_FAST_REQUIRE_UNARY_FALSE
+
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS
+
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
+
+// =================================================================================================
+// == WHAT FOLLOWS IS VERSIONS OF THE MACROS THAT DO NOT DO ANY REGISTERING! ==
+// == THIS CAN BE ENABLED BY DEFINING DOCTEST_CONFIG_DISABLE GLOBALLY! ==
+// =================================================================================================
+#else // DOCTEST_CONFIG_DISABLE
+
+#define DOCTEST_IMPLEMENT_FIXTURE(der, base, func, name) \
+ namespace \
+ { \
+ template <typename T> \
+ struct der : base \
+ { void f(); }; \
+ } \
+ template <typename T> \
+ inline void der<T>::f()
+
+#define DOCTEST_CREATE_AND_REGISTER_FUNCTION(f, name) \
+ template <typename T> \
+ static inline void f()
+
+// for registering tests
+#define DOCTEST_TEST_CASE(name) \
+ DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), name)
+
+// for registering tests with a fixture
+#define DOCTEST_TEST_CASE_FIXTURE(x, name) \
+ DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(_DOCTEST_ANON_CLASS_), x, \
+ DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), name)
+
+// for subcases
+#define DOCTEST_SUBCASE(name)
+
+// for starting a testsuite block
+#define DOCTEST_TEST_SUITE(name) typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
+
+// for ending a testsuite block
+#define DOCTEST_TEST_SUITE_END typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
+
+#define DOCTEST_WARN(expr) ((void)0)
+#define DOCTEST_WARN_FALSE(expr) ((void)0)
+#define DOCTEST_WARN_THROWS(expr) ((void)0)
+#define DOCTEST_WARN_THROWS_AS(expr, ex) ((void)0)
+#define DOCTEST_WARN_NOTHROW(expr) ((void)0)
+#define DOCTEST_CHECK(expr) ((void)0)
+#define DOCTEST_CHECK_FALSE(expr) ((void)0)
+#define DOCTEST_CHECK_THROWS(expr) ((void)0)
+#define DOCTEST_CHECK_THROWS_AS(expr, ex) ((void)0)
+#define DOCTEST_CHECK_NOTHROW(expr) ((void)0)
+#define DOCTEST_REQUIRE(expr) ((void)0)
+#define DOCTEST_REQUIRE_FALSE(expr) ((void)0)
+#define DOCTEST_REQUIRE_THROWS(expr) ((void)0)
+#define DOCTEST_REQUIRE_THROWS_AS(expr, ex) ((void)0)
+#define DOCTEST_REQUIRE_NOTHROW(expr) ((void)0)
+
+#define DOCTEST_WARN_EQ(lhs, rhs) ((void)0)
+#define DOCTEST_CHECK_EQ(lhs, rhs) ((void)0)
+#define DOCTEST_REQUIRE_EQ(lhs, rhs) ((void)0)
+#define DOCTEST_WARN_NE(lhs, rhs) ((void)0)
+#define DOCTEST_CHECK_NE(lhs, rhs) ((void)0)
+#define DOCTEST_REQUIRE_NE(lhs, rhs) ((void)0)
+#define DOCTEST_WARN_GT(lhs, rhs) ((void)0)
+#define DOCTEST_CHECK_GT(lhs, rhs) ((void)0)
+#define DOCTEST_REQUIRE_GT(lhs, rhs) ((void)0)
+#define DOCTEST_WARN_LT(lhs, rhs) ((void)0)
+#define DOCTEST_CHECK_LT(lhs, rhs) ((void)0)
+#define DOCTEST_REQUIRE_LT(lhs, rhs) ((void)0)
+#define DOCTEST_WARN_GE(lhs, rhs) ((void)0)
+#define DOCTEST_CHECK_GE(lhs, rhs) ((void)0)
+#define DOCTEST_REQUIRE_GE(lhs, rhs) ((void)0)
+#define DOCTEST_WARN_LE(lhs, rhs) ((void)0)
+#define DOCTEST_CHECK_LE(lhs, rhs) ((void)0)
+#define DOCTEST_REQUIRE_LE(lhs, rhs) ((void)0)
+
+#define DOCTEST_WARN_UNARY(val) ((void)0)
+#define DOCTEST_CHECK_UNARY(val) ((void)0)
+#define DOCTEST_REQUIRE_UNARY(val) ((void)0)
+#define DOCTEST_WARN_UNARY_FALSE(val) ((void)0)
+#define DOCTEST_CHECK_UNARY_FALSE(val) ((void)0)
+#define DOCTEST_REQUIRE_UNARY_FALSE(val) ((void)0)
+
+#define DOCTEST_FAST_WARN_EQ(lhs, rhs) ((void)0)
+#define DOCTEST_FAST_CHECK_EQ(lhs, rhs) ((void)0)
+#define DOCTEST_FAST_REQUIRE_EQ(lhs, rhs) ((void)0)
+#define DOCTEST_FAST_WARN_NE(lhs, rhs) ((void)0)
+#define DOCTEST_FAST_CHECK_NE(lhs, rhs) ((void)0)
+#define DOCTEST_FAST_REQUIRE_NE(lhs, rhs) ((void)0)
+#define DOCTEST_FAST_WARN_GT(lhs, rhs) ((void)0)
+#define DOCTEST_FAST_CHECK_GT(lhs, rhs) ((void)0)
+#define DOCTEST_FAST_REQUIRE_GT(lhs, rhs) ((void)0)
+#define DOCTEST_FAST_WARN_LT(lhs, rhs) ((void)0)
+#define DOCTEST_FAST_CHECK_LT(lhs, rhs) ((void)0)
+#define DOCTEST_FAST_REQUIRE_LT(lhs, rhs) ((void)0)
+#define DOCTEST_FAST_WARN_GE(lhs, rhs) ((void)0)
+#define DOCTEST_FAST_CHECK_GE(lhs, rhs) ((void)0)
+#define DOCTEST_FAST_REQUIRE_GE(lhs, rhs) ((void)0)
+#define DOCTEST_FAST_WARN_LE(lhs, rhs) ((void)0)
+#define DOCTEST_FAST_CHECK_LE(lhs, rhs) ((void)0)
+#define DOCTEST_FAST_REQUIRE_LE(lhs, rhs) ((void)0)
+
+#define DOCTEST_FAST_WARN_UNARY(val) ((void)0)
+#define DOCTEST_FAST_CHECK_UNARY(val) ((void)0)
+#define DOCTEST_FAST_REQUIRE_UNARY(val) ((void)0)
+#define DOCTEST_FAST_WARN_UNARY_FALSE(val) ((void)0)
+#define DOCTEST_FAST_CHECK_UNARY_FALSE(val) ((void)0)
+#define DOCTEST_FAST_REQUIRE_UNARY_FALSE(val) ((void)0)
+
+#endif // DOCTEST_CONFIG_DISABLE
+
+// BDD style macros
+// clang-format off
+#define DOCTEST_SCENARIO(name) TEST_CASE(" Scenario: " name)
+#define DOCTEST_GIVEN(name) SUBCASE(" Given: " name)
+#define DOCTEST_WHEN(name) SUBCASE(" When: " name)
+#define DOCTEST_AND_WHEN(name) SUBCASE("And when: " name)
+#define DOCTEST_THEN(name) SUBCASE(" Then: " name)
+#define DOCTEST_AND_THEN(name) SUBCASE(" And: " name)
+// clang-format on
+
+// == SHORT VERSIONS OF THE MACROS
+#if !defined(DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES)
+
+#define TEST_CASE DOCTEST_TEST_CASE
+#define TEST_CASE_FIXTURE DOCTEST_TEST_CASE_FIXTURE
+#define SUBCASE DOCTEST_SUBCASE
+#define TEST_SUITE DOCTEST_TEST_SUITE
+#define TEST_SUITE_END DOCTEST_TEST_SUITE_END
+#define WARN DOCTEST_WARN
+#define WARN_FALSE DOCTEST_WARN_FALSE
+#define WARN_THROWS DOCTEST_WARN_THROWS
+#define WARN_THROWS_AS DOCTEST_WARN_THROWS_AS
+#define WARN_NOTHROW DOCTEST_WARN_NOTHROW
+#define CHECK DOCTEST_CHECK
+#define CHECK_FALSE DOCTEST_CHECK_FALSE
+#define CHECK_THROWS DOCTEST_CHECK_THROWS
+#define CHECK_THROWS_AS DOCTEST_CHECK_THROWS_AS
+#define CHECK_NOTHROW DOCTEST_CHECK_NOTHROW
+#define REQUIRE DOCTEST_REQUIRE
+#define REQUIRE_FALSE DOCTEST_REQUIRE_FALSE
+#define REQUIRE_THROWS DOCTEST_REQUIRE_THROWS
+#define REQUIRE_THROWS_AS DOCTEST_REQUIRE_THROWS_AS
+#define REQUIRE_NOTHROW DOCTEST_REQUIRE_NOTHROW
+
+#define SCENARIO DOCTEST_SCENARIO
+#define GIVEN DOCTEST_GIVEN
+#define WHEN DOCTEST_WHEN
+#define AND_WHEN DOCTEST_AND_WHEN
+#define THEN DOCTEST_THEN
+#define AND_THEN DOCTEST_AND_THEN
+
+#define WARN_EQ DOCTEST_WARN_EQ
+#define CHECK_EQ DOCTEST_CHECK_EQ
+#define REQUIRE_EQ DOCTEST_REQUIRE_EQ
+#define WARN_NE DOCTEST_WARN_NE
+#define CHECK_NE DOCTEST_CHECK_NE
+#define REQUIRE_NE DOCTEST_REQUIRE_NE
+#define WARN_GT DOCTEST_WARN_GT
+#define CHECK_GT DOCTEST_CHECK_GT
+#define REQUIRE_GT DOCTEST_REQUIRE_GT
+#define WARN_LT DOCTEST_WARN_LT
+#define CHECK_LT DOCTEST_CHECK_LT
+#define REQUIRE_LT DOCTEST_REQUIRE_LT
+#define WARN_GE DOCTEST_WARN_GE
+#define CHECK_GE DOCTEST_CHECK_GE
+#define REQUIRE_GE DOCTEST_REQUIRE_GE
+#define WARN_LE DOCTEST_WARN_LE
+#define CHECK_LE DOCTEST_CHECK_LE
+#define REQUIRE_LE DOCTEST_REQUIRE_LE
+#define WARN_UNARY DOCTEST_WARN_UNARY
+#define CHECK_UNARY DOCTEST_CHECK_UNARY
+#define REQUIRE_UNARY DOCTEST_REQUIRE_UNARY
+#define WARN_UNARY_FALSE DOCTEST_WARN_UNARY_FALSE
+#define CHECK_UNARY_FALSE DOCTEST_CHECK_UNARY_FALSE
+#define REQUIRE_UNARY_FALSE DOCTEST_REQUIRE_UNARY_FALSE
+
+#define FAST_WARN_EQ DOCTEST_FAST_WARN_EQ
+#define FAST_CHECK_EQ DOCTEST_FAST_CHECK_EQ
+#define FAST_REQUIRE_EQ DOCTEST_FAST_REQUIRE_EQ
+#define FAST_WARN_NE DOCTEST_FAST_WARN_NE
+#define FAST_CHECK_NE DOCTEST_FAST_CHECK_NE
+#define FAST_REQUIRE_NE DOCTEST_FAST_REQUIRE_NE
+#define FAST_WARN_GT DOCTEST_FAST_WARN_GT
+#define FAST_CHECK_GT DOCTEST_FAST_CHECK_GT
+#define FAST_REQUIRE_GT DOCTEST_FAST_REQUIRE_GT
+#define FAST_WARN_LT DOCTEST_FAST_WARN_LT
+#define FAST_CHECK_LT DOCTEST_FAST_CHECK_LT
+#define FAST_REQUIRE_LT DOCTEST_FAST_REQUIRE_LT
+#define FAST_WARN_GE DOCTEST_FAST_WARN_GE
+#define FAST_CHECK_GE DOCTEST_FAST_CHECK_GE
+#define FAST_REQUIRE_GE DOCTEST_FAST_REQUIRE_GE
+#define FAST_WARN_LE DOCTEST_FAST_WARN_LE
+#define FAST_CHECK_LE DOCTEST_FAST_CHECK_LE
+#define FAST_REQUIRE_LE DOCTEST_FAST_REQUIRE_LE
+#define FAST_WARN_UNARY DOCTEST_FAST_WARN_UNARY
+#define FAST_CHECK_UNARY DOCTEST_FAST_CHECK_UNARY
+#define FAST_REQUIRE_UNARY DOCTEST_FAST_REQUIRE_UNARY
+#define FAST_WARN_UNARY_FALSE DOCTEST_FAST_WARN_UNARY_FALSE
+#define FAST_CHECK_UNARY_FALSE DOCTEST_FAST_CHECK_UNARY_FALSE
+#define FAST_REQUIRE_UNARY_FALSE DOCTEST_FAST_REQUIRE_UNARY_FALSE
+
+#endif // DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES
+
+// this is here to clear the 'current test suite' for the current translation unit - at the top
+DOCTEST_TEST_SUITE_END();
+
+#endif // DOCTEST_LIBRARY_INCLUDED
+
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif // __clang__
+
+#if defined(__GNUC__) && !defined(__clang__)
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6)
+#pragma GCC diagnostic pop
+#endif // > gcc 4.6
+#endif // __GNUC__
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif // _MSC_VER
+
+#ifndef DOCTEST_SINGLE_HEADER
+#define DOCTEST_SINGLE_HEADER
+#endif // DOCTEST_SINGLE_HEADER
+
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunknown-pragmas"
+#pragma clang diagnostic ignored "-Wpadded"
+#pragma clang diagnostic ignored "-Wglobal-constructors"
+#pragma clang diagnostic ignored "-Wexit-time-destructors"
+#pragma clang diagnostic ignored "-Wmissing-prototypes"
+#pragma clang diagnostic ignored "-Wsign-conversion"
+#pragma clang diagnostic ignored "-Wshorten-64-to-32"
+#pragma clang diagnostic ignored "-Wmissing-variable-declarations"
+#pragma clang diagnostic ignored "-Wswitch"
+#pragma clang diagnostic ignored "-Wswitch-enum"
+#pragma clang diagnostic ignored "-Wcovered-switch-default"
+#pragma clang diagnostic ignored "-Wmissing-noreturn"
+#pragma clang diagnostic ignored "-Wunused-local-typedef"
+#endif // __clang__
+
+#if defined(__GNUC__) && !defined(__clang__)
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6)
+#pragma GCC diagnostic push
+#endif // > gcc 4.6
+#pragma GCC diagnostic ignored "-Wunknown-pragmas"
+#pragma GCC diagnostic ignored "-Wconversion"
+#pragma GCC diagnostic ignored "-Weffc++"
+#pragma GCC diagnostic ignored "-Wsign-conversion"
+#pragma GCC diagnostic ignored "-Wstrict-overflow"
+#pragma GCC diagnostic ignored "-Wmissing-declarations"
+#pragma GCC diagnostic ignored "-Winline"
+#pragma GCC diagnostic ignored "-Wswitch"
+#pragma GCC diagnostic ignored "-Wswitch-enum"
+#pragma GCC diagnostic ignored "-Wswitch-default"
+#pragma GCC diagnostic ignored "-Wunsafe-loop-optimizations"
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6)
+#pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
+#endif // > gcc 4.6
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 7)
+#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
+#endif // > gcc 4.7
+#if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ > 3)
+#pragma GCC diagnostic ignored "-Wuseless-cast"
+#endif // > gcc 5.3
+#endif // __GNUC__
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 4996) // The compiler encountered a deprecated declaration
+#pragma warning(disable : 4267) // 'var' : conversion from 'size_t' to 'type', possible loss of data
+#pragma warning(disable : 4706) // assignment within conditional expression
+#pragma warning(disable : 4512) // 'class' : assignment operator could not be generated
+#pragma warning(disable : 4127) // conditional expression is constant
+#pragma warning(disable : 4530) // C++ exception handler used, but unwind semantics are not enabled
+#pragma warning(disable : 4577) // 'noexcept' used with no exception handling mode specified
+#endif // _MSC_VER
+
+#if defined(DOCTEST_CONFIG_IMPLEMENT) || defined(DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN) || \
+ !defined(DOCTEST_SINGLE_HEADER)
+#ifndef DOCTEST_LIBRARY_IMPLEMENTATION
+#define DOCTEST_LIBRARY_IMPLEMENTATION
+
+#ifndef DOCTEST_SINGLE_HEADER
+#include "doctest_fwd.h"
+#endif // DOCTEST_SINGLE_HEADER
+
+#if defined(__clang__) && defined(DOCTEST_NO_CPP11_COMPAT)
+#pragma clang diagnostic ignored "-Wc++98-compat"
+#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
+#endif // __clang__ && DOCTEST_NO_CPP11_COMPAT
+
+// snprintf() not in the C++98 standard
+#ifdef _MSC_VER
+#define DOCTEST_SNPRINTF _snprintf
+#else
+#define DOCTEST_SNPRINTF snprintf
+#endif
+
+#define DOCTEST_LOG_START() \
+ do { \
+ if(!DOCTEST_GCS().hasLoggedCurrentTestStart) { \
+ doctest::detail::logTestStart(DOCTEST_GCS().currentTest->m_name, \
+ DOCTEST_GCS().currentTest->m_file, \
+ DOCTEST_GCS().currentTest->m_line); \
+ DOCTEST_GCS().hasLoggedCurrentTestStart = true; \
+ } \
+ } while(doctest::detail::always_false())
+
+// required includes - will go only in one translation unit!
+#include <ctime>
+#include <cmath>
+// borland (Embarcadero) compiler requires math.h and not cmath - https://github.com/onqtam/doctest/pull/37
+#ifdef __BORLANDC__
+#include <math.h>
+#endif // __BORLANDC__
+#include <new>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <limits>
+#include <utility>
+#include <sstream>
+#include <iomanip>
+#include <vector>
+#include <set>
+
+namespace doctest
+{
+namespace detail
+{
+ // not using std::strlen() because of valgrind errors when optimizations are turned on
+ // 'Invalid read of size 4' when the test suite len (with '\0') is not a multiple of 4
+ // for details see http://stackoverflow.com/questions/35671155
+ size_t my_strlen(const char* in) {
+ const char* temp = in;
+ while(temp && *temp)
+ ++temp;
+ return temp - in;
+ }
+
+ template <typename T>
+ T my_max(const T& lhs, const T& rhs) {
+ return lhs > rhs ? lhs : rhs;
+ }
+
+ // case insensitive strcmp
+ int stricmp(char const* a, char const* b) {
+ for(;; a++, b++) {
+ int d = tolower(*a) - tolower(*b);
+ if(d != 0 || !*a)
+ return d;
+ }
+ }
+
+ template <typename T>
+ String fpToString(T value, int precision) {
+ std::ostringstream oss;
+ oss << std::setprecision(precision) << std::fixed << value;
+ std::string d = oss.str();
+ size_t i = d.find_last_not_of('0');
+ if(i != std::string::npos && i != d.size() - 1) {
+ if(d[i] == '.')
+ i++;
+ d = d.substr(0, i + 1);
+ }
+ return d.c_str();
+ }
+
+ struct Endianness
+ {
+ enum Arch
+ {
+ Big,
+ Little
+ };
+
+ static Arch which() {
+ union _
+ {
+ int asInt;
+ char asChar[sizeof(int)];
+ } u;
+
+ u.asInt = 1;
+ return (u.asChar[sizeof(int) - 1] == 1) ? Big : Little;
+ }
+ };
+
+ String rawMemoryToString(const void* object, unsigned size) {
+ // Reverse order for little endian architectures
+ int i = 0, end = static_cast<int>(size), inc = 1;
+ if(Endianness::which() == Endianness::Little) {
+ i = end - 1;
+ end = inc = -1;
+ }
+
+ unsigned char const* bytes = static_cast<unsigned char const*>(object);
+ std::ostringstream os;
+ os << "0x" << std::setfill('0') << std::hex;
+ for(; i != end; i += inc)
+ os << std::setw(2) << static_cast<unsigned>(bytes[i]);
+ return os.str().c_str();
+ }
+
+ std::ostream* createStream() { return new std::ostringstream(); }
+ String getStreamResult(std::ostream* in) {
+ return static_cast<std::ostringstream*>(in)->str().c_str();
+ }
+ void freeStream(std::ostream* in) { delete in; }
+
+#ifndef DOCTEST_CONFIG_DISABLE
+
+ // this holds both parameters for the command line and runtime data for tests
+ struct ContextState : TestAccessibleContextState
+ {
+ // == parameters from the command line
+
+ std::vector<std::vector<String> > filters;
+
+ String order_by; // how tests should be ordered
+ unsigned rand_seed; // the seed for rand ordering
+
+ unsigned first; // the first (matching) test to be executed
+ unsigned last; // the last (matching) test to be executed
+
+ int abort_after; // stop tests after this many failed assertions
+ bool case_sensitive; // if filtering should be case sensitive
+ bool exit; // if the program should be exited after the tests are ran/whatever
+ bool no_exitcode; // if the framework should return 0 as the exitcode
+ bool no_run; // to not run the tests at all (can be done with an "*" exclude)
+ bool no_version; // to not print the version of the framework
+ bool no_colors; // if output to the console should be colorized
+ bool no_path_in_filenames; // if the path to files should be removed from the output
+
+ bool help; // to print the help
+ bool version; // to print the version
+ bool count; // if only the count of matching tests is to be retreived
+ bool list_test_cases; // to list all tests matching the filters
+ bool list_test_suites; // to list all suites matching the filters
+
+ // == data for the tests being ran
+
+ int numAssertions;
+ int numFailedAssertions;
+ int numFailedAssertionsForCurrentTestcase;
+
+ // stuff for subcases
+ std::set<SubcaseSignature> subcasesPassed;
+ std::set<int> subcasesEnteredLevels;
+ std::vector<Subcase> subcasesStack;
+ int subcasesCurrentLevel;
+ bool subcasesHasSkipped;
+
+ void resetRunData() {
+ numAssertions = 0;
+ numFailedAssertions = 0;
+ }
+
+ ContextState()
+ : filters(6) // 6 different filters total
+ {
+ resetRunData();
+ }
+ };
+
+ ContextState*& getContextState();
+#endif // DOCTEST_CONFIG_DISABLE
+} // namespace detail
+
+String::String(const char* in)
+ : m_str(static_cast<char*>(malloc(detail::my_strlen(in) + 1))) {
+ if(in)
+ strcpy(m_str, in);
+ else
+ m_str[0] = '\0';
+}
+
+String::String(const String& other)
+ : m_str(0) {
+ copy(other);
+}
+
+void String::copy(const String& other) {
+ if(m_str)
+ free(m_str);
+ m_str = static_cast<char*>(malloc(detail::my_strlen(other.m_str) + 1));
+ strcpy(m_str, other.m_str);
+}
+
+String::~String() { free(m_str); }
+
+String& String::operator=(const String& other) {
+ if(this != &other)
+ copy(other);
+ return *this;
+}
+
+String String::operator+(const String& other) const { return String(m_str) += other; }
+
+String& String::operator+=(const String& other) {
+ using namespace detail;
+ if(other.m_str != 0) {
+ char* newStr = static_cast<char*>(malloc(my_strlen(m_str) + my_strlen(other.m_str) + 1));
+ strcpy(newStr, m_str);
+ strcpy(newStr + my_strlen(m_str), other.m_str);
+ free(m_str);
+ m_str = newStr;
+ }
+ return *this;
+}
+
+unsigned String::size() const { return m_str ? detail::my_strlen(m_str) : 0; }
+unsigned String::length() const { return size(); }
+
+int String::compare(const char* other, bool no_case) const {
+ if(no_case)
+ return detail::stricmp(m_str, other);
+ return strcmp(m_str, other);
+}
+
+int String::compare(const String& other, bool no_case) const {
+ if(no_case)
+ return detail::stricmp(m_str, other.m_str);
+ return strcmp(m_str, other.m_str);
+}
+
+std::ostream& operator<<(std::ostream& stream, const String& in) {
+ stream << in.c_str();
+ return stream;
+}
+
+Approx::Approx(double value)
+ : m_epsilon(static_cast<double>(std::numeric_limits<float>::epsilon()) * 100)
+ , m_scale(1.0)
+ , m_value(value) {}
+
+bool operator==(double lhs, Approx const& rhs) {
+ // Thanks to Richard Harris for his help refining this formula
+ return fabs(lhs - rhs.m_value) <
+ rhs.m_epsilon * (rhs.m_scale + detail::my_max(fabs(lhs), fabs(rhs.m_value)));
+}
+
+String Approx::toString() const { return String("Approx( ") + doctest::toString(m_value) + " )"; }
+
+#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+String toString(char* in) { return toString(static_cast<const char*>(in)); }
+String toString(const char* in) { return String("\"") + (in ? in : "{null string}") + "\""; }
+#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+String toString(bool in) { return in ? "true" : "false"; }
+String toString(float in) { return detail::fpToString(in, 5) + "f"; }
+String toString(double in) { return detail::fpToString(in, 10); }
+String toString(double long in) { return detail::fpToString(in, 15); }
+
+String toString(char in) {
+ char buf[64];
+ sprintf(buf, "%d", in);
+ return buf;
+}
+
+String toString(char unsigned in) {
+ char buf[64];
+ sprintf(buf, "%ud", in);
+ return buf;
+}
+
+String toString(int short in) {
+ char buf[64];
+ sprintf(buf, "%d", in);
+ return buf;
+}
+
+String toString(int short unsigned in) {
+ char buf[64];
+ sprintf(buf, "%u", in);
+ return buf;
+}
+
+String toString(int in) {
+ char buf[64];
+ sprintf(buf, "%d", in);
+ return buf;
+}
+
+String toString(int unsigned in) {
+ char buf[64];
+ sprintf(buf, "%u", in);
+ return buf;
+}
+
+String toString(int long in) {
+ char buf[64];
+ sprintf(buf, "%ld", in);
+ return buf;
+}
+
+String toString(int long unsigned in) {
+ char buf[64];
+ sprintf(buf, "%lu", in);
+ return buf;
+}
+
+#ifdef DOCTEST_CONFIG_WITH_LONG_LONG
+String toString(int long long in) {
+ char buf[64];
+ sprintf(buf, "%lld", in);
+ return buf;
+}
+String toString(int long long unsigned in) {
+ char buf[64];
+ sprintf(buf, "%llu", in);
+ return buf;
+}
+#endif // DOCTEST_CONFIG_WITH_LONG_LONG
+
+#ifdef DOCTEST_CONFIG_WITH_NULLPTR
+String toString(std::nullptr_t) { return "nullptr"; }
+#endif // DOCTEST_CONFIG_WITH_NULLPTR
+
+} // namespace doctest
+
+#if defined(DOCTEST_CONFIG_DISABLE)
+namespace doctest
+{
+Context::Context(int, const char* const*) {}
+Context::~Context() {}
+void Context::applyCommandLine(int, const char* const*) {}
+void Context::addFilter(const char*, const char*) {}
+void Context::clearFilters() {}
+void Context::setOption(const char*, int) {}
+void Context::setOption(const char*, const char*) {}
+bool Context::shouldExit() { return false; }
+int Context::run() { return 0; }
+} // namespace doctest
+#else // DOCTEST_CONFIG_DISABLE
+
+#if !defined(DOCTEST_CONFIG_COLORS_NONE)
+#if !defined(DOCTEST_CONFIG_COLORS_WINDOWS) && !defined(DOCTEST_CONFIG_COLORS_ANSI)
+#ifdef DOCTEST_PLATFORM_WINDOWS
+#define DOCTEST_CONFIG_COLORS_WINDOWS
+#else // linux
+#define DOCTEST_CONFIG_COLORS_ANSI
+#endif // platform
+#endif // DOCTEST_CONFIG_COLORS_WINDOWS && DOCTEST_CONFIG_COLORS_ANSI
+#endif // DOCTEST_CONFIG_COLORS_NONE
+
+#define DOCTEST_PRINTF_COLORED(buffer, color) \
+ do { \
+ if(buffer[0] != 0) { \
+ doctest::detail::Color col(color); \
+ printf("%s", buffer); \
+ } \
+ } while(doctest::detail::always_false())
+
+// the buffer size used for snprintf() calls
+#if !defined(DOCTEST_SNPRINTF_BUFFER_LENGTH)
+#define DOCTEST_SNPRINTF_BUFFER_LENGTH 1024
+#endif // DOCTEST_SNPRINTF_BUFFER_LENGTH
+
+#if defined(_MSC_VER) || defined(__MINGW32__)
+#if defined(_MSC_VER) && _MSC_VER >= 1700
+#define DOCTEST_WINDOWS_SAL_IN_OPT _In_opt_
+#else // _MSC_VER
+#define DOCTEST_WINDOWS_SAL_IN_OPT
+#endif // _MSC_VER
+extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA(
+ DOCTEST_WINDOWS_SAL_IN_OPT const char*);
+extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
+#endif // _MSC_VER || __MINGW32__
+
+#ifdef DOCTEST_CONFIG_COLORS_ANSI
+#include <unistd.h>
+#endif // DOCTEST_CONFIG_COLORS_ANSI
+
+#ifdef DOCTEST_CONFIG_COLORS_WINDOWS
+
+// defines for a leaner windows.h
+#ifndef WIN32_MEAN_AND_LEAN
+#define WIN32_MEAN_AND_LEAN
+#endif // WIN32_MEAN_AND_LEAN
+#ifndef VC_EXTRA_LEAN
+#define VC_EXTRA_LEAN
+#endif // VC_EXTRA_LEAN
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif // NOMINMAX
+
+// not sure what AfxWin.h is for - here I do what Catch does
+#ifdef __AFXDLL
+#include <AfxWin.h>
+#else
+#include <windows.h>
+#endif
+
+#endif // DOCTEST_CONFIG_COLORS_WINDOWS
+
+namespace doctest
+{
+namespace detail
+{
+ bool TestData::operator<(const TestData& other) const {
+ if(m_line != other.m_line)
+ return m_line < other.m_line;
+ return strcmp(m_file, other.m_file) < 0;
+ }
+
+ const char* getAssertString(assertType::Enum val) {
+ switch(val) {
+ // clang-format off
+ case assertType::DT_WARN : return "WARN";
+ case assertType::DT_CHECK : return "CHECK";
+ case assertType::DT_REQUIRE : return "REQUIRE";
+
+ case assertType::DT_WARN_FALSE : return "WARN_FALSE";
+ case assertType::DT_CHECK_FALSE : return "CHECK_FALSE";
+ case assertType::DT_REQUIRE_FALSE : return "REQUIRE_FALSE";
+
+ case assertType::DT_WARN_THROWS : return "WARN_THROWS";
+ case assertType::DT_CHECK_THROWS : return "CHECK_THROWS";
+ case assertType::DT_REQUIRE_THROWS : return "REQUIRE_THROWS";
+
+ case assertType::DT_WARN_THROWS_AS : return "WARN_THROWS_AS";
+ case assertType::DT_CHECK_THROWS_AS : return "CHECK_THROWS_AS";
+ case assertType::DT_REQUIRE_THROWS_AS : return "REQUIRE_THROWS_AS";
+
+ case assertType::DT_WARN_NOTHROW : return "WARN_NOTHROW";
+ case assertType::DT_CHECK_NOTHROW : return "CHECK_NOTHROW";
+ case assertType::DT_REQUIRE_NOTHROW : return "REQUIRE_NOTHROW";
+
+ case assertType::DT_WARN_EQ : return "WARN_EQ";
+ case assertType::DT_CHECK_EQ : return "CHECK_EQ";
+ case assertType::DT_REQUIRE_EQ : return "REQUIRE_EQ";
+ case assertType::DT_WARN_NE : return "WARN_NE";
+ case assertType::DT_CHECK_NE : return "CHECK_NE";
+ case assertType::DT_REQUIRE_NE : return "REQUIRE_NE";
+ case assertType::DT_WARN_GT : return "WARN_GT";
+ case assertType::DT_CHECK_GT : return "CHECK_GT";
+ case assertType::DT_REQUIRE_GT : return "REQUIRE_GT";
+ case assertType::DT_WARN_LT : return "WARN_LT";
+ case assertType::DT_CHECK_LT : return "CHECK_LT";
+ case assertType::DT_REQUIRE_LT : return "REQUIRE_LT";
+ case assertType::DT_WARN_GE : return "WARN_GE";
+ case assertType::DT_CHECK_GE : return "CHECK_GE";
+ case assertType::DT_REQUIRE_GE : return "REQUIRE_GE";
+ case assertType::DT_WARN_LE : return "WARN_LE";
+ case assertType::DT_CHECK_LE : return "CHECK_LE";
+ case assertType::DT_REQUIRE_LE : return "REQUIRE_LE";
+
+ case assertType::DT_WARN_UNARY : return "WARN_UNARY";
+ case assertType::DT_CHECK_UNARY : return "CHECK_UNARY";
+ case assertType::DT_REQUIRE_UNARY : return "REQUIRE_UNARY";
+ case assertType::DT_WARN_UNARY_FALSE : return "WARN_UNARY_FALSE";
+ case assertType::DT_CHECK_UNARY_FALSE : return "CHECK_UNARY_FALSE";
+ case assertType::DT_REQUIRE_UNARY_FALSE : return "REQUIRE_UNARY_FALSE";
+
+ case assertType::DT_FAST_WARN_EQ : return "FAST_WARN_EQ";
+ case assertType::DT_FAST_CHECK_EQ : return "FAST_CHECK_EQ";
+ case assertType::DT_FAST_REQUIRE_EQ : return "FAST_REQUIRE_EQ";
+ case assertType::DT_FAST_WARN_NE : return "FAST_WARN_NE";
+ case assertType::DT_FAST_CHECK_NE : return "FAST_CHECK_NE";
+ case assertType::DT_FAST_REQUIRE_NE : return "FAST_REQUIRE_NE";
+ case assertType::DT_FAST_WARN_GT : return "FAST_WARN_GT";
+ case assertType::DT_FAST_CHECK_GT : return "FAST_CHECK_GT";
+ case assertType::DT_FAST_REQUIRE_GT : return "FAST_REQUIRE_GT";
+ case assertType::DT_FAST_WARN_LT : return "FAST_WARN_LT";
+ case assertType::DT_FAST_CHECK_LT : return "FAST_CHECK_LT";
+ case assertType::DT_FAST_REQUIRE_LT : return "FAST_REQUIRE_LT";
+ case assertType::DT_FAST_WARN_GE : return "FAST_WARN_GE";
+ case assertType::DT_FAST_CHECK_GE : return "FAST_CHECK_GE";
+ case assertType::DT_FAST_REQUIRE_GE : return "FAST_REQUIRE_GE";
+ case assertType::DT_FAST_WARN_LE : return "FAST_WARN_LE";
+ case assertType::DT_FAST_CHECK_LE : return "FAST_CHECK_LE";
+ case assertType::DT_FAST_REQUIRE_LE : return "FAST_REQUIRE_LE";
+
+ case assertType::DT_FAST_WARN_UNARY : return "FAST_WARN_UNARY";
+ case assertType::DT_FAST_CHECK_UNARY : return "FAST_CHECK_UNARY";
+ case assertType::DT_FAST_REQUIRE_UNARY : return "FAST_REQUIRE_UNARY";
+ case assertType::DT_FAST_WARN_UNARY_FALSE : return "FAST_WARN_UNARY_FALSE";
+ case assertType::DT_FAST_CHECK_UNARY_FALSE : return "FAST_CHECK_UNARY_FALSE";
+ case assertType::DT_FAST_REQUIRE_UNARY_FALSE: return "FAST_REQUIRE_UNARY_FALSE";
+ // clang-format on
+ }
+ return "";
+ }
+
+ bool checkIfShouldThrow(assertType::Enum assert_type) {
+ if(assert_type & assertType::is_require)
+ return true;
+
+ if((assert_type & assertType::is_check) && getContextState()->abort_after > 0) {
+ if(getContextState()->numFailedAssertions >= getContextState()->abort_after)
+ return true;
+ }
+
+ return false;
+ }
+ void fastAssertThrowIfFlagSet(int flags) {
+ if(flags & assertAction::shouldthrow)
+ throwException();
+ }
+ void throwException() {
+#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
+ throw TestFailureException();
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
+ }
+ bool always_false() { return false; }
+
+ // lowers ascii letters
+ char tolower(const char c) { return ((c >= 'A' && c <= 'Z') ? static_cast<char>(c + 32) : c); }
+
+ // matching of a string against a wildcard mask (case sensitivity configurable) taken from
+ // http://www.emoticode.net/c/simple-wildcard-string-compare-globbing-function.html
+ int wildcmp(const char* str, const char* wild, bool caseSensitive) {
+ const char* cp = 0;
+ const char* mp = 0;
+
+ // rolled my own tolower() to not include more headers
+ while((*str) && (*wild != '*')) {
+ if((caseSensitive ? (*wild != *str) : (tolower(*wild) != tolower(*str))) &&
+ (*wild != '?')) {
+ return 0;
+ }
+ wild++;
+ str++;
+ }
+
+ while(*str) {
+ if(*wild == '*') {
+ if(!*++wild) {
+ return 1;
+ }
+ mp = wild;
+ cp = str + 1;
+ } else if((caseSensitive ? (*wild == *str) : (tolower(*wild) == tolower(*str))) ||
+ (*wild == '?')) {
+ wild++;
+ str++;
+ } else {
+ wild = mp;
+ str = cp++;
+ }
+ }
+
+ while(*wild == '*') {
+ wild++;
+ }
+ return !*wild;
+ }
+
+ //// C string hash function (djb2) - taken from http://www.cse.yorku.ca/~oz/hash.html
+ //unsigned hashStr(unsigned const char* str) {
+ // unsigned long hash = 5381;
+ // char c;
+ // while((c = *str++))
+ // hash = ((hash << 5) + hash) + c; // hash * 33 + c
+ // return hash;
+ //}
+
+ // checks if the name matches any of the filters (and can be configured what to do when empty)
+ int matchesAny(const char* name, std::vector<String> filters, int matchEmpty,
+ bool caseSensitive) {
+ if(filters.size() == 0 && matchEmpty)
+ return 1;
+ for(unsigned i = 0; i < filters.size(); ++i)
+ if(wildcmp(name, filters[i].c_str(), caseSensitive))
+ return 1;
+ return 0;
+ }
+
+ // the current ContextState with which tests are being executed
+ ContextState*& getContextState() {
+ static ContextState* data = 0;
+ return data;
+ }
+
+ TestAccessibleContextState* getTestsContextState() { return getContextState(); }
+
+ bool SubcaseSignature::operator<(const SubcaseSignature& other) const {
+ if(m_line != other.m_line)
+ return m_line < other.m_line;
+ if(strcmp(m_file, other.m_file) != 0)
+ return strcmp(m_file, other.m_file) < 0;
+ return strcmp(m_name, other.m_name) < 0;
+ }
+
+ Subcase::Subcase(const char* name, const char* file, int line)
+ : m_signature(name, file, line)
+ , m_entered(false) {
+ ContextState* s = getContextState();
+
+ // if we have already completed it
+ if(s->subcasesPassed.count(m_signature) != 0)
+ return;
+
+ // if a Subcase on the same level has already been entered
+ if(s->subcasesEnteredLevels.count(s->subcasesCurrentLevel) != 0) {
+ s->subcasesHasSkipped = true;
+ return;
+ }
+
+ s->subcasesStack.push_back(*this);
+ if(s->hasLoggedCurrentTestStart)
+ logTestEnd();
+ s->hasLoggedCurrentTestStart = false;
+
+ s->subcasesEnteredLevels.insert(s->subcasesCurrentLevel++);
+ m_entered = true;
+ }
+
+ Subcase::Subcase(const Subcase& other)
+ : m_signature(other.m_signature.m_name, other.m_signature.m_file,
+ other.m_signature.m_line)
+ , m_entered(other.m_entered) {}
+
+ Subcase::~Subcase() {
+ if(m_entered) {
+ ContextState* s = getContextState();
+
+ s->subcasesCurrentLevel--;
+ // only mark the subcase as passed if no subcases have been skipped
+ if(s->subcasesHasSkipped == false)
+ s->subcasesPassed.insert(m_signature);
+
+ if(s->subcasesStack.size() > 0)
+ s->subcasesStack.pop_back();
+ if(s->hasLoggedCurrentTestStart)
+ logTestEnd();
+ s->hasLoggedCurrentTestStart = false;
+ }
+ }
+
+ // for sorting tests by file/line
+ int fileOrderComparator(const void* a, const void* b) {
+ const TestData* lhs = *static_cast<TestData* const*>(a);
+ const TestData* rhs = *static_cast<TestData* const*>(b);
+#ifdef _MSC_VER
+ // this is needed because MSVC gives different case for drive letters
+ // for __FILE__ when evaluated in a header and a source file
+ int res = stricmp(lhs->m_file, rhs->m_file);
+#else // _MSC_VER
+ int res = strcmp(lhs->m_file, rhs->m_file);
+#endif // _MSC_VER
+ if(res != 0)
+ return res;
+ return static_cast<int>(lhs->m_line - rhs->m_line);
+ }
+
+ // for sorting tests by suite/file/line
+ int suiteOrderComparator(const void* a, const void* b) {
+ const TestData* lhs = *static_cast<TestData* const*>(a);
+ const TestData* rhs = *static_cast<TestData* const*>(b);
+
+ int res = strcmp(lhs->m_suite, rhs->m_suite);
+ if(res != 0)
+ return res;
+ return fileOrderComparator(a, b);
+ }
+
+ // for sorting tests by name/suite/file/line
+ int nameOrderComparator(const void* a, const void* b) {
+ const TestData* lhs = *static_cast<TestData* const*>(a);
+ const TestData* rhs = *static_cast<TestData* const*>(b);
+
+ int res = strcmp(lhs->m_name, rhs->m_name);
+ if(res != 0)
+ return res;
+ return suiteOrderComparator(a, b);
+ }
+
+ // holds the current test suite
+ const char*& getCurrentTestSuite() {
+ static const char* data = 0;
+ return data;
+ }
+
+ // sets the current test suite
+ int setTestSuiteName(const char* name) {
+ getCurrentTestSuite() = name;
+ return 0;
+ }
+
+ // all the registered tests
+ std::set<TestData>& getRegisteredTests() {
+ static std::set<TestData> data;
+ return data;
+ }
+
+ // used by the macros for registering tests
+ int regTest(funcType f, unsigned line, const char* file, const char* name) {
+ getRegisteredTests().insert(TestData(getCurrentTestSuite(), name, f, file, line));
+ return 0;
+ }
+
+ struct Color
+ {
+ enum Code
+ {
+ None = 0,
+ White,
+ Red,
+ Green,
+ Blue,
+ Cyan,
+ Yellow,
+ Grey,
+
+ Bright = 0x10,
+
+ BrightRed = Bright | Red,
+ BrightGreen = Bright | Green,
+ LightGrey = Bright | Grey,
+ BrightWhite = Bright | White
+ };
+ Color(Code code) { use(code); }
+ ~Color() { use(None); }
+
+ void use(Code code);
+
+ private:
+ Color(Color const& other);
+ };
+
+ void Color::use(Code
+#ifndef DOCTEST_CONFIG_COLORS_NONE
+ code
+#endif // DOCTEST_CONFIG_COLORS_NONE
+ ) {
+ ContextState* p = getContextState();
+ if(p->no_colors)
+ return;
+#ifdef DOCTEST_CONFIG_COLORS_ANSI
+ if(isatty(STDOUT_FILENO)) {
+ const char* col = "";
+ // clang-format off
+ switch(code) {
+ case Color::Red: col = "[0;31m"; break;
+ case Color::Green: col = "[0;32m"; break;
+ case Color::Blue: col = "[0;34m"; break;
+ case Color::Cyan: col = "[0;36m"; break;
+ case Color::Yellow: col = "[0;33m"; break;
+ case Color::Grey: col = "[1;30m"; break;
+ case Color::LightGrey: col = "[0;37m"; break;
+ case Color::BrightRed: col = "[1;31m"; break;
+ case Color::BrightGreen: col = "[1;32m"; break;
+ case Color::BrightWhite: col = "[1;37m"; break;
+ case Color::Bright: // invalid
+ case Color::None:
+ case Color::White:
+ default: col = "[0m";
+ }
+ // clang-format on
+ printf("\033%s", col);
+ }
+#endif // DOCTEST_CONFIG_COLORS_ANSI
+
+#ifdef DOCTEST_CONFIG_COLORS_WINDOWS
+ static HANDLE stdoutHandle(GetStdHandle(STD_OUTPUT_HANDLE));
+ static WORD originalForegroundAttributes;
+ static WORD originalBackgroundAttributes;
+ static bool attrsInitted = false;
+ if(!attrsInitted) {
+ attrsInitted = true;
+ CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
+ GetConsoleScreenBufferInfo(stdoutHandle, &csbiInfo);
+ originalForegroundAttributes =
+ csbiInfo.wAttributes &
+ ~(BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY);
+ originalBackgroundAttributes =
+ csbiInfo.wAttributes &
+ ~(FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
+ }
+
+#define DOCTEST_SET_ATTR(x) SetConsoleTextAttribute(stdoutHandle, x | originalBackgroundAttributes)
+
+ // clang-format off
+ switch (code) {
+ case Color::White: DOCTEST_SET_ATTR(FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE); break;
+ case Color::Red: DOCTEST_SET_ATTR(FOREGROUND_RED); break;
+ case Color::Green: DOCTEST_SET_ATTR(FOREGROUND_GREEN); break;
+ case Color::Blue: DOCTEST_SET_ATTR(FOREGROUND_BLUE); break;
+ case Color::Cyan: DOCTEST_SET_ATTR(FOREGROUND_BLUE | FOREGROUND_GREEN); break;
+ case Color::Yellow: DOCTEST_SET_ATTR(FOREGROUND_RED | FOREGROUND_GREEN); break;
+ case Color::Grey: DOCTEST_SET_ATTR(0); break;
+ case Color::LightGrey: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY); break;
+ case Color::BrightRed: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_RED); break;
+ case Color::BrightGreen: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_GREEN); break;
+ case Color::BrightWhite: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE); break;
+ case Color::None:
+ case Color::Bright: // invalid
+ default: DOCTEST_SET_ATTR(originalForegroundAttributes);
+ }
+// clang-format on
+#undef DOCTEST_SET_ATTR
+#endif // DOCTEST_CONFIG_COLORS_WINDOWS
+ }
+
+ // this is needed because MSVC does not permit mixing 2 exception handling schemes in a function
+ int callTestFunc(funcType f) {
+ int res = EXIT_SUCCESS;
+#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
+ try {
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
+ f();
+ if(getContextState()->numFailedAssertionsForCurrentTestcase)
+ res = EXIT_FAILURE;
+#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
+ } catch(const TestFailureException&) { res = EXIT_FAILURE; } catch(...) {
+ DOCTEST_LOG_START();
+ logTestCrashed();
+ res = EXIT_FAILURE;
+ }
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
+ return res;
+ }
+
+ // depending on the current options this will remove the path of filenames
+ const char* fileForOutput(const char* file) {
+ if(getContextState()->no_path_in_filenames) {
+ const char* back = strrchr(file, '\\');
+ const char* forward = strrchr(file, '/');
+ if(back || forward) {
+ if(back > forward)
+ forward = back;
+ return forward + 1;
+ }
+ }
+ return file;
+ }
+
+#ifdef DOCTEST_PLATFORM_MAC
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/sysctl.h>
+ // The following function is taken directly from the following technical note:
+ // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
+ // Returns true if the current process is being debugged (either
+ // running under the debugger or has a debugger attached post facto).
+ bool isDebuggerActive() {
+ int mib[4];
+ struct kinfo_proc info;
+ size_t size;
+ // Initialize the flags so that, if sysctl fails for some bizarre
+ // reason, we get a predictable result.
+ info.kp_proc.p_flag = 0;
+ // Initialize mib, which tells sysctl the info we want, in this case
+ // we're looking for information about a specific process ID.
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PID;
+ mib[3] = getpid();
+ // Call sysctl.
+ size = sizeof(info);
+ if(sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, 0, 0) != 0) {
+ fprintf(stderr, "\n** Call to sysctl failed - unable to determine if debugger is "
+ "active **\n\n");
+ return false;
+ }
+ // We're being debugged if the P_TRACED flag is set.
+ return ((info.kp_proc.p_flag & P_TRACED) != 0);
+ }
+#elif defined(_MSC_VER) || defined(__MINGW32__)
+ bool isDebuggerActive() { return ::IsDebuggerPresent() != 0; }
+#else
+ bool isDebuggerActive() { return false; }
+#endif // Platform
+
+#ifdef DOCTEST_PLATFORM_WINDOWS
+ void myOutputDebugString(const String& text) { ::OutputDebugStringA(text.c_str()); }
+#else
+ // TODO: integration with XCode and other IDEs
+ void myOutputDebugString(const String&) {}
+#endif // Platform
+
+ const char* getSeparator() {
+ return "===============================================================================\n";
+ }
+
+ void printToDebugConsole(const String& text) {
+ if(isDebuggerActive())
+ myOutputDebugString(text.c_str());
+ }
+
+ void addFailedAssert(assertType::Enum assert_type) {
+ if((assert_type & assertType::is_warn) == 0) {
+ getContextState()->numFailedAssertionsForCurrentTestcase++;
+ getContextState()->numFailedAssertions++;
+ }
+ }
+
+ void logTestStart(const char* name, const char* file, unsigned line) {
+ const char* newLine = "\n";
+
+ char loc[DOCTEST_SNPRINTF_BUFFER_LENGTH];
+ DOCTEST_SNPRINTF(loc, DOCTEST_COUNTOF(loc), "%s(%d)\n", fileForOutput(file), line);
+
+ char msg[DOCTEST_SNPRINTF_BUFFER_LENGTH];
+ DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), "%s\n", name);
+
+ DOCTEST_PRINTF_COLORED(getSeparator(), Color::Yellow);
+ DOCTEST_PRINTF_COLORED(loc, Color::LightGrey);
+ DOCTEST_PRINTF_COLORED(msg, Color::None);
+
+ String subcaseStuff = "";
+ std::vector<Subcase>& subcasesStack = getContextState()->subcasesStack;
+ for(unsigned i = 0; i < subcasesStack.size(); ++i) {
+ char subcase[DOCTEST_SNPRINTF_BUFFER_LENGTH];
+ DOCTEST_SNPRINTF(subcase, DOCTEST_COUNTOF(loc), " %s\n",
+ subcasesStack[i].m_signature.m_name);
+ DOCTEST_PRINTF_COLORED(subcase, Color::None);
+ subcaseStuff += subcase;
+ }
+
+ DOCTEST_PRINTF_COLORED(newLine, Color::None);
+
+ printToDebugConsole(String(getSeparator()) + loc + msg + subcaseStuff.c_str() + newLine);
+ }
+
+ void logTestEnd() {}
+
+ void logTestCrashed() {
+ char msg[DOCTEST_SNPRINTF_BUFFER_LENGTH];
+
+ DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), "TEST CASE FAILED! (threw exception)\n\n");
+
+ DOCTEST_PRINTF_COLORED(msg, Color::Red);
+
+ printToDebugConsole(String(msg));
+ }
+
+ void logAssert(bool passed, const char* decomposition, bool threw, const char* expr,
+ assertType::Enum assert_type, const char* file, int line) {
+ char loc[DOCTEST_SNPRINTF_BUFFER_LENGTH];
+ DOCTEST_SNPRINTF(loc, DOCTEST_COUNTOF(loc), "%s(%d)", fileForOutput(file), line);
+
+ char msg[DOCTEST_SNPRINTF_BUFFER_LENGTH];
+ if(passed)
+ DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), " PASSED!\n");
+ else
+ DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), " FAILED! %s\n",
+ (threw ? "(threw exception)" : ""));
+
+ char info1[DOCTEST_SNPRINTF_BUFFER_LENGTH];
+ DOCTEST_SNPRINTF(info1, DOCTEST_COUNTOF(info1), " %s( %s )\n",
+ getAssertString(assert_type), expr);
+
+ char info2[DOCTEST_SNPRINTF_BUFFER_LENGTH];
+ char info3[DOCTEST_SNPRINTF_BUFFER_LENGTH];
+ info2[0] = 0;
+ info3[0] = 0;
+ if(!threw) {
+ DOCTEST_SNPRINTF(info2, DOCTEST_COUNTOF(info2), "with expansion:\n");
+ DOCTEST_SNPRINTF(info3, DOCTEST_COUNTOF(info3), " %s( %s )\n",
+ getAssertString(assert_type), decomposition);
+ }
+
+ DOCTEST_PRINTF_COLORED(loc, Color::LightGrey);
+ DOCTEST_PRINTF_COLORED(msg, passed ? Color::BrightGreen : Color::Red);
+ DOCTEST_PRINTF_COLORED(info1, Color::Cyan);
+ DOCTEST_PRINTF_COLORED(info2, Color::None);
+ DOCTEST_PRINTF_COLORED(info3, Color::Cyan);
+ DOCTEST_PRINTF_COLORED("\n", Color::None);
+
+ printToDebugConsole(String(loc) + msg + info1 + info2 + info3 + "\n");
+ }
+
+ void logAssertThrows(bool threw, const char* expr, assertType::Enum assert_type,
+ const char* file, int line) {
+ char loc[DOCTEST_SNPRINTF_BUFFER_LENGTH];
+ DOCTEST_SNPRINTF(loc, DOCTEST_COUNTOF(loc), "%s(%d)", fileForOutput(file), line);
+
+ char msg[DOCTEST_SNPRINTF_BUFFER_LENGTH];
+ if(threw)
+ DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), " PASSED!\n");
+ else
+ DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), " FAILED!\n");
+
+ char info1[DOCTEST_SNPRINTF_BUFFER_LENGTH];
+ DOCTEST_SNPRINTF(info1, DOCTEST_COUNTOF(info1), " %s( %s )\n\n",
+ getAssertString(assert_type), expr);
+
+ DOCTEST_PRINTF_COLORED(loc, Color::LightGrey);
+ DOCTEST_PRINTF_COLORED(msg, threw ? Color::BrightGreen : Color::Red);
+ DOCTEST_PRINTF_COLORED(info1, Color::Cyan);
+
+ printToDebugConsole(String(loc) + msg + info1);
+ }
+
+ void logAssertThrowsAs(bool threw, bool threw_as, const char* as, const char* expr,
+ assertType::Enum assert_type, const char* file, int line) {
+ char loc[DOCTEST_SNPRINTF_BUFFER_LENGTH];
+ DOCTEST_SNPRINTF(loc, DOCTEST_COUNTOF(loc), "%s(%d)", fileForOutput(file), line);
+
+ char msg[DOCTEST_SNPRINTF_BUFFER_LENGTH];
+ if(threw_as)
+ DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), " PASSED!\n");
+ else
+ DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), " FAILED! %s\n",
+ (threw ? "(threw something else)" : "(didn't throw at all)"));
+
+ char info1[DOCTEST_SNPRINTF_BUFFER_LENGTH];
+ DOCTEST_SNPRINTF(info1, DOCTEST_COUNTOF(info1), " %s( %s, %s )\n\n",
+ getAssertString(assert_type), expr, as);
+
+ DOCTEST_PRINTF_COLORED(loc, Color::LightGrey);
+ DOCTEST_PRINTF_COLORED(msg, threw_as ? Color::BrightGreen : Color::Red);
+ DOCTEST_PRINTF_COLORED(info1, Color::Cyan);
+
+ printToDebugConsole(String(loc) + msg + info1);
+ }
+
+ void logAssertNothrow(bool threw, const char* expr, assertType::Enum assert_type,
+ const char* file, int line) {
+ char loc[DOCTEST_SNPRINTF_BUFFER_LENGTH];
+ DOCTEST_SNPRINTF(loc, DOCTEST_COUNTOF(loc), "%s(%d)", fileForOutput(file), line);
+
+ char msg[DOCTEST_SNPRINTF_BUFFER_LENGTH];
+ if(!threw)
+ DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), " PASSED!\n");
+ else
+ DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), " FAILED!\n");
+
+ char info1[DOCTEST_SNPRINTF_BUFFER_LENGTH];
+ DOCTEST_SNPRINTF(info1, DOCTEST_COUNTOF(info1), " %s( %s )\n\n",
+ getAssertString(assert_type), expr);
+
+ DOCTEST_PRINTF_COLORED(loc, Color::LightGrey);
+ DOCTEST_PRINTF_COLORED(msg, !threw ? Color::BrightGreen : Color::Red);
+ DOCTEST_PRINTF_COLORED(info1, Color::Cyan);
+
+ printToDebugConsole(String(loc) + msg + info1);
+ }
+
+ ResultBuilder::ResultBuilder(assertType::Enum assert_type, const char* file, int line,
+ const char* expr, const char* exception_type)
+ : m_assert_type(assert_type)
+ , m_file(file)
+ , m_line(line)
+ , m_expr(expr)
+ , m_exception_type(exception_type)
+ , m_threw(false)
+ , m_threw_as(false)
+ , m_failed(false) {}
+
+ bool ResultBuilder::log() {
+ if((m_assert_type & assertType::is_warn) == 0)
+ DOCTEST_GCS().numAssertionsForCurrentTestcase++;
+
+ if(m_assert_type & assertType::is_false) {
+ m_result.invert();
+ m_failed = m_result;
+ } else if(m_assert_type & assertType::is_throws) {
+ m_failed = !m_threw;
+ } else if(m_assert_type & assertType::is_throws_as) {
+ m_failed = !m_threw_as;
+ } else if(m_assert_type & assertType::is_nothrow) {
+ m_failed = m_threw;
+ } else {
+ m_failed = m_result;
+ }
+
+ if(m_failed || DOCTEST_GCS().success) {
+ DOCTEST_LOG_START();
+
+ if(m_assert_type & assertType::is_throws) {
+ logAssertThrows(m_threw, m_expr, m_assert_type, m_file, m_line);
+ } else if(m_assert_type & assertType::is_throws_as) {
+ logAssertThrowsAs(m_threw, m_threw_as, m_exception_type, m_expr, m_assert_type,
+ m_file, m_line);
+ } else if(m_assert_type & assertType::is_nothrow) {
+ logAssertNothrow(m_threw, m_expr, m_assert_type, m_file, m_line);
+ } else {
+ logAssert(m_result.m_passed, m_result.m_decomposition.c_str(), m_threw, m_expr,
+ m_assert_type, m_file, m_line);
+ }
+ }
+
+ if(m_failed) {
+ addFailedAssert(m_assert_type);
+ if(isDebuggerActive() && !DOCTEST_GCS().no_breaks)
+ return true; // should break into the debugger
+ }
+ return false;
+ }
+
+ void ResultBuilder::react() const {
+ if(m_failed && checkIfShouldThrow(m_assert_type))
+ throwException();
+ }
+
+ // the implementation of parseFlag()
+ bool parseFlagImpl(int argc, const char* const* argv, const char* pattern) {
+ for(int i = argc - 1; i >= 0; --i) {
+ const char* temp = strstr(argv[i], pattern);
+ if(temp && my_strlen(temp) == my_strlen(pattern)) {
+ // eliminate strings in which the chars before the option are not '-'
+ bool noBadCharsFound = true;
+ while(temp != argv[i]) {
+ if(*--temp != '-') {
+ noBadCharsFound = false;
+ break;
+ }
+ }
+ if(noBadCharsFound && argv[i][0] == '-')
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // locates a flag on the command line
+ bool parseFlag(int argc, const char* const* argv, const char* pattern) {
+#ifndef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
+ if(!parseFlagImpl(argc, argv, pattern))
+ return parseFlagImpl(argc, argv, pattern + 3); // 3 for "dt-"
+ return true;
+#else // DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
+ return parseFlagImpl(argc, argv, pattern);
+#endif // DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
+ }
+
+ // the implementation of parseOption()
+ bool parseOptionImpl(int argc, const char* const* argv, const char* pattern, String& res) {
+ for(int i = argc - 1; i >= 0; --i) {
+ const char* temp = strstr(argv[i], pattern);
+ if(temp) {
+ // eliminate matches in which the chars before the option are not '-'
+ bool noBadCharsFound = true;
+ const char* curr = argv[i];
+ while(curr != temp) {
+ if(*curr++ != '-') {
+ noBadCharsFound = false;
+ break;
+ }
+ }
+ if(noBadCharsFound && argv[i][0] == '-') {
+ temp += my_strlen(pattern);
+ unsigned len = my_strlen(temp);
+ if(len) {
+ res = temp;
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ // parses an option and returns the string after the '=' character
+ bool parseOption(int argc, const char* const* argv, const char* pattern, String& res,
+ const String& defaultVal = String()) {
+ res = defaultVal;
+#ifndef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
+ if(!parseOptionImpl(argc, argv, pattern, res))
+ return parseOptionImpl(argc, argv, pattern + 3, res); // 3 for "dt-"
+ return true;
+#else // DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
+ return parseOptionImpl(argc, argv, pattern, res);
+#endif // DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
+ }
+
+ // parses a comma separated list of words after a pattern in one of the arguments in argv
+ bool parseCommaSepArgs(int argc, const char* const* argv, const char* pattern,
+ std::vector<String>& res) {
+ String filtersString;
+ if(parseOption(argc, argv, pattern, filtersString)) {
+ // tokenize with "," as a separator
+ char* pch = strtok(filtersString.c_str(), ","); // modifies the string
+ while(pch != 0) {
+ if(my_strlen(pch))
+ res.push_back(pch);
+ pch = strtok(0, ","); // uses the strtok() internal state to go to the next token
+ }
+ return true;
+ }
+ return false;
+ }
+
+ enum optionType
+ {
+ option_bool,
+ option_int
+ };
+
+ // parses an int/bool option from the command line
+ bool parseIntOption(int argc, const char* const* argv, const char* pattern, optionType type,
+ int& res) {
+ String parsedValue;
+ if(parseOption(argc, argv, pattern, parsedValue)) {
+ if(type == 0) {
+ // boolean
+ const char positive[][5] = {"1", "true", "on", "yes"}; // 5 - strlen("true") + 1
+ const char negative[][6] = {"0", "false", "off", "no"}; // 6 - strlen("false") + 1
+
+ // if the value matches any of the positive/negative possibilities
+ for(unsigned i = 0; i < 4; i++) {
+ if(parsedValue.compare(positive[i], true) == 0) {
+ res = 1;
+ return true;
+ }
+ if(parsedValue.compare(negative[i], true) == 0) {
+ res = 0;
+ return true;
+ }
+ }
+ } else {
+ // integer
+ int theInt = atoi(parsedValue.c_str());
+ if(theInt != 0) {
+ res = theInt;
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ void printVersion() {
+ if(getContextState()->no_version == false) {
+ DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
+ printf("doctest version is \"%s\"\n", DOCTEST_VERSION_STR);
+ }
+ }
+
+ void printHelp() {
+ printVersion();
+ DOCTEST_PRINTF_COLORED("[doctest]\n", Color::Cyan);
+ DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
+ printf("boolean values: \"1/on/yes/true\" or \"0/off/no/false\"\n");
+ DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
+ printf("filter values: \"str1,str2,str3\" (comma separated strings)\n");
+ DOCTEST_PRINTF_COLORED("[doctest]\n", Color::Cyan);
+ DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
+ printf("filters use wildcards for matching strings\n");
+ DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
+ printf("something passes a filter if any of the strings in a filter matches\n");
+ DOCTEST_PRINTF_COLORED("[doctest]\n", Color::Cyan);
+ DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
+ printf("ALL FLAGS, OPTIONS AND FILTERS ALSO AVAILABLE WITH A \"dt-\" PREFIX!!!\n");
+ DOCTEST_PRINTF_COLORED("[doctest]\n", Color::Cyan);
+ DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
+ printf("Query flags - the program quits after them. Available:\n\n");
+ printf(" -?, --help, -h prints this message\n");
+ printf(" -v, --version prints the version\n");
+ printf(" -c, --count prints the number of matching tests\n");
+ printf(" -ltc, --list-test-cases lists all matching tests by name\n");
+ printf(" -lts, --list-test-suites lists all matching test suites\n\n");
+ // ==================================================================================== << 79
+ DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
+ printf("The available <int>/<string> options/filters are:\n\n");
+ printf(" -tc, --test-case=<filters> filters tests by their name\n");
+ printf(" -tce, --test-case-exclude=<filters> filters OUT tests by their name\n");
+ printf(" -sf, --source-file=<filters> filters tests by their file\n");
+ printf(" -sfe, --source-file-exclude=<filters> filters OUT tests by their file\n");
+ printf(" -ts, --test-suite=<filters> filters tests by their test suite\n");
+ printf(" -tse, --test-suite-exclude=<filters> filters OUT tests by their test suite\n");
+ printf(" -ob, --order-by=<string> how the tests should be ordered\n");
+ printf(" <string> - by [file/suite/name/rand]\n");
+ printf(" -rs, --rand-seed=<int> seed for random ordering\n");
+ printf(" -f, --first=<int> the first test passing the filters to\n");
+ printf(" execute - for range-based execution\n");
+ printf(" -l, --last=<int> the last test passing the filters to\n");
+ printf(" execute - for range-based execution\n");
+ printf(" -aa, --abort-after=<int> stop after <int> failed assertions\n\n");
+ DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
+ printf("Bool options - can be used like flags and true is assumed. Available:\n\n");
+ printf(" -s, --success=<bool> include successful assertions in output\n");
+ printf(" -cs, --case-sensitive=<bool> filters being treated as case sensitive\n");
+ printf(" -e, --exit=<bool> exits after the tests finish\n");
+ printf(" -nt, --no-throw=<bool> skips exceptions-related assert checks\n");
+ printf(" -ne, --no-exitcode=<bool> returns (or exits) always with success\n");
+ printf(" -nr, --no-run=<bool> skips all runtime doctest operations\n");
+ printf(" -nv, --no-version=<bool> omit the framework version in the output\n");
+ printf(" -nc, --no-colors=<bool> disables colors in output\n");
+ printf(" -nb, --no-breaks=<bool> disables breakpoints in debuggers\n");
+ printf(" -npf, --no-path-filenames=<bool> only filenames and no paths in output\n\n");
+ // ==================================================================================== << 79
+
+ DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
+ printf("for more information visit the project documentation\n\n");
+ }
+} // namespace detail
+
+Context::Context(int argc, const char* const* argv)
+ : p(new detail::ContextState) {
+ parseArgs(argc, argv, true);
+}
+
+Context::~Context() { delete p; }
+
+void Context::applyCommandLine(int argc, const char* const* argv) { parseArgs(argc, argv); }
+
+// parses args
+void Context::parseArgs(int argc, const char* const* argv, bool withDefaults) {
+ using namespace detail;
+
+ // clang-format off
+ parseCommaSepArgs(argc, argv, "dt-source-file=", p->filters[0]);
+ parseCommaSepArgs(argc, argv, "dt-sf=", p->filters[0]);
+ parseCommaSepArgs(argc, argv, "dt-source-file-exclude=",p->filters[1]);
+ parseCommaSepArgs(argc, argv, "dt-sfe=", p->filters[1]);
+ parseCommaSepArgs(argc, argv, "dt-test-suite=", p->filters[2]);
+ parseCommaSepArgs(argc, argv, "dt-ts=", p->filters[2]);
+ parseCommaSepArgs(argc, argv, "dt-test-suite-exclude=", p->filters[3]);
+ parseCommaSepArgs(argc, argv, "dt-tse=", p->filters[3]);
+ parseCommaSepArgs(argc, argv, "dt-test-case=", p->filters[4]);
+ parseCommaSepArgs(argc, argv, "dt-tc=", p->filters[4]);
+ parseCommaSepArgs(argc, argv, "dt-test-case-exclude=", p->filters[5]);
+ parseCommaSepArgs(argc, argv, "dt-tce=", p->filters[5]);
+ // clang-format on
+
+ int intRes = 0;
+ String strRes;
+
+#define DOCTEST_PARSE_AS_BOOL_OR_FLAG(name, sname, var, default) \
+ if(parseIntOption(argc, argv, DOCTEST_STR_CONCAT_TOSTR(name, =), option_bool, intRes) || \
+ parseIntOption(argc, argv, DOCTEST_STR_CONCAT_TOSTR(sname, =), option_bool, intRes)) \
+ p->var = !!intRes; \
+ else if(parseFlag(argc, argv, #name) || parseFlag(argc, argv, #sname)) \
+ p->var = 1; \
+ else if(withDefaults) \
+ p->var = default
+
+#define DOCTEST_PARSE_INT_OPTION(name, sname, var, default) \
+ if(parseIntOption(argc, argv, DOCTEST_STR_CONCAT_TOSTR(name, =), option_int, intRes) || \
+ parseIntOption(argc, argv, DOCTEST_STR_CONCAT_TOSTR(sname, =), option_int, intRes)) \
+ p->var = intRes; \
+ else if(withDefaults) \
+ p->var = default
+
+#define DOCTEST_PARSE_STR_OPTION(name, sname, var, default) \
+ if(parseOption(argc, argv, DOCTEST_STR_CONCAT_TOSTR(name, =), strRes, default) || \
+ parseOption(argc, argv, DOCTEST_STR_CONCAT_TOSTR(sname, =), strRes, default) || \
+ withDefaults) \
+ p->var = strRes
+
+ // clang-format off
+ DOCTEST_PARSE_STR_OPTION(dt-order-by, dt-ob, order_by, "file");
+ DOCTEST_PARSE_INT_OPTION(dt-rand-seed, dt-rs, rand_seed, 0);
+
+ DOCTEST_PARSE_INT_OPTION(dt-first, dt-f, first, 1);
+ DOCTEST_PARSE_INT_OPTION(dt-last, dt-l, last, 0);
+
+ DOCTEST_PARSE_INT_OPTION(dt-abort-after, dt-aa, abort_after, 0);
+
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG(dt-success, dt-s, success, 0);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG(dt-case-sensitive, dt-cs, case_sensitive, 0);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG(dt-exit, dt-e, exit, 0);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG(dt-no-throw, dt-nt, no_throw, 0);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG(dt-no-exitcode, dt-ne, no_exitcode, 0);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG(dt-no-run, dt-nr, no_run, 0);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG(dt-no-version, dt-nv, no_version, 0);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG(dt-no-colors, dt-nc, no_colors, 0);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG(dt-no-breaks, dt-nb, no_breaks, 0);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG(dt-no-path-filenames, dt-npf, no_path_in_filenames, 0);
+// clang-format on
+
+#undef DOCTEST_PARSE_STR_OPTION
+#undef DOCTEST_PARSE_INT_OPTION
+#undef DOCTEST_PARSE_AS_BOOL_OR_FLAG
+
+ if(withDefaults) {
+ p->help = false;
+ p->version = false;
+ p->count = false;
+ p->list_test_cases = false;
+ p->list_test_suites = false;
+ }
+ if(parseFlag(argc, argv, "dt-help") || parseFlag(argc, argv, "dt-h") ||
+ parseFlag(argc, argv, "dt-?")) {
+ p->help = true;
+ p->exit = true;
+ }
+ if(parseFlag(argc, argv, "dt-version") || parseFlag(argc, argv, "dt-v")) {
+ p->version = true;
+ p->exit = true;
+ }
+ if(parseFlag(argc, argv, "dt-count") || parseFlag(argc, argv, "dt-c")) {
+ p->count = true;
+ p->exit = true;
+ }
+ if(parseFlag(argc, argv, "dt-list-test-cases") || parseFlag(argc, argv, "dt-ltc")) {
+ p->list_test_cases = true;
+ p->exit = true;
+ }
+ if(parseFlag(argc, argv, "dt-list-test-suites") || parseFlag(argc, argv, "dt-lts")) {
+ p->list_test_suites = true;
+ p->exit = true;
+ }
+}
+
+// allows the user to add procedurally to the filters from the command line
+void Context::addFilter(const char* filter, const char* value) { setOption(filter, value); }
+
+// allows the user to clear all filters from the command line
+void Context::clearFilters() {
+ for(unsigned i = 0; i < p->filters.size(); ++i)
+ p->filters[i].clear();
+}
+
+// allows the user to override procedurally the int/bool options from the command line
+void Context::setOption(const char* option, int value) {
+ setOption(option, toString(value).c_str());
+}
+
+// allows the user to override procedurally the string options from the command line
+void Context::setOption(const char* option, const char* value) {
+ String argv = String("-") + option + "=" + value;
+ const char* lvalue = argv.c_str();
+ parseArgs(1, &lvalue);
+}
+
+// users should query this in their main() and exit the program if true
+bool Context::shouldExit() { return p->exit; }
+
+// the main function that does all the filtering and test running
+int Context::run() {
+ using namespace detail;
+
+ getContextState() = p;
+ p->resetRunData();
+
+ // handle version, help and no_run
+ if(p->no_run || p->version || p->help) {
+ if(p->version)
+ printVersion();
+ if(p->help)
+ printHelp();
+
+ getContextState() = 0;
+
+ return EXIT_SUCCESS;
+ }
+
+ printVersion();
+ DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
+ printf("run with \"--help\" for options\n");
+
+ unsigned i = 0; // counter used for loops - here for VC6
+
+ std::set<TestData>& registeredTests = getRegisteredTests();
+
+ std::vector<const TestData*> testArray;
+ for(std::set<TestData>::iterator it = registeredTests.begin(); it != registeredTests.end();
+ ++it)
+ testArray.push_back(&(*it));
+
+ // sort the collected records
+ if(testArray.size() > 0) {
+ if(p->order_by.compare("file", true) == 0) {
+ qsort(&testArray[0], testArray.size(), sizeof(TestData*), fileOrderComparator);
+ } else if(p->order_by.compare("suite", true) == 0) {
+ qsort(&testArray[0], testArray.size(), sizeof(TestData*), suiteOrderComparator);
+ } else if(p->order_by.compare("name", true) == 0) {
+ qsort(&testArray[0], testArray.size(), sizeof(TestData*), nameOrderComparator);
+ } else if(p->order_by.compare("rand", true) == 0) {
+ srand(p->rand_seed);
+
+ // random_shuffle implementation
+ const TestData** first = &testArray[0];
+ for(i = testArray.size() - 1; i > 0; --i) {
+ int idxToSwap = rand() % (i + 1);
+
+ const TestData* temp = first[i];
+
+ first[i] = first[idxToSwap];
+ first[idxToSwap] = temp;
+ }
+ }
+ }
+
+ if(p->list_test_cases) {
+ DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
+ printf("listing all test case names\n");
+ }
+
+ std::set<String> testSuitesPassingFilters;
+ if(p->list_test_suites) {
+ DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
+ printf("listing all test suites\n");
+ }
+
+ unsigned numTestsPassingFilters = 0;
+ unsigned numFailed = 0;
+ // invoke the registered functions if they match the filter criteria (or just count them)
+ for(i = 0; i < testArray.size(); i++) {
+ const TestData& data = *testArray[i];
+ if(!matchesAny(data.m_file, p->filters[0], 1, p->case_sensitive))
+ continue;
+ if(matchesAny(data.m_file, p->filters[1], 0, p->case_sensitive))
+ continue;
+ if(!matchesAny(data.m_suite, p->filters[2], 1, p->case_sensitive))
+ continue;
+ if(matchesAny(data.m_suite, p->filters[3], 0, p->case_sensitive))
+ continue;
+ if(!matchesAny(data.m_name, p->filters[4], 1, p->case_sensitive))
+ continue;
+ if(matchesAny(data.m_name, p->filters[5], 0, p->case_sensitive))
+ continue;
+
+ numTestsPassingFilters++;
+
+ // do not execute the test if we are to only count the number of filter passing tests
+ if(p->count)
+ continue;
+
+ // print the name of the test and don't execute it
+ if(p->list_test_cases) {
+ printf("%s\n", data.m_name);
+ continue;
+ }
+
+ // print the name of the test suite if not done already and don't execute it
+ if(p->list_test_suites) {
+ if(testSuitesPassingFilters.count(data.m_suite) == 0) {
+ printf("%s\n", data.m_suite);
+ testSuitesPassingFilters.insert(data.m_suite);
+ }
+ continue;
+ }
+
+ // skip the test if it is not in the execution range
+ if((p->last < numTestsPassingFilters && p->first <= p->last) ||
+ (p->first > numTestsPassingFilters))
+ continue;
+
+ // execute the test if it passes all the filtering
+ {
+#ifdef _MSC_VER
+//__try {
+#endif // _MSC_VER
+
+ p->currentTest = &data;
+
+ // if logging successful tests - force the start log
+ p->hasLoggedCurrentTestStart = false;
+ if(p->success)
+ DOCTEST_LOG_START();
+
+ unsigned didFail = 0;
+ p->subcasesPassed.clear();
+ do {
+ // reset the assertion state
+ p->numAssertionsForCurrentTestcase = 0;
+ p->numFailedAssertionsForCurrentTestcase = 0;
+
+ // reset some of the fields for subcases (except for the set of fully passed ones)
+ p->subcasesHasSkipped = false;
+ p->subcasesCurrentLevel = 0;
+ p->subcasesEnteredLevels.clear();
+
+ // execute the test
+ didFail += callTestFunc(data.m_f);
+ p->numAssertions += p->numAssertionsForCurrentTestcase;
+
+ // exit this loop if enough assertions have failed
+ if(p->abort_after > 0 && p->numFailedAssertions >= p->abort_after)
+ p->subcasesHasSkipped = false;
+
+ // if the start has been logged
+ if(p->hasLoggedCurrentTestStart)
+ logTestEnd();
+ p->hasLoggedCurrentTestStart = false;
+
+ } while(p->subcasesHasSkipped == true);
+
+ if(didFail > 0)
+ numFailed++;
+
+ // stop executing tests if enough assertions have failed
+ if(p->abort_after > 0 && p->numFailedAssertions >= p->abort_after)
+ break;
+
+#ifdef _MSC_VER
+//} __except(1) {
+// printf("Unknown SEH exception caught!\n");
+// numFailed++;
+//}
+#endif // _MSC_VER
+ }
+ }
+
+ DOCTEST_PRINTF_COLORED(getSeparator(), numFailed > 0 ? Color::Red : Color::Green);
+ if(p->count || p->list_test_cases || p->list_test_suites) {
+ DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
+ printf("number of tests passing the current filters: %d\n", numTestsPassingFilters);
+ } else {
+ char buff[DOCTEST_SNPRINTF_BUFFER_LENGTH];
+
+ DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
+
+ DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), "test cases: %4d", numTestsPassingFilters);
+ DOCTEST_PRINTF_COLORED(buff, Color::None);
+ DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), " | ");
+ DOCTEST_PRINTF_COLORED(buff, Color::None);
+ DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), "%4d passed",
+ numTestsPassingFilters - numFailed);
+ DOCTEST_PRINTF_COLORED(buff, numFailed > 0 ? Color::None : Color::Green);
+ DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), " | ");
+ DOCTEST_PRINTF_COLORED(buff, Color::None);
+ DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), "%4d failed", numFailed);
+ DOCTEST_PRINTF_COLORED(buff, numFailed > 0 ? Color::Red : Color::None);
+
+ DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), " | ");
+ DOCTEST_PRINTF_COLORED(buff, Color::None);
+ DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), "%4d skipped\n",
+ static_cast<unsigned>(testArray.size()) - numTestsPassingFilters);
+ DOCTEST_PRINTF_COLORED(buff, Color::None);
+
+ DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan);
+
+ DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), "assertions: %4d", p->numAssertions);
+ DOCTEST_PRINTF_COLORED(buff, Color::None);
+ DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), " | ");
+ DOCTEST_PRINTF_COLORED(buff, Color::None);
+ DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), "%4d passed",
+ p->numAssertions - p->numFailedAssertions);
+ DOCTEST_PRINTF_COLORED(buff, numFailed > 0 ? Color::None : Color::Green);
+ DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), " | ");
+ DOCTEST_PRINTF_COLORED(buff, Color::None);
+ DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), "%4d failed", p->numFailedAssertions);
+ DOCTEST_PRINTF_COLORED(buff, p->numFailedAssertions > 0 ? Color::Red : Color::None);
+
+ DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), " |\n");
+ DOCTEST_PRINTF_COLORED(buff, Color::None);
+ }
+
+ // remove any coloring
+ DOCTEST_PRINTF_COLORED("", Color::None);
+
+ getContextState() = 0;
+
+ if(numFailed && !p->no_exitcode)
+ return EXIT_FAILURE;
+ return EXIT_SUCCESS;
+}
+} // namespace doctest
+
+#endif // DOCTEST_CONFIG_DISABLE
+#endif // DOCTEST_LIBRARY_IMPLEMENTATION
+#endif // DOCTEST_CONFIG_IMPLEMENT
+
+// == THIS SUPPLIES A MAIN FUNCTION AND SHOULD BE DONE ONLY IN ONE TRANSLATION UNIT
+#if defined(DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN) && !defined(DOCTEST_MAIN_CONFIGURED)
+#define DOCTEST_MAIN_CONFIGURED
+int main(int argc, char** argv) { return doctest::Context(argc, argv).run(); }
+#endif // DOCTEST_MAIN_CONFIGURED
+
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif // __clang__
+
+#if defined(__GNUC__) && !defined(__clang__)
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6)
+#pragma GCC diagnostic pop
+#endif // > gcc 4.6
+#endif // __GNUC__
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif // _MSC_VER
diff --git a/test/test.cpp b/test/test.cpp
index 354f209..d68b8af 100644
--- a/test/test.cpp
+++ b/test/test.cpp
@@ -1,7 +1,7 @@
#include "../include/argagg/argagg.hpp"
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
-#include "doctest/doctest.h"
+#include "doctest.h"
#include <cstring>
#include <iostream>