From 5d7b054f14841b892fb04e27c431addd073959ce Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 20 Apr 2011 19:09:41 +0100 Subject: [PATCH] Improved custom exception handling --- Test/ExceptionTests.cpp | 34 ++++++++++----- catch.hpp | 1 + internal/catch_capture.hpp | 4 +- internal/catch_interfaces_exception.h | 63 +++++++++++++++++++-------- 4 files changed, 71 insertions(+), 31 deletions(-) diff --git a/Test/ExceptionTests.cpp b/Test/ExceptionTests.cpp index caad6fd8..1d45200e 100644 --- a/Test/ExceptionTests.cpp +++ b/Test/ExceptionTests.cpp @@ -79,19 +79,33 @@ private: std::string m_msg; }; - -namespace Catch +CATCH_TRANSLATE_EXCEPTION( CustomException& ex ) { - ExceptionTranslator translator; - - template<> - std::string ExceptionTranslator::translate( CustomException& ex ) const - { - return ex.getMessage(); - } + return ex.getMessage(); } -TEST_CASE_NORETURN( "./succeeding/exceptions/custom", "" ) +CATCH_TRANSLATE_EXCEPTION( double& ex ) +{ + return Catch::toString( ex ); +} + +TEST_CASE_NORETURN( "./failing/exceptions/custom", "Unexpected custom exceptions can be translated" ) { throw CustomException( "custom exception" ); } + +TEST_CASE( "./failing/exceptions/custom/nothrow", "Custom exceptions can be translated when testing for nothrow" ) +{ + REQUIRE_NOTHROW( throw CustomException( "unexpected custom exception" ) ); +} + +TEST_CASE( "./failing/exceptions/custom/throw", "Custom exceptions can be translated when testing for throwing as something else" ) +{ + REQUIRE_THROWS_AS( throw CustomException( "custom exception - not std" ), std::exception ); +} + + +TEST_CASE_NORETURN( "./failing/exceptions/custom/double", "Unexpected custom exceptions can be translated" ) +{ + throw double( 3.14 ); +} diff --git a/catch.hpp b/catch.hpp index 488dde45..f9ff324c 100644 --- a/catch.hpp +++ b/catch.hpp @@ -60,6 +60,7 @@ #define METHOD_AS_TEST_CASE( method, name, description ) CATCH_METHOD_AS_TEST_CASE( method, name, description ) #define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) +#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) #define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) diff --git a/internal/catch_capture.hpp b/internal/catch_capture.hpp index 6763353a..55980469 100644 --- a/internal/catch_capture.hpp +++ b/internal/catch_capture.hpp @@ -735,7 +735,7 @@ inline bool isTrue } \ catch( ... ) \ { \ - INTERNAL_CATCH_ACCEPT_EXPR( Catch::ResultBuilder( __FILE__, __LINE__, macroName, #expr ).setResultType( Catch::ResultWas::ThrewException ), stopOnFailure ); \ + INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ResultBuilder( __FILE__, __LINE__, macroName, #expr ) << Catch::Hub::getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), stopOnFailure ); \ } /////////////////////////////////////////////////////////////////////////////// @@ -759,7 +759,7 @@ inline bool isTrue INTERNAL_CATCH_THROWS( expr, exceptionType, stopOnFailure, macroName ) \ catch( ... ) \ { \ - INTERNAL_CATCH_ACCEPT_EXPR( Catch::ResultBuilder( __FILE__, __LINE__, macroName, #expr ).setResultType( Catch::ResultWas::ThrewException ), stopOnFailure ); \ + INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ResultBuilder( __FILE__, __LINE__, macroName, #expr ) << Catch::Hub::getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), stopOnFailure ); \ } /////////////////////////////////////////////////////////////////////////////// diff --git a/internal/catch_interfaces_exception.h b/internal/catch_interfaces_exception.h index b7edc013..0e17fa36 100644 --- a/internal/catch_interfaces_exception.h +++ b/internal/catch_interfaces_exception.h @@ -38,30 +38,55 @@ namespace Catch }; - template - class ExceptionTranslator : public IExceptionTranslator + class ExceptionTranslatorRegistrar { + template + class ExceptionTranslator : public IExceptionTranslator + { + public: + + ExceptionTranslator + ( + std::string(*translateFunction)( T& ) + ) + : m_translateFunction( translateFunction ) + {} + + virtual std::string translate + () + const + { + try + { + throw; + } + catch( T& ex ) + { + return m_translateFunction( ex ); + } + } + + protected: + std::string(*m_translateFunction)( T& ); + }; + public: - ExceptionTranslator() + template + ExceptionTranslatorRegistrar + ( + std::string(*translateFunction)( T& ) + ) { - Catch::Hub::getExceptionTranslatorRegistry().registerTranslator( this ); + Catch::Hub::getExceptionTranslatorRegistry().registerTranslator + ( new ExceptionTranslator( translateFunction ) ); } - - virtual std::string translate() const - { - try - { - throw; - } - catch( T& ex ) - { - return translate( ex ); - } - } - - protected: - std::string translate( T& ex ) const; }; } +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \ + static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \ + namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\ + static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ) + #endif // TWOBLUECUBES_CATCH_INTERFACES_EXCEPTIONS_H_INCLUDED