mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-11-04 14:09:33 +01:00 
			
		
		
		
	merge from tags
This commit is contained in:
		@@ -19,6 +19,7 @@
 | 
			
		||||
 | 
			
		||||
#if (_MANAGED == 1) || (_M_CEE == 1) // detect CLR
 | 
			
		||||
    #define INTERNAL_CATCH_VS_MANAGED
 | 
			
		||||
    #define INTERNAL_CATCH_INLINE inline
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
#if defined(_WINDLL)
 | 
			
		||||
@@ -26,6 +27,7 @@
 | 
			
		||||
    // It's possible that this is not enough for someone so allow it to be overridden...
 | 
			
		||||
    #if !defined( CATCH_CONFIG_MAIN ) && !defined( CATCH_CONFIG_RUNNER )
 | 
			
		||||
    #define INTERNAL_CATCH_VS_NATIVE
 | 
			
		||||
    #define INTERNAL_CATCH_INLINE inline
 | 
			
		||||
    #endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@@ -52,7 +54,6 @@
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(INTERNAL_CATCH_VS_MANAGED) || defined(INTERNAL_CATCH_VS_NATIVE)
 | 
			
		||||
    #define INTERNAL_CATCH_INLINE inline
 | 
			
		||||
    #ifdef INTERNAL_CATCH_VS_MANAGED
 | 
			
		||||
        #include "internal/catch_vs_managed_impl.hpp"
 | 
			
		||||
    #else // INTERNAL_CATCH_VS_MANAGED
 | 
			
		||||
@@ -203,6 +204,16 @@
 | 
			
		||||
#define THEN( desc )     SECTION( "    Then: " desc, "" )
 | 
			
		||||
#define AND_THEN( desc ) SECTION( "     And: " desc, "" )
 | 
			
		||||
 | 
			
		||||
#if defined(INTERNAL_CATCH_VS_MANAGED) || defined(INTERNAL_CATCH_VS_NATIVE)
 | 
			
		||||
#define CATCH_MAP_CATEGORY_TO_TAG( Category, Tag ) INTERNAL_CATCH_MAP_CATEGORY_TO_TAG( Category, Tag )
 | 
			
		||||
#define CATCH_CONFIG_SHOW_SUCCESS( v ) CATCH_INTERNAL_CONFIG_SHOW_SUCCESS( v )
 | 
			
		||||
#define CATCH_CONFIG_WARN_MISSING_ASSERTIONS( v ) CATCH_INTERNAL_CONFIG_WARN_MISSING_ASSERTIONS( v )
 | 
			
		||||
#else
 | 
			
		||||
#define CATCH_MAP_CATEGORY_TO_TAG( Category, Tag )
 | 
			
		||||
#define CATCH_CONFIG_SHOW_SUCCESS( v )
 | 
			
		||||
#define CATCH_CONFIG_WARN_MISSING_ASSERTIONS( v )
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
using Catch::Detail::Approx;
 | 
			
		||||
 | 
			
		||||
#ifdef __clang__
 | 
			
		||||
 
 | 
			
		||||
