merge from tags

This commit is contained in:
Malcolm Noyes
2013-12-09 16:40:52 +00:00
44 changed files with 5023 additions and 648 deletions

View File

@@ -19,6 +19,7 @@
#if (_MANAGED == 1) || (_M_CEE == 1) // detect CLR
#define INTERNAL_CATCH_VS_MANAGED
#define INTERNAL_CATCH_INLINE inline
#else
#if defined(_WINDLL)
@@ -26,6 +27,7 @@
// It's possible that this is not enough for someone so allow it to be overridden...
#if !defined( CATCH_CONFIG_MAIN ) && !defined( CATCH_CONFIG_RUNNER )
#define INTERNAL_CATCH_VS_NATIVE
#define INTERNAL_CATCH_INLINE inline
#endif
#endif
@@ -52,7 +54,6 @@
#endif
#if defined(INTERNAL_CATCH_VS_MANAGED) || defined(INTERNAL_CATCH_VS_NATIVE)
#define INTERNAL_CATCH_INLINE inline
#ifdef INTERNAL_CATCH_VS_MANAGED
#include "internal/catch_vs_managed_impl.hpp"
#else // INTERNAL_CATCH_VS_MANAGED
@@ -203,6 +204,16 @@
#define THEN( desc ) SECTION( " Then: " desc, "" )
#define AND_THEN( desc ) SECTION( " And: " desc, "" )
#if defined(INTERNAL_CATCH_VS_MANAGED) || defined(INTERNAL_CATCH_VS_NATIVE)
#define CATCH_MAP_CATEGORY_TO_TAG( Category, Tag ) INTERNAL_CATCH_MAP_CATEGORY_TO_TAG( Category, Tag )
#define CATCH_CONFIG_SHOW_SUCCESS( v ) CATCH_INTERNAL_CONFIG_SHOW_SUCCESS( v )
#define CATCH_CONFIG_WARN_MISSING_ASSERTIONS( v ) CATCH_INTERNAL_CONFIG_WARN_MISSING_ASSERTIONS( v )
#else
#define CATCH_MAP_CATEGORY_TO_TAG( Category, Tag )
#define CATCH_CONFIG_SHOW_SUCCESS( v )
#define CATCH_CONFIG_WARN_MISSING_ASSERTIONS( v )
#endif
using Catch::Detail::Approx;
#ifdef __clang__

View File

