diff --git a/docs/tostring.md b/docs/tostring.md index 1f801b3ac0..dbb6cb8d5d 100644 --- a/docs/tostring.md +++ b/docs/tostring.md @@ -55,6 +55,16 @@ namespace Catch { } ``` +## Exceptions + +By default all exceptions deriving from `std::exception` will be translated to strings by calling the `what()` method. For exception types that do not derive from `std::exception` - or if `what()` does not return a suitable string - use `CATCH_TRANSLATE_EXCEPTION`. This defines a function that takes your exception type, by reference, and returns a string. It can appear anywhere in the code - it doesn't have to be in the same translation unit. For example: + +``` +CATCH_TRANSLATE_EXCEPTION( MyType& ex ) { + return ex.message(); +} +``` + --- [Home](Readme.md) diff --git a/include/internal/catch_exception_translator_registry.hpp b/include/internal/catch_exception_translator_registry.hpp index 29ddf8e71c..c4bdb4005c 100644 --- a/include/internal/catch_exception_translator_registry.hpp +++ b/include/internal/catch_exception_translator_registry.hpp @@ -32,13 +32,13 @@ namespace Catch { #ifdef __OBJC__ // In Objective-C try objective-c exceptions first @try { - throw; + return tryTranslators(); } @catch (NSException *exception) { return Catch::toString( [exception description] ); } #else - throw; + return tryTranslators(); #endif } catch( TestFailureException& ) { @@ -54,20 +54,15 @@ namespace Catch { return msg; } catch(...) { - return tryTranslators( m_translators.begin() ); + return "Unknown exception"; } } - std::string tryTranslators( std::vector::const_iterator it ) const { - if( it == m_translators.end() ) - return "Unknown exception"; - - try { - return (*it)->translate(); - } - catch(...) { - return tryTranslators( it+1 ); - } + std::string tryTranslators() const { + if( m_translators.empty() ) + throw; + else + return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() ); } private: diff --git a/include/internal/catch_interfaces_exception.h b/include/internal/catch_interfaces_exception.h index c2fc5bf591..67247e1e30 100644 --- a/include/internal/catch_interfaces_exception.h +++ b/include/internal/catch_interfaces_exception.h @@ -9,15 +9,20 @@ #define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED #include +#include + #include "catch_interfaces_registry_hub.h" namespace Catch { typedef std::string(*exceptionTranslateFunction)(); + struct IExceptionTranslator; + typedef std::vector ExceptionTranslators; + struct IExceptionTranslator { virtual ~IExceptionTranslator(); - virtual std::string translate() const = 0; + virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0; }; struct IExceptionTranslatorRegistry { @@ -35,9 +40,12 @@ namespace Catch { : m_translateFunction( translateFunction ) {} - virtual std::string translate() const { + virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE { try { - throw; + if( it == itEnd ) + throw; + else + return (*it)->translate( it+1, itEnd ); } catch( T& ex ) { return m_translateFunction( ex ); diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index 2b312e6796..87106c2553 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -356,7 +356,7 @@ due to unexpected exception with message: expected exception ------------------------------------------------------------------------------- -Unexpected custom exceptions can be translated +Non-std exceptions can be translated ------------------------------------------------------------------------------- ExceptionTests.cpp: ............................................................................... @@ -365,6 +365,16 @@ ExceptionTests.cpp:: FAILED: due to unexpected exception with message: custom exception +------------------------------------------------------------------------------- +Custom std-exceptions can be custom translated +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: +due to unexpected exception with message: + custom std exception + ------------------------------------------------------------------------------- Custom exceptions can be translated when testing for nothrow ------------------------------------------------------------------------------- @@ -820,6 +830,6 @@ with expansion: "first" == "second" =============================================================================== -test cases: 165 | 123 passed | 41 failed | 1 failed as expected -assertions: 912 | 817 passed | 82 failed | 13 failed as expected +test cases: 166 | 123 passed | 42 failed | 1 failed as expected +assertions: 913 | 817 passed | 83 failed | 13 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index edfeddedb5..4cbe98bb61 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -1217,7 +1217,7 @@ due to unexpected exception with message: expected exception ------------------------------------------------------------------------------- -Unexpected custom exceptions can be translated +Non-std exceptions can be translated ------------------------------------------------------------------------------- ExceptionTests.cpp: ............................................................................... @@ -1226,6 +1226,16 @@ ExceptionTests.cpp:: FAILED: due to unexpected exception with message: custom exception +------------------------------------------------------------------------------- +Custom std-exceptions can be custom translated +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: +due to unexpected exception with message: + custom std exception + ------------------------------------------------------------------------------- Custom exceptions can be translated when testing for nothrow ------------------------------------------------------------------------------- @@ -9024,6 +9034,6 @@ with expansion: 1 > 0 =============================================================================== -test cases: 165 | 122 passed | 42 failed | 1 failed as expected -assertions: 914 | 817 passed | 84 failed | 13 failed as expected +test cases: 166 | 122 passed | 43 failed | 1 failed as expected +assertions: 915 | 817 passed | 85 failed | 13 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index 0243909efa..4daba14a29 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,5 +1,5 @@ - + @@ -226,9 +226,15 @@ expected exception ExceptionTests.cpp: - + custom exception +ExceptionTests.cpp: + + + + +custom std exception ExceptionTests.cpp: diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index f185891ad4..2ab95bbe4d 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -1545,12 +1545,18 @@ - + custom exception + + + custom std exception + + + @@ -9496,7 +9502,7 @@ there" - + - + diff --git a/projects/SelfTest/ExceptionTests.cpp b/projects/SelfTest/ExceptionTests.cpp index eb8b7d8fb0..949962ec15 100644 --- a/projects/SelfTest/ExceptionTests.cpp +++ b/projects/SelfTest/ExceptionTests.cpp @@ -106,22 +106,50 @@ class CustomException std::string m_msg; }; +class CustomStdException : public std::exception +{ +public: + CustomStdException( const std::string& msg ) + : m_msg( msg ) + {} + + std::string getMessage() const + { + return m_msg; + } + +private: + std::string m_msg; +}; + + CATCH_TRANSLATE_EXCEPTION( CustomException& ex ) { return ex.getMessage(); } +CATCH_TRANSLATE_EXCEPTION( CustomStdException& ex ) +{ + return ex.getMessage(); +} + CATCH_TRANSLATE_EXCEPTION( double& ex ) { return Catch::toString( ex ); } -TEST_CASE("Unexpected custom exceptions can be translated", "[.][failing]" ) +TEST_CASE("Non-std exceptions can be translated", "[.][failing]" ) { if( Catch::alwaysTrue() ) throw CustomException( "custom exception" ); } +TEST_CASE("Custom std-exceptions can be custom translated", "[.][failing]" ) +{ + if( Catch::alwaysTrue() ) + throw CustomException( "custom std exception" ); +} + inline void throwCustom() { if( Catch::alwaysTrue() ) throw CustomException( "custom exception - not std" );