Browse Source

Catch updated to latest release v2.2.1 (fixes #115).

main
offa 6 years ago
parent
commit
ae205a9891
1 changed files with 191 additions and 135 deletions
  1. +191
    -135
      test/catch/catch.hpp

+ 191
- 135
test/catch/catch.hpp View File

/* /*
* 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

Loading…
Cancel
Save