@@ -108,6 +108,8 @@ namespace Catch {
std::set<TestCase> m_testsAlreadyRun;
};
#if !defined(INTERNAL_CATCH_VS_MANAGED) && !defined(INTERNAL_CATCH_VS_NATIVE)
class Session {
static bool alreadyInstantiated;
@@ -232,6 +234,8 @@ namespace Catch {
bool Session::alreadyInstantiated = false;
#endif // !VS_MANAGED && !VS_NATIVE
} // end namespace Catch
#endif // TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED

View File

@@ -58,11 +58,7 @@ namespace Catch {
.setResultType( matcher.match( arg ) );
}
#if defined(INTERNAL_CATCH_VS_MANAGED)
// TestFailureException not defined for CLR
#else // detect CLR
struct TestFailureException{};
#endif
struct TestFailureException{};
} // end namespace Catch
@@ -72,7 +68,6 @@ struct TestFailureException{};
#if !defined(INTERNAL_CATCH_VS_MANAGED) && !defined(INTERNAL_CATCH_VS_NATIVE)
// normal Catch
#define INTERNAL_CATCH_TEST_FAILURE_EXCEPTION const Catch::TestFailureException&
#define INTERNAL_CATCH_TEST_THROW_FAILURE throw Catch::TestFailureException();
#else // VS integration
@@ -86,10 +81,9 @@ struct TestFailureException{};
std::stringstream _sf; \
_sf << r->getExpressionInMacro().c_str() << ", " << r->getMessage().c_str(); \
std::string fail = _sf.str(); \
Assert::Fail(Catch::convert_string_to_managed(fail)); \
Assert::Fail(Catch::convert_string_for_assert(fail)); \
}
#define INTERNAL_CATCH_TEST_FAILURE_EXCEPTION AssertFailedException^
#else
#if defined(INTERNAL_CATCH_VS_NATIVE)
@@ -108,8 +102,6 @@ struct TestFailureException{};
Assert::Fail(ws2.c_str(), &li); \
}
#define INTERNAL_CATCH_TEST_FAILURE_EXCEPTION const Catch::TestFailureException&
#endif // INTERNAL_CATCH_VS_MANAGED
#endif // detect CLR
@@ -121,7 +113,7 @@ struct TestFailureException{};
if( Catch::ResultAction::Value internal_catch_action = Catch::getResultCapture().acceptExpression( evaluatedExpr, INTERNAL_CATCH_ASSERTIONINFO_NAME ) ) { \
if( internal_catch_action & Catch::ResultAction::Debug ) CATCH_BREAK_INTO_DEBUGGER(); \
if( internal_catch_action & Catch::ResultAction::Abort ) { INTERNAL_CATCH_TEST_THROW_FAILURE } \
if( !Catch::shouldContinueOnFailure( resultDisposition ) ) { INTERNAL_CATCH_TEST_THROW_FAILURE } \
if( !Catch::shouldContinueOnFailure( resultDisposition ) ) { throw Catch::TestFailureException(); } \
Catch::isTrue( false && originalExpr ); \
}
@@ -135,7 +127,7 @@ struct TestFailureException{};
INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \
try { \
INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionDecomposer()->*expr ).endExpression( resultDisposition ), resultDisposition, expr ); \
} catch( INTERNAL_CATCH_TEST_FAILURE_EXCEPTION ) { \
} catch( const Catch::TestFailureException& ) { \
throw; \
} catch( ... ) { \
INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException(), \
@@ -174,7 +166,7 @@ struct TestFailureException{};
INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::DidntThrowException ), resultDisposition, false ); \
} \
} \
catch( INTERNAL_CATCH_TEST_FAILURE_EXCEPTION ) { \
catch( const Catch::TestFailureException& ) { \
throw; \
} \
catch( exceptionType ) { \
@@ -218,7 +210,7 @@ struct TestFailureException{};
INTERNAL_CATCH_ACCEPT_INFO( #arg " " #matcher, macroName, resultDisposition ); \
try { \
INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::expressionResultBuilderFromMatcher( ::Catch::Matchers::matcher, arg, #matcher ) ), resultDisposition, false ); \
} catch( INTERNAL_CATCH_TEST_FAILURE_EXCEPTION ) { \
} catch( const Catch::TestFailureException& ) { \
throw; \
} catch( ... ) { \
INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException() ), \

View File

@@ -22,6 +22,138 @@
#define CATCH_CONFIG_CONSOLE_WIDTH 80
#endif
namespace CatchOverrides {
class ConfigGuard
{
public:
ConfigGuard()
: origConfig(Catch::getCurrentContext().getConfig())
{}
~ConfigGuard()
{
Catch::getCurrentMutableContext().setConfig(origConfig);
}
const Catch::Ptr<Catch::IConfig const>& value() const {return origConfig;}
private:
ConfigGuard(const ConfigGuard&);
ConfigGuard& operator=(const ConfigGuard&);
const Catch::Ptr<Catch::IConfig const> origConfig;
};
template <typename T>
class Config
{
typedef std::map<int, bool> LineData;
typedef std::map<std::string, LineData> FileLineData;
public:
bool includeSuccessfulResults(const std::string& file, int c) const
{
bool result(false);
FileLineData::const_iterator it = showSuccessfulTestsData.find(file);
if( it != showSuccessfulTestsData.end() )
{
for( LineData::const_iterator lineIt = it->second.begin(); lineIt != it->second.end(); ++lineIt )
{
if( c <= lineIt->first )
break;
result = lineIt->second;
}
}
return result;
}
void insertSuccessfulResults(const std::string& file, int c, bool v)
{
FileLineData::iterator it = showSuccessfulTestsData.find(file);
if( it == showSuccessfulTestsData.end() )
{
LineData tmp;
tmp.insert(std::make_pair(c,v));
showSuccessfulTestsData.insert(std::make_pair(file, tmp));
}
else
{
it->second.insert(std::make_pair(c,v));
}
}
bool warnAboutMissingAssertions(const std::string& file, int c) const
{
bool result(false);
FileLineData::const_iterator it = missingAssertionData.find(file);
if( it != missingAssertionData.end() )
{
for( LineData::const_iterator lineIt = it->second.begin(); lineIt != it->second.end(); ++lineIt )
{
if( c <= lineIt->first )
break;
result = lineIt->second;
}
}
return result;
}
void insertMissingAssertions(const std::string& file, int c, bool v)
{
FileLineData::iterator it = missingAssertionData.find(file);
if( it == missingAssertionData.end() )
{
LineData tmp;
tmp.insert(std::make_pair(c,v));
missingAssertionData.insert(std::make_pair(file, tmp));
}
else
{
it->second.insert(std::make_pair(c,v));
}
}
static Config<T>& instance()
{
if( !s_instance )
{
s_instance = new Config<T>();
}
return *s_instance;
}
private:
FileLineData showSuccessfulTestsData;
FileLineData missingAssertionData;
static Config<T>* s_instance;
};
template <typename T>
Config<T>* Config<T>::s_instance = NULL;
template <typename T>
struct ConfigReset
{
ConfigReset( const std::string& file, int c )
{
Config<T>::instance().insertSuccessfulResults(file, c, false);
Config<T>::instance().insertMissingAssertions(file, c, false);
}
};
template <typename T>
struct ConfigShowSuccessfulTests
{
template <typename U>
ConfigShowSuccessfulTests( const std::string& file, int c, U v )
{
Config<T>::instance().insertSuccessfulResults(file, c, v ? true : false);
}
};
template <typename T>
struct ConfigWarnMissingAssertions
{
template <typename U>
ConfigWarnMissingAssertions( const std::string& file, int c, U v )
{
Config<T>::instance().insertMissingAssertions(file, c, v ? true : false);
}
};
}
namespace Catch {
struct ConfigData {
@@ -41,6 +173,21 @@ namespace Catch {
showDurations( ShowDurations::DefaultForReporter )
{}
explicit ConfigData(const IConfig* other)
: listTests( false ),
listTags( false ),
listReporters( false ),
showSuccessfulTests( other ? other->includeSuccessfulResults() : false ),
shouldDebugBreak( false ),
noThrow( other ? !other->allowThrows() : false ),
showHelp( false ),
abortAfter( -1 ),
verbosity( Verbosity::Normal ),
warnings( other ? (other->warnAboutMissingAssertions() ? WarnAbout::NoAssertions : WarnAbout::Nothing) : WarnAbout::Nothing ),
showDurations( other ? other->showDurations() : ShowDurations::DefaultForReporter ),
name( other ? other->name() : std::string() )
{}
bool listTests;
bool listTags;
bool listReporters;

View File

@@ -12,10 +12,6 @@
namespace Catch {
namespace Detail {
struct IColourImpl;
}
struct Colour {
enum Code {
None = 0,
@@ -53,12 +49,6 @@ namespace Catch {
// Use constructed object for RAII guard
Colour( Code _colourCode );
~Colour();
// Use static method for one-shot changes
static void use( Code _colourCode );
private:
static Detail::IColourImpl* impl;
};
} // end namespace Catch

View File

@@ -10,13 +10,6 @@
#include "catch_console_colour.hpp"
namespace Catch { namespace Detail {
struct IColourImpl {
virtual ~IColourImpl() {}
virtual void use( Colour::Code _colourCode ) = 0;
};
}}
#if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
#ifndef NOMINMAX
@@ -32,7 +25,7 @@ namespace Catch { namespace Detail {
namespace Catch {
namespace {
class Win32ColourImpl : public Detail::IColourImpl {
class Win32ColourImpl {
public:
Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
{
@@ -41,7 +34,7 @@ namespace {
originalAttributes = csbiInfo.wAttributes;
}
virtual void use( Colour::Code _colourCode ) {
void use( Colour::Code _colourCode ) {
switch( _colourCode ) {
case Colour::None: return setTextAttribute( originalAttributes );
case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
@@ -73,7 +66,7 @@ namespace {
return true;
}
Win32ColourImpl platformColourImpl;
typedef Win32ColourImpl PlatformColourImpl;
} // end anon namespace
} // end namespace Catch
@@ -89,9 +82,9 @@ namespace {
// Thanks to Adam Strzelecki for original contribution
// (http://github.com/nanoant)
// https://github.com/philsquared/Catch/pull/131
class PosixColourImpl : public Detail::IColourImpl {
class PosixColourImpl {
public:
virtual void use( Colour::Code _colourCode ) {
void use( Colour::Code _colourCode ) {
switch( _colourCode ) {
case Colour::None:
case Colour::White: return setColour( "[0m" );
@@ -120,7 +113,7 @@ namespace {
return isatty(STDOUT_FILENO);
}
PosixColourImpl platformColourImpl;
typedef PosixColourImpl PlatformColourImpl;
} // end anon namespace
} // end namespace Catch
@@ -129,24 +122,24 @@ namespace {
namespace Catch {
namespace {
struct NoColourImpl : Detail::IColourImpl {
void use( Colour::Code ) {}
};
NoColourImpl noColourImpl;
static const bool shouldUseColour = shouldUseColourForPlatform() &&
!isDebuggerActive();
}
template <typename Impl>
struct ColourChange
{
static Impl impl;
static const bool shouldUseColour;
};
template <typename Impl>
Impl ColourChange<Impl>::impl;
template <typename Impl>
const bool ColourChange<Impl>::shouldUseColour = shouldUseColourForPlatform() &&
!isDebuggerActive();;
Colour::Colour( Code _colourCode ){ use( _colourCode ); }
Colour::~Colour(){ use( None ); }
void Colour::use( Code _colourCode ) {
impl->use( _colourCode );
INTERNAL_CATCH_INLINE Colour::Colour( Code _colourCode ) {
if( ColourChange<PlatformColourImpl>::shouldUseColour ) ColourChange<PlatformColourImpl>::impl.use( _colourCode );
}
INTERNAL_CATCH_INLINE Colour::~Colour() {
if( ColourChange<PlatformColourImpl>::shouldUseColour ) ColourChange<PlatformColourImpl>::impl.use( Colour::None );
}
Detail::IColourImpl* Colour::impl = shouldUseColour
? static_cast<Detail::IColourImpl*>( &platformColourImpl )
: static_cast<Detail::IColourImpl*>( &noColourImpl );
} // end namespace Catch

View File

@@ -15,9 +15,10 @@
namespace Catch {
template <typename Runner, typename ResultCapture>
class Context : public IMutableContext {
Context() : m_config( NULL ), m_runner( NULL ), m_resultCapture( NULL ) {}
Context() : m_config( NULL ), m_runner( &nullRunner ), m_resultCapture( &nullResultCapture ) {}
Context( Context const& );
void operator=( Context const& );
@@ -81,15 +82,28 @@ namespace Catch {
IRunner* m_runner;
IResultCapture* m_resultCapture;
std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName;
static ResultCapture nullResultCapture;
static Runner nullRunner;
public:
static Context* currentContext;
};
namespace {
template <typename Runner, typename ResultCapture>
ResultCapture Context<Runner, ResultCapture>::nullResultCapture;
template <typename Runner, typename ResultCapture>
Runner Context<Runner, ResultCapture>::nullRunner;
template <typename Runner, typename ResultCapture>
Context<Runner,ResultCapture>* Context<Runner, ResultCapture>::currentContext = NULL;
/*namespace {
Context* currentContext = NULL;
}
}*/
typedef Context<NullRunner, NullResultCapture> DefaultContext;
INTERNAL_CATCH_INLINE IMutableContext& getCurrentMutableContext() {
if( !currentContext )
currentContext = new Context();
return *currentContext;
if( !DefaultContext::currentContext )
DefaultContext::currentContext = new DefaultContext();
return *DefaultContext::currentContext;
}
INTERNAL_CATCH_INLINE IContext& getCurrentContext() {
return getCurrentMutableContext();
@@ -104,8 +118,8 @@ namespace Catch {
}
INTERNAL_CATCH_INLINE void cleanUpContext() {
delete currentContext;
currentContext = NULL;
delete DefaultContext::currentContext;
DefaultContext::currentContext = NULL;
}
}

View File

@@ -41,6 +41,23 @@ namespace Catch {
virtual std::string getCurrentTestName() const = 0;
virtual const AssertionResult* getLastResult() const = 0;
};
struct NullResultCapture : public IResultCapture {
virtual void assertionEnded( AssertionResult const& ) {}
virtual bool sectionStarted( SectionInfo const& ,
Counts& ) {return false;}
virtual void sectionEnded( SectionInfo const& , Counts const& , double ) {}
virtual void pushScopedMessage( MessageInfo const& ) {}
virtual void popScopedMessage( MessageInfo const& ) {}
virtual bool shouldDebugBreak() const {return false;}
virtual ResultAction::Value acceptExpression( ExpressionResultBuilder const& , AssertionInfo const& ) {return ResultAction::Abort;}
virtual std::string getCurrentTestName() const {return std::string();}
virtual const AssertionResult* getLastResult() const {return NULL;}
};
}
#endif // TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED

View File

@@ -14,6 +14,10 @@ namespace Catch {
struct IRunner {
virtual ~IRunner();
};
struct NullRunner : public IRunner
{
};
}
#endif // TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED

View File

@@ -16,64 +16,68 @@
namespace Catch {
namespace {
class RegistryHub : public IRegistryHub, public IMutableRegistryHub {
class RegistryHub : public IRegistryHub, public IMutableRegistryHub {
RegistryHub( RegistryHub const& );
void operator=( RegistryHub const& );
RegistryHub( RegistryHub const& );
void operator=( RegistryHub const& );
public: // IRegistryHub
RegistryHub() {
}
virtual IReporterRegistry const& getReporterRegistry() const {
return m_reporterRegistry;
}
virtual ITestCaseRegistry const& getTestCaseRegistry() const {
return m_testCaseRegistry;
}
virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() {
return m_exceptionTranslatorRegistry;
}
public: // IRegistryHub
RegistryHub() {
}
virtual IReporterRegistry const& getReporterRegistry() const {
return m_reporterRegistry;
}
virtual ITestCaseRegistry const& getTestCaseRegistry() const {
return m_testCaseRegistry;
}
virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() {
return m_exceptionTranslatorRegistry;
}
public: // IMutableRegistryHub
virtual void registerReporter( std::string const& name, IReporterFactory* factory ) {
m_reporterRegistry.registerReporter( name, factory );
}
virtual void registerTest( TestCase const& testInfo ) {
m_testCaseRegistry.registerTest( testInfo );
}
virtual void registerTranslator( const IExceptionTranslator* translator ) {
m_exceptionTranslatorRegistry.registerTranslator( translator );
}
public: // IMutableRegistryHub
virtual void registerReporter( std::string const& name, IReporterFactory* factory ) {
m_reporterRegistry.registerReporter( name, factory );
}
virtual void registerTest( TestCase const& testInfo ) {
m_testCaseRegistry.registerTest( testInfo );
}
virtual void registerTranslator( const IExceptionTranslator* translator ) {
m_exceptionTranslatorRegistry.registerTranslator( translator );
}
private:
TestRegistry m_testCaseRegistry;
ReporterRegistry m_reporterRegistry;
ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
};
private:
TestRegistry m_testCaseRegistry;
ReporterRegistry m_reporterRegistry;
ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
};
// Single, global, instance
inline RegistryHub*& getTheRegistryHub() {
static RegistryHub* theRegistryHub = NULL;
// Single, global, instance
template <typename T>
struct GlobalRegistryHub
{
static T*& instance()
{
if( !theRegistryHub )
theRegistryHub = new RegistryHub();
theRegistryHub = new T();
return theRegistryHub;
}
}
static T* theRegistryHub;
};
template <typename T>
T* GlobalRegistryHub<T>::theRegistryHub = NULL;
IRegistryHub& getRegistryHub() {
return *getTheRegistryHub();
INTERNAL_CATCH_INLINE IRegistryHub& getRegistryHub() {
return *GlobalRegistryHub<RegistryHub>::instance();
}
IMutableRegistryHub& getMutableRegistryHub() {
return *getTheRegistryHub();
INTERNAL_CATCH_INLINE IMutableRegistryHub& getMutableRegistryHub() {
return *GlobalRegistryHub<RegistryHub>::instance();
}
void cleanUp() {
delete getTheRegistryHub();
getTheRegistryHub() = NULL;
INTERNAL_CATCH_INLINE void cleanUp() {
delete GlobalRegistryHub<RegistryHub>::instance();
GlobalRegistryHub<RegistryHub>::instance() = NULL;
cleanUpContext();
}
std::string translateActiveException() {
INTERNAL_CATCH_INLINE std::string translateActiveException() {
return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
}

View File

@@ -48,7 +48,6 @@ namespace Catch {
};
///////////////////////////////////////////////////////////////////////////
class RunContext : public IResultCapture, public IRunner {
RunContext( RunContext const& );
@@ -105,18 +104,16 @@ namespace Catch {
}
Totals runTest( TestCase const& testCase ) {
Totals prevTotals = m_totals;
std::string redirectedCout;
std::string redirectedCerr;
TestCaseInfo testInfo = testCase.getTestCaseInfo();
m_reporter->testCaseStarting( testInfo );
UnwindTestCaseOnCompletion finaliser(*this, m_totals, m_reporter, testInfo, redirectedCout, redirectedCerr);
m_activeTestCase = &testCase;
m_testCaseTracker = TestCaseTracker( testInfo.name );
do {
do {
runCurrentTest( redirectedCout, redirectedCerr );
@@ -125,18 +122,10 @@ namespace Catch {
}
while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() );
Totals deltaTotals = m_totals.delta( prevTotals );
m_totals.testCases += deltaTotals.testCases;
m_reporter->testCaseEnded( TestCaseStats( testInfo,
deltaTotals,
redirectedCout,
redirectedCerr,
aborting() ) );
m_activeTestCase = NULL;
m_testCaseTracker.reset();
return deltaTotals;
return finaliser.report();
}
Ptr<IConfig const> config() const {
@@ -194,12 +183,7 @@ namespace Catch {
return true;
}
virtual void sectionEnded( SectionInfo const& info, Counts const& prevAssertions, double _durationInSeconds ) {
if( std::uncaught_exception() ) {
m_unfinishedSections.push_back( UnfinishedSections( info, prevAssertions, _durationInSeconds ) );
return;
}
void unwindSection(SectionInfo const& info, Counts const& prevAssertions, double _durationInSeconds ) {
Counts assertions = m_totals.assertions - prevAssertions;
bool missingAssertions = testForMissingAssertions( assertions );
@@ -209,6 +193,15 @@ namespace Catch {
m_messages.clear();
}
virtual void sectionEnded( SectionInfo const& info, Counts const& prevAssertions, double _durationInSeconds ) {
if( std::uncaught_exception() ) {
m_unfinishedSections.push_back( UnfinishedSections( info, prevAssertions, _durationInSeconds ) );
return;
}
unwindSection(info, prevAssertions, _durationInSeconds);
}
virtual void pushScopedMessage( MessageInfo const& message ) {
m_messages.push_back( message );
}
@@ -257,16 +250,13 @@ namespace Catch {
void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) {
TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
SectionInfo testCaseSection( testCaseInfo.name, testCaseInfo.description, testCaseInfo.lineInfo );
m_reporter->sectionStarting( testCaseSection );
Counts prevAssertions = m_totals.assertions;
double duration = 0;
UnwindSectionOnCompletion finaliser(*this, m_totals, m_reporter, testCaseInfo, m_unfinishedSections, m_messages);
try {
m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal );
TestCaseTracker::Guard guard( *m_testCaseTracker );
Timer timer;
timer.start();
finaliser.startTimer();
if( m_reporter->getPreferences().shouldRedirectStdOut ) {
StreamRedirect coutRedir( std::cout, redirectedCout );
StreamRedirect cerrRedir( std::cerr, redirectedCerr );
@@ -275,37 +265,16 @@ namespace Catch {
else {
m_activeTestCase->invoke();
}
duration = timer.getElapsedSeconds();
finaliser.stopTimer();
}
#ifdef INTERNAL_CATCH_VS_MANAGED // detect CLR
catch(AssertFailedException^) {
throw; // CLR always rethrows - stop on first assert
}
#else
catch( INTERNAL_CATCH_TEST_FAILURE_EXCEPTION ) {
catch( const Catch::TestFailureException& ) {
// This just means the test was aborted due to failure
}
#endif
catch(...) {
ExpressionResultBuilder exResult( ResultWas::ThrewException );
exResult << translateActiveException();
actOnCurrentResult( exResult.buildResult( m_lastAssertionInfo ) );
}
// If sections ended prematurely due to an exception we stored their
// infos here so we can tear them down outside the unwind process.
for( std::vector<UnfinishedSections>::const_iterator it = m_unfinishedSections.begin(),
itEnd = m_unfinishedSections.end();
it != itEnd;
++it )
sectionEnded( it->info, it->prevAssertions, it->durationInSeconds );
m_unfinishedSections.clear();
m_messages.clear();
Counts assertions = m_totals.assertions - prevAssertions;
bool missingAssertions = testForMissingAssertions( assertions );
SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions );
m_reporter->sectionEnded( testCaseSectionStats );
}
private:
@@ -319,6 +288,111 @@ namespace Catch {
double durationInSeconds;
};
class UnwindSectionOnCompletion
{
public:
UnwindSectionOnCompletion(RunContext& context, Totals& totals, Ptr<IStreamingReporter>& reporter, TestCaseInfo const& testCaseInfo,
std::vector<UnfinishedSections>& unfinishedSections, std::vector<MessageInfo>& messages)
: m_context(context)
, m_totals(totals)
, m_reporter(reporter)
, m_testCaseSection( testCaseInfo.name, testCaseInfo.description, testCaseInfo.lineInfo )
, m_unfinishedSections(unfinishedSections)
, m_messages(messages)
, m_duration(0.0)
{
m_prevAssertions = m_totals.assertions;
m_reporter->sectionStarting( m_testCaseSection );
}
~UnwindSectionOnCompletion()
{
// If sections ended prematurely due to an exception we stored their
// infos here so we can tear them down.
for( std::vector<UnfinishedSections>::const_iterator it = m_unfinishedSections.begin(),
itEnd = m_unfinishedSections.end();
it != itEnd;
++it ) {
m_context.unwindSection( it->info, it->prevAssertions, it->durationInSeconds );
}
m_unfinishedSections.clear();
m_messages.clear();
Counts assertions = m_totals.assertions - m_prevAssertions;
bool missingAssertions = m_context.testForMissingAssertions( assertions );
SectionStats testCaseSectionStats( m_testCaseSection, assertions, m_duration, missingAssertions );
m_reporter->sectionEnded( testCaseSectionStats );
}
void startTimer()
{
m_timer.start();
}
void stopTimer()
{
m_duration = m_timer.getElapsedSeconds();
}
private:
// non-copyable
UnwindSectionOnCompletion(const UnwindSectionOnCompletion&);
UnwindSectionOnCompletion& operator=(const UnwindSectionOnCompletion&);
RunContext& m_context;
Totals& m_totals;
Ptr<IStreamingReporter>& m_reporter;
SectionInfo m_testCaseSection;
std::vector<UnfinishedSections>& m_unfinishedSections;
std::vector<MessageInfo>& m_messages;
Timer m_timer;
Counts m_prevAssertions;
double m_duration;
};
class UnwindTestCaseOnCompletion
{
public:
UnwindTestCaseOnCompletion(RunContext& context, Totals& totals, Ptr<IStreamingReporter>& reporter, TestCaseInfo& testInfo,
std::string& redirectedCout, std::string& redirectedCerr)
: m_context(context), m_totals(totals), m_reporter(reporter), m_testInfo(testInfo)
, m_redirectedCout(redirectedCout), m_redirectedCerr(redirectedCerr)
, m_reported(false)
{
m_prevTotals = m_totals;
m_reporter->testCaseStarting( m_testInfo );
}
~UnwindTestCaseOnCompletion()
{
if( !m_reported )
{
report();
}
}
Totals report()
{
m_reported = true;
Totals deltaTotals = m_totals.delta( m_prevTotals );
m_totals.testCases += deltaTotals.testCases;
m_reporter->testCaseEnded( TestCaseStats( m_testInfo,
deltaTotals,
m_redirectedCout,
m_redirectedCerr,
m_context.aborting() ) );
return deltaTotals;
}
private:
// non-copyable
UnwindTestCaseOnCompletion(const UnwindTestCaseOnCompletion&);
UnwindTestCaseOnCompletion& operator=(const UnwindTestCaseOnCompletion&);
RunContext& m_context;
Totals& m_totals;
Ptr<IStreamingReporter>& m_reporter;
TestCaseInfo& m_testInfo;
std::string& m_redirectedCout;
std::string& m_redirectedCerr;
bool m_reported;
Totals m_prevTotals;
};
TestRunInfo m_runInfo;
IMutableContext& m_context;
TestCase const* m_activeTestCase;

View File

@@ -8,7 +8,11 @@
#ifndef TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
#if defined(INTERNAL_CATCH_VS_MANAGED) || defined(INTERNAL_CATCH_VS_NATIVE)
#include "internal/catch_vs_test_registry.hpp"
#else
#include "catch_test_registry.hpp"
#endif
#include "catch_test_case_info.h"
#include "catch_test_spec.h"
#include "catch_context.h"
@@ -124,15 +128,15 @@ namespace Catch {
///////////////////////////////////////////////////////////////////////////
AutoReg::AutoReg( TestFunction function,
INTERNAL_CATCH_INLINE AutoReg::AutoReg( TestFunction function,
SourceLineInfo const& lineInfo,
NameAndDesc const& nameAndDesc ) {
registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo );
}
AutoReg::~AutoReg() {}
INTERNAL_CATCH_INLINE AutoReg::~AutoReg() {}
void AutoReg::registerTestCase( ITestCase* testCase,
INTERNAL_CATCH_INLINE void AutoReg::registerTestCase( ITestCase* testCase,
char const* classOrQualifiedMethodName,
NameAndDesc const& nameAndDesc,
SourceLineInfo const& lineInfo ) {

View File

@@ -24,15 +24,25 @@ namespace Catch {
namespace {
#ifdef CATCH_PLATFORM_WINDOWS
template <typename T>
struct CounterDefaults
{
static T hz;
static T hzo;
};
template <typename T>
T CounterDefaults<T>::hz = 0;
template <typename T>
T CounterDefaults<T>::hzo = 0;
INTERNAL_CATCH_INLINE uint64_t getCurrentTicks() {
static uint64_t hz=0, hzo=0;
if (!hz) {
QueryPerformanceFrequency((LARGE_INTEGER*)&hz);
QueryPerformanceCounter((LARGE_INTEGER*)&hzo);
if (!CounterDefaults<uint64_t>::hz) {
QueryPerformanceFrequency((LARGE_INTEGER*)&CounterDefaults<uint64_t>::hz);
QueryPerformanceCounter((LARGE_INTEGER*)&CounterDefaults<uint64_t>::hzo);
}
uint64_t t;
QueryPerformanceCounter((LARGE_INTEGER*)&t);
return ((t-hzo)*1000000)/hz;
return ((t-CounterDefaults<uint64_t>::hzo)*1000000)/CounterDefaults<uint64_t>::hz;
}
#else
INTERNAL_CATCH_INLINE uint64_t getCurrentTicks() {

View File

@@ -95,7 +95,11 @@ struct StringMaker<T*> {
if( !p )
return INTERNAL_CATCH_STRINGIFY( NULL );
std::ostringstream oss;
#ifdef _MSC_VER
oss << "0x" << p;
#else
oss << p;
#endif
return oss.str();
}
};

View File

@@ -18,7 +18,7 @@ using namespace System::Collections::Generic;
using namespace Microsoft::VisualStudio::TestTools::UnitTesting;
namespace Catch {
inline String^ convert_string_to_managed(const std::string& s)
inline String^ convert_string_for_assert(const std::string& s)
{
String^ result = gcnew String(s.c_str());
return result;
@@ -33,67 +33,50 @@ namespace Catch {
#include "catch_section.hpp"
#include "internal/catch_timer.hpp"
#include "internal/catch_vs_test_registry.hpp"
#include "internal/catch_reporter_registrars.hpp"
#include "reporters/catch_vs_reporter.hpp"
#include "internal/catch_exception_translator_registry.hpp"
#include "catch_registry_hub.hpp"
#include "internal/catch_console_colour_impl.hpp"
#include "catch_runner.hpp"
namespace Catch {
inline NonCopyable::~NonCopyable() {}
inline IShared::~IShared() {}
inline StreamBufBase::~StreamBufBase() throw() {}
inline IContext::~IContext() {}
inline IResultCapture::~IResultCapture() {}
inline ITestCase::~ITestCase() {}
inline ITestCaseRegistry::~ITestCaseRegistry() {}
inline IRegistryHub::~IRegistryHub() {}
inline IMutableRegistryHub::~IMutableRegistryHub() {}
inline IExceptionTranslator::~IExceptionTranslator() {}
inline IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {}
inline IReporter::~IReporter() {}
inline IReporterFactory::~IReporterFactory() {}
inline IReporterRegistry::~IReporterRegistry() {}
inline IStreamingReporter::~IStreamingReporter() {}
inline AssertionStats::~AssertionStats() {}
inline SectionStats::~SectionStats() {}
inline TestCaseStats::~TestCaseStats() {}
inline TestGroupStats::~TestGroupStats() {}
inline TestRunStats::~TestRunStats() {}
class ExceptionRegistryHub : public IRegistryHub, public IMutableRegistryHub {
inline IRunner::~IRunner() {}
inline IMutableContext::~IMutableContext() {}
inline IConfig::~IConfig() {}
inline TestRegistry::~TestRegistry() {}
inline FreeFunctionTestCase::~FreeFunctionTestCase() {}
inline IGeneratorInfo::~IGeneratorInfo() {}
inline IGeneratorsForTest::~IGeneratorsForTest() {}
ExceptionRegistryHub( ExceptionRegistryHub const& );
void operator=( ExceptionRegistryHub const& );
public: // IRegistryHub
ExceptionRegistryHub() {
}
virtual IReporterRegistry const& getReporterRegistry() const {
throw std::runtime_error("can't do this for Visual Studio tests!");
}
virtual ITestCaseRegistry const& getTestCaseRegistry() const {
throw std::runtime_error("can't do this for Visual Studio tests!");
}
virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() {
return m_exceptionTranslatorRegistry;
}
public: // IMutableRegistryHub
virtual void registerReporter( std::string const&, IReporterFactory* ) {
throw std::runtime_error("can't do this for Visual Studio tests!");
}
virtual void registerTest( TestCase const& ) {
throw std::runtime_error("can't do this for Visual Studio tests!");
}
virtual void registerTranslator( const IExceptionTranslator* translator ) {
m_exceptionTranslatorRegistry.registerTranslator( translator );
}
private:
ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
};
template <typename T>
struct GlobalRegistryHub
{
static T& instance()
{
if( !theRegistryHub )
theRegistryHub = new T();
return *theRegistryHub;
}
static T* theRegistryHub;
};
template <typename T>
T* GlobalRegistryHub<T>::theRegistryHub = NULL;
INTERNAL_CATCH_INLINE IMutableRegistryHub& getMutableRegistryHub() {
return GlobalRegistryHub<ExceptionRegistryHub>::instance();
}
INTERNAL_CATCH_INLINE std::string translateActiveException() {
return GlobalRegistryHub<ExceptionRegistryHub>::instance().getExceptionTranslatorRegistry().translateActiveException();
}
inline Matchers::Impl::StdString::Equals::~Equals() {}
inline Matchers::Impl::StdString::Contains::~Contains() {}
inline Matchers::Impl::StdString::StartsWith::~StartsWith() {}
inline Matchers::Impl::StdString::EndsWith::~EndsWith() {}
inline void Config::dummy() {}
}
#endif
#endif // TWOBLUECUBES_CATCH_VS_MANAGED_HPP_INCLUDED

View File

@@ -16,8 +16,6 @@ using Microsoft::VisualStudio::CppUnitTestFramework::Logger;
using Microsoft::VisualStudio::CppUnitTestFramework::Assert;
using Microsoft::VisualStudio::CppUnitTestFramework::__LineInfo;
#define INTERNAL_CATCH_INLINE inline
#include <cvt/wstring>
#include <codecvt>
@@ -26,66 +24,50 @@ using Microsoft::VisualStudio::CppUnitTestFramework::__LineInfo;
#include "catch_tags.hpp"
#include "catch_test_spec.hpp"
#include "catch_section.hpp"
#include "internal/catch_timer.hpp"
#include "internal/catch_vs_test_registry.hpp"
#include "internal/catch_reporter_registrars.hpp"
#include "reporters/catch_vs_reporter.hpp"
#include "catch_registry_hub.hpp"
#include "internal/catch_timer.hpp"
#include "internal/catch_console_colour_impl.hpp"
#include "catch_runner.hpp"
namespace Catch {
inline NonCopyable::~NonCopyable() {}
inline IShared::~IShared() {}
inline StreamBufBase::~StreamBufBase() throw() {}
inline IContext::~IContext() {}
inline IResultCapture::~IResultCapture() {}
inline ITestCase::~ITestCase() {}
inline ITestCaseRegistry::~ITestCaseRegistry() {}
inline IRegistryHub::~IRegistryHub() {}
inline IMutableRegistryHub::~IMutableRegistryHub() {}
inline IExceptionTranslator::~IExceptionTranslator() {}
inline IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {}
inline IReporter::~IReporter() {}
inline IReporterFactory::~IReporterFactory() {}
inline IReporterRegistry::~IReporterRegistry() {}
inline IStreamingReporter::~IStreamingReporter() {}
inline AssertionStats::~AssertionStats() {}
inline SectionStats::~SectionStats() {}
inline TestCaseStats::~TestCaseStats() {}
inline TestGroupStats::~TestGroupStats() {}
inline TestRunStats::~TestRunStats() {}
class ExceptionRegistryHub : public IRegistryHub, public IMutableRegistryHub {
inline IRunner::~IRunner() {}
inline IMutableContext::~IMutableContext() {}
inline IConfig::~IConfig() {}
inline TestRegistry::~TestRegistry() {}
inline FreeFunctionTestCase::~FreeFunctionTestCase() {}
inline IGeneratorInfo::~IGeneratorInfo() {}
inline IGeneratorsForTest::~IGeneratorsForTest() {}
ExceptionRegistryHub( ExceptionRegistryHub const& );
void operator=( ExceptionRegistryHub const& );
public: // IRegistryHub
ExceptionRegistryHub() {
}
virtual IReporterRegistry const& getReporterRegistry() const {
throw std::runtime_error("can't do this for Visual Studio tests!");
}
virtual ITestCaseRegistry const& getTestCaseRegistry() const {
throw std::runtime_error("can't do this for Visual Studio tests!");
}
virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() {
return m_exceptionTranslatorRegistry;
}
public: // IMutableRegistryHub
virtual void registerReporter( std::string const&, IReporterFactory* ) {
throw std::runtime_error("can't do this for Visual Studio tests!");
}
virtual void registerTest( TestCase const& ) {
throw std::runtime_error("can't do this for Visual Studio tests!");
}
virtual void registerTranslator( const IExceptionTranslator* translator ) {
m_exceptionTranslatorRegistry.registerTranslator( translator );
}
private:
ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
};
template <typename T>
struct GlobalRegistryHub
{
static T& instance()
{
if( !theRegistryHub )
theRegistryHub = new T();
return *theRegistryHub;
}
static T* theRegistryHub;
};
template <typename T>
T* GlobalRegistryHub<T>::theRegistryHub = NULL;
INTERNAL_CATCH_INLINE IMutableRegistryHub& getMutableRegistryHub() {
return GlobalRegistryHub<ExceptionRegistryHub>::instance();
}
INTERNAL_CATCH_INLINE std::string translateActiveException() {
return GlobalRegistryHub<ExceptionRegistryHub>::instance().getExceptionTranslatorRegistry().translateActiveException();
}
inline Matchers::Impl::StdString::Equals::~Equals() {}
inline Matchers::Impl::StdString::Contains::~Contains() {}
inline Matchers::Impl::StdString::StartsWith::~StartsWith() {}
inline Matchers::Impl::StdString::EndsWith::~EndsWith() {}
inline void Config::dummy() {}
}
#endif // INTERNAL_CATCH_VS_NATIVE

View File

@@ -16,27 +16,11 @@
#include "catch_common.h"
#include "catch_interfaces_testcase.h"
#include "internal/catch_compiler_capabilities.h"
#include "internal/clara.h"
#include <tchar.h>
namespace Catch {
typedef void(*TestFunction)();
class FreeFunctionTestCase : public SharedImpl<ITestCase> {
public:
FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {}
virtual void invoke() const {
m_fun();
}
private:
virtual ~FreeFunctionTestCase();
TestFunction m_fun;
};
class MethodTestCase : public SharedImpl<ITestCase> {
struct placeholder
@@ -79,7 +63,7 @@ private:
typedef void(*TestFunction)();
struct NameAndDesc {
#if (_MANAGED == 1) || (_M_CEE == 1) // detect CLR
#ifdef INTERNAL_CATCH_VS_MANAGED
NameAndDesc( const char* _name = "", const char* _description= "" )
: name( _name ), description( _description )
{}
@@ -90,14 +74,35 @@ struct NameAndDesc {
NameAndDesc( const wchar_t* _name, const char* _description= "" )
: name(), description( _description )
{
stdext::cvt::wstring_convert<std::codecvt_utf8<wchar_t> > conv1;
name = conv1.to_bytes(_name);
assignName(_name);
}
NameAndDesc( const wchar_t* _name, int )
: name(), description( "" )
{
assignName(_name);
}
void assignName(const wchar_t* _name)
{
stdext::cvt::wstring_convert<std::codecvt_utf8<wchar_t> > conv1;
name = conv1.to_bytes(_name);
std::string tmp = conv1.to_bytes(_name);
if( tmp.empty() )
{
name = tmp;
}
else
{
std::string::iterator startIter = tmp.begin();
if(*startIter == '\"')
{
++startIter;
}
std::string::reverse_iterator endIter = tmp.rbegin();
if(*endIter == '\"')
{
++endIter;
}
name.assign(startIter, endIter.base());
}
}
#endif
@@ -105,9 +110,38 @@ struct NameAndDesc {
std::string description;
};
struct AutoReg {
AutoReg( TestFunction function,
SourceLineInfo const& lineInfo,
NameAndDesc const& nameAndDesc );
template<typename C>
AutoReg( void (C::*method)(),
char const* className,
NameAndDesc const& nameAndDesc,
SourceLineInfo const& lineInfo ) {
registerTestCase( new MethodTestCase( method ),
className,
nameAndDesc,
lineInfo );
}
void registerTestCase( ITestCase* testCase,
char const* className,
NameAndDesc const& nameAndDesc,
SourceLineInfo const& lineInfo );
~AutoReg();
private:
AutoReg( AutoReg const& );
void operator= ( AutoReg const& );
};
} // end namespace Catch
#if (_MANAGED == 1) || (_M_CEE == 1) // detect CLR
#ifdef INTERNAL_CATCH_VS_MANAGED
#define CATCH_INTERNAL_HANDLE_EMPTY_PARAM2( name ) name##""
#define CATCH_INTERNAL_HANDLE_EMPTY_PARAM(...) CATCH_INTERNAL_HANDLE_EMPTY_PARAM2( INTERNAL_CATCH_SPLIT_ARGS_2(__VA_ARGS__) )
@@ -134,7 +168,7 @@ struct NameAndDesc {
#define CATCH_INTERNAL_NAMESPACE( Ext )
#define INTERNAL_CATCH_TEST_METHOD( Method, UniqueExt, Name, Desc ) \
#define INTERNAL_CATCH_TEST_METHOD( Count, UniqueExt, Name, Desc ) \
public: \
[TestMethod] \
[Description( CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Name) )] \
@@ -142,22 +176,24 @@ struct NameAndDesc {
void INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H___M_E_T_H_O_D___, UniqueExt) () \
{ \
Catch::NameAndDesc name_desc( CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Name), Desc ); \
CATCH_INTERNAL_RUN_SINGLE_TEST( Method ); \
CATCH_INTERNAL_RUN_SINGLE_TEST(Count); \
}
#define INTERNAL_CATCH_TEST_CLASS_METHOD( Method, UniqueExt, Name, Desc ) \
#define BEGIN_INTERNAL_CATCH_BATCH_METHOD( Tags, UniqueExt ) \
public: \
[TestMethod] \
[Description( CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Name) )] \
[TestProperty( "Description", CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Name) )] \
void INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H___M_E_T_H_O_D___, UniqueExt) () \
{ \
Catch::NameAndDesc name_desc( CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Name), Desc ); \
CATCH_INTERNAL_RUN_SINGLE_CLASS_TEST( Method ); \
}
[TestCategory( CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Tags) )] \
[Description( CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Tags) )] \
[TestProperty( "Description", CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Tags) )] \
void INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H___M_E_T_H_O_D___, UniqueExt) ()
#define CHECK_FOR_TEST_CASE_CLASH
#define INTERNAL_CATCH_MAP_CATEGORY_TO_TAG( Category, Tag ) \
INTERNAL_CATCH_MAP_CATEGORY_TO_TAG2( #Category, Tag, __COUNTER__ )
#define FAIL_STRING( str ) _T( str )
#else // detect CLR
// Native tests
@@ -173,99 +209,161 @@ struct NameAndDesc {
#define TEST_IMPL_2(tuple) TEST_IMPL2 tuple
#define TEST_IMPL2( INTERNAL_CATCH_SPLIT_ARG_1,INTERNAL_CATCH_SPLIT_ARG_2,N,...) L#INTERNAL_CATCH_SPLIT_ARG_1
#define CATCH_INTERNAL_HANDLE_EMPTY_PARAM(...) CATCH_INTERNAL_HANDLE_EMPTY_PARAM_IMPL( (__VA_ARGS__, 2, 1) )
#define CATCH_INTERNAL_HANDLE_EMPTY_PARAM_IMPL(tuple) CATCH_INTERNAL_HANDLE_EMPTY_PARAM_IMPL2 tuple
#define CATCH_INTERNAL_HANDLE_EMPTY_PARAM_IMPL2( INTERNAL_CATCH_SPLIT_ARG_1,INTERNAL_CATCH_SPLIT_ARG_2,N,...) #INTERNAL_CATCH_SPLIT_ARG_1
#define CATCH_INTERNAL_HANDLE_EMPTY_PARAMW(...) CATCH_INTERNAL_HANDLE_EMPTY_PARAM_IMPLW( (__VA_ARGS__, 2, 1) )
#define CATCH_INTERNAL_HANDLE_EMPTY_PARAM(...) CATCH_INTERNAL_HANDLE_EMPTY_PARAM_IMPLW( (__VA_ARGS__, 2, 1) )
#define CATCH_INTERNAL_HANDLE_EMPTY_PARAM_IMPLW(tuple) CATCH_INTERNAL_HANDLE_EMPTY_PARAM_IMPL2W tuple
#define CATCH_INTERNAL_HANDLE_EMPTY_PARAM_IMPL2W( INTERNAL_CATCH_SPLIT_ARG_1,INTERNAL_CATCH_SPLIT_ARG_2,N,...) L#INTERNAL_CATCH_SPLIT_ARG_1
#define INTERNAL_CATCH_TEST_METHOD( Method, UniqueExt, Name, Desc ) \
#define INTERNAL_CATCH_TEST_METHOD( Count, UniqueExt, Name, Desc ) \
public: \
BEGIN_TEST_METHOD_ATTRIBUTE( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H___M_E_T_H_O_D___, UniqueExt) ) \
TEST_OWNER( CATCH_INTERNAL_HANDLE_EMPTY_PARAMW(Name) ) \
TEST_DESCRIPTION( CATCH_INTERNAL_HANDLE_EMPTY_PARAMW(Name) ) \
TEST_OWNER( CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Name) ) \
TEST_DESCRIPTION( CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Name) ) \
END_TEST_METHOD_ATTRIBUTE() \
TEST_METHOD( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H___M_E_T_H_O_D___, UniqueExt) ) \
{ \
Catch::NameAndDesc name_desc(CATCH_INTERNAL_HANDLE_EMPTY_PARAMW(Name), Desc ); \
CATCH_INTERNAL_RUN_SINGLE_TEST( Method ); \
Catch::NameAndDesc name_desc(CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Name), Desc ); \
CATCH_INTERNAL_RUN_SINGLE_TEST(Count); \
}
#define INTERNAL_CATCH_TEST_CLASS_METHOD( Method, UniqueExt, Name, Desc ) \
#define BEGIN_INTERNAL_CATCH_BATCH_METHOD( Tags, UniqueExt ) \
public: \
BEGIN_TEST_METHOD_ATTRIBUTE( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H___M_E_T_H_O_D___, UniqueExt) ) \
TEST_OWNER( CATCH_INTERNAL_HANDLE_EMPTY_PARAMW(Name) ) \
TEST_DESCRIPTION( CATCH_INTERNAL_HANDLE_EMPTY_PARAMW(Name) ) \
END_TEST_METHOD_ATTRIBUTE() \
TEST_METHOD( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H___M_E_T_H_O_D___, UniqueExt) ) \
{ \
Catch::NameAndDesc name_desc( CATCH_INTERNAL_HANDLE_EMPTY_PARAMW(Name), Desc ); \
CATCH_INTERNAL_RUN_SINGLE_CLASS_TEST( Method ); \
}
BEGIN_TEST_METHOD_ATTRIBUTE( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H___M_E_T_H_O_D___, UniqueExt) ) \
TEST_OWNER( CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Tags) ) \
TEST_DESCRIPTION( CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Tags) ) \
END_TEST_METHOD_ATTRIBUTE() \
TEST_METHOD( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H___M_E_T_H_O_D___, UniqueExt) )
#define CHECK_FOR_TEST_CASE_CLASH void INTERNAL_CATCH_UNIQUE_NAME_LINE( if_you_get_this_error_you_have_a_test_case_name_clash_please_put_a_namespace_around_the_test_case_at_line_, __LINE__ )() {}
#define INTERNAL_CATCH_MAP_CATEGORY_TO_TAG( Category, Tag ) \
INTERNAL_CATCH_MAP_CATEGORY_TO_TAG2( Category, Tag, __COUNTER__ )
#define FAIL_STRING( str ) WIDEN( str )
#endif // detect CLR
#define INTERNAL_CATCH_CONCAT_LINE_COUNTER INTERNAL_CATCH_UNIQUE_NAME_LINE( INTERNAL_CATCH_UNIQUE_NAME_LINE( __LINE__, _ ), __COUNTER__ )
#define INTERNAL_CATCH_CONCAT_LINE_COUNTER( count ) INTERNAL_CATCH_UNIQUE_NAME_LINE( INTERNAL_CATCH_UNIQUE_NAME_LINE( __LINE__, _ ), count )
#define CATCH_INTERNAL_RUN_SINGLE_TEST( Method ) \
{ Catch::ConfigData cd; \
#define CATCH_INTERNAL_CONFIG_SHOW_SUCCESS2( v, Count ) \
namespace { CatchOverrides::ConfigShowSuccessfulTests<Catch::IConfig const*> INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H_____O_V_E_R_R_I_D_E____, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) )(__FILE__, Count, v); }
#define CATCH_INTERNAL_CONFIG_WARN_MISSING_ASSERTIONS2( v, Count ) \
namespace { CatchOverrides::ConfigWarnMissingAssertions<Catch::IConfig const*> INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H_____O_V_E_R_R_I_D_E____, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) )(__FILE__, Count, v); }
#define CATCH_INTERNAL_CONFIG_SHOW_SUCCESS( v ) \
CATCH_INTERNAL_CONFIG_SHOW_SUCCESS2( v, __COUNTER__)
#define CATCH_INTERNAL_CONFIG_WARN_MISSING_ASSERTIONS( v ) \
CATCH_INTERNAL_CONFIG_WARN_MISSING_ASSERTIONS2( v, __COUNTER__)
#define CATCH_INTERNAL_RUN_SINGLE_TEST( Count ) \
{ CatchOverrides::ConfigGuard cg; \
Catch::ConfigData cd(cg.value().get()); \
cd.name = name_desc.name; \
cd.abortAfter = 1; \
cd.showSuccessfulTests = CatchOverrides::Config<Catch::IConfig const*>::instance().includeSuccessfulResults(__FILE__, Count ); \
cd.warnings = (CatchOverrides::Config<Catch::IConfig const*>::instance().warnAboutMissingAssertions(__FILE__, Count ) ? Catch::WarnAbout::NoAssertions : Catch::WarnAbout::Nothing); \
Catch::Ptr<Catch::Config> config(new Catch::Config(cd)); \
Catch::MSTestReporter* rep = new Catch::MSTestReporter(config.get()); \
Catch::RunContext tr(config.get(), rep); \
Catch::TestCase tc = Catch::makeTestCase( new Catch::FreeFunctionTestCase( & Method ), "", name_desc.name, name_desc.description, CATCH_INTERNAL_LINEINFO ); \
tr.runTest(tc); \
std::vector<Catch::TestCase> testCase = Catch::getRegistryHub().getTestCaseRegistry().getMatchingTestCases(name_desc.name); \
if( testCase.empty() ) Assert::Fail(FAIL_STRING("No tests match")); \
if( testCase.size() > 1 ) Assert::Fail(FAIL_STRING("More than one test with the same name")); \
Catch::Totals totals = tr.runTest(*testCase.begin()); \
if( totals.assertions.failed > 0 ) { \
INTERNAL_CATCH_TEST_THROW_FAILURE \
} \
}
#define CATCH_INTERNAL_RUN_SINGLE_CLASS_TEST( ClassMethod ) \
{ Catch::ConfigData cd; \
cd.name = name_desc.name; \
Catch::Ptr<Catch::Config> config(new Catch::Config(cd)); \
Catch::MSTestReporter* rep = new Catch::MSTestReporter(config.get()); \
Catch::RunContext tr(config.get(), rep); \
Catch::TestCase tc = Catch::makeTestCase( new Catch::MethodTestCase( & ClassMethod ), # ClassMethod, name_desc.name, name_desc.description, CATCH_INTERNAL_LINEINFO ); \
tr.runTest(tc); \
}
#define INTERNAL_CATCH_TESTCASE2( UniqueExt, Name, Desc ) \
#define INTERNAL_CATCH_TESTCASE2( Count, Name, Desc ) \
CHECK_FOR_TEST_CASE_CLASH \
static void INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, UniqueExt )(); \
namespace CATCH_INTERNAL_NAMESPACE( UniqueExt ) { \
INTERNAL_CATCH_CLASS_DEFINITION( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____C_L_A_S_S___, UniqueExt ) ) \
static void INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) )(); \
namespace CATCH_INTERNAL_NAMESPACE( INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) ) { \
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( & INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc(CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Name), Desc) ); \
CatchOverrides::ConfigReset<Catch::IConfig const*> INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____C_O_N_F_I_G___, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) )(__FILE__, Count); \
INTERNAL_CATCH_CLASS_DEFINITION( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____C_L_A_S_S___, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) ) ) \
{ \
INTERNAL_CATCH_CLASS_CONTEXT \
INTERNAL_CATCH_TEST_METHOD( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, UniqueExt ), UniqueExt, Name, Desc ) \
INTERNAL_CATCH_TEST_METHOD( Count, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ), Name, Desc ) \
}; \
} \
void INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, UniqueExt )()
void INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) )()
#define INTERNAL_CATCH_METHOD_AS_TEST_CASE2( QualifiedMethod, UniqueExt, Name, Desc ) \
#define INTERNAL_CATCH_METHOD_AS_TEST_CASE2( QualifiedMethod, Count, Name, Desc ) \
CHECK_FOR_TEST_CASE_CLASH \
namespace CATCH_INTERNAL_NAMESPACE( UniqueExt ) { \
INTERNAL_CATCH_CLASS_DEFINITION( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____C_L_A_S_S___, UniqueExt ) ) \
namespace CATCH_INTERNAL_NAMESPACE( INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) ) { \
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( & QualifiedMethod, "&" # QualifiedMethod, Catch::NameAndDesc(CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Name), Desc), CATCH_INTERNAL_LINEINFO ); \
CatchOverrides::ConfigReset<Catch::IConfig const*> INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____C_O_N_F_I_G___, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) )(__FILE__, Count); \
INTERNAL_CATCH_CLASS_DEFINITION( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____C_L_A_S_S___, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) ) ) \
{ \
INTERNAL_CATCH_CLASS_CONTEXT \
INTERNAL_CATCH_TEST_CLASS_METHOD( QualifiedMethod, UniqueExt, Name, Desc ) \
INTERNAL_CATCH_TEST_METHOD( Count, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ), Name, Desc ) \
}; \
};
#define INTERNAL_CATCH_TEST_CASE_METHOD2( ClassName, UniqueExt, TestName, Desc ) \
#define INTERNAL_CATCH_TEST_CASE_METHOD2( ClassName, Count, TestName, Desc ) \
CHECK_FOR_TEST_CASE_CLASH \
struct INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, UniqueExt ) : ClassName { \
struct INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) ) : ClassName { \
void test(); \
static void invoke() { INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, UniqueExt ) tmp; tmp.test(); } \
static void invoke() { INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) ) tmp; tmp.test(); } \
}; \
namespace CATCH_INTERNAL_NAMESPACE( UniqueExt ) { \
INTERNAL_CATCH_CLASS_DEFINITION( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____C_L_A_S_S___, UniqueExt ) ) \
namespace CATCH_INTERNAL_NAMESPACE( INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) ) { \
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( & INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) )::invoke, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc(CATCH_INTERNAL_HANDLE_EMPTY_PARAM(TestName), Desc) ); \
CatchOverrides::ConfigReset<Catch::IConfig const*> INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____C_O_N_F_I_G___, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) )(__FILE__, Count); \
INTERNAL_CATCH_CLASS_DEFINITION( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____C_L_A_S_S___, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) ) ) \
{ \
INTERNAL_CATCH_CLASS_CONTEXT \
INTERNAL_CATCH_TEST_METHOD( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, UniqueExt )::invoke, UniqueExt, TestName, Desc ) \
INTERNAL_CATCH_TEST_METHOD( Count, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ), TestName, Desc ) \
}; \
} \
void INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, UniqueExt )::test()
void INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) )::test()
#if defined(INTERNAL_CATCH_VS_MANAGED)
#define INTERNAL_CATCH_TEST_REPORT_BATCH_FAILURE( count ) \
{ \
std::stringstream _sf; \
_sf << count << " assertions failed - check output for results."; \
std::string fail = _sf.str(); \
Assert::Fail(Catch::convert_string_for_assert(fail)); \
}
#else
#define INTERNAL_CATCH_TEST_REPORT_BATCH_FAILURE( count ) \
{ \
std::wstringstream _s; \
_s << count << " assertions failed - check output for results."; \
std::wstring ws = _s.str(); \
Assert::Fail(ws.c_str()); \
}
#endif
#define INTERNAL_CATCH_MAP_CATEGORY_TO_TAG2( Category, Tag, Count ) \
CHECK_FOR_TEST_CASE_CLASH \
namespace CATCH_INTERNAL_NAMESPACE( INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) ) { \
CatchOverrides::ConfigReset<Catch::IConfig const*> INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____C_O_N_F_I_G___, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) )(__FILE__, Count); \
INTERNAL_CATCH_CLASS_DEFINITION( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____C_L_A_S_S___, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) ) ) \
{ \
INTERNAL_CATCH_CLASS_CONTEXT \
BEGIN_INTERNAL_CATCH_BATCH_METHOD( Category, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) ) \
{ \
Catch::ConfigData cd; \
cd.showSuccessfulTests = CatchOverrides::Config<Catch::IConfig const*>::instance().includeSuccessfulResults(__FILE__, Count ); \
cd.warnings = (CatchOverrides::Config<Catch::IConfig const*>::instance().warnAboutMissingAssertions(__FILE__, Count ) ? Catch::WarnAbout::NoAssertions : Catch::WarnAbout::Nothing); \
cd.reporterName = "vs_reporter"; \
cd.name = "Batch run using tag : " Tag; \
cd.testsOrTags.push_back( Tag ); \
Catch::Ptr<Catch::Config> config(new Catch::Config(cd)); \
Catch::ReporterRegistrar<Catch::MSTestReporter> reporterReg("vs_reporter"); \
Catch::Runner runner(config); \
Catch::Totals totals = runner.runTests(); \
if( totals.assertions.failed > 0 ) { \
INTERNAL_CATCH_TEST_REPORT_BATCH_FAILURE(totals.assertions.failed) \
} \
} \
}; \
}
//#undef CATCH_CONFIG_VARIADIC_MACROS
@@ -279,29 +377,29 @@ struct NameAndDesc {
#define INTERNAL_CATCH_SPLIT_TAGS_IMPL_(INTERNAL_CATCH_SPLIT_ARG_1,INTERNAL_CATCH_SPLIT_ARG_2,N,...) INTERNAL_CATCH_SPLIT_ARG_2
#define INTERNAL_CATCH_TESTCASE( ... ) \
INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_CONCAT_LINE_COUNTER, INTERNAL_CATCH_SPLIT_ARGS_2(__VA_ARGS__), INTERNAL_CATCH_SPLIT_TAGS(__VA_ARGS__) )
INTERNAL_CATCH_TESTCASE2( __COUNTER__ , INTERNAL_CATCH_SPLIT_ARGS_2(__VA_ARGS__), INTERNAL_CATCH_SPLIT_TAGS(__VA_ARGS__) )
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
INTERNAL_CATCH_METHOD_AS_TEST_CASE2( QualifiedMethod, INTERNAL_CATCH_CONCAT_LINE_COUNTER, INTERNAL_CATCH_SPLIT_ARGS_2(__VA_ARGS__), INTERNAL_CATCH_SPLIT_TAGS(__VA_ARGS__) )
INTERNAL_CATCH_METHOD_AS_TEST_CASE2( QualifiedMethod, __COUNTER__, INTERNAL_CATCH_SPLIT_ARGS_2(__VA_ARGS__), INTERNAL_CATCH_SPLIT_TAGS(__VA_ARGS__) )
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... )\
INTERNAL_CATCH_TEST_CASE_METHOD2(ClassName, INTERNAL_CATCH_CONCAT_LINE_COUNTER, INTERNAL_CATCH_SPLIT_ARGS_2(__VA_ARGS__), INTERNAL_CATCH_SPLIT_TAGS(__VA_ARGS__) )
INTERNAL_CATCH_TEST_CASE_METHOD2(ClassName, __COUNTER__, INTERNAL_CATCH_SPLIT_ARGS_2(__VA_ARGS__), INTERNAL_CATCH_SPLIT_TAGS(__VA_ARGS__) )
#else
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_CONCAT_LINE_COUNTER, Name, Desc )
INTERNAL_CATCH_TESTCASE2( __COUNTER__ , Name, Desc )
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
INTERNAL_CATCH_METHOD_AS_TEST_CASE2( QualifiedMethod, INTERNAL_CATCH_CONCAT_LINE_COUNTER, Name, Desc )
INTERNAL_CATCH_METHOD_AS_TEST_CASE2( QualifiedMethod, __COUNTER__, Name, Desc )
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
INTERNAL_CATCH_TEST_CASE_METHOD2(ClassName, INTERNAL_CATCH_CONCAT_LINE_COUNTER, TestName, Desc )
INTERNAL_CATCH_TEST_CASE_METHOD2(ClassName, __COUNTER__, TestName, Desc )
#endif
@@ -320,51 +418,6 @@ struct NameAndDesc {
#include "catch_exception_translator_registry.hpp"
namespace Catch {
inline NonCopyable::~NonCopyable() {}
inline IShared::~IShared() {}
inline StreamBufBase::~StreamBufBase() throw() {}
inline IContext::~IContext() {}
inline IResultCapture::~IResultCapture() {}
inline ITestCase::~ITestCase() {}
inline ITestCaseRegistry::~ITestCaseRegistry() {}
inline IRegistryHub::~IRegistryHub() {}
inline IMutableRegistryHub::~IMutableRegistryHub() {}
inline IExceptionTranslator::~IExceptionTranslator() {}
inline IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {}
inline IReporterFactory::~IReporterFactory() {}
inline IReporterRegistry::~IReporterRegistry() {}
inline IStreamingReporter::~IStreamingReporter() {}
inline AssertionStats::~AssertionStats() {}
inline SectionStats::~SectionStats() {}
inline TestCaseStats::~TestCaseStats() {}
inline TestGroupStats::~TestGroupStats() {}
inline TestRunStats::~TestRunStats() {}
//CumulativeReporterBase::SectionNode::~SectionNode() {}
//CumulativeReporterBase::~CumulativeReporterBase() {}
//StreamingReporterBase::~StreamingReporterBase() {}
//ConsoleReporter::~ConsoleReporter() {}
inline IRunner::~IRunner() {}
inline IMutableContext::~IMutableContext() {}
inline IConfig::~IConfig() {}
//XmlReporter::~XmlReporter() {}
//JunitReporter::~JunitReporter() {}
//TestRegistry::~TestRegistry() {}
inline FreeFunctionTestCase::~FreeFunctionTestCase() {}
inline IGeneratorInfo::~IGeneratorInfo() {}
inline IGeneratorsForTest::~IGeneratorsForTest() {}
inline Matchers::Impl::StdString::Equals::~Equals() {}
inline Matchers::Impl::StdString::Contains::~Contains() {}
inline Matchers::Impl::StdString::StartsWith::~StartsWith() {}
inline Matchers::Impl::StdString::EndsWith::~EndsWith() {}
inline void Config::dummy() {}
//INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( "xml", XmlReporter )
}
#ifdef __clang__
#pragma clang diagnostic pop
#endif

View File

@@ -46,15 +46,27 @@ namespace Catch {
#endif // detect CLR
struct MSTestReporter : SharedImpl<IStreamingReporter> {
MSTestReporter( ReporterConfig const& _config )
: m_config( _config.fullConfig() ),
m_headerPrinted( false ),
m_atLeastOneTestCasePrinted( false ),
m_failed(0)
{}
MSTestReporter( Ptr<IConfig> const& _fullConfig )
: m_config( _fullConfig ),
m_headerPrinted( false ),
m_atLeastOneTestCasePrinted( false )
m_atLeastOneTestCasePrinted( false ),
m_failed(0)
{}
virtual ~MSTestReporter() {
if( m_atLeastOneTestCasePrinted ) {
write_output_message(stream.str());
/*if( m_failed )
{
Assert::IsTrue(false, L"At least one test failed - examine output for failures.");
}*/
}
}
@@ -120,9 +132,6 @@ namespace Catch {
write_output_message(_testCaseStats.stdErr);
write_output_message(getDoubleDashes());
}
if( _testCaseStats.totals.assertions.failed ) {
Assert::IsTrue(false, L"At least one test failed - examine output for CHECK failures.");
}
m_headerPrinted = false;
currentTestCaseInfo.reset();
assert( m_sectionStack.empty() );
@@ -141,6 +150,7 @@ namespace Catch {
printTotalsDivider();
printTotals( _testRunStats.totals );
stream << "\r\n" << "\r\n";
m_failed = _testRunStats.totals.testCases.failed;
currentTestCaseInfo.reset();
currentGroupInfo.reset();
currentTestRunInfo.reset();
@@ -448,6 +458,7 @@ namespace Catch {
std::vector<SectionInfo> m_sectionStack;
bool m_headerPrinted;
bool m_atLeastOneTestCasePrinted;
size_t m_failed;
};
} // end namespace Catch