From 46a3476731b7e8f2a3a413572785bd207c063acf Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 5 Jun 2012 20:50:47 +0100 Subject: [PATCH] Added nothrow command line option Causes _THROWS family of macros to no evaluate expression --- include/internal/catch_capture.hpp | 41 ++++++++----------- include/internal/catch_commandline.hpp | 7 ++++ include/internal/catch_config.hpp | 14 ++++++- include/internal/catch_context.h | 8 +++- include/internal/catch_context_impl.hpp | 10 ++++- include/internal/catch_interfaces_config.h | 21 ++++++++++ include/internal/catch_runner_impl.hpp | 6 +++ projects/SelfTest/TestMain.cpp | 30 +++++++++++--- .../CatchSelfTest.xcodeproj/project.pbxproj | 2 + 9 files changed, 107 insertions(+), 32 deletions(-) create mode 100644 include/internal/catch_interfaces_config.h diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index 84233c3f..41f0f9d8 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -50,8 +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::getCurrentContext().getResultCapture().acceptExpression( expr ) ) \ - { \ + if( Catch::ResultAction::Value internal_catch_action = Catch::getCurrentContext().getResultCapture().acceptExpression( expr ) ) { \ if( internal_catch_action & Catch::ResultAction::Debug ) BreakIntoDebugger(); \ if( internal_catch_action & Catch::ResultAction::Abort ) throw Catch::TestFailureException(); \ if( Catch::isTrue( stopOnFailure ) ) throw Catch::TestFailureException(); \ @@ -60,14 +59,14 @@ inline bool isTrue( bool value ){ return value; } /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TEST( expr, isNot, stopOnFailure, macroName ) \ - do{ try{ \ + do { try { \ INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr, isNot )->*expr ), stopOnFailure, expr ); \ - }catch( Catch::TestFailureException& ){ \ + } catch( Catch::TestFailureException& ) { \ throw; \ - } catch( ... ){ \ + } catch( ... ) { \ 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 ) ) + } } while( Catch::isTrue( false ) ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_IF( expr, isNot, stopOnFailure, macroName ) \ @@ -81,37 +80,33 @@ inline bool isTrue( bool value ){ return value; } /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_NO_THROW( expr, stopOnFailure, macroName ) \ - try \ - { \ + try { \ expr; \ INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ).setResultType( Catch::ResultWas::Ok ), stopOnFailure, false ); \ } \ - catch( ... ) \ - { \ + catch( ... ) { \ INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ) << Catch::getCurrentContext().getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), stopOnFailure, false ); \ } /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_THROWS( expr, exceptionType, stopOnFailure, macroName ) \ - try \ - { \ - expr; \ - INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ).setResultType( Catch::ResultWas::DidntThrowException ), stopOnFailure, false ); \ + try { \ + if( Catch::getCurrentContext().getConfig()->allowThrows() ) { \ + expr; \ + INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ).setResultType( Catch::ResultWas::DidntThrowException ), stopOnFailure, false ); \ + } \ } \ - catch( Catch::TestFailureException& ) \ - { \ + catch( Catch::TestFailureException& ) { \ throw; \ } \ - catch( exceptionType ) \ - { \ + catch( exceptionType ) { \ INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ).setResultType( Catch::ResultWas::Ok ), stopOnFailure, false ); \ } /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, stopOnFailure, macroName ) \ INTERNAL_CATCH_THROWS( expr, exceptionType, stopOnFailure, macroName ) \ - catch( ... ) \ - { \ + catch( ... ) { \ INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ) << Catch::getCurrentContext().getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), stopOnFailure, false ); \ } @@ -126,11 +121,11 @@ inline bool isTrue( bool value ){ return value; } /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CHECK_THAT( arg, matcher, stopOnFailure, macroName ) \ - do{ try{ \ + do { try { \ INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #arg " " #matcher, false ).acceptMatcher( ::Catch::Matchers::matcher, arg, #matcher ) ), stopOnFailure, false ); \ - }catch( Catch::TestFailureException& ){ \ + } catch( Catch::TestFailureException& ) { \ throw; \ - } catch( ... ){ \ + } catch( ... ) { \ 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_commandline.hpp b/include/internal/catch_commandline.hpp index ac40d092..41aa91c8 100644 --- a/include/internal/catch_commandline.hpp +++ b/include/internal/catch_commandline.hpp @@ -174,6 +174,13 @@ namespace Catch { } config.setCutoff( threshold ); } + + if( Command cmd = parser.find( "-nt", "--nothrow" ) ) { + if( cmd.argsCount() != 0 ) + cmd.raiseError( "Does not accept arguments" ); + config.setAllowThrows( false ); + } + } catch( std::exception& ex ) { config.setError( ex.what() ); diff --git a/include/internal/catch_config.hpp b/include/internal/catch_config.hpp index 23d60bb2..9c9661e2 100644 --- a/include/internal/catch_config.hpp +++ b/include/internal/catch_config.hpp @@ -38,7 +38,7 @@ namespace Catch { AsMask = 0xf0 }; }; - class Config : public IReporterConfig { + class Config : public IReporterConfig, public IConfig { private: Config( const Config& other ); Config& operator = ( const Config& other ); @@ -51,7 +51,8 @@ namespace Catch { m_streambuf( NULL ), m_os( std::cout.rdbuf() ), m_includeWhichResults( Include::FailedOnly ), - m_cutoff( -1 ) + m_cutoff( -1 ), + m_allowThrows( true ) {} ~Config() { @@ -173,6 +174,14 @@ namespace Catch { void setCutoff( int cutoff ) { m_cutoff = cutoff; } + + void setAllowThrows( bool allowThrows ) { + m_allowThrows = allowThrows; + } + + virtual bool allowThrows() const { + return m_allowThrows; + } private: Ptr m_reporter; @@ -187,6 +196,7 @@ namespace Catch { Include::WhichResults m_includeWhichResults; std::string m_name; int m_cutoff; + bool m_allowThrows; }; struct NewConfig { diff --git a/include/internal/catch_context.h b/include/internal/catch_context.h index 87ff522e..7b015983 100644 --- a/include/internal/catch_context.h +++ b/include/internal/catch_context.h @@ -9,6 +9,7 @@ #define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED #include "catch_interfaces_reporter.h" +#include "catch_interfaces_config.h" #include #include @@ -36,12 +37,14 @@ namespace Catch { virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; virtual size_t getGeneratorIndex( const std::string& fileInfo, size_t totalSize ) = 0; virtual bool advanceGeneratorsForCurrentTest() = 0; + virtual const IConfig* getConfig() const = 0; }; struct IMutableContext : IContext { virtual void setResultCapture( IResultCapture* resultCapture ) = 0; virtual void setRunner( IRunner* runner ) = 0; + virtual void setConfig( const IConfig* config ) = 0; }; IContext& getCurrentContext(); @@ -60,11 +63,13 @@ namespace Catch { virtual ITestCaseRegistry& getTestCaseRegistry(); virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry(); virtual size_t getGeneratorIndex( const std::string& fileInfo, size_t totalSize ); - virtual bool advanceGeneratorsForCurrentTest(); + virtual bool advanceGeneratorsForCurrentTest(); + virtual const IConfig* getConfig() const; public: // IMutableContext virtual void setResultCapture( IResultCapture* resultCapture ); virtual void setRunner( IRunner* runner ); + virtual void setConfig( const IConfig* config ); public: // Statics static std::streambuf* createStreamBuf( const std::string& streamName ); @@ -82,6 +87,7 @@ namespace Catch { std::auto_ptr m_exceptionTranslatorRegistry; IRunner* m_runner; IResultCapture* m_resultCapture; + const IConfig* m_config; std::map m_generatorsByTestName; }; } diff --git a/include/internal/catch_context_impl.hpp b/include/internal/catch_context_impl.hpp index 418f330b..cf4f3697 100644 --- a/include/internal/catch_context_impl.hpp +++ b/include/internal/catch_context_impl.hpp @@ -32,7 +32,8 @@ namespace Catch { Context::Context() : m_reporterRegistry( new ReporterRegistry ), m_testCaseRegistry( new TestRegistry ), - m_exceptionTranslatorRegistry( new ExceptionTranslatorRegistry ) + m_exceptionTranslatorRegistry( new ExceptionTranslatorRegistry ), + m_config( NULL ) {} void Context::cleanUp() { @@ -47,6 +48,13 @@ namespace Catch { void Context::setResultCapture( IResultCapture* resultCapture ) { m_resultCapture = resultCapture; } + + const IConfig* Context::getConfig() const { + return m_config; + } + void Context::setConfig( const IConfig* config ) { + m_config = config; + } IResultCapture& Context::getResultCapture() { return *m_resultCapture; diff --git a/include/internal/catch_interfaces_config.h b/include/internal/catch_interfaces_config.h new file mode 100644 index 00000000..ec434e5d --- /dev/null +++ b/include/internal/catch_interfaces_config.h @@ -0,0 +1,21 @@ +/* + * Created by Phil on 05/06/2012. + * Copyright 2012 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED +#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED + +namespace Catch { + + struct IConfig { + + virtual ~IConfig(){} + + virtual bool allowThrows() const = 0; + }; +} + +#endif // TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED diff --git a/include/internal/catch_runner_impl.hpp b/include/internal/catch_runner_impl.hpp index 6548a06d..a95922c7 100644 --- a/include/internal/catch_runner_impl.hpp +++ b/include/internal/catch_runner_impl.hpp @@ -64,6 +64,7 @@ namespace Catch { m_prevResultCapture( &m_context.getResultCapture() ) { m_context.setRunner( this ); + m_context.setConfig( &m_config ); m_context.setResultCapture( this ); m_reporter->StartTesting(); } @@ -71,6 +72,7 @@ namespace Catch { ~Runner() { m_reporter->EndTesting( m_totals ); m_context.setRunner( m_prevRunner ); + m_context.setConfig( NULL ); m_context.setResultCapture( m_prevResultCapture ); } @@ -139,6 +141,10 @@ namespace Catch { return m_totals; } + const Config& config() const { + return m_config; + } + private: // IResultCapture virtual ResultAction::Value acceptResult( bool result ) { diff --git a/projects/SelfTest/TestMain.cpp b/projects/SelfTest/TestMain.cpp index 093005be..23691b55 100644 --- a/projects/SelfTest/TestMain.cpp +++ b/projects/SelfTest/TestMain.cpp @@ -75,6 +75,7 @@ TEST_CASE( "selftest/parser", "" ) { CHECK( config.shouldDebugBreak() == false ); CHECK( config.showHelp() == false ); CHECK( config.getCutoff() == -1 ); + CHECK( config.allowThrows() == true ); CHECK( dynamic_cast( config.getReporter().get() ) ); } @@ -225,14 +226,33 @@ TEST_CASE( "selftest/parser", "" ) { REQUIRE_THAT( config.getMessage(), Contains( "accepts" ) ); } } - SECTION( "combinations", "" ) { - SECTION( "-a -b", "" ) { - const char* argv[] = { "test", "-a", "-b" }; + + SECTION( "nothrow", "" ) { + SECTION( "-nt", "" ) { + const char* argv[] = { "test", "-nt" }; Catch::Config config; CHECK( parseIntoConfig( argv, config ) ); - REQUIRE( config.getCutoff() == 1 ); - REQUIRE( config.shouldDebugBreak() ); + REQUIRE( config.allowThrows() == false ); + } + SECTION( "--nothrow", "" ) { + const char* argv[] = { "test", "--nothrow" }; + Catch::Config config; + CHECK( parseIntoConfig( argv, config ) ); + + REQUIRE( config.allowThrows() == false ); + } + + } + SECTION( "combinations", "" ) { + SECTION( "-a -b", "" ) { + const char* argv[] = { "test", "-a", "-b", "-nt" }; + Catch::Config config; + CHECK( parseIntoConfig( argv, config ) ); + + CHECK( config.getCutoff() == 1 ); + CHECK( config.shouldDebugBreak() ); + CHECK( config.allowThrows() == false ); } } diff --git a/projects/XCode4/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj b/projects/XCode4/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj index ffba9c4d..99e642a0 100644 --- a/projects/XCode4/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj +++ b/projects/XCode4/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj @@ -95,6 +95,7 @@ 4AC91CCE155CF02800DC5117 /* catch_expression.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_expression.hpp; sourceTree = ""; }; 4AC91CD0155D8DA600DC5117 /* catch_expression_builder.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_expression_builder.hpp; sourceTree = ""; }; 4AE1840A14EE4F230066340D /* catch_self_test.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_self_test.cpp; path = ../../../SelfTest/catch_self_test.cpp; sourceTree = ""; }; + 4AFC661D157E96A7009D58CF /* catch_interfaces_config.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_interfaces_config.h; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -264,6 +265,7 @@ 4A6D0C55149B3E3D00DB3EAA /* catch_interfaces_reporter.h */, 4A6D0C56149B3E3D00DB3EAA /* catch_interfaces_runner.h */, 4A6D0C57149B3E3D00DB3EAA /* catch_interfaces_testcase.h */, + 4AFC661D157E96A7009D58CF /* catch_interfaces_config.h */, ); name = Interfaces; sourceTree = "";