diff options
| author | Martin Hořeňovský | 2017-04-07 22:56:36 +0200 |
|---|---|---|
| committer | Martin Hořeňovský | 2017-04-07 22:56:36 +0200 |
| commit | 1b03c5ab6aff2ca35dafb45a193108b433c8af0d (patch) | |
| tree | 067d668fc7e87cf5a73e234b8e84d1457c0e9544 | |
| parent | 7dd3c19027913acfa3f9fd63da6da979f444cebc (diff) | |
| download | catch3-1.9.0.tar.gz | |
v1.9.0 releasev1.9.0
| -rw-r--r-- | README.md | 2 | ||||
| -rw-r--r-- | docs/release-notes.md | 32 | ||||
| -rw-r--r-- | include/internal/catch_version.hpp | 2 | ||||
| -rw-r--r-- | single_include/catch.hpp | 537 |
4 files changed, 344 insertions, 229 deletions
@@ -4,7 +4,7 @@ [](https://travis-ci.org/philsquared/Catch) [](https://ci.appveyor.com/project/philsquared/catch/branch/master) -<a href="https://github.com/philsquared/Catch/releases/download/v1.8.2/catch.hpp">The latest, single header, version can be downloaded directly using this link</a> +<a href="https://github.com/philsquared/Catch/releases/download/v1.9.0/catch.hpp">The latest, single header, version can be downloaded directly using this link</a> ## What's the Catch? diff --git a/docs/release-notes.md b/docs/release-notes.md index 1e69eea5..a96ab898 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -1,3 +1,35 @@ +# 1.9.0 + + +### Improvements and minor changes +* Catch no longer attempts to ensure the exception type passed by user in `REQUIRE_THROWS_AS` is a constant reference. + * It was causing trouble when `REQUIRE_THROWS_AS` was used inside templated functions + * This actually reverts changes made in v1.7.2 +* Catch's `Version` struct should no longer be double freed when multiple instances of Catch tests are loaded into single program (#858) + * It is now a static variable in an inline function instead of being an `extern`ed struct. +* Attempt to register invalid tag or tag alias now throws instead of calling `exit()`. + * Because this happen before entering main, it still aborts execution + * Further improvements to this are coming +* `CATCH_CONFIG_FAST_COMPILE` now speeds-up compilation of `REQUIRE*` assertions by further ~15%. + * The trade-off is disabling translation of unexpected exceptions into text. +* When Catch is compiled using C++11, `Approx` is now constructible with anything that can be explicitly converted to `double`. +* Captured messages are now printed on unexpected exceptions + +### Fixes: +* Clang's `-Wexit-time-destructors` should be suppressed for Catch's internals +* GCC's `-Wparentheses` is now suppressed for all TU's that include `catch.hpp`. + * This is functionally a revert of changes made in 1.8.0, where we tried using `_Pragma` based suppression. This should have kept the suppression local to Catch's assertions, but bugs in GCC's handling of `_Pragma`s in C++ mode meant that it did not always work. +* You can now tell Catch to use C++11-based check when checking whether a type can be streamed to output. + * This fixes cases when an unstreamable type has streamable private base (#877) + * [Details can be found in documentation](configuration.md#catch_config_cpp11_stream_insertable_check) + + +### Other notes: +* We have added VS 2017 to our CI +* Work on Catch 2 should start soon + + + # 1.8.2 diff --git a/include/internal/catch_version.hpp b/include/internal/catch_version.hpp index 4ce90645..744eb5d4 100644 --- a/include/internal/catch_version.hpp +++ b/include/internal/catch_version.hpp @@ -38,7 +38,7 @@ namespace Catch { } inline Version libraryVersion() { - static Version version(1, 8, 2, "", 0); + static Version version( 1, 9, 0, "", 0 ); return version; } diff --git a/single_include/catch.hpp b/single_include/catch.hpp index 79036a40..f6c44e42 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -1,6 +1,6 @@ /* - * Catch v1.8.2 - * Generated: 2017-03-13 21:18:33.619572 + * Catch v1.9.0 + * Generated: 2017-04-07 22:51:48.249456 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -40,11 +40,7 @@ #elif defined __GNUC__ # pragma GCC diagnostic ignored "-Wvariadic-macros" # pragma GCC diagnostic ignored "-Wunused-variable" - - // For newer version we can use __Pragma to disable the warnings locally -# if __GNUC__ == 4 && __GNUC_MINOR__ >= 4 && __GNUC_MINOR__ <= 7 -# pragma GCC diagnostic ignored "-Wparentheses" -# endif +# pragma GCC diagnostic ignored "-Wparentheses" # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wpadded" @@ -124,6 +120,12 @@ # endif # if defined(CATCH_CPP11_OR_GREATER) +# define CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ + _Pragma( "clang diagnostic push" ) \ + _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) +# define CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ + _Pragma( "clang diagnostic pop" ) + # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ _Pragma( "clang diagnostic push" ) \ _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) @@ -169,22 +171,10 @@ // GCC #ifdef __GNUC__ -# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) -# define CATCH_GCC_HAS_NEW_PRAGMA -# endif - # if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR # endif -# if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) && defined(CATCH_GCC_HAS_NEW_PRAGMA) -# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ - _Pragma( "GCC diagnostic push" ) \ - _Pragma( "GCC diagnostic ignored \"-Wparentheses\"" ) -# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ - _Pragma( "GCC diagnostic pop" ) -# endif - // - otherwise more recent versions define __cplusplus >= 201103L // and will get picked up below @@ -332,6 +322,10 @@ # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS # define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS #endif +#if !defined(CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS +# define CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS +#endif // noexcept support: #if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT) @@ -770,59 +764,76 @@ void registerTestCaseFunction /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ static void TestName(); \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\ + CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); } \ + CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ static void TestName() #define INTERNAL_CATCH_TESTCASE( ... ) \ INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } + CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } \ + CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ + CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ namespace{ \ struct TestName : ClassName{ \ void test(); \ }; \ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \ } \ + CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ void TestName::test() #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \ INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ - Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); + CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ + Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); \ + CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS #else /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \ static void TestName(); \ + CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\ + CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ static void TestName() #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \ INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), Name, Desc ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } + CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } \ + CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\ + CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ namespace{ \ struct TestCaseName : ClassName{ \ void test(); \ }; \ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \ } \ + CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ void TestCaseName::test() #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\ INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, TestName, Desc ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \ - Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); + CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ + Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); \ + CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS + #endif // #included from: internal/catch_capture.hpp @@ -1192,6 +1203,7 @@ namespace Catch { char const* capturedExpression, ResultDisposition::Flags resultDisposition, char const* secondArg = "" ); + ~ResultBuilder(); template<typename T> ExpressionLhs<T const&> operator <= ( T const& operand ); @@ -1226,6 +1238,9 @@ namespace Catch { template<typename ArgT, typename MatcherT> void captureMatch( ArgT const& arg, MatcherT const& matcher, char const* matcherString ); + void setExceptionGuard(); + void unsetExceptionGuard(); + private: AssertionInfo m_assertionInfo; AssertionResultData m_data; @@ -1233,6 +1248,7 @@ namespace Catch { bool m_shouldDebugBreak; bool m_shouldThrow; + bool m_guardException; }; } // namespace Catch @@ -1557,6 +1573,7 @@ namespace Detail { extern const std::string unprintableString; + #if !defined(CATCH_CONFIG_CPP11_STREAM_INSERTABLE_CHECK) struct BorgType { template<typename T> BorgType( T const& ); }; @@ -1575,6 +1592,20 @@ namespace Detail { static T const&t; enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) }; }; +#else + template<typename T> + class IsStreamInsertable { + template<typename SS, typename TT> + static auto test(int) + -> decltype( std::declval<SS&>() << std::declval<TT>(), std::true_type() ); + + template<typename, typename> + static auto test(...) -> std::false_type; + + public: + static const bool value = decltype(test<std::ostream,const T&>(0))::value; + }; +#endif #if defined(CATCH_CONFIG_CPP11_IS_ENUM) template<typename T, @@ -2017,6 +2048,8 @@ namespace Catch { virtual std::string getCurrentTestName() const = 0; virtual const AssertionResult* getLastResult() const = 0; + virtual void exceptionEarlyReported() = 0; + virtual void handleFatalErrorCondition( std::string const& message ) = 0; }; @@ -2101,45 +2134,6 @@ namespace Catch { }; } -// #included from: catch_type_traits.hpp -#define TWOBLUECUBES_CATCH_TYPE_TRAITS_HPP_INCLUDED - -#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) -#include <type_traits> -#endif - -namespace Catch { - -#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) - - template <typename T> - using add_lvalue_reference = std::add_lvalue_reference<T>; - - template <typename T> - using add_const = std::add_const<T>; - -#else - - template <typename T> - struct add_const { - typedef const T type; - }; - - template <typename T> - struct add_lvalue_reference { - typedef T& type; - }; - template <typename T> - struct add_lvalue_reference<T&> { - typedef T& type; - }; - // No && overload, because that is C++11, in which case we have - // proper type_traits implementation from the standard library - -#endif - -} - #if defined(CATCH_CONFIG_FAST_COMPILE) /////////////////////////////////////////////////////////////////////////////// // We can speedup compilation significantly by breaking into debugger lower in @@ -2147,6 +2141,33 @@ namespace Catch { // macro in each assertion #define INTERNAL_CATCH_REACT( resultBuilder ) \ resultBuilder.react(); + +/////////////////////////////////////////////////////////////////////////////// +// Another way to speed-up compilation is to omit local try-catch for REQUIRE* +// macros. +// This can potentially cause false negative, if the test code catches +// the exception before it propagates back up to the runner. +#define INTERNAL_CATCH_TEST_NO_TRY( macroName, resultDisposition, expr ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + __catchResult.setExceptionGuard(); \ + CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ + ( __catchResult <= expr ).endExpression(); \ + CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ + __catchResult.unsetExceptionGuard(); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::isTrue( false && static_cast<bool>( !!(expr) ) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look +// The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. + +#define INTERNAL_CHECK_THAT_NO_TRY( macroName, matcher, resultDisposition, arg ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ + __catchResult.setExceptionGuard(); \ + __catchResult.captureMatch( arg, matcher, #matcher ); \ + __catchResult.unsetExceptionGuard(); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + #else /////////////////////////////////////////////////////////////////////////////// // In the event of a failure works out if the debugger needs to be invoked @@ -2159,7 +2180,7 @@ namespace Catch { #endif /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \ +#define INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ) \ do { \ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ try { \ @@ -2175,17 +2196,17 @@ namespace Catch { // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \ - INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ +#define INTERNAL_CATCH_IF( macroName, resultDisposition, expr ) \ + INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ); \ if( Catch::getResultCapture().getLastResult()->succeeded() ) /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \ - INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ +#define INTERNAL_CATCH_ELSE( macroName, resultDisposition, expr ) \ + INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ); \ if( !Catch::getResultCapture().getLastResult()->succeeded() ) /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \ +#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, expr ) \ do { \ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ try { \ @@ -2199,7 +2220,7 @@ namespace Catch { } while( Catch::alwaysFalse() ) /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_THROWS( expr, resultDisposition, matcher, macroName ) \ +#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, matcher, expr ) \ do { \ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \ if( __catchResult.allowThrows() ) \ @@ -2216,7 +2237,7 @@ namespace Catch { } while( Catch::alwaysFalse() ) /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \ +#define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \ do { \ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr ", " #exceptionType, resultDisposition ); \ if( __catchResult.allowThrows() ) \ @@ -2224,7 +2245,7 @@ namespace Catch { static_cast<void>(expr); \ __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ } \ - catch( Catch::add_const<Catch::add_lvalue_reference<exceptionType>::type>::type ) { \ + catch( exceptionType ) { \ __catchResult.captureResult( Catch::ResultWas::Ok ); \ } \ catch( ... ) { \ @@ -2237,7 +2258,7 @@ namespace Catch { /////////////////////////////////////////////////////////////////////////////// #ifdef CATCH_CONFIG_VARIADIC_MACROS - #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \ + #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \ do { \ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \ @@ -2255,11 +2276,11 @@ namespace Catch { #endif /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_INFO( log, macroName ) \ +#define INTERNAL_CATCH_INFO( macroName, log ) \ Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log; /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \ +#define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ do { \ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ try { \ @@ -2432,7 +2453,6 @@ namespace Catch { // #included from: internal/catch_generators.hpp #define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED -#include <iterator> #include <vector> #include <string> #include <stdlib.h> @@ -2546,7 +2566,7 @@ public: private: void move( CompositeGenerator& other ) { - std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) ); + m_composed.insert( m_composed.end(), other.m_composed.begin(), other.m_composed.end() ); m_totalSize += other.m_totalSize; other.m_composed.clear(); } @@ -2628,12 +2648,15 @@ namespace Catch { struct IExceptionTranslator; struct IReporterRegistry; struct IReporterFactory; + struct ITagAliasRegistry; struct IRegistryHub { virtual ~IRegistryHub(); virtual IReporterRegistry const& getReporterRegistry() const = 0; virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; + virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0; + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; }; @@ -2643,6 +2666,7 @@ namespace Catch { virtual void registerListener( Ptr<IReporterFactory> const& factory ) = 0; virtual void registerTest( TestCase const& testInfo ) = 0; virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; + virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0; }; IRegistryHub& getRegistryHub(); @@ -2754,6 +2778,11 @@ namespace Detail { } #if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) + + template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> + explicit Approx( T value ): Approx(static_cast<double>(value)) + {} + template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> friend bool operator == ( const T& lhs, Approx const& rhs ) { // Thanks to Richard Harris for his help refining this formula @@ -2781,27 +2810,23 @@ namespace Detail { } template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> - friend bool operator <= ( T lhs, Approx const& rhs ) - { - return double(lhs) < rhs.m_value || lhs == rhs; + friend bool operator <= ( T lhs, Approx const& rhs ) { + return double(lhs) < rhs.m_value || lhs == rhs; } template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> - friend bool operator <= ( Approx const& lhs, T rhs ) - { - return lhs.m_value < double(rhs) || lhs == rhs; + friend bool operator <= ( Approx const& lhs, T rhs ) { + return lhs.m_value < double(rhs) || lhs == rhs; } template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> - friend bool operator >= ( T lhs, Approx const& rhs ) - { - return double(lhs) > rhs.m_value || lhs == rhs; + friend bool operator >= ( T lhs, Approx const& rhs ) { + return double(lhs) > rhs.m_value || lhs == rhs; } template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> - friend bool operator >= ( Approx const& lhs, T rhs ) - { - return lhs.m_value > double(rhs) || lhs == rhs; + friend bool operator >= ( Approx const& lhs, T rhs ) { + return lhs.m_value > double(rhs) || lhs == rhs; } #else friend bool operator == ( double lhs, Approx const& rhs ) { @@ -2825,24 +2850,20 @@ namespace Detail { return !operator==( rhs, lhs ); } - friend bool operator <= ( double lhs, Approx const& rhs ) - { - return lhs < rhs.m_value || lhs == rhs; + friend bool operator <= ( double lhs, Approx const& rhs ) { + return lhs < rhs.m_value || lhs == rhs; } - friend bool operator <= ( Approx const& lhs, double rhs ) - { - return lhs.m_value < rhs || lhs == rhs; + friend bool operator <= ( Approx const& lhs, double rhs ) { + return lhs.m_value < rhs || lhs == rhs; } - friend bool operator >= ( double lhs, Approx const& rhs ) - { - return lhs > rhs.m_value || lhs == rhs; + friend bool operator >= ( double lhs, Approx const& rhs ) { + return lhs > rhs.m_value || lhs == rhs; } - friend bool operator >= ( Approx const& lhs, double rhs ) - { - return lhs.m_value > rhs || lhs == rhs; + friend bool operator >= ( Approx const& lhs, double rhs ) { + return lhs.m_value > rhs || lhs == rhs; } #endif @@ -5885,13 +5906,14 @@ namespace Catch { // #included from: catch_test_case_tracker.hpp #define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED -#include <map> +#include <algorithm> #include <string> #include <assert.h> #include <vector> -#include <iterator> #include <stdexcept> +CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS + namespace Catch { namespace TestCaseTracking { @@ -6162,12 +6184,12 @@ namespace TestCaseTracking { if( !filters.empty() ) { m_filters.push_back(""); // Root - should never be consulted m_filters.push_back(""); // Test Case - not a section filter - std::copy( filters.begin(), filters.end(), std::back_inserter( m_filters ) ); + m_filters.insert( m_filters.end(), filters.begin(), filters.end() ); } } void addNextFilters( std::vector<std::string> const& filters ) { if( filters.size() > 1 ) - std::copy( filters.begin()+1, filters.end(), std::back_inserter( m_filters ) ); + m_filters.insert( m_filters.end(), ++filters.begin(), filters.end() ); } }; @@ -6237,6 +6259,8 @@ using TestCaseTracking::IndexTracker; } // namespace Catch +CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS + // #included from: catch_fatal_condition.hpp #define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED @@ -6489,7 +6513,8 @@ namespace Catch { m_context( getCurrentMutableContext() ), m_activeTestCase( CATCH_NULL ), m_config( _config ), - m_reporter( reporter ) + m_reporter( reporter ), + m_shouldReportUnexpected ( true ) { m_context.setRunner( this ); m_context.setConfig( m_config ); @@ -6646,6 +6671,10 @@ namespace Catch { return &m_lastResult; } + virtual void exceptionEarlyReported() { + m_shouldReportUnexpected = false; + } + virtual void handleFatalErrorCondition( std::string const& message ) { // Don't rebuild the result -- the stringification itself can cause more fatal errors // Instead, fake a result data. @@ -6695,6 +6724,7 @@ namespace Catch { m_reporter->sectionStarting( testCaseSection ); Counts prevAssertions = m_totals.assertions; double duration = 0; + m_shouldReportUnexpected = true; try { m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, std::string(), ResultDisposition::Normal ); @@ -6716,7 +6746,13 @@ namespace Catch { // This just means the test was aborted due to failure } catch(...) { - makeUnexpectedResultBuilder().useActiveException(); + // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions + // are reported without translation at the point of origin. +#ifdef CATCH_CONFIG_FAST_COMPILE + if (m_shouldReportUnexpected) { + makeUnexpectedResultBuilder().useActiveException(); + } +#endif } m_testCaseTracker->close(); handleUnfinishedSections(); @@ -6776,6 +6812,7 @@ namespace Catch { std::vector<SectionEndInfo> m_unfinishedSections; std::vector<ITracker*> m_activeSections; TrackerContext m_trackerContext; + bool m_shouldReportUnexpected; }; IResultCapture& getResultCapture() { @@ -6797,7 +6834,7 @@ namespace Catch { Version( unsigned int _majorVersion, unsigned int _minorVersion, unsigned int _patchNumber, - std::string const& _branchName, + char const * const _branchName, unsigned int _buildNumber ); unsigned int const majorVersion; @@ -6805,7 +6842,7 @@ namespace Catch { unsigned int const patchNumber; // buildNumber is only used if branchName is not null - std::string const branchName; + char const * const branchName; unsigned int const buildNumber; friend std::ostream& operator << ( std::ostream& os, Version const& version ); @@ -6814,7 +6851,7 @@ namespace Catch { void operator=( Version const& ); }; - extern Version libraryVersion; + inline Version libraryVersion(); } #include <fstream> @@ -6926,7 +6963,7 @@ namespace Catch { } void showHelp( std::string const& processName ) { - Catch::cout() << "\nCatch v" << libraryVersion << "\n"; + Catch::cout() << "\nCatch v" << libraryVersion() << "\n"; m_cli.usage( Catch::cout(), processName ); Catch::cout() << "For more detail usage please see the project docs\n" << std::endl; @@ -7314,6 +7351,26 @@ namespace Catch { }; } +// #included from: catch_tag_alias_registry.h +#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED + +#include <map> + +namespace Catch { + + class TagAliasRegistry : public ITagAliasRegistry { + public: + virtual ~TagAliasRegistry(); + virtual Option<TagAlias> find( std::string const& alias ) const; + virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const; + void add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ); + + private: + std::map<std::string, TagAlias> m_registry; + }; + +} // end namespace Catch + namespace Catch { namespace { @@ -7335,6 +7392,9 @@ namespace Catch { virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE { return m_exceptionTranslatorRegistry; } + virtual ITagAliasRegistry const& getTagAliasRegistry() const CATCH_OVERRIDE { + return m_tagAliasRegistry; + } public: // IMutableRegistryHub virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE { @@ -7349,11 +7409,15 @@ namespace Catch { virtual void registerTranslator( const IExceptionTranslator* translator ) CATCH_OVERRIDE { m_exceptionTranslatorRegistry.registerTranslator( translator ); } + virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) CATCH_OVERRIDE { + m_tagAliasRegistry.add( alias, tag, lineInfo ); + } private: TestRegistry m_testCaseRegistry; ReporterRegistry m_reporterRegistry; ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; + TagAliasRegistry m_tagAliasRegistry; }; // Single, global, instance @@ -7980,17 +8044,13 @@ namespace Catch { } inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { if( isReservedTag( tag ) ) { - { - Colour colourGuard( Colour::Red ); - Catch::cerr() - << "Tag name [" << tag << "] not allowed.\n" - << "Tag names starting with non alpha-numeric characters are reserved\n"; - } - { - Colour colourGuard( Colour::FileName ); - Catch::cerr() << _lineInfo << std::endl; - } - exit(1); + std::ostringstream ss; + ss << Colour(Colour::Red) + << "Tag name [" << tag << "] not allowed.\n" + << "Tag names starting with non alpha-numeric characters are reserved\n" + << Colour(Colour::FileName) + << _lineInfo << '\n'; + throw std::runtime_error(ss.str()); } } @@ -8152,7 +8212,7 @@ namespace Catch { ( unsigned int _majorVersion, unsigned int _minorVersion, unsigned int _patchNumber, - std::string const& _branchName, + char const * const _branchName, unsigned int _buildNumber ) : majorVersion( _majorVersion ), minorVersion( _minorVersion ), @@ -8165,15 +8225,18 @@ namespace Catch { os << version.majorVersion << '.' << version.minorVersion << '.' << version.patchNumber; - - if( !version.branchName.empty() ) { - os << '-' << version.branchName - << '.' << version.buildNumber; + // branchName is never null -> 0th char is \0 if it is empty + if (version.branchName[0]) { + os << '-' << version.branchName + << '.' << version.buildNumber; } return os; } - Version libraryVersion( 1, 8, 2, "", 0 ); + inline Version libraryVersion() { + static Version version( 1, 9, 0, "", 0 ); + return version; + } } @@ -8207,7 +8270,9 @@ namespace Catch { {} ScopedMessage::~ScopedMessage() { - getResultCapture().popScopedMessage( m_info ); + if ( !std::uncaught_exception() ){ + getResultCapture().popScopedMessage(m_info); + } } } // end namespace Catch @@ -8874,9 +8939,20 @@ namespace Catch { char const* secondArg ) : m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ), m_shouldDebugBreak( false ), - m_shouldThrow( false ) + m_shouldThrow( false ), + m_guardException( false ) {} + ResultBuilder::~ResultBuilder() { |