diff --git a/include/catch.hpp b/include/catch.hpp index 666d5dd1..714b00e1 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -15,7 +15,6 @@ #include "internal/catch_generators.hpp" #include "internal/catch_interfaces_exception.h" #include "internal/catch_approx.hpp" -#include "internal/catch_test_case_info.hpp" #include "internal/catch_matchers.hpp" #ifdef __OBJC__ diff --git a/include/catch_runner.hpp b/include/catch_runner.hpp index eda59e6f..ed16b342 100644 --- a/include/catch_runner.hpp +++ b/include/catch_runner.hpp @@ -62,7 +62,9 @@ namespace Catch { config.getReporter()->EndGroup( *it, runner.getTotals() - prevTotals ); } } - return static_cast( runner.getTotals().assertions.failed ); + int result = static_cast( runner.getTotals().assertions.failed ); + Catch::Context::cleanUp(); + return result; } inline void showHelp( std::string exeName ) { @@ -87,25 +89,25 @@ namespace Catch { if( !config.getMessage().empty() ) { std::cerr << config.getMessage() << std::endl; + Catch::Context::cleanUp(); return (std::numeric_limits::max)(); } // Handle help if( config.showHelp() ) { showHelp( argv[0] ); + Catch::Context::cleanUp(); return 0; } - return Main( config ); } inline int Main( int argc, char* const argv[] ) { Config config; +// !TBD: This doesn't always work, for some reason // if( isDebuggerActive() ) // config.useStream( "debug" ); - int result = Main( argc, argv, config ); - Catch::Context::cleanUp(); - return result; + return Main( argc, argv, config ); } } // end namespace Catch diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index 688f8455..0724b089 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -22,11 +22,11 @@ struct TestFailureException{}; class ScopedInfo { public: ScopedInfo() : m_oss() { - Context::getResultCapture().pushScopedInfo( this ); + getCurrentContext().getResultCapture().pushScopedInfo( this ); } ~ScopedInfo() { - Context::getResultCapture().popScopedInfo( this ); + getCurrentContext().getResultCapture().popScopedInfo( this ); } template @@ -50,7 +50,7 @@ inline bool isTrue( bool value ){ return value; } /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_ACCEPT_EXPR( expr, stopOnFailure, originalExpr ) \ - if( Catch::ResultAction::Value internal_catch_action = Catch::Context::getResultCapture().acceptExpression( expr ) ) \ + if( Catch::ResultAction::Value internal_catch_action = Catch::getCurrentContext().getResultCapture().acceptExpression( expr ) ) \ { \ if( internal_catch_action == Catch::ResultAction::DebugFailed ) BreakIntoDebugger(); \ if( Catch::isTrue( stopOnFailure ) ) throw Catch::TestFailureException(); \ @@ -64,19 +64,19 @@ inline bool isTrue( bool value ){ return value; } }catch( Catch::TestFailureException& ){ \ throw; \ } catch( ... ){ \ - INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ) << Catch::Context::getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), false, expr ); \ + INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ) << Catch::getCurrentContext().getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), false, expr ); \ throw; \ }}while( Catch::isTrue( false ) ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_IF( expr, isNot, stopOnFailure, macroName ) \ INTERNAL_CATCH_TEST( expr, isNot, stopOnFailure, macroName ); \ - if( Catch::Context::getResultCapture().getLastResult()->ok() ) + if( Catch::getCurrentContext().getResultCapture().getLastResult()->ok() ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_ELSE( expr, isNot, stopOnFailure, macroName ) \ INTERNAL_CATCH_TEST( expr, isNot, stopOnFailure, macroName ); \ - if( !Catch::Context::getResultCapture().getLastResult()->ok() ) + if( !Catch::getCurrentContext().getResultCapture().getLastResult()->ok() ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_NO_THROW( expr, stopOnFailure, macroName ) \ @@ -87,7 +87,7 @@ inline bool isTrue( bool value ){ return value; } } \ catch( ... ) \ { \ - INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ) << Catch::Context::getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), stopOnFailure, false ); \ + INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ) << Catch::getCurrentContext().getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), stopOnFailure, false ); \ } /////////////////////////////////////////////////////////////////////////////// @@ -111,12 +111,12 @@ inline bool isTrue( bool value ){ return value; } INTERNAL_CATCH_THROWS( expr, exceptionType, stopOnFailure, macroName ) \ catch( ... ) \ { \ - INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ) << Catch::Context::getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), stopOnFailure, false ); \ + INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ) << Catch::getCurrentContext().getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), stopOnFailure, false ); \ } /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_MSG( reason, resultType, stopOnFailure, macroName ) \ - Catch::Context::getResultCapture().acceptExpression( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName ) << reason ).setResultType( resultType ) ); + Catch::getCurrentContext().getResultCapture().acceptExpression( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName ) << reason ).setResultType( resultType ) ); /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_SCOPED_INFO( log ) \ @@ -130,7 +130,7 @@ inline bool isTrue( bool value ){ return value; } }catch( Catch::TestFailureException& ){ \ throw; \ } catch( ... ){ \ - INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #arg " " #matcher ) << Catch::Context::getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), false, false ); \ + INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #arg " " #matcher ) << Catch::getCurrentContext().getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), false, false ); \ throw; \ }}while( Catch::isTrue( false ) ) diff --git a/include/internal/catch_config.hpp b/include/internal/catch_config.hpp index 6f26a64d..d6bd0819 100644 --- a/include/internal/catch_config.hpp +++ b/include/internal/catch_config.hpp @@ -62,7 +62,7 @@ namespace Catch { void setReporter( const std::string& reporterName ) { if( m_reporter.get() ) return setError( "Only one reporter may be specified" ); - setReporter( Context::getReporterRegistry().create( reporterName, *this ) ); + setReporter( getCurrentContext().getReporterRegistry().create( reporterName, *this ) ); } void addTestSpec( const std::string& testSpec ) { @@ -107,7 +107,7 @@ namespace Catch { Ptr getReporter() { if( !m_reporter.get() ) - const_cast( this )->setReporter( Context::getReporterRegistry().create( "basic", *this ) ); + const_cast( this )->setReporter( getCurrentContext().getReporterRegistry().create( "basic", *this ) ); return m_reporter; } diff --git a/include/internal/catch_context.h b/include/internal/catch_context.h index 1e3711e7..6d0052f9 100644 --- a/include/internal/catch_context.h +++ b/include/internal/catch_context.h @@ -25,28 +25,56 @@ namespace Catch { class StreamBufBase : public std::streambuf{}; - class Context { + struct IContext + { + virtual IResultCapture& getResultCapture() = 0; + virtual IRunner& getRunner() = 0; + virtual IReporterRegistry& getReporterRegistry() = 0; + virtual ITestCaseRegistry& getTestCaseRegistry() = 0; + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; + virtual size_t getGeneratorIndex( const std::string& fileInfo, size_t totalSize ) = 0; + virtual bool advanceGeneratorsForCurrentTest() = 0; + }; - Context(); + struct IMutableContext : IContext + { + virtual void setResultCapture( IResultCapture* resultCapture ) = 0; + virtual void setRunner( IRunner* runner ) = 0; + }; + + IContext& getCurrentContext(); + IMutableContext& getCurrentMutableContext(); + + class Context : public IMutableContext { + + Context(); Context( const Context& ); void operator=( const Context& ); - static Context& me(); - public: - static void setRunner( IRunner* runner ); - static void setResultCapture( IResultCapture* resultCapture ); - static IResultCapture& getResultCapture(); - static IReporterRegistry& getReporterRegistry(); - static ITestCaseRegistry& getTestCaseRegistry(); - static IExceptionTranslatorRegistry& getExceptionTranslatorRegistry(); + public: // friends + friend IContext& getCurrentContext() { return Context::getCurrent(); } + friend IMutableContext& getCurrentMutableContext() { return Context::getCurrent(); } + + public: // IContext + virtual IResultCapture& getResultCapture(); + virtual IRunner& getRunner(); + virtual IReporterRegistry& getReporterRegistry(); + virtual ITestCaseRegistry& getTestCaseRegistry(); + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry(); + virtual size_t getGeneratorIndex( const std::string& fileInfo, size_t totalSize ); + virtual bool advanceGeneratorsForCurrentTest(); + + public: // IMutableContext + virtual void setResultCapture( IResultCapture* resultCapture ); + virtual void setRunner( IRunner* runner ); + + public: // Statics static std::streambuf* createStreamBuf( const std::string& streamName ); - static IRunner& getRunner(); - static size_t getGeneratorIndex( const std::string& fileInfo, size_t totalSize ); - static bool advanceGeneratorsForCurrentTest(); static void cleanUp(); private: - static Context*& singleInstance(); + static Context& getCurrent(); + static Context*& singleInstance(); GeneratorsForTest* findGeneratorsForCurrentTest(); GeneratorsForTest& getGeneratorsForCurrentTest(); diff --git a/include/internal/catch_context_impl.hpp b/include/internal/catch_context_impl.hpp index b807f4db..83b52869 100644 --- a/include/internal/catch_context_impl.hpp +++ b/include/internal/catch_context_impl.hpp @@ -17,13 +17,20 @@ namespace Catch { + + Context::Context() : m_reporterRegistry( new ReporterRegistry ), m_testCaseRegistry( new TestRegistry ), m_exceptionTranslatorRegistry( new ExceptionTranslatorRegistry ) {} - Context& Context::me() { + Context*& Context::singleInstance() { + static Context* hub = NULL; + return hub; + } + + Context& Context::getCurrent() { Context*& hub = singleInstance(); if( !hub ) hub = new Context(); @@ -36,37 +43,32 @@ namespace Catch { hub = NULL; } - Context*& Context::singleInstance() { - static Context* hub = NULL; - return hub; - } - void Context::setRunner( IRunner* runner ) { - me().m_runner = runner; + m_runner = runner; } void Context::setResultCapture( IResultCapture* resultCapture ) { - me().m_resultCapture = resultCapture; + m_resultCapture = resultCapture; } IResultCapture& Context::getResultCapture() { - return *me().m_resultCapture; + return *m_resultCapture; } IRunner& Context::getRunner() { - return *me().m_runner; + return *m_runner; } IReporterRegistry& Context::getReporterRegistry() { - return *me().m_reporterRegistry.get(); + return *m_reporterRegistry.get(); } ITestCaseRegistry& Context::getTestCaseRegistry() { - return *me().m_testCaseRegistry.get(); + return *m_testCaseRegistry.get(); } IExceptionTranslatorRegistry& Context::getExceptionTranslatorRegistry() { - return *me().m_exceptionTranslatorRegistry.get(); + return *m_exceptionTranslatorRegistry.get(); } std::streambuf* Context::createStreamBuf( const std::string& streamName ) { @@ -78,7 +80,7 @@ namespace Catch { } GeneratorsForTest* Context::findGeneratorsForCurrentTest() { - std::string testName = getResultCapture().getCurrentTestName(); + std::string testName = getCurrentContext().getResultCapture().getCurrentTestName(); std::map::const_iterator it = m_generatorsByTestName.find( testName ); @@ -90,7 +92,7 @@ namespace Catch { GeneratorsForTest& Context::getGeneratorsForCurrentTest() { GeneratorsForTest* generators = findGeneratorsForCurrentTest(); if( !generators ) { - std::string testName = getResultCapture().getCurrentTestName(); + std::string testName = getCurrentContext().getResultCapture().getCurrentTestName(); generators = new GeneratorsForTest(); m_generatorsByTestName.insert( std::make_pair( testName, generators ) ); } @@ -98,13 +100,13 @@ namespace Catch { } size_t Context::getGeneratorIndex( const std::string& fileInfo, size_t totalSize ) { - return me().getGeneratorsForCurrentTest() + return getGeneratorsForCurrentTest() .getGeneratorInfo( fileInfo, totalSize ) .getCurrentIndex(); } bool Context::advanceGeneratorsForCurrentTest() { - GeneratorsForTest* generators = me().findGeneratorsForCurrentTest(); + GeneratorsForTest* generators = findGeneratorsForCurrentTest(); return generators && generators->moveNext(); } } diff --git a/include/internal/catch_evaluate.hpp b/include/internal/catch_evaluate.hpp index 78472f6b..686e0b30 100644 --- a/include/internal/catch_evaluate.hpp +++ b/include/internal/catch_evaluate.hpp @@ -20,26 +20,13 @@ namespace Internal { IsGreaterThanOrEqualTo }; - template - struct OperatorTraits{ static const char* getName(){ return "*error - unknown operator*"; } }; - - template<> - struct OperatorTraits{ static const char* getName(){ return "=="; } }; - - template<> - struct OperatorTraits{ static const char* getName(){ return "!="; } }; - - template<> - struct OperatorTraits{ static const char* getName(){ return "<"; } }; - - template<> - struct OperatorTraits{ static const char* getName(){ return ">"; } }; - - template<> - struct OperatorTraits{ static const char* getName(){ return "<="; } }; - - template<> - struct OperatorTraits{ static const char* getName(){ return ">="; } }; + template struct OperatorTraits { static const char* getName(){ return "*error*"; } }; + template<> struct OperatorTraits { static const char* getName(){ return "=="; } }; + template<> struct OperatorTraits { static const char* getName(){ return "!="; } }; + template<> struct OperatorTraits { static const char* getName(){ return "<"; } }; + template<> struct OperatorTraits { static const char* getName(){ return ">"; } }; + template<> struct OperatorTraits { static const char* getName(){ return "<="; } }; + template<> struct OperatorTraits{ static const char* getName(){ return ">="; } }; // So the compare overloads can be operator agnostic we convey the operator as a template // enum, which is used to specialise an Evaluator for doing the comparison. diff --git a/include/internal/catch_generators.hpp b/include/internal/catch_generators.hpp index 6c72c397..295db35d 100644 --- a/include/internal/catch_generators.hpp +++ b/include/internal/catch_generators.hpp @@ -87,7 +87,7 @@ public: } operator T () const { - size_t overallIndex = Context::getGeneratorIndex( m_fileInfo, m_totalSize ); + size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize ); typename std::vector*>::const_iterator it = m_composed.begin(); typename std::vector*>::const_iterator itEnd = m_composed.end(); diff --git a/include/internal/catch_interfaces_exception.h b/include/internal/catch_interfaces_exception.h index 9c699583..3bb23ebd 100644 --- a/include/internal/catch_interfaces_exception.h +++ b/include/internal/catch_interfaces_exception.h @@ -51,7 +51,7 @@ namespace Catch { public: template ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) { - Catch::Context::getExceptionTranslatorRegistry().registerTranslator + getCurrentContext().getExceptionTranslatorRegistry().registerTranslator ( new ExceptionTranslator( translateFunction ) ); } }; diff --git a/include/internal/catch_list.hpp b/include/internal/catch_list.hpp index 773547f5..266a12b3 100644 --- a/include/internal/catch_list.hpp +++ b/include/internal/catch_list.hpp @@ -14,10 +14,11 @@ namespace Catch { inline int List( Config& config ) { + IContext& context = getCurrentContext(); if( config.listWhat() & Config::List::Reports ) { std::cout << "Available reports:\n"; - IReporterRegistry::FactoryMap::const_iterator it = Context::getReporterRegistry().getFactories().begin(); - IReporterRegistry::FactoryMap::const_iterator itEnd = Context::getReporterRegistry().getFactories().end(); + IReporterRegistry::FactoryMap::const_iterator it = context.getReporterRegistry().getFactories().begin(); + IReporterRegistry::FactoryMap::const_iterator itEnd = context.getReporterRegistry().getFactories().end(); for(; it != itEnd; ++it ) { // !TBD: consider listAs() std::cout << "\t" << it->first << "\n\t\t'" << it->second->getDescription() << "'\n"; @@ -27,8 +28,8 @@ namespace Catch { if( config.listWhat() & Config::List::Tests ) { std::cout << "Available tests:\n"; - std::vector::const_iterator it = Context::getTestCaseRegistry().getAllTests().begin(); - std::vector::const_iterator itEnd = Context::getTestCaseRegistry().getAllTests().end(); + std::vector::const_iterator it = context.getTestCaseRegistry().getAllTests().begin(); + std::vector::const_iterator itEnd = context.getTestCaseRegistry().getAllTests().end(); for(; it != itEnd; ++it ) { // !TBD: consider listAs() std::cout << "\t" << it->getName() << "\n\t\t '" << it->getDescription() << "'\n"; diff --git a/include/internal/catch_objc.hpp b/include/internal/catch_objc.hpp index 6db1b707..91fc8df8 100644 --- a/include/internal/catch_objc.hpp +++ b/include/internal/catch_objc.hpp @@ -137,7 +137,7 @@ namespace Catch { std::string name = Detail::getAnnotation( cls, "Name", testCaseName ); std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); - Context::getTestCaseRegistry().registerTest( TestCaseInfo( new OcMethod( cls, selector ), name.c_str(), desc.c_str(), SourceLineInfo() ) ); + getCurrentContext().getTestCaseRegistry().registerTest( TestCaseInfo( new OcMethod( cls, selector ), name.c_str(), desc.c_str(), SourceLineInfo() ) ); noTestMethods++; } } diff --git a/include/internal/catch_reporter_registrars.hpp b/include/internal/catch_reporter_registrars.hpp index 05e7c713..e650cd0c 100644 --- a/include/internal/catch_reporter_registrars.hpp +++ b/include/internal/catch_reporter_registrars.hpp @@ -29,7 +29,7 @@ namespace Catch { public: ReporterRegistrar( const std::string& name ) { - Context::getReporterRegistry().registerReporter( name, new ReporterFactory() ); + getCurrentContext().getReporterRegistry().registerReporter( name, new ReporterFactory() ); } }; } diff --git a/include/internal/catch_runner_impl.hpp b/include/internal/catch_runner_impl.hpp index 3ca2fe36..fd30d8f5 100644 --- a/include/internal/catch_runner_impl.hpp +++ b/include/internal/catch_runner_impl.hpp @@ -56,25 +56,26 @@ namespace Catch { public: explicit Runner( Config& config ) - : m_runningTest( NULL ), + : m_context( getCurrentMutableContext() ), + m_runningTest( NULL ), m_config( config ), m_reporter( config.getReporter() ), - m_prevRunner( &Context::getRunner() ), - m_prevResultCapture( &Context::getResultCapture() ) + m_prevRunner( &m_context.getRunner() ), + m_prevResultCapture( &m_context.getResultCapture() ) { - Context::setRunner( this ); - Context::setResultCapture( this ); + m_context.setRunner( this ); + m_context.setResultCapture( this ); m_reporter->StartTesting(); } ~Runner() { m_reporter->EndTesting( m_totals ); - Context::setRunner( m_prevRunner ); - Context::setResultCapture( m_prevResultCapture ); + m_context.setRunner( m_prevRunner ); + m_context.setResultCapture( m_prevResultCapture ); } virtual void runAll( bool runHiddenTests = false ) { - std::vector allTests = Context::getTestCaseRegistry().getAllTests(); + const std::vector& allTests = getCurrentContext().getTestCaseRegistry().getAllTests(); for( std::size_t i=0; i < allTests.size(); ++i ) { if( runHiddenTests || !allTests[i].isHidden() ) runTest( allTests[i] ); @@ -84,7 +85,7 @@ namespace Catch { virtual std::size_t runMatching( const std::string& rawTestSpec ) { TestSpec testSpec( rawTestSpec ); - std::vector allTests = Context::getTestCaseRegistry().getAllTests(); + const std::vector& allTests = getCurrentContext().getTestCaseRegistry().getAllTests(); std::size_t testsRun = 0; for( std::size_t i=0; i < allTests.size(); ++i ) { if( testSpec.matches( allTests[i].getName() ) ) { @@ -114,7 +115,7 @@ namespace Catch { } while( m_runningTest->hasUntestedSections() ); } - while( Context::advanceGeneratorsForCurrentTest() ); + while( getCurrentContext().advanceGeneratorsForCurrentTest() ); delete m_runningTest; m_runningTest = NULL; @@ -251,13 +252,14 @@ namespace Catch { // This just means the test was aborted due to failure } catch(...) { - acceptMessage( Catch::Context::getExceptionTranslatorRegistry().translateActiveException() ); + acceptMessage( getCurrentContext().getExceptionTranslatorRegistry().translateActiveException() ); acceptResult( ResultWas::ThrewException ); } m_info.clear(); } private: + IMutableContext& m_context; RunningTest* m_runningTest; ResultInfoBuilder m_currentResult; ResultInfo m_lastResult; @@ -270,6 +272,7 @@ namespace Catch { IRunner* m_prevRunner; IResultCapture* m_prevResultCapture; }; -} + +} // end namespace Catch #endif // TWOBLUECUBES_INTERNAL_CATCH_RUNNER_HPP_INCLUDED diff --git a/include/internal/catch_section.hpp b/include/internal/catch_section.hpp index aee53b81..38bea0d2 100644 --- a/include/internal/catch_section.hpp +++ b/include/internal/catch_section.hpp @@ -21,12 +21,12 @@ namespace Catch { const std::string& description, const SourceLineInfo& lineInfo ) : m_name( name ), - m_sectionIncluded( Context::getResultCapture().sectionStarted( name, description, lineInfo, m_assertions ) ) + m_sectionIncluded( getCurrentContext().getResultCapture().sectionStarted( name, description, lineInfo, m_assertions ) ) {} ~Section() { if( m_sectionIncluded ) - Context::getResultCapture().sectionEnded( m_name, m_assertions ); + getCurrentContext().getResultCapture().sectionEnded( m_name, m_assertions ); } // This indicates whether the section should be executed or not diff --git a/include/internal/catch_test_case_registry_impl.hpp b/include/internal/catch_test_case_registry_impl.hpp index e5067875..cd0e0f16 100644 --- a/include/internal/catch_test_case_registry_impl.hpp +++ b/include/internal/catch_test_case_registry_impl.hpp @@ -109,7 +109,7 @@ namespace Catch { const char* name, const char* description, const SourceLineInfo& lineInfo ) { - Context::getTestCaseRegistry().registerTest( TestCaseInfo( testCase, name, description, lineInfo ) ); + getCurrentContext().getTestCaseRegistry().registerTest( TestCaseInfo( testCase, name, description, lineInfo ) ); } } // end namespace Catch diff --git a/projects/SelfTest/catch_self_test.hpp b/projects/SelfTest/catch_self_test.hpp index 0081e3b2..93a0d607 100644 --- a/projects/SelfTest/catch_self_test.hpp +++ b/projects/SelfTest/catch_self_test.hpp @@ -9,6 +9,7 @@ #define TWOBLUECUBES_CATCH_SELF_TEST_HPP_INCLUDED #include "catch.hpp" +#include "catch_test_case_info.hpp" #include "set" @@ -143,7 +144,7 @@ namespace Catch { static void runMatching( const std::string& testSpec, Expected::Result expectedResult ) { - forEach( Context::getTestCaseRegistry().getMatchingTestCases( testSpec ), + forEach( getCurrentContext().getTestCaseRegistry().getMatchingTestCases( testSpec ), MetaTestRunner( expectedResult ) ); } diff --git a/single_include/catch.hpp b/single_include/catch.hpp index c4d65ef6..471b76fb 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -298,27 +298,55 @@ namespace Catch { class StreamBufBase : public std::streambuf{}; - class Context { + struct IContext + { + virtual IResultCapture& getResultCapture() = 0; + virtual IRunner& getRunner() = 0; + virtual IReporterRegistry& getReporterRegistry() = 0; + virtual ITestCaseRegistry& getTestCaseRegistry() = 0; + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; + virtual size_t getGeneratorIndex( const std::string& fileInfo, size_t totalSize ) = 0; + virtual bool advanceGeneratorsForCurrentTest() = 0; + }; + + struct IMutableContext : IContext + { + virtual void setResultCapture( IResultCapture* resultCapture ) = 0; + virtual void setRunner( IRunner* runner ) = 0; + }; + + IContext& getCurrentContext(); + IMutableContext& getCurrentMutableContext(); + + class Context : public IMutableContext { Context(); Context( const Context& ); void operator=( const Context& ); - static Context& me(); - public: - static void setRunner( IRunner* runner ); - static void setResultCapture( IResultCapture* resultCapture ); - static IResultCapture& getResultCapture(); - static IReporterRegistry& getReporterRegistry(); - static ITestCaseRegistry& getTestCaseRegistry(); - static IExceptionTranslatorRegistry& getExceptionTranslatorRegistry(); + public: // friends + friend IContext& getCurrentContext() { return Context::getCurrent(); } + friend IMutableContext& getCurrentMutableContext() { return Context::getCurrent(); } + + public: // IContext + virtual IResultCapture& getResultCapture(); + virtual IRunner& getRunner(); + virtual IReporterRegistry& getReporterRegistry(); + virtual ITestCaseRegistry& getTestCaseRegistry(); + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry(); + virtual size_t getGeneratorIndex( const std::string& fileInfo, size_t totalSize ); + virtual bool advanceGeneratorsForCurrentTest(); + + public: // IMutableContext + virtual void setResultCapture( IResultCapture* resultCapture ); + virtual void setRunner( IRunner* runner ); + + public: // Statics static std::streambuf* createStreamBuf( const std::string& streamName ); - static IRunner& getRunner(); - static size_t getGeneratorIndex( const std::string& fileInfo, size_t totalSize ); - static bool advanceGeneratorsForCurrentTest(); static void cleanUp(); private: + static Context& getCurrent(); static Context*& singleInstance(); GeneratorsForTest* findGeneratorsForCurrentTest(); GeneratorsForTest& getGeneratorsForCurrentTest(); @@ -735,26 +763,13 @@ namespace Internal { IsGreaterThanOrEqualTo }; - template - struct OperatorTraits{ static const char* getName(){ return "*error - unknown operator*"; } }; - - template<> - struct OperatorTraits{ static const char* getName(){ return "=="; } }; - - template<> - struct OperatorTraits{ static const char* getName(){ return "!="; } }; - - template<> - struct OperatorTraits{ static const char* getName(){ return "<"; } }; - - template<> - struct OperatorTraits{ static const char* getName(){ return ">"; } }; - - template<> - struct OperatorTraits{ static const char* getName(){ return "<="; } }; - - template<> - struct OperatorTraits{ static const char* getName(){ return ">="; } }; + template struct OperatorTraits { static const char* getName(){ return "*error*"; } }; + template<> struct OperatorTraits { static const char* getName(){ return "=="; } }; + template<> struct OperatorTraits { static const char* getName(){ return "!="; } }; + template<> struct OperatorTraits { static const char* getName(){ return "<"; } }; + template<> struct OperatorTraits { static const char* getName(){ return ">"; } }; + template<> struct OperatorTraits { static const char* getName(){ return "<="; } }; + template<> struct OperatorTraits{ static const char* getName(){ return ">="; } }; // So the compare overloads can be operator agnostic we convey the operator as a template // enum, which is used to specialise an Evaluator for doing the comparison. @@ -1314,11 +1329,11 @@ struct TestFailureException{}; class ScopedInfo { public: ScopedInfo() : m_oss() { - Context::getResultCapture().pushScopedInfo( this ); + getCurrentContext().getResultCapture().pushScopedInfo( this ); } ~ScopedInfo() { - Context::getResultCapture().popScopedInfo( this ); + getCurrentContext().getResultCapture().popScopedInfo( this ); } template @@ -1342,7 +1357,7 @@ inline bool isTrue( bool value ){ return value; } /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_ACCEPT_EXPR( expr, stopOnFailure, originalExpr ) \ - if( Catch::ResultAction::Value internal_catch_action = Catch::Context::getResultCapture().acceptExpression( expr ) ) \ + if( Catch::ResultAction::Value internal_catch_action = Catch::getCurrentContext().getResultCapture().acceptExpression( expr ) ) \ { \ if( internal_catch_action == Catch::ResultAction::DebugFailed ) BreakIntoDebugger(); \ if( Catch::isTrue( stopOnFailure ) ) throw Catch::TestFailureException(); \ @@ -1356,19 +1371,19 @@ inline bool isTrue( bool value ){ return value; } }catch( Catch::TestFailureException& ){ \ throw; \ } catch( ... ){ \ - INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ) << Catch::Context::getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), false, expr ); \ + INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ) << Catch::getCurrentContext().getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), false, expr ); \ throw; \ }}while( Catch::isTrue( false ) ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_IF( expr, isNot, stopOnFailure, macroName ) \ INTERNAL_CATCH_TEST( expr, isNot, stopOnFailure, macroName ); \ - if( Catch::Context::getResultCapture().getLastResult()->ok() ) + if( Catch::getCurrentContext().getResultCapture().getLastResult()->ok() ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_ELSE( expr, isNot, stopOnFailure, macroName ) \ INTERNAL_CATCH_TEST( expr, isNot, stopOnFailure, macroName ); \ - if( !Catch::Context::getResultCapture().getLastResult()->ok() ) + if( !Catch::getCurrentContext().getResultCapture().getLastResult()->ok() ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_NO_THROW( expr, stopOnFailure, macroName ) \ @@ -1379,7 +1394,7 @@ inline bool isTrue( bool value ){ return value; } } \ catch( ... ) \ { \ - INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ) << Catch::Context::getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), stopOnFailure, false ); \ + INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ) << Catch::getCurrentContext().getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), stopOnFailure, false ); \ } /////////////////////////////////////////////////////////////////////////////// @@ -1403,12 +1418,12 @@ inline bool isTrue( bool value ){ return value; } INTERNAL_CATCH_THROWS( expr, exceptionType, stopOnFailure, macroName ) \ catch( ... ) \ { \ - INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ) << Catch::Context::getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), stopOnFailure, false ); \ + INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ) << Catch::getCurrentContext().getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), stopOnFailure, false ); \ } /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_MSG( reason, resultType, stopOnFailure, macroName ) \ - Catch::Context::getResultCapture().acceptExpression( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName ) << reason ).setResultType( resultType ) ); + Catch::getCurrentContext().getResultCapture().acceptExpression( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName ) << reason ).setResultType( resultType ) ); /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_SCOPED_INFO( log ) \ @@ -1422,7 +1437,7 @@ inline bool isTrue( bool value ){ return value; } }catch( Catch::TestFailureException& ){ \ throw; \ } catch( ... ){ \ - INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #arg " " #matcher ) << Catch::Context::getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), false, false ); \ + INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #arg " " #matcher ) << Catch::getCurrentContext().getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), false, false ); \ throw; \ }}while( Catch::isTrue( false ) ) @@ -1438,12 +1453,12 @@ namespace Catch { const std::string& description, const SourceLineInfo& lineInfo ) : m_name( name ), - m_sectionIncluded( Context::getResultCapture().sectionStarted( name, description, lineInfo, m_assertions ) ) + m_sectionIncluded( getCurrentContext().getResultCapture().sectionStarted( name, description, lineInfo, m_assertions ) ) {} ~Section() { if( m_sectionIncluded ) - Context::getResultCapture().sectionEnded( m_name, m_assertions ); + getCurrentContext().getResultCapture().sectionEnded( m_name, m_assertions ); } // This indicates whether the section should be executed or not @@ -1542,7 +1557,7 @@ public: } operator T () const { - size_t overallIndex = Context::getGeneratorIndex( m_fileInfo, m_totalSize ); + size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize ); typename std::vector*>::const_iterator it = m_composed.begin(); typename std::vector*>::const_iterator itEnd = m_composed.end(); @@ -1687,7 +1702,7 @@ namespace Catch { public: template ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) { - Catch::Context::getExceptionTranslatorRegistry().registerTranslator + getCurrentContext().getExceptionTranslatorRegistry().registerTranslator ( new ExceptionTranslator( translateFunction ) ); } }; @@ -1779,6 +1794,84 @@ inline std::string toString( const Detail::Approx& value ) { } // end namespace Catch +// #included from: internal/catch_matchers.hpp + +namespace Catch { +namespace Matchers { + namespace Impl { + namespace StdString { + + struct Contains { + Contains( const std::string& substr ) : m_substr( substr ){} + + bool operator()( const std::string& str ) const + { + return str.find( m_substr ) != std::string::npos; + } + + friend std::ostream& operator<<( std::ostream& os, const Contains& matcher ) + { + os << "contains: \"" << matcher.m_substr << "\""; + return os; + } + std::string m_substr; + }; + + struct StartsWith { + StartsWith( const std::string& substr ) : m_substr( substr ){} + + bool operator()( const std::string& str ) const + { + return str.find( m_substr ) == 0; + } + + friend std::ostream& operator<<( std::ostream& os, const StartsWith& matcher ) + { + os << "starts with: \"" << matcher.m_substr << "\""; + return os; + } + std::string m_substr; + }; + + struct EndsWith { + EndsWith( const std::string& substr ) : m_substr( substr ){} + + bool operator()( const std::string& str ) const + { + return str.find( m_substr ) == str.size() - m_substr.size(); + } + + friend std::ostream& operator<<( std::ostream& os, const EndsWith& matcher ) + { + os << "ends with: \"" << matcher.m_substr << "\""; + return os; + } + std::string m_substr; + }; + } // namespace StdString + } // namespace Impl + + inline Impl::StdString::Contains Contains( const std::string& substr ){ return Impl::StdString::Contains( substr ); } + inline Impl::StdString::StartsWith StartsWith( const std::string& substr ){ return Impl::StdString::StartsWith( substr ); } + inline Impl::StdString::EndsWith EndsWith( const std::string& substr ){ return Impl::StdString::EndsWith( substr ); } + +} // namespace Matchers + +using namespace Matchers; + +} // namespace Catch + +#ifdef __OBJC__ +// #included from: internal/catch_objc.hpp + +#import +#import + +#include + +// NB. Any general catch headers included here must be included +// in catch.hpp first to make sure they are included by the single +// header for non obj-usage // #included from: internal/catch_test_case_info.hpp #include @@ -1897,84 +1990,6 @@ namespace Catch { }; } -// #included from: internal/catch_matchers.hpp - -namespace Catch { -namespace Matchers { - namespace Impl { - namespace StdString { - - struct Contains { - Contains( const std::string& substr ) : m_substr( substr ){} - - bool operator()( const std::string& str ) const - { - return str.find( m_substr ) != std::string::npos; - } - - friend std::ostream& operator<<( std::ostream& os, const Contains& matcher ) - { - os << "contains: \"" << matcher.m_substr << "\""; - return os; - } - std::string m_substr; - }; - - struct StartsWith { - StartsWith( const std::string& substr ) : m_substr( substr ){} - - bool operator()( const std::string& str ) const - { - return str.find( m_substr ) == 0; - } - - friend std::ostream& operator<<( std::ostream& os, const StartsWith& matcher ) - { - os << "starts with: \"" << matcher.m_substr << "\""; - return os; - } - std::string m_substr; - }; - - struct EndsWith { - EndsWith( const std::string& substr ) : m_substr( substr ){} - - bool operator()( const std::string& str ) const - { - return str.find( m_substr ) == str.size() - m_substr.size(); - } - - friend std::ostream& operator<<( std::ostream& os, const EndsWith& matcher ) - { - os << "ends with: \"" << matcher.m_substr << "\""; - return os; - } - std::string m_substr; - }; - } // namespace StdString - } // namespace Impl - - inline Impl::StdString::Contains Contains( const std::string& substr ){ return Impl::StdString::Contains( substr ); } - inline Impl::StdString::StartsWith StartsWith( const std::string& substr ){ return Impl::StdString::StartsWith( substr ); } - inline Impl::StdString::EndsWith EndsWith( const std::string& substr ){ return Impl::StdString::EndsWith( substr ); } - -} // namespace Matchers - -using namespace Matchers; - -} // namespace Catch - -#ifdef __OBJC__ -// #included from: internal/catch_objc.hpp - -#import -#import - -#include - -// NB. Any general catch headers included here must be included -// in catch.hpp first to make sure they are included by the single -// header for non obj-usage #ifdef __has_feature #define CATCH_ARC_ENABLED __has_feature(objc_arc) @@ -2095,7 +2110,7 @@ namespace Catch { std::string name = Detail::getAnnotation( cls, "Name", testCaseName ); std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); - Context::getTestCaseRegistry().registerTest( TestCaseInfo( new OcMethod( cls, selector ), name.c_str(), desc.c_str(), SourceLineInfo() ) ); + getCurrentContext().getTestCaseRegistry().registerTest( TestCaseInfo( new OcMethod( cls, selector ), name.c_str(), desc.c_str(), SourceLineInfo() ) ); noTestMethods++; } } @@ -2314,7 +2329,7 @@ namespace Catch { const char* name, const char* description, const SourceLineInfo& lineInfo ) { - Context::getTestCaseRegistry().registerTest( TestCaseInfo( testCase, name, description, lineInfo ) ); + getCurrentContext().getTestCaseRegistry().registerTest( TestCaseInfo( testCase, name, description, lineInfo ) ); } } // end namespace Catch @@ -2388,7 +2403,7 @@ namespace Catch { void setReporter( const std::string& reporterName ) { if( m_reporter.get() ) return setError( "Only one reporter may be specified" ); - setReporter( Context::getReporterRegistry().create( reporterName, *this ) ); + setReporter( getCurrentContext().getReporterRegistry().create( reporterName, *this ) ); } void addTestSpec( const std::string& testSpec ) { @@ -2433,7 +2448,7 @@ namespace Catch { Ptr getReporter() { if( !m_reporter.get() ) - const_cast( this )->setReporter( Context::getReporterRegistry().create( "basic", *this ) ); + const_cast( this )->setReporter( getCurrentContext().getReporterRegistry().create( "basic", *this ) ); return m_reporter; } @@ -2730,25 +2745,26 @@ namespace Catch { public: explicit Runner( Config& config ) - : m_runningTest( NULL ), + : m_context( getCurrentMutableContext() ), + m_runningTest( NULL ), m_config( config ), m_reporter( config.getReporter() ), - m_prevRunner( &Context::getRunner() ), - m_prevResultCapture( &Context::getResultCapture() ) + m_prevRunner( &m_context.getRunner() ), + m_prevResultCapture( &m_context.getResultCapture() ) { - Context::setRunner( this ); - Context::setResultCapture( this ); + m_context.setRunner( this ); + m_context.setResultCapture( this ); m_reporter->StartTesting(); } ~Runner() { m_reporter->EndTesting( m_totals ); - Context::setRunner( m_prevRunner ); - Context::setResultCapture( m_prevResultCapture ); + m_context.setRunner( m_prevRunner ); + m_context.setResultCapture( m_prevResultCapture ); } virtual void runAll( bool runHiddenTests = false ) { - std::vector allTests = Context::getTestCaseRegistry().getAllTests(); + const std::vector& allTests = getCurrentContext().getTestCaseRegistry().getAllTests(); for( std::size_t i=0; i < allTests.size(); ++i ) { if( runHiddenTests || !allTests[i].isHidden() ) runTest( allTests[i] ); @@ -2758,7 +2774,7 @@ namespace Catch { virtual std::size_t runMatching( const std::string& rawTestSpec ) { TestSpec testSpec( rawTestSpec ); - std::vector allTests = Context::getTestCaseRegistry().getAllTests(); + const std::vector& allTests = getCurrentContext().getTestCaseRegistry().getAllTests(); std::size_t testsRun = 0; for( std::size_t i=0; i < allTests.size(); ++i ) { if( testSpec.matches( allTests[i].getName() ) ) { @@ -2788,7 +2804,7 @@ namespace Catch { } while( m_runningTest->hasUntestedSections() ); } - while( Context::advanceGeneratorsForCurrentTest() ); + while( getCurrentContext().advanceGeneratorsForCurrentTest() ); delete m_runningTest; m_runningTest = NULL; @@ -2925,13 +2941,14 @@ namespace Catch { // This just means the test was aborted due to failure } catch(...) { - acceptMessage( Catch::Context::getExceptionTranslatorRegistry().translateActiveException() ); + acceptMessage( getCurrentContext().getExceptionTranslatorRegistry().translateActiveException() ); acceptResult( ResultWas::ThrewException ); } m_info.clear(); } private: + IMutableContext& m_context; RunningTest* m_runningTest; ResultInfoBuilder m_currentResult; ResultInfo m_lastResult; @@ -2944,7 +2961,8 @@ namespace Catch { IRunner* m_prevRunner; IResultCapture* m_prevResultCapture; }; -} + +} // end namespace Catch // #included from: catch_generators_impl.hpp @@ -3281,7 +3299,12 @@ namespace Catch { m_exceptionTranslatorRegistry( new ExceptionTranslatorRegistry ) {} - Context& Context::me() { + Context*& Context::singleInstance() { + static Context* hub = NULL; + return hub; + } + + Context& Context::getCurrent() { Context*& hub = singleInstance(); if( !hub ) hub = new Context(); @@ -3294,37 +3317,32 @@ namespace Catch { hub = NULL; } - Context*& Context::singleInstance() { - static Context* hub = NULL; - return hub; - } - void Context::setRunner( IRunner* runner ) { - me().m_runner = runner; + m_runner = runner; } void Context::setResultCapture( IResultCapture* resultCapture ) { - me().m_resultCapture = resultCapture; + m_resultCapture = resultCapture; } IResultCapture& Context::getResultCapture() { - return *me().m_resultCapture; + return *m_resultCapture; } IRunner& Context::getRunner() { - return *me().m_runner; + return *m_runner; } IReporterRegistry& Context::getReporterRegistry() { - return *me().m_reporterRegistry.get(); + return *m_reporterRegistry.get(); } ITestCaseRegistry& Context::getTestCaseRegistry() { - return *me().m_testCaseRegistry.get(); + return *m_testCaseRegistry.get(); } IExceptionTranslatorRegistry& Context::getExceptionTranslatorRegistry() { - return *me().m_exceptionTranslatorRegistry.get(); + return *m_exceptionTranslatorRegistry.get(); } std::streambuf* Context::createStreamBuf( const std::string& streamName ) { @@ -3336,7 +3354,7 @@ namespace Catch { } GeneratorsForTest* Context::findGeneratorsForCurrentTest() { - std::string testName = getResultCapture().getCurrentTestName(); + std::string testName = getCurrentContext().getResultCapture().getCurrentTestName(); std::map::const_iterator it = m_generatorsByTestName.find( testName ); @@ -3348,7 +3366,7 @@ namespace Catch { GeneratorsForTest& Context::getGeneratorsForCurrentTest() { GeneratorsForTest* generators = findGeneratorsForCurrentTest(); if( !generators ) { - std::string testName = getResultCapture().getCurrentTestName(); + std::string testName = getCurrentContext().getResultCapture().getCurrentTestName(); generators = new GeneratorsForTest(); m_generatorsByTestName.insert( std::make_pair( testName, generators ) ); } @@ -3356,13 +3374,13 @@ namespace Catch { } size_t Context::getGeneratorIndex( const std::string& fileInfo, size_t totalSize ) { - return me().getGeneratorsForCurrentTest() + return getGeneratorsForCurrentTest() .getGeneratorInfo( fileInfo, totalSize ) .getCurrentIndex(); } bool Context::advanceGeneratorsForCurrentTest() { - GeneratorsForTest* generators = me().findGeneratorsForCurrentTest(); + GeneratorsForTest* generators = findGeneratorsForCurrentTest(); return generators && generators->moveNext(); } } @@ -3547,10 +3565,11 @@ namespace Catch { namespace Catch { inline int List( Config& config ) { + IContext& context = getCurrentContext(); if( config.listWhat() & Config::List::Reports ) { std::cout << "Available reports:\n"; - IReporterRegistry::FactoryMap::const_iterator it = Context::getReporterRegistry().getFactories().begin(); - IReporterRegistry::FactoryMap::const_iterator itEnd = Context::getReporterRegistry().getFactories().end(); + IReporterRegistry::FactoryMap::const_iterator it = context.getReporterRegistry().getFactories().begin(); + IReporterRegistry::FactoryMap::const_iterator itEnd = context.getReporterRegistry().getFactories().end(); for(; it != itEnd; ++it ) { // !TBD: consider listAs() std::cout << "\t" << it->first << "\n\t\t'" << it->second->getDescription() << "'\n"; @@ -3560,8 +3579,8 @@ namespace Catch { if( config.listWhat() & Config::List::Tests ) { std::cout << "Available tests:\n"; - std::vector::const_iterator it = Context::getTestCaseRegistry().getAllTests().begin(); - std::vector::const_iterator itEnd = Context::getTestCaseRegistry().getAllTests().end(); + std::vector::const_iterator it = context.getTestCaseRegistry().getAllTests().begin(); + std::vector::const_iterator itEnd = context.getTestCaseRegistry().getAllTests().end(); for(; it != itEnd; ++it ) { // !TBD: consider listAs() std::cout << "\t" << it->getName() << "\n\t\t '" << it->getDescription() << "'\n"; @@ -3606,7 +3625,7 @@ namespace Catch { public: ReporterRegistrar( const std::string& name ) { - Context::getReporterRegistry().registerReporter( name, new ReporterFactory() ); + getCurrentContext().getReporterRegistry().registerReporter( name, new ReporterFactory() ); } }; } @@ -4505,7 +4524,9 @@ namespace Catch { config.getReporter()->EndGroup( *it, runner.getTotals() - prevTotals ); } } - return static_cast( runner.getTotals().assertions.failed ); + int result = static_cast( runner.getTotals().assertions.failed ); + Catch::Context::cleanUp(); + return result; } inline void showHelp( std::string exeName ) { @@ -4530,25 +4551,25 @@ namespace Catch { if( !config.getMessage().empty() ) { std::cerr << config.getMessage() << std::endl; + Catch::Context::cleanUp(); return (std::numeric_limits::max)(); } // Handle help if( config.showHelp() ) { showHelp( argv[0] ); + Catch::Context::cleanUp(); return 0; } - return Main( config ); } inline int Main( int argc, char* const argv[] ) { Config config; +// !TBD: This doesn't always work, for some reason // if( isDebuggerActive() ) // config.useStream( "debug" ); - int result = Main( argc, argv, config ); - Catch::Context::cleanUp(); - return result; + return Main( argc, argv, config ); } } // end namespace Catch