@@ -108,6 +108,8 @@ namespace Catch {
 | 
			
		||||
        std::set<TestCase> m_testsAlreadyRun;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
#if !defined(INTERNAL_CATCH_VS_MANAGED) && !defined(INTERNAL_CATCH_VS_NATIVE)
 | 
			
		||||
 | 
			
		||||
    class Session {
 | 
			
		||||
        static bool alreadyInstantiated;
 | 
			
		||||
 | 
			
		||||
@@ -232,6 +234,8 @@ namespace Catch {
 | 
			
		||||
 | 
			
		||||
    bool Session::alreadyInstantiated = false;
 | 
			
		||||
 | 
			
		||||
#endif // !VS_MANAGED && !VS_NATIVE
 | 
			
		||||
 | 
			
		||||
} // end namespace Catch
 | 
			
		||||
 | 
			
		||||
#endif // TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
 | 
			
		||||
 
 | 
			
		||||
@@ -58,11 +58,7 @@ namespace Catch {
 | 
			
		||||
            .setResultType( matcher.match( arg ) );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#if defined(INTERNAL_CATCH_VS_MANAGED)
 | 
			
		||||
    // TestFailureException not defined for CLR
 | 
			
		||||
#else // detect CLR
 | 
			
		||||
struct TestFailureException{};
 | 
			
		||||
#endif
 | 
			
		||||
    struct TestFailureException{};
 | 
			
		||||
 | 
			
		||||
} // end namespace Catch
 | 
			
		||||
 | 
			
		||||
@@ -72,7 +68,6 @@ struct TestFailureException{};
 | 
			
		||||
#if !defined(INTERNAL_CATCH_VS_MANAGED) && !defined(INTERNAL_CATCH_VS_NATIVE)
 | 
			
		||||
 | 
			
		||||
    // normal Catch
 | 
			
		||||
    #define INTERNAL_CATCH_TEST_FAILURE_EXCEPTION const Catch::TestFailureException&
 | 
			
		||||
    #define INTERNAL_CATCH_TEST_THROW_FAILURE throw Catch::TestFailureException();
 | 
			
		||||
 | 
			
		||||
#else   // VS integration
 | 
			
		||||
@@ -86,10 +81,9 @@ struct TestFailureException{};
 | 
			
		||||
        std::stringstream _sf; \
 | 
			
		||||
        _sf << r->getExpressionInMacro().c_str() << ", " << r->getMessage().c_str(); \
 | 
			
		||||
        std::string fail = _sf.str(); \
 | 
			
		||||
        Assert::Fail(Catch::convert_string_to_managed(fail)); \
 | 
			
		||||
        Assert::Fail(Catch::convert_string_for_assert(fail)); \
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #define INTERNAL_CATCH_TEST_FAILURE_EXCEPTION AssertFailedException^
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
#if defined(INTERNAL_CATCH_VS_NATIVE)
 | 
			
		||||
@@ -108,8 +102,6 @@ struct TestFailureException{};
 | 
			
		||||
        Assert::Fail(ws2.c_str(), &li); \
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #define INTERNAL_CATCH_TEST_FAILURE_EXCEPTION const Catch::TestFailureException&
 | 
			
		||||
 | 
			
		||||
#endif // INTERNAL_CATCH_VS_MANAGED
 | 
			
		||||
 | 
			
		||||
#endif // detect CLR
 | 
			
		||||
@@ -121,7 +113,7 @@ struct TestFailureException{};
 | 
			
		||||
    if( Catch::ResultAction::Value internal_catch_action = Catch::getResultCapture().acceptExpression( evaluatedExpr, INTERNAL_CATCH_ASSERTIONINFO_NAME )  ) { \
 | 
			
		||||
        if( internal_catch_action & Catch::ResultAction::Debug ) CATCH_BREAK_INTO_DEBUGGER(); \
 | 
			
		||||
        if( internal_catch_action & Catch::ResultAction::Abort ) { INTERNAL_CATCH_TEST_THROW_FAILURE } \
 | 
			
		||||
        if( !Catch::shouldContinueOnFailure( resultDisposition ) ) { INTERNAL_CATCH_TEST_THROW_FAILURE } \
 | 
			
		||||
        if( !Catch::shouldContinueOnFailure( resultDisposition ) ) { throw Catch::TestFailureException(); } \
 | 
			
		||||
        Catch::isTrue( false && originalExpr ); \
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -135,7 +127,7 @@ struct TestFailureException{};
 | 
			
		||||
        INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \
 | 
			
		||||
        try { \
 | 
			
		||||
            INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionDecomposer()->*expr ).endExpression( resultDisposition ), resultDisposition, expr ); \
 | 
			
		||||
        } catch( INTERNAL_CATCH_TEST_FAILURE_EXCEPTION ) { \
 | 
			
		||||
        } catch( const Catch::TestFailureException& ) { \
 | 
			
		||||
            throw; \
 | 
			
		||||
        } catch( ... ) { \
 | 
			
		||||
            INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException(), \
 | 
			
		||||
@@ -174,7 +166,7 @@ struct TestFailureException{};
 | 
			
		||||
            INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::DidntThrowException ), resultDisposition, false ); \
 | 
			
		||||
        } \
 | 
			
		||||
    } \
 | 
			
		||||
    catch( INTERNAL_CATCH_TEST_FAILURE_EXCEPTION ) { \
 | 
			
		||||
    catch( const Catch::TestFailureException& ) { \
 | 
			
		||||
        throw; \
 | 
			
		||||
    } \
 | 
			
		||||
    catch( exceptionType ) { \
 | 
			
		||||
@@ -218,7 +210,7 @@ struct TestFailureException{};
 | 
			
		||||
        INTERNAL_CATCH_ACCEPT_INFO( #arg " " #matcher, macroName, resultDisposition ); \
 | 
			
		||||
        try { \
 | 
			
		||||
            INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::expressionResultBuilderFromMatcher( ::Catch::Matchers::matcher, arg, #matcher ) ), resultDisposition, false ); \
 | 
			
		||||
        } catch( INTERNAL_CATCH_TEST_FAILURE_EXCEPTION ) { \
 | 
			
		||||
        } catch( const Catch::TestFailureException& ) { \
 | 
			
		||||
            throw; \
 | 
			
		||||
        } catch( ... ) { \
 | 
			
		||||
            INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException() ), \
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,138 @@
 | 
			
		||||
#define CATCH_CONFIG_CONSOLE_WIDTH 80
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
namespace CatchOverrides {
 | 
			
		||||
 | 
			
		||||
    class ConfigGuard
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        ConfigGuard()
 | 
			
		||||
            : origConfig(Catch::getCurrentContext().getConfig())
 | 
			
		||||
        {}
 | 
			
		||||
        ~ConfigGuard()
 | 
			
		||||
        {
 | 
			
		||||
            Catch::getCurrentMutableContext().setConfig(origConfig);
 | 
			
		||||
        }
 | 
			
		||||
        const Catch::Ptr<Catch::IConfig const>& value() const {return origConfig;}
 | 
			
		||||
    private:
 | 
			
		||||
        ConfigGuard(const ConfigGuard&);
 | 
			
		||||
        ConfigGuard& operator=(const ConfigGuard&);
 | 
			
		||||
        
 | 
			
		||||
        const Catch::Ptr<Catch::IConfig const> origConfig;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    template <typename T>
 | 
			
		||||
    class Config
 | 
			
		||||
    {
 | 
			
		||||
        typedef std::map<int, bool> LineData;
 | 
			
		||||
        typedef std::map<std::string, LineData> FileLineData;
 | 
			
		||||
    public:
 | 
			
		||||
        bool includeSuccessfulResults(const std::string& file, int c) const
 | 
			
		||||
        {
 | 
			
		||||
            bool result(false);
 | 
			
		||||
            FileLineData::const_iterator it = showSuccessfulTestsData.find(file);
 | 
			
		||||
            if( it != showSuccessfulTestsData.end() )
 | 
			
		||||
            {
 | 
			
		||||
                for( LineData::const_iterator lineIt = it->second.begin(); lineIt != it->second.end(); ++lineIt )
 | 
			
		||||
                {
 | 
			
		||||
                    if( c <= lineIt->first )
 | 
			
		||||
                        break;
 | 
			
		||||
                    result = lineIt->second;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return result;
 | 
			
		||||
        }
 | 
			
		||||
        void insertSuccessfulResults(const std::string& file, int c, bool v)
 | 
			
		||||
        {
 | 
			
		||||
            FileLineData::iterator it = showSuccessfulTestsData.find(file);
 | 
			
		||||
            if( it == showSuccessfulTestsData.end() )
 | 
			
		||||
            {
 | 
			
		||||
                LineData tmp;
 | 
			
		||||
                tmp.insert(std::make_pair(c,v));
 | 
			
		||||
                showSuccessfulTestsData.insert(std::make_pair(file, tmp));
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                it->second.insert(std::make_pair(c,v));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        bool warnAboutMissingAssertions(const std::string& file, int c) const
 | 
			
		||||
        {
 | 
			
		||||
            bool result(false);
 | 
			
		||||
            FileLineData::const_iterator it = missingAssertionData.find(file);
 | 
			
		||||
            if( it != missingAssertionData.end() )
 | 
			
		||||
            {
 | 
			
		||||
                for( LineData::const_iterator lineIt = it->second.begin(); lineIt != it->second.end(); ++lineIt )
 | 
			
		||||
                {
 | 
			
		||||
                    if( c <= lineIt->first )
 | 
			
		||||
                        break;
 | 
			
		||||
                    result = lineIt->second;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return result;
 | 
			
		||||
        }
 | 
			
		||||
        void insertMissingAssertions(const std::string& file, int c, bool v)
 | 
			
		||||
        {
 | 
			
		||||
            FileLineData::iterator it = missingAssertionData.find(file);
 | 
			
		||||
            if( it == missingAssertionData.end() )
 | 
			
		||||
            {
 | 
			
		||||
                LineData tmp;
 | 
			
		||||
                tmp.insert(std::make_pair(c,v));
 | 
			
		||||
                missingAssertionData.insert(std::make_pair(file, tmp));
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                it->second.insert(std::make_pair(c,v));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        static Config<T>& instance()
 | 
			
		||||
        {
 | 
			
		||||
            if( !s_instance )
 | 
			
		||||
            {
 | 
			
		||||
                s_instance = new Config<T>();
 | 
			
		||||
            }
 | 
			
		||||
            return *s_instance;
 | 
			
		||||
        }
 | 
			
		||||
    private:
 | 
			
		||||
        FileLineData showSuccessfulTestsData;
 | 
			
		||||
        FileLineData missingAssertionData;
 | 
			
		||||
        
 | 
			
		||||
        static Config<T>* s_instance;
 | 
			
		||||
    };
 | 
			
		||||
    template <typename T>
 | 
			
		||||
    Config<T>* Config<T>::s_instance = NULL;
 | 
			
		||||
 | 
			
		||||
    template <typename T>
 | 
			
		||||
    struct ConfigReset
 | 
			
		||||
    {
 | 
			
		||||
        ConfigReset( const std::string& file, int c )
 | 
			
		||||
        {
 | 
			
		||||
            Config<T>::instance().insertSuccessfulResults(file, c, false);
 | 
			
		||||
            Config<T>::instance().insertMissingAssertions(file, c, false);
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    template <typename T>
 | 
			
		||||
    struct ConfigShowSuccessfulTests
 | 
			
		||||
    {
 | 
			
		||||
        template <typename U>
 | 
			
		||||
        ConfigShowSuccessfulTests( const std::string& file, int c, U v )
 | 
			
		||||
        {
 | 
			
		||||
            Config<T>::instance().insertSuccessfulResults(file, c, v ? true : false);
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    template <typename T>
 | 
			
		||||
    struct ConfigWarnMissingAssertions
 | 
			
		||||
    {
 | 
			
		||||
        template <typename U>
 | 
			
		||||
        ConfigWarnMissingAssertions( const std::string& file, int c, U v )
 | 
			
		||||
        {
 | 
			
		||||
            Config<T>::instance().insertMissingAssertions(file, c, v ? true : false);
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace Catch {
 | 
			
		||||
 | 
			
		||||
    struct ConfigData {
 | 
			
		||||
@@ -41,6 +173,21 @@ namespace Catch {
 | 
			
		||||
            showDurations( ShowDurations::DefaultForReporter )
 | 
			
		||||
        {}
 | 
			
		||||
 | 
			
		||||
        explicit ConfigData(const IConfig* other)
 | 
			
		||||
        :   listTests( false ),
 | 
			
		||||
            listTags( false ),
 | 
			
		||||
            listReporters( false ),
 | 
			
		||||
            showSuccessfulTests( other ? other->includeSuccessfulResults() : false ),
 | 
			
		||||
            shouldDebugBreak( false ),
 | 
			
		||||
            noThrow( other ? !other->allowThrows() : false ),
 | 
			
		||||
            showHelp( false ),
 | 
			
		||||
            abortAfter( -1 ),
 | 
			
		||||
            verbosity( Verbosity::Normal ),
 | 
			
		||||
            warnings( other ? (other->warnAboutMissingAssertions() ? WarnAbout::NoAssertions : WarnAbout::Nothing) : WarnAbout::Nothing ),
 | 
			
		||||
            showDurations( other ? other->showDurations() : ShowDurations::DefaultForReporter ),
 | 
			
		||||
            name( other ? other->name() : std::string() )
 | 
			
		||||
        {}
 | 
			
		||||
 | 
			
		||||
        bool listTests;
 | 
			
		||||
        bool listTags;
 | 
			
		||||
        bool listReporters;
 | 
			
		||||
 
 | 
			
		||||
@@ -12,10 +12,6 @@
 | 
			
		||||
 | 
			
		||||
namespace Catch {
 | 
			
		||||
 | 
			
		||||
    namespace Detail {
 | 
			
		||||
        struct IColourImpl;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    struct Colour {
 | 
			
		||||
        enum Code {
 | 
			
		||||
            None = 0,
 | 
			
		||||
@@ -53,12 +49,6 @@ namespace Catch {
 | 
			
		||||
        // Use constructed object for RAII guard
 | 
			
		||||
        Colour( Code _colourCode );
 | 
			
		||||
        ~Colour();
 | 
			
		||||
 | 
			
		||||
        // Use static method for one-shot changes
 | 
			
		||||
        static void use( Code _colourCode );
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        static Detail::IColourImpl* impl;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
} // end namespace Catch
 | 
			
		||||
 
 | 
			
		||||
@@ -10,13 +10,6 @@
 | 
			
		||||
 | 
			
		||||
#include "catch_console_colour.hpp"
 | 
			
		||||
 | 
			
		||||
namespace Catch { namespace Detail {
 | 
			
		||||
    struct IColourImpl {
 | 
			
		||||
        virtual ~IColourImpl() {}
 | 
			
		||||
        virtual void use( Colour::Code _colourCode ) = 0;
 | 
			
		||||
    };
 | 
			
		||||
}}
 | 
			
		||||
 | 
			
		||||
#if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
#ifndef NOMINMAX
 | 
			
		||||
@@ -32,7 +25,7 @@ namespace Catch { namespace Detail {
 | 
			
		||||
namespace Catch {
 | 
			
		||||
namespace {
 | 
			
		||||
 | 
			
		||||
    class Win32ColourImpl : public Detail::IColourImpl {
 | 
			
		||||
    class Win32ColourImpl {
 | 
			
		||||
    public:
 | 
			
		||||
        Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
 | 
			
		||||
        {
 | 
			
		||||
@@ -41,7 +34,7 @@ namespace {
 | 
			
		||||
            originalAttributes = csbiInfo.wAttributes;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtual void use( Colour::Code _colourCode ) {
 | 
			
		||||
        void use( Colour::Code _colourCode ) {
 | 
			
		||||
            switch( _colourCode ) {
 | 
			
		||||
                case Colour::None:      return setTextAttribute( originalAttributes );
 | 
			
		||||
                case Colour::White:     return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
 | 
			
		||||
@@ -73,7 +66,7 @@ namespace {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Win32ColourImpl platformColourImpl;
 | 
			
		||||
    typedef Win32ColourImpl PlatformColourImpl;
 | 
			
		||||
 | 
			
		||||
} // end anon namespace
 | 
			
		||||
} // end namespace Catch
 | 
			
		||||
@@ -89,9 +82,9 @@ namespace {
 | 
			
		||||
    // Thanks to Adam Strzelecki for original contribution
 | 
			
		||||
    // (http://github.com/nanoant)
 | 
			
		||||
    // https://github.com/philsquared/Catch/pull/131
 | 
			
		||||
    class PosixColourImpl : public Detail::IColourImpl {
 | 
			
		||||
    class PosixColourImpl {
 | 
			
		||||
    public:
 | 
			
		||||
        virtual void use( Colour::Code _colourCode ) {
 | 
			
		||||
        void use( Colour::Code _colourCode ) {
 | 
			
		||||
            switch( _colourCode ) {
 | 
			
		||||
                case Colour::None:
 | 
			
		||||
                case Colour::White:     return setColour( "[0m" );
 | 
			
		||||
@@ -120,7 +113,7 @@ namespace {
 | 
			
		||||
        return isatty(STDOUT_FILENO);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    PosixColourImpl platformColourImpl;
 | 
			
		||||
    typedef PosixColourImpl PlatformColourImpl;
 | 
			
		||||
 | 
			
		||||
} // end anon namespace
 | 
			
		||||
} // end namespace Catch
 | 
			
		||||
@@ -129,24 +122,24 @@ namespace {
 | 
			
		||||
 | 
			
		||||
namespace Catch {
 | 
			
		||||
 | 
			
		||||
    namespace {
 | 
			
		||||
        struct NoColourImpl : Detail::IColourImpl {
 | 
			
		||||
            void use( Colour::Code ) {}
 | 
			
		||||
        };
 | 
			
		||||
        NoColourImpl noColourImpl;
 | 
			
		||||
        static const bool shouldUseColour = shouldUseColourForPlatform() &&
 | 
			
		||||
                                            !isDebuggerActive();
 | 
			
		||||
    }
 | 
			
		||||
    template <typename Impl>
 | 
			
		||||
    struct ColourChange
 | 
			
		||||
    {
 | 
			
		||||
        static Impl impl;
 | 
			
		||||
        static const bool shouldUseColour;
 | 
			
		||||
    };
 | 
			
		||||
    template <typename Impl>
 | 
			
		||||
    Impl ColourChange<Impl>::impl;
 | 
			
		||||
    template <typename Impl>
 | 
			
		||||
    const bool ColourChange<Impl>::shouldUseColour = shouldUseColourForPlatform() &&
 | 
			
		||||
                                            !isDebuggerActive();;
 | 
			
		||||
 | 
			
		||||
    Colour::Colour( Code _colourCode ){ use( _colourCode ); }
 | 
			
		||||
    Colour::~Colour(){ use( None ); }
 | 
			
		||||
    void Colour::use( Code _colourCode ) {
 | 
			
		||||
        impl->use( _colourCode );
 | 
			
		||||
    INTERNAL_CATCH_INLINE Colour::Colour( Code _colourCode ) {
 | 
			
		||||
        if( ColourChange<PlatformColourImpl>::shouldUseColour ) ColourChange<PlatformColourImpl>::impl.use( _colourCode );
 | 
			
		||||
    }
 | 
			
		||||
    INTERNAL_CATCH_INLINE Colour::~Colour() {
 | 
			
		||||
        if( ColourChange<PlatformColourImpl>::shouldUseColour ) ColourChange<PlatformColourImpl>::impl.use( Colour::None );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Detail::IColourImpl* Colour::impl = shouldUseColour
 | 
			
		||||
            ? static_cast<Detail::IColourImpl*>( &platformColourImpl )
 | 
			
		||||
            : static_cast<Detail::IColourImpl*>( &noColourImpl );
 | 
			
		||||
 | 
			
		||||
} // end namespace Catch
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -15,9 +15,10 @@
 | 
			
		||||
 | 
			
		||||
namespace Catch {
 | 
			
		||||
 | 
			
		||||
    template <typename Runner, typename ResultCapture>
 | 
			
		||||
    class Context : public IMutableContext {
 | 
			
		||||
 | 
			
		||||
        Context() : m_config( NULL ), m_runner( NULL ), m_resultCapture( NULL ) {}
 | 
			
		||||
        Context() : m_config( NULL ), m_runner( &nullRunner ), m_resultCapture( &nullResultCapture ) {}
 | 
			
		||||
        Context( Context const& );
 | 
			
		||||
        void operator=( Context const& );
 | 
			
		||||
 | 
			
		||||
@@ -81,15 +82,28 @@ namespace Catch {
 | 
			
		||||
        IRunner* m_runner;
 | 
			
		||||
        IResultCapture* m_resultCapture;
 | 
			
		||||
        std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName;
 | 
			
		||||
        
 | 
			
		||||
        static ResultCapture nullResultCapture;
 | 
			
		||||
        static Runner nullRunner;
 | 
			
		||||
    public:
 | 
			
		||||
        static Context* currentContext;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    namespace {
 | 
			
		||||
    template <typename Runner, typename ResultCapture>
 | 
			
		||||
    ResultCapture Context<Runner, ResultCapture>::nullResultCapture;
 | 
			
		||||
    template <typename Runner, typename ResultCapture>
 | 
			
		||||
    Runner Context<Runner, ResultCapture>::nullRunner;
 | 
			
		||||
    template <typename Runner, typename ResultCapture>
 | 
			
		||||
    Context<Runner,ResultCapture>* Context<Runner, ResultCapture>::currentContext = NULL;
 | 
			
		||||
 | 
			
		||||
    /*namespace {
 | 
			
		||||
        Context* currentContext = NULL;
 | 
			
		||||
    }
 | 
			
		||||
    }*/
 | 
			
		||||
    typedef Context<NullRunner, NullResultCapture> DefaultContext;
 | 
			
		||||
    INTERNAL_CATCH_INLINE IMutableContext& getCurrentMutableContext() {
 | 
			
		||||
        if( !currentContext )
 | 
			
		||||
            currentContext = new Context();
 | 
			
		||||
        return *currentContext;
 | 
			
		||||
        if( !DefaultContext::currentContext )
 | 
			
		||||
            DefaultContext::currentContext = new DefaultContext();
 | 
			
		||||
        return *DefaultContext::currentContext;
 | 
			
		||||
    }
 | 
			
		||||
    INTERNAL_CATCH_INLINE IContext& getCurrentContext() {
 | 
			
		||||
        return getCurrentMutableContext();
 | 
			
		||||
@@ -104,8 +118,8 @@ namespace Catch {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    INTERNAL_CATCH_INLINE void cleanUpContext() {
 | 
			
		||||
        delete currentContext;
 | 
			
		||||
        currentContext = NULL;
 | 
			
		||||
        delete DefaultContext::currentContext;
 | 
			
		||||
        DefaultContext::currentContext = NULL;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -41,6 +41,23 @@ namespace Catch {
 | 
			
		||||
        virtual std::string getCurrentTestName() const = 0;
 | 
			
		||||
        virtual const AssertionResult* getLastResult() const = 0;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    struct NullResultCapture : public IResultCapture {
 | 
			
		||||
 | 
			
		||||
        virtual void assertionEnded( AssertionResult const& ) {}
 | 
			
		||||
        virtual bool sectionStarted(    SectionInfo const& ,
 | 
			
		||||
            Counts&  ) {return false;}
 | 
			
		||||
        virtual void sectionEnded( SectionInfo const& , Counts const& , double ) {}
 | 
			
		||||
        virtual void pushScopedMessage( MessageInfo const& ) {}
 | 
			
		||||
        virtual void popScopedMessage( MessageInfo const& ) {}
 | 
			
		||||
 | 
			
		||||
        virtual bool shouldDebugBreak() const {return false;}
 | 
			
		||||
 | 
			
		||||
        virtual ResultAction::Value acceptExpression( ExpressionResultBuilder const& , AssertionInfo const&  ) {return ResultAction::Abort;}
 | 
			
		||||
 | 
			
		||||
        virtual std::string getCurrentTestName() const {return std::string();}
 | 
			
		||||
        virtual const AssertionResult* getLastResult() const {return NULL;}
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,10 @@ namespace Catch {
 | 
			
		||||
    struct IRunner {
 | 
			
		||||
        virtual ~IRunner();
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    struct NullRunner : public IRunner
 | 
			
		||||
    {
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
 | 
			
		||||
 
 | 
			
		||||
@@ -16,64 +16,68 @@
 | 
			
		||||
 | 
			
		||||
namespace Catch {
 | 
			
		||||
 | 
			
		||||
    namespace {
 | 
			
		||||
    class RegistryHub : public IRegistryHub, public IMutableRegistryHub {
 | 
			
		||||
 | 
			
		||||
        class RegistryHub : public IRegistryHub, public IMutableRegistryHub {
 | 
			
		||||
        RegistryHub( RegistryHub const& );
 | 
			
		||||
        void operator=( RegistryHub const& );
 | 
			
		||||
 | 
			
		||||
            RegistryHub( RegistryHub const& );
 | 
			
		||||
            void operator=( RegistryHub const& );
 | 
			
		||||
    public: // IRegistryHub
 | 
			
		||||
        RegistryHub() {
 | 
			
		||||
        }
 | 
			
		||||
        virtual IReporterRegistry const& getReporterRegistry() const {
 | 
			
		||||
            return m_reporterRegistry;
 | 
			
		||||
        }
 | 
			
		||||
        virtual ITestCaseRegistry const& getTestCaseRegistry() const {
 | 
			
		||||
            return m_testCaseRegistry;
 | 
			
		||||
        }
 | 
			
		||||
        virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() {
 | 
			
		||||
            return m_exceptionTranslatorRegistry;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public: // IRegistryHub
 | 
			
		||||
            RegistryHub() {
 | 
			
		||||
            }
 | 
			
		||||
            virtual IReporterRegistry const& getReporterRegistry() const {
 | 
			
		||||
                return m_reporterRegistry;
 | 
			
		||||
            }
 | 
			
		||||
            virtual ITestCaseRegistry const& getTestCaseRegistry() const {
 | 
			
		||||
                return m_testCaseRegistry;
 | 
			
		||||
            }
 | 
			
		||||
            virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() {
 | 
			
		||||
                return m_exceptionTranslatorRegistry;
 | 
			
		||||
            }
 | 
			
		||||
    public: // IMutableRegistryHub
 | 
			
		||||
        virtual void registerReporter( std::string const& name, IReporterFactory* factory ) {
 | 
			
		||||
            m_reporterRegistry.registerReporter( name, factory );
 | 
			
		||||
        }
 | 
			
		||||
        virtual void registerTest( TestCase const& testInfo ) {
 | 
			
		||||
            m_testCaseRegistry.registerTest( testInfo );
 | 
			
		||||
        }
 | 
			
		||||
        virtual void registerTranslator( const IExceptionTranslator* translator ) {
 | 
			
		||||
            m_exceptionTranslatorRegistry.registerTranslator( translator );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public: // IMutableRegistryHub
 | 
			
		||||
            virtual void registerReporter( std::string const& name, IReporterFactory* factory ) {
 | 
			
		||||
                m_reporterRegistry.registerReporter( name, factory );
 | 
			
		||||
            }
 | 
			
		||||
            virtual void registerTest( TestCase const& testInfo ) {
 | 
			
		||||
                m_testCaseRegistry.registerTest( testInfo );
 | 
			
		||||
            }
 | 
			
		||||
            virtual void registerTranslator( const IExceptionTranslator* translator ) {
 | 
			
		||||
                m_exceptionTranslatorRegistry.registerTranslator( translator );
 | 
			
		||||
            }
 | 
			
		||||
    private:
 | 
			
		||||
        TestRegistry m_testCaseRegistry;
 | 
			
		||||
        ReporterRegistry m_reporterRegistry;
 | 
			
		||||
        ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
        private:
 | 
			
		||||
            TestRegistry m_testCaseRegistry;
 | 
			
		||||
            ReporterRegistry m_reporterRegistry;
 | 
			
		||||
            ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        // Single, global, instance
 | 
			
		||||
        inline RegistryHub*& getTheRegistryHub() {
 | 
			
		||||
            static RegistryHub* theRegistryHub = NULL;
 | 
			
		||||
    // Single, global, instance
 | 
			
		||||
    template <typename T>
 | 
			
		||||
    struct GlobalRegistryHub
 | 
			
		||||
    {
 | 
			
		||||
        static T*& instance()
 | 
			
		||||
        {
 | 
			
		||||
            if( !theRegistryHub )
 | 
			
		||||
                theRegistryHub = new RegistryHub();
 | 
			
		||||
                theRegistryHub = new T();
 | 
			
		||||
            return theRegistryHub;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
        static T* theRegistryHub;
 | 
			
		||||
    };
 | 
			
		||||
    template <typename T>
 | 
			
		||||
    T* GlobalRegistryHub<T>::theRegistryHub = NULL;
 | 
			
		||||
 | 
			
		||||
    IRegistryHub& getRegistryHub() {
 | 
			
		||||
        return *getTheRegistryHub();
 | 
			
		||||
    INTERNAL_CATCH_INLINE IRegistryHub& getRegistryHub() {
 | 
			
		||||
        return *GlobalRegistryHub<RegistryHub>::instance();
 | 
			
		||||
    }
 | 
			
		||||
    IMutableRegistryHub& getMutableRegistryHub() {
 | 
			
		||||
        return *getTheRegistryHub();
 | 
			
		||||
    INTERNAL_CATCH_INLINE IMutableRegistryHub& getMutableRegistryHub() {
 | 
			
		||||
        return *GlobalRegistryHub<RegistryHub>::instance();
 | 
			
		||||
    }
 | 
			
		||||
    void cleanUp() {
 | 
			
		||||
        delete getTheRegistryHub();
 | 
			
		||||
        getTheRegistryHub() = NULL;
 | 
			
		||||
    INTERNAL_CATCH_INLINE void cleanUp() {
 | 
			
		||||
        delete GlobalRegistryHub<RegistryHub>::instance();
 | 
			
		||||
        GlobalRegistryHub<RegistryHub>::instance() = NULL;
 | 
			
		||||
        cleanUpContext();
 | 
			
		||||
    }
 | 
			
		||||
    std::string translateActiveException() {
 | 
			
		||||
    INTERNAL_CATCH_INLINE std::string translateActiveException() {
 | 
			
		||||
        return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -48,7 +48,6 @@ namespace Catch {
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    ///////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
    class RunContext : public IResultCapture, public IRunner {
 | 
			
		||||
 | 
			
		||||
        RunContext( RunContext const& );
 | 
			
		||||
@@ -105,18 +104,16 @@ namespace Catch {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Totals runTest( TestCase const& testCase ) {
 | 
			
		||||
            Totals prevTotals = m_totals;
 | 
			
		||||
 | 
			
		||||
            std::string redirectedCout;
 | 
			
		||||
            std::string redirectedCerr;
 | 
			
		||||
 | 
			
		||||
            TestCaseInfo testInfo = testCase.getTestCaseInfo();
 | 
			
		||||
 | 
			
		||||
            m_reporter->testCaseStarting( testInfo );
 | 
			
		||||
            UnwindTestCaseOnCompletion finaliser(*this, m_totals, m_reporter, testInfo, redirectedCout, redirectedCerr);
 | 
			
		||||
 | 
			
		||||
            m_activeTestCase = &testCase;
 | 
			
		||||
            m_testCaseTracker = TestCaseTracker( testInfo.name );
 | 
			
		||||
 | 
			
		||||
            do {
 | 
			
		||||
                do {
 | 
			
		||||
                    runCurrentTest( redirectedCout, redirectedCerr );
 | 
			
		||||
@@ -125,18 +122,10 @@ namespace Catch {
 | 
			
		||||
            }
 | 
			
		||||
            while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() );
 | 
			
		||||
 | 
			
		||||
            Totals deltaTotals = m_totals.delta( prevTotals );
 | 
			
		||||
            m_totals.testCases += deltaTotals.testCases;
 | 
			
		||||
            m_reporter->testCaseEnded( TestCaseStats(   testInfo,
 | 
			
		||||
                                                        deltaTotals,
 | 
			
		||||
                                                        redirectedCout,
 | 
			
		||||
                                                        redirectedCerr,
 | 
			
		||||
                                                        aborting() ) );
 | 
			
		||||
 | 
			
		||||
            m_activeTestCase = NULL;
 | 
			
		||||
            m_testCaseTracker.reset();
 | 
			
		||||
 | 
			
		||||
            return deltaTotals;
 | 
			
		||||
            return finaliser.report();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Ptr<IConfig const> config() const {
 | 
			
		||||
@@ -194,12 +183,7 @@ namespace Catch {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtual void sectionEnded( SectionInfo const& info, Counts const& prevAssertions, double _durationInSeconds ) {
 | 
			
		||||
            if( std::uncaught_exception() ) {
 | 
			
		||||
                m_unfinishedSections.push_back( UnfinishedSections( info, prevAssertions, _durationInSeconds ) );
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        void unwindSection(SectionInfo const& info, Counts const& prevAssertions, double _durationInSeconds ) {
 | 
			
		||||
            Counts assertions = m_totals.assertions - prevAssertions;
 | 
			
		||||
            bool missingAssertions = testForMissingAssertions( assertions );
 | 
			
		||||
 | 
			
		||||
@@ -209,6 +193,15 @@ namespace Catch {
 | 
			
		||||
            m_messages.clear();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtual void sectionEnded( SectionInfo const& info, Counts const& prevAssertions, double _durationInSeconds ) {
 | 
			
		||||
            if( std::uncaught_exception() ) {
 | 
			
		||||
                m_unfinishedSections.push_back( UnfinishedSections( info, prevAssertions, _durationInSeconds ) );
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            unwindSection(info, prevAssertions, _durationInSeconds);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtual void pushScopedMessage( MessageInfo const& message ) {
 | 
			
		||||
            m_messages.push_back( message );
 | 
			
		||||
        }
 | 
			
		||||
@@ -257,16 +250,13 @@ namespace Catch {
 | 
			
		||||
 | 
			
		||||
        void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) {
 | 
			
		||||
            TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
 | 
			
		||||
            SectionInfo testCaseSection( testCaseInfo.name, testCaseInfo.description, testCaseInfo.lineInfo );
 | 
			
		||||
            m_reporter->sectionStarting( testCaseSection );
 | 
			
		||||
            Counts prevAssertions = m_totals.assertions;
 | 
			
		||||
            double duration = 0;
 | 
			
		||||
 | 
			
		||||
            UnwindSectionOnCompletion finaliser(*this, m_totals, m_reporter, testCaseInfo, m_unfinishedSections, m_messages);
 | 
			
		||||
            try {
 | 
			
		||||
                m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal );
 | 
			
		||||
                TestCaseTracker::Guard guard( *m_testCaseTracker );
 | 
			
		||||
 | 
			
		||||
                Timer timer;
 | 
			
		||||
                timer.start();
 | 
			
		||||
                finaliser.startTimer();
 | 
			
		||||
                if( m_reporter->getPreferences().shouldRedirectStdOut ) {
 | 
			
		||||
                    StreamRedirect coutRedir( std::cout, redirectedCout );
 | 
			
		||||
                    StreamRedirect cerrRedir( std::cerr, redirectedCerr );
 | 
			
		||||
@@ -275,37 +265,16 @@ namespace Catch {
 | 
			
		||||
                else {
 | 
			
		||||
                    m_activeTestCase->invoke();
 | 
			
		||||
                }
 | 
			
		||||
                duration = timer.getElapsedSeconds();
 | 
			
		||||
                finaliser.stopTimer();
 | 
			
		||||
            }
 | 
			
		||||
#ifdef INTERNAL_CATCH_VS_MANAGED // detect CLR
 | 
			
		||||
            catch(AssertFailedException^) {
 | 
			
		||||
                throw;  // CLR always rethrows - stop on first assert
 | 
			
		||||
            }
 | 
			
		||||
#else
 | 
			
		||||
            catch( INTERNAL_CATCH_TEST_FAILURE_EXCEPTION ) {
 | 
			
		||||
            catch( const Catch::TestFailureException& ) {
 | 
			
		||||
                // This just means the test was aborted due to failure
 | 
			
		||||
            }
 | 
			
		||||
#endif
 | 
			
		||||
            catch(...) {
 | 
			
		||||
                ExpressionResultBuilder exResult( ResultWas::ThrewException );
 | 
			
		||||
                exResult << translateActiveException();
 | 
			
		||||
                actOnCurrentResult( exResult.buildResult( m_lastAssertionInfo )  );
 | 
			
		||||
            }
 | 
			
		||||
            // If sections ended prematurely due to an exception we stored their
 | 
			
		||||
            // infos here so we can tear them down outside the unwind process.
 | 
			
		||||
            for( std::vector<UnfinishedSections>::const_iterator it = m_unfinishedSections.begin(),
 | 
			
		||||
                        itEnd = m_unfinishedSections.end();
 | 
			
		||||
                    it != itEnd;
 | 
			
		||||
                    ++it )
 | 
			
		||||
                sectionEnded( it->info, it->prevAssertions, it->durationInSeconds );
 | 
			
		||||
            m_unfinishedSections.clear();
 | 
			
		||||
            m_messages.clear();
 | 
			
		||||
 | 
			
		||||
            Counts assertions = m_totals.assertions - prevAssertions;
 | 
			
		||||
            bool missingAssertions = testForMissingAssertions( assertions );
 | 
			
		||||
 | 
			
		||||
            SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions );
 | 
			
		||||
            m_reporter->sectionEnded( testCaseSectionStats );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
@@ -319,6 +288,111 @@ namespace Catch {
 | 
			
		||||
            double durationInSeconds;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        class UnwindSectionOnCompletion
 | 
			
		||||
        {
 | 
			
		||||
        public:
 | 
			
		||||
            UnwindSectionOnCompletion(RunContext& context, Totals& totals, Ptr<IStreamingReporter>& reporter, TestCaseInfo const& testCaseInfo,
 | 
			
		||||
                std::vector<UnfinishedSections>& unfinishedSections, std::vector<MessageInfo>& messages)
 | 
			
		||||
                : m_context(context)
 | 
			
		||||
                , m_totals(totals)
 | 
			
		||||
                , m_reporter(reporter)
 | 
			
		||||
                , m_testCaseSection( testCaseInfo.name, testCaseInfo.description, testCaseInfo.lineInfo )
 | 
			
		||||
                , m_unfinishedSections(unfinishedSections)
 | 
			
		||||
                , m_messages(messages)
 | 
			
		||||
                , m_duration(0.0)
 | 
			
		||||
            {
 | 
			
		||||
                m_prevAssertions = m_totals.assertions;
 | 
			
		||||
                m_reporter->sectionStarting( m_testCaseSection );
 | 
			
		||||
            }
 | 
			
		||||
            ~UnwindSectionOnCompletion()
 | 
			
		||||
            {
 | 
			
		||||
                // If sections ended prematurely due to an exception we stored their
 | 
			
		||||
                // infos here so we can tear them down.
 | 
			
		||||
                for( std::vector<UnfinishedSections>::const_iterator it = m_unfinishedSections.begin(),
 | 
			
		||||
                            itEnd = m_unfinishedSections.end();
 | 
			
		||||
                        it != itEnd;
 | 
			
		||||
                        ++it ) {
 | 
			
		||||
                    m_context.unwindSection( it->info, it->prevAssertions, it->durationInSeconds );
 | 
			
		||||
                }
 | 
			
		||||
                m_unfinishedSections.clear();
 | 
			
		||||
                m_messages.clear();
 | 
			
		||||
 | 
			
		||||
                Counts assertions = m_totals.assertions - m_prevAssertions;
 | 
			
		||||
                bool missingAssertions = m_context.testForMissingAssertions( assertions );
 | 
			
		||||
 | 
			
		||||
                SectionStats testCaseSectionStats( m_testCaseSection, assertions, m_duration, missingAssertions );
 | 
			
		||||
                m_reporter->sectionEnded( testCaseSectionStats );
 | 
			
		||||
            }
 | 
			
		||||
            void startTimer()
 | 
			
		||||
            {
 | 
			
		||||
                m_timer.start();
 | 
			
		||||
            }
 | 
			
		||||
            void stopTimer()
 | 
			
		||||
            {
 | 
			
		||||
                m_duration = m_timer.getElapsedSeconds();
 | 
			
		||||
            }
 | 
			
		||||
        private:
 | 
			
		||||
            // non-copyable
 | 
			
		||||
            UnwindSectionOnCompletion(const UnwindSectionOnCompletion&);
 | 
			
		||||
            UnwindSectionOnCompletion& operator=(const UnwindSectionOnCompletion&);
 | 
			
		||||
 | 
			
		||||
            RunContext& m_context;
 | 
			
		||||
            Totals& m_totals;
 | 
			
		||||
            Ptr<IStreamingReporter>& m_reporter;
 | 
			
		||||
            SectionInfo m_testCaseSection;
 | 
			
		||||
            std::vector<UnfinishedSections>& m_unfinishedSections;
 | 
			
		||||
            std::vector<MessageInfo>& m_messages;
 | 
			
		||||
            Timer m_timer;
 | 
			
		||||
            Counts m_prevAssertions;
 | 
			
		||||
            double m_duration;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        class UnwindTestCaseOnCompletion
 | 
			
		||||
        {
 | 
			
		||||
        public:
 | 
			
		||||
            UnwindTestCaseOnCompletion(RunContext& context, Totals& totals, Ptr<IStreamingReporter>& reporter, TestCaseInfo& testInfo,
 | 
			
		||||
                std::string& redirectedCout, std::string& redirectedCerr)
 | 
			
		||||
                : m_context(context), m_totals(totals), m_reporter(reporter), m_testInfo(testInfo)
 | 
			
		||||
                , m_redirectedCout(redirectedCout), m_redirectedCerr(redirectedCerr)
 | 
			
		||||
                , m_reported(false)
 | 
			
		||||
            {
 | 
			
		||||
                m_prevTotals = m_totals;
 | 
			
		||||
                m_reporter->testCaseStarting( m_testInfo );
 | 
			
		||||
            }
 | 
			
		||||
            ~UnwindTestCaseOnCompletion()
 | 
			
		||||
            {
 | 
			
		||||
                if( !m_reported )
 | 
			
		||||
                {
 | 
			
		||||
                    report();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            Totals report()
 | 
			
		||||
            {
 | 
			
		||||
                m_reported = true;
 | 
			
		||||
                Totals deltaTotals = m_totals.delta( m_prevTotals );
 | 
			
		||||
                m_totals.testCases += deltaTotals.testCases;
 | 
			
		||||
                m_reporter->testCaseEnded( TestCaseStats(   m_testInfo,
 | 
			
		||||
                                                            deltaTotals,
 | 
			
		||||
                                                            m_redirectedCout,
 | 
			
		||||
                                                            m_redirectedCerr,
 | 
			
		||||
                                                            m_context.aborting() ) );
 | 
			
		||||
                return deltaTotals;
 | 
			
		||||
            }
 | 
			
		||||
        private:
 | 
			
		||||
            // non-copyable
 | 
			
		||||
            UnwindTestCaseOnCompletion(const UnwindTestCaseOnCompletion&);
 | 
			
		||||
            UnwindTestCaseOnCompletion& operator=(const UnwindTestCaseOnCompletion&);
 | 
			
		||||
 | 
			
		||||
            RunContext& m_context;
 | 
			
		||||
            Totals& m_totals;
 | 
			
		||||
            Ptr<IStreamingReporter>& m_reporter;
 | 
			
		||||
            TestCaseInfo& m_testInfo;
 | 
			
		||||
            std::string& m_redirectedCout;
 | 
			
		||||
            std::string& m_redirectedCerr;
 | 
			
		||||
            bool m_reported;
 | 
			
		||||
            Totals m_prevTotals;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        TestRunInfo m_runInfo;
 | 
			
		||||
        IMutableContext& m_context;
 | 
			
		||||
        TestCase const* m_activeTestCase;
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,11 @@
 | 
			
		||||
#ifndef TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
 | 
			
		||||
#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
 | 
			
		||||
 | 
			
		||||
#if defined(INTERNAL_CATCH_VS_MANAGED) || defined(INTERNAL_CATCH_VS_NATIVE)
 | 
			
		||||
#include "internal/catch_vs_test_registry.hpp"
 | 
			
		||||
#else
 | 
			
		||||
#include "catch_test_registry.hpp"
 | 
			
		||||
#endif
 | 
			
		||||
#include "catch_test_case_info.h"
 | 
			
		||||
#include "catch_test_spec.h"
 | 
			
		||||
#include "catch_context.h"
 | 
			
		||||
@@ -124,15 +128,15 @@ namespace Catch {
 | 
			
		||||
 | 
			
		||||
    ///////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
    AutoReg::AutoReg(   TestFunction function,
 | 
			
		||||
    INTERNAL_CATCH_INLINE AutoReg::AutoReg(   TestFunction function,
 | 
			
		||||
                        SourceLineInfo const& lineInfo,
 | 
			
		||||
                        NameAndDesc const& nameAndDesc ) {
 | 
			
		||||
        registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    AutoReg::~AutoReg() {}
 | 
			
		||||
    INTERNAL_CATCH_INLINE AutoReg::~AutoReg() {}
 | 
			
		||||
 | 
			
		||||
    void AutoReg::registerTestCase( ITestCase* testCase,
 | 
			
		||||
    INTERNAL_CATCH_INLINE void AutoReg::registerTestCase( ITestCase* testCase,
 | 
			
		||||
                                    char const* classOrQualifiedMethodName,
 | 
			
		||||
                                    NameAndDesc const& nameAndDesc,
 | 
			
		||||
                                    SourceLineInfo const& lineInfo ) {
 | 
			
		||||
 
 | 
			
		||||
@@ -24,15 +24,25 @@ namespace Catch {
 | 
			
		||||
 | 
			
		||||
    namespace {
 | 
			
		||||
#ifdef CATCH_PLATFORM_WINDOWS
 | 
			
		||||
        template <typename T>
 | 
			
		||||
        struct CounterDefaults
 | 
			
		||||
        {
 | 
			
		||||
            static T hz;
 | 
			
		||||
            static T hzo;
 | 
			
		||||
        };
 | 
			
		||||
        template <typename T>
 | 
			
		||||
        T CounterDefaults<T>::hz = 0;
 | 
			
		||||
        template <typename T>
 | 
			
		||||
        T CounterDefaults<T>::hzo = 0;
 | 
			
		||||
 | 
			
		||||
        INTERNAL_CATCH_INLINE uint64_t getCurrentTicks() {
 | 
			
		||||
            static uint64_t hz=0, hzo=0;
 | 
			
		||||
            if (!hz) {
 | 
			
		||||
                QueryPerformanceFrequency((LARGE_INTEGER*)&hz);
 | 
			
		||||
                QueryPerformanceCounter((LARGE_INTEGER*)&hzo);
 | 
			
		||||
            if (!CounterDefaults<uint64_t>::hz) {
 | 
			
		||||
                QueryPerformanceFrequency((LARGE_INTEGER*)&CounterDefaults<uint64_t>::hz);
 | 
			
		||||
                QueryPerformanceCounter((LARGE_INTEGER*)&CounterDefaults<uint64_t>::hzo);
 | 
			
		||||
            }
 | 
			
		||||
            uint64_t t;
 | 
			
		||||
            QueryPerformanceCounter((LARGE_INTEGER*)&t);
 | 
			
		||||
            return ((t-hzo)*1000000)/hz;
 | 
			
		||||
            return ((t-CounterDefaults<uint64_t>::hzo)*1000000)/CounterDefaults<uint64_t>::hz;
 | 
			
		||||
        }
 | 
			
		||||
#else
 | 
			
		||||
        INTERNAL_CATCH_INLINE uint64_t getCurrentTicks() {
 | 
			
		||||
 
 | 
			
		||||
@@ -95,7 +95,11 @@ struct StringMaker<T*> {
 | 
			
		||||
        if( !p )
 | 
			
		||||
            return INTERNAL_CATCH_STRINGIFY( NULL );
 | 
			
		||||
        std::ostringstream oss;
 | 
			
		||||
#ifdef _MSC_VER
 | 
			
		||||
        oss << "0x" << p;
 | 
			
		||||
#else
 | 
			
		||||
        oss << p;
 | 
			
		||||
#endif
 | 
			
		||||
        return oss.str();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -18,7 +18,7 @@ using namespace System::Collections::Generic;
 | 
			
		||||
using namespace Microsoft::VisualStudio::TestTools::UnitTesting;
 | 
			
		||||
 | 
			
		||||
namespace Catch {
 | 
			
		||||
    inline String^ convert_string_to_managed(const std::string& s)
 | 
			
		||||
    inline String^ convert_string_for_assert(const std::string& s)
 | 
			
		||||
    {
 | 
			
		||||
        String^ result = gcnew String(s.c_str());
 | 
			
		||||
        return result;
 | 
			
		||||
@@ -33,67 +33,50 @@ namespace Catch {
 | 
			
		||||
#include "catch_section.hpp"
 | 
			
		||||
#include "internal/catch_timer.hpp"
 | 
			
		||||
#include "internal/catch_vs_test_registry.hpp"
 | 
			
		||||
#include "internal/catch_reporter_registrars.hpp"
 | 
			
		||||
#include "reporters/catch_vs_reporter.hpp"
 | 
			
		||||
 | 
			
		||||
#include "internal/catch_exception_translator_registry.hpp"
 | 
			
		||||
#include "catch_registry_hub.hpp"
 | 
			
		||||
#include "internal/catch_console_colour_impl.hpp"
 | 
			
		||||
#include "catch_runner.hpp"
 | 
			
		||||
 | 
			
		||||
namespace Catch {
 | 
			
		||||
    inline NonCopyable::~NonCopyable() {}
 | 
			
		||||
    inline IShared::~IShared() {}
 | 
			
		||||
    inline StreamBufBase::~StreamBufBase() throw() {}
 | 
			
		||||
    inline IContext::~IContext() {}
 | 
			
		||||
    inline IResultCapture::~IResultCapture() {}
 | 
			
		||||
    inline ITestCase::~ITestCase() {}
 | 
			
		||||
    inline ITestCaseRegistry::~ITestCaseRegistry() {}
 | 
			
		||||
    inline IRegistryHub::~IRegistryHub() {}
 | 
			
		||||
    inline IMutableRegistryHub::~IMutableRegistryHub() {}
 | 
			
		||||
    inline IExceptionTranslator::~IExceptionTranslator() {}
 | 
			
		||||
    inline IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {}
 | 
			
		||||
    inline IReporter::~IReporter() {}
 | 
			
		||||
    inline IReporterFactory::~IReporterFactory() {}
 | 
			
		||||
    inline IReporterRegistry::~IReporterRegistry() {}
 | 
			
		||||
    inline IStreamingReporter::~IStreamingReporter() {}
 | 
			
		||||
    inline AssertionStats::~AssertionStats() {}
 | 
			
		||||
    inline SectionStats::~SectionStats() {}
 | 
			
		||||
    inline TestCaseStats::~TestCaseStats() {}
 | 
			
		||||
    inline TestGroupStats::~TestGroupStats() {}
 | 
			
		||||
    inline TestRunStats::~TestRunStats() {}
 | 
			
		||||
 | 
			
		||||
    class ExceptionRegistryHub : public IRegistryHub, public IMutableRegistryHub {
 | 
			
		||||
    inline IRunner::~IRunner() {}
 | 
			
		||||
    inline IMutableContext::~IMutableContext() {}
 | 
			
		||||
    inline IConfig::~IConfig() {}
 | 
			
		||||
    inline TestRegistry::~TestRegistry() {}
 | 
			
		||||
    inline FreeFunctionTestCase::~FreeFunctionTestCase() {}
 | 
			
		||||
    inline IGeneratorInfo::~IGeneratorInfo() {}
 | 
			
		||||
    inline IGeneratorsForTest::~IGeneratorsForTest() {}
 | 
			
		||||
 | 
			
		||||
        ExceptionRegistryHub( ExceptionRegistryHub const& );
 | 
			
		||||
        void operator=( ExceptionRegistryHub const& );
 | 
			
		||||
 | 
			
		||||
    public: // IRegistryHub
 | 
			
		||||
        ExceptionRegistryHub() {
 | 
			
		||||
        }
 | 
			
		||||
        virtual IReporterRegistry const& getReporterRegistry() const {
 | 
			
		||||
            throw std::runtime_error("can't do this for Visual Studio tests!");
 | 
			
		||||
        }
 | 
			
		||||
        virtual ITestCaseRegistry const& getTestCaseRegistry() const {
 | 
			
		||||
            throw std::runtime_error("can't do this for Visual Studio tests!");
 | 
			
		||||
        }
 | 
			
		||||
        virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() {
 | 
			
		||||
            return m_exceptionTranslatorRegistry;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    public: // IMutableRegistryHub
 | 
			
		||||
        virtual void registerReporter( std::string const&, IReporterFactory* ) {
 | 
			
		||||
            throw std::runtime_error("can't do this for Visual Studio tests!");
 | 
			
		||||
        }
 | 
			
		||||
        virtual void registerTest( TestCase const& ) {
 | 
			
		||||
            throw std::runtime_error("can't do this for Visual Studio tests!");
 | 
			
		||||
        }
 | 
			
		||||
        virtual void registerTranslator( const IExceptionTranslator* translator ) {
 | 
			
		||||
            m_exceptionTranslatorRegistry.registerTranslator( translator );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    template <typename T>
 | 
			
		||||
    struct GlobalRegistryHub
 | 
			
		||||
    {
 | 
			
		||||
        static T& instance()
 | 
			
		||||
        {
 | 
			
		||||
            if( !theRegistryHub )
 | 
			
		||||
                theRegistryHub = new T();
 | 
			
		||||
            return *theRegistryHub;
 | 
			
		||||
        }
 | 
			
		||||
        static T* theRegistryHub;
 | 
			
		||||
    };
 | 
			
		||||
    template <typename T>
 | 
			
		||||
    T* GlobalRegistryHub<T>::theRegistryHub = NULL;
 | 
			
		||||
 | 
			
		||||
    INTERNAL_CATCH_INLINE IMutableRegistryHub& getMutableRegistryHub() {
 | 
			
		||||
        return GlobalRegistryHub<ExceptionRegistryHub>::instance();
 | 
			
		||||
    }
 | 
			
		||||
    INTERNAL_CATCH_INLINE std::string translateActiveException() {
 | 
			
		||||
        return GlobalRegistryHub<ExceptionRegistryHub>::instance().getExceptionTranslatorRegistry().translateActiveException();
 | 
			
		||||
    }
 | 
			
		||||
    inline Matchers::Impl::StdString::Equals::~Equals() {}
 | 
			
		||||
    inline Matchers::Impl::StdString::Contains::~Contains() {}
 | 
			
		||||
    inline Matchers::Impl::StdString::StartsWith::~StartsWith() {}
 | 
			
		||||
    inline Matchers::Impl::StdString::EndsWith::~EndsWith() {}
 | 
			
		||||
 | 
			
		||||
    inline void Config::dummy() {}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif // TWOBLUECUBES_CATCH_VS_MANAGED_HPP_INCLUDED
 | 
			
		||||
 
 | 
			
		||||
@@ -16,8 +16,6 @@ using Microsoft::VisualStudio::CppUnitTestFramework::Logger;
 | 
			
		||||
using Microsoft::VisualStudio::CppUnitTestFramework::Assert;
 | 
			
		||||
using Microsoft::VisualStudio::CppUnitTestFramework::__LineInfo;
 | 
			
		||||
 | 
			
		||||
#define INTERNAL_CATCH_INLINE inline
 | 
			
		||||
 | 
			
		||||
#include <cvt/wstring>
 | 
			
		||||
#include <codecvt>
 | 
			
		||||
 | 
			
		||||
@@ -26,66 +24,50 @@ using Microsoft::VisualStudio::CppUnitTestFramework::__LineInfo;
 | 
			
		||||
#include "catch_tags.hpp"
 | 
			
		||||
#include "catch_test_spec.hpp"
 | 
			
		||||
#include "catch_section.hpp"
 | 
			
		||||
#include "internal/catch_timer.hpp"
 | 
			
		||||
#include "internal/catch_vs_test_registry.hpp"
 | 
			
		||||
#include "internal/catch_reporter_registrars.hpp"
 | 
			
		||||
#include "reporters/catch_vs_reporter.hpp"
 | 
			
		||||
#include "catch_registry_hub.hpp"
 | 
			
		||||
#include "internal/catch_timer.hpp"
 | 
			
		||||
#include "internal/catch_console_colour_impl.hpp"
 | 
			
		||||
#include "catch_runner.hpp"
 | 
			
		||||
 | 
			
		||||
namespace Catch {
 | 
			
		||||
    inline NonCopyable::~NonCopyable() {}
 | 
			
		||||
    inline IShared::~IShared() {}
 | 
			
		||||
    inline StreamBufBase::~StreamBufBase() throw() {}
 | 
			
		||||
    inline IContext::~IContext() {}
 | 
			
		||||
    inline IResultCapture::~IResultCapture() {}
 | 
			
		||||
    inline ITestCase::~ITestCase() {}
 | 
			
		||||
    inline ITestCaseRegistry::~ITestCaseRegistry() {}
 | 
			
		||||
    inline IRegistryHub::~IRegistryHub() {}
 | 
			
		||||
    inline IMutableRegistryHub::~IMutableRegistryHub() {}
 | 
			
		||||
    inline IExceptionTranslator::~IExceptionTranslator() {}
 | 
			
		||||
    inline IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {}
 | 
			
		||||
    inline IReporter::~IReporter() {}
 | 
			
		||||
    inline IReporterFactory::~IReporterFactory() {}
 | 
			
		||||
    inline IReporterRegistry::~IReporterRegistry() {}
 | 
			
		||||
    inline IStreamingReporter::~IStreamingReporter() {}
 | 
			
		||||
    inline AssertionStats::~AssertionStats() {}
 | 
			
		||||
    inline SectionStats::~SectionStats() {}
 | 
			
		||||
    inline TestCaseStats::~TestCaseStats() {}
 | 
			
		||||
    inline TestGroupStats::~TestGroupStats() {}
 | 
			
		||||
    inline TestRunStats::~TestRunStats() {}
 | 
			
		||||
 | 
			
		||||
    class ExceptionRegistryHub : public IRegistryHub, public IMutableRegistryHub {
 | 
			
		||||
    inline IRunner::~IRunner() {}
 | 
			
		||||
    inline IMutableContext::~IMutableContext() {}
 | 
			
		||||
    inline IConfig::~IConfig() {}
 | 
			
		||||
    inline TestRegistry::~TestRegistry() {}
 | 
			
		||||
    inline FreeFunctionTestCase::~FreeFunctionTestCase() {}
 | 
			
		||||
    inline IGeneratorInfo::~IGeneratorInfo() {}
 | 
			
		||||
    inline IGeneratorsForTest::~IGeneratorsForTest() {}
 | 
			
		||||
 | 
			
		||||
        ExceptionRegistryHub( ExceptionRegistryHub const& );
 | 
			
		||||
        void operator=( ExceptionRegistryHub const& );
 | 
			
		||||
 | 
			
		||||
    public: // IRegistryHub
 | 
			
		||||
        ExceptionRegistryHub() {
 | 
			
		||||
        }
 | 
			
		||||
        virtual IReporterRegistry const& getReporterRegistry() const {
 | 
			
		||||
            throw std::runtime_error("can't do this for Visual Studio tests!");
 | 
			
		||||
        }
 | 
			
		||||
        virtual ITestCaseRegistry const& getTestCaseRegistry() const {
 | 
			
		||||
            throw std::runtime_error("can't do this for Visual Studio tests!");
 | 
			
		||||
        }
 | 
			
		||||
        virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() {
 | 
			
		||||
            return m_exceptionTranslatorRegistry;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    public: // IMutableRegistryHub
 | 
			
		||||
        virtual void registerReporter( std::string const&, IReporterFactory* ) {
 | 
			
		||||
            throw std::runtime_error("can't do this for Visual Studio tests!");
 | 
			
		||||
        }
 | 
			
		||||
        virtual void registerTest( TestCase const& ) {
 | 
			
		||||
            throw std::runtime_error("can't do this for Visual Studio tests!");
 | 
			
		||||
        }
 | 
			
		||||
        virtual void registerTranslator( const IExceptionTranslator* translator ) {
 | 
			
		||||
            m_exceptionTranslatorRegistry.registerTranslator( translator );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    template <typename T>
 | 
			
		||||
    struct GlobalRegistryHub
 | 
			
		||||
    {
 | 
			
		||||
        static T& instance()
 | 
			
		||||
        {
 | 
			
		||||
            if( !theRegistryHub )
 | 
			
		||||
                theRegistryHub = new T();
 | 
			
		||||
            return *theRegistryHub;
 | 
			
		||||
        }
 | 
			
		||||
        static T* theRegistryHub;
 | 
			
		||||
    };
 | 
			
		||||
    template <typename T>
 | 
			
		||||
    T* GlobalRegistryHub<T>::theRegistryHub = NULL;
 | 
			
		||||
 | 
			
		||||
    INTERNAL_CATCH_INLINE IMutableRegistryHub& getMutableRegistryHub() {
 | 
			
		||||
        return GlobalRegistryHub<ExceptionRegistryHub>::instance();
 | 
			
		||||
    }
 | 
			
		||||
    INTERNAL_CATCH_INLINE std::string translateActiveException() {
 | 
			
		||||
        return GlobalRegistryHub<ExceptionRegistryHub>::instance().getExceptionTranslatorRegistry().translateActiveException();
 | 
			
		||||
    }
 | 
			
		||||
    inline Matchers::Impl::StdString::Equals::~Equals() {}
 | 
			
		||||
    inline Matchers::Impl::StdString::Contains::~Contains() {}
 | 
			
		||||
    inline Matchers::Impl::StdString::StartsWith::~StartsWith() {}
 | 
			
		||||
    inline Matchers::Impl::StdString::EndsWith::~EndsWith() {}
 | 
			
		||||
 | 
			
		||||
    inline void Config::dummy() {}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // INTERNAL_CATCH_VS_NATIVE
 | 
			
		||||
 
 | 
			
		||||
@@ -16,27 +16,11 @@
 | 
			
		||||
#include "catch_common.h"
 | 
			
		||||
#include "catch_interfaces_testcase.h"
 | 
			
		||||
#include "internal/catch_compiler_capabilities.h"
 | 
			
		||||
#include "internal/clara.h"
 | 
			
		||||
#include <tchar.h>
 | 
			
		||||
 | 
			
		||||
namespace Catch {
 | 
			
		||||
 | 
			
		||||
    typedef void(*TestFunction)();
 | 
			
		||||
 | 
			
		||||
    class FreeFunctionTestCase : public SharedImpl<ITestCase> {
 | 
			
		||||
    public:
 | 
			
		||||
 | 
			
		||||
        FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {}
 | 
			
		||||
 | 
			
		||||
        virtual void invoke() const {
 | 
			
		||||
            m_fun();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        virtual ~FreeFunctionTestCase();
 | 
			
		||||
 | 
			
		||||
        TestFunction m_fun;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
class MethodTestCase : public SharedImpl<ITestCase> {
 | 
			
		||||
 | 
			
		||||
    struct placeholder
 | 
			
		||||
@@ -79,7 +63,7 @@ private:
 | 
			
		||||
typedef void(*TestFunction)();
 | 
			
		||||
 | 
			
		||||
struct NameAndDesc {
 | 
			
		||||
#if (_MANAGED == 1) || (_M_CEE == 1) // detect CLR
 | 
			
		||||
#ifdef INTERNAL_CATCH_VS_MANAGED
 | 
			
		||||
    NameAndDesc( const char* _name = "", const char* _description= "" )
 | 
			
		||||
    : name( _name ), description( _description )
 | 
			
		||||
    {}
 | 
			
		||||
@@ -90,14 +74,35 @@ struct NameAndDesc {
 | 
			
		||||
    NameAndDesc( const wchar_t* _name, const char* _description= ""  )
 | 
			
		||||
    : name(), description( _description )
 | 
			
		||||
    {
 | 
			
		||||
        stdext::cvt::wstring_convert<std::codecvt_utf8<wchar_t> > conv1;
 | 
			
		||||
        name = conv1.to_bytes(_name);
 | 
			
		||||
        assignName(_name);
 | 
			
		||||
    }
 | 
			
		||||
    NameAndDesc( const wchar_t* _name, int  )
 | 
			
		||||
    : name(), description( "" )
 | 
			
		||||
    {
 | 
			
		||||
        assignName(_name);
 | 
			
		||||
    }
 | 
			
		||||
    void assignName(const wchar_t* _name)
 | 
			
		||||
    {
 | 
			
		||||
        stdext::cvt::wstring_convert<std::codecvt_utf8<wchar_t> > conv1;
 | 
			
		||||
        name = conv1.to_bytes(_name);
 | 
			
		||||
        std::string tmp = conv1.to_bytes(_name);
 | 
			
		||||
        if( tmp.empty() )
 | 
			
		||||
        {
 | 
			
		||||
            name = tmp;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            std::string::iterator startIter = tmp.begin();
 | 
			
		||||
            if(*startIter == '\"')
 | 
			
		||||
            {
 | 
			
		||||
                ++startIter;
 | 
			
		||||
            }
 | 
			
		||||
            std::string::reverse_iterator endIter = tmp.rbegin();
 | 
			
		||||
            if(*endIter == '\"')
 | 
			
		||||
            {
 | 
			
		||||
                ++endIter;
 | 
			
		||||
            }
 | 
			
		||||
            name.assign(startIter, endIter.base());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@@ -105,9 +110,38 @@ struct NameAndDesc {
 | 
			
		||||
    std::string description;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct AutoReg {
 | 
			
		||||
 | 
			
		||||
    AutoReg(    TestFunction function,
 | 
			
		||||
                SourceLineInfo const& lineInfo,
 | 
			
		||||
                NameAndDesc const& nameAndDesc );
 | 
			
		||||
 | 
			
		||||
    template<typename C>
 | 
			
		||||
    AutoReg(    void (C::*method)(),
 | 
			
		||||
                char const* className,
 | 
			
		||||
                NameAndDesc const& nameAndDesc,
 | 
			
		||||
                SourceLineInfo const& lineInfo ) {
 | 
			
		||||
        registerTestCase(   new MethodTestCase( method ),
 | 
			
		||||
                            className,
 | 
			
		||||
                            nameAndDesc,
 | 
			
		||||
                            lineInfo );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void registerTestCase(  ITestCase* testCase,
 | 
			
		||||
                            char const* className,
 | 
			
		||||
                            NameAndDesc const& nameAndDesc,
 | 
			
		||||
                            SourceLineInfo const& lineInfo );
 | 
			
		||||
 | 
			
		||||
    ~AutoReg();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    AutoReg( AutoReg const& );
 | 
			
		||||
    void operator= ( AutoReg const& );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // end namespace Catch
 | 
			
		||||
 | 
			
		||||
#if (_MANAGED == 1) || (_M_CEE == 1) // detect CLR
 | 
			
		||||
#ifdef INTERNAL_CATCH_VS_MANAGED
 | 
			
		||||
 | 
			
		||||
#define CATCH_INTERNAL_HANDLE_EMPTY_PARAM2( name ) name##""
 | 
			
		||||
#define CATCH_INTERNAL_HANDLE_EMPTY_PARAM(...) CATCH_INTERNAL_HANDLE_EMPTY_PARAM2( INTERNAL_CATCH_SPLIT_ARGS_2(__VA_ARGS__) )
 | 
			
		||||
@@ -134,7 +168,7 @@ struct NameAndDesc {
 | 
			
		||||
 | 
			
		||||
#define CATCH_INTERNAL_NAMESPACE( Ext )
 | 
			
		||||
 | 
			
		||||
#define INTERNAL_CATCH_TEST_METHOD( Method, UniqueExt, Name, Desc ) \
 | 
			
		||||
#define INTERNAL_CATCH_TEST_METHOD( Count, UniqueExt, Name, Desc ) \
 | 
			
		||||
        public: \
 | 
			
		||||
            [TestMethod] \
 | 
			
		||||
            [Description( CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Name) )] \
 | 
			
		||||
@@ -142,22 +176,24 @@ struct NameAndDesc {
 | 
			
		||||
            void INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H___M_E_T_H_O_D___, UniqueExt) () \
 | 
			
		||||
            { \
 | 
			
		||||
                Catch::NameAndDesc name_desc( CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Name), Desc ); \
 | 
			
		||||
                CATCH_INTERNAL_RUN_SINGLE_TEST( Method ); \
 | 
			
		||||
                CATCH_INTERNAL_RUN_SINGLE_TEST(Count); \
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
#define INTERNAL_CATCH_TEST_CLASS_METHOD( Method, UniqueExt, Name, Desc ) \
 | 
			
		||||
#define BEGIN_INTERNAL_CATCH_BATCH_METHOD( Tags, UniqueExt ) \
 | 
			
		||||
        public: \
 | 
			
		||||
            [TestMethod] \
 | 
			
		||||
            [Description( CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Name) )] \
 | 
			
		||||
            [TestProperty( "Description", CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Name) )] \
 | 
			
		||||
            void INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H___M_E_T_H_O_D___, UniqueExt) () \
 | 
			
		||||
            { \
 | 
			
		||||
                Catch::NameAndDesc name_desc( CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Name), Desc ); \
 | 
			
		||||
                CATCH_INTERNAL_RUN_SINGLE_CLASS_TEST( Method ); \
 | 
			
		||||
            }
 | 
			
		||||
            [TestCategory( CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Tags) )] \
 | 
			
		||||
            [Description( CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Tags) )] \
 | 
			
		||||
            [TestProperty( "Description", CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Tags) )] \
 | 
			
		||||
            void INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H___M_E_T_H_O_D___, UniqueExt) ()
 | 
			
		||||
 | 
			
		||||
#define CHECK_FOR_TEST_CASE_CLASH 
 | 
			
		||||
 | 
			
		||||
#define INTERNAL_CATCH_MAP_CATEGORY_TO_TAG( Category, Tag ) \
 | 
			
		||||
    INTERNAL_CATCH_MAP_CATEGORY_TO_TAG2( #Category, Tag, __COUNTER__ )
 | 
			
		||||
 | 
			
		||||
#define FAIL_STRING( str ) _T( str )
 | 
			
		||||
 | 
			
		||||
#else // detect CLR
 | 
			
		||||
 | 
			
		||||
// Native tests
 | 
			
		||||
@@ -173,99 +209,161 @@ struct NameAndDesc {
 | 
			
		||||
#define TEST_IMPL_2(tuple) TEST_IMPL2 tuple
 | 
			
		||||
#define TEST_IMPL2( INTERNAL_CATCH_SPLIT_ARG_1,INTERNAL_CATCH_SPLIT_ARG_2,N,...) L#INTERNAL_CATCH_SPLIT_ARG_1
 | 
			
		||||
 | 
			
		||||
#define CATCH_INTERNAL_HANDLE_EMPTY_PARAM(...) CATCH_INTERNAL_HANDLE_EMPTY_PARAM_IMPL( (__VA_ARGS__, 2, 1) )
 | 
			
		||||
#define CATCH_INTERNAL_HANDLE_EMPTY_PARAM_IMPL(tuple) CATCH_INTERNAL_HANDLE_EMPTY_PARAM_IMPL2 tuple
 | 
			
		||||
#define CATCH_INTERNAL_HANDLE_EMPTY_PARAM_IMPL2( INTERNAL_CATCH_SPLIT_ARG_1,INTERNAL_CATCH_SPLIT_ARG_2,N,...) #INTERNAL_CATCH_SPLIT_ARG_1
 | 
			
		||||
#define CATCH_INTERNAL_HANDLE_EMPTY_PARAMW(...) CATCH_INTERNAL_HANDLE_EMPTY_PARAM_IMPLW( (__VA_ARGS__, 2, 1) )
 | 
			
		||||
#define CATCH_INTERNAL_HANDLE_EMPTY_PARAM(...) CATCH_INTERNAL_HANDLE_EMPTY_PARAM_IMPLW( (__VA_ARGS__, 2, 1) )
 | 
			
		||||
#define CATCH_INTERNAL_HANDLE_EMPTY_PARAM_IMPLW(tuple) CATCH_INTERNAL_HANDLE_EMPTY_PARAM_IMPL2W tuple
 | 
			
		||||
#define CATCH_INTERNAL_HANDLE_EMPTY_PARAM_IMPL2W( INTERNAL_CATCH_SPLIT_ARG_1,INTERNAL_CATCH_SPLIT_ARG_2,N,...) L#INTERNAL_CATCH_SPLIT_ARG_1
 | 
			
		||||
 | 
			
		||||
#define INTERNAL_CATCH_TEST_METHOD( Method, UniqueExt, Name, Desc ) \
 | 
			
		||||
#define INTERNAL_CATCH_TEST_METHOD( Count, UniqueExt, Name, Desc ) \
 | 
			
		||||
        public: \
 | 
			
		||||
	    BEGIN_TEST_METHOD_ATTRIBUTE( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H___M_E_T_H_O_D___, UniqueExt) ) \
 | 
			
		||||
            TEST_OWNER( CATCH_INTERNAL_HANDLE_EMPTY_PARAMW(Name) ) \
 | 
			
		||||
            TEST_DESCRIPTION( CATCH_INTERNAL_HANDLE_EMPTY_PARAMW(Name) ) \
 | 
			
		||||
            TEST_OWNER( CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Name) ) \
 | 
			
		||||
            TEST_DESCRIPTION( CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Name) ) \
 | 
			
		||||
	    END_TEST_METHOD_ATTRIBUTE() \
 | 
			
		||||
    	TEST_METHOD( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H___M_E_T_H_O_D___, UniqueExt) ) \
 | 
			
		||||
        { \
 | 
			
		||||
            Catch::NameAndDesc name_desc(CATCH_INTERNAL_HANDLE_EMPTY_PARAMW(Name), Desc ); \
 | 
			
		||||
            CATCH_INTERNAL_RUN_SINGLE_TEST( Method ); \
 | 
			
		||||
            Catch::NameAndDesc name_desc(CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Name), Desc ); \
 | 
			
		||||
            CATCH_INTERNAL_RUN_SINGLE_TEST(Count); \
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
#define INTERNAL_CATCH_TEST_CLASS_METHOD( Method, UniqueExt, Name, Desc ) \
 | 
			
		||||
#define BEGIN_INTERNAL_CATCH_BATCH_METHOD( Tags, UniqueExt ) \
 | 
			
		||||
        public: \
 | 
			
		||||
	    BEGIN_TEST_METHOD_ATTRIBUTE( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H___M_E_T_H_O_D___, UniqueExt) ) \
 | 
			
		||||
            TEST_OWNER( CATCH_INTERNAL_HANDLE_EMPTY_PARAMW(Name) ) \
 | 
			
		||||
            TEST_DESCRIPTION( CATCH_INTERNAL_HANDLE_EMPTY_PARAMW(Name) ) \
 | 
			
		||||
	    END_TEST_METHOD_ATTRIBUTE() \
 | 
			
		||||
    	TEST_METHOD( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H___M_E_T_H_O_D___, UniqueExt) ) \
 | 
			
		||||
        { \
 | 
			
		||||
            Catch::NameAndDesc name_desc( CATCH_INTERNAL_HANDLE_EMPTY_PARAMW(Name), Desc ); \
 | 
			
		||||
            CATCH_INTERNAL_RUN_SINGLE_CLASS_TEST( Method ); \
 | 
			
		||||
        }
 | 
			
		||||
	        BEGIN_TEST_METHOD_ATTRIBUTE( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H___M_E_T_H_O_D___, UniqueExt) ) \
 | 
			
		||||
                TEST_OWNER( CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Tags) ) \
 | 
			
		||||
                TEST_DESCRIPTION( CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Tags) ) \
 | 
			
		||||
	        END_TEST_METHOD_ATTRIBUTE() \
 | 
			
		||||
            TEST_METHOD( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H___M_E_T_H_O_D___, UniqueExt) )
 | 
			
		||||
 | 
			
		||||
#define CHECK_FOR_TEST_CASE_CLASH void INTERNAL_CATCH_UNIQUE_NAME_LINE( if_you_get_this_error_you_have_a_test_case_name_clash_please_put_a_namespace_around_the_test_case_at_line_, __LINE__ )() {}
 | 
			
		||||
 | 
			
		||||
#define INTERNAL_CATCH_MAP_CATEGORY_TO_TAG( Category, Tag ) \
 | 
			
		||||
    INTERNAL_CATCH_MAP_CATEGORY_TO_TAG2( Category, Tag, __COUNTER__ )
 | 
			
		||||
 | 
			
		||||
#define FAIL_STRING( str ) WIDEN( str )
 | 
			
		||||
 | 
			
		||||
#endif // detect CLR
 | 
			
		||||
 | 
			
		||||
#define INTERNAL_CATCH_CONCAT_LINE_COUNTER INTERNAL_CATCH_UNIQUE_NAME_LINE( INTERNAL_CATCH_UNIQUE_NAME_LINE( __LINE__, _ ), __COUNTER__ )
 | 
			
		||||
#define INTERNAL_CATCH_CONCAT_LINE_COUNTER( count ) INTERNAL_CATCH_UNIQUE_NAME_LINE( INTERNAL_CATCH_UNIQUE_NAME_LINE( __LINE__, _ ), count )
 | 
			
		||||
 | 
			
		||||
#define CATCH_INTERNAL_RUN_SINGLE_TEST( Method ) \
 | 
			
		||||
        {   Catch::ConfigData cd; \
 | 
			
		||||
#define CATCH_INTERNAL_CONFIG_SHOW_SUCCESS2( v, Count ) \
 | 
			
		||||
    namespace { CatchOverrides::ConfigShowSuccessfulTests<Catch::IConfig const*> INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H_____O_V_E_R_R_I_D_E____, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) )(__FILE__, Count, v); }
 | 
			
		||||
 | 
			
		||||
#define CATCH_INTERNAL_CONFIG_WARN_MISSING_ASSERTIONS2( v, Count ) \
 | 
			
		||||
    namespace { CatchOverrides::ConfigWarnMissingAssertions<Catch::IConfig const*> INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H_____O_V_E_R_R_I_D_E____, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) )(__FILE__, Count, v); }
 | 
			
		||||
 | 
			
		||||
#define CATCH_INTERNAL_CONFIG_SHOW_SUCCESS( v ) \
 | 
			
		||||
    CATCH_INTERNAL_CONFIG_SHOW_SUCCESS2( v, __COUNTER__)
 | 
			
		||||
 | 
			
		||||
#define CATCH_INTERNAL_CONFIG_WARN_MISSING_ASSERTIONS( v ) \
 | 
			
		||||
    CATCH_INTERNAL_CONFIG_WARN_MISSING_ASSERTIONS2( v, __COUNTER__)
 | 
			
		||||
 | 
			
		||||
#define CATCH_INTERNAL_RUN_SINGLE_TEST( Count ) \
 | 
			
		||||
        {   CatchOverrides::ConfigGuard cg; \
 | 
			
		||||
            Catch::ConfigData cd(cg.value().get()); \
 | 
			
		||||
            cd.name = name_desc.name; \
 | 
			
		||||
            cd.abortAfter = 1; \
 | 
			
		||||
            cd.showSuccessfulTests = CatchOverrides::Config<Catch::IConfig const*>::instance().includeSuccessfulResults(__FILE__, Count ); \
 | 
			
		||||
            cd.warnings            = (CatchOverrides::Config<Catch::IConfig const*>::instance().warnAboutMissingAssertions(__FILE__, Count ) ? Catch::WarnAbout::NoAssertions : Catch::WarnAbout::Nothing); \
 | 
			
		||||
            Catch::Ptr<Catch::Config> config(new Catch::Config(cd)); \
 | 
			
		||||
            Catch::MSTestReporter* rep = new Catch::MSTestReporter(config.get()); \
 | 
			
		||||
            Catch::RunContext tr(config.get(), rep); \
 | 
			
		||||
            Catch::TestCase tc = Catch::makeTestCase( new Catch::FreeFunctionTestCase( & Method ), "", name_desc.name, name_desc.description, CATCH_INTERNAL_LINEINFO ); \
 | 
			
		||||
            tr.runTest(tc); \
 | 
			
		||||
            std::vector<Catch::TestCase> testCase = Catch::getRegistryHub().getTestCaseRegistry().getMatchingTestCases(name_desc.name); \
 | 
			
		||||
            if( testCase.empty() ) Assert::Fail(FAIL_STRING("No tests match")); \
 | 
			
		||||
            if( testCase.size() > 1 ) Assert::Fail(FAIL_STRING("More than one test with the same name")); \
 | 
			
		||||
            Catch::Totals totals = tr.runTest(*testCase.begin()); \
 | 
			
		||||
            if( totals.assertions.failed > 0 ) { \
 | 
			
		||||
                INTERNAL_CATCH_TEST_THROW_FAILURE \
 | 
			
		||||
            } \
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
#define CATCH_INTERNAL_RUN_SINGLE_CLASS_TEST( ClassMethod ) \
 | 
			
		||||
        {   Catch::ConfigData cd; \
 | 
			
		||||
            cd.name = name_desc.name; \
 | 
			
		||||
            Catch::Ptr<Catch::Config> config(new Catch::Config(cd)); \
 | 
			
		||||
            Catch::MSTestReporter* rep = new Catch::MSTestReporter(config.get()); \
 | 
			
		||||
            Catch::RunContext tr(config.get(), rep); \
 | 
			
		||||
            Catch::TestCase tc = Catch::makeTestCase( new Catch::MethodTestCase( & ClassMethod ), # ClassMethod, name_desc.name, name_desc.description, CATCH_INTERNAL_LINEINFO ); \
 | 
			
		||||
            tr.runTest(tc); \
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
#define INTERNAL_CATCH_TESTCASE2( UniqueExt, Name, Desc ) \
 | 
			
		||||
#define INTERNAL_CATCH_TESTCASE2( Count, Name, Desc ) \
 | 
			
		||||
    CHECK_FOR_TEST_CASE_CLASH \
 | 
			
		||||
    static void INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, UniqueExt )(); \
 | 
			
		||||
    namespace CATCH_INTERNAL_NAMESPACE( UniqueExt ) { \
 | 
			
		||||
        INTERNAL_CATCH_CLASS_DEFINITION( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____C_L_A_S_S___, UniqueExt ) ) \
 | 
			
		||||
    static void INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) )(); \
 | 
			
		||||
    namespace CATCH_INTERNAL_NAMESPACE( INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) ) { \
 | 
			
		||||
        Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( & INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc(CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Name), Desc) ); \
 | 
			
		||||
        CatchOverrides::ConfigReset<Catch::IConfig const*> INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____C_O_N_F_I_G___, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) )(__FILE__, Count); \
 | 
			
		||||
        INTERNAL_CATCH_CLASS_DEFINITION( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____C_L_A_S_S___, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) ) ) \
 | 
			
		||||
        { \
 | 
			
		||||
            INTERNAL_CATCH_CLASS_CONTEXT \
 | 
			
		||||
            INTERNAL_CATCH_TEST_METHOD( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, UniqueExt ), UniqueExt, Name, Desc ) \
 | 
			
		||||
            INTERNAL_CATCH_TEST_METHOD( Count, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ), Name, Desc ) \
 | 
			
		||||
        }; \
 | 
			
		||||
    } \
 | 
			
		||||
    void INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, UniqueExt )()
 | 
			
		||||
    void INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) )()
 | 
			
		||||
 | 
			
		||||
#define INTERNAL_CATCH_METHOD_AS_TEST_CASE2( QualifiedMethod, UniqueExt, Name, Desc ) \
 | 
			
		||||
#define INTERNAL_CATCH_METHOD_AS_TEST_CASE2( QualifiedMethod, Count, Name, Desc ) \
 | 
			
		||||
    CHECK_FOR_TEST_CASE_CLASH \
 | 
			
		||||
    namespace CATCH_INTERNAL_NAMESPACE( UniqueExt ) { \
 | 
			
		||||
        INTERNAL_CATCH_CLASS_DEFINITION( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____C_L_A_S_S___, UniqueExt ) ) \
 | 
			
		||||
    namespace CATCH_INTERNAL_NAMESPACE( INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) ) { \
 | 
			
		||||
        Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( & QualifiedMethod, "&" # QualifiedMethod, Catch::NameAndDesc(CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Name), Desc), CATCH_INTERNAL_LINEINFO ); \
 | 
			
		||||
        CatchOverrides::ConfigReset<Catch::IConfig const*> INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____C_O_N_F_I_G___, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) )(__FILE__, Count); \
 | 
			
		||||
        INTERNAL_CATCH_CLASS_DEFINITION( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____C_L_A_S_S___, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) ) ) \
 | 
			
		||||
        { \
 | 
			
		||||
            INTERNAL_CATCH_CLASS_CONTEXT \
 | 
			
		||||
            INTERNAL_CATCH_TEST_CLASS_METHOD( QualifiedMethod, UniqueExt, Name, Desc ) \
 | 
			
		||||
            INTERNAL_CATCH_TEST_METHOD( Count, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ), Name, Desc ) \
 | 
			
		||||
        }; \
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
#define INTERNAL_CATCH_TEST_CASE_METHOD2( ClassName, UniqueExt, TestName, Desc ) \
 | 
			
		||||
#define INTERNAL_CATCH_TEST_CASE_METHOD2( ClassName, Count, TestName, Desc ) \
 | 
			
		||||
    CHECK_FOR_TEST_CASE_CLASH \
 | 
			
		||||
    struct INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, UniqueExt ) : ClassName { \
 | 
			
		||||
    struct INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) ) : ClassName { \
 | 
			
		||||
        void test(); \
 | 
			
		||||
        static void invoke() { INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, UniqueExt ) tmp; tmp.test(); } \
 | 
			
		||||
        static void invoke() { INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) ) tmp; tmp.test(); } \
 | 
			
		||||
    }; \
 | 
			
		||||
    namespace CATCH_INTERNAL_NAMESPACE( UniqueExt ) { \
 | 
			
		||||
        INTERNAL_CATCH_CLASS_DEFINITION( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____C_L_A_S_S___, UniqueExt ) ) \
 | 
			
		||||
    namespace CATCH_INTERNAL_NAMESPACE( INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) ) { \
 | 
			
		||||
        Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( & INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) )::invoke, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc(CATCH_INTERNAL_HANDLE_EMPTY_PARAM(TestName), Desc) ); \
 | 
			
		||||
        CatchOverrides::ConfigReset<Catch::IConfig const*> INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____C_O_N_F_I_G___, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) )(__FILE__, Count); \
 | 
			
		||||
        INTERNAL_CATCH_CLASS_DEFINITION( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____C_L_A_S_S___, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) ) ) \
 | 
			
		||||
        { \
 | 
			
		||||
            INTERNAL_CATCH_CLASS_CONTEXT \
 | 
			
		||||
            INTERNAL_CATCH_TEST_METHOD( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, UniqueExt )::invoke, UniqueExt, TestName, Desc ) \
 | 
			
		||||
            INTERNAL_CATCH_TEST_METHOD( Count, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ), TestName, Desc ) \
 | 
			
		||||
        }; \
 | 
			
		||||
    } \
 | 
			
		||||
    void INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, UniqueExt )::test()
 | 
			
		||||
    void INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) )::test()
 | 
			
		||||
 | 
			
		||||
#if defined(INTERNAL_CATCH_VS_MANAGED)
 | 
			
		||||
 | 
			
		||||
    #define INTERNAL_CATCH_TEST_REPORT_BATCH_FAILURE( count ) \
 | 
			
		||||
    { \
 | 
			
		||||
        std::stringstream _sf; \
 | 
			
		||||
        _sf << count << " assertions failed - check output for results."; \
 | 
			
		||||
        std::string fail = _sf.str(); \
 | 
			
		||||
        Assert::Fail(Catch::convert_string_for_assert(fail)); \
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
    #define INTERNAL_CATCH_TEST_REPORT_BATCH_FAILURE( count ) \
 | 
			
		||||
    { \
 | 
			
		||||
        std::wstringstream _s; \
 | 
			
		||||
        _s << count << " assertions failed - check output for results."; \
 | 
			
		||||
        std::wstring ws = _s.str(); \
 | 
			
		||||
        Assert::Fail(ws.c_str()); \
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define INTERNAL_CATCH_MAP_CATEGORY_TO_TAG2( Category, Tag, Count ) \
 | 
			
		||||
    CHECK_FOR_TEST_CASE_CLASH \
 | 
			
		||||
    namespace CATCH_INTERNAL_NAMESPACE( INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) ) { \
 | 
			
		||||
        CatchOverrides::ConfigReset<Catch::IConfig const*> INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____C_O_N_F_I_G___, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) )(__FILE__, Count); \
 | 
			
		||||
        INTERNAL_CATCH_CLASS_DEFINITION( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____C_L_A_S_S___, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) ) ) \
 | 
			
		||||
        { \
 | 
			
		||||
            INTERNAL_CATCH_CLASS_CONTEXT \
 | 
			
		||||
	        BEGIN_INTERNAL_CATCH_BATCH_METHOD( Category, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) ) \
 | 
			
		||||
            { \
 | 
			
		||||
                Catch::ConfigData cd; \
 | 
			
		||||
                cd.showSuccessfulTests = CatchOverrides::Config<Catch::IConfig const*>::instance().includeSuccessfulResults(__FILE__, Count ); \
 | 
			
		||||
                cd.warnings            = (CatchOverrides::Config<Catch::IConfig const*>::instance().warnAboutMissingAssertions(__FILE__, Count ) ? Catch::WarnAbout::NoAssertions : Catch::WarnAbout::Nothing); \
 | 
			
		||||
                cd.reporterName = "vs_reporter"; \
 | 
			
		||||
                cd.name = "Batch run using tag : " Tag; \
 | 
			
		||||
                cd.testsOrTags.push_back( Tag ); \
 | 
			
		||||
                Catch::Ptr<Catch::Config> config(new Catch::Config(cd)); \
 | 
			
		||||
                Catch::ReporterRegistrar<Catch::MSTestReporter> reporterReg("vs_reporter"); \
 | 
			
		||||
                Catch::Runner runner(config); \
 | 
			
		||||
                Catch::Totals totals = runner.runTests(); \
 | 
			
		||||
                if( totals.assertions.failed > 0 ) { \
 | 
			
		||||
                    INTERNAL_CATCH_TEST_REPORT_BATCH_FAILURE(totals.assertions.failed) \
 | 
			
		||||
                } \
 | 
			
		||||
            } \
 | 
			
		||||
        }; \
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
//#undef CATCH_CONFIG_VARIADIC_MACROS
 | 
			
		||||
 | 
			
		||||
@@ -279,29 +377,29 @@ struct NameAndDesc {
 | 
			
		||||
    #define INTERNAL_CATCH_SPLIT_TAGS_IMPL_(INTERNAL_CATCH_SPLIT_ARG_1,INTERNAL_CATCH_SPLIT_ARG_2,N,...) INTERNAL_CATCH_SPLIT_ARG_2
 | 
			
		||||
 | 
			
		||||
    #define INTERNAL_CATCH_TESTCASE( ... ) \
 | 
			
		||||
        INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_CONCAT_LINE_COUNTER, INTERNAL_CATCH_SPLIT_ARGS_2(__VA_ARGS__), INTERNAL_CATCH_SPLIT_TAGS(__VA_ARGS__) )
 | 
			
		||||
        INTERNAL_CATCH_TESTCASE2( __COUNTER__ , INTERNAL_CATCH_SPLIT_ARGS_2(__VA_ARGS__), INTERNAL_CATCH_SPLIT_TAGS(__VA_ARGS__) )
 | 
			
		||||
 | 
			
		||||
    ///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
    #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
 | 
			
		||||
        INTERNAL_CATCH_METHOD_AS_TEST_CASE2( QualifiedMethod, INTERNAL_CATCH_CONCAT_LINE_COUNTER, INTERNAL_CATCH_SPLIT_ARGS_2(__VA_ARGS__), INTERNAL_CATCH_SPLIT_TAGS(__VA_ARGS__) )
 | 
			
		||||
        INTERNAL_CATCH_METHOD_AS_TEST_CASE2( QualifiedMethod, __COUNTER__, INTERNAL_CATCH_SPLIT_ARGS_2(__VA_ARGS__), INTERNAL_CATCH_SPLIT_TAGS(__VA_ARGS__) )
 | 
			
		||||
 | 
			
		||||
    ///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
    #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... )\
 | 
			
		||||
        INTERNAL_CATCH_TEST_CASE_METHOD2(ClassName, INTERNAL_CATCH_CONCAT_LINE_COUNTER, INTERNAL_CATCH_SPLIT_ARGS_2(__VA_ARGS__), INTERNAL_CATCH_SPLIT_TAGS(__VA_ARGS__) )
 | 
			
		||||
        INTERNAL_CATCH_TEST_CASE_METHOD2(ClassName, __COUNTER__, INTERNAL_CATCH_SPLIT_ARGS_2(__VA_ARGS__), INTERNAL_CATCH_SPLIT_TAGS(__VA_ARGS__) )
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
    ///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
    #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
 | 
			
		||||
        INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_CONCAT_LINE_COUNTER, Name, Desc )
 | 
			
		||||
        INTERNAL_CATCH_TESTCASE2( __COUNTER__ , Name, Desc )
 | 
			
		||||
 | 
			
		||||
    ///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
    #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
 | 
			
		||||
        INTERNAL_CATCH_METHOD_AS_TEST_CASE2( QualifiedMethod, INTERNAL_CATCH_CONCAT_LINE_COUNTER, Name, Desc )
 | 
			
		||||
        INTERNAL_CATCH_METHOD_AS_TEST_CASE2( QualifiedMethod, __COUNTER__, Name, Desc )
 | 
			
		||||
 | 
			
		||||
    ///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
    #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
 | 
			
		||||
        INTERNAL_CATCH_TEST_CASE_METHOD2(ClassName, INTERNAL_CATCH_CONCAT_LINE_COUNTER, TestName, Desc )
 | 
			
		||||
        INTERNAL_CATCH_TEST_CASE_METHOD2(ClassName, __COUNTER__, TestName, Desc )
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@@ -320,51 +418,6 @@ struct NameAndDesc {
 | 
			
		||||
 | 
			
		||||
#include "catch_exception_translator_registry.hpp"
 | 
			
		||||
 | 
			
		||||
namespace Catch {
 | 
			
		||||
    inline NonCopyable::~NonCopyable() {}
 | 
			
		||||
    inline IShared::~IShared() {}
 | 
			
		||||
    inline StreamBufBase::~StreamBufBase() throw() {}
 | 
			
		||||
    inline IContext::~IContext() {}
 | 
			
		||||
    inline IResultCapture::~IResultCapture() {}
 | 
			
		||||
    inline ITestCase::~ITestCase() {}
 | 
			
		||||
    inline ITestCaseRegistry::~ITestCaseRegistry() {}
 | 
			
		||||
    inline IRegistryHub::~IRegistryHub() {}
 | 
			
		||||
    inline IMutableRegistryHub::~IMutableRegistryHub() {}
 | 
			
		||||
    inline IExceptionTranslator::~IExceptionTranslator() {}
 | 
			
		||||
    inline IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {}
 | 
			
		||||
    inline IReporterFactory::~IReporterFactory() {}
 | 
			
		||||
    inline IReporterRegistry::~IReporterRegistry() {}
 | 
			
		||||
    inline IStreamingReporter::~IStreamingReporter() {}
 | 
			
		||||
    inline AssertionStats::~AssertionStats() {}
 | 
			
		||||
    inline SectionStats::~SectionStats() {}
 | 
			
		||||
    inline TestCaseStats::~TestCaseStats() {}
 | 
			
		||||
    inline TestGroupStats::~TestGroupStats() {}
 | 
			
		||||
    inline TestRunStats::~TestRunStats() {}
 | 
			
		||||
    //CumulativeReporterBase::SectionNode::~SectionNode() {}
 | 
			
		||||
    //CumulativeReporterBase::~CumulativeReporterBase() {}
 | 
			
		||||
 | 
			
		||||
    //StreamingReporterBase::~StreamingReporterBase() {}
 | 
			
		||||
    //ConsoleReporter::~ConsoleReporter() {}
 | 
			
		||||
    inline IRunner::~IRunner() {}
 | 
			
		||||
    inline IMutableContext::~IMutableContext() {}
 | 
			
		||||
    inline IConfig::~IConfig() {}
 | 
			
		||||
    //XmlReporter::~XmlReporter() {}
 | 
			
		||||
    //JunitReporter::~JunitReporter() {}
 | 
			
		||||
    //TestRegistry::~TestRegistry() {}
 | 
			
		||||
    inline FreeFunctionTestCase::~FreeFunctionTestCase() {}
 | 
			
		||||
    inline IGeneratorInfo::~IGeneratorInfo() {}
 | 
			
		||||
    inline IGeneratorsForTest::~IGeneratorsForTest() {}
 | 
			
		||||
 | 
			
		||||
    inline Matchers::Impl::StdString::Equals::~Equals() {}
 | 
			
		||||
    inline Matchers::Impl::StdString::Contains::~Contains() {}
 | 
			
		||||
    inline Matchers::Impl::StdString::StartsWith::~StartsWith() {}
 | 
			
		||||
    inline Matchers::Impl::StdString::EndsWith::~EndsWith() {}
 | 
			
		||||
 | 
			
		||||
    inline void Config::dummy() {}
 | 
			
		||||
 | 
			
		||||
    //INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( "xml", XmlReporter )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef __clang__
 | 
			
		||||
#pragma clang diagnostic pop
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -46,15 +46,27 @@ namespace Catch {
 | 
			
		||||
#endif  // detect CLR
 | 
			
		||||
 | 
			
		||||
    struct MSTestReporter : SharedImpl<IStreamingReporter> {
 | 
			
		||||
        MSTestReporter( ReporterConfig const& _config )
 | 
			
		||||
        :   m_config( _config.fullConfig() ),
 | 
			
		||||
            m_headerPrinted( false ),
 | 
			
		||||
            m_atLeastOneTestCasePrinted( false ),
 | 
			
		||||
            m_failed(0)
 | 
			
		||||
        {}
 | 
			
		||||
        
 | 
			
		||||
        MSTestReporter( Ptr<IConfig> const& _fullConfig )
 | 
			
		||||
        :   m_config( _fullConfig ),
 | 
			
		||||
            m_headerPrinted( false ),
 | 
			
		||||
            m_atLeastOneTestCasePrinted( false )
 | 
			
		||||
            m_atLeastOneTestCasePrinted( false ),
 | 
			
		||||
            m_failed(0)
 | 
			
		||||
        {}
 | 
			
		||||
 | 
			
		||||
        virtual ~MSTestReporter() {
 | 
			
		||||
            if( m_atLeastOneTestCasePrinted ) {
 | 
			
		||||
                write_output_message(stream.str());
 | 
			
		||||
                /*if( m_failed )
 | 
			
		||||
                {
 | 
			
		||||
                    Assert::IsTrue(false, L"At least one test failed - examine output for failures.");
 | 
			
		||||
                }*/
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    
 | 
			
		||||
@@ -120,9 +132,6 @@ namespace Catch {
 | 
			
		||||
                write_output_message(_testCaseStats.stdErr);
 | 
			
		||||
                write_output_message(getDoubleDashes());
 | 
			
		||||
            }
 | 
			
		||||
            if( _testCaseStats.totals.assertions.failed ) {
 | 
			
		||||
                Assert::IsTrue(false, L"At least one test failed - examine output for CHECK failures.");
 | 
			
		||||
            }
 | 
			
		||||
            m_headerPrinted = false;
 | 
			
		||||
            currentTestCaseInfo.reset();
 | 
			
		||||
            assert( m_sectionStack.empty() );
 | 
			
		||||
@@ -141,6 +150,7 @@ namespace Catch {
 | 
			
		||||
                printTotalsDivider();
 | 
			
		||||
            printTotals( _testRunStats.totals );
 | 
			
		||||
            stream << "\r\n" << "\r\n";
 | 
			
		||||
            m_failed = _testRunStats.totals.testCases.failed;
 | 
			
		||||
            currentTestCaseInfo.reset();
 | 
			
		||||
            currentGroupInfo.reset();
 | 
			
		||||
            currentTestRunInfo.reset();
 | 
			
		||||
@@ -448,6 +458,7 @@ namespace Catch {
 | 
			
		||||
        std::vector<SectionInfo> m_sectionStack;
 | 
			
		||||
        bool m_headerPrinted;
 | 
			
		||||
        bool m_atLeastOneTestCasePrinted;
 | 
			
		||||
        size_t m_failed;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
} // end namespace Catch
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user