|
|
|
|
|
|
|
|
/* |
|
|
/* |
|
|
* Catch v2.1.2 |
|
|
|
|
|
* Generated: 2018-02-09 17:05:21.506253 |
|
|
|
|
|
|
|
|
* Catch v2.2.1 |
|
|
|
|
|
* Generated: 2018-03-11 12:01:31.654719 |
|
|
* ---------------------------------------------------------- |
|
|
* ---------------------------------------------------------- |
|
|
* This file has been merged from multiple headers. Please don't edit it directly |
|
|
* This file has been merged from multiple headers. Please don't edit it directly |
|
|
* Copyright (c) 2018 Two Blue Cubes Ltd. All rights reserved. |
|
|
* Copyright (c) 2018 Two Blue Cubes Ltd. All rights reserved. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define CATCH_VERSION_MAJOR 2 |
|
|
#define CATCH_VERSION_MAJOR 2 |
|
|
#define CATCH_VERSION_MINOR 1 |
|
|
|
|
|
#define CATCH_VERSION_PATCH 2 |
|
|
|
|
|
|
|
|
#define CATCH_VERSION_MINOR 2 |
|
|
|
|
|
#define CATCH_VERSION_PATCH 1 |
|
|
|
|
|
|
|
|
#ifdef __clang__ |
|
|
#ifdef __clang__ |
|
|
# pragma clang system_header |
|
|
# pragma clang system_header |
|
|
|
|
|
|
|
|
#endif // __clang__ |
|
|
#endif // __clang__ |
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////// |
|
|
//////////////////////////////////////////////////////////////////////////////// |
|
|
// We know some environments not to support full POSIX signals |
|
|
|
|
|
#if defined(__CYGWIN__) || defined(__QNX__) |
|
|
|
|
|
|
|
|
|
|
|
# if !defined(CATCH_CONFIG_POSIX_SIGNALS) |
|
|
|
|
|
# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS |
|
|
|
|
|
# endif |
|
|
|
|
|
|
|
|
// Assume that non-Windows platforms support posix signals by default |
|
|
|
|
|
#if !defined(CATCH_PLATFORM_WINDOWS) |
|
|
|
|
|
#define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////// |
|
|
|
|
|
// We know some environments not to support full POSIX signals |
|
|
|
|
|
#if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__) |
|
|
|
|
|
#define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
#ifdef __OS400__ |
|
|
#ifdef __OS400__ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////// |
|
|
//////////////////////////////////////////////////////////////////////////////// |
|
|
|
|
|
|
|
|
|
|
|
// DJGPP |
|
|
|
|
|
#ifdef __DJGPP__ |
|
|
|
|
|
# define CATCH_INTERNAL_CONFIG_NO_WCHAR |
|
|
|
|
|
#endif // __DJGPP__ |
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////// |
|
|
|
|
|
|
|
|
// Use of __COUNTER__ is suppressed during code analysis in |
|
|
// Use of __COUNTER__ is suppressed during code analysis in |
|
|
// CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly |
|
|
// CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly |
|
|
// handled by it. |
|
|
// handled by it. |
|
|
|
|
|
|
|
|
# define CATCH_CONFIG_WINDOWS_SEH |
|
|
# define CATCH_CONFIG_WINDOWS_SEH |
|
|
#endif |
|
|
#endif |
|
|
// This is set by default, because we assume that unix compilers are posix-signal-compatible by default. |
|
|
// This is set by default, because we assume that unix compilers are posix-signal-compatible by default. |
|
|
#if !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS) |
|
|
|
|
|
|
|
|
#if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS) && !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS) |
|
|
# define CATCH_CONFIG_POSIX_SIGNALS |
|
|
# define CATCH_CONFIG_POSIX_SIGNALS |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
// This is set by default, because we assume that compilers with no wchar_t support are just rare exceptions. |
|
|
|
|
|
#if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR) |
|
|
|
|
|
# define CATCH_CONFIG_WCHAR |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_INTERNAL_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) |
|
|
|
|
|
|
|
|
#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) |
|
|
# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS |
|
|
# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public: // substrings and searches |
|
|
public: // substrings and searches |
|
|
auto substr( size_type start, size_type size ) const noexcept -> StringRef; |
|
|
auto substr( size_type start, size_type size ) const noexcept -> StringRef; |
|
|
|
|
|
|
|
|
|
|
|
// Returns the current start pointer. |
|
|
|
|
|
// Note that the pointer can change when if the StringRef is a substring |
|
|
|
|
|
auto currentData() const noexcept -> char const*; |
|
|
|
|
|
|
|
|
private: // ownership queries - may not be consistent between calls |
|
|
private: // ownership queries - may not be consistent between calls |
|
|
auto isOwned() const noexcept -> bool; |
|
|
auto isOwned() const noexcept -> bool; |
|
|
auto isSubstring() const noexcept -> bool; |
|
|
auto isSubstring() const noexcept -> bool; |
|
|
auto data() const noexcept -> char const*; |
|
|
|
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string; |
|
|
auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string; |
|
|
auto operator + ( StringRef const& lhs, char const* rhs ) -> std::string; |
|
|
auto operator + ( StringRef const& lhs, char const* rhs ) -> std::string; |
|
|
auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string; |
|
|
auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string; |
|
|
|
|
|
|
|
|
|
|
|
auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&; |
|
|
auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&; |
|
|
auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&; |
|
|
|
|
|
|
|
|
inline auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef { |
|
|
inline auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef { |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
struct NameAndTags { |
|
|
struct NameAndTags { |
|
|
NameAndTags( StringRef name_ = StringRef(), StringRef tags_ = StringRef() ) noexcept; |
|
|
|
|
|
|
|
|
NameAndTags( StringRef const& name_ = StringRef(), StringRef const& tags_ = StringRef() ) noexcept; |
|
|
StringRef name; |
|
|
StringRef name; |
|
|
StringRef tags; |
|
|
StringRef tags; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
struct AutoReg : NonCopyable { |
|
|
struct AutoReg : NonCopyable { |
|
|
AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) noexcept; |
|
|
|
|
|
|
|
|
AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept; |
|
|
~AutoReg(); |
|
|
~AutoReg(); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::string convertUnknownEnumToString( E e ); |
|
|
std::string convertUnknownEnumToString( E e ); |
|
|
|
|
|
|
|
|
template<typename T> |
|
|
template<typename T> |
|
|
typename std::enable_if<!std::is_enum<T>::value, std::string>::type convertUnstreamable( T const& ) { |
|
|
|
|
|
|
|
|
typename std::enable_if<!std::is_enum<T>::value, std::string>::type convertUnstreamable( T const& value ) { |
|
|
|
|
|
#if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER) |
|
|
|
|
|
(void)value; |
|
|
return Detail::unprintableString; |
|
|
return Detail::unprintableString; |
|
|
|
|
|
#else |
|
|
|
|
|
return CATCH_CONFIG_FALLBACK_STRINGIFIER(value); |
|
|
|
|
|
#endif |
|
|
} |
|
|
} |
|
|
template<typename T> |
|
|
template<typename T> |
|
|
typename std::enable_if<std::is_enum<T>::value, std::string>::type convertUnstreamable( T const& value ) { |
|
|
typename std::enable_if<std::is_enum<T>::value, std::string>::type convertUnstreamable( T const& value ) { |
|
|
|
|
|
|
|
|
struct StringMaker<std::string> { |
|
|
struct StringMaker<std::string> { |
|
|
static std::string convert(const std::string& str); |
|
|
static std::string convert(const std::string& str); |
|
|
}; |
|
|
}; |
|
|
|
|
|
#ifdef CATCH_CONFIG_WCHAR |
|
|
template<> |
|
|
template<> |
|
|
struct StringMaker<std::wstring> { |
|
|
struct StringMaker<std::wstring> { |
|
|
static std::string convert(const std::wstring& wstr); |
|
|
static std::string convert(const std::wstring& wstr); |
|
|
}; |
|
|
}; |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
template<> |
|
|
template<> |
|
|
struct StringMaker<char const *> { |
|
|
struct StringMaker<char const *> { |
|
|
|
|
|
|
|
|
struct StringMaker<char *> { |
|
|
struct StringMaker<char *> { |
|
|
static std::string convert(char * str); |
|
|
static std::string convert(char * str); |
|
|
}; |
|
|
}; |
|
|
|
|
|
#ifdef CATCH_CONFIG_WCHAR |
|
|
template<> |
|
|
template<> |
|
|
struct StringMaker<wchar_t const *> { |
|
|
struct StringMaker<wchar_t const *> { |
|
|
static std::string convert(wchar_t const * str); |
|
|
static std::string convert(wchar_t const * str); |
|
|
|
|
|
|
|
|
struct StringMaker<wchar_t *> { |
|
|
struct StringMaker<wchar_t *> { |
|
|
static std::string convert(wchar_t * str); |
|
|
static std::string convert(wchar_t * str); |
|
|
}; |
|
|
}; |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
template<int SZ> |
|
|
template<int SZ> |
|
|
struct StringMaker<char[SZ]> { |
|
|
struct StringMaker<char[SZ]> { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Totals delta( Totals const& prevTotals ) const; |
|
|
Totals delta( Totals const& prevTotals ) const; |
|
|
|
|
|
|
|
|
|
|
|
int error = 0; |
|
|
Counts assertions; |
|
|
Counts assertions; |
|
|
Counts testCases; |
|
|
Counts testCases; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
class TestCase : public TestCaseInfo { |
|
|
class TestCase : public TestCaseInfo { |
|
|
public: |
|
|
public: |
|
|
|
|
|
|
|
|
TestCase( ITestInvoker* testCase, TestCaseInfo const& info ); |
|
|
|
|
|
|
|
|
TestCase( ITestInvoker* testCase, TestCaseInfo&& info ); |
|
|
|
|
|
|
|
|
TestCase withName( std::string const& _newName ) const; |
|
|
TestCase withName( std::string const& _newName ) const; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TestCase makeTestCase( ITestInvoker* testCase, |
|
|
TestCase makeTestCase( ITestInvoker* testCase, |
|
|
std::string const& className, |
|
|
std::string const& className, |
|
|
std::string const& name, |
|
|
|
|
|
std::string const& description, |
|
|
|
|
|
|
|
|
NameAndTags const& nameAndTags, |
|
|
SourceLineInfo const& lineInfo ); |
|
|
SourceLineInfo const& lineInfo ); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct WarnAbout { enum What { |
|
|
struct WarnAbout { enum What { |
|
|
Nothing = 0x00, |
|
|
Nothing = 0x00, |
|
|
NoAssertions = 0x01 |
|
|
|
|
|
|
|
|
NoAssertions = 0x01, |
|
|
|
|
|
NoTests = 0x02 |
|
|
}; }; |
|
|
}; }; |
|
|
|
|
|
|
|
|
struct ShowDurations { enum OrNot { |
|
|
struct ShowDurations { enum OrNot { |
|
|
|
|
|
|
|
|
virtual bool includeSuccessfulResults() const = 0; |
|
|
virtual bool includeSuccessfulResults() const = 0; |
|
|
virtual bool shouldDebugBreak() const = 0; |
|
|
virtual bool shouldDebugBreak() const = 0; |
|
|
virtual bool warnAboutMissingAssertions() const = 0; |
|
|
virtual bool warnAboutMissingAssertions() const = 0; |
|
|
|
|
|
virtual bool warnAboutNoTests() const = 0; |
|
|
virtual int abortAfter() const = 0; |
|
|
virtual int abortAfter() const = 0; |
|
|
virtual bool showInvisibles() const = 0; |
|
|
virtual bool showInvisibles() const = 0; |
|
|
virtual ShowDurations::OrNot showDurations() const = 0; |
|
|
virtual ShowDurations::OrNot showDurations() const = 0; |
|
|
virtual TestSpec const& testSpec() const = 0; |
|
|
virtual TestSpec const& testSpec() const = 0; |
|
|
|
|
|
virtual bool hasTestFilters() const = 0; |
|
|
virtual RunTests::InWhatOrder runOrder() const = 0; |
|
|
virtual RunTests::InWhatOrder runOrder() const = 0; |
|
|
virtual unsigned int rngSeed() const = 0; |
|
|
virtual unsigned int rngSeed() const = 0; |
|
|
virtual int benchmarkResolutionMultiple() const = 0; |
|
|
virtual int benchmarkResolutionMultiple() const = 0; |
|
|
|
|
|
|
|
|
std::string getProcessName() const; |
|
|
std::string getProcessName() const; |
|
|
|
|
|
|
|
|
std::vector<std::string> const& getReporterNames() const; |
|
|
std::vector<std::string> const& getReporterNames() const; |
|
|
|
|
|
std::vector<std::string> const& getTestsOrTags() const; |
|
|
std::vector<std::string> const& getSectionsToRun() const override; |
|
|
std::vector<std::string> const& getSectionsToRun() const override; |
|
|
|
|
|
|
|
|
virtual TestSpec const& testSpec() const override; |
|
|
virtual TestSpec const& testSpec() const override; |
|
|
|
|
|
bool hasTestFilters() const override; |
|
|
|
|
|
|
|
|
bool showHelp() const; |
|
|
bool showHelp() const; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::string name() const override; |
|
|
std::string name() const override; |
|
|
bool includeSuccessfulResults() const override; |
|
|
bool includeSuccessfulResults() const override; |
|
|
bool warnAboutMissingAssertions() const override; |
|
|
bool warnAboutMissingAssertions() const override; |
|
|
|
|
|
bool warnAboutNoTests() const override; |
|
|
ShowDurations::OrNot showDurations() const override; |
|
|
ShowDurations::OrNot showDurations() const override; |
|
|
RunTests::InWhatOrder runOrder() const override; |
|
|
RunTests::InWhatOrder runOrder() const override; |
|
|
unsigned int rngSeed() const override; |
|
|
unsigned int rngSeed() const override; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::unique_ptr<IStream const> m_stream; |
|
|
std::unique_ptr<IStream const> m_stream; |
|
|
TestSpec m_testSpec; |
|
|
TestSpec m_testSpec; |
|
|
|
|
|
bool m_hasTestFilters = false; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
} // end namespace Catch |
|
|
} // end namespace Catch |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// start catch_fatal_condition.h |
|
|
// start catch_fatal_condition.h |
|
|
|
|
|
|
|
|
#include <string> |
|
|
|
|
|
|
|
|
|
|
|
#if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// |
|
|
|
|
|
// start catch_windows_h_proxy.h |
|
|
// start catch_windows_h_proxy.h |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif // defined(CATCH_PLATFORM_WINDOWS) |
|
|
#endif // defined(CATCH_PLATFORM_WINDOWS) |
|
|
|
|
|
|
|
|
// end catch_windows_h_proxy.h |
|
|
// end catch_windows_h_proxy.h |
|
|
|
|
|
|
|
|
# if !defined ( CATCH_CONFIG_WINDOWS_SEH ) |
|
|
|
|
|
|
|
|
|
|
|
namespace Catch { |
|
|
|
|
|
struct FatalConditionHandler { |
|
|
|
|
|
void reset(); |
|
|
|
|
|
}; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
# else // CATCH_CONFIG_WINDOWS_SEH is defined |
|
|
|
|
|
|
|
|
#if defined( CATCH_CONFIG_WINDOWS_SEH ) |
|
|
|
|
|
|
|
|
namespace Catch { |
|
|
namespace Catch { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace Catch |
|
|
} // namespace Catch |
|
|
|
|
|
|
|
|
# endif // CATCH_CONFIG_WINDOWS_SEH |
|
|
|
|
|
|
|
|
|
|
|
#else // Not Windows - assumed to be POSIX compatible ////////////////////////// |
|
|
|
|
|
|
|
|
|
|
|
# if !defined(CATCH_CONFIG_POSIX_SIGNALS) |
|
|
|
|
|
|
|
|
|
|
|
namespace Catch { |
|
|
|
|
|
struct FatalConditionHandler { |
|
|
|
|
|
void reset(); |
|
|
|
|
|
}; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
# else // CATCH_CONFIG_POSIX_SIGNALS is defined |
|
|
|
|
|
|
|
|
#elif defined ( CATCH_CONFIG_POSIX_SIGNALS ) |
|
|
|
|
|
|
|
|
#include <signal.h> |
|
|
#include <signal.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct FatalConditionHandler { |
|
|
struct FatalConditionHandler { |
|
|
|
|
|
|
|
|
static bool isSet; |
|
|
static bool isSet; |
|
|
static struct sigaction oldSigActions[];// [sizeof(signalDefs) / sizeof(SignalDefs)]; |
|
|
|
|
|
|
|
|
static struct sigaction oldSigActions[]; |
|
|
static stack_t oldSigStack; |
|
|
static stack_t oldSigStack; |
|
|
static char altStackMem[]; |
|
|
static char altStackMem[]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace Catch |
|
|
} // namespace Catch |
|
|
|
|
|
|
|
|
# endif // CATCH_CONFIG_POSIX_SIGNALS |
|
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
|
|
|
|
namespace Catch { |
|
|
|
|
|
struct FatalConditionHandler { |
|
|
|
|
|
void reset(); |
|
|
|
|
|
}; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
#endif // not Windows |
|
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
// end catch_fatal_condition.h |
|
|
// end catch_fatal_condition.h |
|
|
#include <string> |
|
|
#include <string> |
|
|
|
|
|
|
|
|
expr = m_info.capturedExpression; |
|
|
expr = m_info.capturedExpression; |
|
|
else { |
|
|
else { |
|
|
expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 ); |
|
|
expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 ); |
|
|
expr += m_info.macroName.c_str(); |
|
|
|
|
|
|
|
|
expr += m_info.macroName; |
|
|
expr += "( "; |
|
|
expr += "( "; |
|
|
expr += m_info.capturedExpression.c_str(); |
|
|
|
|
|
|
|
|
expr += m_info.capturedExpression; |
|
|
expr += " )"; |
|
|
expr += " )"; |
|
|
} |
|
|
} |
|
|
return expr; |
|
|
return expr; |
|
|
|
|
|
|
|
|
using StringMatcher = Matchers::Impl::MatcherBase<std::string>; |
|
|
using StringMatcher = Matchers::Impl::MatcherBase<std::string>; |
|
|
|
|
|
|
|
|
// This is the general overload that takes a any string matcher |
|
|
// This is the general overload that takes a any string matcher |
|
|
// There is another overload, in catch_assertinhandler.h/.cpp, that only takes a string and infers |
|
|
|
|
|
|
|
|
// There is another overload, in catch_assertionhandler.h/.cpp, that only takes a string and infers |
|
|
// the Equals matcher (so the header does not mention matchers) |
|
|
// the Equals matcher (so the header does not mention matchers) |
|
|
void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString ) { |
|
|
void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString ) { |
|
|
std::string exceptionMessage = Catch::translateActiveException(); |
|
|
std::string exceptionMessage = Catch::translateActiveException(); |
|
|
|
|
|
|
|
|
// |
|
|
// |
|
|
// See https://github.com/philsquared/Clara for more details |
|
|
// See https://github.com/philsquared/Clara for more details |
|
|
|
|
|
|
|
|
// Clara v1.1.2 |
|
|
|
|
|
|
|
|
// Clara v1.1.4 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef CATCH_CLARA_CONFIG_CONSOLE_WIDTH |
|
|
#ifndef CATCH_CLARA_CONFIG_CONSOLE_WIDTH |
|
|
|
|
|
|
|
|
#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CLARA_CONFIG_CONSOLE_WIDTH |
|
|
#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CLARA_CONFIG_CONSOLE_WIDTH |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#ifndef CLARA_CONFIG_OPTIONAL_TYPE |
|
|
|
|
|
#ifdef __has_include |
|
|
|
|
|
#if __has_include(<optional>) && __cplusplus >= 201703L |
|
|
|
|
|
#include <optional> |
|
|
|
|
|
#define CLARA_CONFIG_OPTIONAL_TYPE std::optional |
|
|
|
|
|
#endif |
|
|
|
|
|
#endif |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
// ----------- #included from clara_textflow.hpp ----------- |
|
|
// ----------- #included from clara_textflow.hpp ----------- |
|
|
|
|
|
|
|
|
// TextFlowCpp |
|
|
// TextFlowCpp |
|
|
|
|
|
|
|
|
std::vector<std::string> m_args; |
|
|
std::vector<std::string> m_args; |
|
|
|
|
|
|
|
|
public: |
|
|
public: |
|
|
Args( int argc, char *argv[] ) { |
|
|
|
|
|
m_exeName = argv[0]; |
|
|
|
|
|
for( int i = 1; i < argc; ++i ) |
|
|
|
|
|
m_args.push_back( argv[i] ); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
Args( int argc, char const* const* argv ) |
|
|
|
|
|
: m_exeName(argv[0]), |
|
|
|
|
|
m_args(argv + 1, argv + argc) {} |
|
|
|
|
|
|
|
|
Args( std::initializer_list<std::string> args ) |
|
|
Args( std::initializer_list<std::string> args ) |
|
|
: m_exeName( *args.begin() ), |
|
|
: m_exeName( *args.begin() ), |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected: |
|
|
protected: |
|
|
void enforceOk() const override { |
|
|
void enforceOk() const override { |
|
|
// !TBD: If no exceptions, std::terminate here or something |
|
|
|
|
|
switch( m_type ) { |
|
|
|
|
|
case ResultBase::LogicError: |
|
|
|
|
|
throw std::logic_error( m_errorMessage ); |
|
|
|
|
|
case ResultBase::RuntimeError: |
|
|
|
|
|
throw std::runtime_error( m_errorMessage ); |
|
|
|
|
|
case ResultBase::Ok: |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Errors shouldn't reach this point, but if they do |
|
|
|
|
|
// the actual error message will be in m_errorMessage |
|
|
|
|
|
assert( m_type != ResultBase::LogicError ); |
|
|
|
|
|
assert( m_type != ResultBase::RuntimeError ); |
|
|
|
|
|
if( m_type != ResultBase::Ok ) |
|
|
|
|
|
std::abort(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
std::string m_errorMessage; // Only populated if resultType is an error |
|
|
std::string m_errorMessage; // Only populated if resultType is an error |
|
|
|
|
|
|
|
|
return ParserResult::runtimeError( "Expected a boolean value but did not recognise: '" + source + "'" ); |
|
|
return ParserResult::runtimeError( "Expected a boolean value but did not recognise: '" + source + "'" ); |
|
|
return ParserResult::ok( ParseResultType::Matched ); |
|
|
return ParserResult::ok( ParseResultType::Matched ); |
|
|
} |
|
|
} |
|
|
|
|
|
#ifdef CLARA_CONFIG_OPTIONAL_TYPE |
|
|
|
|
|
template<typename T> |
|
|
|
|
|
inline auto convertInto( std::string const &source, CLARA_CONFIG_OPTIONAL_TYPE<T>& target ) -> ParserResult { |
|
|
|
|
|
T temp; |
|
|
|
|
|
auto result = convertInto( source, temp ); |
|
|
|
|
|
if( result ) |
|
|
|
|
|
target = std::move(temp); |
|
|
|
|
|
return result; |
|
|
|
|
|
} |
|
|
|
|
|
#endif // CLARA_CONFIG_OPTIONAL_TYPE |
|
|
|
|
|
|
|
|
struct NonCopyable { |
|
|
struct NonCopyable { |
|
|
NonCopyable() = default; |
|
|
NonCopyable() = default; |
|
|
|
|
|
|
|
|
using namespace clara; |
|
|
using namespace clara; |
|
|
|
|
|
|
|
|
auto const setWarning = [&]( std::string const& warning ) { |
|
|
auto const setWarning = [&]( std::string const& warning ) { |
|
|
if( warning != "NoAssertions" ) |
|
|
|
|
|
|
|
|
auto warningSet = [&]() { |
|
|
|
|
|
if( warning == "NoAssertions" ) |
|
|
|
|
|
return WarnAbout::NoAssertions; |
|
|
|
|
|
|
|
|
|
|
|
if ( warning == "NoTests" ) |
|
|
|
|
|
return WarnAbout::NoTests; |
|
|
|
|
|
|
|
|
|
|
|
return WarnAbout::Nothing; |
|
|
|
|
|
}(); |
|
|
|
|
|
|
|
|
|
|
|
if (warningSet == WarnAbout::Nothing) |
|
|
return ParserResult::runtimeError( "Unrecognised warning: '" + warning + "'" ); |
|
|
return ParserResult::runtimeError( "Unrecognised warning: '" + warning + "'" ); |
|
|
config.warnings = static_cast<WarnAbout::What>( config.warnings | WarnAbout::NoAssertions ); |
|
|
|
|
|
|
|
|
config.warnings = static_cast<WarnAbout::What>( config.warnings | warningSet ); |
|
|
return ParserResult::ok( ParseResultType::Matched ); |
|
|
return ParserResult::ok( ParseResultType::Matched ); |
|
|
}; |
|
|
}; |
|
|
auto const loadTestNamesFromFile = [&]( std::string const& filename ) { |
|
|
auto const loadTestNamesFromFile = [&]( std::string const& filename ) { |
|
|
|
|
|
|
|
|
// start catch_enforce.h |
|
|
// start catch_enforce.h |
|
|
|
|
|
|
|
|
#include <stdexcept> |
|
|
#include <stdexcept> |
|
|
#include <iosfwd> |
|
|
|
|
|
|
|
|
|
|
|
#define CATCH_PREPARE_EXCEPTION( type, msg ) \ |
|
|
#define CATCH_PREPARE_EXCEPTION( type, msg ) \ |
|
|
type( static_cast<std::ostringstream&&>( Catch::ReusableStringStream().get() << msg ).str() ) |
|
|
|
|
|
|
|
|
type( ( Catch::ReusableStringStream() << msg ).str() ) |
|
|
#define CATCH_INTERNAL_ERROR( msg ) \ |
|
|
#define CATCH_INTERNAL_ERROR( msg ) \ |
|
|
throw CATCH_PREPARE_EXCEPTION( std::logic_error, CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg); |
|
|
throw CATCH_PREPARE_EXCEPTION( std::logic_error, CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg); |
|
|
#define CATCH_ERROR( msg ) \ |
|
|
#define CATCH_ERROR( msg ) \ |
|
|
|
|
|
|
|
|
: m_data( data ), |
|
|
: m_data( data ), |
|
|
m_stream( openStream() ) |
|
|
m_stream( openStream() ) |
|
|
{ |
|
|
{ |
|
|
if( !data.testsOrTags.empty() ) { |
|
|
|
|
|
TestSpecParser parser( ITagAliasRegistry::get() ); |
|
|
|
|
|
|
|
|
TestSpecParser parser(ITagAliasRegistry::get()); |
|
|
|
|
|
if (data.testsOrTags.empty()) { |
|
|
|
|
|
parser.parse("~[.]"); // All not hidden tests |
|
|
|
|
|
} |
|
|
|
|
|
else { |
|
|
|
|
|
m_hasTestFilters = true; |
|
|
for( auto const& testOrTags : data.testsOrTags ) |
|
|
for( auto const& testOrTags : data.testsOrTags ) |
|
|
parser.parse( testOrTags ); |
|
|
parser.parse( testOrTags ); |
|
|
m_testSpec = parser.testSpec(); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
m_testSpec = parser.testSpec(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
std::string const& Config::getFilename() const { |
|
|
std::string const& Config::getFilename() const { |
|
|
|
|
|
|
|
|
std::string Config::getProcessName() const { return m_data.processName; } |
|
|
std::string Config::getProcessName() const { return m_data.processName; } |
|
|
|
|
|
|
|
|
std::vector<std::string> const& Config::getReporterNames() const { return m_data.reporterNames; } |
|
|
std::vector<std::string> const& Config::getReporterNames() const { return m_data.reporterNames; } |
|
|
|
|
|
std::vector<std::string> const& Config::getTestsOrTags() const { return m_data.testsOrTags; } |
|
|
std::vector<std::string> const& Config::getSectionsToRun() const { return m_data.sectionsToRun; } |
|
|
std::vector<std::string> const& Config::getSectionsToRun() const { return m_data.sectionsToRun; } |
|
|
|
|
|
|
|
|
TestSpec const& Config::testSpec() const { return m_testSpec; } |
|
|
TestSpec const& Config::testSpec() const { return m_testSpec; } |
|
|
|
|
|
bool Config::hasTestFilters() const { return m_hasTestFilters; } |
|
|
|
|
|
|
|
|
bool Config::showHelp() const { return m_data.showHelp; } |
|
|
bool Config::showHelp() const { return m_data.showHelp; } |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::ostream& Config::stream() const { return m_stream->stream(); } |
|
|
std::ostream& Config::stream() const { return m_stream->stream(); } |
|
|
std::string Config::name() const { return m_data.name.empty() ? m_data.processName : m_data.name; } |
|
|
std::string Config::name() const { return m_data.name.empty() ? m_data.processName : m_data.name; } |
|
|
bool Config::includeSuccessfulResults() const { return m_data.showSuccessfulTests; } |
|
|
bool Config::includeSuccessfulResults() const { return m_data.showSuccessfulTests; } |
|
|
bool Config::warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; } |
|
|
|
|
|
|
|
|
bool Config::warnAboutMissingAssertions() const { return !!(m_data.warnings & WarnAbout::NoAssertions); } |
|
|
|
|
|
bool Config::warnAboutNoTests() const { return !!(m_data.warnings & WarnAbout::NoTests); } |
|
|
ShowDurations::OrNot Config::showDurations() const { return m_data.showDurations; } |
|
|
ShowDurations::OrNot Config::showDurations() const { return m_data.showDurations; } |
|
|
RunTests::InWhatOrder Config::runOrder() const { return m_data.runOrder; } |
|
|
RunTests::InWhatOrder Config::runOrder() const { return m_data.runOrder; } |
|
|
unsigned int Config::rngSeed() const { return m_data.rngSeed; } |
|
|
unsigned int Config::rngSeed() const { return m_data.rngSeed; } |
|
|
|
|
|
|
|
|
#ifdef CATCH_PLATFORM_MAC |
|
|
#ifdef CATCH_PLATFORM_MAC |
|
|
!isDebuggerActive() && |
|
|
!isDebuggerActive() && |
|
|
#endif |
|
|
#endif |
|
|
isatty(STDOUT_FILENO); |
|
|
|
|
|
|
|
|
#if !(defined(__DJGPP__) && defined(__STRICT_ANSI__)) |
|
|
|
|
|
isatty(STDOUT_FILENO) |
|
|
|
|
|
#else |
|
|
|
|
|
false |
|
|
|
|
|
#endif |
|
|
|
|
|
; |
|
|
} |
|
|
} |
|
|
IColourImpl* platformColourInstance() { |
|
|
IColourImpl* platformColourInstance() { |
|
|
ErrnoGuard guard; |
|
|
ErrnoGuard guard; |
|
|
|
|
|
|
|
|
::OutputDebugStringA( text.c_str() ); |
|
|
::OutputDebugStringA( text.c_str() ); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
#else |
|
|
#else |
|
|
|
|
|
|
|
|
namespace Catch { |
|
|
namespace Catch { |
|
|
void writeToDebugConsole( std::string const& text ) { |
|
|
void writeToDebugConsole( std::string const& text ) { |
|
|
// !TBD: Need a version for Mac/ XCode and other IDEs |
|
|
// !TBD: Need a version for Mac/ XCode and other IDEs |
|
|
Catch::cout() << text; |
|
|
Catch::cout() << text; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
#endif // Platform |
|
|
#endif // Platform |
|
|
// end catch_debug_console.cpp |
|
|
// end catch_debug_console.cpp |
|
|
// start catch_debugger.cpp |
|
|
// start catch_debugger.cpp |
|
|
|
|
|
|
|
|
# pragma GCC diagnostic ignored "-Wmissing-field-initializers" |
|
|
# pragma GCC diagnostic ignored "-Wmissing-field-initializers" |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
#if (defined(CATCH_PLATFORM_WINDOWS) && defined(CATCH_CONFIG_WINDOWS_SEH)) || defined(CATCH_CONFIG_POSIX_SIGNALS) |
|
|
|
|
|
|
|
|
#if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS ) |
|
|
|
|
|
|
|
|
namespace { |
|
|
namespace { |
|
|
// Report the error condition |
|
|
// Report the error condition |
|
|
void reportFatal( char const * const message ) { |
|
|
void reportFatal( char const * const message ) { |
|
|
Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message ); |
|
|
Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message ); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// |
|
|
|
|
|
|
|
|
#endif // signals/SEH handling |
|
|
|
|
|
|
|
|
# if !defined ( CATCH_CONFIG_WINDOWS_SEH ) |
|
|
|
|
|
|
|
|
|
|
|
namespace Catch { |
|
|
|
|
|
void FatalConditionHandler::reset() {} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
# else // CATCH_CONFIG_WINDOWS_SEH is defined |
|
|
|
|
|
|
|
|
#if defined( CATCH_CONFIG_WINDOWS_SEH ) |
|
|
|
|
|
|
|
|
namespace Catch { |
|
|
namespace Catch { |
|
|
struct SignalDefs { DWORD id; const char* name; }; |
|
|
struct SignalDefs { DWORD id; const char* name; }; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void FatalConditionHandler::reset() { |
|
|
void FatalConditionHandler::reset() { |
|
|
if (isSet) { |
|
|
if (isSet) { |
|
|
// Unregister handler and restore the old guarantee |
|
|
|
|
|
RemoveVectoredExceptionHandler(exceptionHandlerHandle); |
|
|
RemoveVectoredExceptionHandler(exceptionHandlerHandle); |
|
|
SetThreadStackGuarantee(&guaranteeSize); |
|
|
SetThreadStackGuarantee(&guaranteeSize); |
|
|
exceptionHandlerHandle = nullptr; |
|
|
exceptionHandlerHandle = nullptr; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace Catch |
|
|
} // namespace Catch |
|
|
|
|
|
|
|
|
# endif // CATCH_CONFIG_WINDOWS_SEH |
|
|
|
|
|
|
|
|
|
|
|
#else // Not Windows - assumed to be POSIX compatible ////////////////////////// |
|
|
|
|
|
|
|
|
|
|
|
# if !defined(CATCH_CONFIG_POSIX_SIGNALS) |
|
|
|
|
|
|
|
|
|
|
|
namespace Catch { |
|
|
|
|
|
void FatalConditionHandler::reset() {} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
# else // CATCH_CONFIG_POSIX_SIGNALS is defined |
|
|
|
|
|
|
|
|
|
|
|
#include <signal.h> |
|
|
|
|
|
|
|
|
#elif defined( CATCH_CONFIG_POSIX_SIGNALS ) |
|
|
|
|
|
|
|
|
namespace Catch { |
|
|
namespace Catch { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace Catch |
|
|
} // namespace Catch |
|
|
|
|
|
|
|
|
# endif // CATCH_CONFIG_POSIX_SIGNALS |
|
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
|
|
|
|
namespace Catch { |
|
|
|
|
|
void FatalConditionHandler::reset() {} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
#endif // not Windows |
|
|
|
|
|
|
|
|
#endif // signals/SEH handling |
|
|
|
|
|
|
|
|
#if defined(__GNUC__) |
|
|
#if defined(__GNUC__) |
|
|
# pragma GCC diagnostic pop |
|
|
# pragma GCC diagnostic pop |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::size_t listTests( Config const& config ) { |
|
|
std::size_t listTests( Config const& config ) { |
|
|
TestSpec testSpec = config.testSpec(); |
|
|
TestSpec testSpec = config.testSpec(); |
|
|
if( config.testSpec().hasFilters() ) |
|
|
|
|
|
|
|
|
if( config.hasTestFilters() ) |
|
|
Catch::cout() << "Matching test cases:\n"; |
|
|
Catch::cout() << "Matching test cases:\n"; |
|
|
else { |
|
|
else { |
|
|
Catch::cout() << "All available test cases:\n"; |
|
|
Catch::cout() << "All available test cases:\n"; |
|
|
testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
auto matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); |
|
|
auto matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); |
|
|
|
|
|
|
|
|
Catch::cout() << Column( testCaseInfo.tagsAsString() ).indent( 6 ) << "\n"; |
|
|
Catch::cout() << Column( testCaseInfo.tagsAsString() ).indent( 6 ) << "\n"; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if( !config.testSpec().hasFilters() ) |
|
|
|
|
|
|
|
|
if( !config.hasTestFilters() ) |
|
|
Catch::cout() << pluralise( matchedTestCases.size(), "test case" ) << '\n' << std::endl; |
|
|
Catch::cout() << pluralise( matchedTestCases.size(), "test case" ) << '\n' << std::endl; |
|
|
else |
|
|
else |
|
|
Catch::cout() << pluralise( matchedTestCases.size(), "matching test case" ) << '\n' << std::endl; |
|
|
Catch::cout() << pluralise( matchedTestCases.size(), "matching test case" ) << '\n' << std::endl; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::size_t listTestsNamesOnly( Config const& config ) { |
|
|
std::size_t listTestsNamesOnly( Config const& config ) { |
|
|
TestSpec testSpec = config.testSpec(); |
|
|
TestSpec testSpec = config.testSpec(); |
|
|
if( !config.testSpec().hasFilters() ) |
|
|
|
|
|
testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); |
|
|
|
|
|
std::size_t matchedTests = 0; |
|
|
std::size_t matchedTests = 0; |
|
|
std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); |
|
|
std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); |
|
|
for( auto const& testCaseInfo : matchedTestCases ) { |
|
|
for( auto const& testCaseInfo : matchedTestCases ) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::size_t listTags( Config const& config ) { |
|
|
std::size_t listTags( Config const& config ) { |
|
|
TestSpec testSpec = config.testSpec(); |
|
|
TestSpec testSpec = config.testSpec(); |
|
|
if( config.testSpec().hasFilters() ) |
|
|
|
|
|
|
|
|
if( config.hasTestFilters() ) |
|
|
Catch::cout() << "Tags for matching test cases:\n"; |
|
|
Catch::cout() << "Tags for matching test cases:\n"; |
|
|
else { |
|
|
else { |
|
|
Catch::cout() << "All available tags:\n"; |
|
|
Catch::cout() << "All available tags:\n"; |
|
|
testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
std::map<std::string, TagInfo> tagCounts; |
|
|
std::map<std::string, TagInfo> tagCounts; |
|
|
|
|
|
|
|
|
void invoke() const override; |
|
|
void invoke() const override; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
std::string extractClassName( std::string const& classOrQualifiedMethodName ); |
|
|
|
|
|
|
|
|
std::string extractClassName( StringRef const& classOrQualifiedMethodName ); |
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////// |
|
|
/////////////////////////////////////////////////////////////////////////// |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
m_context(getCurrentMutableContext()), |
|
|
m_context(getCurrentMutableContext()), |
|
|
m_config(_config), |
|
|
m_config(_config), |
|
|
m_reporter(std::move(reporter)), |
|
|
m_reporter(std::move(reporter)), |
|
|
m_lastAssertionInfo{ "", SourceLineInfo("",0), "", ResultDisposition::Normal }, |
|
|
|
|
|
|
|
|
m_lastAssertionInfo{ StringRef(), SourceLineInfo("",0), StringRef(), ResultDisposition::Normal }, |
|
|
m_includeSuccessfulResults( m_config->includeSuccessfulResults() ) |
|
|
m_includeSuccessfulResults( m_config->includeSuccessfulResults() ) |
|
|
{ |
|
|
{ |
|
|
m_context.setRunner(this); |
|
|
m_context.setRunner(this); |
|
|
|
|
|
|
|
|
std::string redirectedCout; |
|
|
std::string redirectedCout; |
|
|
std::string redirectedCerr; |
|
|
std::string redirectedCerr; |
|
|
|
|
|
|
|
|
TestCaseInfo testInfo = testCase.getTestCaseInfo(); |
|
|
|
|
|
|
|
|
auto const& testInfo = testCase.getTestCaseInfo(); |
|
|
|
|
|
|
|
|
m_reporter->testCaseStarting(testInfo); |
|
|
m_reporter->testCaseStarting(testInfo); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Counts prevAssertions = m_totals.assertions; |
|
|
Counts prevAssertions = m_totals.assertions; |
|
|
double duration = 0; |
|
|
double duration = 0; |
|
|
m_shouldReportUnexpected = true; |
|
|
m_shouldReportUnexpected = true; |
|
|
m_lastAssertionInfo = { "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal }; |
|
|
|
|
|
|
|
|
m_lastAssertionInfo = { "TEST_CASE"_sr, testCaseInfo.lineInfo, StringRef(), ResultDisposition::Normal }; |
|
|
|
|
|
|
|
|
seedRng(*m_config); |
|
|
seedRng(*m_config); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void showHelp() const; |
|
|
void showHelp() const; |
|
|
void libIdentify(); |
|
|
void libIdentify(); |
|
|
|
|
|
|
|
|
int applyCommandLine( int argc, char* argv[] ); |
|
|
|
|
|
|
|
|
int applyCommandLine( int argc, char const * const * argv ); |
|
|
|
|
|
|
|
|
void useConfigData( ConfigData const& configData ); |
|
|
void useConfigData( ConfigData const& configData ); |
|
|
|
|
|
|
|
|
int run( int argc, char* argv[] ); |
|
|
int run( int argc, char* argv[] ); |
|
|
#if defined(WIN32) && defined(UNICODE) |
|
|
|
|
|
|
|
|
#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE) |
|
|
int run( int argc, wchar_t* const argv[] ); |
|
|
int run( int argc, wchar_t* const argv[] ); |
|
|
#endif |
|
|
#endif |
|
|
int run(); |
|
|
int run(); |
|
|
|
|
|
|
|
|
context.testGroupStarting(config->name(), 1, 1); |
|
|
context.testGroupStarting(config->name(), 1, 1); |
|
|
|
|
|
|
|
|
TestSpec testSpec = config->testSpec(); |
|
|
TestSpec testSpec = config->testSpec(); |
|
|
if (!testSpec.hasFilters()) |
|
|
|
|
|
testSpec = TestSpecParser(ITagAliasRegistry::get()).parse("~[.]").testSpec(); // All not hidden tests |
|
|
|
|
|
|
|
|
|
|
|
auto const& allTestCases = getAllTestCasesSorted(*config); |
|
|
auto const& allTestCases = getAllTestCasesSorted(*config); |
|
|
for (auto const& testCase : allTestCases) { |
|
|
for (auto const& testCase : allTestCases) { |
|
|
|
|
|
|
|
|
context.reporter().skipTest(testCase); |
|
|
context.reporter().skipTest(testCase); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (config->warnAboutNoTests() && totals.testCases.total() == 0) { |
|
|
|
|
|
ReusableStringStream testConfig; |
|
|
|
|
|
|
|
|
|
|
|
bool first = true; |
|
|
|
|
|
for (const auto& input : config->getTestsOrTags()) { |
|
|
|
|
|
if (!first) { testConfig << ' '; } |
|
|
|
|
|
first = false; |
|
|
|
|
|
testConfig << input; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
context.reporter().noMatchingTestCases(testConfig.str()); |
|
|
|
|
|
totals.error = -1; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
context.testGroupEnded(config->name(), totals, 1, 1); |
|
|
context.testGroupEnded(config->name(), totals, 1, 1); |
|
|
return totals; |
|
|
return totals; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if ( !exceptions.empty() ) { |
|
|
if ( !exceptions.empty() ) { |
|
|
m_startupExceptions = true; |
|
|
m_startupExceptions = true; |
|
|
Colour colourGuard( Colour::Red ); |
|
|
Colour colourGuard( Colour::Red ); |
|
|
Catch::cerr() << "Errors occured during startup!" << '\n'; |
|
|
|
|
|
|
|
|
Catch::cerr() << "Errors occurred during startup!" << '\n'; |
|
|
// iterate over all exceptions and notify user |
|
|
// iterate over all exceptions and notify user |
|
|
for ( const auto& ex_ptr : exceptions ) { |
|
|
for ( const auto& ex_ptr : exceptions ) { |
|
|
try { |
|
|
try { |
|
|
|
|
|
|
|
|
<< std::left << std::setw(16) << "version: " << libraryVersion() << std::endl; |
|
|
<< std::left << std::setw(16) << "version: " << libraryVersion() << std::endl; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
int Session::applyCommandLine( int argc, char* argv[] ) { |
|
|
|
|
|
|
|
|
int Session::applyCommandLine( int argc, char const * const * argv ) { |
|
|
if( m_startupExceptions ) |
|
|
if( m_startupExceptions ) |
|
|
return 1; |
|
|
return 1; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return returnCode; |
|
|
return returnCode; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
#if defined(WIN32) && defined(UNICODE) |
|
|
|
|
|
|
|
|
#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE) |
|
|
int Session::run( int argc, wchar_t* const argv[] ) { |
|
|
int Session::run( int argc, wchar_t* const argv[] ) { |
|
|
|
|
|
|
|
|
char **utf8Argv = new char *[ argc ]; |
|
|
char **utf8Argv = new char *[ argc ]; |
|
|
|
|
|
|
|
|
if( Option<std::size_t> listed = list( config() ) ) |
|
|
if( Option<std::size_t> listed = list( config() ) ) |
|
|
return static_cast<int>( *listed ); |
|
|
return static_cast<int>( *listed ); |
|
|
|
|
|
|
|
|
|
|
|
auto totals = runTests( m_config ); |
|
|
// Note that on unices only the lower 8 bits are usually used, clamping |
|
|
// Note that on unices only the lower 8 bits are usually used, clamping |
|
|
// the return value to 255 prevents false negative when some multiple |
|
|
// the return value to 255 prevents false negative when some multiple |
|
|
// of 256 tests has failed |
|
|
// of 256 tests has failed |
|
|
return (std::min)( MaxExitCode, static_cast<int>( runTests( m_config ).assertions.failed ) ); |
|
|
|
|
|
|
|
|
return (std::min) (MaxExitCode, (std::max) (totals.error, static_cast<int>(totals.assertions.failed))); |
|
|
} |
|
|
} |
|
|
catch( std::exception& ex ) { |
|
|
catch( std::exception& ex ) { |
|
|
Catch::cerr() << ex.what() << std::endl; |
|
|
Catch::cerr() << ex.what() << std::endl; |
|
|
|
|
|
|
|
|
const_cast<StringRef*>( this )->takeOwnership(); |
|
|
const_cast<StringRef*>( this )->takeOwnership(); |
|
|
return m_start; |
|
|
return m_start; |
|
|
} |
|
|
} |
|
|
auto StringRef::data() const noexcept -> char const* { |
|
|
|
|
|
|
|
|
auto StringRef::currentData() const noexcept -> char const* { |
|
|
return m_start; |
|
|
return m_start; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
auto operator << ( std::ostream& os, StringRef const& str ) -> std::ostream& { |
|
|
auto operator << ( std::ostream& os, StringRef const& str ) -> std::ostream& { |
|
|
return os << str.c_str(); |
|
|
|
|
|
|
|
|
return os.write(str.currentData(), str.size()); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
auto operator+=( std::string& lhs, StringRef const& rhs ) -> std::string& { |
|
|
|
|
|
lhs.append(rhs.currentData(), rhs.size()); |
|
|
|
|
|
return lhs; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
} // namespace Catch |
|
|
} // namespace Catch |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TestCase makeTestCase( ITestInvoker* _testCase, |
|
|
TestCase makeTestCase( ITestInvoker* _testCase, |
|
|
std::string const& _className, |
|
|
std::string const& _className, |
|
|
std::string const& _name, |
|
|
|
|
|
std::string const& _descOrTags, |
|
|
|
|
|
|
|
|
NameAndTags const& nameAndTags, |
|
|
SourceLineInfo const& _lineInfo ) |
|
|
SourceLineInfo const& _lineInfo ) |
|
|
{ |
|
|
{ |
|
|
bool isHidden = false; |
|
|
bool isHidden = false; |
|
|
|
|
|
|
|
|
std::vector<std::string> tags; |
|
|
std::vector<std::string> tags; |
|
|
std::string desc, tag; |
|
|
std::string desc, tag; |
|
|
bool inTag = false; |
|
|
bool inTag = false; |
|
|
|
|
|
std::string _descOrTags = nameAndTags.tags; |
|
|
for (char c : _descOrTags) { |
|
|
for (char c : _descOrTags) { |
|
|
if( !inTag ) { |
|
|
if( !inTag ) { |
|
|
if( c == '[' ) |
|
|
if( c == '[' ) |
|
|
|
|
|
|
|
|
tags.push_back( "." ); |
|
|
tags.push_back( "." ); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
TestCaseInfo info( _name, _className, desc, tags, _lineInfo ); |
|
|
|
|
|
return TestCase( _testCase, info ); |
|
|
|
|
|
|
|
|
TestCaseInfo info( nameAndTags.name, _className, desc, tags, _lineInfo ); |
|
|
|
|
|
return TestCase( _testCase, std::move(info) ); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void setTags( TestCaseInfo& testCaseInfo, std::vector<std::string> tags ) { |
|
|
void setTags( TestCaseInfo& testCaseInfo, std::vector<std::string> tags ) { |
|
|
|
|
|
|
|
|
return ret; |
|
|
return ret; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
TestCase::TestCase( ITestInvoker* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {} |
|
|
|
|
|
|
|
|
TestCase::TestCase( ITestInvoker* testCase, TestCaseInfo&& info ) : TestCaseInfo( std::move(info) ), test( testCase ) {} |
|
|
|
|
|
|
|
|
TestCase TestCase::withName( std::string const& _newName ) const { |
|
|
TestCase TestCase::withName( std::string const& _newName ) const { |
|
|
TestCase other( *this ); |
|
|
TestCase other( *this ); |
|
|
|
|
|
|
|
|
m_testAsFunction(); |
|
|
m_testAsFunction(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
std::string extractClassName( std::string const& classOrQualifiedMethodName ) { |
|
|
|
|
|
|
|
|
std::string extractClassName( StringRef const& classOrQualifiedMethodName ) { |
|
|
std::string className = classOrQualifiedMethodName; |
|
|
std::string className = classOrQualifiedMethodName; |
|
|
if( startsWith( className, '&' ) ) |
|
|
if( startsWith( className, '&' ) ) |
|
|
{ |
|
|
{ |
|
|
|
|
|
|
|
|
return new(std::nothrow) TestInvokerAsFunction( testAsFunction ); |
|
|
return new(std::nothrow) TestInvokerAsFunction( testAsFunction ); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
NameAndTags::NameAndTags( StringRef name_ , StringRef tags_ ) noexcept : name( name_ ), tags( tags_ ) {} |
|
|
|
|
|
|
|
|
NameAndTags::NameAndTags( StringRef const& name_ , StringRef const& tags_ ) noexcept : name( name_ ), tags( tags_ ) {} |
|
|
|
|
|
|
|
|
AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) noexcept { |
|
|
|
|
|
|
|
|
AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept { |
|
|
try { |
|
|
try { |
|
|
getMutableRegistryHub() |
|
|
getMutableRegistryHub() |
|
|
.registerTest( |
|
|
.registerTest( |
|
|
makeTestCase( |
|
|
makeTestCase( |
|
|
invoker, |
|
|
invoker, |
|
|
extractClassName( classOrMethod ), |
|
|
extractClassName( classOrMethod ), |
|
|
nameAndTags.name, |
|
|
|
|
|
nameAndTags.tags, |
|
|
|
|
|
|
|
|
nameAndTags, |
|
|
lineInfo)); |
|
|
lineInfo)); |
|
|
} catch (...) { |
|
|
} catch (...) { |
|
|
// Do not throw when constructing global objects, instead register the exception to be processed later |
|
|
// Do not throw when constructing global objects, instead register the exception to be processed later |
|
|
|
|
|
|
|
|
return s; |
|
|
return s; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#ifdef CATCH_CONFIG_WCHAR |
|
|
std::string StringMaker<std::wstring>::convert(const std::wstring& wstr) { |
|
|
std::string StringMaker<std::wstring>::convert(const std::wstring& wstr) { |
|
|
std::string s; |
|
|
std::string s; |
|
|
s.reserve(wstr.size()); |
|
|
s.reserve(wstr.size()); |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
return ::Catch::Detail::stringify(s); |
|
|
return ::Catch::Detail::stringify(s); |
|
|
} |
|
|
} |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
std::string StringMaker<char const*>::convert(char const* str) { |
|
|
std::string StringMaker<char const*>::convert(char const* str) { |
|
|
if (str) { |
|
|
if (str) { |
|
|
|
|
|
|
|
|
return{ "{null string}" }; |
|
|
return{ "{null string}" }; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
#ifdef CATCH_CONFIG_WCHAR |
|
|
std::string StringMaker<wchar_t const*>::convert(wchar_t const * str) { |
|
|
std::string StringMaker<wchar_t const*>::convert(wchar_t const * str) { |
|
|
if (str) { |
|
|
if (str) { |
|
|
return ::Catch::Detail::stringify(std::wstring{ str }); |
|
|
return ::Catch::Detail::stringify(std::wstring{ str }); |
|
|
|
|
|
|
|
|
return{ "{null string}" }; |
|
|
return{ "{null string}" }; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
std::string StringMaker<int>::convert(int value) { |
|
|
std::string StringMaker<int>::convert(int value) { |
|
|
return ::Catch::Detail::stringify(static_cast<long long>(value)); |
|
|
return ::Catch::Detail::stringify(static_cast<long long>(value)); |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Version const& libraryVersion() { |
|
|
Version const& libraryVersion() { |
|
|
static Version version( 2, 1, 2, "", 0 ); |
|
|
|
|
|
|
|
|
static Version version( 2, 2, 1, "", 0 ); |
|
|
return version; |
|
|
return version; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef __OBJC__ |
|
|
#ifndef __OBJC__ |
|
|
|
|
|
|
|
|
#if defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN) |
|
|
|
|
|
|
|
|
#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN) |
|
|
// Standard C/C++ Win32 Unicode wmain entry point |
|
|
// Standard C/C++ Win32 Unicode wmain entry point |
|
|
extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) { |
|
|
extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) { |
|
|
#else |
|
|
#else |