diff --git a/.gitignore b/.gitignore index 45fc0fa8..f256957d 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ Debug Release ipch TestResults +projects/VS2010/TestCatch/Visual Lint *.user *.xcuserstate *.o diff --git a/include/internal/catch_registry_hub.hpp b/include/internal/catch_registry_hub.hpp index 303a843a..a0d1df1e 100644 --- a/include/internal/catch_registry_hub.hpp +++ b/include/internal/catch_registry_hub.hpp @@ -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 + struct GlobalRegistryHub + { + static T*& instance() + { if( !theRegistryHub ) - theRegistryHub = new RegistryHub(); + theRegistryHub = new T(); return theRegistryHub; } - } + static T* theRegistryHub; + }; + template + T* GlobalRegistryHub::theRegistryHub = NULL; - IRegistryHub& getRegistryHub() { - return *getTheRegistryHub(); + INTERNAL_CATCH_INLINE IRegistryHub& getRegistryHub() { + return *GlobalRegistryHub::instance(); } - IMutableRegistryHub& getMutableRegistryHub() { - return *getTheRegistryHub(); + INTERNAL_CATCH_INLINE IMutableRegistryHub& getMutableRegistryHub() { + return *GlobalRegistryHub::instance(); } - void cleanUp() { - delete getTheRegistryHub(); - getTheRegistryHub() = NULL; + INTERNAL_CATCH_INLINE void cleanUp() { + delete GlobalRegistryHub::instance(); + GlobalRegistryHub::instance() = NULL; cleanUpContext(); } - std::string translateActiveException() { + INTERNAL_CATCH_INLINE std::string translateActiveException() { return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); } diff --git a/include/internal/catch_runner_impl.hpp b/include/internal/catch_runner_impl.hpp index bd392f94..eff066f6 100644 --- a/include/internal/catch_runner_impl.hpp +++ b/include/internal/catch_runner_impl.hpp @@ -279,7 +279,8 @@ namespace Catch { } #ifdef INTERNAL_CATCH_VS_MANAGED // detect CLR catch(AssertFailedException^) { - throw; // CLR always rethrows - stop on first assert + if( aborting() ) + throw; // CLR always rethrows - stop on first assert } #else catch( INTERNAL_CATCH_TEST_FAILURE_EXCEPTION ) { diff --git a/include/internal/catch_test_case_registry_impl.hpp b/include/internal/catch_test_case_registry_impl.hpp index 41714bc8..3fc0680c 100644 --- a/include/internal/catch_test_case_registry_impl.hpp +++ b/include/internal/catch_test_case_registry_impl.hpp @@ -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 ) { diff --git a/include/internal/catch_vs_managed_impl.hpp b/include/internal/catch_vs_managed_impl.hpp index df7043a3..7991091f 100644 --- a/include/internal/catch_vs_managed_impl.hpp +++ b/include/internal/catch_vs_managed_impl.hpp @@ -27,11 +27,12 @@ namespace Catch { } #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_exception_translator_registry.hpp" - +//#define OLD (1) +#ifdef OLD namespace Catch { class ExceptionRegistryHub : public IRegistryHub, public IMutableRegistryHub { @@ -70,11 +71,11 @@ namespace Catch { template struct GlobalRegistryHub { - static T& instance() + static T*& instance() { if( !theRegistryHub ) theRegistryHub = new T(); - return *theRegistryHub; + return theRegistryHub; } static T* theRegistryHub; }; @@ -82,13 +83,64 @@ namespace Catch { T* GlobalRegistryHub::theRegistryHub = NULL; INTERNAL_CATCH_INLINE IMutableRegistryHub& getMutableRegistryHub() { - return GlobalRegistryHub::instance(); + return *GlobalRegistryHub::instance(); } INTERNAL_CATCH_INLINE std::string translateActiveException() { - return GlobalRegistryHub::instance().getExceptionTranslatorRegistry().translateActiveException(); + return GlobalRegistryHub::instance()->getExceptionTranslatorRegistry().translateActiveException(); } } +#endif // OLD + +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() {} + //CumulativeReporterBase::SectionNode::~SectionNode() {} + //CumulativeReporterBase::~CumulativeReporterBase() {} + + //StreamingReporterBase::~StreamingReporterBase() {} + //ConsoleReporter::~ConsoleReporter() {} + inline IRunner::~IRunner() {} + inline IMutableContext::~IMutableContext() {} + inline IConfig::~IConfig() {} + //XmlReporter::~XmlReporter() {} + //JunitReporter::~JunitReporter() {} + inline TestRegistry::~TestRegistry() {} + inline FreeFunctionTestCase::~FreeFunctionTestCase() {} + inline IGeneratorInfo::~IGeneratorInfo() {} + inline IGeneratorsForTest::~IGeneratorsForTest() {} + inline TagParser::~TagParser() {} + inline TagExtracter::~TagExtracter() {} + inline TagExpressionParser::~TagExpressionParser() {} + + 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 ) +} + #endif #endif // TWOBLUECUBES_CATCH_VS_MANAGED_HPP_INCLUDED diff --git a/include/internal/catch_vs_test_registry.hpp b/include/internal/catch_vs_test_registry.hpp index ee1e022b..dfc09c20 100644 --- a/include/internal/catch_vs_test_registry.hpp +++ b/include/internal/catch_vs_test_registry.hpp @@ -16,27 +16,11 @@ #include "catch_common.h" #include "catch_interfaces_testcase.h" #include "internal/catch_compiler_capabilities.h" +#include "internal/clara.h" #include namespace Catch { - typedef void(*TestFunction)(); - - class FreeFunctionTestCase : public SharedImpl { - public: - - FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {} - - virtual void invoke() const { - m_fun(); - } - - private: - virtual ~FreeFunctionTestCase(); - - TestFunction m_fun; - }; - class MethodTestCase : public SharedImpl { struct placeholder @@ -105,6 +89,35 @@ struct NameAndDesc { std::string description; }; +struct AutoReg { + + AutoReg( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ); + + template + 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 @@ -213,27 +226,34 @@ struct NameAndDesc { #define CATCH_INTERNAL_RUN_SINGLE_TEST( Method ) \ { Catch::ConfigData cd; \ cd.name = name_desc.name; \ + cd.abortAfter = 1; \ Catch::Ptr 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 testCase = Catch::getRegistryHub().getTestCaseRegistry().getMatchingTestCases(name_desc.name); \ + if( testCase.empty() ) Assert::Fail("No tests match"); \ + if( testCase.size() > 1 ) Assert::Fail("More than one test with the same name"); \ + tr.runTest(*testCase.begin()); \ } #define CATCH_INTERNAL_RUN_SINGLE_CLASS_TEST( ClassMethod ) \ { Catch::ConfigData cd; \ cd.name = name_desc.name; \ + cd.abortAfter = 1; \ Catch::Ptr 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); \ + std::vector testCase = Catch::getRegistryHub().getTestCaseRegistry().getMatchingTestCases(name_desc.name); \ + if( testCase.empty() ) Assert::Fail("No tests match"); \ + if( testCase.size() > 1 ) Assert::Fail("More than one test with the same name"); \ + tr.runTest(*testCase.begin()); \ } #define INTERNAL_CATCH_TESTCASE2( UniqueExt, 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 ) { \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( & INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, UniqueExt ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc(Name, Desc) ); \ INTERNAL_CATCH_CLASS_DEFINITION( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____C_L_A_S_S___, UniqueExt ) ) \ { \ INTERNAL_CATCH_CLASS_CONTEXT \ @@ -245,6 +265,7 @@ struct NameAndDesc { #define INTERNAL_CATCH_METHOD_AS_TEST_CASE2( QualifiedMethod, UniqueExt, Name, Desc ) \ CHECK_FOR_TEST_CASE_CLASH \ namespace CATCH_INTERNAL_NAMESPACE( UniqueExt ) { \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( & QualifiedMethod, "&" # QualifiedMethod, Catch::NameAndDesc(Name, Desc), CATCH_INTERNAL_LINEINFO ); \ INTERNAL_CATCH_CLASS_DEFINITION( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____C_L_A_S_S___, UniqueExt ) ) \ { \ INTERNAL_CATCH_CLASS_CONTEXT \ @@ -259,6 +280,7 @@ struct NameAndDesc { static void invoke() { INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, UniqueExt ) tmp; tmp.test(); } \ }; \ namespace CATCH_INTERNAL_NAMESPACE( UniqueExt ) { \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( & INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, UniqueExt )::invoke, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc(TestName, Desc) ); \ INTERNAL_CATCH_CLASS_DEFINITION( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____C_L_A_S_S___, UniqueExt ) ) \ { \ INTERNAL_CATCH_CLASS_CONTEXT \ @@ -320,55 +342,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 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() {} - //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 TagParser::~TagParser() {} - inline TagExtracter::~TagExtracter() {} - inline TagExpressionParser::~TagExpressionParser() {} - - 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 diff --git a/include/reporters/catch_vs_reporter.hpp b/include/reporters/catch_vs_reporter.hpp index 29f0be57..0f9c9966 100644 --- a/include/reporters/catch_vs_reporter.hpp +++ b/include/reporters/catch_vs_reporter.hpp @@ -46,6 +46,12 @@ namespace Catch { #endif // detect CLR struct MSTestReporter : SharedImpl { + MSTestReporter( ReporterConfig const& _config ) + : m_config( _config.fullConfig() ), + m_headerPrinted( false ), + m_atLeastOneTestCasePrinted( false ) + {} + MSTestReporter( Ptr const& _fullConfig ) : m_config( _fullConfig ), m_headerPrinted( false ),