diff options
Diffstat (limited to 'test/unit/catch.hpp')
| -rw-r--r-- | test/unit/catch.hpp | 5037 | 
1 files changed, 3048 insertions, 1989 deletions
| diff --git a/test/unit/catch.hpp b/test/unit/catch.hpp index 2fc6b728e..03665c43f 100644 --- a/test/unit/catch.hpp +++ b/test/unit/catch.hpp @@ -1,6 +1,6 @@  /* - *  CATCH v1.0 build 13 (master branch) - *  Generated: 2013-11-13 08:10:05.836093 + *  CATCH v1.0 build 43 (master branch) + *  Generated: 2014-05-04 09:22:51.466832   *  ----------------------------------------------------------   *  This file has been merged from multiple headers. Please don't edit it directly   *  Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -16,9 +16,22 @@  #ifdef __clang__  #pragma clang diagnostic ignored "-Wglobal-constructors"  #pragma clang diagnostic ignored "-Wvariadic-macros" - +#pragma clang diagnostic ignored "-Wc99-extensions"  #pragma clang diagnostic push  #pragma clang diagnostic ignored "-Wpadded" +#pragma clang diagnostic ignored "-Wc++98-compat" +#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif + +#ifdef CATCH_CONFIG_MAIN +#  define CATCH_CONFIG_RUNNER +#endif + +#ifdef CATCH_CONFIG_RUNNER +#  ifndef CLARA_CONFIG_MAIN +#    define CLARA_CONFIG_MAIN_NOT_DEFINED +#    define CLARA_CONFIG_MAIN +#  endif  #endif  // #included from: internal/catch_notimplemented_exception.h @@ -43,6 +56,18 @@  // Much of the following code is based on Boost (1.53) +#ifdef __clang__ + +#  if __has_feature(cxx_nullptr) +#    define CATCH_CONFIG_CPP11_NULLPTR +#  endif + +#  if __has_feature(cxx_noexcept) +#    define CATCH_CONFIG_CPP11_NOEXCEPT +#  endif + +#endif // __clang__ +  ////////////////////////////////////////////////////////////////////////////////  // Borland  #ifdef __BORLANDC__ @@ -89,6 +114,11 @@  #endif // __GNUC__ < 3 +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) ) + +#define CATCH_CONFIG_CPP11_NULLPTR +#endif +  #endif // __GNUC__  //////////////////////////////////////////////////////////////////////////////// @@ -113,6 +143,26 @@  #endif +//////////////////////////////////////////////////////////////////////////////// +// C++ language feature support + +// detect language version: +#if (__cplusplus == 201103L) +#  define CATCH_CPP11 +#  define CATCH_CPP11_OR_GREATER +#elif (__cplusplus >= 201103L) +#  define CATCH_CPP11_OR_GREATER +#endif + +// noexcept support: +#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT) +#  define CATCH_NOEXCEPT noexcept +#  define CATCH_NOEXCEPT_IS(x) noexcept(x) +#else +#  define CATCH_NOEXCEPT throw() +#  define CATCH_NOEXCEPT_IS(x) +#endif +  namespace Catch {      class NonCopyable { @@ -149,46 +199,17 @@ namespace Catch {              delete it->second;      } -    template<typename ContainerT, typename Function> -    inline void forEach( ContainerT& container, Function function ) { -        std::for_each( container.begin(), container.end(), function ); -    } - -    template<typename ContainerT, typename Function> -    inline void forEach( ContainerT const& container, Function function ) { -        std::for_each( container.begin(), container.end(), function ); -    } - -    inline bool startsWith( std::string const& s, std::string const& prefix ) { -        return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix; -    } -    inline bool endsWith( std::string const& s, std::string const& suffix ) { -        return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix; -    } -    inline bool contains( std::string const& s, std::string const& infix ) { -        return s.find( infix ) != std::string::npos; -    } -    inline void toLowerInPlace( std::string& s ) { -        std::transform( s.begin(), s.end(), s.begin(), ::tolower ); -    } -    inline std::string toLower( std::string const& s ) { -        std::string lc = s; -        toLowerInPlace( lc ); -        return lc; -    } +    bool startsWith( std::string const& s, std::string const& prefix ); +    bool endsWith( std::string const& s, std::string const& suffix ); +    bool contains( std::string const& s, std::string const& infix ); +    void toLowerInPlace( std::string& s ); +    std::string toLower( std::string const& s ); +    std::string trim( std::string const& str );      struct pluralise { -        pluralise( std::size_t count, std::string const& label ) -        :   m_count( count ), -            m_label( label ) -        {} +        pluralise( std::size_t count, std::string const& label ); -        friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { -            os << pluraliser.m_count << " " << pluraliser.m_label; -            if( pluraliser.m_count != 1 ) -                os << "s"; -            return os; -        } +        friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser );          std::size_t m_count;          std::string m_label; @@ -196,42 +217,40 @@ namespace Catch {      struct SourceLineInfo { -        SourceLineInfo() : line( 0 ){} -        SourceLineInfo( std::string const& _file, std::size_t _line ) -        :   file( _file ), -            line( _line ) -        {} -        SourceLineInfo( SourceLineInfo const& other ) -        :   file( other.file ), -            line( other.line ) -        {} -        bool empty() const { -            return file.empty(); -        } -        bool operator == ( SourceLineInfo const& other ) const { -            return line == other.line && file == other.file; -        } +        SourceLineInfo(); +        SourceLineInfo( char const* _file, std::size_t _line ); +        SourceLineInfo( SourceLineInfo const& other ); +#  ifdef CATCH_CPP11_OR_GREATER +        SourceLineInfo( SourceLineInfo && )                  = default; +        SourceLineInfo& operator = ( SourceLineInfo const& ) = default; +        SourceLineInfo& operator = ( SourceLineInfo && )     = default; +#  endif +        bool empty() const; +        bool operator == ( SourceLineInfo const& other ) const; +          std::string file;          std::size_t line;      }; -    inline std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { -#ifndef __GNUG__ -        os << info.file << "(" << info.line << ")"; -#else -        os << info.file << ":" << info.line; -#endif -        return os; -    } +    std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );      // This is just here to avoid compiler warnings with macro constants and boolean literals      inline bool isTrue( bool value ){ return value; } -    inline void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) { -        std::ostringstream oss; -        oss << locationInfo << ": Internal Catch error: '" << message << "'"; -        if( isTrue( true )) -            throw std::logic_error( oss.str() ); +    void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ); + +    // Use this in variadic streaming macros to allow +    //    >> +StreamEndStop +    // as well as +    //    >> stuff +StreamEndStop +    struct StreamEndStop { +        std::string operator+() { +            return std::string(); +        } +    }; +    template<typename T> +    T const& operator + ( T const& value, StreamEndStop ) { +        return value;      }  } @@ -247,9 +266,9 @@ namespace Catch {      public:          NotImplementedException( SourceLineInfo const& lineInfo ); -        virtual ~NotImplementedException() throw() {} +        virtual ~NotImplementedException() CATCH_NOEXCEPT {} -        virtual const char* what() const throw(); +        virtual const char* what() const CATCH_NOEXCEPT;      private:          std::string m_what; @@ -430,11 +449,14 @@ namespace Catch {      };      class TestCase; +    struct IConfig;      struct ITestCaseRegistry {          virtual ~ITestCaseRegistry();          virtual std::vector<TestCase> const& getAllTests() const = 0; -        virtual std::vector<TestCase> getMatchingTestCases( std::string const& rawTestSpec ) const = 0; +        virtual void getFilteredTests( TestCaseFilters const& filters, IConfig const& config, std::vector<TestCase>& matchingTestCases ) const = 0; +        virtual void getFilteredTests( IConfig const& config, std::vector<TestCase>& matchingTestCases ) const = 0; +      };  } @@ -555,8 +577,8 @@ private:  // #included from: catch_expressionresult_builder.h  #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_BUILDER_H_INCLUDED -// #included from: catch_tostring.hpp -#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED +// #included from: catch_tostring.h +#define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED  // #included from: catch_sfinae.hpp  #define TWOBLUECUBES_CATCH_SFINAE_HPP_INCLUDED @@ -596,6 +618,7 @@ namespace Catch {  #include <iomanip>  #include <limits>  #include <vector> +#include <cstddef>  #ifdef __OBJC__  // #included from: catch_objc_arc.hpp @@ -702,6 +725,43 @@ namespace Detail {          }      }; +    struct Endianness { +        enum Arch { Big, Little }; + +        static Arch which() { +            union { +                int asInt; +                char asChar[sizeof (int)]; +            }; + +            asInt = 1; +            return ( asChar[sizeof(int)-1] == 1 ) ? Big : Little; +        } +    }; + +    // Writes the raw memory into a string, considering endianness +    template<typename T> +    std::string rawMemoryToString( T value ) { +        union { +            T typedValue; +            unsigned char bytes[sizeof(T)]; +        }; + +        typedValue = value; + +        std::ostringstream oss; +        oss << "0x"; + +        int i = 0, end = sizeof(T), inc = 1; +        if( Endianness::which() == Endianness::Little ) { +            i = end-1; +            end = inc = -1; +        } +        for( ; i != end; i += inc ) +            oss << std::hex << std::setw(2) << std::setfill('0') << (unsigned int)bytes[i]; +        return oss.str(); +    } +  } // end namespace Detail  template<typename T> @@ -717,9 +777,18 @@ struct StringMaker<T*> {      static std::string convert( U* p ) {          if( !p )              return INTERNAL_CATCH_STRINGIFY( NULL ); -        std::ostringstream oss; -        oss << p; -        return oss.str(); +        else +            return Detail::rawMemoryToString( p ); +    } +}; + +template<typename R, typename C> +struct StringMaker<R C::*> { +    static std::string convert( R C::* p ) { +        if( !p ) +            return INTERNAL_CATCH_STRINGIFY( NULL ); +        else +            return Detail::rawMemoryToString( p );      }  }; @@ -737,7 +806,7 @@ struct StringMaker<std::vector<T, Allocator> > {  namespace Detail {      template<typename T> -    inline std::string makeString( T const& value ) { +    std::string makeString( T const& value ) {          return StringMaker<T>::convert( value );      }  } // end namespace Detail @@ -756,99 +825,27 @@ std::string toString( T const& value ) {  // Built in overloads -inline std::string toString( std::string const& value ) { -    return "\"" + value + "\""; -} - -inline std::string toString( std::wstring const& value ) { -    std::ostringstream oss; -    oss << "\""; -    for(size_t i = 0; i < value.size(); ++i ) -        oss << static_cast<char>( value[i] <= 0xff ? value[i] : '?'); -    oss << "\""; -    return oss.str(); -} - -inline std::string toString( const char* const value ) { -    return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" ); -} - -inline std::string toString( char* const value ) { -    return Catch::toString( static_cast<const char*>( value ) ); -} - -inline std::string toString( int value ) { -    std::ostringstream oss; -    oss << value; -    return oss.str(); -} - -inline std::string toString( unsigned long value ) { -    std::ostringstream oss; -    if( value > 8192 ) -        oss << "0x" << std::hex << value; -    else -        oss << value; -    return oss.str(); -} - -inline std::string toString( unsigned int value ) { -    return toString( static_cast<unsigned long>( value ) ); -} - -inline std::string toString( const double value ) { -    std::ostringstream oss; -    oss << std::setprecision( 10 ) -        << std::fixed -        << value; -    std::string d = oss.str(); -    std::size_t i = d.find_last_not_of( '0' ); -    if( i != std::string::npos && i != d.size()-1 ) { -        if( d[i] == '.' ) -            i++; -        d = d.substr( 0, i+1 ); -    } -    return d; -} - -inline std::string toString( bool value ) { -    return value ? "true" : "false"; -} - -inline std::string toString( char value ) { -    return value < ' ' -        ? toString( static_cast<unsigned int>( value ) ) -        : Detail::makeString( value ); -} - -inline std::string toString( signed char value ) { -    return toString( static_cast<char>( value ) ); -} - -inline std::string toString( unsigned char value ) { -    return toString( static_cast<char>( value ) ); -} +std::string toString( std::string const& value ); +std::string toString( std::wstring const& value ); +std::string toString( const char* const value ); +std::string toString( char* const value ); +std::string toString( int value ); +std::string toString( unsigned long value ); +std::string toString( unsigned int value ); +std::string toString( const double value ); +std::string toString( bool value ); +std::string toString( char value ); +std::string toString( signed char value ); +std::string toString( unsigned char value );  #ifdef CATCH_CONFIG_CPP11_NULLPTR -inline std::string toString( std::nullptr_t ) { -    return "nullptr"; -} +std::string toString( std::nullptr_t );  #endif  #ifdef __OBJC__ -    inline std::string toString( NSString const * const& nsstring ) { -        if( !nsstring ) -            return "nil"; -        return std::string( "@\"" ) + [nsstring UTF8String] + "\""; -    } -    inline std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) { -        if( !nsstring ) -            return "nil"; -        return std::string( "@\"" ) + [nsstring UTF8String] + "\""; -    } -    inline std::string toString( NSObject* const& nsObject ) { -        return toString( [nsObject description] ); -    } +    std::string toString( NSString const * const& nsstring ); +    std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ); +    std::string toString( NSObject* const& nsObject );  #endif      namespace Detail { @@ -962,6 +959,12 @@ namespace Catch {          AssertionResult();          AssertionResult( AssertionInfo const& info, AssertionResultData const& data );          ~AssertionResult(); +#  ifdef CATCH_CPP11_OR_GREATER +         AssertionResult( AssertionResult const& )              = default; +         AssertionResult( AssertionResult && )                  = default; +         AssertionResult& operator = ( AssertionResult const& ) = default; +         AssertionResult& operator = ( AssertionResult && )     = default; +#  endif          bool isOk() const;          bool succeeded() const; @@ -991,6 +994,8 @@ namespace Catch {  #pragma warning(disable:4389) // '==' : signed/unsigned mismatch  #endif +#include <cstddef> +  namespace Catch {  namespace Internal { @@ -1200,14 +1205,21 @@ private:  namespace Catch { -// Wraps the LHS of an expression and captures the operator and RHS (if any) - wrapping them all -// in an ExpressionResultBuilder object +// Wraps the LHS of an expression and captures the operator and RHS (if any) - +// wrapping them all in an ExpressionResultBuilder object  template<typename T>  class ExpressionLhs { -    void operator = ( ExpressionLhs const& ); +    ExpressionLhs& operator = ( ExpressionLhs const& ); +#  ifdef CATCH_CPP11_OR_GREATER +    ExpressionLhs& operator = ( ExpressionLhs && ) = delete; +#  endif  public:      ExpressionLhs( T lhs ) : m_lhs( lhs ) {} +#  ifdef CATCH_CPP11_OR_GREATER +    ExpressionLhs( ExpressionLhs const& ) = default; +    ExpressionLhs( ExpressionLhs && )     = default; +#  endif      template<typename RhsT>      ExpressionResultBuilder& operator == ( RhsT const& rhs ) { @@ -1358,65 +1370,6 @@ namespace Catch {  #define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED  #include <string> -// #included from: catch_totals.hpp -#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED - -#include <cstddef> - -namespace Catch { - -    struct Counts { -        Counts() : passed( 0 ), failed( 0 ) {} - -        Counts operator - ( Counts const& other ) const { -            Counts diff; -            diff.passed = passed - other.passed; -            diff.failed = failed - other.failed; -            return diff; -        } -        Counts& operator += ( Counts const& other ) { -            passed += other.passed; -            failed += other.failed; -            return *this; -        } - -        std::size_t total() const { -            return passed + failed; -        } - -        std::size_t passed; -        std::size_t failed; -    }; - -    struct Totals { - -        Totals operator - ( Totals const& other ) const { -            Totals diff; -            diff.assertions = assertions - other.assertions; -            diff.testCases = testCases - other.testCases; -            return diff; -        } - -        Totals delta( Totals const& prevTotals ) const { -            Totals diff = *this - prevTotals; -            if( diff.assertions.failed > 0 ) -                ++diff.testCases.failed; -            else -                ++diff.testCases.passed; -            return diff; -        } - -        Totals& operator += ( Totals const& other ) { -            assertions += other.assertions; -            testCases += other.testCases; -            return *this; -        } - -        Counts assertions; -        Counts testCases; -    }; -} -  namespace Catch { @@ -1427,6 +1380,7 @@ namespace Catch {      struct SectionInfo;      struct MessageInfo;      class ScopedMessageBuilder; +    struct Counts;      struct IResultCapture { @@ -1448,10 +1402,8 @@ namespace Catch {      };  } -// #included from: catch_debugger.hpp -#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED - -#include <iostream> +// #included from: catch_debugger.h +#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED  // #included from: catch_platform.h  #define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED @@ -1464,516 +1416,74 @@ namespace Catch {  #define CATCH_PLATFORM_WINDOWS  #endif -#ifdef CATCH_PLATFORM_MAC - -    #include <assert.h> -    #include <stdbool.h> -    #include <sys/types.h> -    #include <unistd.h> -    #include <sys/sysctl.h> - -    namespace Catch{ - -        // The following function is taken directly from the following technical note: -        // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html - -        // Returns true if the current process is being debugged (either -        // running under the debugger or has a debugger attached post facto). -        inline bool isDebuggerActive(){ - -            int                 junk; -            int                 mib[4]; -            struct kinfo_proc   info; -            size_t              size; - -            // Initialize the flags so that, if sysctl fails for some bizarre -            // reason, we get a predictable result. - -            info.kp_proc.p_flag = 0; - -            // Initialize mib, which tells sysctl the info we want, in this case -            // we're looking for information about a specific process ID. - -            mib[0] = CTL_KERN; -            mib[1] = KERN_PROC; -            mib[2] = KERN_PROC_PID; -            mib[3] = getpid(); +#include <string> -            // Call sysctl. +namespace Catch{ -            size = sizeof(info); -            junk = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0); -            assert(junk == 0); - -            // We're being debugged if the P_TRACED flag is set. +    bool isDebuggerActive(); +    void writeToDebugConsole( std::string const& text ); +} -            return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); -        } -    } +#ifdef CATCH_PLATFORM_MAC -    // The following code snippet taken from: +    // The following code snippet based on:      // http://cocoawithlove.com/2008/03/break-into-debugger.html      #ifdef DEBUG          #if defined(__ppc64__) || defined(__ppc__) -            #define BreakIntoDebugger() \ -            if( Catch::isDebuggerActive() ) { \ -            __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \ -            : : : "memory","r0","r3","r4" ); \ -            } +            #define CATCH_BREAK_INTO_DEBUGGER() \ +                if( Catch::isDebuggerActive() ) { \ +                    __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \ +                    : : : "memory","r0","r3","r4" ); \ +                }          #else -            #define BreakIntoDebugger() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );} +            #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );}          #endif -    #else -        inline void BreakIntoDebugger(){}      #endif  #elif defined(_MSC_VER) -    extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); -    #define BreakIntoDebugger() if (IsDebuggerPresent() ) { __debugbreak(); } -    inline bool isDebuggerActive() { -        return IsDebuggerPresent() != 0; -    } +    #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); }  #elif defined(__MINGW32__) -    extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();      extern "C" __declspec(dllimport) void __stdcall DebugBreak(); -    #define BreakIntoDebugger() if (IsDebuggerPresent() ) { DebugBreak(); } -    inline bool isDebuggerActive() { -        return IsDebuggerPresent() != 0; -    } -#else -       inline void BreakIntoDebugger(){} -       inline bool isDebuggerActive() { return false; } +    #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); }  #endif -#ifdef CATCH_PLATFORM_WINDOWS -extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* ); -inline void writeToDebugConsole( std::string const& text ) { -    ::OutputDebugStringA( text.c_str() ); -} -#else -inline void writeToDebugConsole( std::string const& text ) { -    // !TBD: Need a version for Mac/ XCode and other IDEs -    std::cout << text; -} -#endif // CATCH_PLATFORM_WINDOWS +#ifndef CATCH_BREAK_INTO_DEBUGGER +#define CATCH_BREAK_INTO_DEBUGGER() Catch::isTrue( true ); +#endif  // #included from: catch_interfaces_registry_hub.h  #define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED -// #included from: catch_interfaces_reporter.h -#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED - -// #included from: catch_config.hpp -#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED - -// #included from: catch_test_spec.h -#define TWOBLUECUBES_CATCH_TEST_SPEC_H_INCLUDED - -// #included from: catch_test_case_info.h -#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED -  #include <string> -#include <set> - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpadded" -#endif  namespace Catch { -    struct ITestCase; - -    struct TestCaseInfo { -        TestCaseInfo(   std::string const& _name, -                        std::string const& _className, -                        std::string const& _description, -                        std::set<std::string> const& _tags, -                        bool _isHidden, -                        SourceLineInfo const& _lineInfo ); - -        TestCaseInfo( TestCaseInfo const& other ); - -        std::string name; -        std::string className; -        std::string description; -        std::set<std::string> tags; -        std::string tagsAsString; -        SourceLineInfo lineInfo; -        bool isHidden; -    }; - -    class TestCase : protected TestCaseInfo { -    public: - -        TestCase( ITestCase* testCase, TestCaseInfo const& info ); -        TestCase( TestCase const& other ); - -        TestCase withName( std::string const& _newName ) const; - -        void invoke() const; - -        TestCaseInfo const& getTestCaseInfo() const; - -        bool isHidden() const; -        bool hasTag( std::string const& tag ) const; -        bool matchesTags( std::string const& tagPattern ) const; -        std::set<std::string> const& getTags() const; - -        void swap( TestCase& other ); -        bool operator == ( TestCase const& other ) const; -        bool operator < ( TestCase const& other ) const; -        TestCase& operator = ( TestCase const& other ); - -    private: -        Ptr<ITestCase> test; -    }; - -    TestCase makeTestCase(  ITestCase* testCase, -                            std::string const& className, -                            std::string const& name, -                            std::string const& description, -                            SourceLineInfo const& lineInfo ); -} - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -// #included from: catch_tags.hpp -#define TWOBLUECUBES_CATCH_TAGS_HPP_INCLUDED - -#include <string> -#include <set> -#include <map> -#include <vector> - -#ifdef __clang__ -#pragma clang diagnostic ignored "-Wpadded" -#endif - -namespace Catch { -    class TagParser { -    public: -        virtual ~TagParser(); - -        void parse( std::string const& str ) { -            std::size_t pos = 0; -            while( pos < str.size() ) { -                char c = str[pos]; -                if( c == '[' ) { -                    std::size_t end = str.find_first_of( ']', pos ); -                    if( end != std::string::npos ) { -                        acceptTag( str.substr( pos+1, end-pos-1 ) ); -                        pos = end+1; -                    } -                    else { -                        acceptChar( c ); -                        pos++; -                    } -                } -                else { -                    acceptChar( c ); -                    pos++; -                } -            } -            endParse(); -        } - -    protected: -        virtual void acceptTag( std::string const& tag ) = 0; -        virtual void acceptChar( char c ) = 0; -        virtual void endParse() {} - -    private: -    }; - -    class TagExtracter : public TagParser { -    public: - -        TagExtracter( std::set<std::string>& tags ) -        :   m_tags( tags ) -        {} -        virtual ~TagExtracter(); - -        void parse( std::string& description ) { -            TagParser::parse( description ); -            description = m_remainder; -        } - -    private: -        virtual void acceptTag( std::string const& tag ) { -            m_tags.insert( toLower( tag ) ); -        } -        virtual void acceptChar( char c ) { -            m_remainder += c; -        } - -        TagExtracter& operator=(TagExtracter const&); - -        std::set<std::string>& m_tags; -        std::string m_remainder; -    }; - -    class Tag { -    public: -        Tag() -        :   m_isNegated( false ) -        {} - -        Tag( std::string const& name, bool isNegated ) -        :   m_name( name ), -            m_isNegated( isNegated ) -        {} - -        std::string getName() const { -            return m_name; -        } -        bool isNegated() const { -            return m_isNegated; -        } - -        bool operator ! () const { -            return m_name.empty(); -        } - -    private: -        std::string m_name; -        bool m_isNegated; -    }; - -    class TagSet { -        typedef std::map<std::string, Tag> TagMap; -    public: -        void add( Tag const& tag ) { -            m_tags.insert( std::make_pair( toLower( tag.getName() ), tag ) ); -        } - -        bool empty() const { -            return m_tags.empty(); -        } - -        bool matches( std::set<std::string> const& tags ) const { -            for(    TagMap::const_iterator -                        it = m_tags.begin(), itEnd = m_tags.end(); -                    it != itEnd; -                    ++it ) { -                bool found = tags.find( it->first ) != tags.end(); -                if( found == it->second.isNegated() ) -                    return false; -            } -            return true; -        } - -    private: -        TagMap m_tags; -    }; - -    class TagExpression { -    public: -        bool matches( std::set<std::string> const& tags ) const { -            for(    std::vector<TagSet>::const_iterator -                        it = m_tagSets.begin(), itEnd = m_tagSets.end(); -                    it != itEnd; -                    ++it ) -                if( it->matches( tags ) ) -                    return true; -            return false; -        } - -    private: -        friend class TagExpressionParser; - -        std::vector<TagSet> m_tagSets; -    }; - -    class TagExpressionParser : public TagParser { -    public: -        TagExpressionParser( TagExpression& exp ) -        :   m_isNegated( false ), -            m_exp( exp ) -        {} - -        ~TagExpressionParser(); - -    private: -        virtual void acceptTag( std::string const& tag ) { -            m_currentTagSet.add( Tag( tag, m_isNegated ) ); -            m_isNegated = false; -        } -        virtual void acceptChar( char c ) { -            switch( c ) { -                case '~': -                    m_isNegated = true; -                    break; -                case ',': -                    m_exp.m_tagSets.push_back( m_currentTagSet ); -                    m_currentTagSet = TagSet(); -                    break; -            } -        } -        virtual void endParse() { -            if( !m_currentTagSet.empty() ) -                m_exp.m_tagSets.push_back( m_currentTagSet ); -        } +    class TestCase; +    struct ITestCaseRegistry; +    struct IExceptionTranslatorRegistry; +    struct IExceptionTranslator; +    struct IReporterRegistry; +    struct IReporterFactory; -        TagExpressionParser& operator=(TagExpressionParser const&); +    struct IRegistryHub { +        virtual ~IRegistryHub(); -        bool m_isNegated; -        TagSet m_currentTagSet; -        TagExpression& m_exp; +        virtual IReporterRegistry const& getReporterRegistry() const = 0; +        virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; +        virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0;      }; -} // end namespace Catch - -#include <string> -#include <vector> - -namespace Catch { - -    struct IfFilterMatches{ enum DoWhat { -        AutoDetectBehaviour, -        IncludeTests, -        ExcludeTests -    }; }; - -    class TestCaseFilter { -        enum WildcardPosition { -            NoWildcard = 0, -            WildcardAtStart = 1, -            WildcardAtEnd = 2, -            WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd -        }; - -    public: -        TestCaseFilter( std::string const& testSpec, IfFilterMatches::DoWhat matchBehaviour = IfFilterMatches::AutoDetectBehaviour ) -        :   m_stringToMatch( toLower( testSpec ) ), -            m_filterType( matchBehaviour ), -            m_wildcardPosition( NoWildcard ) -        { -            if( m_filterType == IfFilterMatches::AutoDetectBehaviour ) { -                if( startsWith( m_stringToMatch, "exclude:" ) ) { -                    m_stringToMatch = m_stringToMatch.substr( 8 ); -                    m_filterType = IfFilterMatches::ExcludeTests; -                } -                else if( startsWith( m_stringToMatch, "~" ) ) { -                    m_stringToMatch = m_stringToMatch.substr( 1 ); -                    m_filterType = IfFilterMatches::ExcludeTests; -                } -                else { -                    m_filterType = IfFilterMatches::IncludeTests; -                } -            } - -            if( startsWith( m_stringToMatch, "*" ) ) { -                m_stringToMatch = m_stringToMatch.substr( 1 ); -                m_wildcardPosition = (WildcardPosition)( m_wildcardPosition | WildcardAtStart ); -            } -            if( endsWith( m_stringToMatch, "*" ) ) { -                m_stringToMatch = m_stringToMatch.substr( 0, m_stringToMatch.size()-1 ); -                m_wildcardPosition = (WildcardPosition)( m_wildcardPosition | WildcardAtEnd ); -            } -        } - -        IfFilterMatches::DoWhat getFilterType() const { -            return m_filterType; -        } - -        bool shouldInclude( TestCase const& testCase ) const { -            return isMatch( testCase ) == (m_filterType == IfFilterMatches::IncludeTests); -        } -    private: - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunreachable-code" -#endif - -        bool isMatch( TestCase const& testCase ) const { -            std::string name = testCase.getTestCaseInfo().name; -            toLowerInPlace( name ); - -            switch( m_wildcardPosition ) { -                case NoWildcard: -                    return m_stringToMatch == name; -                case WildcardAtStart: -                    return endsWith( name, m_stringToMatch ); -                case WildcardAtEnd: -                    return startsWith( name, m_stringToMatch ); -                case WildcardAtBothEnds: -                    return contains( name, m_stringToMatch ); -            } -            throw std::logic_error( "Unhandled wildcard type" ); -        } - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -        std::string m_stringToMatch; -        IfFilterMatches::DoWhat m_filterType; -        WildcardPosition m_wildcardPosition; +    struct IMutableRegistryHub { +        virtual ~IMutableRegistryHub(); +        virtual void registerReporter( std::string const& name, IReporterFactory* factory ) = 0; +        virtual void registerTest( TestCase const& testInfo ) = 0; +        virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;      }; -    class TestCaseFilters { -    public: -        TestCaseFilters( std::string const& name ) : m_name( name ) {} - -        std::string getName() const { -            return m_name; -        } - -        void addFilter( TestCaseFilter const& filter ) { -            if( filter.getFilterType() == IfFilterMatches::ExcludeTests ) -                m_exclusionFilters.push_back( filter ); -            else -                m_inclusionFilters.push_back( filter ); -        } - -        void addTags( std::string const& tagPattern ) { -            TagExpression exp; -            TagExpressionParser( exp ).parse( tagPattern ); - -            m_tagExpressions.push_back( exp ); -        } - -        bool shouldInclude( TestCase const& testCase ) const { -            if( !m_tagExpressions.empty() ) { -                std::vector<TagExpression>::const_iterator it = m_tagExpressions.begin(); -                std::vector<TagExpression>::const_iterator itEnd = m_tagExpressions.end(); -                for(; it != itEnd; ++it ) -                    if( it->matches( testCase.getTags() ) ) -                        break; -                if( it == itEnd ) -                    return false; -            } - -            if( !m_inclusionFilters.empty() ) { -                std::vector<TestCaseFilter>::const_iterator it = m_inclusionFilters.begin(); -                std::vector<TestCaseFilter>::const_iterator itEnd = m_inclusionFilters.end(); -                for(; it != itEnd; ++it ) -                    if( it->shouldInclude( testCase ) ) -                        break; -                if( it == itEnd ) -                    return false; -            } -            else if( m_exclusionFilters.empty() && m_tagExpressions.empty() ) { -                return !testCase.isHidden(); -            } - -            std::vector<TestCaseFilter>::const_iterator it = m_exclusionFilters.begin(); -            std::vector<TestCaseFilter>::const_iterator itEnd = m_exclusionFilters.end(); -            for(; it != itEnd; ++it ) -                if( !it->shouldInclude( testCase ) ) -                    return false; -            return true; -        } -    private: -        std::vector<TagExpression> m_tagExpressions; -        std::vector<TestCaseFilter> m_inclusionFilters; -        std::vector<TestCaseFilter> m_exclusionFilters; -        std::string m_name; -    }; +    IRegistryHub& getRegistryHub(); +    IMutableRegistryHub& getMutableRegistryHub(); +    void cleanUp(); +    std::string translateActiveException();  } @@ -1982,6 +1492,7 @@ namespace Catch {  #include <iostream>  #include <string> +#include <vector>  namespace Catch { @@ -2002,6 +1513,8 @@ namespace Catch {          Never      }; }; +    class TestCaseFilters; +      struct IConfig : IShared {          virtual ~IConfig(); @@ -2013,774 +1526,12 @@ namespace Catch {          virtual bool shouldDebugBreak() const = 0;          virtual bool warnAboutMissingAssertions() const = 0;          virtual int abortAfter() const = 0; +        virtual bool showInvisibles() const = 0;          virtual ShowDurations::OrNot showDurations() const = 0; +        virtual std::vector<TestCaseFilters> const& filters() const = 0;      };  } -// #included from: catch_stream.hpp -#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED - -// #included from: catch_streambuf.h -#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED - -#include <streambuf> - -namespace Catch { - -    class StreamBufBase : public std::streambuf { -    public: -        virtual ~StreamBufBase() throw(); -    }; -} - -#include <stdexcept> -#include <cstdio> - -namespace Catch { - -    template<typename WriterF, size_t bufferSize=256> -    class StreamBufImpl : public StreamBufBase { -        char data[bufferSize]; -        WriterF m_writer; - -    public: -        StreamBufImpl() { -            setp( data, data + sizeof(data) ); -        } - -        ~StreamBufImpl() throw() { -            sync(); -        } - -    private: -        int overflow( int c ) { -            sync(); - -            if( c != EOF ) { -                if( pbase() == epptr() ) -                    m_writer( std::string( 1, static_cast<char>( c ) ) ); -                else -                    sputc( static_cast<char>( c ) ); -            } -            return 0; -        } - -        int sync() { -            if( pbase() != pptr() ) { -                m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) ); -                setp( pbase(), epptr() ); -            } -            return 0; -        } -    }; - -    /////////////////////////////////////////////////////////////////////////// - -    struct OutputDebugWriter { - -        void operator()( std::string const&str ) { -            writeToDebugConsole( str ); -        } -    }; - -    class Stream { -    public: -        Stream() -        : streamBuf( NULL ), isOwned( false ) -        {} - -        Stream( std::streambuf* _streamBuf, bool _isOwned ) -        : streamBuf( _streamBuf ), isOwned( _isOwned ) -        {} - -        void release() { -            if( isOwned ) { -                delete streamBuf; -                streamBuf = NULL; -                isOwned = false; -            } -        } - -        std::streambuf* streamBuf; - -    private: -        bool isOwned; -    }; -} - -#include <memory> -#include <vector> -#include <string> -#include <iostream> - -#ifndef CATCH_CONFIG_CONSOLE_WIDTH -#define CATCH_CONFIG_CONSOLE_WIDTH 80 -#endif - -namespace Catch { - -    struct ConfigData { - -        ConfigData() -        :   listTests( false ), -            listTags( false ), -            listReporters( false ), -            showSuccessfulTests( false ), -            shouldDebugBreak( false ), -            noThrow( false ), -            showHelp( false ), -            abortAfter( -1 ), -            verbosity( Verbosity::Normal ), -            warnings( WarnAbout::Nothing ), -            showDurations( ShowDurations::DefaultForReporter ) -        {} - -        bool listTests; -        bool listTags; -        bool listReporters; - -        bool showSuccessfulTests; -        bool shouldDebugBreak; -        bool noThrow; -        bool showHelp; - -        int abortAfter; - -        Verbosity::Level verbosity; -        WarnAbout::What warnings; -        ShowDurations::OrNot showDurations; - -        std::string reporterName; -        std::string outputFilename; -        std::string name; -        std::string processName; - -        std::vector<std::string> testsOrTags; -    }; - -    class Config : public SharedImpl<IConfig> { -    private: -        Config( Config const& other ); -        Config& operator = ( Config const& other ); -        virtual void dummy(); -    public: - -        Config() -        :   m_os( std::cout.rdbuf() ) -        {} - -        Config( ConfigData const& data ) -        :   m_data( data ), -            m_os( std::cout.rdbuf() ) -        { -            if( !data.testsOrTags.empty() ) { -                std::string groupName; -                for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) { -                    if( i != 0 ) -                        groupName += " "; -                    groupName += data.testsOrTags[i]; -                } -                TestCaseFilters filters( groupName ); -                for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) { -                    std::string filter = data.testsOrTags[i]; -                    if( startsWith( filter, "[" ) || startsWith( filter, "~[" ) ) -                        filters.addTags( filter ); -                    else -                        filters.addFilter( TestCaseFilter( filter ) ); -                } -                m_filterSets.push_back( filters ); -            } -        } - -        virtual ~Config() { -            m_os.rdbuf( std::cout.rdbuf() ); -            m_stream.release(); -        } - -        void setFilename( std::string const& filename ) { -            m_data.outputFilename = filename; -        } - -        std::string const& getFilename() const { -            return m_data.outputFilename ; -        } - -        bool listTests() const { return m_data.listTests; } -        bool listTags() const { return m_data.listTags; } -        bool listReporters() const { return m_data.listReporters; } - -        std::string getProcessName() const { -            return m_data.processName; -        } - -        bool shouldDebugBreak() const { -            return m_data.shouldDebugBreak; -        } - -        void setStreamBuf( std::streambuf* buf ) { -            m_os.rdbuf( buf ? buf : std::cout.rdbuf() ); -        } - -        void useStream( std::string const& streamName ) { -            Stream stream = createStream( streamName ); -            setStreamBuf( stream.streamBuf ); -            m_stream.release(); -            m_stream = stream; -        } - -        std::string getReporterName() const { return m_data.reporterName; } - -        void addTestSpec( std::string const& testSpec ) { -            TestCaseFilters filters( testSpec ); -            filters.addFilter( TestCaseFilter( testSpec ) ); -            m_filterSets.push_back( filters ); -        } - -        int abortAfter() const { -            return m_data.abortAfter; -        } - -        std::vector<TestCaseFilters> const& filters() const { -            return m_filterSets; -        } - -        bool showHelp() const { return m_data.showHelp; } - -        // IConfig interface -        virtual bool allowThrows() const        { return !m_data.noThrow; } -        virtual std::ostream& stream() const    { return m_os; } -        virtual std::string name() const        { return m_data.name.empty() ? m_data.processName : m_data.name; } -        virtual bool includeSuccessfulResults() const   { return m_data.showSuccessfulTests; } -        virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; } -        virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; } - -    private: -        ConfigData m_data; - -        Stream m_stream; -        mutable std::ostream m_os; -        std::vector<TestCaseFilters> m_filterSets; -    }; - -} // end namespace Catch - -// #included from: catch_option.hpp -#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED - -namespace Catch { - -    // An optional type -    template<typename T> -    class Option { -    public: -        Option() : nullableValue( NULL ) {} -        Option( T const& _value ) -        : nullableValue( new( storage ) T( _value ) ) -        {} -        Option( Option const& _other ) -        : nullableValue( _other ? new( storage ) T( *_other ) : NULL ) -        {} - -        ~Option() { -            reset(); -        } - -        Option& operator= ( Option const& _other ) { -            reset(); -            if( _other ) -                nullableValue = new( storage ) T( *_other ); -            return *this; -        } -        Option& operator = ( T const& _value ) { -            reset(); -            nullableValue = new( storage ) T( _value ); -            return *this; -        } - -        void reset() { -            if( nullableValue ) -                nullableValue->~T(); -            nullableValue = NULL; -        } - -        T& operator*() { return *nullableValue; } -        T const& operator*() const { return *nullableValue; } -        T* operator->() { return nullableValue; } -        const T* operator->() const { return nullableValue; } - -        T valueOr( T const& defaultValue ) const { -            return nullableValue ? *nullableValue : defaultValue; -        } - -        bool some() const { return nullableValue != NULL; } -        bool none() const { return nullableValue == NULL; } - -        bool operator !() const { return nullableValue == NULL; } -        operator SafeBool::type() const { -            return SafeBool::makeSafe( some() ); -        } - -    private: -        T* nullableValue; -        char storage[sizeof(T)]; -    }; - -} // end namespace Catch - -#include <string> -#include <ostream> -#include <map> -#include <assert.h> - -namespace Catch -{ -    struct ReporterConfig { -        explicit ReporterConfig( Ptr<IConfig> const& _fullConfig ) -        :   m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} - -        ReporterConfig( Ptr<IConfig> const& _fullConfig, std::ostream& _stream ) -        :   m_stream( &_stream ), m_fullConfig( _fullConfig ) {} - -        std::ostream& stream() const    { return *m_stream; } -        Ptr<IConfig> fullConfig() const { return m_fullConfig; } - -    private: -        std::ostream* m_stream; -        Ptr<IConfig> m_fullConfig; -    }; - -    struct ReporterPreferences { -        ReporterPreferences() -        : shouldRedirectStdOut( false ) -        {} - -        bool shouldRedirectStdOut; -    }; - -    template<typename T> -    struct LazyStat : Option<T> { -        LazyStat() : used( false ) {} -        LazyStat& operator=( T const& _value ) { -            Option<T>::operator=( _value ); -            used = false; -            return *this; -        } -        void reset() { -            Option<T>::reset(); -            used = false; -        } -        bool used; -    }; - -    struct TestRunInfo { -        TestRunInfo( std::string const& _name ) : name( _name ) {} -        std::string name; -    }; -    struct GroupInfo { -        GroupInfo(  std::string const& _name, -                    std::size_t _groupIndex, -                    std::size_t _groupsCount ) -        :   name( _name ), -            groupIndex( _groupIndex ), -            groupsCounts( _groupsCount ) -        {} - -        std::string name; -        std::size_t groupIndex; -        std::size_t groupsCounts; -    }; - -    struct SectionInfo { -        SectionInfo(    std::string const& _name, -                        std::string const& _description, -                        SourceLineInfo const& _lineInfo ) -        :   name( _name ), -            description( _description ), -            lineInfo( _lineInfo ) -        {} - -        std::string name; -        std::string description; -        SourceLineInfo lineInfo; -    }; - -    struct AssertionStats { -        AssertionStats( AssertionResult const& _assertionResult, -                        std::vector<MessageInfo> const& _infoMessages, -                        Totals const& _totals ) -        :   assertionResult( _assertionResult ), -            infoMessages( _infoMessages ), -            totals( _totals ) -        { -            if( assertionResult.hasMessage() ) { -                // Copy message into messages list. -                // !TBD This should have been done earlier, somewhere -                MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); -                builder << assertionResult.getMessage(); -                builder.m_info.message = builder.m_stream.str(); - -                infoMessages.push_back( builder.m_info ); -            } -        } -        virtual ~AssertionStats(); - -        AssertionResult assertionResult; -        std::vector<MessageInfo> infoMessages; -        Totals totals; -    }; - -    struct SectionStats { -        SectionStats(   SectionInfo const& _sectionInfo, -                        Counts const& _assertions, -                        double _durationInSeconds, -                        bool _missingAssertions ) -        :   sectionInfo( _sectionInfo ), -            assertions( _assertions ), -            durationInSeconds( _durationInSeconds ), -            missingAssertions( _missingAssertions ) -        {} -        virtual ~SectionStats(); - -        SectionInfo sectionInfo; -        Counts assertions; -        double durationInSeconds; -        bool missingAssertions; -    }; - -    struct TestCaseStats { -        TestCaseStats(  TestCaseInfo const& _testInfo, -                        Totals const& _totals, -                        std::string const& _stdOut, -                        std::string const& _stdErr, -                        bool _aborting ) -        : testInfo( _testInfo ), -            totals( _totals ), -            stdOut( _stdOut ), -            stdErr( _stdErr ), -            aborting( _aborting ) -        {} -        virtual ~TestCaseStats(); - -        TestCaseInfo testInfo; -        Totals totals; -        std::string stdOut; -        std::string stdErr; -        bool aborting; -    }; - -    struct TestGroupStats { -        TestGroupStats( GroupInfo const& _groupInfo, -                        Totals const& _totals, -                        bool _aborting ) -        :   groupInfo( _groupInfo ), -            totals( _totals ), -            aborting( _aborting ) -        {} -        TestGroupStats( GroupInfo const& _groupInfo ) -        :   groupInfo( _groupInfo ), -            aborting( false ) -        {} -        virtual ~TestGroupStats(); - -        GroupInfo groupInfo; -        Totals totals; -        bool aborting; -    }; - -    struct TestRunStats { -        TestRunStats(   TestRunInfo const& _runInfo, -                        Totals const& _totals, -                        bool _aborting ) -        :   runInfo( _runInfo ), -            totals( _totals ), -            aborting( _aborting ) -        {} -        TestRunStats( TestRunStats const& _other ) -        :   runInfo( _other.runInfo ), -            totals( _other.totals ), -            aborting( _other.aborting ) -        {} -        virtual ~TestRunStats(); - -        TestRunInfo runInfo; -        Totals totals; -        bool aborting; -    }; - -    struct IStreamingReporter : IShared { -        virtual ~IStreamingReporter(); - -        // Implementing class must also provide the following static method: -        // static std::string getDescription(); - -        virtual ReporterPreferences getPreferences() const = 0; - -        virtual void noMatchingTestCases( std::string const& spec ) = 0; - -        virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; -        virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0; - -        virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; -        virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; - -        virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; - -        virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; -        virtual void sectionEnded( SectionStats const& sectionStats ) = 0; -        virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; -        virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; -        virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; -    }; - -    struct StreamingReporterBase : SharedImpl<IStreamingReporter> { - -        StreamingReporterBase( ReporterConfig const& _config ) -        :   m_config( _config.fullConfig() ), -            stream( _config.stream() ) -        {} - -        virtual ~StreamingReporterBase(); - -        virtual void noMatchingTestCases( std::string const& ) {} - -        virtual void testRunStarting( TestRunInfo const& _testRunInfo ) { -            currentTestRunInfo = _testRunInfo; -        } -        virtual void testGroupStarting( GroupInfo const& _groupInfo ) { -            currentGroupInfo = _groupInfo; -        } - -        virtual void testCaseStarting( TestCaseInfo const& _testInfo ) { -            currentTestCaseInfo = _testInfo; -        } -        virtual void sectionStarting( SectionInfo const& _sectionInfo ) { -            m_sectionStack.push_back( _sectionInfo ); -        } - -        virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) { -            m_sectionStack.pop_back(); -        } -        virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) { -            currentTestCaseInfo.reset(); -            assert( m_sectionStack.empty() ); -        } -        virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) { -            currentGroupInfo.reset(); -        } -        virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) { -            currentTestCaseInfo.reset(); -            currentGroupInfo.reset(); -            currentTestRunInfo.reset(); -        } - -        Ptr<IConfig> m_config; -        std::ostream& stream; - -        LazyStat<TestRunInfo> currentTestRunInfo; -        LazyStat<GroupInfo> currentGroupInfo; -        LazyStat<TestCaseInfo> currentTestCaseInfo; - -        std::vector<SectionInfo> m_sectionStack; -    }; - -    struct CumulativeReporterBase : SharedImpl<IStreamingReporter> { -        template<typename T, typename ChildNodeT> -        struct Node : SharedImpl<> { -            explicit Node( T const& _value ) : value( _value ) {} -            virtual ~Node() {} - -            typedef std::vector<Ptr<ChildNodeT> > ChildNodes; -            T value; -            ChildNodes children; -        }; -        struct SectionNode : SharedImpl<> { -            explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {} -            virtual ~SectionNode(); - -            bool operator == ( SectionNode const& other ) const { -                return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; -            } -            bool operator == ( Ptr<SectionNode> const& other ) const { -                return operator==( *other ); -            } - -            SectionStats stats; -            typedef std::vector<Ptr<SectionNode> > ChildSections; -            typedef std::vector<AssertionStats> Assertions; -            ChildSections childSections; -            Assertions assertions; -            std::string stdOut; -            std::string stdErr; -        }; -        friend bool operator == ( Ptr<SectionNode> const& node, SectionInfo const& other ) { -            return node->stats.sectionInfo.lineInfo == other.lineInfo; -        } - -        typedef Node<TestCaseStats, SectionNode> TestCaseNode; -        typedef Node<TestGroupStats, TestCaseNode> TestGroupNode; -        typedef Node<TestRunStats, TestGroupNode> TestRunNode; - -        CumulativeReporterBase( ReporterConfig const& _config ) -        :   m_config( _config.fullConfig() ), -            stream( _config.stream() ) -        {} -        ~CumulativeReporterBase(); - -        virtual void testRunStarting( TestRunInfo const& ) {} -        virtual void testGroupStarting( GroupInfo const& ) {} - -        virtual void testCaseStarting( TestCaseInfo const& ) {} - -        virtual void sectionStarting( SectionInfo const& sectionInfo ) { -            SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); -            Ptr<SectionNode> node; -            if( m_sectionStack.empty() ) { -                if( !m_rootSection ) -                    m_rootSection = new SectionNode( incompleteStats ); -                node = m_rootSection; -            } -            else { -                SectionNode& parentNode = *m_sectionStack.back(); -                SectionNode::ChildSections::const_iterator it = -                    std::find( parentNode.childSections.begin(), parentNode.childSections.end(), sectionInfo ); -                if( it == parentNode.childSections.end() ) { -                    node = new SectionNode( incompleteStats ); -                    parentNode.childSections.push_back( node ); -                } -                else -                    node = *it; -            } -            m_sectionStack.push_back( node ); -            m_deepestSection = node; -        } - -        virtual void assertionStarting( AssertionInfo const& ) {} - -        virtual bool assertionEnded( AssertionStats const& assertionStats ) { -            assert( !m_sectionStack.empty() ); -            SectionNode& sectionNode = *m_sectionStack.back(); -            sectionNode.assertions.push_back( assertionStats ); -            return true; -        } -        virtual void sectionEnded( SectionStats const& sectionStats ) { -            assert( !m_sectionStack.empty() ); -            SectionNode& node = *m_sectionStack.back(); -            node.stats = sectionStats; -            m_sectionStack.pop_back(); -        } -        virtual void testCaseEnded( TestCaseStats const& testCaseStats ) { -            Ptr<TestCaseNode> node = new TestCaseNode( testCaseStats ); -            assert( m_sectionStack.size() == 0 ); -            node->children.push_back( m_rootSection ); -            m_testCases.push_back( node ); -            m_rootSection.reset(); - -            assert( m_deepestSection ); -            m_deepestSection->stdOut = testCaseStats.stdOut; -            m_deepestSection->stdErr = testCaseStats.stdErr; -        } -        virtual void testGroupEnded( TestGroupStats const& testGroupStats ) { -            Ptr<TestGroupNode> node = new TestGroupNode( testGroupStats ); -            node->children.swap( m_testCases ); -            m_testGroups.push_back( node ); -        } -        virtual void testRunEnded( TestRunStats const& testRunStats ) { -            Ptr<TestRunNode> node = new TestRunNode( testRunStats ); -            node->children.swap( m_testGroups ); -            m_testRuns.push_back( node ); -            testRunEnded(); -        } -        virtual void testRunEnded() = 0; - -        Ptr<IConfig> m_config; -        std::ostream& stream; -        std::vector<AssertionStats> m_assertions; -        std::vector<std::vector<Ptr<SectionNode> > > m_sections; -        std::vector<Ptr<TestCaseNode> > m_testCases; -        std::vector<Ptr<TestGroupNode> > m_testGroups; - -        std::vector<Ptr<TestRunNode> > m_testRuns; - -        Ptr<SectionNode> m_rootSection; -        Ptr<SectionNode> m_deepestSection; -        std::vector<Ptr<SectionNode> > m_sectionStack; - -    }; - -    // Deprecated -    struct IReporter : IShared { -        virtual ~IReporter(); - -        virtual bool shouldRedirectStdout() const = 0; - -        virtual void StartTesting() = 0; -        virtual void EndTesting( Totals const& totals ) = 0; -        virtual void StartGroup( std::string const& groupName ) = 0; -        virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0; -        virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0; -        virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0; -        virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0; -        virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0; -        virtual void NoAssertionsInSection( std::string const& sectionName ) = 0; -        virtual void NoAssertionsInTestCase( std::string const& testName ) = 0; -        virtual void Aborted() = 0; -        virtual void Result( AssertionResult const& result ) = 0; -    }; - -    struct IReporterFactory { -        virtual ~IReporterFactory(); -        virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0; -        virtual std::string getDescription() const = 0; -    }; - -    struct IReporterRegistry { -        typedef std::map<std::string, IReporterFactory*> FactoryMap; - -        virtual ~IReporterRegistry(); -        virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig> const& config ) const = 0; -        virtual FactoryMap const& getFactories() const = 0; -    }; - -    inline std::string trim( std::string const& str ) { -        static char const* whitespaceChars = "\n\r\t "; -        std::string::size_type start = str.find_first_not_of( whitespaceChars ); -        std::string::size_type end = str.find_last_not_of( whitespaceChars ); - -        return start != std::string::npos ? str.substr( start, 1+end-start ) : ""; -    } -} - -#include <vector> - -namespace Catch { - -    class TestCase; -    struct ITestCaseRegistry; -    struct IExceptionTranslatorRegistry; -    struct IExceptionTranslator; - -    struct IRegistryHub { -        virtual ~IRegistryHub(); - -        virtual IReporterRegistry const& getReporterRegistry() const = 0; -        virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; -        virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; -    }; - -    struct IMutableRegistryHub { -        virtual ~IMutableRegistryHub(); -        virtual void registerReporter( std::string const& name, IReporterFactory* factory ) = 0; -        virtual void registerTest( TestCase const& testInfo ) = 0; -        virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; -    }; - -    IRegistryHub& getRegistryHub(); -    IMutableRegistryHub& getMutableRegistryHub(); -    void cleanUp(); -    std::string translateActiveException(); - -} -  #include <ostream>  namespace Catch { @@ -2823,32 +1574,25 @@ struct TestFailureException{};  } // end namespace Catch  /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_ASSERTIONINFO_NAME INTERNAL_CATCH_UNIQUE_NAME( __assertionInfo ) - -///////////////////////////////////////////////////////////////////////////////  #define INTERNAL_CATCH_ACCEPT_EXPR( evaluatedExpr, resultDisposition, originalExpr ) \ -    if( Catch::ResultAction::Value internal_catch_action = Catch::getResultCapture().acceptExpression( evaluatedExpr, INTERNAL_CATCH_ASSERTIONINFO_NAME )  ) { \ -        if( internal_catch_action & Catch::ResultAction::Debug ) BreakIntoDebugger(); \ +    if( Catch::ResultAction::Value internal_catch_action = Catch::getResultCapture().acceptExpression( evaluatedExpr, __assertionInfo )  ) { \ +        if( internal_catch_action & Catch::ResultAction::Debug ) CATCH_BREAK_INTO_DEBUGGER(); \          if( internal_catch_action & Catch::ResultAction::Abort ) throw Catch::TestFailureException(); \          if( !Catch::shouldContinueOnFailure( resultDisposition ) ) throw Catch::TestFailureException(); \          Catch::isTrue( false && originalExpr ); \      }  /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_ACCEPT_INFO( expr, macroName, resultDisposition ) \ -    Catch::AssertionInfo INTERNAL_CATCH_ASSERTIONINFO_NAME( macroName, CATCH_INTERNAL_LINEINFO, expr, resultDisposition ); - -///////////////////////////////////////////////////////////////////////////////  #define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \      do { \ -        INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \ +        Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \          try { \              INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionDecomposer()->*expr ).endExpression( resultDisposition ), resultDisposition, expr ); \          } catch( Catch::TestFailureException& ) { \              throw; \          } catch( ... ) { \              INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException(), \ -                resultDisposition | Catch::ResultDisposition::ContinueOnFailure, expr ); \ +                Catch::ResultDisposition::Normal, expr ); \          } \      } while( Catch::isTrue( false ) ) @@ -2865,7 +1609,7 @@ struct TestFailureException{};  ///////////////////////////////////////////////////////////////////////////////  #define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \      do { \ -        INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \ +        Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \          try { \              expr; \              INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::Ok ), resultDisposition, false ); \ @@ -2893,14 +1637,14 @@ struct TestFailureException{};  ///////////////////////////////////////////////////////////////////////////////  #define INTERNAL_CATCH_THROWS( expr, exceptionType, resultDisposition, macroName ) \      do { \ -        INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \ +        Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \          INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \      } while( Catch::isTrue( false ) )  ///////////////////////////////////////////////////////////////////////////////  #define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \      do { \ -        INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \ +        Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \          INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \          catch( ... ) { \              INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException() ), \ @@ -2909,11 +1653,19 @@ struct TestFailureException{};      } while( Catch::isTrue( false ) )  /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_MSG( log, messageType, resultDisposition, macroName ) \ -    do { \ -        INTERNAL_CATCH_ACCEPT_INFO( "", macroName, resultDisposition ); \ -        INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( messageType ) << log, resultDisposition, true ) \ -    } while( Catch::isTrue( false ) ) +#ifdef CATCH_CONFIG_VARIADIC_MACROS +    #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \ +        do { \ +            Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ +            INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( messageType ) << __VA_ARGS__ +::Catch::StreamEndStop(), resultDisposition, true ) \ +        } while( Catch::isTrue( false ) ) +#else +    #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \ +        do { \ +            Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ +            INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( messageType ) << log, resultDisposition, true ) \ +        } while( Catch::isTrue( false ) ) +#endif  ///////////////////////////////////////////////////////////////////////////////  #define INTERNAL_CATCH_INFO( log, macroName ) \ @@ -2922,7 +1674,7 @@ struct TestFailureException{};  ///////////////////////////////////////////////////////////////////////////////  #define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \      do { \ -        INTERNAL_CATCH_ACCEPT_INFO( #arg " " #matcher, macroName, resultDisposition ); \ +        Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #arg " " #matcher, resultDisposition ); \          try { \              INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::expressionResultBuilderFromMatcher( ::Catch::Matchers::matcher, arg, #matcher ) ), resultDisposition, false ); \          } catch( Catch::TestFailureException& ) { \ @@ -2933,8 +1685,88 @@ struct TestFailureException{};          } \      } while( Catch::isTrue( false ) ) -// #included from: internal/catch_section.hpp -#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED +// #included from: internal/catch_section.h +#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED + +// #included from: catch_section_info.h +#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED + +namespace Catch { + +    struct SectionInfo { +        SectionInfo(    std::string const& _name, +                        std::string const& _description, +                        SourceLineInfo const& _lineInfo ) +        :   name( _name ), +            description( _description ), +            lineInfo( _lineInfo ) +        {} + +        std::string name; +        std::string description; +        SourceLineInfo lineInfo; +    }; + +} // end namespace Catch + +// #included from: catch_totals.hpp +#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED + +#include <cstddef> + +namespace Catch { + +    struct Counts { +        Counts() : passed( 0 ), failed( 0 ) {} + +        Counts operator - ( Counts const& other ) const { +            Counts diff; +            diff.passed = passed - other.passed; +            diff.failed = failed - other.failed; +            return diff; +        } +        Counts& operator += ( Counts const& other ) { +            passed += other.passed; +            failed += other.failed; +            return *this; +        } + +        std::size_t total() const { +            return passed + failed; +        } + +        std::size_t passed; +        std::size_t failed; +    }; + +    struct Totals { + +        Totals operator - ( Totals const& other ) const { +            Totals diff; +            diff.assertions = assertions - other.assertions; +            diff.testCases = testCases - other.testCases; +            return diff; +        } + +        Totals delta( Totals const& prevTotals ) const { +            Totals diff = *this - prevTotals; +            if( diff.assertions.failed > 0 ) +                ++diff.testCases.failed; +            else +                ++diff.testCases.passed; +            return diff; +        } + +        Totals& operator += ( Totals const& other ) { +            assertions += other.assertions; +            testCases += other.testCases; +            return *this; +        } + +        Counts assertions; +        Counts testCases; +    }; +}  // #included from: catch_timer.h  #define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED @@ -2969,24 +1801,20 @@ namespace Catch {      public:          Section(    SourceLineInfo const& lineInfo,                      std::string const& name, -                    std::string const& description = "" ) -        :   m_info( name, description, lineInfo ), -            m_sectionIncluded( getCurrentContext().getResultCapture().sectionStarted( m_info, m_assertions ) ) -        { -            m_timer.start(); -        } - -        ~Section() { -            if( m_sectionIncluded ) -                getCurrentContext().getResultCapture().sectionEnded( m_info, m_assertions, m_timer.getElapsedSeconds() ); -        } +                    std::string const& description = "" ); +        ~Section(); +#  ifdef CATCH_CPP11_OR_GREATER +        Section( Section const& )              = default; +        Section( Section && )                  = default; +        Section& operator = ( Section const& ) = default; +        Section& operator = ( Section && )     = default; +#  endif          // This indicates whether the section should be executed or not -        operator bool() { -            return m_sectionIncluded; -        } +        operator bool();      private: +          SectionInfo m_info;          std::string m_name; @@ -3305,7 +2133,7 @@ namespace Detail {          std::string toString() const {              std::ostringstream oss; -            oss << "Approx( " << m_value << " )"; +            oss << "Approx( " << Catch::toString( m_value ) << " )";              return oss.str();          } @@ -3550,10 +2378,81 @@ using namespace Matchers;  // These files are included here so the single_include script doesn't put them  // in the conditionally compiled sections -// #included from: internal/catch_interfaces_runner.h -#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED +// #included from: internal/catch_test_case_info.h +#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED  #include <string> +#include <set> + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + +    struct ITestCase; + +    struct TestCaseInfo { +        TestCaseInfo(   std::string const& _name, +                        std::string const& _className, +                        std::string const& _description, +                        std::set<std::string> const& _tags, +                        bool _isHidden, +                        SourceLineInfo const& _lineInfo ); + +        TestCaseInfo( TestCaseInfo const& other ); + +        std::string name; +        std::string className; +        std::string description; +        std::set<std::string> tags; +        std::string tagsAsString; +        SourceLineInfo lineInfo; +        bool isHidden; +        bool throws; +    }; + +    class TestCase : protected TestCaseInfo { +    public: + +        TestCase( ITestCase* testCase, TestCaseInfo const& info ); +        TestCase( TestCase const& other ); + +        TestCase withName( std::string const& _newName ) const; + +        void invoke() const; + +        TestCaseInfo const& getTestCaseInfo() const; + +        bool isHidden() const; +        bool throws() const; +        bool hasTag( std::string const& tag ) const; +        bool matchesTags( std::string const& tagPattern ) const; +        std::set<std::string> const& getTags() const; + +        void swap( TestCase& other ); +        bool operator == ( TestCase const& other ) const; +        bool operator < ( TestCase const& other ) const; +        TestCase& operator = ( TestCase const& other ); + +    private: +        Ptr<ITestCase> test; +    }; + +    TestCase makeTestCase(  ITestCase* testCase, +                            std::string const& className, +                            std::string const& name, +                            std::string const& description, +                            SourceLineInfo const& lineInfo ); +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +// #included from: internal/catch_interfaces_runner.h +#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED  namespace Catch {      class TestCase; @@ -3613,10 +2512,6 @@ namespace Catch {      namespace Detail{ -        inline bool startsWith( std::string const& str, std::string const& sub ) { -            return str.length() > sub.length() && str.substr( 0, sub.length() ) == sub; -        } -          inline std::string getAnnotation(   Class cls,                                              std::string const& annotationName,                                              std::string const& testCaseName ) { @@ -3645,7 +2540,7 @@ namespace Catch {                  for( u_int m = 0; m < count ; m++ ) {                      SEL selector = method_getName(methods[m]);                      std::string methodName = sel_getName(selector); -                    if( Detail::startsWith( methodName, "Catch_TestCase_" ) ) { +                    if( startsWith( methodName, "Catch_TestCase_" ) ) {                          std::string testCaseName = methodName.substr( 15 );                          std::string name = Detail::getAnnotation( cls, "Name", testCaseName );                          std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); @@ -3762,7 +2657,7 @@ return @ desc; \  #endif -#if defined( CATCH_CONFIG_MAIN ) || defined( CATCH_CONFIG_RUNNER ) +#ifdef CATCH_CONFIG_RUNNER  // #included from: internal/catch_impl.hpp  #define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED @@ -3780,22 +2675,405 @@ return @ desc; \  // #included from: internal/catch_commandline.hpp  #define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED -// #included from: clara.h -#define TWOBLUECUBES_CLARA_H_INCLUDED +// #included from: catch_config.hpp +#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED -// #included from: catch_text.h -#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED +// #included from: catch_test_spec.h +#define TWOBLUECUBES_CATCH_TEST_SPEC_H_INCLUDED + +// #included from: catch_tags.h +#define TWOBLUECUBES_CATCH_TAGS_H_INCLUDED + +#include <string> +#include <set> +#include <map> +#include <vector> + +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { +    class TagParser { +    public: +        virtual ~TagParser(); + +        void parse( std::string const& str ); + +    protected: +        virtual void acceptTag( std::string const& tag ) = 0; +        virtual void acceptChar( char c ) = 0; +        virtual void endParse() {} + +    private: +    }; + +    class TagExtracter : public TagParser { +    public: + +        TagExtracter( std::set<std::string>& tags ); +        virtual ~TagExtracter(); + +        void parse( std::string& description ); + +    private: +        virtual void acceptTag( std::string const& tag ); +        virtual void acceptChar( char c ); + +        TagExtracter& operator=(TagExtracter const&); + +        std::set<std::string>& m_tags; +        std::string m_remainder; +    }; + +    class Tag { +    public: +        Tag(); +        Tag( std::string const& name, bool isNegated ); +        std::string getName() const; +        bool isNegated() const; +        bool operator ! () const; + +    private: +        std::string m_name; +        bool m_isNegated; +    }; + +    class TagSet { +        typedef std::map<std::string, Tag> TagMap; +    public: +        void add( Tag const& tag ); +        bool empty() const; +        bool matches( std::set<std::string> const& tags ) const; + +    private: +        TagMap m_tags; +    }; + +    class TagExpression { +    public: +        bool matches( std::set<std::string> const& tags ) const; + +    private: +        friend class TagExpressionParser; + +        std::vector<TagSet> m_tagSets; +    }; + +    class TagExpressionParser : public TagParser { +    public: +        TagExpressionParser( TagExpression& exp ); +        ~TagExpressionParser(); + +    private: +        virtual void acceptTag( std::string const& tag ); +        virtual void acceptChar( char c ); +        virtual void endParse(); + +        TagExpressionParser& operator=(TagExpressionParser const&); + +        bool m_isNegated; +        TagSet m_currentTagSet; +        TagExpression& m_exp; +    }; + +} // end namespace Catch  #include <string>  #include <vector>  namespace Catch { +    class TestCase; + +    struct IfFilterMatches{ enum DoWhat { +        AutoDetectBehaviour, +        IncludeTests, +        ExcludeTests +    }; }; + +    class TestCaseFilter { +        enum WildcardPosition { +            NoWildcard = 0, +            WildcardAtStart = 1, +            WildcardAtEnd = 2, +            WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd +        }; + +    public: +        TestCaseFilter( std::string const& testSpec, IfFilterMatches::DoWhat matchBehaviour = IfFilterMatches::AutoDetectBehaviour ); + +        IfFilterMatches::DoWhat getFilterType() const; +        bool shouldInclude( TestCase const& testCase ) const; + +    private: +        bool isMatch( TestCase const& testCase ) const; + +        std::string m_stringToMatch; +        IfFilterMatches::DoWhat m_filterType; +        WildcardPosition m_wildcardPosition; +    }; + +    class TestCaseFilters { +    public: +        TestCaseFilters( std::string const& name ); +        std::string getName() const; +        void addFilter( TestCaseFilter const& filter ); +        void addTags( std::string const& tagPattern ); +        bool shouldInclude( TestCase const& testCase ) const; + +    private: +        std::vector<TagExpression> m_tagExpressions; +        std::vector<TestCaseFilter> m_inclusionFilters; +        std::vector<TestCaseFilter> m_exclusionFilters; +        std::string m_name; +    }; + +} + +// #included from: catch_stream.h +#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED + +#include <streambuf> + +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + +    class Stream { +    public: +        Stream(); +        Stream( std::streambuf* _streamBuf, bool _isOwned ); +        void release(); + +        std::streambuf* streamBuf; + +    private: +        bool isOwned; +    }; +} + +#include <memory> +#include <vector> +#include <string> +#include <iostream> + +#ifndef CATCH_CONFIG_CONSOLE_WIDTH +#define CATCH_CONFIG_CONSOLE_WIDTH 80 +#endif + +namespace Catch { + +    struct ConfigData { + +        ConfigData() +        :   listTests( false ), +            listTags( false ), +            listReporters( false ), +            listTestNamesOnly( false ), +            showSuccessfulTests( false ), +            shouldDebugBreak( false ), +            noThrow( false ), +            showHelp( false ), +            showInvisibles( false ), +            abortAfter( -1 ), +            verbosity( Verbosity::Normal ), +            warnings( WarnAbout::Nothing ), +            showDurations( ShowDurations::DefaultForReporter ) +        {} + +        bool listTests; +        bool listTags; +        bool listReporters; +        bool listTestNamesOnly; + +        bool showSuccessfulTests; +        bool shouldDebugBreak; +        bool noThrow; +        bool showHelp; +        bool showInvisibles; + +        int abortAfter; + +        Verbosity::Level verbosity; +        WarnAbout::What warnings; +        ShowDurations::OrNot showDurations; + +        std::string reporterName; +        std::string outputFilename; +        std::string name; +        std::string processName; + +        std::vector<std::string> testsOrTags; +    }; + +    class Config : public SharedImpl<IConfig> { +    private: +        Config( Config const& other ); +        Config& operator = ( Config const& other ); +        virtual void dummy(); +    public: + +        Config() +        :   m_os( std::cout.rdbuf() ) +        {} + +        Config( ConfigData const& data ) +        :   m_data( data ), +            m_os( std::cout.rdbuf() ) +        { +            if( !data.testsOrTags.empty() ) { +                std::string groupName; +                for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) { +                    if( i != 0 ) +                        groupName += " "; +                    groupName += data.testsOrTags[i]; +                } +                TestCaseFilters filters( groupName ); +                for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) { +                    std::string filter = data.testsOrTags[i]; +                    if( startsWith( filter, "[" ) || startsWith( filter, "~[" ) ) +                        filters.addTags( filter ); +                    else +                        filters.addFilter( TestCaseFilter( filter ) ); +                } +                m_filterSets.push_back( filters ); +            } +        } + +        virtual ~Config() { +            m_os.rdbuf( std::cout.rdbuf() ); +            m_stream.release(); +        } + +        void setFilename( std::string const& filename ) { +            m_data.outputFilename = filename; +        } + +        std::string const& getFilename() const { +            return m_data.outputFilename ; +        } + +        bool listTests() const { return m_data.listTests; } +        bool listTestNamesOnly() const { return m_data.listTestNamesOnly; } +        bool listTags() const { return m_data.listTags; } +        bool listReporters() const { return m_data.listReporters; } + +        std::string getProcessName() const { +            return m_data.processName; +        } + +        bool shouldDebugBreak() const { +            return m_data.shouldDebugBreak; +        } + +        void setStreamBuf( std::streambuf* buf ) { +            m_os.rdbuf( buf ? buf : std::cout.rdbuf() ); +        } + +        void useStream( std::string const& streamName ) { +            Stream stream = createStream( streamName ); +            setStreamBuf( stream.streamBuf ); +            m_stream.release(); +            m_stream = stream; +        } + +        std::string getReporterName() const { return m_data.reporterName; } + +        void addTestSpec( std::string const& testSpec ) { +            TestCaseFilters filters( testSpec ); +            filters.addFilter( TestCaseFilter( testSpec ) ); +            m_filterSets.push_back( filters ); +        } + +        int abortAfter() const { +            return m_data.abortAfter; +        } + +        std::vector<TestCaseFilters> const& filters() const { +            return m_filterSets; +        } + +        bool showHelp() const { return m_data.showHelp; } +        bool showInvisibles() const { return m_data.showInvisibles; } + +        // IConfig interface +        virtual bool allowThrows() const        { return !m_data.noThrow; } +        virtual std::ostream& stream() const    { return m_os; } +        virtual std::string name() const        { return m_data.name.empty() ? m_data.processName : m_data.name; } +        virtual bool includeSuccessfulResults() const   { return m_data.showSuccessfulTests; } +        virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; } +        virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; } + +    private: +        ConfigData m_data; + +        Stream m_stream; +        mutable std::ostream m_os; +        std::vector<TestCaseFilters> m_filterSets; +    }; + +} // end namespace Catch + +// #included from: catch_clara.h +#define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED + +// Use Catch's value for console width (store Clara's off to the side, if present) +#ifdef CLARA_CONFIG_CONSOLE_WIDTH +#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH +#undef CLARA_CONFIG_CONSOLE_WIDTH +#endif +#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH + +// Declare Clara inside the Catch namespace +#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch { +// #included from: ../external/clara.h + +// Only use header guard if we are not using an outer namespace +#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE) + +#ifndef STITCH_CLARA_OPEN_NAMESPACE +#define TWOBLUECUBES_CLARA_H_INCLUDED +#define STITCH_CLARA_OPEN_NAMESPACE +#define STITCH_CLARA_CLOSE_NAMESPACE +#else +#define STITCH_CLARA_CLOSE_NAMESPACE } +#endif + +#define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE + +// ----------- #included from tbc_text_format.h ----------- + +// Only use header guard if we are not using an outer namespace +#if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE) +#ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +#define TBC_TEXT_FORMAT_H_INCLUDED +#endif + +#include <string> +#include <vector> +#include <sstream> + +// Use optional outer namespace +#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE { +#endif + +namespace Tbc { + +#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH +    const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; +#else +    const unsigned int consoleWidth = 80; +#endif +      struct TextAttributes {          TextAttributes()          :   initialIndent( std::string::npos ),              indent( 0 ), -            width( CATCH_CONFIG_CONSOLE_WIDTH-1 ), +            width( consoleWidth-1 ),              tabChar( '\t' )          {} @@ -3812,8 +3090,66 @@ namespace Catch {      class Text {      public: -        Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ); -        void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ); +        Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) +        : attr( _attr ) +        { +            std::string wrappableChars = " [({.,/|\\-"; +            std::size_t indent = _attr.initialIndent != std::string::npos +                ? _attr.initialIndent +                : _attr.indent; +            std::string remainder = _str; + +            while( !remainder.empty() ) { +                if( lines.size() >= 1000 ) { +                    lines.push_back( "... message truncated due to excessive size" ); +                    return; +                } +                std::size_t tabPos = std::string::npos; +                std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); +                std::size_t pos = remainder.find_first_of( '\n' ); +                if( pos <= width ) { +                    width = pos; +                } +                pos = remainder.find_last_of( _attr.tabChar, width ); +                if( pos != std::string::npos ) { +                    tabPos = pos; +                    if( remainder[width] == '\n' ) +                        width--; +                    remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); +                } + +                if( width == remainder.size() ) { +                    spliceLine( indent, remainder, width ); +                } +                else if( remainder[width] == '\n' ) { +                    spliceLine( indent, remainder, width ); +                    if( width <= 1 || remainder.size() != 1 ) +                        remainder = remainder.substr( 1 ); +                    indent = _attr.indent; +                } +                else { +                    pos = remainder.find_last_of( wrappableChars, width ); +                    if( pos != std::string::npos && pos > 0 ) { +                        spliceLine( indent, remainder, pos ); +                        if( remainder[0] == ' ' ) +                            remainder = remainder.substr( 1 ); +                    } +                    else { +                        spliceLine( indent, remainder, width-1 ); +                        lines.back() += "-"; +                    } +                    if( lines.size() == 1 ) +                        indent = _attr.indent; +                    if( tabPos != std::string::npos ) +                        indent += tabPos; +                } +            } +        } + +        void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { +            lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); +            _remainder = _remainder.substr( _pos ); +        }          typedef std::vector<std::string>::const_iterator const_iterator; @@ -3822,9 +3158,21 @@ namespace Catch {          std::string const& last() const { return lines.back(); }          std::size_t size() const { return lines.size(); }          std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } -        std::string toString() const; +        std::string toString() const { +            std::ostringstream oss; +            oss << *this; +            return oss.str(); +        } -        friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ); +        inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { +            for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); +                it != itEnd; ++it ) { +                if( it != _text.begin() ) +                    _stream << "\n"; +                _stream << *it; +            } +            return _stream; +        }      private:          std::string str; @@ -3832,10 +3180,53 @@ namespace Catch {          std::vector<std::string> lines;      }; -} // end namespace Catch +} // end namespace Tbc + +#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +} // end outer namespace +#endif + +#endif // TBC_TEXT_FORMAT_H_INCLUDED + +// ----------- end of #include from tbc_text_format.h ----------- +// ........... back in /Users/philnash/Dev/OSS/Clara/srcs/clara.h + +#undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE + +#include <map> +#include <algorithm> +#include <stdexcept> +#include <memory> + +// Use optional outer namespace +#ifdef STITCH_CLARA_OPEN_NAMESPACE +STITCH_CLARA_OPEN_NAMESPACE +#endif  namespace Clara { + +    struct UnpositionalTag {}; + +    extern UnpositionalTag _; + +#ifdef CLARA_CONFIG_MAIN +    UnpositionalTag _; +#endif +      namespace Detail { + +#ifdef CLARA_CONSOLE_WIDTH +    const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH; +#else +    const unsigned int consoleWidth = 80; +#endif + +        using namespace Tbc; + +        inline bool startsWith( std::string const& str, std::string const& prefix ) { +            return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix; +        } +          template<typename T> struct RemoveConstRef{ typedef T type; };          template<typename T> struct RemoveConstRef<T&>{ typedef T type; };          template<typename T> struct RemoveConstRef<T const&>{ typedef T type; }; @@ -3876,6 +3267,10 @@ namespace Clara {          template<typename ConfigT>          struct IArgFunction {              virtual ~IArgFunction() {} +#  ifdef CATCH_CPP11_OR_GREATER +            IArgFunction()                      = default; +            IArgFunction( IArgFunction const& ) = default; +#  endif              virtual void set( ConfigT& config, std::string const& value ) const = 0;              virtual void setFlag( ConfigT& config ) const = 0;              virtual bool takesArg() const = 0; @@ -3885,10 +3280,11 @@ namespace Clara {          template<typename ConfigT>          class BoundArgFunction {          public: +            BoundArgFunction() : functionObj( NULL ) {}              BoundArgFunction( IArgFunction<ConfigT>* _functionObj ) : functionObj( _functionObj ) {} -            BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj->clone() ) {} +            BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : NULL ) {}              BoundArgFunction& operator = ( BoundArgFunction const& other ) { -                IArgFunction<ConfigT>* newFunctionObj = other.functionObj->clone(); +                IArgFunction<ConfigT>* newFunctionObj = other.functionObj ? other.functionObj->clone() : NULL;                  delete functionObj;                  functionObj = newFunctionObj;                  return *this; @@ -3902,6 +3298,10 @@ namespace Clara {                  functionObj->setFlag( config );              }              bool takesArg() const { return functionObj->takesArg(); } + +            bool isSet() const { +                return functionObj != NULL; +            }          private:              IArgFunction<ConfigT>* functionObj;          }; @@ -3996,26 +3396,6 @@ namespace Clara {              void (*function)( C&, T );          }; -        template<typename C, typename M> -        BoundArgFunction<C> makeBoundField( M C::* _member ) { -            return BoundArgFunction<C>( new BoundDataMember<C,M>( _member ) ); -        } -        template<typename C, typename M> -        BoundArgFunction<C> makeBoundField( void (C::*_member)( M ) ) { -            return BoundArgFunction<C>( new BoundUnaryMethod<C,M>( _member ) ); -        } -        template<typename C> -        BoundArgFunction<C> makeBoundField( void (C::*_member)() ) { -            return BoundArgFunction<C>( new BoundNullaryMethod<C>( _member ) ); -        } -        template<typename C> -        BoundArgFunction<C> makeBoundField( void (*_function)( C& ) ) { -            return BoundArgFunction<C>( new BoundUnaryFunction<C>( _function ) ); -        } -        template<typename C, typename T> -        BoundArgFunction<C> makeBoundField( void (*_function)( C&, T ) ) { -            return BoundArgFunction<C>( new BoundBinaryFunction<C, T>( _function ) ); -        }      } // namespace Detail      struct Parser { @@ -4029,7 +3409,8 @@ namespace Clara {          };          void parseIntoTokens( int argc, char const * const * argv, std::vector<Parser::Token>& tokens ) const { -            for( int i = 1; i < argc; ++i ) +            const std::string doubleDash = "--"; +            for( int i = 1; i < argc && argv[i] != doubleDash; ++i )                  parseIntoTokens( argv[i] , tokens);          }          void parseIntoTokens( std::string arg, std::vector<Parser::Token>& tokens ) const { @@ -4062,32 +3443,52 @@ namespace Clara {      };      template<typename ConfigT> +    struct CommonArgProperties { +        CommonArgProperties() {} +        CommonArgProperties( Detail::BoundArgFunction<ConfigT> const& _boundField ) : boundField( _boundField ) {} + +        Detail::BoundArgFunction<ConfigT> boundField; +        std::string description; +        std::string detail; +        std::string placeholder; // Only value if boundField takes an arg + +        bool takesArg() const { +            return !placeholder.empty(); +        } +        void validate() const { +            if( !boundField.isSet() ) +                throw std::logic_error( "option not bound" ); +        } +    }; +    struct OptionArgProperties { +        std::vector<std::string> shortNames; +        std::string longName; + +        bool hasShortName( std::string const& shortName ) const { +            return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end(); +        } +        bool hasLongName( std::string const& _longName ) const { +            return _longName == longName; +        } +    }; +    struct PositionalArgProperties { +        PositionalArgProperties() : position( -1 ) {} +        int position; // -1 means non-positional (floating) + +        bool isFixedPositional() const { +            return position != -1; +        } +    }; + +    template<typename ConfigT>      class CommandLine { -        struct Arg { -            Arg( Detail::BoundArgFunction<ConfigT> const& _boundField ) : boundField( _boundField ), position( -1 ) {} +        struct Arg : CommonArgProperties<ConfigT>, OptionArgProperties, PositionalArgProperties { +            Arg() {} +            Arg( Detail::BoundArgFunction<ConfigT> const& _boundField ) : CommonArgProperties<ConfigT>( _boundField ) {} + +            using CommonArgProperties<ConfigT>::placeholder; // !TBD -            bool hasShortName( std::string const& shortName ) const { -                for(    std::vector<std::string>::const_iterator -                            it = shortNames.begin(), itEnd = shortNames.end(); -                        it != itEnd; -                        ++it ) -                    if( *it == shortName ) -                        return true; -                return false; -            } -            bool hasLongName( std::string const& _longName ) const { -                return _longName == longName; -            } -            bool takesArg() const { -                return !hint.empty(); -            } -            bool isFixedPositional() const { -                return position != -1; -            } -            bool isAnyPositional() const { -                return position == -1 && shortNames.empty() && longName.empty(); -            }              std::string dbgName() const {                  if( !longName.empty() )                      return "--" + longName; @@ -4095,10 +3496,6 @@ namespace Clara {                      return "-" + shortNames[0];                  return "positional args";              } -            void validate() const { -                if( boundField.takesArg() && !takesArg() ) -                    throw std::logic_error( dbgName() + " must specify an arg name" ); -            }              std::string commands() const {                  std::ostringstream oss;                  bool first = true; @@ -4115,113 +3512,182 @@ namespace Clara {                          oss << ", ";                      oss << "--" << longName;                  } -                if( !hint.empty() ) -                    oss << " <" << hint << ">"; +                if( !placeholder.empty() ) +                    oss << " <" << placeholder << ">";                  return oss.str();              } - -            Detail::BoundArgFunction<ConfigT> boundField; -            std::vector<std::string> shortNames; -            std::string longName; -            std::string description; -            std::string hint; -            int position;          }; -        class ArgBinder { +        // NOTE: std::auto_ptr is deprecated in c++11/c++0x +#if defined(__cplusplus) && __cplusplus > 199711L +        typedef std::unique_ptr<Arg> ArgAutoPtr; +#else +        typedef std::auto_ptr<Arg> ArgAutoPtr; +#endif + +        friend void addOptName( Arg& arg, std::string const& optName ) +        { +            if( optName.empty() ) +                return; +            if( Detail::startsWith( optName, "--" ) ) { +                if( !arg.longName.empty() ) +                    throw std::logic_error( "Only one long opt may be specified. '" +                        + arg.longName +                        + "' already specified, now attempting to add '" +                        + optName + "'" ); +                arg.longName = optName.substr( 2 ); +            } +            else if( Detail::startsWith( optName, "-" ) ) +                arg.shortNames.push_back( optName.substr( 1 ) ); +            else +                throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" ); +        } +        friend void setPositionalArg( Arg& arg, int position ) +        { +            arg.position = position; +        } + +        class ArgBuilder {          public: -            template<typename F> -            ArgBinder( CommandLine* cl, F f ) -            :   m_cl( cl ), -                m_arg( Detail::makeBoundField( f ) ) -            {} -            ArgBinder( ArgBinder& other ) -            :   m_cl( other.m_cl ), -                m_arg( other.m_arg ) -            { -                other.m_cl = NULL; -            } -            ~ArgBinder() { -                if( m_cl ) { -                    m_arg.validate(); -                    if( m_arg.isFixedPositional() ) { -                        m_cl->m_positionalArgs.insert( std::make_pair( m_arg.position, m_arg ) ); -                        if( m_arg.position > m_cl->m_highestSpecifiedArgPosition ) -                            m_cl->m_highestSpecifiedArgPosition = m_arg.position; -                    } -                    else if( m_arg.isAnyPositional() ) { -                        if( m_cl->m_arg.get() ) -                            throw std::logic_error( "Only one unpositional argument can be added" ); -                        m_cl->m_arg = std::auto_ptr<Arg>( new Arg( m_arg ) ); -                    } -                    else -                        m_cl->m_options.push_back( m_arg ); -                } +            ArgBuilder( Arg* arg ) : m_arg( arg ) {} + +            // Bind a non-boolean data member (requires placeholder string) +            template<typename C, typename M> +            void bind( M C::* field, std::string const& placeholder ) { +                m_arg->boundField = new Detail::BoundDataMember<C,M>( field ); +                m_arg->placeholder = placeholder;              } -            ArgBinder& shortOpt( std::string const& name ) { -                m_arg.shortNames.push_back( name ); -                return *this; +            // Bind a boolean data member (no placeholder required) +            template<typename C> +            void bind( bool C::* field ) { +                m_arg->boundField = new Detail::BoundDataMember<C,bool>( field );              } -            ArgBinder& longOpt( std::string const& name ) { -                m_arg.longName = name; -                return *this; + +            // Bind a method taking a single, non-boolean argument (requires a placeholder string) +            template<typename C, typename M> +            void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) { +                m_arg->boundField = new Detail::BoundUnaryMethod<C,M>( unaryMethod ); +                m_arg->placeholder = placeholder;              } -            ArgBinder& describe( std::string const& description ) { -                m_arg.description = description; + +            // Bind a method taking a single, boolean argument (no placeholder string required) +            template<typename C> +            void bind( void (C::* unaryMethod)( bool ) ) { +                m_arg->boundField = new Detail::BoundUnaryMethod<C,bool>( unaryMethod ); +            } + +            // Bind a method that takes no arguments (will be called if opt is present) +            template<typename C> +            void bind( void (C::* nullaryMethod)() ) { +                m_arg->boundField = new Detail::BoundNullaryMethod<C>( nullaryMethod ); +            } + +            // Bind a free function taking a single argument - the object to operate on (no placeholder string required) +            template<typename C> +            void bind( void (* unaryFunction)( C& ) ) { +                m_arg->boundField = new Detail::BoundUnaryFunction<C>( unaryFunction ); +            } + +            // Bind a free function taking a single argument - the object to operate on (requires a placeholder string) +            template<typename C, typename T> +            void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) { +                m_arg->boundField = new Detail::BoundBinaryFunction<C, T>( binaryFunction ); +                m_arg->placeholder = placeholder; +            } + +            ArgBuilder& describe( std::string const& description ) { +                m_arg->description = description;                  return *this;              } -            ArgBinder& hint( std::string const& hint ) { -                m_arg.hint = hint; +            ArgBuilder& detail( std::string const& detail ) { +                m_arg->detail = detail;                  return *this;              } -            ArgBinder& position( int position ) { -                m_arg.position = position; + +        protected: +            Arg* m_arg; +        }; + +        class OptBuilder : public ArgBuilder { +        public: +            OptBuilder( Arg* arg ) : ArgBuilder( arg ) {} +            OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {} + +            OptBuilder& operator[]( std::string const& optName ) { +                addOptName( *ArgBuilder::m_arg, optName );                  return *this;              } -        private: -            CommandLine* m_cl; -            Arg m_arg;          };      public:          CommandLine()          :   m_boundProcessName( new Detail::NullBinder<ConfigT>() ), -            m_highestSpecifiedArgPosition( 0 ) +            m_highestSpecifiedArgPosition( 0 ), +            m_throwOnUnrecognisedTokens( false )          {}          CommandLine( CommandLine const& other )          :   m_boundProcessName( other.m_boundProcessName ),              m_options ( other.m_options ),              m_positionalArgs( other.m_positionalArgs ), -            m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ) +            m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ), +            m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens )          { -            if( other.m_arg.get() ) -                m_arg = std::auto_ptr<Arg>( new Arg( *other.m_arg ) ); +            if( other.m_floatingArg.get() ) +                m_floatingArg = ArgAutoPtr( new Arg( *other.m_floatingArg ) );          } -        template<typename F> -        ArgBinder bind( F f ) { -            ArgBinder binder( this, f ); -            return binder; +        CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) { +            m_throwOnUnrecognisedTokens = shouldThrow; +            return *this;          } -        template<typename F> -        void bindProcessName( F f ) { -            m_boundProcessName = Detail::makeBoundField( f ); + +        OptBuilder operator[]( std::string const& optName ) { +            m_options.push_back( Arg() ); +            addOptName( m_options.back(), optName ); +            OptBuilder builder( &m_options.back() ); +            return builder; +        } + +        ArgBuilder operator[]( int position ) { +            m_positionalArgs.insert( std::make_pair( position, Arg() ) ); +            if( position > m_highestSpecifiedArgPosition ) +                m_highestSpecifiedArgPosition = position; +            setPositionalArg( m_positionalArgs[position], position ); +            ArgBuilder builder( &m_positionalArgs[position] ); +            return builder;          } -        void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = CATCH_CONFIG_CONSOLE_WIDTH ) const { +        // Invoke this with the _ instance +        ArgBuilder operator[]( UnpositionalTag ) { +            if( m_floatingArg.get() ) +                throw std::logic_error( "Only one unpositional argument can be added" ); +            m_floatingArg = ArgAutoPtr( new Arg() ); +            ArgBuilder builder( m_floatingArg.get() ); +            return builder; +        } + +        template<typename C, typename M> +        void bindProcessName( M C::* field ) { +            m_boundProcessName = new Detail::BoundDataMember<C,M>( field ); +        } +        template<typename C, typename M> +        void bindProcessName( void (C::*_unaryMethod)( M ) ) { +            m_boundProcessName = new Detail::BoundUnaryMethod<C,M>( _unaryMethod ); +        } + +        void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const {              typename std::vector<Arg>::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it;              std::size_t maxWidth = 0;              for( it = itBegin; it != itEnd; ++it )                  maxWidth = (std::max)( maxWidth, it->commands().size() );              for( it = itBegin; it != itEnd; ++it ) { -                Catch::Text usage( it->commands(), Catch::TextAttributes() +                Detail::Text usage( it->commands(), Detail::TextAttributes()                                                          .setWidth( maxWidth+indent )                                                          .setIndent( indent ) ); -                // !TBD handle longer usage strings -                Catch::Text desc( it->description, Catch::TextAttributes() -                                                        .setWidth( width - maxWidth -3 ) ); +                Detail::Text desc( it->description, Detail::TextAttributes() +                                                        .setWidth( width - maxWidth - 3 ) );                  for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) {                      std::string usageCol = i < usage.size() ? usage[i] : ""; @@ -4246,17 +3712,17 @@ namespace Clara {                      os << " ";                  typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( i );                  if( it != m_positionalArgs.end() ) -                    os << "<" << it->second.hint << ">"; -                else if( m_arg.get() ) -                    os << "<" << m_arg->hint << ">"; +                    os << "<" << it->second.placeholder << ">"; +                else if( m_floatingArg.get() ) +                    os << "<" << m_floatingArg->placeholder << ">";                  else                      throw std::logic_error( "non consecutive positional arguments with no floating args" );              }              // !TBD No indication of mandatory args -            if( m_arg.get() ) { +            if( m_floatingArg.get() ) {                  if( m_highestSpecifiedArgPosition > 1 )                      os << " "; -                os << "[<" << m_arg->hint << "> ...]"; +                os << "[<" << m_floatingArg->placeholder << "> ...]";              }          }          std::string argSynopsis() const { @@ -4266,6 +3732,7 @@ namespace Clara {          }          void usage( std::ostream& os, std::string const& procName ) const { +            validate();              os << "usage:\n  " << procName << " ";              argSynopsis( os );              if( !m_options.empty() ) { @@ -4280,6 +3747,12 @@ namespace Clara {              return oss.str();          } +        ConfigT parse( int argc, char const * const * argv ) const { +            ConfigT config; +            parseInto( argc, argv, config ); +            return config; +        } +          std::vector<Parser::Token> parseInto( int argc, char const * const * argv, ConfigT& config ) const {              std::string processName = argv[0];              std::size_t lastSlash = processName.find_last_of( "/\\" ); @@ -4293,9 +3766,7 @@ namespace Clara {          }          std::vector<Parser::Token> populate( std::vector<Parser::Token> const& tokens, ConfigT& config ) const { -            if( m_options.empty() && m_positionalArgs.empty() ) -                throw std::logic_error( "No options or arguments specified" ); - +            validate();              std::vector<Parser::Token> unusedTokens = populateOptions( tokens, config );              unusedTokens = populateFixedArgs( unusedTokens, config );              unusedTokens = populateFloatingArgs( unusedTokens, config ); @@ -4304,6 +3775,7 @@ namespace Clara {          std::vector<Parser::Token> populateOptions( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {              std::vector<Parser::Token> unusedTokens; +            std::vector<std::string> errors;              for( std::size_t i = 0; i < tokens.size(); ++i ) {                  Parser::Token const& token = tokens[i];                  typename std::vector<Arg>::const_iterator it = m_options.begin(), itEnd = m_options.end(); @@ -4315,8 +3787,9 @@ namespace Clara {                              ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) {                              if( arg.takesArg() ) {                                  if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional ) -                                    throw std::domain_error( "Expected argument to option " + token.data ); -                                arg.boundField.set( config, tokens[++i].data ); +                                    errors.push_back( "Expected argument to option: " + token.data ); +                                else +                                    arg.boundField.set( config, tokens[++i].data );                              }                              else {                                  arg.boundField.setFlag( config ); @@ -4325,11 +3798,26 @@ namespace Clara {                          }                      }                      catch( std::exception& ex ) { -                        throw std::runtime_error( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" ); +                        errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" );                      }                  } -                if( it == itEnd ) -                    unusedTokens.push_back( token ); +                if( it == itEnd ) { +                    if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens ) +                        unusedTokens.push_back( token ); +                    else if( m_throwOnUnrecognisedTokens ) +                        errors.push_back( "unrecognised option: " + token.data ); +                } +            } +            if( !errors.empty() ) { +                std::ostringstream oss; +                for( std::vector<std::string>::const_iterator it = errors.begin(), itEnd = errors.end(); +                        it != itEnd; +                        ++it ) { +                    if( it != errors.begin() ) +                        oss << "\n"; +                    oss << *it; +                } +                throw std::runtime_error( oss.str() );              }              return unusedTokens;          } @@ -4349,29 +3837,56 @@ namespace Clara {              return unusedTokens;          }          std::vector<Parser::Token> populateFloatingArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const { -            if( !m_arg.get() ) +            if( !m_floatingArg.get() )                  return tokens;              std::vector<Parser::Token> unusedTokens;              for( std::size_t i = 0; i < tokens.size(); ++i ) {                  Parser::Token const& token = tokens[i];                  if( token.type == Parser::Token::Positional ) -                    m_arg->boundField.set( config, token.data ); +                    m_floatingArg->boundField.set( config, token.data );                  else                      unusedTokens.push_back( token );              }              return unusedTokens;          } +        void validate() const +        { +            if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() ) +                throw std::logic_error( "No options or arguments specified" ); + +            for( typename std::vector<Arg>::const_iterator  it = m_options.begin(), +                                                            itEnd = m_options.end(); +                    it != itEnd; ++it ) +                it->validate(); +        } +      private:          Detail::BoundArgFunction<ConfigT> m_boundProcessName;          std::vector<Arg> m_options;          std::map<int, Arg> m_positionalArgs; -        std::auto_ptr<Arg> m_arg; +        ArgAutoPtr m_floatingArg;          int m_highestSpecifiedArgPosition; +        bool m_throwOnUnrecognisedTokens;      };  } // end namespace Clara +STITCH_CLARA_CLOSE_NAMESPACE +#undef STITCH_CLARA_OPEN_NAMESPACE +#undef STITCH_CLARA_CLOSE_NAMESPACE + +#endif // TWOBLUECUBES_CLARA_H_INCLUDED +#undef STITCH_CLARA_OPEN_NAMESPACE + +// Restore Clara's value for console width, if present +#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#endif + +#include <fstream> +  namespace Catch {      inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; } @@ -4398,99 +3913,106 @@ namespace Catch {              ? ShowDurations::Always              : ShowDurations::Never;      } +    inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) { +        std::ifstream f( _filename.c_str() ); +        if( !f.is_open() ) +            throw std::domain_error( "Unable to load input file: " + _filename ); + +        std::string line; +        while( std::getline( f, line ) ) { +            line = trim(line); +            if( !line.empty() && !startsWith( line, "#" ) ) +                addTestOrTags( config, line ); +        } +    }      inline Clara::CommandLine<ConfigData> makeCommandLineParser() { -        Clara::CommandLine<ConfigData> cli; +        using namespace Clara; +        CommandLine<ConfigData> cli;          cli.bindProcessName( &ConfigData::processName ); -        cli.bind( &ConfigData::showHelp ) +        cli["-?"]["-h"]["--help"]              .describe( "display usage information" ) -            .shortOpt( "?") -            .shortOpt( "h") -            .longOpt( "help" ); - -        cli.bind( &ConfigData::listTests ) -            .describe( "list all (or matching) test cases" ) -            .shortOpt( "l") -            .longOpt( "list-tests" ); +            .bind( &ConfigData::showHelp ); -        cli.bind( &ConfigData::listTags ) -            .describe( "list all (or matching) tags" ) -            .shortOpt( "t") -            .longOpt( "list-tags" ); +        cli["-l"]["--list-tests"] +            .describe( "list all/matching test cases" ) +            .bind( &ConfigData::listTests ); -        cli.bind( &ConfigData::listReporters ) -            .describe( "list all reporters" ) -            .longOpt( "list-reporters" ); +        cli["-t"]["--list-tags"] +            .describe( "list all/matching tags" ) +            .bind( &ConfigData::listTags ); -        cli.bind( &ConfigData::showSuccessfulTests ) +        cli["-s"]["--success"]              .describe( "include successful tests in output" ) -            .shortOpt( "s") -            .longOpt( "success" ); +            .bind( &ConfigData::showSuccessfulTests ); -        cli.bind( &ConfigData::shouldDebugBreak ) +        cli["-b"]["--break"]              .describe( "break into debugger on failure" ) -            .shortOpt( "b") -            .longOpt( "break" ); +            .bind( &ConfigData::shouldDebugBreak ); -        cli.bind( &ConfigData::noThrow ) +        cli["-e"]["--nothrow"]              .describe( "skip exception tests" ) -            .shortOpt( "e") -            .longOpt( "nothrow" ); +            .bind( &ConfigData::noThrow ); -        cli.bind( &ConfigData::outputFilename ) +        cli["-i"]["--invisibles"] +            .describe( "show invisibles (tabs, newlines)" ) +            .bind( &ConfigData::showInvisibles ); + +        cli["-o"]["--out"]              .describe( "output filename" ) -            .shortOpt( "o") -            .longOpt( "out" ) -            .hint( "filename" ); - -        cli.bind( &ConfigData::reporterName ) -            .describe( "reporter to use - defaults to console" ) -            .shortOpt( "r") -            .longOpt( "reporter" ) -//            .hint( "name[:filename]" ); -            .hint( "name" ); - -        cli.bind( &ConfigData::name ) +            .bind( &ConfigData::outputFilename, "filename" ); + +        cli["-r"]["--reporter"] +//            .placeholder( "name[:filename]" ) +            .describe( "reporter to use (defaults to console)" ) +            .bind( &ConfigData::reporterName, "name" ); + +        cli["-n"]["--name"]              .describe( "suite name" ) -            .shortOpt( "n") -            .longOpt( "name" ) -            .hint( "name" ); +            .bind( &ConfigData::name, "name" ); -        cli.bind( &abortAfterFirst ) +        cli["-a"]["--abort"]              .describe( "abort at first failure" ) -            .shortOpt( "a") -            .longOpt( "abort" ); +            .bind( &abortAfterFirst ); -        cli.bind( &abortAfterX ) +        cli["-x"]["--abortx"]              .describe( "abort after x failures" ) -            .shortOpt( "x") -            .longOpt( "abortx" ) -            .hint( "number of failures" ); +            .bind( &abortAfterX, "no. failures" ); -        cli.bind( &addWarning ) +        cli["-w"]["--warn"]              .describe( "enable warnings" ) -            .shortOpt( "w") -            .longOpt( "warn" ) -            .hint( "warning name" ); +            .bind( &addWarning, "warning name" ); -//        cli.bind( &setVerbosity ) +// - needs updating if reinstated +//        cli.into( &setVerbosity )  //            .describe( "level of verbosity (0=no output)" )  //            .shortOpt( "v")  //            .longOpt( "verbosity" ) -//            .hint( "level" ); +//            .placeholder( "level" ); -        cli.bind( &addTestOrTags ) +        cli[_]              .describe( "which test or tests to use" ) -            .hint( "test name, pattern or tags" ); +            .bind( &addTestOrTags, "test name, pattern or tags" ); -        cli.bind( &setShowDurations ) +        cli["-d"]["--durations"]              .describe( "show test durations" ) -            .shortOpt( "d") -            .longOpt( "durations" ) -            .hint( "yes/no" ); +            .bind( &setShowDurations, "yes/no" ); + +        cli["-f"]["--input-file"] +            .describe( "load test names to run from a file" ) +            .bind( &loadTestNamesFromFile, "filename" ); + +        // Less common commands which don't have a short form +        cli["--list-test-names-only"] +            .describe( "list all/matching test cases names only" ) +            .bind( &ConfigData::listTestNamesOnly ); + +        cli["--list-reporters"] +            .describe( "list all reporters" ) +            .bind( &ConfigData::listReporters );          return cli;      } @@ -4500,6 +4022,166 @@ namespace Catch {  // #included from: internal/catch_list.hpp  #define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED +// #included from: catch_text.h +#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED + +#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH + +#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch +// #included from: ../external/tbc_text_format.h +// Only use header guard if we are not using an outer namespace +#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED +#  ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +#   define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +#  endif +# else +#  define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED +# endif +#endif +#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +#include <string> +#include <vector> +#include <sstream> + +// Use optional outer namespace +#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE { +#endif + +namespace Tbc { + +#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH +    const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; +#else +    const unsigned int consoleWidth = 80; +#endif + +    struct TextAttributes { +        TextAttributes() +        :   initialIndent( std::string::npos ), +            indent( 0 ), +            width( consoleWidth-1 ), +            tabChar( '\t' ) +        {} + +        TextAttributes& setInitialIndent( std::size_t _value )  { initialIndent = _value; return *this; } +        TextAttributes& setIndent( std::size_t _value )         { indent = _value; return *this; } +        TextAttributes& setWidth( std::size_t _value )          { width = _value; return *this; } +        TextAttributes& setTabChar( char _value )               { tabChar = _value; return *this; } + +        std::size_t initialIndent;  // indent of first line, or npos +        std::size_t indent;         // indent of subsequent lines, or all if initialIndent is npos +        std::size_t width;          // maximum width of text, including indent. Longer text will wrap +        char tabChar;               // If this char is seen the indent is changed to current pos +    }; + +    class Text { +    public: +        Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) +        : attr( _attr ) +        { +            std::string wrappableChars = " [({.,/|\\-"; +            std::size_t indent = _attr.initialIndent != std::string::npos +                ? _attr.initialIndent +                : _attr.indent; +            std::string remainder = _str; + +            while( !remainder.empty() ) { +                if( lines.size() >= 1000 ) { +                    lines.push_back( "... message truncated due to excessive size" ); +                    return; +                } +                std::size_t tabPos = std::string::npos; +                std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); +                std::size_t pos = remainder.find_first_of( '\n' ); +                if( pos <= width ) { +                    width = pos; +                } +                pos = remainder.find_last_of( _attr.tabChar, width ); +                if( pos != std::string::npos ) { +                    tabPos = pos; +                    if( remainder[width] == '\n' ) +                        width--; +                    remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); +                } + +                if( width == remainder.size() ) { +                    spliceLine( indent, remainder, width ); +                } +                else if( remainder[width] == '\n' ) { +                    spliceLine( indent, remainder, width ); +                    if( width <= 1 || remainder.size() != 1 ) +                        remainder = remainder.substr( 1 ); +                    indent = _attr.indent; +                } +                else { +                    pos = remainder.find_last_of( wrappableChars, width ); +                    if( pos != std::string::npos && pos > 0 ) { +                        spliceLine( indent, remainder, pos ); +                        if( remainder[0] == ' ' ) +                            remainder = remainder.substr( 1 ); +                    } +                    else { +                        spliceLine( indent, remainder, width-1 ); +                        lines.back() += "-"; +                    } +                    if( lines.size() == 1 ) +                        indent = _attr.indent; +                    if( tabPos != std::string::npos ) +                        indent += tabPos; +                } +            } +        } + +        void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { +            lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); +            _remainder = _remainder.substr( _pos ); +        } + +        typedef std::vector<std::string>::const_iterator const_iterator; + +        const_iterator begin() const { return lines.begin(); } +        const_iterator end() const { return lines.end(); } +        std::string const& last() const { return lines.back(); } +        std::size_t size() const { return lines.size(); } +        std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } +        std::string toString() const { +            std::ostringstream oss; +            oss << *this; +            return oss.str(); +        } + +        inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { +            for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); +                it != itEnd; ++it ) { +                if( it != _text.begin() ) +                    _stream << "\n"; +                _stream << *it; +            } +            return _stream; +        } + +    private: +        std::string str; +        TextAttributes attr; +        std::vector<std::string> lines; +    }; + +} // end namespace Tbc + +#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +} // end outer namespace +#endif + +#endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +#undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE + +namespace Catch { +    using Tbc::Text; +    using Tbc::TextAttributes; +} +  // #included from: catch_console_colour.hpp  #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED @@ -4551,23 +4233,325 @@ namespace Catch {          static void use( Code _colourCode );      private: -        static Detail::IColourImpl* impl; +        static Detail::IColourImpl* impl();      };  } // end namespace Catch +// #included from: catch_interfaces_reporter.h +#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED + +// #included from: catch_option.hpp +#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED + +namespace Catch { + +    // An optional type +    template<typename T> +    class Option { +    public: +        Option() : nullableValue( NULL ) {} +        Option( T const& _value ) +        : nullableValue( new( storage ) T( _value ) ) +        {} +        Option( Option const& _other ) +        : nullableValue( _other ? new( storage ) T( *_other ) : NULL ) +        {} + +        ~Option() { +            reset(); +        } + +        Option& operator= ( Option const& _other ) { +            if( &_other != this ) { +                reset(); +                if( _other ) +                    nullableValue = new( storage ) T( *_other ); +            } +            return *this; +        } +        Option& operator = ( T const& _value ) { +            reset(); +            nullableValue = new( storage ) T( _value ); +            return *this; +        } + +        void reset() { +            if( nullableValue ) +                nullableValue->~T(); +            nullableValue = NULL; +        } + +        T& operator*() { return *nullableValue; } +        T const& operator*() const { return *nullableValue; } +        T* operator->() { return nullableValue; } +        const T* operator->() const { return nullableValue; } + +        T valueOr( T const& defaultValue ) const { +            return nullableValue ? *nullableValue : defaultValue; +        } + +        bool some() const { return nullableValue != NULL; } +        bool none() const { return nullableValue == NULL; } + +        bool operator !() const { return nullableValue == NULL; } +        operator SafeBool::type() const { +            return SafeBool::makeSafe( some() ); +        } + +    private: +        T* nullableValue; +        char storage[sizeof(T)]; +    }; + +} // end namespace Catch + +#include <string> +#include <ostream> +#include <map> +#include <assert.h> + +namespace Catch +{ +    struct ReporterConfig { +        explicit ReporterConfig( Ptr<IConfig> const& _fullConfig ) +        :   m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} + +        ReporterConfig( Ptr<IConfig> const& _fullConfig, std::ostream& _stream ) +        :   m_stream( &_stream ), m_fullConfig( _fullConfig ) {} + +        std::ostream& stream() const    { return *m_stream; } +        Ptr<IConfig> fullConfig() const { return m_fullConfig; } + +    private: +        std::ostream* m_stream; +        Ptr<IConfig> m_fullConfig; +    }; + +    struct ReporterPreferences { +        ReporterPreferences() +        : shouldRedirectStdOut( false ) +        {} + +        bool shouldRedirectStdOut; +    }; + +    template<typename T> +    struct LazyStat : Option<T> { +        LazyStat() : used( false ) {} +        LazyStat& operator=( T const& _value ) { +            Option<T>::operator=( _value ); +            used = false; +            return *this; +        } +        void reset() { +            Option<T>::reset(); +            used = false; +        } +        bool used; +    }; + +    struct TestRunInfo { +        TestRunInfo( std::string const& _name ) : name( _name ) {} +        std::string name; +    }; +    struct GroupInfo { +        GroupInfo(  std::string const& _name, +                    std::size_t _groupIndex, +                    std::size_t _groupsCount ) +        :   name( _name ), +            groupIndex( _groupIndex ), +            groupsCounts( _groupsCount ) +        {} + +        std::string name; +        std::size_t groupIndex; +        std::size_t groupsCounts; +    }; + +    struct AssertionStats { +        AssertionStats( AssertionResult const& _assertionResult, +                        std::vector<MessageInfo> const& _infoMessages, +                        Totals const& _totals ) +        :   assertionResult( _assertionResult ), +            infoMessages( _infoMessages ), +            totals( _totals ) +        { +            if( assertionResult.hasMessage() ) { +                // Copy message into messages list. +                // !TBD This should have been done earlier, somewhere +                MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); +                builder << assertionResult.getMessage(); +                builder.m_info.message = builder.m_stream.str(); + +                infoMessages.push_back( builder.m_info ); +            } +        } +        virtual ~AssertionStats(); + +#  ifdef CATCH_CPP11_OR_GREATER +        AssertionStats( AssertionStats const& )              = default; +        AssertionStats( AssertionStats && )                  = default; +        AssertionStats& operator = ( AssertionStats const& ) = default; +        AssertionStats& operator = ( AssertionStats && )     = default; +#  endif + +        AssertionResult assertionResult; +        std::vector<MessageInfo> infoMessages; +        Totals totals; +    }; + +    struct SectionStats { +        SectionStats(   SectionInfo const& _sectionInfo, +                        Counts const& _assertions, +                        double _durationInSeconds, +                        bool _missingAssertions ) +        :   sectionInfo( _sectionInfo ), +            assertions( _assertions ), +            durationInSeconds( _durationInSeconds ), +            missingAssertions( _missingAssertions ) +        {} +        virtual ~SectionStats(); +#  ifdef CATCH_CPP11_OR_GREATER +        SectionStats( SectionStats const& )              = default; +        SectionStats( SectionStats && )                  = default; +        SectionStats& operator = ( SectionStats const& ) = default; +        SectionStats& operator = ( SectionStats && )     = default; +#  endif + +        SectionInfo sectionInfo; +        Counts assertions; +        double durationInSeconds; +        bool missingAssertions; +    }; + +    struct TestCaseStats { +        TestCaseStats(  TestCaseInfo const& _testInfo, +                        Totals const& _totals, +                        std::string const& _stdOut, +                        std::string const& _stdErr, +                        bool _aborting ) +        : testInfo( _testInfo ), +            totals( _totals ), +            stdOut( _stdOut ), +            stdErr( _stdErr ), +            aborting( _aborting ) +        {} +        virtual ~TestCaseStats(); + +#  ifdef CATCH_CPP11_OR_GREATER +        TestCaseStats( TestCaseStats const& )              = default; +        TestCaseStats( TestCaseStats && )                  = default; +        TestCaseStats& operator = ( TestCaseStats const& ) = default; +        TestCaseStats& operator = ( TestCaseStats && )     = default; +#  endif + +        TestCaseInfo testInfo; +        Totals totals; +        std::string stdOut; +        std::string stdErr; +        bool aborting; +    }; + +    struct TestGroupStats { +        TestGroupStats( GroupInfo const& _groupInfo, +                        Totals const& _totals, +                        bool _aborting ) +        :   groupInfo( _groupInfo ), +            totals( _totals ), +            aborting( _aborting ) +        {} +        TestGroupStats( GroupInfo const& _groupInfo ) +        :   groupInfo( _groupInfo ), +            aborting( false ) +        {} +        virtual ~TestGroupStats(); + +#  ifdef CATCH_CPP11_OR_GREATER +        TestGroupStats( TestGroupStats const& )              = default; +        TestGroupStats( TestGroupStats && )                  = default; +        TestGroupStats& operator = ( TestGroupStats const& ) = default; +        TestGroupStats& operator = ( TestGroupStats && )     = default; +#  endif + +        GroupInfo groupInfo; +        Totals totals; +        bool aborting; +    }; + +    struct TestRunStats { +        TestRunStats(   TestRunInfo const& _runInfo, +                        Totals const& _totals, +                        bool _aborting ) +        :   runInfo( _runInfo ), +            totals( _totals ), +            aborting( _aborting ) +        {} +        virtual ~TestRunStats(); + +#  ifndef CATCH_CPP11_OR_GREATER +        TestRunStats( TestRunStats const& _other ) +        :   runInfo( _other.runInfo ), +            totals( _other.totals ), +            aborting( _other.aborting ) +        {} +#  else +        TestRunStats( TestRunStats const& )              = default; +        TestRunStats( TestRunStats && )                  = default; +        TestRunStats& operator = ( TestRunStats const& ) = default; +        TestRunStats& operator = ( TestRunStats && )     = default; +#  endif + +        TestRunInfo runInfo; +        Totals totals; +        bool aborting; +    }; + +    struct IStreamingReporter : IShared { +        virtual ~IStreamingReporter(); + +        // Implementing class must also provide the following static method: +        // static std::string getDescription(); + +        virtual ReporterPreferences getPreferences() const = 0; + +        virtual void noMatchingTestCases( std::string const& spec ) = 0; + +        virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; +        virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0; + +        virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; +        virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; + +        virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; + +        virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; +        virtual void sectionEnded( SectionStats const& sectionStats ) = 0; +        virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; +        virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; +        virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; +    }; + +    struct IReporterFactory { +        virtual ~IReporterFactory(); +        virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0; +        virtual std::string getDescription() const = 0; +    }; + +    struct IReporterRegistry { +        typedef std::map<std::string, IReporterFactory*> FactoryMap; + +        virtual ~IReporterRegistry(); +        virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig> const& config ) const = 0; +        virtual FactoryMap const& getFactories() const = 0; +    }; + +} +  #include <limits>  #include <algorithm>  namespace Catch { -    inline bool matchesFilters( std::vector<TestCaseFilters> const& filters, TestCase const& testCase ) { -        std::vector<TestCaseFilters>::const_iterator it = filters.begin(); -        std::vector<TestCaseFilters>::const_iterator itEnd = filters.end(); -        for(; it != itEnd; ++it ) -            if( !it->shouldInclude( testCase ) ) -                return false; -        return true; -    }      inline std::size_t listTests( Config const& config ) {          if( config.filters().empty() ) @@ -4580,22 +4564,22 @@ namespace Catch {          nameAttr.setInitialIndent( 2 ).setIndent( 4 );          tagsAttr.setIndent( 6 ); -        std::vector<TestCase> const& allTests = getRegistryHub().getTestCaseRegistry().getAllTests(); -        for( std::vector<TestCase>::const_iterator it = allTests.begin(), itEnd = allTests.end(); +        std::vector<TestCase> matchedTestCases; +        getRegistryHub().getTestCaseRegistry().getFilteredTests( config, matchedTestCases ); +        for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();                  it != itEnd; -                ++it ) -            if( matchesFilters( config.filters(), *it ) ) { -                matchedTests++; -                TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); -                Colour::Code colour = testCaseInfo.isHidden -                    ? Colour::SecondaryText -                    : Colour::None; -                Colour colourGuard( colour ); +                ++it ) { +            matchedTests++; +            TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); +            Colour::Code colour = testCaseInfo.isHidden +                ? Colour::SecondaryText +                : Colour::None; +            Colour colourGuard( colour ); -                std::cout << Text( testCaseInfo.name, nameAttr ) << std::endl; -                if( !testCaseInfo.tags.empty() ) -                    std::cout << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl; -            } +            std::cout << Text( testCaseInfo.name, nameAttr ) << std::endl; +            if( !testCaseInfo.tags.empty() ) +                std::cout << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl; +        }          if( config.filters().empty() )              std::cout << pluralise( matchedTests, "test case" ) << "\n" << std::endl; @@ -4604,6 +4588,20 @@ namespace Catch {          return matchedTests;      } +    inline std::size_t listTestsNamesOnly( Config const& config ) { +        std::size_t matchedTests = 0; +        std::vector<TestCase> matchedTestCases; +        getRegistryHub().getTestCaseRegistry().getFilteredTests( config, matchedTestCases ); +        for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); +                it != itEnd; +                ++it ) { +            matchedTests++; +            TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); +            std::cout << testCaseInfo.name << std::endl; +        } +        return matchedTests; +    } +      inline std::size_t listTags( Config const& config ) {          if( config.filters().empty() )              std::cout << "All available tags:\n"; @@ -4612,23 +4610,21 @@ namespace Catch {          std::map<std::string, int> tagCounts; -        std::vector<TestCase> const& allTests = getRegistryHub().getTestCaseRegistry().getAllTests(); -        for( std::vector<TestCase>::const_iterator  it = allTests.begin(), -                                                    itEnd = allTests.end(); +        std::vector<TestCase> matchedTestCases; +        getRegistryHub().getTestCaseRegistry().getFilteredTests( config, matchedTestCases ); +        for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();                  it != itEnd;                  ++it ) { -            if( matchesFilters( config.filters(), *it ) ) { -                for( std::set<std::string>::const_iterator  tagIt = it->getTestCaseInfo().tags.begin(), -                                                            tagItEnd = it->getTestCaseInfo().tags.end(); -                        tagIt != tagItEnd; -                        ++tagIt ) { -                    std::string tagName = *tagIt; -                    std::map<std::string, int>::iterator countIt = tagCounts.find( tagName ); -                    if( countIt == tagCounts.end() ) -                        tagCounts.insert( std::make_pair( tagName, 1 ) ); -                    else -                        countIt->second++; -                } +            for( std::set<std::string>::const_iterator  tagIt = it->getTestCaseInfo().tags.begin(), +                                                        tagItEnd = it->getTestCaseInfo().tags.end(); +                    tagIt != tagItEnd; +                    ++tagIt ) { +                std::string tagName = *tagIt; +                std::map<std::string, int>::iterator countIt = tagCounts.find( tagName ); +                if( countIt == tagCounts.end() ) +                    tagCounts.insert( std::make_pair( tagName, 1 ) ); +                else +                    countIt->second++;              }          } @@ -4675,6 +4671,8 @@ namespace Catch {          Option<std::size_t> listedCount;          if( config.listTests() )              listedCount = listedCount.valueOr(0) + listTests( config ); +        if( config.listTestNamesOnly() ) +            listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config );          if( config.listTags() )              listedCount = listedCount.valueOr(0) + listTags( config );          if( config.listReporters() ) @@ -4715,13 +4713,18 @@ namespace SectionTracking {          RunState runState() const { return m_runState; } -        void addChild( std::string const& childName ) { -            m_children.insert( std::make_pair( childName, TrackedSection( childName, this ) ) ); +        TrackedSection* findChild( std::string const& childName ) { +            TrackedSections::iterator it = m_children.find( childName ); +            return it != m_children.end() +                ? &it->second +                : NULL;          } -        TrackedSection* getChild( std::string const& childName ) { -            return &m_children.find( childName )->second; +        TrackedSection* acquireChild( std::string const& childName ) { +            if( TrackedSection* child = findChild( childName ) ) +                return child; +            m_children.insert( std::make_pair( childName, TrackedSection( childName, this ) ) ); +            return findChild( childName );          } -          void enter() {              if( m_runState == NotStarted )                  m_runState = Executing; @@ -4760,21 +4763,13 @@ namespace SectionTracking {          {}          bool enterSection( std::string const& name ) { -            if( m_completedASectionThisRun ) +            TrackedSection* child = m_currentSection->acquireChild( name ); +            if( m_completedASectionThisRun || child->runState() == TrackedSection::Completed )                  return false; -            if( m_currentSection->runState() == TrackedSection::Executing ) { -                m_currentSection->addChild( name ); -                return false; -            } -            else { -                TrackedSection* child = m_currentSection->getChild( name ); -                if( child->runState() != TrackedSection::Completed ) { -                    m_currentSection = child; -                    m_currentSection->enter(); -                    return true; -                } -                return false; -            } + +            m_currentSection = child; +            m_currentSection->enter(); +            return true;          }          void leaveSection() {              m_currentSection->leave(); @@ -4792,9 +4787,7 @@ namespace SectionTracking {          class Guard {          public: -            Guard( TestCaseTracker& tracker ) -            : m_tracker( tracker ) -            { +            Guard( TestCaseTracker& tracker ) : m_tracker( tracker ) {                  m_tracker.enterTestCase();              }              ~Guard() { @@ -4895,23 +4888,6 @@ namespace Catch {              m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) );          } -        Totals runMatching( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) { - -            std::vector<TestCase> matchingTests = getRegistryHub().getTestCaseRegistry().getMatchingTestCases( testSpec ); - -            Totals totals; - -            testGroupStarting( testSpec, groupIndex, groupsCount ); - -            std::vector<TestCase>::const_iterator it = matchingTests.begin(); -            std::vector<TestCase>::const_iterator itEnd = matchingTests.end(); -            for(; it != itEnd; ++it ) -                totals += runTest( *it ); - -            testGroupEnded( testSpec, totals, groupIndex, groupsCount ); -            return totals; -        } -          Totals runTest( TestCase const& testCase ) {              Totals prevTotals = m_totals; @@ -5095,8 +5071,8 @@ namespace Catch {              }              // 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(); +            for( std::vector<UnfinishedSections>::const_reverse_iterator it = m_unfinishedSections.rbegin(), +                        itEnd = m_unfinishedSections.rend();                      it != itEnd;                      ++it )                  sectionEnded( it->info, it->prevAssertions, it->durationInSeconds ); @@ -5150,17 +5126,17 @@ namespace Catch {          Version(    unsigned int _majorVersion,                      unsigned int _minorVersion,                      unsigned int _buildNumber, -                    std::string const& _branchName ) +                    char const* const _branchName )          :   majorVersion( _majorVersion ),              minorVersion( _minorVersion ),              buildNumber( _buildNumber ),              branchName( _branchName )          {} -        const unsigned int majorVersion; -        const unsigned int minorVersion; -        const unsigned int buildNumber; -        const std::string branchName; +        unsigned int const majorVersion; +        unsigned int const minorVersion; +        unsigned int const buildNumber; +        char const* const branchName;      private:          void operator=( Version const& ); @@ -5204,29 +5180,29 @@ namespace Catch {              }              return totals;          } - -        Totals runTestsForGroup( RunContext& context, const TestCaseFilters& filterGroup ) { +        Totals runTestsForGroup( RunContext& context, TestCaseFilters const& filterGroup ) {              Totals totals; -            std::vector<TestCase>::const_iterator it = getRegistryHub().getTestCaseRegistry().getAllTests().begin(); -            std::vector<TestCase>::const_iterator itEnd = getRegistryHub().getTestCaseRegistry().getAllTests().end(); + +            std::vector<TestCase> testCases; +            getRegistryHub().getTestCaseRegistry().getFilteredTests( filterGroup, *m_config, testCases ); +              int testsRunForGroup = 0; -            for(; it != itEnd; ++it ) { -                if( filterGroup.shouldInclude( *it ) ) { -                    testsRunForGroup++; -                    if( m_testsAlreadyRun.find( *it ) == m_testsAlreadyRun.end() ) { +            for( std::vector<TestCase>::const_iterator it = testCases.begin(), itEnd = testCases.end(); +                    it != itEnd; +                    ++it ) { +                testsRunForGroup++; +                if( m_testsAlreadyRun.find( *it ) == m_testsAlreadyRun.end() ) { -                        if( context.aborting() ) -                            break; +                    if( context.aborting() ) +                        break; -                        totals += context.runTest( *it ); -                        m_testsAlreadyRun.insert( *it ); -                    } +                    totals += context.runTest( *it ); +                    m_testsAlreadyRun.insert( *it );                  }              }              if( testsRunForGroup == 0 && !filterGroup.getName().empty() )                  m_reporter->noMatchingTestCases( filterGroup.getName() );              return totals; -          }      private: @@ -5286,7 +5262,7 @@ namespace Catch {              std::cout << "\nCatch v"    << libraryVersion.majorVersion << "."                                          << libraryVersion.minorVersion << " build "                                          << libraryVersion.buildNumber; -            if( libraryVersion.branchName != "master" ) +            if( libraryVersion.branchName != std::string( "master" ) )                  std::cout << " (" << libraryVersion.branchName << " branch)";              std::cout << "\n"; @@ -5296,9 +5272,8 @@ namespace Catch {          int applyCommandLine( int argc, char* const argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) {              try { +                m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail );                  m_unusedTokens = m_cli.parseInto( argc, argv, m_configData ); -                if( unusedOptionBehaviour == OnUnusedOptions::Fail ) -                    enforceNoUsedTokens();                  if( m_configData.showHelp )                      showHelp( m_configData.processName );                  m_config.reset(); @@ -5306,7 +5281,7 @@ namespace Catch {              catch( std::exception& ex ) {                  {                      Colour colourGuard( Colour::Red ); -                    std::cerr   << "\nError in input:\n" +                    std::cerr   << "\nError(s) in input:\n"                                  << Text( ex.what(), TextAttributes().setIndent(2) )                                  << "\n\n";                  } @@ -5321,18 +5296,6 @@ namespace Catch {              m_config.reset();          } -        void enforceNoUsedTokens() const { -            if( !m_unusedTokens.empty() ) { -                std::vector<Clara::Parser::Token>::const_iterator -                    it = m_unusedTokens.begin(), -                    itEnd = m_unusedTokens.end(); -                std::string msg; -                for(; it != itEnd; ++it ) -                    msg += "  unrecognised option: " + it->data + "\n"; -                throw std::runtime_error( msg.substr( 0, msg.size()-1 ) ); -            } -        } -          int run( int argc, char* const argv[] ) {              int returnCode = applyCommandLine( argc, argv ); @@ -5422,9 +5385,12 @@ namespace Catch {              }              else {                  TestCase const& prev = *m_functions.find( testCase ); -                std::cerr   << "error: TEST_CASE( \"" << name << "\" ) already defined.\n" -                            << "\tFirst seen at " << SourceLineInfo( prev.getTestCaseInfo().lineInfo ) << "\n" -                            << "\tRedefined at " << SourceLineInfo( testCase.getTestCaseInfo().lineInfo ) << std::endl; +                { +                    Colour colourGuard( Colour::Red ); +                    std::cerr   << "error: TEST_CASE( \"" << name << "\" ) already defined.\n" +                                << "\tFirst seen at " << prev.getTestCaseInfo().lineInfo << "\n" +                                << "\tRedefined at " << testCase.getTestCaseInfo().lineInfo << std::endl; +                }                  exit(1);              }          } @@ -5437,32 +5403,24 @@ namespace Catch {              return m_nonHiddenFunctions;          } -        // !TBD deprecated -        virtual std::vector<TestCase> getMatchingTestCases( std::string const& rawTestSpec ) const { -            std::vector<TestCase> matchingTests; -            getMatchingTestCases( rawTestSpec, matchingTests ); -            return matchingTests; -        } - -        // !TBD deprecated -        virtual void getMatchingTestCases( std::string const& rawTestSpec, std::vector<TestCase>& matchingTestsOut ) const { -            TestCaseFilter filter( rawTestSpec ); - -            std::vector<TestCase>::const_iterator it = m_functionsInOrder.begin(); -            std::vector<TestCase>::const_iterator itEnd = m_functionsInOrder.end(); -            for(; it != itEnd; ++it ) { -                if( filter.shouldInclude( *it ) ) { -                    matchingTestsOut.push_back( *it ); -                } +        virtual void getFilteredTests( TestCaseFilters const& filters, IConfig const& config, std::vector<TestCase>& matchingTestCases ) const { +            for( std::vector<TestCase>::const_iterator  it = m_functionsInOrder.begin(), +                                                        itEnd = m_functionsInOrder.end(); +                    it != itEnd; +                    ++it ) { +                if( filters.shouldInclude( *it ) && ( config.allowThrows() || !it->throws() ) ) +                    matchingTestCases.push_back( *it );              }          } -        virtual void getMatchingTestCases( TestCaseFilters const& filters, std::vector<TestCase>& matchingTestsOut ) const { -            std::vector<TestCase>::const_iterator it = m_functionsInOrder.begin(); -            std::vector<TestCase>::const_iterator itEnd = m_functionsInOrder.end(); -            // !TBD: replace with algorithm -            for(; it != itEnd; ++it ) -                if( filters.shouldInclude( *it ) ) -                    matchingTestsOut.push_back( *it ); +        virtual void getFilteredTests( IConfig const& config, std::vector<TestCase>& matchingTestCases ) const { +            if( config.filters().empty() ) +                return getFilteredTests( TestCaseFilters( "empty" ), config, matchingTestCases ); + +            for( std::vector<TestCaseFilters>::const_iterator   it = config.filters().begin(), +                                                                itEnd = config.filters().end(); +                    it != itEnd; +                    ++it ) +                getFilteredTests( *it, config, matchingTestCases );          }      private: @@ -5707,7 +5665,7 @@ namespace Catch {          m_what = oss.str();      } -    const char* NotImplementedException::what() const throw() { +    const char* NotImplementedException::what() const CATCH_NOEXCEPT {          return m_what.c_str();      } @@ -5716,6 +5674,89 @@ namespace Catch {  // #included from: catch_context_impl.hpp  #define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED +// #included from: catch_stream.hpp +#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED + +// #included from: catch_streambuf.h +#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED + +#include <streambuf> + +namespace Catch { + +    class StreamBufBase : public std::streambuf { +    public: +        virtual ~StreamBufBase() CATCH_NOEXCEPT; +    }; +} + +#include <stdexcept> +#include <cstdio> + +namespace Catch { + +    template<typename WriterF, size_t bufferSize=256> +    class StreamBufImpl : public StreamBufBase { +        char data[bufferSize]; +        WriterF m_writer; + +    public: +        StreamBufImpl() { +            setp( data, data + sizeof(data) ); +        } + +        ~StreamBufImpl() CATCH_NOEXCEPT { +            sync(); +        } + +    private: +        int overflow( int c ) { +            sync(); + +            if( c != EOF ) { +                if( pbase() == epptr() ) +                    m_writer( std::string( 1, static_cast<char>( c ) ) ); +                else +                    sputc( static_cast<char>( c ) ); +            } +            return 0; +        } + +        int sync() { +            if( pbase() != pptr() ) { +                m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) ); +                setp( pbase(), epptr() ); +            } +            return 0; +        } +    }; + +    /////////////////////////////////////////////////////////////////////////// + +    struct OutputDebugWriter { + +        void operator()( std::string const&str ) { +            writeToDebugConsole( str ); +        } +    }; + +    Stream::Stream() +    : streamBuf( NULL ), isOwned( false ) +    {} + +    Stream::Stream( std::streambuf* _streamBuf, bool _isOwned ) +    : streamBuf( _streamBuf ), isOwned( _isOwned ) +    {} + +    void Stream::release() { +        if( isOwned ) { +            delete streamBuf; +            streamBuf = NULL; +            isOwned = false; +        } +    } +} +  namespace Catch {      class Context : public IMutableContext { @@ -5878,7 +5919,10 @@ namespace {          return true;      } -    Win32ColourImpl platformColourImpl; +    static Detail::IColourImpl* platformColourInstance() { +        static Win32ColourImpl s_instance; +        return &s_instance; +    }  } // end anon namespace  } // end namespace Catch @@ -5922,10 +5966,13 @@ namespace {      };      inline bool shouldUseColourForPlatform() { -        return isatty( fileno(stdout) ); +        return isatty(STDOUT_FILENO);      } -    PosixColourImpl platformColourImpl; +    static Detail::IColourImpl* platformColourInstance() { +        static PosixColourImpl s_instance; +        return &s_instance; +    }  } // end anon namespace  } // end namespace Catch @@ -5937,21 +5984,28 @@ namespace Catch {      namespace {          struct NoColourImpl : Detail::IColourImpl {              void use( Colour::Code ) {} + +            static IColourImpl* instance() { +                static NoColourImpl s_instance; +                return &s_instance; +            }          }; -        NoColourImpl noColourImpl; -        static const bool shouldUseColour = shouldUseColourForPlatform() && -                                            !isDebuggerActive(); +        static bool shouldUseColour() { +            return shouldUseColourForPlatform() && !isDebuggerActive(); +        }      }      Colour::Colour( Code _colourCode ){ use( _colourCode ); }      Colour::~Colour(){ use( None ); }      void Colour::use( Code _colourCode ) { -        impl->use( _colourCode ); +        impl()->use( _colourCode );      } -    Detail::IColourImpl* Colour::impl = shouldUseColour -            ? static_cast<Detail::IColourImpl*>( &platformColourImpl ) -            : static_cast<Detail::IColourImpl*>( &noColourImpl ); +    Detail::IColourImpl* Colour::impl() { +        return shouldUseColour() +            ? platformColourInstance() +            : NoColourImpl::instance(); +    }  } // end namespace Catch @@ -6202,6 +6256,16 @@ namespace Catch {  namespace Catch { +    inline bool isSpecialTag( std::string const& tag ) { +        return  tag == "." || +                tag == "hide" || +                tag == "!hide" || +                tag == "!throws"; +    } +    inline bool isReservedTag( std::string const& tag ) { +        return !isSpecialTag( tag ) && tag.size() > 0 && !isalnum( tag[0] ); +    } +      TestCase makeTestCase(  ITestCase* _testCase,                              std::string const& _className,                              std::string const& _name, @@ -6209,12 +6273,33 @@ namespace Catch {                              SourceLineInfo const& _lineInfo )      {          std::string desc = _descOrTags; -        bool isHidden( startsWith( _name, "./" ) ); +        bool isHidden( startsWith( _name, "./" ) ); // Legacy support          std::set<std::string> tags;          TagExtracter( tags ).parse( desc ); +        for( std::set<std::string>::const_iterator it = tags.begin(), itEnd = tags.end(); +                it != itEnd; +                ++it ) +            if( isReservedTag( *it ) ) { +                { +                    Colour colourGuard( Colour::Red ); +                    std::cerr +                        << "Tag name [" << *it << "] not allowed.\n" +                        << "Tag names starting with non alpha-numeric characters are reserved\n"; +                } +                { +                    Colour colourGuard( Colour::FileName ); +                    std::cerr << _lineInfo << std::endl; +                } +                exit(1); +            } +          if( tags.find( "hide" ) != tags.end() || tags.find( "." ) != tags.end() )              isHidden = true; +        if( isHidden ) { +            tags.insert( "hide" ); +            tags.insert( "." ); +        }          TestCaseInfo info( _name, _className, desc, tags, isHidden, _lineInfo );          return TestCase( _testCase, info );      } @@ -6230,11 +6315,15 @@ namespace Catch {          description( _description ),          tags( _tags ),          lineInfo( _lineInfo ), -        isHidden( _isHidden ) +        isHidden( _isHidden ), +        throws( false )      {          std::ostringstream oss; -        for( std::set<std::string>::const_iterator it = _tags.begin(), itEnd = _tags.end(); it != itEnd; ++it ) +        for( std::set<std::string>::const_iterator it = _tags.begin(), itEnd = _tags.end(); it != itEnd; ++it ) {              oss << "[" << *it << "]"; +            if( *it == "!throws" ) +                throws = true; +        }          tagsAsString = oss.str();      } @@ -6245,7 +6334,8 @@ namespace Catch {          tags( other.tags ),          tagsAsString( other.tagsAsString ),          lineInfo( other.lineInfo ), -        isHidden( other.isHidden ) +        isHidden( other.isHidden ), +        throws( other.throws )      {}      TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {} @@ -6268,6 +6358,9 @@ namespace Catch {      bool TestCase::isHidden() const {          return TestCaseInfo::isHidden;      } +    bool TestCase::throws() const { +        return TestCaseInfo::throws; +    }      bool TestCase::hasTag( std::string const& tag ) const {          return tags.find( toLower( tag ) ) != tags.end(); @@ -6311,101 +6404,260 @@ namespace Catch {  } // end namespace Catch -// #included from: catch_version.hpp -#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED +// #included from: catch_tags.hpp +#define TWOBLUECUBES_CATCH_TAGS_HPP_INCLUDED  namespace Catch { +    TagParser::~TagParser() {} -    // These numbers are maintained by a script -    Version libraryVersion( 1, 0, 13, "master" ); -} +    void TagParser::parse( std::string const& str ) { +        std::size_t pos = 0; +        while( pos < str.size() ) { +            char c = str[pos]; +            if( c == '[' ) { +                std::size_t end = str.find_first_of( ']', pos ); +                if( end != std::string::npos ) { +                    acceptTag( str.substr( pos+1, end-pos-1 ) ); +                    pos = end+1; +                } +                else { +                    acceptChar( c ); +                    pos++; +                } +            } +            else { +                acceptChar( c ); +                pos++; +            } +        } +        endParse(); +    } -// #included from: catch_text.hpp -#define TWOBLUECUBES_CATCH_TEXT_HPP_INCLUDED +    TagExtracter::TagExtracter( std::set<std::string>& tags ) +    :   m_tags( tags ) +    {} -#include <string> -#include <vector> +    TagExtracter::~TagExtracter() {} + +    void TagExtracter::parse( std::string& description ) { +        TagParser::parse( description ); +        description = m_remainder; +    } + +    void TagExtracter::acceptTag( std::string const& tag ) { +        m_tags.insert( toLower( tag ) ); +    } +    void TagExtracter::acceptChar( char c ) { +        m_remainder += c; +    } + +    Tag::Tag() : m_isNegated( false ) {} +    Tag::Tag( std::string const& name, bool isNegated ) +    :   m_name( name ), +        m_isNegated( isNegated ) +    {} + +    std::string Tag::getName() const { +        return m_name; +    } +    bool Tag::isNegated() const { +        return m_isNegated; +    } + +    bool Tag::operator ! () const { +        return m_name.empty(); +    } + +    void TagSet::add( Tag const& tag ) { +        m_tags.insert( std::make_pair( toLower( tag.getName() ), tag ) ); +    } + +    bool TagSet::empty() const { +        return m_tags.empty(); +    } + +    bool TagSet::matches( std::set<std::string> const& tags ) const { +        for(    TagMap::const_iterator +                    it = m_tags.begin(), itEnd = m_tags.end(); +                it != itEnd; +                ++it ) { +            bool found = tags.find( it->first ) != tags.end(); +            if( found == it->second.isNegated() ) +                return false; +        } +        return true; +    } + +    bool TagExpression::matches( std::set<std::string> const& tags ) const { +        for(    std::vector<TagSet>::const_iterator +                    it = m_tagSets.begin(), itEnd = m_tagSets.end(); +                it != itEnd; +                ++it ) +            if( it->matches( tags ) ) +                return true; +        return false; +    } + +    TagExpressionParser::TagExpressionParser( TagExpression& exp ) +    :   m_isNegated( false ), +        m_exp( exp ) +    {} + +    TagExpressionParser::~TagExpressionParser() {} + +    void TagExpressionParser::acceptTag( std::string const& tag ) { +        m_currentTagSet.add( Tag( tag, m_isNegated ) ); +        m_isNegated = false; +    } + +    void TagExpressionParser::acceptChar( char c ) { +        switch( c ) { +            case '~': +                m_isNegated = true; +                break; +            case ',': +                m_exp.m_tagSets.push_back( m_currentTagSet ); +                m_currentTagSet = TagSet(); +                break; +        } +    } + +    void TagExpressionParser::endParse() { +        if( !m_currentTagSet.empty() ) +            m_exp.m_tagSets.push_back( m_currentTagSet ); +    } + +} // end namespace Catch + +// #included from: catch_test_spec.hpp +#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED  namespace Catch { -    Text::Text( std::string const& _str, TextAttributes const& _attr ) -    : attr( _attr ) +    TestCaseFilter::TestCaseFilter( std::string const& testSpec, IfFilterMatches::DoWhat matchBehaviour ) +    :   m_stringToMatch( toLower( testSpec ) ), +        m_filterType( matchBehaviour ), +        m_wildcardPosition( NoWildcard )      { -        std::string wrappableChars = " [({.,/|\\-"; -        std::size_t indent = _attr.initialIndent != std::string::npos -            ? _attr.initialIndent -            : _attr.indent; -        std::string remainder = _str; - -        while( !remainder.empty() ) { -            if( lines.size() >= 1000 ) { -                lines.push_back( "... message truncated due to excessive size" ); -                return; +        if( m_filterType == IfFilterMatches::AutoDetectBehaviour ) { +            if( startsWith( m_stringToMatch, "exclude:" ) ) { +                m_stringToMatch = m_stringToMatch.substr( 8 ); +                m_filterType = IfFilterMatches::ExcludeTests;              } -            std::size_t tabPos = std::string::npos; -            std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); -            std::size_t pos = remainder.find_first_of( '\n' ); -            if( pos <= width ) { -                width = pos; -            } -            pos = remainder.find_last_of( _attr.tabChar, width ); -            if( pos != std::string::npos ) { -                tabPos = pos; -                if( remainder[width] == '\n' ) -                    width--; -                remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); -            } - -            if( width == remainder.size() ) { -                spliceLine( indent, remainder, width ); -            } -            else if( remainder[width] == '\n' ) { -                spliceLine( indent, remainder, width ); -                if( width <= 1 || remainder.size() != 1 ) -                    remainder = remainder.substr( 1 ); -                indent = _attr.indent; +            else if( startsWith( m_stringToMatch, "~" ) ) { +                m_stringToMatch = m_stringToMatch.substr( 1 ); +                m_filterType = IfFilterMatches::ExcludeTests;              }              else { -                pos = remainder.find_last_of( wrappableChars, width ); -                if( pos != std::string::npos && pos > 0 ) { -                    spliceLine( indent, remainder, pos ); -                    if( remainder[0] == ' ' ) -                        remainder = remainder.substr( 1 ); -                } -                else { -                    spliceLine( indent, remainder, width-1 ); -                    lines.back() += "-"; -                } -                if( lines.size() == 1 ) -                    indent = _attr.indent; -                if( tabPos != std::string::npos ) -                    indent += tabPos; +                m_filterType = IfFilterMatches::IncludeTests;              }          } + +        if( startsWith( m_stringToMatch, "*" ) ) { +            m_stringToMatch = m_stringToMatch.substr( 1 ); +            m_wildcardPosition = (WildcardPosition)( m_wildcardPosition | WildcardAtStart ); +        } +        if( endsWith( m_stringToMatch, "*" ) ) { +            m_stringToMatch = m_stringToMatch.substr( 0, m_stringToMatch.size()-1 ); +            m_wildcardPosition = (WildcardPosition)( m_wildcardPosition | WildcardAtEnd ); +        }      } -    void Text::spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { -        lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); -        _remainder = _remainder.substr( _pos ); +    IfFilterMatches::DoWhat TestCaseFilter::getFilterType() const { +        return m_filterType;      } -    std::string Text::toString() const { -        std::ostringstream oss; -        oss << *this; -        return oss.str(); +    bool TestCaseFilter::shouldInclude( TestCase const& testCase ) const { +        return isMatch( testCase ) == (m_filterType == IfFilterMatches::IncludeTests);      } -    std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { -        for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); -            it != itEnd; ++it ) { -            if( it != _text.begin() ) -                _stream << "\n"; -            _stream << *it; +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunreachable-code" +#endif + +    bool TestCaseFilter::isMatch( TestCase const& testCase ) const { +        std::string name = testCase.getTestCaseInfo().name; +        toLowerInPlace( name ); + +        switch( m_wildcardPosition ) { +            case NoWildcard: +                return m_stringToMatch == name; +            case WildcardAtStart: +                return endsWith( name, m_stringToMatch ); +            case WildcardAtEnd: +                return startsWith( name, m_stringToMatch ); +            case WildcardAtBothEnds: +                return contains( name, m_stringToMatch );          } -        return _stream; +        throw std::logic_error( "Unhandled wildcard type" );      } -} // end namespace Catch +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +    TestCaseFilters::TestCaseFilters( std::string const& name ) : m_name( name ) {} + +    std::string TestCaseFilters::getName() const { +        return m_name; +    } + +    void TestCaseFilters::addFilter( TestCaseFilter const& filter ) { +        if( filter.getFilterType() == IfFilterMatches::ExcludeTests ) +            m_exclusionFilters.push_back( filter ); +        else +            m_inclusionFilters.push_back( filter ); +    } + +    void TestCaseFilters::addTags( std::string const& tagPattern ) { +        TagExpression exp; +        TagExpressionParser( exp ).parse( tagPattern ); + +        m_tagExpressions.push_back( exp ); +    } + +    bool TestCaseFilters::shouldInclude( TestCase const& testCase ) const { +        if( !m_tagExpressions.empty() ) { +            std::vector<TagExpression>::const_iterator it = m_tagExpressions.begin(); +            std::vector<TagExpression>::const_iterator itEnd = m_tagExpressions.end(); +            for(; it != itEnd; ++it ) +                if( it->matches( testCase.getTags() ) ) +                    break; +            if( it == itEnd ) +                return false; +        } + +        if( !m_inclusionFilters.empty() ) { +            std::vector<TestCaseFilter>::const_iterator it = m_inclusionFilters.begin(); +            std::vector<TestCaseFilter>::const_iterator itEnd = m_inclusionFilters.end(); +            for(; it != itEnd; ++it ) +                if( it->shouldInclude( testCase ) ) +                    break; +            if( it == itEnd ) +                return false; +        } +        else if( m_exclusionFilters.empty() && m_tagExpressions.empty() ) { +            return !testCase.isHidden(); +        } + +        std::vector<TestCaseFilter>::const_iterator it = m_exclusionFilters.begin(); +        std::vector<TestCaseFilter>::const_iterator itEnd = m_exclusionFilters.end(); +        for(; it != itEnd; ++it ) +            if( !it->shouldInclude( testCase ) ) +                return false; +        return true; +    } +} + +// #included from: catch_version.hpp +#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED + +namespace Catch { + +    // These numbers are maintained by a script +    Version libraryVersion( 1, 0, 43, "master" ); +}  // #included from: catch_message.hpp  #define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED @@ -6446,6 +6698,26 @@ namespace Catch {  namespace Catch  { +    // Deprecated +    struct IReporter : IShared { +        virtual ~IReporter(); + +        virtual bool shouldRedirectStdout() const = 0; + +        virtual void StartTesting() = 0; +        virtual void EndTesting( Totals const& totals ) = 0; +        virtual void StartGroup( std::string const& groupName ) = 0; +        virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0; +        virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0; +        virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0; +        virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0; +        virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0; +        virtual void NoAssertionsInSection( std::string const& sectionName ) = 0; +        virtual void NoAssertionsInTestCase( std::string const& testName ) = 0; +        virtual void Aborted() = 0; +        virtual void Result( AssertionResult const& result ) = 0; +    }; +      class LegacyReporterAdapter : public SharedImpl<IStreamingReporter>      {      public: @@ -6593,9 +6865,507 @@ namespace Catch {  #ifdef __clang__  #pragma clang diagnostic pop  #endif +// #included from: catch_common.hpp +#define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED + +namespace Catch { + +    bool startsWith( std::string const& s, std::string const& prefix ) { +        return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix; +    } +    bool endsWith( std::string const& s, std::string const& suffix ) { +        return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix; +    } +    bool contains( std::string const& s, std::string const& infix ) { +        return s.find( infix ) != std::string::npos; +    } +    void toLowerInPlace( std::string& s ) { +        std::transform( s.begin(), s.end(), s.begin(), ::tolower ); +    } +    std::string toLower( std::string const& s ) { +        std::string lc = s; +        toLowerInPlace( lc ); +        return lc; +    } +    std::string trim( std::string const& str ) { +        static char const* whitespaceChars = "\n\r\t "; +        std::string::size_type start = str.find_first_not_of( whitespaceChars ); +        std::string::size_type end = str.find_last_not_of( whitespaceChars ); + +        return start != std::string::npos ? str.substr( start, 1+end-start ) : ""; +    } + +    pluralise::pluralise( std::size_t count, std::string const& label ) +    :   m_count( count ), +        m_label( label ) +    {} + +    std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { +        os << pluraliser.m_count << " " << pluraliser.m_label; +        if( pluraliser.m_count != 1 ) +            os << "s"; +        return os; +    } + +    SourceLineInfo::SourceLineInfo() : line( 0 ){} +    SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line ) +    :   file( _file ), +        line( _line ) +    {} +    SourceLineInfo::SourceLineInfo( SourceLineInfo const& other ) +    :   file( other.file ), +        line( other.line ) +    {} +    bool SourceLineInfo::empty() const { +        return file.empty(); +    } +    bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const { +        return line == other.line && file == other.file; +    } + +    std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { +#ifndef __GNUG__ +        os << info.file << "(" << info.line << ")"; +#else +        os << info.file << ":" << info.line; +#endif +        return os; +    } + +    void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) { +        std::ostringstream oss; +        oss << locationInfo << ": Internal Catch error: '" << message << "'"; +        if( isTrue( true )) +            throw std::logic_error( oss.str() ); +    } +} + +// #included from: catch_section.hpp +#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED + +namespace Catch { + +    Section::Section(   SourceLineInfo const& lineInfo, +                        std::string const& name, +                        std::string const& description ) +    :   m_info( name, description, lineInfo ), +        m_sectionIncluded( getCurrentContext().getResultCapture().sectionStarted( m_info, m_assertions ) ) +    { +        m_timer.start(); +    } + +    Section::~Section() { +        if( m_sectionIncluded ) +            getCurrentContext().getResultCapture().sectionEnded( m_info, m_assertions, m_timer.getElapsedSeconds() ); +    } + +    // This indicates whether the section should be executed or not +    Section::operator bool() { +        return m_sectionIncluded; +    } + +} // end namespace Catch + +// #included from: catch_debugger.hpp +#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED + +#include <iostream> + +#ifdef CATCH_PLATFORM_MAC + +    #include <assert.h> +    #include <stdbool.h> +    #include <sys/types.h> +    #include <unistd.h> +    #include <sys/sysctl.h> + +    namespace Catch{ + +        // The following function is taken directly from the following technical note: +        // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html + +        // Returns true if the current process is being debugged (either +        // running under the debugger or has a debugger attached post facto). +        bool isDebuggerActive(){ + +            int                 mib[4]; +            struct kinfo_proc   info; +            size_t              size; + +            // Initialize the flags so that, if sysctl fails for some bizarre +            // reason, we get a predictable result. + +            info.kp_proc.p_flag = 0; + +            // Initialize mib, which tells sysctl the info we want, in this case +            // we're looking for information about a specific process ID. + +            mib[0] = CTL_KERN; +            mib[1] = KERN_PROC; +            mib[2] = KERN_PROC_PID; +            mib[3] = getpid(); + +            // Call sysctl. + +            size = sizeof(info); +            if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0) != 0 ) { +                std::cerr << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; +                return false; +            } + +            // We're being debugged if the P_TRACED flag is set. + +            return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); +        } +    } // namespace Catch + +#elif defined(_MSC_VER) +    extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); +    namespace Catch { +        bool isDebuggerActive() { +            return IsDebuggerPresent() != 0; +        } +    } +#elif defined(__MINGW32__) +    extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); +    namespace Catch { +        bool isDebuggerActive() { +            return IsDebuggerPresent() != 0; +        } +    } +#else +    namespace Catch { +       inline bool isDebuggerActive() { return false; } +    } +#endif // Platform + +#ifdef CATCH_PLATFORM_WINDOWS +    extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* ); +    namespace Catch { +        void writeToDebugConsole( std::string const& text ) { +            ::OutputDebugStringA( text.c_str() ); +        } +    } +#else +    namespace Catch { +        void writeToDebugConsole( std::string const& text ) { +            // !TBD: Need a version for Mac/ XCode and other IDEs +            std::cout << text; +        } +    } +#endif // Platform + +// #included from: catch_tostring.hpp +#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED + +namespace Catch { + +std::string toString( std::string const& value ) { +    std::string s = value; +    if( getCurrentContext().getConfig()->showInvisibles() ) { +        for(size_t i = 0; i < s.size(); ++i ) { +            std::string subs; +            switch( s[i] ) { +            case '\n': subs = "\\n"; break; +            case '\t': subs = "\\t"; break; +            default: break; +            } +            if( !subs.empty() ) { +                s = s.substr( 0, i ) + subs + s.substr( i+1 ); +                ++i; +            } +        } +    } +    return "\"" + s + "\""; +} +std::string toString( std::wstring const& value ) { + +    std::string s; +    s.reserve( value.size() ); +    for(size_t i = 0; i < value.size(); ++i ) +        s += value[i] <= 0xff ? static_cast<char>( value[i] ) : '?'; +    return toString( s ); +} + +std::string toString( const char* const value ) { +    return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" ); +} + +std::string toString( char* const value ) { +    return Catch::toString( static_cast<const char*>( value ) ); +} + +std::string toString( int value ) { +    std::ostringstream oss; +    oss << value; +    return oss.str(); +} + +std::string toString( unsigned long value ) { +    std::ostringstream oss; +    if( value > 8192 ) +        oss << "0x" << std::hex << value; +    else +        oss << value; +    return oss.str(); +} + +std::string toString( unsigned int value ) { +    return toString( static_cast<unsigned long>( value ) ); +} + +std::string toString( const double value ) { +    std::ostringstream oss; +    oss << std::setprecision( 10 ) +        << std::fixed +        << value; +    std::string d = oss.str(); +    std::size_t i = d.find_last_not_of( '0' ); +    if( i != std::string::npos && i != d.size()-1 ) { +        if( d[i] == '.' ) +            i++; +        d = d.substr( 0, i+1 ); +    } +    return d; +} + +std::string toString( bool value ) { +    return value ? "true" : "false"; +} + +std::string toString( char value ) { +    return value < ' ' +        ? toString( static_cast<unsigned int>( value ) ) +        : Detail::makeString( value ); +} + +std::string toString( signed char value ) { +    return toString( static_cast<char>( value ) ); +} + +std::string toString( unsigned char value ) { +    return toString( static_cast<char>( value ) ); +} + +#ifdef CATCH_CONFIG_CPP11_NULLPTR +std::string toString( std::nullptr_t ) { +    return "nullptr"; +} +#endif + +#ifdef __OBJC__ +    std::string toString( NSString const * const& nsstring ) { +        if( !nsstring ) +            return "nil"; +        return std::string( "@\"" ) + [nsstring UTF8String] + "\""; +    } +    std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) { +        if( !nsstring ) +            return "nil"; +        return std::string( "@\"" ) + [nsstring UTF8String] + "\""; +    } +    std::string toString( NSObject* const& nsObject ) { +        return toString( [nsObject description] ); +    } +#endif + +} // end namespace Catch +  // #included from: ../reporters/catch_reporter_xml.hpp  #define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED +// #included from: catch_reporter_bases.hpp +#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED + +namespace Catch { + +    struct StreamingReporterBase : SharedImpl<IStreamingReporter> { + +        StreamingReporterBase( ReporterConfig const& _config ) +        :   m_config( _config.fullConfig() ), +            stream( _config.stream() ) +        {} + +        virtual ~StreamingReporterBase(); + +        virtual void noMatchingTestCases( std::string const& ) {} + +        virtual void testRunStarting( TestRunInfo const& _testRunInfo ) { +            currentTestRunInfo = _testRunInfo; +        } +        virtual void testGroupStarting( GroupInfo const& _groupInfo ) { +            currentGroupInfo = _groupInfo; +        } + +        virtual void testCaseStarting( TestCaseInfo const& _testInfo ) { +            currentTestCaseInfo = _testInfo; +        } +        virtual void sectionStarting( SectionInfo const& _sectionInfo ) { +            m_sectionStack.push_back( _sectionInfo ); +        } + +        virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) { +            m_sectionStack.pop_back(); +        } +        virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) { +            currentTestCaseInfo.reset(); +            assert( m_sectionStack.empty() ); +        } +        virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) { +            currentGroupInfo.reset(); +        } +        virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) { +            currentTestCaseInfo.reset(); +            currentGroupInfo.reset(); +            currentTestRunInfo.reset(); +        } + +        Ptr<IConfig> m_config; +        std::ostream& stream; + +        LazyStat<TestRunInfo> currentTestRunInfo; +        LazyStat<GroupInfo> currentGroupInfo; +        LazyStat<TestCaseInfo> currentTestCaseInfo; + +        std::vector<SectionInfo> m_sectionStack; +    }; + +    struct CumulativeReporterBase : SharedImpl<IStreamingReporter> { +        template<typename T, typename ChildNodeT> +        struct Node : SharedImpl<> { +            explicit Node( T const& _value ) : value( _value ) {} +            virtual ~Node() {} + +            typedef std::vector<Ptr<ChildNodeT> > ChildNodes; +            T value; +            ChildNodes children; +        }; +        struct SectionNode : SharedImpl<> { +            explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {} +            virtual ~SectionNode(); + +            bool operator == ( SectionNode const& other ) const { +                return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; +            } +            bool operator == ( Ptr<SectionNode> const& other ) const { +                return operator==( *other ); +            } + +            SectionStats stats; +            typedef std::vector<Ptr<SectionNode> > ChildSections; +            typedef std::vector<AssertionStats> Assertions; +            ChildSections childSections; +            Assertions assertions; +            std::string stdOut; +            std::string stdErr; +        }; + +        struct BySectionInfo { +            BySectionInfo( SectionInfo const& other ) : m_other( other ) {} +            bool operator() ( Ptr<SectionNode> const& node ) const { +                return node->stats.sectionInfo.lineInfo == m_other.lineInfo; +            } +        private: +            BySectionInfo& operator=( BySectionInfo const& other ); // = delete; + +            SectionInfo const& m_other; +        }; + +        typedef Node<TestCaseStats, SectionNode> TestCaseNode; +        typedef Node<TestGroupStats, TestCaseNode> TestGroupNode; +        typedef Node<TestRunStats, TestGroupNode> TestRunNode; + +        CumulativeReporterBase( ReporterConfig const& _config ) +        :   m_config( _config.fullConfig() ), +            stream( _config.stream() ) +        {} +        ~CumulativeReporterBase(); + +        virtual void testRunStarting( TestRunInfo const& ) {} +        virtual void testGroupStarting( GroupInfo const& ) {} + +        virtual void testCaseStarting( TestCaseInfo const& ) {} + +        virtual void sectionStarting( SectionInfo const& sectionInfo ) { +            SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); +            Ptr<SectionNode> node; +            if( m_sectionStack.empty() ) { +                if( !m_rootSection ) +                    m_rootSection = new SectionNode( incompleteStats ); +                node = m_rootSection; +            } +            else { +                SectionNode& parentNode = *m_sectionStack.back(); +                SectionNode::ChildSections::const_iterator it = +                    std::find_if(   parentNode.childSections.begin(), +                                    parentNode.childSections.end(), +                                    BySectionInfo( sectionInfo ) ); +                if( it == parentNode.childSections.end() ) { +                    node = new SectionNode( incompleteStats ); +                    parentNode.childSections.push_back( node ); +                } +                else +                    node = *it; +            } +            m_sectionStack.push_back( node ); +            m_deepestSection = node; +        } + +        virtual void assertionStarting( AssertionInfo const& ) {} + +        virtual bool assertionEnded( AssertionStats const& assertionStats ) { +            assert( !m_sectionStack.empty() ); +            SectionNode& sectionNode = *m_sectionStack.back(); +            sectionNode.assertions.push_back( assertionStats ); +            return true; +        } +        virtual void sectionEnded( SectionStats const& sectionStats ) { +            assert( !m_sectionStack.empty() ); +            SectionNode& node = *m_sectionStack.back(); +            node.stats = sectionStats; +            m_sectionStack.pop_back(); +        } +        virtual void testCaseEnded( TestCaseStats const& testCaseStats ) { +            Ptr<TestCaseNode> node = new TestCaseNode( testCaseStats ); +            assert( m_sectionStack.size() == 0 ); +            node->children.push_back( m_rootSection ); +            m_testCases.push_back( node ); +            m_rootSection.reset(); + +            assert( m_deepestSection ); +            m_deepestSection->stdOut = testCaseStats.stdOut; +            m_deepestSection->stdErr = testCaseStats.stdErr; +        } +        virtual void testGroupEnded( TestGroupStats const& testGroupStats ) { +            Ptr<TestGroupNode> node = new TestGroupNode( testGroupStats ); +            node->children.swap( m_testCases ); +            m_testGroups.push_back( node ); +        } +        virtual void testRunEnded( TestRunStats const& testRunStats ) { +            Ptr<TestRunNode> node = new TestRunNode( testRunStats ); +            node->children.swap( m_testGroups ); +            m_testRuns.push_back( node ); +            testRunEndedCumulative(); +        } +        virtual void testRunEndedCumulative() = 0; + +        Ptr<IConfig> m_config; +        std::ostream& stream; +        std::vector<AssertionStats> m_assertions; +        std::vector<std::vector<Ptr<SectionNode> > > m_sections; +        std::vector<Ptr<TestCaseNode> > m_testCases; +        std::vector<Ptr<TestGroupNode> > m_testGroups; + +        std::vector<Ptr<TestRunNode> > m_testRuns; + +        Ptr<SectionNode> m_rootSection; +        Ptr<SectionNode> m_deepestSection; +        std::vector<Ptr<SectionNode> > m_sectionStack; + +    }; + +} // end namespace Catch +  // #included from: ../internal/catch_reporter_registrars.hpp  #define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED @@ -6720,11 +7490,18 @@ namespace Catch {                  endElement();          } +#  ifndef CATCH_CPP11_OR_GREATER          XmlWriter& operator = ( XmlWriter const& other ) {              XmlWriter temp( other );              swap( temp );              return *this;          } +#  else +        XmlWriter( XmlWriter const& )              = default; +        XmlWriter( XmlWriter && )                  = default; +        XmlWriter& operator = ( XmlWriter const& ) = default; +        XmlWriter& operator = ( XmlWriter && )     = default; +#  endif          void swap( XmlWriter& other ) {              std::swap( m_tagIsOpen, other.m_tagIsOpen ); @@ -6907,7 +7684,7 @@ namespace Catch {          virtual void StartSection( const std::string& sectionName, const std::string& description ) {              if( m_sectionDepth++ > 0 ) {                  m_xml.startElement( "Section" ) -                    .writeAttribute( "name", sectionName ) +                    .writeAttribute( "name", trim( sectionName ) )                      .writeAttribute( "description", description );              }          } @@ -6924,7 +7701,7 @@ namespace Catch {          }          virtual void StartTestCase( const Catch::TestCaseInfo& testInfo ) { -            m_xml.startElement( "TestCase" ).writeAttribute( "name", testInfo.name ); +            m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) );              m_currentTestSuccess = true;          } @@ -7055,7 +7832,7 @@ namespace Catch {              writeGroup( *m_testGroups.back(), suiteTime );          } -        virtual void testRunEnded() { +        virtual void testRunEndedCumulative() {              xml.endElement();          } @@ -7211,6 +7988,8 @@ namespace Catch {  // #included from: ../reporters/catch_reporter_console.hpp  #define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED +#include <cstring> +  namespace Catch {      struct ConsoleReporter : StreamingReporterBase { @@ -7454,13 +8233,13 @@ namespace Catch {              m_atLeastOneTestCasePrinted = true;          }          void lazyPrintRunInfo() { -            stream  << "\n" << getTildes() << "\n"; +            stream  << "\n" << getLineOfChars<'~'>() << "\n";              Colour colour( Colour::SecondaryText );              stream  << currentTestRunInfo->name                      << " is a Catch v"  << libraryVersion.majorVersion << "."                      << libraryVersion.minorVersion << " b"                      << libraryVersion.buildNumber; -            if( libraryVersion.branchName != "master" ) +            if( libraryVersion.branchName != std::string( "master" ) )                  stream << " (" << libraryVersion.branchName << ")";              stream  << " host application.\n"                      << "Run with -? for options\n\n"; @@ -7490,19 +8269,19 @@ namespace Catch {              SourceLineInfo lineInfo = m_sectionStack.front().lineInfo;              if( !lineInfo.empty() ){ -                stream << getDashes() << "\n"; +                stream << getLineOfChars<'-'>() << "\n";                  Colour colourGuard( Colour::FileName );                  stream << lineInfo << "\n";              } -            stream << getDots() << "\n" << std::endl; +            stream << getLineOfChars<'.'>() << "\n" << std::endl;          }          void printClosedHeader( std::string const& _name ) {              printOpenHeader( _name ); -            stream << getDots() << "\n"; +            stream << getLineOfChars<'.'>() << "\n";          }          void printOpenHeader( std::string const& _name ) { -            stream  << getDashes() << "\n"; +            stream  << getLineOfChars<'-'>() << "\n";              {                  Colour colourGuard( Colour::Headers );                  printHeaderString( _name ); @@ -7575,26 +8354,19 @@ namespace Catch {          }          void printTotalsDivider() { -            stream << getDoubleDashes() << "\n"; +            stream << getLineOfChars<'='>() << "\n";          }          void printSummaryDivider() { -            stream << getDashes() << "\n"; -        } -        static std::string const& getDashes() { -            static const std::string dashes( CATCH_CONFIG_CONSOLE_WIDTH-1, '-' ); -            return dashes; -        } -        static std::string const& getDots() { -            static const std::string dots( CATCH_CONFIG_CONSOLE_WIDTH-1, '.' ); -            return dots; +            stream << getLineOfChars<'-'>() << "\n";          } -        static std::string const& getDoubleDashes() { -            static const std::string doubleDashes( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' ); -            return doubleDashes; -        } -        static std::string const& getTildes() { -            static const std::string dots( CATCH_CONFIG_CONSOLE_WIDTH-1, '~' ); -            return dots; +        template<char C> +        static char const* getLineOfChars() { +            static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0}; +            if( !*line ) { +                memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 ); +                line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0; +            } +            return line;          }      private: @@ -7606,10 +8378,291 @@ namespace Catch {  } // end namespace Catch +// #included from: ../reporters/catch_reporter_compact.hpp +#define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED + +namespace Catch { + +    struct CompactReporter : StreamingReporterBase { + +        CompactReporter( ReporterConfig const& _config ) +        : StreamingReporterBase( _config ) +        {} + +        virtual ~CompactReporter(); + +        static std::string getDescription() { +            return "Reports test results on a single line, suitable for IDEs"; +        } + +        virtual ReporterPreferences getPreferences() const { +            ReporterPreferences prefs; +            prefs.shouldRedirectStdOut = false; +            return prefs; +        } + +        virtual void noMatchingTestCases( std::string const& spec ) { +            stream << "No test cases matched '" << spec << "'" << std::endl; +        } + +        virtual void assertionStarting( AssertionInfo const& ) { +        } + +        virtual bool assertionEnded( AssertionStats const& _assertionStats ) { +            AssertionResult const& result = _assertionStats.assertionResult; + +            bool printInfoMessages = true; + +            // Drop out if result was successful and we're not printing those +            if( !m_config->includeSuccessfulResults() && result.isOk() ) { +                if( result.getResultType() != ResultWas::Warning ) +                    return false; +                printInfoMessages = false; +            } + +            AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); +            printer.print(); + +            stream << std::endl; +            return true; +        } + +        virtual void testRunEnded( TestRunStats const& _testRunStats ) { +            printTotals( _testRunStats.totals ); +            stream << "\n" << std::endl; +            StreamingReporterBase::testRunEnded( _testRunStats ); +        } + +    private: +        class AssertionPrinter { +            void operator= ( AssertionPrinter const& ); +        public: +            AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) +            : stream( _stream ) +            , stats( _stats ) +            , result( _stats.assertionResult ) +            , messages( _stats.infoMessages ) +            , itMessage( _stats.infoMessages.begin() ) +            , printInfoMessages( _printInfoMessages ) +            {} + +            void print() { +                printSourceInfo(); + +                itMessage = messages.begin(); + +                switch( result.getResultType() ) { +                    case ResultWas::Ok: +                        printResultType( Colour::ResultSuccess, passedString() ); +                        printOriginalExpression(); +                        printReconstructedExpression(); +                        if ( ! result.hasExpression() ) +                            printRemainingMessages( Colour::None ); +                        else +                            printRemainingMessages(); +                        break; +                    case ResultWas::ExpressionFailed: +                        if( result.isOk() ) +                            printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) ); +                        else +                            printResultType( Colour::Error, failedString() ); +                        printOriginalExpression(); +                        printReconstructedExpression(); +                        printRemainingMessages(); +                        break; +                    case ResultWas::ThrewException: +                        printResultType( Colour::Error, failedString() ); +                        printIssue( "unexpected exception with message:" ); +                        printMessage(); +                        printExpressionWas(); +                        printRemainingMessages(); +                        break; +                    case ResultWas::DidntThrowException: +                        printResultType( Colour::Error, failedString() ); +                        printIssue( "expected exception, got none" ); +                        printExpressionWas(); +                        printRemainingMessages(); +                        break; +                    case ResultWas::Info: +                        printResultType( Colour::None, "info" ); +                        printMessage(); +                        printRemainingMessages(); +                        break; +                    case ResultWas::Warning: +                        printResultType( Colour::None, "warning" ); +                        printMessage(); +                        printRemainingMessages(); +                        break; +                    case ResultWas::ExplicitFailure: +                        printResultType( Colour::Error, failedString() ); +                        printIssue( "explicitly" ); +                        printRemainingMessages( Colour::None ); +                        break; +                    // These cases are here to prevent compiler warnings +                    case ResultWas::Unknown: +                    case ResultWas::FailureBit: +                    case ResultWas::Exception: +                        printResultType( Colour::Error, "** internal error **" ); +                        break; +                } +            } + +        private: +            // Colour::LightGrey + +            static Colour dimColour() { return Colour::FileName; } + +#ifdef CATCH_PLATFORM_MAC +            static const char* failedString() { return "FAILED"; } +            static const char* passedString() { return "PASSED"; } +#else +            static const char* failedString() { return "failed"; } +            static const char* passedString() { return "passed"; } +#endif + +            void printSourceInfo() const { +                Colour colourGuard( Colour::FileName ); +                stream << result.getSourceInfo() << ":"; +            } + +            void printResultType( Colour colour, std::string passOrFail ) const { +                if( !passOrFail.empty() ) { +                    { +                        Colour colourGuard( colour ); +                        stream << " " << passOrFail; +                    } +                    stream << ":"; +                } +            } + +            void printIssue( std::string issue ) const { +                stream << " " << issue; +            } + +            void printExpressionWas() { +                if( result.hasExpression() ) { +                    stream << ";"; +                    { +                        Colour colour( dimColour() ); +                        stream << " expression was:"; +                    } +                    printOriginalExpression(); +                } +            } + +            void printOriginalExpression() const { +                if( result.hasExpression() ) { +                    stream << " " << result.getExpression(); +                } +            } + +            void printReconstructedExpression() const { +                if( result.hasExpandedExpression() ) { +                    { +                        Colour colour( dimColour() ); +                        stream << " for: "; +                    } +                    stream << result.getExpandedExpression(); +                } +            } + +            void printMessage() { +                if ( itMessage != messages.end() ) { +                    stream << " '" << itMessage->message << "'"; +                    ++itMessage; +                } +            } + +            void printRemainingMessages( Colour colour = dimColour() ) { +                if ( itMessage == messages.end() ) +                    return; + +                // using messages.end() directly yields compilation error: +                std::vector<MessageInfo>::const_iterator itEnd = messages.end(); +                const std::size_t N = static_cast<std::size_t>( std::distance( itMessage, itEnd ) ); + +                { +                    Colour colourGuard( colour ); +                    stream << " with " << pluralise( N, "message" ) << ":"; +                } + +                for(; itMessage != itEnd; ) { +                    // If this assertion is a warning ignore any INFO messages +                    if( printInfoMessages || itMessage->type != ResultWas::Info ) { +                        stream << " '" << itMessage->message << "'"; +                        if ( ++itMessage != itEnd ) { +                            Colour colourGuard( dimColour() ); +                            stream << " and"; +                        } +                    } +                } +            } + +        private: +            std::ostream& stream; +            AssertionStats const& stats; +            AssertionResult const& result; +            std::vector<MessageInfo> messages; +            std::vector<MessageInfo>::const_iterator itMessage; +            bool printInfoMessages; +        }; + +        // Colour, message variants: +        // - white: No tests ran. +        // -   red: Failed [both/all] N test cases, failed [both/all] M assertions. +        // - white: Passed [both/all] N test cases (no assertions). +        // -   red: Failed N tests cases, failed M assertions. +        // - green: Passed [both/all] N tests cases with M assertions. + +        std::string bothOrAll( std::size_t count ) const { +            return count == 1 ? "" : count == 2 ? "both " : "all " ; +        } + +        void printTotals( const Totals& totals ) const { +            if( totals.testCases.total() == 0 ) { +                stream << "No tests ran."; +            } +            else if( totals.testCases.failed == totals.testCases.total() ) { +                Colour colour( Colour::ResultError ); +                const std::string qualify_assertions_failed = +                    totals.assertions.failed == totals.assertions.total() ? +                        bothOrAll( totals.assertions.failed ) : ""; +                stream << +                    "Failed " << bothOrAll( totals.testCases.failed ) +                              << pluralise( totals.testCases.failed, "test case"  ) << ", " +                    "failed " << qualify_assertions_failed << +                                 pluralise( totals.assertions.failed, "assertion" ) << "."; +            } +            else if( totals.assertions.total() == 0 ) { +                stream << +                    "Passed " << bothOrAll( totals.testCases.total() ) +                              << pluralise( totals.testCases.total(), "test case" ) +                              << " (no assertions)."; +            } +            else if( totals.assertions.failed ) { +                Colour colour( Colour::ResultError ); +                stream << +                    "Failed " << pluralise( totals.testCases.failed, "test case"  ) << ", " +                    "failed " << pluralise( totals.assertions.failed, "assertion" ) << "."; +            } +            else { +                Colour colour( Colour::ResultSuccess ); +                stream << +                    "Passed " << bothOrAll( totals.testCases.passed ) +                              << pluralise( totals.testCases.passed, "test case"  ) << +                    " with "  << pluralise( totals.assertions.passed, "assertion" ) << "."; +            } +        } +    }; + +    INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter ) + +} // end namespace Catch +  namespace Catch {      NonCopyable::~NonCopyable() {}      IShared::~IShared() {} -    StreamBufBase::~StreamBufBase() throw() {} +    StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {}      IContext::~IContext() {}      IResultCapture::~IResultCapture() {}      ITestCase::~ITestCase() {} @@ -7632,6 +8685,7 @@ namespace Catch {      StreamingReporterBase::~StreamingReporterBase() {}      ConsoleReporter::~ConsoleReporter() {} +    CompactReporter::~CompactReporter() {}      IRunner::~IRunner() {}      IMutableContext::~IMutableContext() {}      IConfig::~IConfig() {} @@ -7641,9 +8695,6 @@ namespace Catch {      FreeFunctionTestCase::~FreeFunctionTestCase() {}      IGeneratorInfo::~IGeneratorInfo() {}      IGeneratorsForTest::~IGeneratorsForTest() {} -    TagParser::~TagParser() {} -    TagExtracter::~TagExtracter() {} -    TagExpressionParser::~TagExpressionParser() {}      Matchers::Impl::StdString::Equals::~Equals() {}      Matchers::Impl::StdString::Contains::~Contains() {} @@ -7694,6 +8745,10 @@ int main (int argc, char * const argv[]) {  #endif +#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED +#  undef CLARA_CONFIG_MAIN +#endif +  //////  // If this config identifier is defined then all CATCH macros are prefixed with CATCH_ @@ -7720,9 +8775,7 @@ int main (int argc, char * const argv[]) {  #define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" )  #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) -#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN" ) -#define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL" ) -#define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED" ) +#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg )  #define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )  #define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )  #define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) @@ -7732,11 +8785,15 @@ int main (int argc, char * const argv[]) {      #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )      #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )      #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) +    #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ ) +    #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ )  #else      #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )      #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )      #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )      #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) +    #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg ) +    #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg )  #endif  #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) @@ -7781,9 +8838,7 @@ int main (int argc, char * const argv[]) {  #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" )  #define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) -#define WARN( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN" ) -#define FAIL( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL" ) -#define SUCCEED( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED" ) +#define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg )  #define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )  #define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )  #define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) @@ -7793,11 +8848,15 @@ int main (int argc, char * const argv[]) {      #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )      #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )      #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) +    #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ ) +    #define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ )  #else      #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )      #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )      #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )      #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) +    #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg ) +    #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg )  #endif  #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) | 
