upgrade Doctest to 2.3.5

parent 3790bd9a
...@@ -48,8 +48,8 @@ ...@@ -48,8 +48,8 @@
#define DOCTEST_VERSION_MAJOR 2 #define DOCTEST_VERSION_MAJOR 2
#define DOCTEST_VERSION_MINOR 3 #define DOCTEST_VERSION_MINOR 3
#define DOCTEST_VERSION_PATCH 1 #define DOCTEST_VERSION_PATCH 5
#define DOCTEST_VERSION_STR "2.3.1" #define DOCTEST_VERSION_STR "2.3.5"
#define DOCTEST_VERSION \ #define DOCTEST_VERSION \
(DOCTEST_VERSION_MAJOR * 10000 + DOCTEST_VERSION_MINOR * 100 + DOCTEST_VERSION_PATCH) (DOCTEST_VERSION_MAJOR * 10000 + DOCTEST_VERSION_MINOR * 100 + DOCTEST_VERSION_PATCH)
...@@ -214,7 +214,8 @@ DOCTEST_MSVC_SUPPRESS_WARNING(26444) // Avoid unnamed objects with custom constr ...@@ -214,7 +214,8 @@ DOCTEST_MSVC_SUPPRESS_WARNING(26444) // Avoid unnamed objects with custom constr
DOCTEST_MSVC_SUPPRESS_WARNING(5026) \ DOCTEST_MSVC_SUPPRESS_WARNING(5026) \
DOCTEST_MSVC_SUPPRESS_WARNING(4623) \ DOCTEST_MSVC_SUPPRESS_WARNING(4623) \
DOCTEST_MSVC_SUPPRESS_WARNING(5039) \ DOCTEST_MSVC_SUPPRESS_WARNING(5039) \
DOCTEST_MSVC_SUPPRESS_WARNING(5045) DOCTEST_MSVC_SUPPRESS_WARNING(5045) \
DOCTEST_MSVC_SUPPRESS_WARNING(5105)
#define DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END DOCTEST_MSVC_SUPPRESS_WARNING_POP #define DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END DOCTEST_MSVC_SUPPRESS_WARNING_POP
...@@ -227,7 +228,7 @@ DOCTEST_MSVC_SUPPRESS_WARNING(26444) // Avoid unnamed objects with custom constr ...@@ -227,7 +228,7 @@ DOCTEST_MSVC_SUPPRESS_WARNING(26444) // Avoid unnamed objects with custom constr
// GCC C++11 feature support table: https://gcc.gnu.org/projects/cxx-status.html // GCC C++11 feature support table: https://gcc.gnu.org/projects/cxx-status.html
// MSVC version table: // MSVC version table:
// https://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B#Internal_version_numbering // https://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B#Internal_version_numbering
// MSVC++ 14.2 (16) _MSC_VER == 1920 (Visual Studio 2019) << NOT YET RELEASED - April 2 2019 // MSVC++ 14.2 (16) _MSC_VER == 1920 (Visual Studio 2019)
// MSVC++ 14.1 (15) _MSC_VER == 1910 (Visual Studio 2017) // MSVC++ 14.1 (15) _MSC_VER == 1910 (Visual Studio 2017)
// MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015) // MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015)
// MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013) // MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013)
...@@ -306,10 +307,6 @@ DOCTEST_MSVC_SUPPRESS_WARNING(26444) // Avoid unnamed objects with custom constr ...@@ -306,10 +307,6 @@ DOCTEST_MSVC_SUPPRESS_WARNING(26444) // Avoid unnamed objects with custom constr
#define DOCTEST_ALIGNMENT(x) __attribute__((aligned(x))) #define DOCTEST_ALIGNMENT(x) __attribute__((aligned(x)))
#endif // MSVC #endif // MSVC
#ifndef DOCTEST_CONFIG_NUM_CAPTURES_ON_STACK
#define DOCTEST_CONFIG_NUM_CAPTURES_ON_STACK 5
#endif // DOCTEST_CONFIG_NUM_CAPTURES_ON_STACK
// ================================================================================================= // =================================================================================================
// == FEATURE DETECTION END ======================================================================== // == FEATURE DETECTION END ========================================================================
// ================================================================================================= // =================================================================================================
...@@ -342,30 +339,27 @@ DOCTEST_MSVC_SUPPRESS_WARNING(26444) // Avoid unnamed objects with custom constr ...@@ -342,30 +339,27 @@ DOCTEST_MSVC_SUPPRESS_WARNING(26444) // Avoid unnamed objects with custom constr
#define DOCTEST_PLATFORM_LINUX #define DOCTEST_PLATFORM_LINUX
#endif // DOCTEST_PLATFORM #endif // DOCTEST_PLATFORM
// clang-format off
#define DOCTEST_DELETE_COPIES(type) type(const type&) = delete; type& operator=(const type&) = delete
#define DOCTEST_DECLARE_COPIES(type) type(const type&); type& operator=(const type&)
#define DOCTEST_DEFINE_COPIES(type) type::type(const type&) = default; type& type::operator=(const type&) = default
#define DOCTEST_DECLARE_DEFAULTS(type) type(); ~type()
#define DOCTEST_DEFINE_DEFAULTS(type) type::type() = default; type::~type() = default
// clang-format on
#define DOCTEST_GLOBAL_NO_WARNINGS(var) \ #define DOCTEST_GLOBAL_NO_WARNINGS(var) \
DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wglobal-constructors") \ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wglobal-constructors") \
DOCTEST_CLANG_SUPPRESS_WARNING("-Wunused-variable") \
static int var DOCTEST_UNUSED // NOLINT(fuchsia-statically-constructed-objects,cert-err58-cpp) static int var DOCTEST_UNUSED // NOLINT(fuchsia-statically-constructed-objects,cert-err58-cpp)
#define DOCTEST_GLOBAL_NO_WARNINGS_END() DOCTEST_CLANG_SUPPRESS_WARNING_POP #define DOCTEST_GLOBAL_NO_WARNINGS_END() DOCTEST_CLANG_SUPPRESS_WARNING_POP
#ifndef DOCTEST_BREAK_INTO_DEBUGGER
// should probably take a look at https://github.com/scottt/debugbreak // should probably take a look at https://github.com/scottt/debugbreak
#ifdef DOCTEST_PLATFORM_MAC #ifdef DOCTEST_PLATFORM_MAC
#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) #define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :)
#elif DOCTEST_MSVC #elif DOCTEST_MSVC
#define DOCTEST_BREAK_INTO_DEBUGGER() __debugbreak() #define DOCTEST_BREAK_INTO_DEBUGGER() __debugbreak()
#elif defined(__MINGW32__) #elif defined(__MINGW32__)
DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wredundant-decls")
extern "C" __declspec(dllimport) void __stdcall DebugBreak(); extern "C" __declspec(dllimport) void __stdcall DebugBreak();
DOCTEST_GCC_SUPPRESS_WARNING_POP
#define DOCTEST_BREAK_INTO_DEBUGGER() ::DebugBreak() #define DOCTEST_BREAK_INTO_DEBUGGER() ::DebugBreak()
#else // linux #else // linux
#define DOCTEST_BREAK_INTO_DEBUGGER() ((void)0) #define DOCTEST_BREAK_INTO_DEBUGGER() ((void)0)
#endif // linux #endif // linux
#endif // DOCTEST_BREAK_INTO_DEBUGGER
// this is kept here for backwards compatibility since the config option was changed // this is kept here for backwards compatibility since the config option was changed
#ifdef DOCTEST_CONFIG_USE_IOSFWD #ifdef DOCTEST_CONFIG_USE_IOSFWD
...@@ -375,6 +369,10 @@ extern "C" __declspec(dllimport) void __stdcall DebugBreak(); ...@@ -375,6 +369,10 @@ extern "C" __declspec(dllimport) void __stdcall DebugBreak();
#ifdef DOCTEST_CONFIG_USE_STD_HEADERS #ifdef DOCTEST_CONFIG_USE_STD_HEADERS
#include <iosfwd> #include <iosfwd>
#include <cstddef> #include <cstddef>
#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0)
// see this issue on why this is needed: https://github.com/onqtam/doctest/issues/183
#include <ostream>
#endif // VS 2019
#else // DOCTEST_CONFIG_USE_STD_HEADERS #else // DOCTEST_CONFIG_USE_STD_HEADERS
#if DOCTEST_CLANG #if DOCTEST_CLANG
...@@ -393,7 +391,7 @@ extern "C" __declspec(dllimport) void __stdcall DebugBreak(); ...@@ -393,7 +391,7 @@ extern "C" __declspec(dllimport) void __stdcall DebugBreak();
// Forward declaring 'X' in namespace std is not permitted by the C++ Standard. // Forward declaring 'X' in namespace std is not permitted by the C++ Standard.
DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4643) DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4643)
DOCTEST_STD_NAMESPACE_BEGIN DOCTEST_STD_NAMESPACE_BEGIN // NOLINT (cert-dcl58-cpp)
typedef decltype(nullptr) nullptr_t; typedef decltype(nullptr) nullptr_t;
template <class charT> template <class charT>
struct char_traits; struct char_traits;
...@@ -404,6 +402,14 @@ class basic_ostream; ...@@ -404,6 +402,14 @@ class basic_ostream;
typedef basic_ostream<char, char_traits<char>> ostream; typedef basic_ostream<char, char_traits<char>> ostream;
template <class... Types> template <class... Types>
class tuple; class tuple;
#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0)
// see this issue on why this is needed: https://github.com/onqtam/doctest/issues/183
template <class _Ty>
class allocator;
template <class _Elem, class _Traits, class _Alloc>
class basic_string;
using string = basic_string<char, char_traits<char>, allocator<char>>;
#endif // VS 2019
DOCTEST_STD_NAMESPACE_END DOCTEST_STD_NAMESPACE_END
DOCTEST_MSVC_SUPPRESS_WARNING_POP DOCTEST_MSVC_SUPPRESS_WARNING_POP
...@@ -578,6 +584,10 @@ namespace assertType { ...@@ -578,6 +584,10 @@ namespace assertType {
DT_CHECK_THROWS_WITH = is_throws_with | is_check, DT_CHECK_THROWS_WITH = is_throws_with | is_check,
DT_REQUIRE_THROWS_WITH = is_throws_with | is_require, DT_REQUIRE_THROWS_WITH = is_throws_with | is_require,
DT_WARN_THROWS_WITH_AS = is_throws_with | is_throws_as | is_warn,
DT_CHECK_THROWS_WITH_AS = is_throws_with | is_throws_as | is_check,
DT_REQUIRE_THROWS_WITH_AS = is_throws_with | is_throws_as | is_require,
DT_WARN_NOTHROW = is_nothrow | is_warn, DT_WARN_NOTHROW = is_nothrow | is_warn,
DT_CHECK_NOTHROW = is_nothrow | is_check, DT_CHECK_NOTHROW = is_nothrow | is_check,
DT_REQUIRE_NOTHROW = is_nothrow | is_require, DT_REQUIRE_NOTHROW = is_nothrow | is_require,
...@@ -632,9 +642,6 @@ struct DOCTEST_INTERFACE TestCaseData ...@@ -632,9 +642,6 @@ struct DOCTEST_INTERFACE TestCaseData
bool m_should_fail; bool m_should_fail;
int m_expected_failures; int m_expected_failures;
double m_timeout; double m_timeout;
DOCTEST_DECLARE_DEFAULTS(TestCaseData);
DOCTEST_DECLARE_COPIES(TestCaseData);
}; };
struct DOCTEST_INTERFACE AssertData struct DOCTEST_INTERFACE AssertData
...@@ -657,9 +664,7 @@ struct DOCTEST_INTERFACE AssertData ...@@ -657,9 +664,7 @@ struct DOCTEST_INTERFACE AssertData
// for specific exception-related asserts // for specific exception-related asserts
bool m_threw_as; bool m_threw_as;
const char* m_exception_type; const char* m_exception_type;
const char* m_exception_string;
DOCTEST_DECLARE_DEFAULTS(AssertData);
DOCTEST_DELETE_COPIES(AssertData);
}; };
struct DOCTEST_INTERFACE MessageData struct DOCTEST_INTERFACE MessageData
...@@ -668,9 +673,6 @@ struct DOCTEST_INTERFACE MessageData ...@@ -668,9 +673,6 @@ struct DOCTEST_INTERFACE MessageData
const char* m_file; const char* m_file;
int m_line; int m_line;
assertType::Enum m_severity; assertType::Enum m_severity;
DOCTEST_DECLARE_DEFAULTS(MessageData);
DOCTEST_DELETE_COPIES(MessageData);
}; };
struct DOCTEST_INTERFACE SubcaseSignature struct DOCTEST_INTERFACE SubcaseSignature
...@@ -679,18 +681,11 @@ struct DOCTEST_INTERFACE SubcaseSignature ...@@ -679,18 +681,11 @@ struct DOCTEST_INTERFACE SubcaseSignature
const char* m_file; const char* m_file;
int m_line; int m_line;
SubcaseSignature(const char* name, const char* file, int line);
bool operator<(const SubcaseSignature& other) const; bool operator<(const SubcaseSignature& other) const;
DOCTEST_DECLARE_DEFAULTS(SubcaseSignature);
DOCTEST_DECLARE_COPIES(SubcaseSignature);
}; };
struct DOCTEST_INTERFACE IContextScope struct DOCTEST_INTERFACE IContextScope
{ {
DOCTEST_DELETE_COPIES(IContextScope);
IContextScope(); IContextScope();
virtual ~IContextScope(); virtual ~IContextScope();
virtual void stringify(std::ostream*) const = 0; virtual void stringify(std::ostream*) const = 0;
...@@ -732,13 +727,10 @@ struct ContextOptions //!OCLINT too many fields ...@@ -732,13 +727,10 @@ struct ContextOptions //!OCLINT too many fields
bool help; // to print the help bool help; // to print the help
bool version; // to print the version bool version; // to print the version
bool count; // if only the count of matching tests is to be retreived bool count; // if only the count of matching tests is to be retrieved
bool list_test_cases; // to list all tests matching the filters bool list_test_cases; // to list all tests matching the filters
bool list_test_suites; // to list all suites matching the filters bool list_test_suites; // to list all suites matching the filters
bool list_reporters; // lists all registered reporters bool list_reporters; // lists all registered reporters
DOCTEST_DECLARE_DEFAULTS(ContextOptions);
DOCTEST_DELETE_COPIES(ContextOptions);
}; };
namespace detail { namespace detail {
...@@ -884,13 +876,16 @@ DOCTEST_INTERFACE String toString(int long long in); ...@@ -884,13 +876,16 @@ DOCTEST_INTERFACE String toString(int long long in);
DOCTEST_INTERFACE String toString(int long long unsigned in); DOCTEST_INTERFACE String toString(int long long unsigned in);
DOCTEST_INTERFACE String toString(std::nullptr_t in); DOCTEST_INTERFACE String toString(std::nullptr_t in);
#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0)
// see this issue on why this is needed: https://github.com/onqtam/doctest/issues/183
DOCTEST_INTERFACE String toString(const std::string& in);
#endif // VS 2019
class DOCTEST_INTERFACE Approx class DOCTEST_INTERFACE Approx
{ {
public: public:
explicit Approx(double value); explicit Approx(double value);
DOCTEST_DECLARE_COPIES(Approx);
Approx operator()(double value) const; Approx operator()(double value) const;
#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS #ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
...@@ -990,8 +985,6 @@ namespace detail { ...@@ -990,8 +985,6 @@ namespace detail {
struct DOCTEST_INTERFACE TestFailureException struct DOCTEST_INTERFACE TestFailureException
{ {
DOCTEST_DECLARE_DEFAULTS(TestFailureException);
DOCTEST_DECLARE_COPIES(TestFailureException);
}; };
DOCTEST_INTERFACE bool checkIfShouldThrow(assertType::Enum at); DOCTEST_INTERFACE bool checkIfShouldThrow(assertType::Enum at);
...@@ -1009,8 +1002,6 @@ namespace detail { ...@@ -1009,8 +1002,6 @@ namespace detail {
Subcase(const char* name, const char* file, int line); Subcase(const char* name, const char* file, int line);
~Subcase(); ~Subcase();
DOCTEST_DELETE_COPIES(Subcase);
operator bool() const; operator bool() const;
}; };
...@@ -1049,9 +1040,6 @@ namespace detail { ...@@ -1049,9 +1040,6 @@ namespace detail {
Result(bool passed, const String& decomposition = String()); Result(bool passed, const String& decomposition = String());
DOCTEST_DECLARE_DEFAULTS(Result);
DOCTEST_DECLARE_COPIES(Result);
// forbidding some expressions based on this table: http://en.cppreference.com/w/cpp/language/operator_precedence // forbidding some expressions based on this table: http://en.cppreference.com/w/cpp/language/operator_precedence
DOCTEST_FORBIT_EXPRESSION(Result, &) DOCTEST_FORBIT_EXPRESSION(Result, &)
DOCTEST_FORBIT_EXPRESSION(Result, ^) DOCTEST_FORBIT_EXPRESSION(Result, ^)
...@@ -1213,9 +1201,6 @@ namespace detail { ...@@ -1213,9 +1201,6 @@ namespace detail {
ExpressionDecomposer(assertType::Enum at); ExpressionDecomposer(assertType::Enum at);
DOCTEST_DECLARE_DEFAULTS(ExpressionDecomposer);
DOCTEST_DELETE_COPIES(ExpressionDecomposer);
// The right operator for capturing expressions is "<=" instead of "<<" (based on the operator precedence table) // The right operator for capturing expressions is "<=" instead of "<<" (based on the operator precedence table)
// but then there will be warnings from GCC about "-Wparentheses" and since "_Pragma()" is problematic this will stay for now... // but then there will be warnings from GCC about "-Wparentheses" and since "_Pragma()" is problematic this will stay for now...
// https://github.com/catchorg/Catch2/issues/870 // https://github.com/catchorg/Catch2/issues/870
...@@ -1236,9 +1221,6 @@ namespace detail { ...@@ -1236,9 +1221,6 @@ namespace detail {
int m_expected_failures; int m_expected_failures;
double m_timeout; double m_timeout;
DOCTEST_DECLARE_DEFAULTS(TestSuite);
DOCTEST_DECLARE_COPIES(TestSuite);
TestSuite& operator*(const char* in); TestSuite& operator*(const char* in);
template <typename T> template <typename T>
...@@ -1261,8 +1243,6 @@ namespace detail { ...@@ -1261,8 +1243,6 @@ namespace detail {
TestCase(funcType test, const char* file, unsigned line, const TestSuite& test_suite, TestCase(funcType test, const char* file, unsigned line, const TestSuite& test_suite,
const char* type = "", int template_id = -1); const char* type = "", int template_id = -1);
DOCTEST_DECLARE_DEFAULTS(TestCase);
TestCase(const TestCase& other); TestCase(const TestCase& other);
DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(26434) // hides a non-virtual function DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(26434) // hides a non-virtual function
...@@ -1285,6 +1265,9 @@ namespace detail { ...@@ -1285,6 +1265,9 @@ namespace detail {
DOCTEST_INTERFACE int setTestSuite(const TestSuite& ts); DOCTEST_INTERFACE int setTestSuite(const TestSuite& ts);
DOCTEST_INTERFACE bool isDebuggerActive(); DOCTEST_INTERFACE bool isDebuggerActive();
template<typename T>
int instantiationHelper(const T&) { return 0; }
namespace binaryAssertComparison { namespace binaryAssertComparison {
enum Enum enum Enum
{ {
...@@ -1314,10 +1297,7 @@ namespace detail { ...@@ -1314,10 +1297,7 @@ namespace detail {
struct DOCTEST_INTERFACE ResultBuilder : public AssertData struct DOCTEST_INTERFACE ResultBuilder : public AssertData
{ {
ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr,
const char* exception_type = ""); const char* exception_type = "", const char* exception_string = "");
DOCTEST_DECLARE_DEFAULTS(ResultBuilder);
DOCTEST_DELETE_COPIES(ResultBuilder);
void setResult(const Result& res); void setResult(const Result& res);
...@@ -1419,8 +1399,6 @@ namespace detail { ...@@ -1419,8 +1399,6 @@ namespace detail {
struct DOCTEST_INTERFACE IExceptionTranslator struct DOCTEST_INTERFACE IExceptionTranslator
{ {
DOCTEST_DELETE_COPIES(IExceptionTranslator);
IExceptionTranslator(); IExceptionTranslator();
virtual ~IExceptionTranslator(); virtual ~IExceptionTranslator();
virtual bool translate(String&) const = 0; virtual bool translate(String&) const = 0;
...@@ -1505,107 +1483,27 @@ namespace detail { ...@@ -1505,107 +1483,27 @@ namespace detail {
DOCTEST_INTERFACE void toStream(std::ostream* s, int long long in); DOCTEST_INTERFACE void toStream(std::ostream* s, int long long in);
DOCTEST_INTERFACE void toStream(std::ostream* s, int long long unsigned in); DOCTEST_INTERFACE void toStream(std::ostream* s, int long long unsigned in);
class DOCTEST_INTERFACE ContextBuilder // ContextScope base class used to allow implementing methods of ContextScope
{ // that don't depend on the template parameter in doctest.cpp.
friend class ContextScope; class DOCTEST_INTERFACE ContextScopeBase : public IContextScope {
protected:
struct DOCTEST_INTERFACE ICapture ContextScopeBase();
{
DOCTEST_DELETE_COPIES(ICapture);
ICapture();
virtual ~ICapture();
virtual void toStream(std::ostream*) const = 0;
};
template <typename T>
struct Capture : public ICapture //!OCLINT destructor of virtual class
{
const T* capture;
explicit Capture(const T* in)
: capture(in) {}
void toStream(std::ostream* s) const override { detail::toStream(s, *capture); }
};
struct DOCTEST_INTERFACE Chunk
{
char buf[sizeof(Capture<char>)] DOCTEST_ALIGNMENT(
2 * sizeof(void*)); // place to construct a Capture<T>
DOCTEST_DECLARE_DEFAULTS(Chunk);
DOCTEST_DELETE_COPIES(Chunk);
};
struct DOCTEST_INTERFACE Node
{
Chunk chunk;
Node* next;
DOCTEST_DECLARE_DEFAULTS(Node);
DOCTEST_DELETE_COPIES(Node);
};
Chunk stackChunks[DOCTEST_CONFIG_NUM_CAPTURES_ON_STACK];
int numCaptures = 0;
Node* head = nullptr;
Node* tail = nullptr;
ContextBuilder(ContextBuilder& other);
ContextBuilder& operator=(const ContextBuilder&) = delete;
void stringify(std::ostream* s) const;
public:
ContextBuilder();
~ContextBuilder();
template <typename T>
DOCTEST_NOINLINE ContextBuilder& operator<<(T& in) {
Capture<T> temp(&in);
// construct either on stack or on heap
// copy the bytes for the whole object - including the vtable because we cant construct
// the object directly in the buffer using placement new - need the <new> header...
if(numCaptures < DOCTEST_CONFIG_NUM_CAPTURES_ON_STACK) {
my_memcpy(stackChunks[numCaptures].buf, &temp, sizeof(Chunk));
} else {
auto curr = new Node;
curr->next = nullptr;
if(tail) {
tail->next = curr;
tail = curr;
} else {
head = tail = curr;
}
my_memcpy(tail->chunk.buf, &temp, sizeof(Chunk));
}
++numCaptures;
return *this;
}
template <typename T> void destroy();
ContextBuilder& operator<<(const T&&) {
static_assert(deferred_false<T>::value,
"Cannot pass temporaries or rvalues to the streaming operator because it "
"caches pointers to the passed objects for lazy evaluation!");
return *this;
}
}; };
class DOCTEST_INTERFACE ContextScope : public IContextScope template <typename L> class DOCTEST_INTERFACE ContextScope : public ContextScopeBase
{ {
ContextBuilder contextBuilder; const L &lambda_;
public: public:
explicit ContextScope(ContextBuilder& temp); explicit ContextScope(const L &lambda) : lambda_(lambda) {}
DOCTEST_DELETE_COPIES(ContextScope); ContextScope(ContextScope &&other) : lambda_(other.lambda_) {}
~ContextScope() override; void stringify(std::ostream* s) const override { lambda_(s); }
void stringify(std::ostream* s) const override; ~ContextScope() override { destroy(); }
}; };
struct DOCTEST_INTERFACE MessageBuilder : public MessageData struct DOCTEST_INTERFACE MessageBuilder : public MessageData
...@@ -1616,8 +1514,6 @@ namespace detail { ...@@ -1616,8 +1514,6 @@ namespace detail {
MessageBuilder() = delete; MessageBuilder() = delete;
~MessageBuilder(); ~MessageBuilder();
DOCTEST_DELETE_COPIES(MessageBuilder);
template <typename T> template <typename T>
MessageBuilder& operator<<(const T& in) { MessageBuilder& operator<<(const T& in) {
toStream(m_stream, in); toStream(m_stream, in);
...@@ -1627,6 +1523,11 @@ namespace detail { ...@@ -1627,6 +1523,11 @@ namespace detail {
bool log(); bool log();
void react(); void react();
}; };
template <typename L>
ContextScope<L> MakeContextScope(const L &lambda) {
return ContextScope<L>(lambda);
}
} // namespace detail } // namespace detail
#define DOCTEST_DEFINE_DECORATOR(name, type, def) \ #define DOCTEST_DEFINE_DECORATOR(name, type, def) \
...@@ -1686,8 +1587,6 @@ class DOCTEST_INTERFACE Context ...@@ -1686,8 +1587,6 @@ class DOCTEST_INTERFACE Context
public: public:
explicit Context(int argc = 0, const char* const* argv = nullptr); explicit Context(int argc = 0, const char* const* argv = nullptr);
DOCTEST_DELETE_COPIES(Context);
~Context(); ~Context();
void applyCommandLine(int argc, const char* const* argv); void applyCommandLine(int argc, const char* const* argv);
...@@ -1729,9 +1628,6 @@ struct DOCTEST_INTERFACE CurrentTestCaseStats ...@@ -1729,9 +1628,6 @@ struct DOCTEST_INTERFACE CurrentTestCaseStats
int numAssertsFailedCurrentTest; int numAssertsFailedCurrentTest;
double seconds; double seconds;
int failure_flags; // use TestCaseFailureReason::Enum int failure_flags; // use TestCaseFailureReason::Enum
DOCTEST_DECLARE_DEFAULTS(CurrentTestCaseStats);
DOCTEST_DELETE_COPIES(CurrentTestCaseStats);
}; };
struct DOCTEST_INTERFACE TestCaseException struct DOCTEST_INTERFACE TestCaseException
...@@ -1748,9 +1644,6 @@ struct DOCTEST_INTERFACE TestRunStats ...@@ -1748,9 +1644,6 @@ struct DOCTEST_INTERFACE TestRunStats
unsigned numTestCasesFailed; unsigned numTestCasesFailed;
int numAsserts; int numAsserts;
int numAssertsFailed; int numAssertsFailed;
DOCTEST_DECLARE_DEFAULTS(TestRunStats);
DOCTEST_DELETE_COPIES(TestRunStats);
}; };
struct QueryData struct QueryData
...@@ -1776,6 +1669,8 @@ struct DOCTEST_INTERFACE IReporter ...@@ -1776,6 +1669,8 @@ struct DOCTEST_INTERFACE IReporter
// called when a test case is started (safe to cache a pointer to the input) // called when a test case is started (safe to cache a pointer to the input)
virtual void test_case_start(const TestCaseData&) = 0; virtual void test_case_start(const TestCaseData&) = 0;
// called when a test case is reentered because of unfinished subcases (safe to cache a pointer to the input)
virtual void test_case_reenter(const TestCaseData&) = 0;
// called when a test case has ended // called when a test case has ended
virtual void test_case_end(const CurrentTestCaseStats&) = 0; virtual void test_case_end(const CurrentTestCaseStats&) = 0;
...@@ -1811,7 +1706,7 @@ struct DOCTEST_INTERFACE IReporter ...@@ -1811,7 +1706,7 @@ struct DOCTEST_INTERFACE IReporter
namespace detail { namespace detail {
typedef IReporter* (*reporterCreatorFunc)(const ContextOptions&); typedef IReporter* (*reporterCreatorFunc)(const ContextOptions&);
DOCTEST_INTERFACE void registerReporterImpl(const char* name, int prio, reporterCreatorFunc c); DOCTEST_INTERFACE void registerReporterImpl(const char* name, int prio, reporterCreatorFunc c, bool isReporter);
template <typename Reporter> template <typename Reporter>
IReporter* reporterCreator(const ContextOptions& o) { IReporter* reporterCreator(const ContextOptions& o) {
...@@ -1820,8 +1715,8 @@ namespace detail { ...@@ -1820,8 +1715,8 @@ namespace detail {
} // namespace detail } // namespace detail
template <typename Reporter> template <typename Reporter>
int registerReporter(const char* name, int priority) { int registerReporter(const char* name, int priority, bool isReporter) {
detail::registerReporterImpl(name, priority, detail::reporterCreator<Reporter>); detail::registerReporterImpl(name, priority, detail::reporterCreator<Reporter>, isReporter);
return 0; return 0;
} }
} // namespace doctest } // namespace doctest
...@@ -1920,68 +1815,55 @@ int registerReporter(const char* name, int priority) { ...@@ -1920,68 +1815,55 @@ int registerReporter(const char* name, int priority) {
} \ } \
typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_) typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
// for typed tests
#define DOCTEST_REGISTER_TYPED_TEST_CASE_IMPL(func, type, decorators, idx) \
doctest::detail::regTest( \
doctest::detail::TestCase(func, __FILE__, __LINE__, \
doctest_detail_test_suite_ns::getCurrentTestSuite(), \
doctest::detail::type_to_string<type>(), idx) * \
decorators)
#define DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, iter, func) \ #define DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, iter, func) \
template <typename T> \ template <typename T> \
inline void func(); \ static void func(); \
namespace { \
template <typename Tuple> \ template <typename Tuple> \
struct iter; \ struct iter; \
template <typename Type, typename... Rest> \ template <typename Type, typename... Rest> \
struct iter<std::tuple<Type, Rest...>> \ struct iter<std::tuple<Type, Rest...>> \
{ \ { \
iter(int line, int index) { \ iter(const char* file, unsigned line, int index) { \
DOCTEST_REGISTER_TYPED_TEST_CASE_IMPL(func<Type>, Type, dec, line * 1000 + index); \ doctest::detail::regTest(doctest::detail::TestCase(func<Type>, file, line, \
iter<std::tuple<Rest...>>(line, index + 1); \ doctest_detail_test_suite_ns::getCurrentTestSuite(), \
doctest::detail::type_to_string<Type>(), \
int(line) * 1000 + index) \
* dec); \
iter<std::tuple<Rest...>>(file, line, index + 1); \
} \ } \
}; \ }; \
template <> \ template <> \
struct iter<std::tuple<>> \ struct iter<std::tuple<>> \
{ \ { \
iter(int, int) {} \ iter(const char*, unsigned, int) {} \
}; \ }; \
} \
template <typename T> \ template <typename T> \
inline void func() static void func()
#define DOCTEST_TEST_CASE_TEMPLATE_DEFINE(dec, T, id) \ #define DOCTEST_TEST_CASE_TEMPLATE_DEFINE(dec, T, id) \
DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(id, ITERATOR), \ DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(id, ITERATOR), \
DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_)) DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_))
#define DOCTEST_TEST_CASE_TEMPLATE_INVOKE_IMPL(id, anon, ...) \ #define DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, anon, ...) \
DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_CAT(anon, DUMMY)) = [] { \ DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_CAT(anon, DUMMY)) = \
DOCTEST_CAT(id, ITERATOR)<std::tuple<__VA_ARGS__>> DOCTEST_UNUSED DOCTEST_CAT( \ doctest::detail::instantiationHelper(DOCTEST_CAT(id, ITERATOR)<__VA_ARGS__>(__FILE__, __LINE__, 0));\
anon, inner_dummy)(__LINE__, 0); \
return 0; \
}(); \
DOCTEST_GLOBAL_NO_WARNINGS_END() DOCTEST_GLOBAL_NO_WARNINGS_END()
#define DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, ...) \ #define DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, ...) \
DOCTEST_TEST_CASE_TEMPLATE_INVOKE_IMPL(id, DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_), __VA_ARGS__) \ DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_), std::tuple<__VA_ARGS__>) \
typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_) typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
#define DOCTEST_TEST_CASE_TEMPLATE_APPLY_IMPL(id, anon, ...) \
DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_CAT(anon, DUMMY)) = [] { \
DOCTEST_CAT(id, ITERATOR)<__VA_ARGS__> DOCTEST_UNUSED DOCTEST_CAT(anon, inner_dummy)( \
__LINE__, 0); \
return 0; \
}(); \
DOCTEST_GLOBAL_NO_WARNINGS_END()
#define DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, ...) \ #define DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, ...) \
DOCTEST_TEST_CASE_TEMPLATE_APPLY_IMPL(id, DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_), __VA_ARGS__) \ DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_), __VA_ARGS__) \
typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_) typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
#define DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, anon, ...) \ #define DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, anon, ...) \
DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(anon, ITERATOR), anon); \ DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(anon, ITERATOR), anon); \
DOCTEST_TEST_CASE_TEMPLATE_INVOKE_IMPL(anon, anon, __VA_ARGS__) \ DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(anon, anon, std::tuple<__VA_ARGS__>) \
template <typename T> \ template <typename T> \
inline void anon() static void anon()
#define DOCTEST_TEST_CASE_TEMPLATE(dec, T, ...) \ #define DOCTEST_TEST_CASE_TEMPLATE(dec, T, ...) \
DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_), __VA_ARGS__) DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_), __VA_ARGS__)
...@@ -2040,16 +1922,33 @@ int registerReporter(const char* name, int priority) { ...@@ -2040,16 +1922,33 @@ int registerReporter(const char* name, int priority) {
DOCTEST_REGISTER_EXCEPTION_TRANSLATOR_IMPL(DOCTEST_ANONYMOUS(_DOCTEST_ANON_TRANSLATOR_), \ DOCTEST_REGISTER_EXCEPTION_TRANSLATOR_IMPL(DOCTEST_ANONYMOUS(_DOCTEST_ANON_TRANSLATOR_), \
signature) signature)
// for registering // for registering reporters
#define DOCTEST_REGISTER_REPORTER(name, priority, reporter) \ #define DOCTEST_REGISTER_REPORTER(name, priority, reporter) \
DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(_DOCTEST_ANON_REPORTER_)) = \ DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(_DOCTEST_ANON_REPORTER_)) = \
doctest::registerReporter<reporter>(name, priority); \ doctest::registerReporter<reporter>(name, priority, true); \
DOCTEST_GLOBAL_NO_WARNINGS_END() typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
// for registering listeners
#define DOCTEST_REGISTER_LISTENER(name, priority, reporter) \
DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(_DOCTEST_ANON_REPORTER_)) = \
doctest::registerReporter<reporter>(name, priority, false); \
DOCTEST_GLOBAL_NO_WARNINGS_END() typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_) DOCTEST_GLOBAL_NO_WARNINGS_END() typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
// for logging // for logging
#define DOCTEST_INFO(x) \ #define DOCTEST_INFO(expression) \
doctest::detail::ContextScope DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_)( \ DOCTEST_INFO_IMPL(DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_), DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_), \
doctest::detail::ContextBuilder() << x) DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_), expression)
#define DOCTEST_INFO_IMPL(lambda_name, mb_name, s_name, expression) \
DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4626) \
auto lambda_name = [&](std::ostream* s_name) { \
doctest::detail::MessageBuilder mb_name(__FILE__, __LINE__, doctest::assertType::is_warn); \
mb_name.m_stream = s_name; \
mb_name << expression; \
}; \
DOCTEST_MSVC_SUPPRESS_WARNING_POP \
auto DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_) = doctest::detail::MakeContextScope(lambda_name)
#define DOCTEST_CAPTURE(x) DOCTEST_INFO(#x " := " << x) #define DOCTEST_CAPTURE(x) DOCTEST_INFO(#x " := " << x)
#define DOCTEST_ADD_AT_IMPL(type, file, line, mb, x) \ #define DOCTEST_ADD_AT_IMPL(type, file, line, mb, x) \
...@@ -2069,14 +1968,7 @@ int registerReporter(const char* name, int priority) { ...@@ -2069,14 +1968,7 @@ int registerReporter(const char* name, int priority) {
#define DOCTEST_FAIL_CHECK(x) DOCTEST_ADD_FAIL_CHECK_AT(__FILE__, __LINE__, x) #define DOCTEST_FAIL_CHECK(x) DOCTEST_ADD_FAIL_CHECK_AT(__FILE__, __LINE__, x)
#define DOCTEST_FAIL(x) DOCTEST_ADD_FAIL_AT(__FILE__, __LINE__, x) #define DOCTEST_FAIL(x) DOCTEST_ADD_FAIL_AT(__FILE__, __LINE__, x)
// hack for macros like INFO() that require lvalues #define DOCTEST_TO_LVALUE(...) __VA_ARGS__ // Not removed to keep backwards compatibility.
#if __cplusplus >= 201402L || (DOCTEST_MSVC >= DOCTEST_COMPILER(19, 10, 0))
template <class T, T x>
constexpr T to_lvalue = x;
#define DOCTEST_TO_LVALUE(...) to_lvalue<decltype(__VA_ARGS__), __VA_ARGS__>
#else // TO_LVALUE
#define DOCTEST_TO_LVALUE(...) TO_LVALUE_CAN_BE_USED_ONLY_IN_CPP14_MODE_OR_WITH_VS_2017_OR_NEWER
#endif // TO_LVALUE
#ifndef DOCTEST_CONFIG_SUPER_FAST_ASSERTS #ifndef DOCTEST_CONFIG_SUPER_FAST_ASSERTS
...@@ -2097,6 +1989,9 @@ constexpr T to_lvalue = x; ...@@ -2097,6 +1989,9 @@ constexpr T to_lvalue = x;
#else // DOCTEST_CONFIG_SUPER_FAST_ASSERTS #else // DOCTEST_CONFIG_SUPER_FAST_ASSERTS
// necessary for <ASSERT>_MESSAGE
#define DOCTEST_ASSERT_IMPLEMENT_2 DOCTEST_ASSERT_IMPLEMENT_1
#define DOCTEST_ASSERT_IMPLEMENT_1(assert_type, ...) \ #define DOCTEST_ASSERT_IMPLEMENT_1(assert_type, ...) \
DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Woverloaded-shift-op-parentheses") \ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Woverloaded-shift-op-parentheses") \
doctest::detail::decomp_assert( \ doctest::detail::decomp_assert( \
...@@ -2122,11 +2017,11 @@ constexpr T to_lvalue = x; ...@@ -2122,11 +2017,11 @@ constexpr T to_lvalue = x;
#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, msg) do { DOCTEST_INFO(msg); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE_FALSE, cond); } while((void)0, 0) #define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, msg) do { DOCTEST_INFO(msg); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE_FALSE, cond); } while((void)0, 0)
// clang-format on // clang-format on
#define DOCTEST_ASSERT_THROWS_AS(expr, assert_type, ...) \ #define DOCTEST_ASSERT_THROWS_AS(expr, assert_type, message, ...) \
do { \ do { \
if(!doctest::getContextOptions()->no_throw) { \ if(!doctest::getContextOptions()->no_throw) { \
doctest::detail::ResultBuilder _DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ doctest::detail::ResultBuilder _DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
__LINE__, #expr, #__VA_ARGS__); \ __LINE__, #expr, #__VA_ARGS__, message); \
try { \ try { \
DOCTEST_CAST_TO_VOID(expr) \ DOCTEST_CAST_TO_VOID(expr) \
} catch(const doctest::detail::remove_const< \ } catch(const doctest::detail::remove_const< \
...@@ -2142,7 +2037,7 @@ constexpr T to_lvalue = x; ...@@ -2142,7 +2037,7 @@ constexpr T to_lvalue = x;
do { \ do { \
if(!doctest::getContextOptions()->no_throw) { \ if(!doctest::getContextOptions()->no_throw) { \
doctest::detail::ResultBuilder _DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ doctest::detail::ResultBuilder _DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
__LINE__, #expr, __VA_ARGS__); \ __LINE__, #expr, "", __VA_ARGS__); \
try { \ try { \
DOCTEST_CAST_TO_VOID(expr) \ DOCTEST_CAST_TO_VOID(expr) \
} catch(...) { _DOCTEST_RB.translateException(); } \ } catch(...) { _DOCTEST_RB.translateException(); } \
...@@ -2165,14 +2060,18 @@ constexpr T to_lvalue = x; ...@@ -2165,14 +2060,18 @@ constexpr T to_lvalue = x;
#define DOCTEST_CHECK_THROWS(expr) DOCTEST_ASSERT_THROWS_WITH(expr, DT_CHECK_THROWS, "") #define DOCTEST_CHECK_THROWS(expr) DOCTEST_ASSERT_THROWS_WITH(expr, DT_CHECK_THROWS, "")
#define DOCTEST_REQUIRE_THROWS(expr) DOCTEST_ASSERT_THROWS_WITH(expr, DT_REQUIRE_THROWS, "") #define DOCTEST_REQUIRE_THROWS(expr) DOCTEST_ASSERT_THROWS_WITH(expr, DT_REQUIRE_THROWS, "")
#define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_WARN_THROWS_AS, __VA_ARGS__) #define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_WARN_THROWS_AS, "", __VA_ARGS__)
#define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_CHECK_THROWS_AS, __VA_ARGS__) #define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_CHECK_THROWS_AS, "", __VA_ARGS__)
#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_REQUIRE_THROWS_AS, __VA_ARGS__) #define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_REQUIRE_THROWS_AS, "", __VA_ARGS__)
#define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, DT_WARN_THROWS_WITH, __VA_ARGS__) #define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, DT_WARN_THROWS_WITH, __VA_ARGS__)
#define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, DT_CHECK_THROWS_WITH, __VA_ARGS__) #define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, DT_CHECK_THROWS_WITH, __VA_ARGS__)
#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, DT_REQUIRE_THROWS_WITH, __VA_ARGS__) #define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, DT_REQUIRE_THROWS_WITH, __VA_ARGS__)
#define DOCTEST_WARN_THROWS_WITH_AS(expr, message, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_WARN_THROWS_WITH_AS, message, __VA_ARGS__)
#define DOCTEST_CHECK_THROWS_WITH_AS(expr, message, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_CHECK_THROWS_WITH_AS, message, __VA_ARGS__)
#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, message, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_REQUIRE_THROWS_WITH_AS, message, __VA_ARGS__)
#define DOCTEST_WARN_NOTHROW(expr) DOCTEST_ASSERT_NOTHROW(expr, DT_WARN_NOTHROW) #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_CHECK_NOTHROW(expr) DOCTEST_ASSERT_NOTHROW(expr, DT_CHECK_NOTHROW)
#define DOCTEST_REQUIRE_NOTHROW(expr) DOCTEST_ASSERT_NOTHROW(expr, DT_REQUIRE_NOTHROW) #define DOCTEST_REQUIRE_NOTHROW(expr) DOCTEST_ASSERT_NOTHROW(expr, DT_REQUIRE_NOTHROW)
...@@ -2183,9 +2082,12 @@ constexpr T to_lvalue = x; ...@@ -2183,9 +2082,12 @@ constexpr T to_lvalue = x;
#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_WARN_THROWS_AS(expr, ex); } while((void)0, 0) #define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_WARN_THROWS_AS(expr, ex); } while((void)0, 0)
#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_CHECK_THROWS_AS(expr, ex); } while((void)0, 0) #define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_CHECK_THROWS_AS(expr, ex); } while((void)0, 0)
#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_REQUIRE_THROWS_AS(expr, ex); } while((void)0, 0) #define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_REQUIRE_THROWS_AS(expr, ex); } while((void)0, 0)
#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_WARN_THROWS_WITH(expr, ex); } while((void)0, 0) #define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, msg) do { DOCTEST_INFO(msg); DOCTEST_WARN_THROWS_WITH(expr, with); } while((void)0, 0)
#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_CHECK_THROWS_WITH(expr, ex); } while((void)0, 0) #define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, msg) do { DOCTEST_INFO(msg); DOCTEST_CHECK_THROWS_WITH(expr, with); } while((void)0, 0)
#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_REQUIRE_THROWS_WITH(expr, ex); } while((void)0, 0) #define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, msg) do { DOCTEST_INFO(msg); DOCTEST_REQUIRE_THROWS_WITH(expr, with); } while((void)0, 0)
#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_WARN_THROWS_WITH_AS(expr, with, ex); } while((void)0, 0)
#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ex); } while((void)0, 0)
#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ex); } while((void)0, 0)
#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, msg) do { DOCTEST_INFO(msg); DOCTEST_WARN_NOTHROW(expr); } while((void)0, 0) #define DOCTEST_WARN_NOTHROW_MESSAGE(expr, msg) do { DOCTEST_INFO(msg); DOCTEST_WARN_NOTHROW(expr); } while((void)0, 0)
#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, msg) do { DOCTEST_INFO(msg); DOCTEST_CHECK_NOTHROW(expr); } while((void)0, 0) #define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, msg) do { DOCTEST_INFO(msg); DOCTEST_CHECK_NOTHROW(expr); } while((void)0, 0)
#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, msg) do { DOCTEST_INFO(msg); DOCTEST_REQUIRE_NOTHROW(expr); } while((void)0, 0) #define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, msg) do { DOCTEST_INFO(msg); DOCTEST_REQUIRE_NOTHROW(expr); } while((void)0, 0)
...@@ -2260,6 +2162,9 @@ constexpr T to_lvalue = x; ...@@ -2260,6 +2162,9 @@ constexpr T to_lvalue = x;
#undef DOCTEST_WARN_THROWS_WITH #undef DOCTEST_WARN_THROWS_WITH
#undef DOCTEST_CHECK_THROWS_WITH #undef DOCTEST_CHECK_THROWS_WITH
#undef DOCTEST_REQUIRE_THROWS_WITH #undef DOCTEST_REQUIRE_THROWS_WITH
#undef DOCTEST_WARN_THROWS_WITH_AS
#undef DOCTEST_CHECK_THROWS_WITH_AS
#undef DOCTEST_REQUIRE_THROWS_WITH_AS
#undef DOCTEST_WARN_NOTHROW #undef DOCTEST_WARN_NOTHROW
#undef DOCTEST_CHECK_NOTHROW #undef DOCTEST_CHECK_NOTHROW
#undef DOCTEST_REQUIRE_NOTHROW #undef DOCTEST_REQUIRE_NOTHROW
...@@ -2273,6 +2178,9 @@ constexpr T to_lvalue = x; ...@@ -2273,6 +2178,9 @@ constexpr T to_lvalue = x;
#undef DOCTEST_WARN_THROWS_WITH_MESSAGE #undef DOCTEST_WARN_THROWS_WITH_MESSAGE
#undef DOCTEST_CHECK_THROWS_WITH_MESSAGE #undef DOCTEST_CHECK_THROWS_WITH_MESSAGE
#undef DOCTEST_REQUIRE_THROWS_WITH_MESSAGE #undef DOCTEST_REQUIRE_THROWS_WITH_MESSAGE
#undef DOCTEST_WARN_THROWS_WITH_AS_MESSAGE
#undef DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE
#undef DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE
#undef DOCTEST_WARN_NOTHROW_MESSAGE #undef DOCTEST_WARN_NOTHROW_MESSAGE
#undef DOCTEST_CHECK_NOTHROW_MESSAGE #undef DOCTEST_CHECK_NOTHROW_MESSAGE
#undef DOCTEST_REQUIRE_NOTHROW_MESSAGE #undef DOCTEST_REQUIRE_NOTHROW_MESSAGE
...@@ -2288,6 +2196,9 @@ constexpr T to_lvalue = x; ...@@ -2288,6 +2196,9 @@ constexpr T to_lvalue = x;
#define DOCTEST_WARN_THROWS_WITH(expr, ...) ((void)0) #define DOCTEST_WARN_THROWS_WITH(expr, ...) ((void)0)
#define DOCTEST_CHECK_THROWS_WITH(expr, ...) ((void)0) #define DOCTEST_CHECK_THROWS_WITH(expr, ...) ((void)0)
#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) ((void)0) #define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) ((void)0)
#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) ((void)0)
#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) ((void)0)
#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) ((void)0)
#define DOCTEST_WARN_NOTHROW(expr) ((void)0) #define DOCTEST_WARN_NOTHROW(expr) ((void)0)
#define DOCTEST_CHECK_NOTHROW(expr) ((void)0) #define DOCTEST_CHECK_NOTHROW(expr) ((void)0)
#define DOCTEST_REQUIRE_NOTHROW(expr) ((void)0) #define DOCTEST_REQUIRE_NOTHROW(expr) ((void)0)
...@@ -2298,9 +2209,12 @@ constexpr T to_lvalue = x; ...@@ -2298,9 +2209,12 @@ constexpr T to_lvalue = x;
#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, msg) ((void)0) #define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, msg) ((void)0)
#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, msg) ((void)0) #define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, msg) ((void)0)
#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, msg) ((void)0) #define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, msg) ((void)0)
#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, ex, msg) ((void)0) #define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, msg) ((void)0)
#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, ex, msg) ((void)0) #define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, msg) ((void)0)
#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, ex, msg) ((void)0) #define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, msg) ((void)0)
#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) ((void)0)
#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) ((void)0)
#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) ((void)0)
#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, msg) ((void)0) #define DOCTEST_WARN_NOTHROW_MESSAGE(expr, msg) ((void)0)
#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, msg) ((void)0) #define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, msg) ((void)0)
#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, msg) ((void)0) #define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, msg) ((void)0)
...@@ -2392,6 +2306,7 @@ constexpr T to_lvalue = x; ...@@ -2392,6 +2306,7 @@ constexpr T to_lvalue = x;
static inline doctest::String DOCTEST_ANONYMOUS(_DOCTEST_ANON_TRANSLATOR_)(signature) static inline doctest::String DOCTEST_ANONYMOUS(_DOCTEST_ANON_TRANSLATOR_)(signature)
#define DOCTEST_REGISTER_REPORTER(name, priority, reporter) #define DOCTEST_REGISTER_REPORTER(name, priority, reporter)
#define DOCTEST_REGISTER_LISTENER(name, priority, reporter)
#define DOCTEST_INFO(x) ((void)0) #define DOCTEST_INFO(x) ((void)0)
#define DOCTEST_CAPTURE(x) ((void)0) #define DOCTEST_CAPTURE(x) ((void)0)
...@@ -2425,6 +2340,9 @@ constexpr T to_lvalue = x; ...@@ -2425,6 +2340,9 @@ constexpr T to_lvalue = x;
#define DOCTEST_WARN_THROWS_WITH(expr, ...) ((void)0) #define DOCTEST_WARN_THROWS_WITH(expr, ...) ((void)0)
#define DOCTEST_CHECK_THROWS_WITH(expr, ...) ((void)0) #define DOCTEST_CHECK_THROWS_WITH(expr, ...) ((void)0)
#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) ((void)0) #define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) ((void)0)
#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) ((void)0)
#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) ((void)0)
#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) ((void)0)
#define DOCTEST_WARN_NOTHROW(expr) ((void)0) #define DOCTEST_WARN_NOTHROW(expr) ((void)0)
#define DOCTEST_CHECK_NOTHROW(expr) ((void)0) #define DOCTEST_CHECK_NOTHROW(expr) ((void)0)
#define DOCTEST_REQUIRE_NOTHROW(expr) ((void)0) #define DOCTEST_REQUIRE_NOTHROW(expr) ((void)0)
...@@ -2435,9 +2353,12 @@ constexpr T to_lvalue = x; ...@@ -2435,9 +2353,12 @@ constexpr T to_lvalue = x;
#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, msg) ((void)0) #define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, msg) ((void)0)
#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, msg) ((void)0) #define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, msg) ((void)0)
#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, msg) ((void)0) #define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, msg) ((void)0)
#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, ex, msg) ((void)0) #define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, msg) ((void)0)
#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, ex, msg) ((void)0) #define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, msg) ((void)0)
#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, ex, msg) ((void)0) #define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, msg) ((void)0)
#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) ((void)0)
#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) ((void)0)
#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) ((void)0)
#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, msg) ((void)0) #define DOCTEST_WARN_NOTHROW_MESSAGE(expr, msg) ((void)0)
#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, msg) ((void)0) #define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, msg) ((void)0)
#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, msg) ((void)0) #define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, msg) ((void)0)
...@@ -2508,11 +2429,11 @@ constexpr T to_lvalue = x; ...@@ -2508,11 +2429,11 @@ constexpr T to_lvalue = x;
#define DOCTEST_SCENARIO_TEMPLATE(name, T, ...) DOCTEST_TEST_CASE_TEMPLATE(" Scenario: " name, T, __VA_ARGS__) #define DOCTEST_SCENARIO_TEMPLATE(name, T, ...) DOCTEST_TEST_CASE_TEMPLATE(" Scenario: " name, T, __VA_ARGS__)
#define DOCTEST_SCENARIO_TEMPLATE_DEFINE(name, T, id) DOCTEST_TEST_CASE_TEMPLATE_DEFINE(" Scenario: " name, T, id) #define DOCTEST_SCENARIO_TEMPLATE_DEFINE(name, T, id) DOCTEST_TEST_CASE_TEMPLATE_DEFINE(" Scenario: " name, T, id)
#define DOCTEST_GIVEN(name) SUBCASE(" Given: " name) #define DOCTEST_GIVEN(name) DOCTEST_SUBCASE(" Given: " name)
#define DOCTEST_WHEN(name) SUBCASE(" When: " name) #define DOCTEST_WHEN(name) DOCTEST_SUBCASE(" When: " name)
#define DOCTEST_AND_WHEN(name) SUBCASE("And when: " name) #define DOCTEST_AND_WHEN(name) DOCTEST_SUBCASE("And when: " name)
#define DOCTEST_THEN(name) SUBCASE(" Then: " name) #define DOCTEST_THEN(name) DOCTEST_SUBCASE(" Then: " name)
#define DOCTEST_AND_THEN(name) SUBCASE(" And: " name) #define DOCTEST_AND_THEN(name) DOCTEST_SUBCASE(" And: " name)
// clang-format on // clang-format on
// == SHORT VERSIONS OF THE MACROS // == SHORT VERSIONS OF THE MACROS
...@@ -2532,6 +2453,7 @@ constexpr T to_lvalue = x; ...@@ -2532,6 +2453,7 @@ constexpr T to_lvalue = x;
#define TEST_SUITE_END DOCTEST_TEST_SUITE_END #define TEST_SUITE_END DOCTEST_TEST_SUITE_END
#define REGISTER_EXCEPTION_TRANSLATOR DOCTEST_REGISTER_EXCEPTION_TRANSLATOR #define REGISTER_EXCEPTION_TRANSLATOR DOCTEST_REGISTER_EXCEPTION_TRANSLATOR
#define REGISTER_REPORTER DOCTEST_REGISTER_REPORTER #define REGISTER_REPORTER DOCTEST_REGISTER_REPORTER
#define REGISTER_LISTENER DOCTEST_REGISTER_LISTENER
#define INFO DOCTEST_INFO #define INFO DOCTEST_INFO
#define CAPTURE DOCTEST_CAPTURE #define CAPTURE DOCTEST_CAPTURE
#define ADD_MESSAGE_AT DOCTEST_ADD_MESSAGE_AT #define ADD_MESSAGE_AT DOCTEST_ADD_MESSAGE_AT
...@@ -2547,18 +2469,21 @@ constexpr T to_lvalue = x; ...@@ -2547,18 +2469,21 @@ constexpr T to_lvalue = x;
#define WARN_THROWS DOCTEST_WARN_THROWS #define WARN_THROWS DOCTEST_WARN_THROWS
#define WARN_THROWS_AS DOCTEST_WARN_THROWS_AS #define WARN_THROWS_AS DOCTEST_WARN_THROWS_AS
#define WARN_THROWS_WITH DOCTEST_WARN_THROWS_WITH #define WARN_THROWS_WITH DOCTEST_WARN_THROWS_WITH
#define WARN_THROWS_WITH_AS DOCTEST_WARN_THROWS_WITH_AS
#define WARN_NOTHROW DOCTEST_WARN_NOTHROW #define WARN_NOTHROW DOCTEST_WARN_NOTHROW
#define CHECK DOCTEST_CHECK #define CHECK DOCTEST_CHECK
#define CHECK_FALSE DOCTEST_CHECK_FALSE #define CHECK_FALSE DOCTEST_CHECK_FALSE
#define CHECK_THROWS DOCTEST_CHECK_THROWS #define CHECK_THROWS DOCTEST_CHECK_THROWS
#define CHECK_THROWS_AS DOCTEST_CHECK_THROWS_AS #define CHECK_THROWS_AS DOCTEST_CHECK_THROWS_AS
#define CHECK_THROWS_WITH DOCTEST_CHECK_THROWS_WITH #define CHECK_THROWS_WITH DOCTEST_CHECK_THROWS_WITH
#define CHECK_THROWS_WITH_AS DOCTEST_CHECK_THROWS_WITH_AS
#define CHECK_NOTHROW DOCTEST_CHECK_NOTHROW #define CHECK_NOTHROW DOCTEST_CHECK_NOTHROW
#define REQUIRE DOCTEST_REQUIRE #define REQUIRE DOCTEST_REQUIRE
#define REQUIRE_FALSE DOCTEST_REQUIRE_FALSE #define REQUIRE_FALSE DOCTEST_REQUIRE_FALSE
#define REQUIRE_THROWS DOCTEST_REQUIRE_THROWS #define REQUIRE_THROWS DOCTEST_REQUIRE_THROWS
#define REQUIRE_THROWS_AS DOCTEST_REQUIRE_THROWS_AS #define REQUIRE_THROWS_AS DOCTEST_REQUIRE_THROWS_AS
#define REQUIRE_THROWS_WITH DOCTEST_REQUIRE_THROWS_WITH #define REQUIRE_THROWS_WITH DOCTEST_REQUIRE_THROWS_WITH
#define REQUIRE_THROWS_WITH_AS DOCTEST_REQUIRE_THROWS_WITH_AS
#define REQUIRE_NOTHROW DOCTEST_REQUIRE_NOTHROW #define REQUIRE_NOTHROW DOCTEST_REQUIRE_NOTHROW
#define WARN_MESSAGE DOCTEST_WARN_MESSAGE #define WARN_MESSAGE DOCTEST_WARN_MESSAGE
...@@ -2566,18 +2491,21 @@ constexpr T to_lvalue = x; ...@@ -2566,18 +2491,21 @@ constexpr T to_lvalue = x;
#define WARN_THROWS_MESSAGE DOCTEST_WARN_THROWS_MESSAGE #define WARN_THROWS_MESSAGE DOCTEST_WARN_THROWS_MESSAGE
#define WARN_THROWS_AS_MESSAGE DOCTEST_WARN_THROWS_AS_MESSAGE #define WARN_THROWS_AS_MESSAGE DOCTEST_WARN_THROWS_AS_MESSAGE
#define WARN_THROWS_WITH_MESSAGE DOCTEST_WARN_THROWS_WITH_MESSAGE #define WARN_THROWS_WITH_MESSAGE DOCTEST_WARN_THROWS_WITH_MESSAGE
#define WARN_THROWS_WITH_AS_MESSAGE DOCTEST_WARN_THROWS_WITH_AS_MESSAGE
#define WARN_NOTHROW_MESSAGE DOCTEST_WARN_NOTHROW_MESSAGE #define WARN_NOTHROW_MESSAGE DOCTEST_WARN_NOTHROW_MESSAGE
#define CHECK_MESSAGE DOCTEST_CHECK_MESSAGE #define CHECK_MESSAGE DOCTEST_CHECK_MESSAGE
#define CHECK_FALSE_MESSAGE DOCTEST_CHECK_FALSE_MESSAGE #define CHECK_FALSE_MESSAGE DOCTEST_CHECK_FALSE_MESSAGE
#define CHECK_THROWS_MESSAGE DOCTEST_CHECK_THROWS_MESSAGE #define CHECK_THROWS_MESSAGE DOCTEST_CHECK_THROWS_MESSAGE
#define CHECK_THROWS_AS_MESSAGE DOCTEST_CHECK_THROWS_AS_MESSAGE #define CHECK_THROWS_AS_MESSAGE DOCTEST_CHECK_THROWS_AS_MESSAGE
#define CHECK_THROWS_WITH_MESSAGE DOCTEST_CHECK_THROWS_WITH_MESSAGE #define CHECK_THROWS_WITH_MESSAGE DOCTEST_CHECK_THROWS_WITH_MESSAGE
#define CHECK_THROWS_WITH_AS_MESSAGE DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE
#define CHECK_NOTHROW_MESSAGE DOCTEST_CHECK_NOTHROW_MESSAGE #define CHECK_NOTHROW_MESSAGE DOCTEST_CHECK_NOTHROW_MESSAGE
#define REQUIRE_MESSAGE DOCTEST_REQUIRE_MESSAGE #define REQUIRE_MESSAGE DOCTEST_REQUIRE_MESSAGE
#define REQUIRE_FALSE_MESSAGE DOCTEST_REQUIRE_FALSE_MESSAGE #define REQUIRE_FALSE_MESSAGE DOCTEST_REQUIRE_FALSE_MESSAGE
#define REQUIRE_THROWS_MESSAGE DOCTEST_REQUIRE_THROWS_MESSAGE #define REQUIRE_THROWS_MESSAGE DOCTEST_REQUIRE_THROWS_MESSAGE
#define REQUIRE_THROWS_AS_MESSAGE DOCTEST_REQUIRE_THROWS_AS_MESSAGE #define REQUIRE_THROWS_AS_MESSAGE DOCTEST_REQUIRE_THROWS_AS_MESSAGE
#define REQUIRE_THROWS_WITH_MESSAGE DOCTEST_REQUIRE_THROWS_WITH_MESSAGE #define REQUIRE_THROWS_WITH_MESSAGE DOCTEST_REQUIRE_THROWS_WITH_MESSAGE
#define REQUIRE_THROWS_WITH_AS_MESSAGE DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE
#define REQUIRE_NOTHROW_MESSAGE DOCTEST_REQUIRE_NOTHROW_MESSAGE #define REQUIRE_NOTHROW_MESSAGE DOCTEST_REQUIRE_NOTHROW_MESSAGE
#define SCENARIO DOCTEST_SCENARIO #define SCENARIO DOCTEST_SCENARIO
...@@ -2686,13 +2614,18 @@ DOCTEST_GCC_SUPPRESS_WARNING_POP ...@@ -2686,13 +2614,18 @@ DOCTEST_GCC_SUPPRESS_WARNING_POP
#endif // DOCTEST_SINGLE_HEADER #endif // DOCTEST_SINGLE_HEADER
#if defined(DOCTEST_CONFIG_IMPLEMENT) || !defined(DOCTEST_SINGLE_HEADER) #if defined(DOCTEST_CONFIG_IMPLEMENT) || !defined(DOCTEST_SINGLE_HEADER)
#ifndef DOCTEST_LIBRARY_IMPLEMENTATION
#define DOCTEST_LIBRARY_IMPLEMENTATION
#ifndef DOCTEST_SINGLE_HEADER #ifndef DOCTEST_SINGLE_HEADER
#include "doctest_fwd.h" #include "doctest_fwd.h"
#endif // DOCTEST_SINGLE_HEADER #endif // DOCTEST_SINGLE_HEADER
DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-macros")
#ifndef DOCTEST_LIBRARY_IMPLEMENTATION
#define DOCTEST_LIBRARY_IMPLEMENTATION
DOCTEST_CLANG_SUPPRESS_WARNING_POP
DOCTEST_CLANG_SUPPRESS_WARNING_PUSH DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
DOCTEST_CLANG_SUPPRESS_WARNING("-Wunknown-pragmas") DOCTEST_CLANG_SUPPRESS_WARNING("-Wunknown-pragmas")
DOCTEST_CLANG_SUPPRESS_WARNING("-Wpadded") DOCTEST_CLANG_SUPPRESS_WARNING("-Wpadded")
...@@ -2813,9 +2746,6 @@ DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN ...@@ -2813,9 +2746,6 @@ DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN
#ifndef WIN32_LEAN_AND_MEAN #ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#endif // WIN32_LEAN_AND_MEAN #endif // WIN32_LEAN_AND_MEAN
#ifndef VC_EXTRA_LEAN
#define VC_EXTRA_LEAN
#endif // VC_EXTRA_LEAN
#ifndef NOMINMAX #ifndef NOMINMAX
#define NOMINMAX #define NOMINMAX
#endif // NOMINMAX #endif // NOMINMAX
...@@ -2927,7 +2857,7 @@ namespace detail { ...@@ -2927,7 +2857,7 @@ namespace detail {
return oss.str().c_str(); return oss.str().c_str();
} }
DOCTEST_THREAD_LOCAL std::ostringstream g_oss; DOCTEST_THREAD_LOCAL std::ostringstream g_oss; // NOLINT(cert-err58-cpp)
std::ostream* getTlsOss() { std::ostream* getTlsOss() {
g_oss.clear(); // there shouldn't be anything worth clearing in the flags g_oss.clear(); // there shouldn't be anything worth clearing in the flags
...@@ -3000,10 +2930,11 @@ namespace detail { ...@@ -3000,10 +2930,11 @@ namespace detail {
std::vector<String> stringifiedContexts; // logging from INFO() due to an exception std::vector<String> stringifiedContexts; // logging from INFO() due to an exception
// stuff for subcases // stuff for subcases
std::set<SubcaseSignature> subcasesPassed; std::vector<SubcaseSignature> subcasesStack;
std::set<int> subcasesEnteredLevels; std::set<decltype(subcasesStack)> subcasesPassed;
int subcasesCurrentLevel; int subcasesCurrentMaxLevel;
bool should_reenter; bool should_reenter;
std::atomic<bool> shouldLogCurrentException;
void resetRunData() { void resetRunData() {
numTestCases = 0; numTestCases = 0;
...@@ -3270,6 +3201,10 @@ const char* assertString(assertType::Enum at) { ...@@ -3270,6 +3201,10 @@ const char* assertString(assertType::Enum at) {
case assertType::DT_CHECK_THROWS_WITH : return "CHECK_THROWS_WITH"; case assertType::DT_CHECK_THROWS_WITH : return "CHECK_THROWS_WITH";
case assertType::DT_REQUIRE_THROWS_WITH : return "REQUIRE_THROWS_WITH"; case assertType::DT_REQUIRE_THROWS_WITH : return "REQUIRE_THROWS_WITH";
case assertType::DT_WARN_THROWS_WITH_AS : return "WARN_THROWS_WITH_AS";
case assertType::DT_CHECK_THROWS_WITH_AS : return "CHECK_THROWS_WITH_AS";
case assertType::DT_REQUIRE_THROWS_WITH_AS : return "REQUIRE_THROWS_WITH_AS";
case assertType::DT_WARN_NOTHROW : return "WARN_NOTHROW"; case assertType::DT_WARN_NOTHROW : return "WARN_NOTHROW";
case assertType::DT_CHECK_NOTHROW : return "CHECK_NOTHROW"; case assertType::DT_CHECK_NOTHROW : return "CHECK_NOTHROW";
case assertType::DT_REQUIRE_NOTHROW : return "REQUIRE_NOTHROW"; case assertType::DT_REQUIRE_NOTHROW : return "REQUIRE_NOTHROW";
...@@ -3333,21 +3268,6 @@ const char* skipPathFromFilename(const char* file) { ...@@ -3333,21 +3268,6 @@ const char* skipPathFromFilename(const char* file) {
DOCTEST_CLANG_SUPPRESS_WARNING_POP DOCTEST_CLANG_SUPPRESS_WARNING_POP
DOCTEST_GCC_SUPPRESS_WARNING_POP DOCTEST_GCC_SUPPRESS_WARNING_POP
DOCTEST_DEFINE_DEFAULTS(TestCaseData);
DOCTEST_DEFINE_COPIES(TestCaseData);
DOCTEST_DEFINE_DEFAULTS(AssertData);
DOCTEST_DEFINE_DEFAULTS(MessageData);
SubcaseSignature::SubcaseSignature(const char* name, const char* file, int line)
: m_name(name)
, m_file(file)
, m_line(line) {}
DOCTEST_DEFINE_DEFAULTS(SubcaseSignature);
DOCTEST_DEFINE_COPIES(SubcaseSignature);
bool SubcaseSignature::operator<(const SubcaseSignature& other) const { bool SubcaseSignature::operator<(const SubcaseSignature& other) const {
if(m_line != other.m_line) if(m_line != other.m_line)
return m_line < other.m_line; return m_line < other.m_line;
...@@ -3359,8 +3279,6 @@ bool SubcaseSignature::operator<(const SubcaseSignature& other) const { ...@@ -3359,8 +3279,6 @@ bool SubcaseSignature::operator<(const SubcaseSignature& other) const {
IContextScope::IContextScope() = default; IContextScope::IContextScope() = default;
IContextScope::~IContextScope() = default; IContextScope::~IContextScope() = default;
DOCTEST_DEFINE_DEFAULTS(ContextOptions);
#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING #ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
String toString(char* in) { return toString(static_cast<const char*>(in)); } String toString(char* in) { return toString(static_cast<const char*>(in)); }
String toString(const char* in) { return String("\"") + (in ? in : "{null string}") + "\""; } String toString(const char* in) { return String("\"") + (in ? in : "{null string}") + "\""; }
...@@ -3391,13 +3309,16 @@ DOCTEST_TO_STRING_OVERLOAD(int long long unsigned, "%llu") ...@@ -3391,13 +3309,16 @@ DOCTEST_TO_STRING_OVERLOAD(int long long unsigned, "%llu")
String toString(std::nullptr_t) { return "NULL"; } String toString(std::nullptr_t) { return "NULL"; }
#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0)
// see this issue on why this is needed: https://github.com/onqtam/doctest/issues/183
String toString(const std::string& in) { return in.c_str(); }
#endif // VS 2019
Approx::Approx(double value) Approx::Approx(double value)
: m_epsilon(static_cast<double>(std::numeric_limits<float>::epsilon()) * 100) : m_epsilon(static_cast<double>(std::numeric_limits<float>::epsilon()) * 100)
, m_scale(1.0) , m_scale(1.0)
, m_value(value) {} , m_value(value) {}
DOCTEST_DEFINE_COPIES(Approx);
Approx Approx::operator()(double value) const { Approx Approx::operator()(double value) const {
Approx approx(value); Approx approx(value);
approx.epsilon(m_epsilon); approx.epsilon(m_epsilon);
...@@ -3417,7 +3338,7 @@ Approx& Approx::scale(double newScale) { ...@@ -3417,7 +3338,7 @@ Approx& Approx::scale(double newScale) {
bool operator==(double lhs, const Approx& rhs) { bool operator==(double lhs, const Approx& rhs) {
// Thanks to Richard Harris for his help refining this formula // Thanks to Richard Harris for his help refining this formula
return std::fabs(lhs - rhs.m_value) < return std::fabs(lhs - rhs.m_value) <
rhs.m_epsilon * (rhs.m_scale + std::max(std::fabs(lhs), std::fabs(rhs.m_value))); rhs.m_epsilon * (rhs.m_scale + std::max<double>(std::fabs(lhs), std::fabs(rhs.m_value)));
} }
bool operator==(const Approx& lhs, double rhs) { return operator==(rhs, lhs); } bool operator==(const Approx& lhs, double rhs) { return operator==(rhs, lhs); }
bool operator!=(double lhs, const Approx& rhs) { return !operator==(lhs, rhs); } bool operator!=(double lhs, const Approx& rhs) { return !operator==(lhs, rhs); }
...@@ -3452,10 +3373,6 @@ void Context::setAsDefaultForAssertsOutOfTestCases() {} ...@@ -3452,10 +3373,6 @@ void Context::setAsDefaultForAssertsOutOfTestCases() {}
void Context::setAssertHandler(detail::assert_handler) {} void Context::setAssertHandler(detail::assert_handler) {}
int Context::run() { return 0; } int Context::run() { return 0; }
DOCTEST_DEFINE_DEFAULTS(CurrentTestCaseStats);
DOCTEST_DEFINE_DEFAULTS(TestRunStats);
IReporter::~IReporter() = default; IReporter::~IReporter() = default;
int IReporter::get_num_active_contexts() { return 0; } int IReporter::get_num_active_contexts() { return 0; }
...@@ -3491,18 +3408,21 @@ namespace { ...@@ -3491,18 +3408,21 @@ namespace {
// the int (priority) is part of the key for automatic sorting - sadly one can register a // the int (priority) is part of the key for automatic sorting - sadly one can register a
// reporter with a duplicate name and a different priority but hopefully that won't happen often :| // reporter with a duplicate name and a different priority but hopefully that won't happen often :|
typedef std::map<std::pair<int, String>, reporterCreatorFunc> reporterMap; typedef std::map<std::pair<int, String>, reporterCreatorFunc> reporterMap;
reporterMap& getReporters() { reporterMap& getReporters() {
static reporterMap data; static reporterMap data;
return data; return data;
} }
reporterMap& getListeners() {
static reporterMap data;
return data;
}
} // namespace } // namespace
namespace detail { namespace detail {
#define DOCTEST_ITERATE_THROUGH_REPORTERS(function, ...) \ #define DOCTEST_ITERATE_THROUGH_REPORTERS(function, ...) \
for(auto& curr_rep : g_cs->reporters_currently_used) \ for(auto& curr_rep : g_cs->reporters_currently_used) \
curr_rep->function(__VA_ARGS__) curr_rep->function(__VA_ARGS__)
DOCTEST_DEFINE_DEFAULTS(TestFailureException);
DOCTEST_DEFINE_COPIES(TestFailureException);
bool checkIfShouldThrow(assertType::Enum at) { bool checkIfShouldThrow(assertType::Enum at) {
if(at & assertType::is_require) //!OCLINT bitwise operator in conditional if(at & assertType::is_require) //!OCLINT bitwise operator in conditional
return true; return true;
...@@ -3517,7 +3437,10 @@ namespace detail { ...@@ -3517,7 +3437,10 @@ namespace detail {
} }
#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
[[noreturn]] void throwException() { throw TestFailureException(); } [[noreturn]] void throwException() {
g_cs->shouldLogCurrentException = false;
throw TestFailureException();
} // NOLINT(cert-err60-cpp)
#else // DOCTEST_CONFIG_NO_EXCEPTIONS #else // DOCTEST_CONFIG_NO_EXCEPTIONS
void throwException() {} void throwException() {}
#endif // DOCTEST_CONFIG_NO_EXCEPTIONS #endif // DOCTEST_CONFIG_NO_EXCEPTIONS
...@@ -3586,15 +3509,11 @@ namespace { ...@@ -3586,15 +3509,11 @@ namespace {
namespace detail { namespace detail {
Subcase::Subcase(const char* name, const char* file, int line) Subcase::Subcase(const char* name, const char* file, int line)
: m_signature(name, file, line) { : m_signature({name, file, line}) {
ContextState* s = g_cs; ContextState* s = g_cs;
// if we have already completed it
if(s->subcasesPassed.count(m_signature) != 0)
return;
// check subcase filters // check subcase filters
if(s->subcasesCurrentLevel < s->subcase_filter_levels) { if(s->subcasesStack.size() < size_t(s->subcase_filter_levels)) {
if(!matchesAny(m_signature.m_name, s->filters[6], true, s->case_sensitive)) if(!matchesAny(m_signature.m_name, s->filters[6], true, s->case_sensitive))
return; return;
if(matchesAny(m_signature.m_name, s->filters[7], false, s->case_sensitive)) if(matchesAny(m_signature.m_name, s->filters[7], false, s->case_sensitive))
...@@ -3602,29 +3521,50 @@ namespace detail { ...@@ -3602,29 +3521,50 @@ namespace detail {
} }
// if a Subcase on the same level has already been entered // if a Subcase on the same level has already been entered
if(s->subcasesEnteredLevels.count(s->subcasesCurrentLevel) != 0) { if(s->subcasesStack.size() < size_t(s->subcasesCurrentMaxLevel)) {
s->should_reenter = true; s->should_reenter = true;
return; return;
} }
s->subcasesEnteredLevels.insert(s->subcasesCurrentLevel++); // push the current signature to the stack so we can check if the
// current stack + the current new subcase have been traversed
s->subcasesStack.push_back(m_signature);
if(s->subcasesPassed.count(s->subcasesStack) != 0) {
// pop - revert to previous stack since we've already passed this
s->subcasesStack.pop_back();
return;
}
s->subcasesCurrentMaxLevel = s->subcasesStack.size();
m_entered = true; m_entered = true;
DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_start, m_signature); DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_start, m_signature);
} }
DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4996) // std::uncaught_exception is deprecated in C++17
DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
Subcase::~Subcase() { Subcase::~Subcase() {
if(m_entered) { if(m_entered) {
ContextState* s = g_cs; // only mark the subcase stack as passed if no subcases have been skipped
if(g_cs->should_reenter == false)
s->subcasesCurrentLevel--; g_cs->subcasesPassed.insert(g_cs->subcasesStack);
// only mark the subcase as passed if no subcases have been skipped g_cs->subcasesStack.pop_back();
if(s->should_reenter == false)
s->subcasesPassed.insert(m_signature); if(std::uncaught_exception() && g_cs->shouldLogCurrentException) {
DOCTEST_ITERATE_THROUGH_REPORTERS(
test_case_exception, {"exception thrown in subcase - will translate later "
"when the whole test case has been exited (cannot "
"translate while there is an active exception)",
false});
g_cs->shouldLogCurrentException = false;
}
DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY); DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY);
} }
} }
DOCTEST_CLANG_SUPPRESS_WARNING_POP
DOCTEST_GCC_SUPPRESS_WARNING_POP
DOCTEST_MSVC_SUPPRESS_WARNING_POP
Subcase::operator bool() const { return m_entered; } Subcase::operator bool() const { return m_entered; }
...@@ -3632,17 +3572,9 @@ namespace detail { ...@@ -3632,17 +3572,9 @@ namespace detail {
: m_passed(passed) : m_passed(passed)
, m_decomp(decomposition) {} , m_decomp(decomposition) {}
DOCTEST_DEFINE_DEFAULTS(Result);
DOCTEST_DEFINE_COPIES(Result);
ExpressionDecomposer::ExpressionDecomposer(assertType::Enum at) ExpressionDecomposer::ExpressionDecomposer(assertType::Enum at)
: m_at(at) {} : m_at(at) {}
DOCTEST_DEFINE_DEFAULTS(ExpressionDecomposer);
DOCTEST_DEFINE_DEFAULTS(TestSuite);
DOCTEST_DEFINE_COPIES(TestSuite);
TestSuite& TestSuite::operator*(const char* in) { TestSuite& TestSuite::operator*(const char* in) {
m_test_suite = in; m_test_suite = in;
// clear state // clear state
...@@ -3659,7 +3591,7 @@ namespace detail { ...@@ -3659,7 +3591,7 @@ namespace detail {
const char* type, int template_id) { const char* type, int template_id) {
m_file = file; m_file = file;
m_line = line; m_line = line;
m_name = nullptr; m_name = nullptr; // will be later overridden in operator*
m_test_suite = test_suite.m_test_suite; m_test_suite = test_suite.m_test_suite;
m_description = test_suite.m_description; m_description = test_suite.m_description;
m_skip = test_suite.m_skip; m_skip = test_suite.m_skip;
...@@ -3673,8 +3605,6 @@ namespace detail { ...@@ -3673,8 +3605,6 @@ namespace detail {
m_template_id = template_id; m_template_id = template_id;
} }
DOCTEST_DEFINE_DEFAULTS(TestCase);
TestCase::TestCase(const TestCase& other) TestCase::TestCase(const TestCase& other)
: TestCaseData() { : TestCaseData() {
*this = other; *this = other;
...@@ -3885,6 +3815,9 @@ namespace detail { ...@@ -3885,6 +3815,9 @@ namespace detail {
return 0; return 0;
} }
#ifdef DOCTEST_IS_DEBUGGER_ACTIVE
bool isDebuggerActive() { return DOCTEST_IS_DEBUGGER_ACTIVE(); }
#else // DOCTEST_IS_DEBUGGER_ACTIVE
#ifdef DOCTEST_PLATFORM_MAC #ifdef DOCTEST_PLATFORM_MAC
// The following function is taken directly from the following technical note: // The following function is taken directly from the following technical note:
// http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
...@@ -3917,6 +3850,7 @@ namespace detail { ...@@ -3917,6 +3850,7 @@ namespace detail {
#else #else
bool isDebuggerActive() { return false; } bool isDebuggerActive() { return false; }
#endif // Platform #endif // Platform
#endif // DOCTEST_IS_DEBUGGER_ACTIVE
void registerExceptionTranslatorImpl(const IExceptionTranslator* et) { void registerExceptionTranslatorImpl(const IExceptionTranslator* et) {
if(std::find(getExceptionTranslators().begin(), getExceptionTranslators().end(), et) == if(std::find(getExceptionTranslators().begin(), getExceptionTranslators().end(), et) ==
...@@ -3947,64 +3881,17 @@ namespace detail { ...@@ -3947,64 +3881,17 @@ namespace detail {
DOCTEST_THREAD_LOCAL std::vector<IContextScope*> g_infoContexts; // for logging with INFO() DOCTEST_THREAD_LOCAL std::vector<IContextScope*> g_infoContexts; // for logging with INFO()
ContextBuilder::ICapture::ICapture() = default; ContextScopeBase::ContextScopeBase() {
ContextBuilder::ICapture::~ICapture() = default;
ContextBuilder::Chunk::Chunk() = default;
ContextBuilder::Chunk::~Chunk() = default;
ContextBuilder::Node::Node() = default;
ContextBuilder::Node::~Node() = default;
// steal the contents of the other - acting as a move constructor...
ContextBuilder::ContextBuilder(ContextBuilder& other)
: numCaptures(other.numCaptures)
, head(other.head)
, tail(other.tail) {
other.numCaptures = 0;
other.head = nullptr;
other.tail = nullptr;
memcpy(stackChunks, other.stackChunks,
unsigned(int(sizeof(Chunk)) * DOCTEST_CONFIG_NUM_CAPTURES_ON_STACK));
}
DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wcast-align")
void ContextBuilder::stringify(std::ostream* s) const {
int curr = 0;
// iterate over small buffer
while(curr < numCaptures && curr < DOCTEST_CONFIG_NUM_CAPTURES_ON_STACK)
reinterpret_cast<const ICapture*>(stackChunks[curr++].buf)->toStream(s);
// iterate over list
auto curr_elem = head;
while(curr < numCaptures) {
reinterpret_cast<const ICapture*>(curr_elem->chunk.buf)->toStream(s);
curr_elem = curr_elem->next;
++curr;
}
}
DOCTEST_GCC_SUPPRESS_WARNING_POP
ContextBuilder::ContextBuilder() = default;
ContextBuilder::~ContextBuilder() {
// free the linked list - the ones on the stack are left as-is
// no destructors are called at all - there is no need
while(head) {
auto next = head->next;
delete head;
head = next;
}
}
ContextScope::ContextScope(ContextBuilder& temp)
: contextBuilder(temp) {
g_infoContexts.push_back(this); g_infoContexts.push_back(this);
} }
DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4996) // std::uncaught_exception is deprecated in C++17 DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4996) // std::uncaught_exception is deprecated in C++17
DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
ContextScope::~ContextScope() { // destroy cannot be inlined into the destructor because that would mean calling stringify after
// ContextScope has been destroyed (base class destructors run after derived class destructors).
// Instead, ContextScope calls this method directly from its destructor.
void ContextScopeBase::destroy() {
if(std::uncaught_exception()) { if(std::uncaught_exception()) {
std::ostringstream s; std::ostringstream s;
this->stringify(&s); this->stringify(&s);
...@@ -4016,7 +3903,6 @@ namespace detail { ...@@ -4016,7 +3903,6 @@ namespace detail {
DOCTEST_GCC_SUPPRESS_WARNING_POP DOCTEST_GCC_SUPPRESS_WARNING_POP
DOCTEST_MSVC_SUPPRESS_WARNING_POP DOCTEST_MSVC_SUPPRESS_WARNING_POP
void ContextScope::stringify(std::ostream* s) const { contextBuilder.stringify(s); }
} // namespace detail } // namespace detail
namespace { namespace {
using namespace detail; using namespace detail;
...@@ -4184,7 +4070,7 @@ namespace { ...@@ -4184,7 +4070,7 @@ namespace {
#define DOCTEST_OUTPUT_DEBUG_STRING(text) ::OutputDebugStringA(text) #define DOCTEST_OUTPUT_DEBUG_STRING(text) ::OutputDebugStringA(text)
#else #else
// TODO: integration with XCode and other IDEs // TODO: integration with XCode and other IDEs
#define DOCTEST_OUTPUT_DEBUG_STRING(text) #define DOCTEST_OUTPUT_DEBUG_STRING(text) // NOLINT(clang-diagnostic-unused-macros)
#endif // Platform #endif // Platform
void addAssert(assertType::Enum at) { void addAssert(assertType::Enum at) {
...@@ -4203,8 +4089,10 @@ namespace { ...@@ -4203,8 +4089,10 @@ namespace {
DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_exception, {message.c_str(), true}); DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_exception, {message.c_str(), true});
while(g_cs->subcasesCurrentLevel--) while(g_cs->subcasesStack.size()) {
g_cs->subcasesStack.pop_back();
DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY); DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY);
}
g_cs->finalizeTestCaseData(); g_cs->finalizeTestCaseData();
...@@ -4217,7 +4105,7 @@ namespace { ...@@ -4217,7 +4105,7 @@ namespace {
namespace detail { namespace detail {
ResultBuilder::ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, ResultBuilder::ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr,
const char* exception_type) { const char* exception_type, const char* exception_string) {
m_test_case = g_cs->currentTest; m_test_case = g_cs->currentTest;
m_at = at; m_at = at;
m_file = file; m_file = file;
...@@ -4227,14 +4115,13 @@ namespace detail { ...@@ -4227,14 +4115,13 @@ namespace detail {
m_threw = false; m_threw = false;
m_threw_as = false; m_threw_as = false;
m_exception_type = exception_type; m_exception_type = exception_type;
m_exception_string = exception_string;
#if DOCTEST_MSVC #if DOCTEST_MSVC
if(m_expr[0] == ' ') // this happens when variadic macros are disabled under MSVC if(m_expr[0] == ' ') // this happens when variadic macros are disabled under MSVC
++m_expr; ++m_expr;
#endif // MSVC #endif // MSVC
} }
DOCTEST_DEFINE_DEFAULTS(ResultBuilder);
void ResultBuilder::setResult(const Result& res) { void ResultBuilder::setResult(const Result& res) {
m_decomp = res.m_decomp; m_decomp = res.m_decomp;
m_failed = !res.m_passed; m_failed = !res.m_passed;
...@@ -4248,10 +4135,12 @@ namespace detail { ...@@ -4248,10 +4135,12 @@ namespace detail {
bool ResultBuilder::log() { bool ResultBuilder::log() {
if(m_at & assertType::is_throws) { //!OCLINT bitwise operator in conditional if(m_at & assertType::is_throws) { //!OCLINT bitwise operator in conditional
m_failed = !m_threw; m_failed = !m_threw;
} else if((m_at & assertType::is_throws_as) && (m_at & assertType::is_throws_with)) { //!OCLINT
m_failed = !m_threw_as || (m_exception != m_exception_string);
} else if(m_at & assertType::is_throws_as) { //!OCLINT bitwise operator in conditional } else if(m_at & assertType::is_throws_as) { //!OCLINT bitwise operator in conditional
m_failed = !m_threw_as; m_failed = !m_threw_as;
} else if(m_at & assertType::is_throws_with) { //!OCLINT bitwise operator in conditional } else if(m_at & assertType::is_throws_with) { //!OCLINT bitwise operator in conditional
m_failed = m_exception != m_exception_type; m_failed = m_exception != m_exception_string;
} else if(m_at & assertType::is_nothrow) { //!OCLINT bitwise operator in conditional } else if(m_at & assertType::is_nothrow) { //!OCLINT bitwise operator in conditional
m_failed = m_threw; m_failed = m_threw;
} }
...@@ -4313,7 +4202,7 @@ namespace detail { ...@@ -4313,7 +4202,7 @@ namespace detail {
const bool isWarn = m_severity & assertType::is_warn; const bool isWarn = m_severity & assertType::is_warn;
// warn is just a message in this context so we dont treat it as an assert // warn is just a message in this context so we don't treat it as an assert
if(!isWarn) { if(!isWarn) {
addAssert(m_severity); addAssert(m_severity);
addFailedAssert(m_severity); addFailedAssert(m_severity);
...@@ -4796,6 +4685,10 @@ namespace { ...@@ -4796,6 +4685,10 @@ namespace {
void report_query(const QueryData& in) override { void report_query(const QueryData& in) override {
test_run_start(); test_run_start();
if(opt.list_reporters) { if(opt.list_reporters) {
for(auto& curr : getListeners())
xml.scopedElement("Listener")
.writeAttribute("priority", curr.first.first)
.writeAttribute("name", curr.first.second);
for(auto& curr : getReporters()) for(auto& curr : getReporters())
xml.scopedElement("Reporter") xml.scopedElement("Reporter")
.writeAttribute("priority", curr.first.first) .writeAttribute("priority", curr.first.first)
...@@ -4865,6 +4758,8 @@ namespace { ...@@ -4865,6 +4758,8 @@ namespace {
xml.ensureTagClosed(); xml.ensureTagClosed();
} }
void test_case_reenter(const TestCaseData&) override {}
void test_case_end(const CurrentTestCaseStats& st) override { void test_case_end(const CurrentTestCaseStats& st) override {
xml.startElement("OverallResultsAsserts") xml.startElement("OverallResultsAsserts")
.writeAttribute("successes", .writeAttribute("successes",
...@@ -4916,11 +4811,12 @@ namespace { ...@@ -4916,11 +4811,12 @@ namespace {
if(rb.m_threw) if(rb.m_threw)
xml.scopedElement("Exception").writeText(rb.m_exception.c_str()); xml.scopedElement("Exception").writeText(rb.m_exception.c_str());
if(rb.m_at & (assertType::is_throws_as | assertType::is_throws_with)) { if(rb.m_at & assertType::is_throws_as)
xml.scopedElement("ExpectedException").writeText(rb.m_exception_type); xml.scopedElement("ExpectedException").writeText(rb.m_exception_type);
} else if((rb.m_at & assertType::is_normal) && !rb.m_threw) { if(rb.m_at & assertType::is_throws_with)
xml.scopedElement("ExpectedExceptionString").writeText(rb.m_exception_string);
if((rb.m_at & assertType::is_normal) && !rb.m_threw)
xml.scopedElement("Expanded").writeText(rb.m_decomp.c_str()); xml.scopedElement("Expanded").writeText(rb.m_decomp.c_str());
}
log_contexts(); log_contexts();
...@@ -5177,11 +5073,17 @@ namespace { ...@@ -5177,11 +5073,17 @@ namespace {
void printRegisteredReporters() { void printRegisteredReporters() {
printVersion(); printVersion();
s << Color::Cyan << "[doctest] " << Color::None << "listing all registered reporters\n"; auto printReporters = [this] (const reporterMap& reporters, const char* type) {
for(auto& curr : getReporters()) if(reporters.size()) {
s << Color::Cyan << "[doctest] " << Color::None << "listing all registered " << type << "\n";
for(auto& curr : reporters)
s << "priority: " << std::setw(5) << curr.first.first s << "priority: " << std::setw(5) << curr.first.first
<< " name: " << curr.first.second << "\n"; << " name: " << curr.first.second << "\n";
} }
};
printReporters(getListeners(), "listeners");
printReporters(getReporters(), "reporters");
}
void list_query_results() { void list_query_results() {
separator_to_stream(); separator_to_stream();
...@@ -5279,6 +5181,8 @@ namespace { ...@@ -5279,6 +5181,8 @@ namespace {
tc = &in; tc = &in;
} }
void test_case_reenter(const TestCaseData&) override {}
void test_case_end(const CurrentTestCaseStats& st) override { void test_case_end(const CurrentTestCaseStats& st) override {
// log the preamble of the test case only if there is something // log the preamble of the test case only if there is something
// else to print - something other than that an assert has failed // else to print - something other than that an assert has failed
...@@ -5310,7 +5214,7 @@ namespace { ...@@ -5310,7 +5214,7 @@ namespace {
if(st.failure_flags & TestCaseFailureReason::TooManyFailedAsserts) { if(st.failure_flags & TestCaseFailureReason::TooManyFailedAsserts) {
s << Color::Red << "Aborting - too many failed asserts!\n"; s << Color::Red << "Aborting - too many failed asserts!\n";
} }
s << Color::None; s << Color::None; // lgtm [cpp/useless-expression]
} }
void test_case_exception(const TestCaseException& e) override { void test_case_exception(const TestCaseException& e) override {
...@@ -5326,9 +5230,9 @@ namespace { ...@@ -5326,9 +5230,9 @@ namespace {
if(num_stringified_contexts) { if(num_stringified_contexts) {
auto stringified_contexts = get_stringified_contexts(); auto stringified_contexts = get_stringified_contexts();
s << Color::None << " logged: "; s << Color::None << " logged: ";
for(int i = num_stringified_contexts - 1; i >= 0; --i) { for(int i = num_stringified_contexts; i > 0; --i) {
s << (i == num_stringified_contexts - 1 ? "" : " ") s << (i == num_stringified_contexts ? "" : " ")
<< stringified_contexts[i] << "\n"; << stringified_contexts[i - 1] << "\n";
} }
} }
s << "\n" << Color::None; s << "\n" << Color::None;
...@@ -5363,6 +5267,19 @@ namespace { ...@@ -5363,6 +5267,19 @@ namespace {
if(rb.m_at & assertType::is_throws) { //!OCLINT bitwise operator in conditional if(rb.m_at & assertType::is_throws) { //!OCLINT bitwise operator in conditional
s << (rb.m_threw ? "threw as expected!" : "did NOT throw at all!") << "\n"; s << (rb.m_threw ? "threw as expected!" : "did NOT throw at all!") << "\n";
} else if((rb.m_at & assertType::is_throws_as) &&
(rb.m_at & assertType::is_throws_with)) { //!OCLINT
s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \""
<< rb.m_exception_string << "\", " << rb.m_exception_type << " ) " << Color::None;
if(rb.m_threw) {
if(!rb.m_failed) {
s << "threw as expected!\n";
} else {
s << "threw a DIFFERENT exception! (contents: " << rb.m_exception << ")\n";
}
} else {
s << "did NOT throw at all!\n";
}
} else if(rb.m_at & } else if(rb.m_at &
assertType::is_throws_as) { //!OCLINT bitwise operator in conditional assertType::is_throws_as) { //!OCLINT bitwise operator in conditional
s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", " s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", "
...@@ -5374,7 +5291,7 @@ namespace { ...@@ -5374,7 +5291,7 @@ namespace {
} else if(rb.m_at & } else if(rb.m_at &
assertType::is_throws_with) { //!OCLINT bitwise operator in conditional assertType::is_throws_with) { //!OCLINT bitwise operator in conditional
s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \"" s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \""
<< rb.m_exception_type << "\" ) " << Color::None << rb.m_exception_string << "\" ) " << Color::None
<< (rb.m_threw ? (!rb.m_failed ? "threw as expected!" : << (rb.m_threw ? (!rb.m_failed ? "threw as expected!" :
"threw a DIFFERENT exception: ") : "threw a DIFFERENT exception: ") :
"did NOT throw at all!") "did NOT throw at all!")
...@@ -5433,6 +5350,7 @@ namespace { ...@@ -5433,6 +5350,7 @@ namespace {
DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_run_start, DOCTEST_EMPTY, DOCTEST_EMPTY) DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_run_start, DOCTEST_EMPTY, DOCTEST_EMPTY)
DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_run_end, const TestRunStats&, in) DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_run_end, const TestRunStats&, in)
DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_start, const TestCaseData&, in) DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_start, const TestCaseData&, in)
DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_reenter, const TestCaseData&, in)
DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_end, const CurrentTestCaseStats&, in) DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_end, const CurrentTestCaseStats&, in)
DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_exception, const TestCaseException&, in) DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_exception, const TestCaseException&, in)
DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(subcase_start, const SubcaseSignature&, in) DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(subcase_start, const SubcaseSignature&, in)
...@@ -5445,55 +5363,33 @@ namespace { ...@@ -5445,55 +5363,33 @@ namespace {
DOCTEST_THREAD_LOCAL std::ostringstream DebugOutputWindowReporter::oss; DOCTEST_THREAD_LOCAL std::ostringstream DebugOutputWindowReporter::oss;
#endif // DOCTEST_PLATFORM_WINDOWS #endif // DOCTEST_PLATFORM_WINDOWS
// the implementation of parseFlag()
bool parseFlagImpl(int argc, const char* const* argv, const char* pattern) {
for(int i = argc - 1; i >= 0; --i) {
auto temp = std::strstr(argv[i], pattern);
if(temp && strlen(temp) == strlen(pattern)) {
// eliminate strings in which the chars before the option are not '-'
bool noBadCharsFound = true; //!OCLINT prefer early exits and continue
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
// offset (normally 3 for "dt-") to skip prefix
if(parseFlagImpl(argc, argv, pattern + strlen(DOCTEST_CONFIG_OPTIONS_PREFIX)))
return true;
#endif // DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
return parseFlagImpl(argc, argv, pattern);
}
// the implementation of parseOption() // the implementation of parseOption()
bool parseOptionImpl(int argc, const char* const* argv, const char* pattern, String& res) { bool parseOptionImpl(int argc, const char* const* argv, const char* pattern, String* value) {
for(int i = argc - 1; i >= 0; --i) { // going from the end to the beginning and stopping on the first occurrence from the end
auto temp = std::strstr(argv[i], pattern); for(int i = argc; i > 0; --i) {
if(temp) { //!OCLINT prefer early exits and continue auto index = i - 1;
auto temp = std::strstr(argv[index], pattern);
if(temp && (value || strlen(temp) == strlen(pattern))) { //!OCLINT prefer early exits and continue
// eliminate matches in which the chars before the option are not '-' // eliminate matches in which the chars before the option are not '-'
bool noBadCharsFound = true; bool noBadCharsFound = true;
auto curr = argv[i]; auto curr = argv[index];
while(curr != temp) { while(curr != temp) {
if(*curr++ != '-') { if(*curr++ != '-') {
noBadCharsFound = false; noBadCharsFound = false;
break; break;
} }
} }
if(noBadCharsFound && argv[i][0] == '-') { if(noBadCharsFound && argv[index][0] == '-') {
if(value) {
// parsing the value of an option
temp += strlen(pattern); temp += strlen(pattern);
const unsigned len = strlen(temp); const unsigned len = strlen(temp);
if(len) { if(len) {
res = temp; *value = temp;
return true;
}
} else {
// just a flag - no value
return true; return true;
} }
} }
...@@ -5503,22 +5399,28 @@ namespace { ...@@ -5503,22 +5399,28 @@ namespace {
} }
// parses an option and returns the string after the '=' character // parses an option and returns the string after the '=' character
bool parseOption(int argc, const char* const* argv, const char* pattern, String& res, bool parseOption(int argc, const char* const* argv, const char* pattern, String* value = nullptr,
const String& defaultVal = String()) { const String& defaultVal = String()) {
res = defaultVal; if(value)
*value = defaultVal;
#ifndef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS #ifndef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
// offset (normally 3 for "dt-") to skip prefix // offset (normally 3 for "dt-") to skip prefix
if(parseOptionImpl(argc, argv, pattern + strlen(DOCTEST_CONFIG_OPTIONS_PREFIX), res)) if(parseOptionImpl(argc, argv, pattern + strlen(DOCTEST_CONFIG_OPTIONS_PREFIX), value))
return true; return true;
#endif // DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS #endif // DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
return parseOptionImpl(argc, argv, pattern, res); return parseOptionImpl(argc, argv, pattern, value);
}
// locates a flag on the command line
bool parseFlag(int argc, const char* const* argv, const char* pattern) {
return parseOption(argc, argv, pattern);
} }
// parses a comma separated list of words after a pattern in one of the arguments in argv // 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, bool parseCommaSepArgs(int argc, const char* const* argv, const char* pattern,
std::vector<String>& res) { std::vector<String>& res) {
String filtersString; String filtersString;
if(parseOption(argc, argv, pattern, filtersString)) { if(parseOption(argc, argv, pattern, &filtersString)) {
// tokenize with "," as a separator // tokenize with "," as a separator
// cppcheck-suppress strtokCalled // cppcheck-suppress strtokCalled
DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
...@@ -5546,7 +5448,7 @@ namespace { ...@@ -5546,7 +5448,7 @@ namespace {
bool parseIntOption(int argc, const char* const* argv, const char* pattern, optionType type, bool parseIntOption(int argc, const char* const* argv, const char* pattern, optionType type,
int& res) { int& res) {
String parsedValue; String parsedValue;
if(!parseOption(argc, argv, pattern, parsedValue)) if(!parseOption(argc, argv, pattern, &parsedValue))
return false; return false;
if(type == 0) { if(type == 0) {
...@@ -5643,8 +5545,8 @@ void Context::parseArgs(int argc, const char* const* argv, bool withDefaults) { ...@@ -5643,8 +5545,8 @@ void Context::parseArgs(int argc, const char* const* argv, bool withDefaults) {
p->var = default p->var = default
#define DOCTEST_PARSE_STR_OPTION(name, sname, var, default) \ #define DOCTEST_PARSE_STR_OPTION(name, sname, var, default) \
if(parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", strRes, default) || \ if(parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", &strRes, default) || \
parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", strRes, default) || \ parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", &strRes, default) || \
withDefaults) \ withDefaults) \
p->var = strRes p->var = strRes
...@@ -5788,8 +5690,6 @@ int Context::run() { ...@@ -5788,8 +5690,6 @@ int Context::run() {
return EXIT_SUCCESS; return EXIT_SUCCESS;
}; };
DOCTEST_REGISTER_REPORTER("console", 0, ConsoleReporter);
// setup default reporter if none is given through the command line // setup default reporter if none is given through the command line
if(p->filters[8].empty()) if(p->filters[8].empty())
p->filters[8].push_back("console"); p->filters[8].push_back("console");
...@@ -5800,6 +5700,12 @@ int Context::run() { ...@@ -5800,6 +5700,12 @@ int Context::run() {
p->reporters_currently_used.push_back(curr.second(*g_cs)); p->reporters_currently_used.push_back(curr.second(*g_cs));
} }
// TODO: check if there is nothing in reporters_currently_used
// prepend all listeners
for(auto& curr : getListeners())
p->reporters_currently_used.insert(p->reporters_currently_used.begin(), curr.second(*g_cs));
#ifdef DOCTEST_PLATFORM_WINDOWS #ifdef DOCTEST_PLATFORM_WINDOWS
if(isDebuggerActive()) if(isDebuggerActive())
p->reporters_currently_used.push_back(new DebugOutputWindowReporter(*g_cs)); p->reporters_currently_used.push_back(new DebugOutputWindowReporter(*g_cs));
...@@ -5921,11 +5827,15 @@ int Context::run() { ...@@ -5921,11 +5827,15 @@ int Context::run() {
p->timer.start(); p->timer.start();
bool run_test = true;
do { do {
// reset some of the fields for subcases (except for the set of fully passed ones) // reset some of the fields for subcases (except for the set of fully passed ones)
p->should_reenter = false; p->should_reenter = false;
p->subcasesCurrentLevel = 0; p->subcasesCurrentMaxLevel = 0;
p->subcasesEnteredLevels.clear(); p->subcasesStack.clear();
p->shouldLogCurrentException = true;
// reset stuff for logging with INFO() // reset stuff for logging with INFO()
p->stringifiedContexts.clear(); p->stringifiedContexts.clear();
...@@ -5950,10 +5860,15 @@ int Context::run() { ...@@ -5950,10 +5860,15 @@ int Context::run() {
// exit this loop if enough assertions have failed - even if there are more subcases // exit this loop if enough assertions have failed - even if there are more subcases
if(p->abort_after > 0 && if(p->abort_after > 0 &&
p->numAssertsFailed + p->numAssertsFailedCurrentTest_atomic >= p->abort_after) { p->numAssertsFailed + p->numAssertsFailedCurrentTest_atomic >= p->abort_after) {
p->should_reenter = false; run_test = false;
p->failure_flags |= TestCaseFailureReason::TooManyFailedAsserts; p->failure_flags |= TestCaseFailureReason::TooManyFailedAsserts;
} }
} while(p->should_reenter == true);
if(p->should_reenter && run_test)
DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_reenter, tc);
if(!p->should_reenter)
run_test = false;
} while(run_test);
p->finalizeTestCaseData(); p->finalizeTestCaseData();
...@@ -5977,13 +5892,16 @@ int Context::run() { ...@@ -5977,13 +5892,16 @@ int Context::run() {
DOCTEST_ITERATE_THROUGH_REPORTERS(report_query, qdata); DOCTEST_ITERATE_THROUGH_REPORTERS(report_query, qdata);
} }
// see these issues on the reasoning for this:
// - https://github.com/onqtam/doctest/issues/143#issuecomment-414418903
// - https://github.com/onqtam/doctest/issues/126
auto DOCTEST_FIX_FOR_MACOS_LIBCPP_IOSFWD_STRING_LINK_ERRORS = []() DOCTEST_NOINLINE
{ std::cout << std::string(); };
DOCTEST_FIX_FOR_MACOS_LIBCPP_IOSFWD_STRING_LINK_ERRORS();
return cleanup_and_return(); return cleanup_and_return();
} }
DOCTEST_DEFINE_DEFAULTS(CurrentTestCaseStats);
DOCTEST_DEFINE_DEFAULTS(TestRunStats);
IReporter::~IReporter() = default; IReporter::~IReporter() = default;
int IReporter::get_num_active_contexts() { return detail::g_infoContexts.size(); } int IReporter::get_num_active_contexts() { return detail::g_infoContexts.size(); }
...@@ -5997,16 +5915,14 @@ const String* IReporter::get_stringified_contexts() { ...@@ -5997,16 +5915,14 @@ const String* IReporter::get_stringified_contexts() {
} }
namespace detail { namespace detail {
void registerReporterImpl(const char* name, int priority, reporterCreatorFunc c) { void registerReporterImpl(const char* name, int priority, reporterCreatorFunc c, bool isReporter) {
if(isReporter)
getReporters().insert(reporterMap::value_type(reporterMap::key_type(priority, name), c)); getReporters().insert(reporterMap::value_type(reporterMap::key_type(priority, name), c));
else
getListeners().insert(reporterMap::value_type(reporterMap::key_type(priority, name), c));
} }
} // namespace detail } // namespace detail
// see these issues on the reasoning for this:
// - https://github.com/onqtam/doctest/issues/143#issuecomment-414418903
// - https://github.com/onqtam/doctest/issues/126
void DOCTEST_FIX_FOR_MACOS_LIBCPP_IOSFWD_STRING_LINK_ERRORS() { std::cout << std::string(); }
} // namespace doctest } // namespace doctest
#endif // DOCTEST_CONFIG_DISABLE #endif // DOCTEST_CONFIG_DISABLE
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment