diff --git a/Test/ExceptionTests.cpp b/Test/ExceptionTests.cpp index e0332be8..caad6fd8 100644 --- a/Test/ExceptionTests.cpp +++ b/Test/ExceptionTests.cpp @@ -62,3 +62,36 @@ TEST_CASE( "./succeeding/exceptions/implicit", "When unchecked exceptions are th { } } + +class CustomException +{ +public: + CustomException( const std::string& msg ) + : m_msg( msg ) + {} + + std::string getMessage() const + { + return m_msg; + } + +private: + std::string m_msg; +}; + + +namespace Catch +{ + ExceptionTranslator translator; + + template<> + std::string ExceptionTranslator::translate( CustomException& ex ) const + { + return ex.getMessage(); + } +} + +TEST_CASE_NORETURN( "./succeeding/exceptions/custom", "" ) +{ + throw CustomException( "custom exception" ); +} diff --git a/Test/Test.xcodeproj/project.pbxproj b/Test/Test.xcodeproj/project.pbxproj index 9767a657..87b489e7 100644 --- a/Test/Test.xcodeproj/project.pbxproj +++ b/Test/Test.xcodeproj/project.pbxproj @@ -32,6 +32,8 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 4A13FF93135EBF0000EC5928 /* catch_exception_translator_registry.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_exception_translator_registry.hpp; path = ../internal/catch_exception_translator_registry.hpp; sourceTree = SOURCE_ROOT; }; + 4A13FF94135EBF2600EC5928 /* catch_interfaces_exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = catch_interfaces_exception.h; path = ../internal/catch_interfaces_exception.h; sourceTree = SOURCE_ROOT; }; 4A15D2B712E0418F0005EB03 /* catch_self_test.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_self_test.hpp; path = ../internal/catch_self_test.hpp; sourceTree = SOURCE_ROOT; }; 4A15D4A812E4DF0D0005EB03 /* catch_stream.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_stream.hpp; path = ../internal/catch_stream.hpp; sourceTree = SOURCE_ROOT; }; 4A302DE312D5114900C84B67 /* catch.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch.hpp; path = ../catch.hpp; sourceTree = SOURCE_ROOT; }; @@ -116,6 +118,15 @@ name = Products; sourceTree = ""; }; + 4A13FF92135EBED500EC5928 /* Exceptions */ = { + isa = PBXGroup; + children = ( + 4A13FF93135EBF0000EC5928 /* catch_exception_translator_registry.hpp */, + 4A13FF94135EBF2600EC5928 /* catch_interfaces_exception.h */, + ); + name = Exceptions; + sourceTree = ""; + }; 4A302E3712D515B700C84B67 /* TestCase registration */ = { isa = PBXGroup; children = ( @@ -216,6 +227,7 @@ 4AFC341412809A1B003A0C29 /* Internal */ = { isa = PBXGroup; children = ( + 4A13FF92135EBED500EC5928 /* Exceptions */, 4A302E3912D5160400C84B67 /* Hub */, 4A302E3812D515DF00C84B67 /* Running & Results */, 4A302E3712D515B700C84B67 /* TestCase registration */, diff --git a/catch.hpp b/catch.hpp index 0a241b09..488dde45 100644 --- a/catch.hpp +++ b/catch.hpp @@ -28,6 +28,7 @@ #include "internal/catch_capture.hpp" #include "internal/catch_section.hpp" #include "internal/catch_generators.hpp" +#include "internal/catch_interfaces_exception.h" ////// diff --git a/internal/catch_exception_translator_registry.hpp b/internal/catch_exception_translator_registry.hpp new file mode 100644 index 00000000..3c677545 --- /dev/null +++ b/internal/catch_exception_translator_registry.hpp @@ -0,0 +1,63 @@ +/* + * catch_exception_translator_registry.hpp + * Catch + * + * Created by Phil on 20/04/2011. + * Copyright 2011 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_EXCEPTION_TRANSLATOR_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_HPP_INCLUDED + +#include "catch_interfaces_exception.h" + +namespace Catch +{ + class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry + { + /////////////////////////////////////////////////////////////////////// + virtual void registerTranslator + ( + IExceptionTranslator* translator + ) + { + m_translators.push_back( translator ); + } + + /////////////////////////////////////////////////////////////////////// + virtual std::string translateActiveException + () + const + { + return tryTranslators( m_translators.begin() ); + } + + /////////////////////////////////////////////////////////////////////// + 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 ); + } + } + + private: + std::vector m_translators; + }; +} + +#endif // TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_HPP_INCLUDED diff --git a/internal/catch_hub.h b/internal/catch_hub.h index 1926e141..63e4468e 100644 --- a/internal/catch_hub.h +++ b/internal/catch_hub.h @@ -24,6 +24,7 @@ namespace Catch struct IResultCapture; struct ITestCaseRegistry; struct IRunner; + struct IExceptionTranslatorRegistry; class GeneratorsForTest; class StreamBufBase : public std::streambuf @@ -58,6 +59,9 @@ namespace Catch static ITestCaseRegistry& getTestCaseRegistry (); + static IExceptionTranslatorRegistry& getExceptionTranslatorRegistry + (); + static std::streambuf* createStreamBuf ( const std::string& streamName ); @@ -82,6 +86,7 @@ namespace Catch std::auto_ptr m_reporterRegistry; std::auto_ptr m_testCaseRegistry; + std::auto_ptr m_exceptionTranslatorRegistry; IRunner* m_runner; IResultCapture* m_resultCapture; std::map m_generatorsByTestName; diff --git a/internal/catch_hub_impl.hpp b/internal/catch_hub_impl.hpp index 34d8631e..437bc427 100644 --- a/internal/catch_hub_impl.hpp +++ b/internal/catch_hub_impl.hpp @@ -12,6 +12,7 @@ #include "catch_hub.h" #include "catch_reporter_registry.hpp" #include "catch_test_case_registry_impl.hpp" +#include "catch_exception_translator_registry.hpp" #include "catch_runner_impl.hpp" #include "catch_generators_impl.hpp" #include "catch_stream.hpp" @@ -22,7 +23,8 @@ namespace Catch Hub::Hub () : m_reporterRegistry( new ReporterRegistry ), - m_testCaseRegistry( new TestRegistry ) + m_testCaseRegistry( new TestRegistry ), + m_exceptionTranslatorRegistry( new ExceptionTranslatorRegistry ) { } @@ -73,6 +75,13 @@ namespace Catch return *me().m_testCaseRegistry.get(); } + /////////////////////////////////////////////////////////////////////////// + IExceptionTranslatorRegistry& Hub::getExceptionTranslatorRegistry + () + { + return *me().m_exceptionTranslatorRegistry.get(); + } + /////////////////////////////////////////////////////////////////////////// std::streambuf* Hub::createStreamBuf ( diff --git a/internal/catch_interfaces_exception.h b/internal/catch_interfaces_exception.h new file mode 100644 index 00000000..b7edc013 --- /dev/null +++ b/internal/catch_interfaces_exception.h @@ -0,0 +1,67 @@ +/* + * catch_exception_interfaces.h + * Catch + * + * Created by Phil on 20/04/2011. + * Copyright 2011 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_EXCEPTIONS_H_INCLUDED +#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTIONS_H_INCLUDED + +#include + +namespace Catch +{ + typedef std::string(*exceptionTranslateFunction)(); + + struct IExceptionTranslator + { + virtual ~IExceptionTranslator(){} + virtual std::string translate() const = 0; + }; + + struct IExceptionTranslatorRegistry + { + virtual ~IExceptionTranslatorRegistry + () + {} + + virtual void registerTranslator + ( IExceptionTranslator* translator + ) = 0; + virtual std::string translateActiveException + () const = 0; + + }; + + template + class ExceptionTranslator : public IExceptionTranslator + { + public: + ExceptionTranslator() + { + Catch::Hub::getExceptionTranslatorRegistry().registerTranslator( this ); + } + + virtual std::string translate() const + { + try + { + throw; + } + catch( T& ex ) + { + return translate( ex ); + } + } + + protected: + std::string translate( T& ex ) const; + }; +} + +#endif // TWOBLUECUBES_CATCH_INTERFACES_EXCEPTIONS_H_INCLUDED diff --git a/internal/catch_runner_impl.hpp b/internal/catch_runner_impl.hpp index 4c528bc3..38845fe1 100644 --- a/internal/catch_runner_impl.hpp +++ b/internal/catch_runner_impl.hpp @@ -577,7 +577,7 @@ namespace Catch } catch(...) { - acceptMessage( "unknown exception" ); + acceptMessage( Catch::Hub::getExceptionTranslatorRegistry().translateActiveException() ); acceptResult( ResultWas::ThrewException ); } m_info.clear();