mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-10-31 12:17:11 +01:00 
			
		
		
		
	Re-org
This commit is contained in:
		
							
								
								
									
										785
									
								
								include/internal/catch_capture.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										785
									
								
								include/internal/catch_capture.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,785 @@ | ||||
| /* | ||||
|  *  catch_capture.hpp | ||||
|  *  Catch | ||||
|  * | ||||
|  *  Created by Phil on 18/10/2010. | ||||
|  *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved. | ||||
|  * | ||||
|  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||
|  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||
|  * | ||||
|  */ | ||||
| #ifndef TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED | ||||
| #define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED | ||||
|  | ||||
| #include "catch_resultinfo.hpp" | ||||
| #include "catch_result_type.h" | ||||
| #include "catch_interfaces_capture.h" | ||||
| #include "catch_debugger.hpp" | ||||
| #include "catch_evaluate.hpp" | ||||
| #include <sstream> | ||||
| #include <cmath> | ||||
|  | ||||
| namespace Catch | ||||
| { | ||||
| namespace Detail | ||||
| { | ||||
|     // The following code, contributed by Sam Partington, allows us to choose an implementation | ||||
|     // of toString() depending on whether a << overload is available | ||||
|      | ||||
|     struct NonStreamable | ||||
|     { | ||||
|         // allow construction from anything... | ||||
|         template<typename Anything>  | ||||
|         NonStreamable(Anything) | ||||
|         {} | ||||
|     }; | ||||
|      | ||||
|     // a local operator<<  which may be called if there isn't a better one elsewhere... | ||||
|     inline NonStreamable operator << ( std::ostream&, const NonStreamable& ns ) | ||||
|     { | ||||
|         return ns; | ||||
|     } | ||||
|  | ||||
|     template<typename T> | ||||
|     struct IsStreamable | ||||
|     { | ||||
|         static NoType Deduce( const NonStreamable& ); | ||||
|         static YesType Deduce( std::ostream& ); | ||||
|  | ||||
|         enum | ||||
|         { | ||||
|             value = sizeof( Deduce( Synth<std::ostream&>() << Synth<const T&>() ) )  | ||||
|                         == sizeof( YesType ) | ||||
|         }; | ||||
|     }; | ||||
|      | ||||
|     // << is available, so use it with ostringstream to make the string | ||||
|     template<typename T, bool streamable> | ||||
|     struct StringMaker | ||||
|     { | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         static std::string apply | ||||
|         ( | ||||
|             const T& value | ||||
|         ) | ||||
|         { | ||||
|             std::ostringstream oss; | ||||
|             oss << value; | ||||
|             return oss.str(); | ||||
|         } | ||||
|     }; | ||||
|        | ||||
|     // << not available - use a default string | ||||
|     template<typename T> | ||||
|     struct StringMaker<T, false> | ||||
|     { | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         static std::string apply | ||||
|         ( | ||||
|             const T& | ||||
|         ) | ||||
|         { | ||||
|             return "{?}"; | ||||
|         } | ||||
|     }; | ||||
|  | ||||
| }// end namespace Detail | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| template<typename T> | ||||
| std::string toString | ||||
| ( | ||||
|     const T& value | ||||
| ) | ||||
| { | ||||
|     return Detail::StringMaker<T, Detail::IsStreamable<T>::value>::apply( value ); | ||||
| } | ||||
|      | ||||
| // Shortcut overloads | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| inline std::string toString | ||||
| ( | ||||
|     const std::string& value | ||||
| ) | ||||
| { | ||||
|     return "\"" + value + "\""; | ||||
| } | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| inline std::string toString | ||||
| ( | ||||
|     const std::wstring& 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* const>( value ) ); | ||||
| }         | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| inline std::string toString | ||||
| ( | ||||
|     int value | ||||
| ) | ||||
| { | ||||
|     std::ostringstream oss; | ||||
|     oss << value; | ||||
|     return oss.str(); | ||||
| } | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| inline std::string toString | ||||
| ( | ||||
|     unsigned int value | ||||
| ) | ||||
| { | ||||
|     std::ostringstream oss; | ||||
|     if( value > 8192 ) | ||||
|         oss << "0x" << std::hex << value; | ||||
|     else | ||||
|         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 | ||||
| ( | ||||
|     const double value  | ||||
| ) | ||||
| { | ||||
|     std::ostringstream oss; | ||||
|     oss << value; | ||||
|     return oss.str(); | ||||
| }     | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| inline std::string toString | ||||
| ( | ||||
|     bool value | ||||
| ) | ||||
| { | ||||
|     return value ? "true" : "false"; | ||||
| } | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| inline std::string toString | ||||
| ( | ||||
|     void* p | ||||
| ) | ||||
| { | ||||
|     if( !p ) | ||||
|         return INTERNAL_CATCH_STRINGIFY( NULL ); | ||||
|     std::ostringstream oss; | ||||
|     oss << p; | ||||
|     return oss.str(); | ||||
| } | ||||
|      | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| template<typename T> | ||||
| inline std::string toString | ||||
| ( | ||||
|     T* p | ||||
| ) | ||||
| { | ||||
|     return Catch::toString( static_cast<void*>( p ) ); | ||||
| } | ||||
|      | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| template<typename T> | ||||
| inline std::string toString | ||||
| ( | ||||
|     const T* p | ||||
| ) | ||||
| { | ||||
|     return Catch::toString( static_cast<void*>( const_cast<T*>( p ) ) ); | ||||
| } | ||||
|      | ||||
| struct TestFailureException | ||||
| { | ||||
| }; | ||||
| struct DummyExceptionType_DontUse | ||||
| { | ||||
| }; | ||||
| struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison; | ||||
|      | ||||
| class MutableResultInfo : public ResultInfo | ||||
| { | ||||
| public: | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     MutableResultInfo | ||||
|     () | ||||
|     {} | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     MutableResultInfo | ||||
|     ( | ||||
|         const char* expr,  | ||||
|         bool isNot,  | ||||
|         const char* filename,  | ||||
|         std::size_t line,  | ||||
|         const char* macroName, | ||||
|         const char* message = "" | ||||
|     ) | ||||
|     : ResultInfo( expr, ResultWas::Unknown, isNot, filename, line, macroName, message ) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     void setResultType | ||||
|     ( | ||||
|         ResultWas::OfType result | ||||
|     ) | ||||
|     { | ||||
|         // Flip bool results if isNot is set | ||||
|         if( m_isNot && result == ResultWas::Ok ) | ||||
|             m_result = ResultWas::ExpressionFailed; | ||||
|         else if( m_isNot && result == ResultWas::ExpressionFailed ) | ||||
|             m_result = ResultWas::Ok; | ||||
|         else | ||||
|             m_result = result;         | ||||
|     } | ||||
|  | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     void setMessage | ||||
|     ( | ||||
|         const std::string& message | ||||
|     ) | ||||
|     { | ||||
|         m_message = message; | ||||
|     } | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     void setFileAndLine | ||||
|     ( | ||||
|         const std::string& filename, | ||||
|         std::size_t line | ||||
|     ) | ||||
|     { | ||||
|         m_filename = filename; | ||||
|         m_line = line; | ||||
|     } | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     template<typename RhsT> | ||||
|     STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || | ||||
|     ( | ||||
|         const RhsT& | ||||
|     ); | ||||
|  | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     template<typename RhsT> | ||||
|     STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && | ||||
|     ( | ||||
|         const RhsT& | ||||
|     ); | ||||
|      | ||||
| private: | ||||
|     friend class ResultBuilder; | ||||
|     template<typename T> friend class Expression; | ||||
|  | ||||
|     template<typename T> friend class PtrExpression; | ||||
|  | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     MutableResultInfo& captureBoolExpression | ||||
|     ( | ||||
|         bool result | ||||
|     ) | ||||
|     { | ||||
|         m_lhs = Catch::toString( result ); | ||||
|         m_op = m_isNot ? "!" : ""; | ||||
|         setResultType( result ? ResultWas::Ok : ResultWas::ExpressionFailed ); | ||||
|         return *this; | ||||
|     }     | ||||
|  | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     template<Internal::Operator Op, typename T1, typename T2>     | ||||
|     MutableResultInfo& captureExpression | ||||
|     ( | ||||
|         const T1& lhs,  | ||||
|         const T2& rhs | ||||
|     ) | ||||
|     { | ||||
|         setResultType( Internal::compare<Op>( lhs, rhs ) ? ResultWas::Ok : ResultWas::ExpressionFailed ); | ||||
|         m_lhs = Catch::toString( lhs ); | ||||
|         m_rhs = Catch::toString( rhs ); | ||||
|         m_op = Internal::OperatorTraits<Op>::getName(); | ||||
|         return *this; | ||||
|     } | ||||
|      | ||||
| }; | ||||
|  | ||||
| template<typename T> | ||||
| class Expression | ||||
| { | ||||
| 	void operator = ( const Expression& ); | ||||
|  | ||||
| public: | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     Expression | ||||
|     ( | ||||
|         MutableResultInfo& result,  | ||||
|         const T& lhs  | ||||
|     ) | ||||
|     :   m_result( result ), | ||||
|         m_lhs( lhs ) | ||||
|     { | ||||
|     } | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     template<typename RhsT> | ||||
|     MutableResultInfo& operator ==  | ||||
|     ( | ||||
|         const RhsT& rhs | ||||
|     ) | ||||
|     { | ||||
|         return m_result.captureExpression<Internal::IsEqualTo>( m_lhs, rhs ); | ||||
|     } | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     template<typename RhsT> | ||||
|     MutableResultInfo& operator !=  | ||||
|     ( | ||||
|         const RhsT& rhs | ||||
|     ) | ||||
|     { | ||||
|         return m_result.captureExpression<Internal::IsNotEqualTo>( m_lhs, rhs ); | ||||
|     } | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     template<typename RhsT> | ||||
|     MutableResultInfo& operator < | ||||
|     ( | ||||
|         const RhsT& rhs | ||||
|     ) | ||||
|     { | ||||
|         return m_result.captureExpression<Internal::IsLessThan>( m_lhs, rhs ); | ||||
|     } | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     template<typename RhsT> | ||||
|     MutableResultInfo& operator > | ||||
|     ( | ||||
|         const RhsT& rhs | ||||
|     ) | ||||
|     { | ||||
|         return m_result.captureExpression<Internal::IsGreaterThan>( m_lhs, rhs ); | ||||
|     } | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     template<typename RhsT> | ||||
|     MutableResultInfo& operator <=  | ||||
|     ( | ||||
|         const RhsT& rhs | ||||
|     ) | ||||
|     { | ||||
|         return m_result.captureExpression<Internal::IsLessThanOrEqualTo>( m_lhs, rhs ); | ||||
|     } | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     template<typename RhsT> | ||||
|     MutableResultInfo& operator >=  | ||||
|     ( | ||||
|         const RhsT& rhs | ||||
|     ) | ||||
|     { | ||||
|         return m_result.captureExpression<Internal::IsGreaterThanOrEqualTo>( m_lhs, rhs ); | ||||
|     } | ||||
|  | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     operator MutableResultInfo& | ||||
|     () | ||||
|     { | ||||
|         return m_result.captureBoolExpression( m_lhs ); | ||||
|     } | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     template<typename RhsT> | ||||
|     STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + | ||||
|     ( | ||||
|         const RhsT& | ||||
|     ); | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     template<typename RhsT> | ||||
|     STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - | ||||
|     ( | ||||
|         const RhsT& | ||||
|     ); | ||||
|  | ||||
| private: | ||||
|     MutableResultInfo& m_result; | ||||
|     const T& m_lhs; | ||||
| }; | ||||
|      | ||||
| template<typename LhsT>  | ||||
| class PtrExpression | ||||
| { | ||||
| public: | ||||
|  | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     PtrExpression | ||||
|     ( | ||||
|         MutableResultInfo& result,  | ||||
|         const LhsT* lhs  | ||||
|     ) | ||||
|     :   m_result( &result ), | ||||
|         m_lhs( lhs ) | ||||
|     {} | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     template<typename RhsT> | ||||
|     MutableResultInfo& operator ==  | ||||
|     ( | ||||
|         const RhsT* rhs | ||||
|     ) | ||||
|     { | ||||
|         return m_result->captureExpression<Internal::IsEqualTo>( m_lhs, rhs ); | ||||
|     } | ||||
|  | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     // This catches NULL | ||||
|     MutableResultInfo& operator ==  | ||||
|     ( | ||||
|         LhsT* rhs | ||||
|     ) | ||||
|     { | ||||
|         return m_result->captureExpression<Internal::IsEqualTo>( m_lhs, rhs ); | ||||
|     } | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     template<typename RhsT> | ||||
|     MutableResultInfo& operator !=  | ||||
|     ( | ||||
|         const RhsT* rhs | ||||
|     ) | ||||
|     { | ||||
|         return m_result->captureExpression<Internal::IsNotEqualTo>( m_lhs, rhs ); | ||||
|     } | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     // This catches NULL | ||||
|     MutableResultInfo& operator !=  | ||||
|     ( | ||||
|         LhsT* rhs | ||||
|     ) | ||||
|     { | ||||
|         return m_result->captureExpression<Internal::IsNotEqualTo>( m_lhs, rhs ); | ||||
|     } | ||||
|  | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     operator MutableResultInfo& | ||||
|     () | ||||
|     { | ||||
|         return m_result->captureBoolExpression( (bool)m_lhs ); | ||||
|     } | ||||
|      | ||||
|      | ||||
| private: | ||||
|     MutableResultInfo* m_result; | ||||
|     const LhsT* m_lhs; | ||||
| }; | ||||
|      | ||||
| class ResultBuilder | ||||
| { | ||||
| public: | ||||
|  | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     ResultBuilder | ||||
|     ( | ||||
|         const char* filename,  | ||||
|         std::size_t line,  | ||||
|         const char* macroName, | ||||
|         const char* expr = "", | ||||
|         bool isNot = false | ||||
|     ) | ||||
|     : m_result( expr, isNot, filename, line, macroName ) | ||||
|     {} | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     template<typename T> | ||||
|     Expression<T> operator->* | ||||
|     ( | ||||
|         const T & operand | ||||
|     ) | ||||
|     { | ||||
|         Expression<T> expr( m_result, operand ); | ||||
|          | ||||
|         return expr; | ||||
|     } | ||||
|  | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     template<typename T> | ||||
|     PtrExpression<T> operator->* | ||||
|     ( | ||||
|         const T* operand | ||||
|     ) | ||||
|     { | ||||
|         PtrExpression<T> expr( m_result, operand ); | ||||
|          | ||||
|         return expr; | ||||
|     } | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     template<typename T> | ||||
|     PtrExpression<T> operator->* | ||||
|     ( | ||||
|         T* operand | ||||
|     ) | ||||
|     { | ||||
|         PtrExpression<T> expr( m_result, operand ); | ||||
|          | ||||
|         return expr; | ||||
|     } | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     template<typename T> | ||||
|     ResultBuilder& operator << | ||||
|     ( | ||||
|         const T & value | ||||
|     ) | ||||
|     { | ||||
|         m_messageStream << value; | ||||
|         return *this; | ||||
|     } | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     ResultBuilder& setResultType | ||||
|     ( | ||||
|         ResultWas::OfType resultType | ||||
|     ) | ||||
|     { | ||||
|         m_result.setResultType( resultType ); | ||||
|         return *this; | ||||
|     } | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     operator MutableResultInfo& | ||||
|     () | ||||
|     { | ||||
|         m_result.setMessage( m_messageStream.str() ); | ||||
|         return m_result; | ||||
|     } | ||||
|      | ||||
| private: | ||||
|     MutableResultInfo m_result; | ||||
|     std::ostringstream m_messageStream; | ||||
|      | ||||
| }; | ||||
|  | ||||
| class ScopedInfo | ||||
| { | ||||
| public: | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     ScopedInfo | ||||
|     () | ||||
|     { | ||||
|         Hub::getResultCapture().pushScopedInfo( this ); | ||||
|     } | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     ~ScopedInfo | ||||
|     () | ||||
|     { | ||||
|         Hub::getResultCapture().popScopedInfo( this ); | ||||
|     } | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     ScopedInfo& operator <<  | ||||
|     ( | ||||
|         const char* str | ||||
|     ) | ||||
|     { | ||||
|         m_oss << str; | ||||
|         return *this;  | ||||
|     } | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     std::string getInfo | ||||
|     () | ||||
|     const | ||||
|     { | ||||
|         return m_oss.str(); | ||||
|     } | ||||
|      | ||||
| private: | ||||
|     std::ostringstream m_oss; | ||||
| }; | ||||
|      | ||||
|      | ||||
| // !TBD Need to clean this all up | ||||
| #define CATCH_absTol 1e-10 | ||||
| #define CATCH_relTol 1e-10 | ||||
|  | ||||
| inline double catch_max( double x, double y ) | ||||
| { | ||||
|     return x > y ? x : y; | ||||
| } | ||||
| namespace Detail | ||||
| { | ||||
|     class Approx | ||||
|     { | ||||
|     public: | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         // !TBD more generic | ||||
|         explicit Approx | ||||
|         ( | ||||
|             double d | ||||
|         ) | ||||
|         : m_d( d ) | ||||
|         { | ||||
|         } | ||||
|  | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         template<typename T> | ||||
|         friend bool operator ==  | ||||
|         ( | ||||
|             const T& lhs,  | ||||
|             const Approx& rhs | ||||
|         ) | ||||
|         { | ||||
|             // !TBD Use proper tolerance | ||||
|             // From: http://realtimecollisiondetection.net/blog/?p=89 | ||||
|             // see also: http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm | ||||
|             return fabs( lhs - rhs.m_d ) <= catch_max( CATCH_absTol, CATCH_relTol * catch_max( fabs(lhs), fabs(rhs.m_d) ) ); | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         template<typename T> | ||||
|         friend bool operator !=  | ||||
|         ( | ||||
|             const T& lhs,  | ||||
|             const Approx& rhs | ||||
|         ) | ||||
|         { | ||||
|             return ! operator==( lhs, rhs ); | ||||
|         } | ||||
|          | ||||
|         double m_d; | ||||
|     }; | ||||
| } | ||||
|      | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| template<> | ||||
|     inline std::string toString<Detail::Approx> | ||||
| ( | ||||
|     const Detail::Approx& value | ||||
| ) | ||||
| { | ||||
|     std::ostringstream oss; | ||||
|     oss << "Approx( " << value.m_d << ")"; | ||||
|     return oss.str(); | ||||
| } | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| // This is just here to avoid compiler warnings with macro constants | ||||
| inline bool isTrue | ||||
| ( | ||||
|     bool value | ||||
| ) | ||||
| { | ||||
|     return value; | ||||
| } | ||||
|      | ||||
| } // end namespace Catch | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| #define INTERNAL_CATCH_ACCEPT_EXPR( expr, stopOnFailure ) \ | ||||
|     if( Catch::ResultAction::Value action = Catch::Hub::getResultCapture().acceptExpression( expr )  ) \ | ||||
|     { \ | ||||
|         if( action == Catch::ResultAction::DebugFailed ) BreakIntoDebugger(); \ | ||||
|         if( Catch::isTrue( stopOnFailure ) ) throw Catch::TestFailureException(); \ | ||||
|     } | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| #define INTERNAL_CATCH_TEST( expr, isNot, stopOnFailure, macroName ) \ | ||||
|     INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ResultBuilder( __FILE__, __LINE__, macroName, #expr, isNot )->*expr ), stopOnFailure ); \ | ||||
|     if( Catch::isTrue( false ) ){ bool dummyResult = ( expr ); Catch::isTrue( dummyResult ); } | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| #define INTERNAL_CATCH_NO_THROW( expr, stopOnFailure, macroName ) \ | ||||
|     try \ | ||||
|     { \ | ||||
|         expr; \ | ||||
|         INTERNAL_CATCH_ACCEPT_EXPR( Catch::ResultBuilder( __FILE__, __LINE__, macroName, #expr ).setResultType( Catch::ResultWas::Ok ), stopOnFailure ); \ | ||||
|     } \ | ||||
|     catch( std::exception& ex ) \ | ||||
|     { \ | ||||
|         INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ResultBuilder( __FILE__, __LINE__, macroName, #expr ) << ex.what() ).setResultType( Catch::ResultWas::ThrewException ), stopOnFailure ); \ | ||||
|     } \ | ||||
|     catch( ... ) \ | ||||
|     { \ | ||||
|         INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ResultBuilder( __FILE__, __LINE__, macroName, #expr ) << Catch::Hub::getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), stopOnFailure ); \ | ||||
|     } | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| #define INTERNAL_CATCH_THROWS( expr, exceptionType, stopOnFailure, macroName ) \ | ||||
|     try \ | ||||
|     { \ | ||||
|         expr; \ | ||||
|         INTERNAL_CATCH_ACCEPT_EXPR( Catch::ResultBuilder( __FILE__, __LINE__, macroName, #expr ).setResultType( Catch::ResultWas::DidntThrowException ), stopOnFailure ); \ | ||||
|     } \ | ||||
|     catch( Catch::TestFailureException& ) \ | ||||
|     { \ | ||||
|         throw; \ | ||||
|     } \ | ||||
|     catch( exceptionType ) \ | ||||
|     { \ | ||||
|         INTERNAL_CATCH_ACCEPT_EXPR( Catch::ResultBuilder( __FILE__, __LINE__, macroName, #expr ).setResultType( Catch::ResultWas::Ok ), stopOnFailure ); \ | ||||
|     } | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| #define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, stopOnFailure, macroName ) \ | ||||
|     INTERNAL_CATCH_THROWS( expr, exceptionType, stopOnFailure, macroName ) \ | ||||
|     catch( ... ) \ | ||||
|     { \ | ||||
|         INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ResultBuilder( __FILE__, __LINE__, macroName, #expr ) << Catch::Hub::getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), stopOnFailure ); \ | ||||
|     } | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| #define INTERNAL_CATCH_MSG( reason, resultType, stopOnFailure, macroName ) \ | ||||
|     Catch::Hub::getResultCapture().acceptExpression( ( Catch::ResultBuilder( __FILE__, __LINE__, macroName ) << reason ).setResultType( resultType ) ); | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| #define INTERNAL_CATCH_SCOPED_INFO( log ) \ | ||||
|     Catch::ScopedInfo INTERNAL_CATCH_UNIQUE_NAME( info ); \ | ||||
|     INTERNAL_CATCH_UNIQUE_NAME( info ) << log | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED | ||||
							
								
								
									
										225
									
								
								include/internal/catch_commandline.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										225
									
								
								include/internal/catch_commandline.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,225 @@ | ||||
| /* | ||||
|  *  catch_commandline.hpp | ||||
|  *  Catch | ||||
|  * | ||||
|  *  Created by Phil on 02/11/2010. | ||||
|  *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved. | ||||
|  * | ||||
|  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||
|  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #ifndef TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED | ||||
| #define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED | ||||
|  | ||||
| #include "catch_config.hpp" | ||||
| #include "catch_runner_impl.hpp" | ||||
|  | ||||
| namespace Catch | ||||
| { | ||||
|     // !TBD: This could be refactored to be more "declarative" | ||||
|     //       have a table up front that relates the mode, option strings, # arguments, names of arguments | ||||
|     //       - may not be worth it at this scale | ||||
|      | ||||
|     // -l, --list tests [xml] lists available tests (optionally in xml) | ||||
|     // -l, --list reporters [xml] lists available reports (optionally in xml) | ||||
|     // -l, --list all [xml] lists available tests and reports (optionally in xml) | ||||
|     // -t, --test "testspec" ["testspec", ...] | ||||
|     // -r, --reporter <type> | ||||
|     // -o, --out filename to write to | ||||
|     // -s, --success report successful cases too | ||||
|     // -b, --break breaks into debugger on test failure | ||||
|     // -n, --name specifies an optional name for the test run | ||||
| 	class ArgParser : NonCopyable | ||||
|     { | ||||
|         enum Mode | ||||
|         { | ||||
|             modeNone, | ||||
|             modeList, | ||||
|             modeTest, | ||||
|             modeReport, | ||||
|             modeOutput, | ||||
|             modeSuccess, | ||||
|             modeBreak, | ||||
|             modeName, | ||||
|             modeHelp, | ||||
|  | ||||
|             modeError | ||||
|         }; | ||||
|          | ||||
|     public: | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         ArgParser | ||||
|         ( | ||||
|             int argc,  | ||||
|             char * const argv[],  | ||||
|             Config& config | ||||
|         ) | ||||
|         :   m_mode( modeNone ), | ||||
|             m_config( config ) | ||||
|         { | ||||
|             for( int i=1; i < argc; ++i ) | ||||
|             { | ||||
|                 if( argv[i][0] == '-' ) | ||||
|                 { | ||||
|                     std::string cmd = ( argv[i] ); | ||||
|                     if( cmd == "-l" || cmd == "--list" ) | ||||
|                         changeMode( cmd, modeList ); | ||||
|                     else if( cmd == "-t" || cmd == "--test" ) | ||||
|                         changeMode( cmd, modeTest ); | ||||
|                     else if( cmd == "-r" || cmd == "--reporter" ) | ||||
|                         changeMode( cmd, modeReport ); | ||||
|                     else if( cmd == "-o" || cmd == "--out" ) | ||||
|                         changeMode( cmd, modeOutput ); | ||||
|                     else if( cmd == "-s" || cmd == "--success" ) | ||||
|                         changeMode( cmd, modeSuccess ); | ||||
|                     else if( cmd == "-b" || cmd == "--break" ) | ||||
|                         changeMode( cmd, modeBreak ); | ||||
|                     else if( cmd == "-n" || cmd == "--name" ) | ||||
|                         changeMode( cmd, modeName ); | ||||
|                     else if( cmd == "-h" || cmd == "-?" || cmd == "--help" ) | ||||
|                         changeMode( cmd, modeHelp ); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     m_args.push_back( argv[i] ); | ||||
|                 } | ||||
|                 if( m_mode == modeError ) | ||||
|                     return; | ||||
|             } | ||||
|             changeMode( "", modeNone );             | ||||
|         } | ||||
|          | ||||
|     private: | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         std::string argsAsString | ||||
|         () | ||||
|         { | ||||
|             std::ostringstream oss; | ||||
|             std::vector<std::string>::const_iterator it = m_args.begin(); | ||||
|             std::vector<std::string>::const_iterator itEnd = m_args.end(); | ||||
|             for( bool first = true; it != itEnd; ++it, first = false ) | ||||
|             { | ||||
|                 if( !first ) | ||||
|                     oss << " "; | ||||
|                 oss << *it; | ||||
|             } | ||||
|             return oss.str(); | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         void changeMode | ||||
|         ( | ||||
|             const std::string& cmd,  | ||||
|             Mode mode | ||||
|         ) | ||||
|         { | ||||
|             m_command = cmd; | ||||
|             switch( m_mode ) | ||||
|             { | ||||
|                 case modeNone: | ||||
|                     if( m_args.size() > 0 ) | ||||
|                         return setErrorMode( "Unexpected arguments before " + m_command + ": " + argsAsString() ); | ||||
|                     break; | ||||
|                 case modeList: | ||||
|                     if( m_args.size() > 2 ) | ||||
|                     { | ||||
|                         return setErrorMode( m_command + " expected upto 2 arguments but recieved: " + argsAsString() ); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         Config::List::What listSpec = Config::List::All; | ||||
|                         if( m_args.size() >= 1 ) | ||||
|                         { | ||||
|                             if( m_args[0] == "tests" ) | ||||
|                                 listSpec = Config::List::Tests; | ||||
|                             else if( m_args[0] == "reporters" ) | ||||
|                                 listSpec = Config::List::Reports; | ||||
|                             else | ||||
|                                 return setErrorMode( m_command + " expected [tests] or [reporters] but recieved: [" + m_args[0] + "]" );                         | ||||
|                         } | ||||
|                         if( m_args.size() >= 2 ) | ||||
|                         { | ||||
|                             if( m_args[1] == "xml" ) | ||||
|                                 listSpec = static_cast<Config::List::What>( listSpec | Config::List::AsXml ); | ||||
|                             else if( m_args[1] == "text" ) | ||||
|                                 listSpec = static_cast<Config::List::What>( listSpec | Config::List::AsText ); | ||||
|                             else | ||||
|                                 return setErrorMode( m_command + " expected [xml] or [text] but recieved: [" + m_args[1] + "]" );                         | ||||
|                         } | ||||
|                         m_config.setListSpec( static_cast<Config::List::What>( m_config.getListSpec() | listSpec ) ); | ||||
|                     } | ||||
|                     break; | ||||
|                 case modeTest: | ||||
|                     if( m_args.size() == 0 )                         | ||||
|                         return setErrorMode( m_command + " expected at least 1 argument but recieved none" ); | ||||
|                     { | ||||
|                         std::vector<std::string>::const_iterator it = m_args.begin(); | ||||
|                         std::vector<std::string>::const_iterator itEnd = m_args.end(); | ||||
|                         for(; it != itEnd; ++it ) | ||||
|                             m_config.addTestSpec( *it ); | ||||
|                     } | ||||
|                     break; | ||||
|                 case modeReport: | ||||
|                     if( m_args.size() != 1 ) | ||||
|                         return setErrorMode( m_command + " expected one argument, recieved: " +  argsAsString() ); | ||||
|                     m_config.setReporter( m_args[0] ); | ||||
|                     break; | ||||
|                 case modeOutput: | ||||
|                     if( m_args.size() == 0 ) | ||||
|                         return setErrorMode( m_command + " expected filename" ); | ||||
|                     if( m_args[0][0] == '%' ) | ||||
|                         m_config.useStream( m_args[0].substr( 1 ) ); | ||||
|                     else | ||||
|                         m_config.setFilename( m_args[0] ); | ||||
|                     break; | ||||
|                 case modeSuccess: | ||||
|                     if( m_args.size() != 0 ) | ||||
|                         return setErrorMode( m_command + " does not accept arguments" ); | ||||
|                     m_config.setIncludeWhat( Config::Include::SuccessfulResults ); | ||||
|                     break; | ||||
|                 case modeBreak: | ||||
|                     if( m_args.size() != 0 ) | ||||
|                         return setErrorMode( m_command + " does not accept arguments" ); | ||||
|                     m_config.setShouldDebugBreak( true ); | ||||
|                 case modeName: | ||||
|                     if( m_args.size() != 1 ) | ||||
|                         return setErrorMode( m_command + " requires exactly one argument (a name)" ); | ||||
|                     m_config.setName( m_args[0] ); | ||||
|                     break; | ||||
|                 case modeHelp: | ||||
|                     if( m_args.size() != 0 ) | ||||
|                         return setErrorMode( m_command + " does not accept arguments" ); | ||||
|                     m_config.setShowHelp( true ); | ||||
|                     break; | ||||
|                 default: | ||||
|                 break; | ||||
|             } | ||||
|             m_args.clear(); | ||||
|             m_mode = mode; | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         void setErrorMode | ||||
|         ( | ||||
|             const std::string& errorMessage | ||||
|         ) | ||||
|         { | ||||
|             m_mode = modeError; | ||||
|             m_command = ""; | ||||
|             m_config.setError( errorMessage ); | ||||
|         } | ||||
|          | ||||
|     private: | ||||
|          | ||||
|         Mode m_mode; | ||||
|         std::string m_command; | ||||
|         std::vector<std::string> m_args; | ||||
|         Config& m_config; | ||||
|     }; | ||||
|      | ||||
|      | ||||
| } // end namespace Catch | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED | ||||
							
								
								
									
										94
									
								
								include/internal/catch_common.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								include/internal/catch_common.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,94 @@ | ||||
| /* | ||||
|  *  catch_common.h | ||||
|  *  Catch | ||||
|  * | ||||
|  *  Created by Phil on 29/10/2010. | ||||
|  *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved. | ||||
|  * | ||||
|  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||
|  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #ifndef TWOBLUECUBES_CATCH_COMMON_H_INCLUDED | ||||
| #define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED | ||||
|  | ||||
| #define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line | ||||
| #define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) | ||||
| #define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) | ||||
|  | ||||
| #define INTERNAL_CATCH_STRINGIFY2( expr ) #expr | ||||
| #define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr ) | ||||
|  | ||||
| #ifdef __GNUC__ | ||||
| #define ATTRIBUTE_NORETURN __attribute__ ((noreturn)) | ||||
| #else | ||||
| #define ATTRIBUTE_NORETURN | ||||
| #endif | ||||
|  | ||||
| #include <sstream> | ||||
| #include <stdexcept> | ||||
| #include <algorithm> | ||||
|  | ||||
| namespace Catch | ||||
| { | ||||
| 	class NonCopyable | ||||
| 	{ | ||||
| 		NonCopyable( const NonCopyable& ); | ||||
| 		void operator = ( const NonCopyable& ); | ||||
| 	protected: | ||||
| 		NonCopyable(){} | ||||
| 	}; | ||||
|      | ||||
|     typedef char NoType; | ||||
|     typedef int YesType; | ||||
|  | ||||
|     // create a T for use in sizeof expressions | ||||
|     template<typename T> T Synth(); | ||||
|  | ||||
|     template<typename ContainerT> | ||||
|     inline void deleteAll( ContainerT& container ) | ||||
|     { | ||||
|         typename ContainerT::const_iterator it = container.begin(); | ||||
|         typename ContainerT::const_iterator itEnd = container.end(); | ||||
|         for(; it != itEnd; ++it ) | ||||
|         { | ||||
|             delete *it; | ||||
|         } | ||||
|     } | ||||
|     template<typename AssociativeContainerT> | ||||
|     inline void deleteAllValues( AssociativeContainerT& container ) | ||||
|     { | ||||
|         typename AssociativeContainerT::const_iterator it = container.begin(); | ||||
|         typename AssociativeContainerT::const_iterator itEnd = container.end(); | ||||
|         for(; it != itEnd; ++it ) | ||||
|         { | ||||
|             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( const ContainerT& container, Function function ) | ||||
|     { | ||||
|         std::for_each( container.begin(), container.end(), function ); | ||||
|     } | ||||
|      | ||||
|     ATTRIBUTE_NORETURN | ||||
|     inline void throwLogicError( const std::string& message, const std::string& file, long line ) | ||||
|     { | ||||
|         std::ostringstream oss; | ||||
|         oss << "Internal Catch error: '" << message << "' at: " << file << "(" << line << ")"; | ||||
|         throw std::logic_error( oss.str() ); | ||||
|     } | ||||
| } | ||||
|  | ||||
| #define CATCH_INTERNAL_ERROR( msg ) throwLogicError( msg, __FILE__, __LINE__ ); | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_COMMON_H_INCLUDED | ||||
|  | ||||
							
								
								
									
										250
									
								
								include/internal/catch_config.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										250
									
								
								include/internal/catch_config.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,250 @@ | ||||
| /* | ||||
|  *  catch_config.hpp | ||||
|  *  Catch | ||||
|  * | ||||
|  *  Created by Phil on 08/11/2010. | ||||
|  *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved. | ||||
|  * | ||||
|  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||
|  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #ifndef TWOBLUECUBES_CATCH_RUNNERCONFIG_HPP_INCLUDED | ||||
| #define TWOBLUECUBES_CATCH_RUNNERCONFIG_HPP_INCLUDED | ||||
|  | ||||
| #include "catch_interfaces_reporter.h" | ||||
| #include "catch_hub.h" | ||||
|  | ||||
| #include <memory> | ||||
| #include <vector> | ||||
| #include <string> | ||||
| #include <iostream> | ||||
|  | ||||
| namespace Catch | ||||
| { | ||||
|      | ||||
|     class Config : public IReporterConfig | ||||
|     { | ||||
|     private: | ||||
|         Config( const Config& other ); | ||||
|         Config& operator = ( const Config& other ); | ||||
|     public: | ||||
|          | ||||
|         struct Include { enum What | ||||
|         { | ||||
|             FailedOnly,  | ||||
|             SuccessfulResults | ||||
|         }; }; | ||||
|  | ||||
|         struct List{ enum What | ||||
|         { | ||||
|             None = 0, | ||||
|              | ||||
|             Reports = 1, | ||||
|             Tests = 2, | ||||
|             All = 3, | ||||
|              | ||||
|             WhatMask = 0xf, | ||||
|              | ||||
|             AsText = 0x10, | ||||
|             AsXml = 0x11, | ||||
|              | ||||
|             AsMask = 0xf0 | ||||
|         }; }; | ||||
|          | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         Config() | ||||
|         :   m_reporter( NULL ), | ||||
|             m_listSpec( List::None ), | ||||
|             m_shouldDebugBreak( false ), | ||||
|             m_showHelp( false ), | ||||
|             m_streambuf( std::cout.rdbuf() ), | ||||
|             m_os( m_streambuf ), | ||||
|             m_includeWhat( Include::FailedOnly ) | ||||
|         {} | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         ~Config() | ||||
|         { | ||||
|             setStreamBuf( NULL ); | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         void setReporter( const std::string& reporterName ) | ||||
|         { | ||||
|             if( m_reporter.get() ) | ||||
|                 return setError( "Only one reporter may be specified" ); | ||||
|             setReporter( Hub::getReporterRegistry().create( reporterName, *this ) ); | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         void addTestSpec( const std::string& testSpec ) | ||||
|         { | ||||
|             m_testSpecs.push_back( testSpec ); | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         bool testsSpecified() const | ||||
|         { | ||||
|             return !m_testSpecs.empty(); | ||||
|         } | ||||
|  | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         const std::vector<std::string>& getTestSpecs() const | ||||
|         { | ||||
|             return m_testSpecs; | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         List::What getListSpec( void ) const | ||||
|         { | ||||
|             return m_listSpec; | ||||
|         } | ||||
|  | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         void setListSpec( List::What listSpec ) | ||||
|         { | ||||
|             m_listSpec = listSpec; | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         void setFilename( const std::string& filename ) | ||||
|         { | ||||
|             m_filename = filename; | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         const std::string& getFilename() const | ||||
|         { | ||||
|             return m_filename; | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         const std::string& getMessage() const | ||||
|         { | ||||
|             return m_message; | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         void setError( const std::string& errorMessage ) | ||||
|         { | ||||
|             m_message = errorMessage + "\n\n" + "Usage: ..."; | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         void setReporter( IReporter* reporter ) | ||||
|         { | ||||
|             m_reporter = std::auto_ptr<IReporter>( reporter ); | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         IReporter* getReporter() const | ||||
|         { | ||||
|             if( !m_reporter.get() ) | ||||
|                 const_cast<Config*>( this )->setReporter( Hub::getReporterRegistry().create( "basic", *this ) ); | ||||
|             return m_reporter.get(); | ||||
|         } | ||||
|                  | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         List::What listWhat() const | ||||
|         { | ||||
|             return static_cast<List::What>( m_listSpec & List::WhatMask ); | ||||
|         }         | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         List::What listAs() const | ||||
|         { | ||||
|             return static_cast<List::What>( m_listSpec & List::AsMask ); | ||||
|         }         | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         void setIncludeWhat( Include::What includeWhat ) | ||||
|         { | ||||
|             m_includeWhat = includeWhat; | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         void setShouldDebugBreak( bool shouldDebugBreakFlag ) | ||||
|         { | ||||
|             m_shouldDebugBreak = shouldDebugBreakFlag; | ||||
|         } | ||||
|  | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         void setName( const std::string& name ) | ||||
|         { | ||||
|             m_name = name; | ||||
|         } | ||||
|  | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         std::string getName() const | ||||
|         { | ||||
|             return m_name; | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         bool shouldDebugBreak() const | ||||
|         { | ||||
|             return m_shouldDebugBreak; | ||||
|         } | ||||
|  | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         void setShowHelp( bool showHelpFlag ) | ||||
|         { | ||||
|             m_showHelp = showHelpFlag; | ||||
|         } | ||||
|  | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         bool showHelp() const | ||||
|         { | ||||
|             return m_showHelp; | ||||
|         } | ||||
|  | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         virtual std::ostream& stream() const | ||||
|         { | ||||
|             return m_os; | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         void setStreamBuf( std::streambuf* buf ) | ||||
|         { | ||||
|             // Delete previous stream buf if we own it | ||||
|             if( m_streambuf && dynamic_cast<StreamBufBase*>( m_streambuf ) ) | ||||
|                 delete m_streambuf; | ||||
|  | ||||
|             m_streambuf = buf; | ||||
|             m_os.rdbuf( buf ? buf : std::cout.rdbuf() ); | ||||
|         }         | ||||
|  | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         void useStream( const std::string& streamName ) | ||||
|         { | ||||
|             setStreamBuf( Hub::createStreamBuf( streamName ) ); | ||||
|         }         | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         virtual bool includeSuccessfulResults() const | ||||
|         { | ||||
|             return m_includeWhat == Include::SuccessfulResults; | ||||
|         } | ||||
|          | ||||
|     private: | ||||
|         std::auto_ptr<IReporter> m_reporter; | ||||
|         std::string m_filename; | ||||
|         std::string m_message; | ||||
|         List::What m_listSpec; | ||||
|         std::vector<std::string> m_testSpecs; | ||||
|         bool m_shouldDebugBreak; | ||||
|         bool m_showHelp; | ||||
|         std::streambuf* m_streambuf; | ||||
|         mutable std::ostream m_os; | ||||
|         Include::What m_includeWhat; | ||||
|         std::string m_name; | ||||
|          | ||||
|     }; | ||||
|      | ||||
| } // end namespace Catch | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_RUNNERCONFIG_HPP_INCLUDED | ||||
							
								
								
									
										112
									
								
								include/internal/catch_debugger.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								include/internal/catch_debugger.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,112 @@ | ||||
| /* | ||||
|  *  catch_debugger.hpp | ||||
|  *  Catch | ||||
|  * | ||||
|  *  Created by Phil on 27/12/2010. | ||||
|  *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved. | ||||
|  * | ||||
|  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||
|  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||
|  * | ||||
|  * Provides a BreakIntoDebugger() macro for Windows and Mac (so far) | ||||
|  */ | ||||
|  | ||||
| #ifndef TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED | ||||
| #define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED | ||||
|  | ||||
| #include <iostream> | ||||
|  | ||||
| #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) | ||||
| #define CATCH_PLATFORM_MAC | ||||
| #elif defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) | ||||
| #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 | ||||
|              | ||||
|         inline bool isDebuggerActive() | ||||
|         // Returns true if the current process is being debugged (either | ||||
|         // running under the debugger or has a debugger attached post facto). | ||||
|         { | ||||
|             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(); | ||||
|              | ||||
|             // Call sysctl. | ||||
|              | ||||
|             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. | ||||
|              | ||||
|             return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); | ||||
|         }         | ||||
|     } | ||||
|  | ||||
|     // The following code snippet taken from: | ||||
|     // 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" ); \ | ||||
|             } | ||||
|         #else | ||||
|             #define BreakIntoDebugger() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );} | ||||
|         #endif | ||||
|     #else | ||||
|         inline void BreakIntoDebugger(){} | ||||
|     #endif | ||||
|  | ||||
| #elif defined(CATCH_PLATFORM_WINDOWS) | ||||
|     extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); | ||||
|     extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* ); | ||||
|     #define BreakIntoDebugger() if (IsDebuggerPresent() ) { __debugbreak(); } | ||||
|     inline bool isDebuggerActive() | ||||
|     { | ||||
|         return IsDebuggerPresent() != 0; | ||||
|     } | ||||
| #else | ||||
| 	   inline void BreakIntoDebugger(){} | ||||
| 	   inline bool isDebuggerActive() { return false; } | ||||
| #endif | ||||
|  | ||||
| inline void writeToDebugConsole( const std::string& text ) | ||||
| { | ||||
| #ifdef CATCH_PLATFORM_WINDOWS | ||||
|     ::OutputDebugStringA( text.c_str() );     | ||||
| #else | ||||
|     // !TBD: Need a version for Mac/ XCode and other IDEs | ||||
|     std::cout << text; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED | ||||
							
								
								
									
										191
									
								
								include/internal/catch_evaluate.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										191
									
								
								include/internal/catch_evaluate.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,191 @@ | ||||
| /* | ||||
|  *  catch_evaluate.hpp | ||||
|  *  Catch | ||||
|  * | ||||
|  *  Created by Phil on 04/03/2011. | ||||
|  *  Copyright 2011 Two Blue Cubes Ltd. All rights reserved. | ||||
|  * | ||||
|  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||
|  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #ifndef TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED | ||||
| #define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED | ||||
|  | ||||
| namespace Catch | ||||
| { | ||||
| namespace Internal | ||||
| { | ||||
|     enum Operator | ||||
|     { | ||||
|         IsEqualTo, | ||||
|         IsNotEqualTo, | ||||
|         IsLessThan, | ||||
|         IsGreaterThan, | ||||
|         IsLessThanOrEqualTo, | ||||
|         IsGreaterThanOrEqualTo | ||||
|     }; | ||||
|      | ||||
|     template<Operator Op> | ||||
|     struct OperatorTraits{ static const char* getName(){ return "*error - unknown operator*"; } }; | ||||
|  | ||||
|     template<> | ||||
|     struct OperatorTraits<IsEqualTo>{ static const char* getName(){ return "=="; } }; | ||||
|      | ||||
|     template<> | ||||
|     struct OperatorTraits<IsNotEqualTo>{ static const char* getName(){ return "!="; } }; | ||||
|      | ||||
|     template<> | ||||
|     struct OperatorTraits<IsLessThan>{ static const char* getName(){ return "<"; } }; | ||||
|      | ||||
|     template<> | ||||
|     struct OperatorTraits<IsGreaterThan>{ static const char* getName(){ return ">"; } }; | ||||
|      | ||||
|     template<> | ||||
|     struct OperatorTraits<IsLessThanOrEqualTo>{ static const char* getName(){ return "<="; } }; | ||||
|      | ||||
|     template<> | ||||
|     struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } }; | ||||
|      | ||||
|     // So the compare overloads can be operator agnostic we convey the operator as a template | ||||
|     // enum, which is used to specialise an Evaluator for doing the comparison. | ||||
|     template<typename T1, typename T2, Operator Op> | ||||
|     class Evaluator{}; | ||||
|      | ||||
|     template<typename T1, typename T2> | ||||
|     struct Evaluator<T1, T2, IsEqualTo> | ||||
|     { | ||||
|         static bool evaluate( const T1& lhs, const T2& rhs) | ||||
|         { | ||||
|             return const_cast<T1&>( lhs ) == const_cast<T2&>( rhs ); | ||||
|         } | ||||
|     }; | ||||
|     template<typename T1, typename T2> | ||||
|     struct Evaluator<T1, T2, IsNotEqualTo> | ||||
|     { | ||||
|         static bool evaluate( const T1& lhs, const T2& rhs ) | ||||
|         { | ||||
|             return const_cast<T1&>( lhs ) != const_cast<T2&>( rhs ); | ||||
|         } | ||||
|     }; | ||||
|     template<typename T1, typename T2> | ||||
|     struct Evaluator<T1, T2, IsLessThan> | ||||
|     { | ||||
|         static bool evaluate( const T1& lhs, const T2& rhs ) | ||||
|         { | ||||
|             return const_cast<T1&>( lhs ) < const_cast<T2&>( rhs ); | ||||
|         } | ||||
|     }; | ||||
|     template<typename T1, typename T2> | ||||
|     struct Evaluator<T1, T2, IsGreaterThan> | ||||
|     { | ||||
|         static bool evaluate( const T1& lhs, const T2& rhs ) | ||||
|         { | ||||
|             return const_cast<T1&>( lhs ) > const_cast<T2&>( rhs ); | ||||
|         } | ||||
|     }; | ||||
|     template<typename T1, typename T2> | ||||
|     struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> | ||||
|     { | ||||
|         static bool evaluate( const T1& lhs, const T2& rhs ) | ||||
|         { | ||||
|             return const_cast<T1&>( lhs ) >= const_cast<T2&>( rhs ); | ||||
|         } | ||||
|     }; | ||||
|     template<typename T1, typename T2> | ||||
|     struct Evaluator<T1, T2, IsLessThanOrEqualTo> | ||||
|     { | ||||
|         static bool evaluate( const T1& lhs, const T2& rhs ) | ||||
|         { | ||||
|             return const_cast<T1&>( lhs ) <= const_cast<T2&>( rhs ); | ||||
|         } | ||||
|     }; | ||||
|      | ||||
|     template<Operator Op, typename T1, typename T2> | ||||
|     bool applyEvaluator( const T1& lhs, const T2& rhs ) | ||||
|     { | ||||
|         return Evaluator<T1, T2, Op>::evaluate( lhs, rhs ); | ||||
|     } | ||||
|      | ||||
|     // "base" overload | ||||
|     template<Operator Op, typename T1, typename T2> | ||||
|     bool compare( const T1& lhs, const T2& rhs ) | ||||
|     { | ||||
|         return Evaluator<T1, T2, Op>::evaluate( lhs, rhs ); | ||||
|     } | ||||
|      | ||||
|     // unsigned X to int | ||||
|     template<Operator Op> bool compare( unsigned int lhs, int rhs ) | ||||
|     { | ||||
|         return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) ); | ||||
|     } | ||||
|     template<Operator Op> bool compare( unsigned long lhs, int rhs ) | ||||
|     { | ||||
|         return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) ); | ||||
|     } | ||||
|     template<Operator Op> bool compare( unsigned char lhs, int rhs ) | ||||
|     { | ||||
|         return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) ); | ||||
|     } | ||||
|      | ||||
|     // unsigned X to long | ||||
|     template<Operator Op> bool compare( unsigned int lhs, long rhs ) | ||||
|     { | ||||
|         return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) ); | ||||
|     } | ||||
|     template<Operator Op> bool compare( unsigned long lhs, long rhs ) | ||||
|     { | ||||
|         return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) ); | ||||
|     } | ||||
|     template<Operator Op> bool compare( unsigned char lhs, long rhs ) | ||||
|     { | ||||
|         return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) ); | ||||
|     } | ||||
|      | ||||
|     // int to unsigned X | ||||
|     template<Operator Op> bool compare( int lhs, unsigned int rhs ) | ||||
|     { | ||||
|         return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs ); | ||||
|     } | ||||
|     template<Operator Op> bool compare( int lhs, unsigned long rhs ) | ||||
|     { | ||||
|         return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs ); | ||||
|     } | ||||
|     template<Operator Op> bool compare( int lhs, unsigned char rhs ) | ||||
|     { | ||||
|         return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs ); | ||||
|     } | ||||
|      | ||||
|     // long to unsigned X | ||||
|     template<Operator Op> bool compare( long lhs, unsigned int rhs ) | ||||
|     { | ||||
|         return applyEvaluator<Op>( static_cast<unsigned long>( lhs ) ); | ||||
|     } | ||||
|     template<Operator Op> bool compare( long lhs, unsigned long rhs ) | ||||
|     { | ||||
|         return applyEvaluator<Op>( static_cast<unsigned long>( lhs ) ); | ||||
|     } | ||||
|     template<Operator Op> bool compare( long lhs, unsigned char rhs ) | ||||
|     { | ||||
|         return applyEvaluator<Op>( static_cast<unsigned long>( lhs ) ); | ||||
|     } | ||||
|  | ||||
|     template<Operator Op, typename T> | ||||
|     bool compare( long lhs, const T* rhs ) | ||||
|     { | ||||
|         return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( NULL ), rhs ); | ||||
|  | ||||
|     } | ||||
|      | ||||
|     template<Operator Op, typename T> | ||||
|     bool compare( long lhs, T* rhs ) | ||||
|     { | ||||
|         return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs ); | ||||
|          | ||||
|     } | ||||
|      | ||||
| } // end of namespace Internal | ||||
| } // end of namespace Catch | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED | ||||
							
								
								
									
										63
									
								
								include/internal/catch_exception_translator_registry.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								include/internal/catch_exception_translator_registry.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | ||||
| /* | ||||
|  *  catch_exception_translator_registry.hpp | ||||
|  *  Catch | ||||
|  * | ||||
|  *  Created by Phil on 20/04/2011. | ||||
|  *  Copyright 2011 Two Blue Cubes Ltd. All rights reserved. | ||||
|  * | ||||
|  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||
|  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||
|  * | ||||
|  */ | ||||
| #ifndef TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_HPP_INCLUDED | ||||
| #define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_HPP_INCLUDED | ||||
|  | ||||
| #include "catch_interfaces_exception.h" | ||||
|  | ||||
| namespace Catch | ||||
| {     | ||||
|     class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry | ||||
|     { | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         virtual void registerTranslator | ||||
|         (    | ||||
|             IExceptionTranslator* translator  | ||||
|         ) | ||||
|         { | ||||
|             m_translators.push_back( translator ); | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         virtual std::string translateActiveException | ||||
|         () | ||||
|         const | ||||
|         { | ||||
|             return tryTranslators( m_translators.begin() ); | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         std::string tryTranslators | ||||
|         ( | ||||
|             std::vector<IExceptionTranslator*>::const_iterator it | ||||
|         )  | ||||
|         const | ||||
|         { | ||||
|             if( it == m_translators.end() ) | ||||
|                 return "Unknown exception"; | ||||
|              | ||||
|             try | ||||
|             { | ||||
|                 return (*it)->translate(); | ||||
|             } | ||||
|             catch(...) | ||||
|             { | ||||
|                 return tryTranslators( it+1 ); | ||||
|             } | ||||
|         } | ||||
|          | ||||
|     private: | ||||
|         std::vector<IExceptionTranslator*> m_translators; | ||||
|     }; | ||||
| } | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_HPP_INCLUDED | ||||
							
								
								
									
										310
									
								
								include/internal/catch_generators.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										310
									
								
								include/internal/catch_generators.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,310 @@ | ||||
| /* | ||||
|  *  catch_generators.hpp | ||||
|  *  Catch | ||||
|  * | ||||
|  *  Created by Phil on 27/01/2011. | ||||
|  *  Copyright 2011 Two Blue Cubes Ltd. All rights reserved. | ||||
|  * | ||||
|  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||
|  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #ifndef TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED | ||||
| #define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED | ||||
|  | ||||
| #include "catch_hub.h" | ||||
|  | ||||
| #include <iterator> | ||||
| #include <vector> | ||||
| #include <string> | ||||
| #include <stdlib.h> | ||||
|  | ||||
| namespace Catch | ||||
| { | ||||
|  | ||||
| template<typename T> | ||||
| struct IGenerator | ||||
| {         | ||||
|     virtual ~IGenerator | ||||
|     () | ||||
|     {} | ||||
|      | ||||
|     virtual T getValue | ||||
|         ( std::size_t index | ||||
|         ) const = 0; | ||||
|      | ||||
|     virtual std::size_t size | ||||
|         () const = 0; | ||||
| }; | ||||
|  | ||||
| template<typename T> | ||||
| class BetweenGenerator : public IGenerator<T> | ||||
| { | ||||
| public: | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     BetweenGenerator | ||||
|     (  | ||||
|         T from,  | ||||
|         T to  | ||||
|     ) | ||||
|     :   m_from( from ),  | ||||
|         m_to( to ) | ||||
|     { | ||||
|     } | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     virtual T getValue | ||||
|     ( | ||||
|         std::size_t index | ||||
|     ) | ||||
|     const | ||||
|     { | ||||
|         return m_from+static_cast<T>( index ); | ||||
|     } | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     virtual std::size_t size | ||||
|     () | ||||
|     const | ||||
|     { | ||||
|         return 1+m_to-m_from; | ||||
|     } | ||||
|      | ||||
| private: | ||||
|      | ||||
|     T m_from; | ||||
|     T m_to; | ||||
| }; | ||||
|  | ||||
| template<typename T> | ||||
| class ValuesGenerator : public IGenerator<T> | ||||
| { | ||||
| public: | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     ValuesGenerator | ||||
|     () | ||||
|     { | ||||
|     } | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     void add | ||||
|     ( | ||||
|         T value | ||||
|     ) | ||||
|     { | ||||
|         m_values.push_back( value ); | ||||
|     } | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     virtual T getValue | ||||
|     ( | ||||
|         std::size_t index | ||||
|     ) | ||||
|     const | ||||
|     { | ||||
|         return m_values[index]; | ||||
|     } | ||||
|  | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     virtual std::size_t size | ||||
|     () | ||||
|     const | ||||
|     { | ||||
|         return m_values.size(); | ||||
|     } | ||||
|      | ||||
| private: | ||||
|      | ||||
|     std::vector<T> m_values; | ||||
| }; | ||||
|  | ||||
| template<typename T> | ||||
| class CompositeGenerator | ||||
| { | ||||
| public: | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     CompositeGenerator() | ||||
|     :   m_totalSize( 0 ) | ||||
|     { | ||||
|     } | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
| 	// *** Move semantics, similar to auto_ptr *** | ||||
|     CompositeGenerator( CompositeGenerator& other ) | ||||
| 	:	m_fileInfo( other.m_fileInfo ), | ||||
| 		m_totalSize( 0 ) | ||||
|     { | ||||
| 		move( other ); | ||||
|     } | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     CompositeGenerator& setFileInfo | ||||
|     ( | ||||
|         const char* fileInfo | ||||
|     ) | ||||
|     { | ||||
|         m_fileInfo = fileInfo; | ||||
|         return *this; | ||||
|     } | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     ~CompositeGenerator | ||||
|     () | ||||
|     { | ||||
|         deleteAll( m_composed ); | ||||
|     } | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     operator T | ||||
|     () | ||||
|     const | ||||
|     { | ||||
|         size_t overallIndex = Hub::getGeneratorIndex( m_fileInfo, m_totalSize ); | ||||
|          | ||||
|         typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin(); | ||||
|         typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end(); | ||||
|         for( size_t index = 0; it != itEnd; ++it ) | ||||
|         { | ||||
|             const IGenerator<T>* generator = *it; | ||||
|             if( overallIndex >= index && overallIndex < index + generator->size() ) | ||||
|             { | ||||
|                 return generator->getValue( overallIndex-index ); | ||||
|             } | ||||
|             index += generator->size(); | ||||
|         } | ||||
|         CATCH_INTERNAL_ERROR( "Indexed past end of generated range" ); | ||||
| 		return T(); // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so | ||||
|     } | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     void add | ||||
|     ( | ||||
|         const IGenerator<T>* generator | ||||
|     ) | ||||
|     { | ||||
|         m_totalSize += generator->size(); | ||||
|         m_composed.push_back( generator ); | ||||
|     } | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     CompositeGenerator& then | ||||
|     ( | ||||
|         CompositeGenerator& other | ||||
|     ) | ||||
|     { | ||||
|         move( other ); | ||||
|         return *this; | ||||
|     } | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     CompositeGenerator& then | ||||
|     ( | ||||
|         T value | ||||
|     ) | ||||
|     { | ||||
|         ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>(); | ||||
|         valuesGen->add( value ); | ||||
|         add( valuesGen ); | ||||
|         return *this; | ||||
|     } | ||||
|      | ||||
| private: | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     void move | ||||
|     ( | ||||
|         CompositeGenerator& other | ||||
|     ) | ||||
|     { | ||||
|         std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) ); | ||||
|         m_totalSize += other.m_totalSize; | ||||
|         other.m_composed.clear(); | ||||
|     } | ||||
|      | ||||
|     std::vector<const IGenerator<T>*> m_composed; | ||||
|     std::string m_fileInfo; | ||||
|     size_t m_totalSize; | ||||
| }; | ||||
|  | ||||
| namespace Generators | ||||
| { | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     template<typename T> | ||||
|     CompositeGenerator<T> between | ||||
|     ( | ||||
|         T from,  | ||||
|         T to | ||||
|     ) | ||||
|     { | ||||
|         CompositeGenerator<T> generators; | ||||
|         generators.add( new BetweenGenerator<T>( from, to ) ); | ||||
|         return generators; | ||||
|     } | ||||
|  | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     template<typename T> | ||||
|     CompositeGenerator<T> values | ||||
|     ( | ||||
|         T val1,  | ||||
|         T val2 | ||||
|     ) | ||||
|     { | ||||
|         CompositeGenerator<T> generators; | ||||
|         ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>(); | ||||
|         valuesGen->add( val1 ); | ||||
|         valuesGen->add( val2 ); | ||||
|         generators.add( valuesGen ); | ||||
|         return generators; | ||||
|     } | ||||
|  | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     template<typename T> | ||||
|     CompositeGenerator<T> values | ||||
|     ( | ||||
|         T val1,  | ||||
|         T val2,  | ||||
|         T val3 | ||||
|     ) | ||||
|     { | ||||
|         CompositeGenerator<T> generators; | ||||
|         ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>(); | ||||
|         valuesGen->add( val1 ); | ||||
|         valuesGen->add( val2 ); | ||||
|         valuesGen->add( val3 ); | ||||
|         generators.add( valuesGen ); | ||||
|         return generators; | ||||
|     } | ||||
|  | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     template<typename T> | ||||
|     CompositeGenerator<T> values | ||||
|     ( | ||||
|         T val1,  | ||||
|         T val2,  | ||||
|         T val3,  | ||||
|         T val4 | ||||
|     ) | ||||
|     { | ||||
|         CompositeGenerator<T> generators; | ||||
|         ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>(); | ||||
|         valuesGen->add( val1 ); | ||||
|         valuesGen->add( val2 ); | ||||
|         valuesGen->add( val3 ); | ||||
|         valuesGen->add( val4 ); | ||||
|         generators.add( valuesGen ); | ||||
|         return generators; | ||||
|     } | ||||
|  | ||||
| } // end namespace Generators | ||||
|      | ||||
| using namespace Generators; | ||||
|      | ||||
| } // end namespace Catch | ||||
|  | ||||
| #define INTERNAL_CATCH_LINESTR2( line ) #line | ||||
| #define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line ) | ||||
|  | ||||
| #define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" ) | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED | ||||
							
								
								
									
										118
									
								
								include/internal/catch_generators_impl.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								include/internal/catch_generators_impl.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,118 @@ | ||||
| /* | ||||
|  *  catch_generators_impl.hpp | ||||
|  *  Catch | ||||
|  * | ||||
|  *  Created by Phil on 28/01/2011. | ||||
|  *  Copyright 2011 Two Blue Cubes Ltd. All rights reserved. | ||||
|  * | ||||
|  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||
|  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #ifndef TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED | ||||
| #define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED | ||||
|  | ||||
| #include "catch_common.h" | ||||
|  | ||||
| #include <vector> | ||||
| #include <string> | ||||
| #include <map> | ||||
|  | ||||
| namespace Catch | ||||
| { | ||||
|     struct GeneratorInfo | ||||
|     { | ||||
|         ///////////////////////////////////////////////////////////////////////         | ||||
|         GeneratorInfo | ||||
|         (  | ||||
|             std::size_t size | ||||
|         ) | ||||
|         :   m_size( size ), | ||||
|             m_currentIndex( 0 ) | ||||
|         { | ||||
|         } | ||||
|          | ||||
|         ///////////////////////////////////////////////////////////////////////         | ||||
|         bool moveNext | ||||
|         () | ||||
|         { | ||||
|             if( ++m_currentIndex == m_size ) | ||||
|             { | ||||
|                 m_currentIndex = 0; | ||||
|                 return false; | ||||
|             } | ||||
|             return true; | ||||
|         } | ||||
|          | ||||
|         ///////////////////////////////////////////////////////////////////////         | ||||
|         std::size_t getCurrentIndex | ||||
|         () | ||||
|         const | ||||
|         { | ||||
|             return m_currentIndex; | ||||
|         } | ||||
|          | ||||
|         std::size_t m_size; | ||||
|         std::size_t m_currentIndex; | ||||
|     }; | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|      | ||||
|     class GeneratorsForTest | ||||
|     { | ||||
|          | ||||
|     public: | ||||
|         ///////////////////////////////////////////////////////////////////////         | ||||
|         ~GeneratorsForTest | ||||
|         () | ||||
|         { | ||||
|             deleteAll( m_generatorsInOrder ); | ||||
|         } | ||||
|          | ||||
|         ///////////////////////////////////////////////////////////////////////         | ||||
|         GeneratorInfo& getGeneratorInfo | ||||
|         ( | ||||
|             const std::string& fileInfo, | ||||
|             std::size_t size | ||||
|         ) | ||||
|         { | ||||
|             std::map<std::string, GeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo ); | ||||
|             if( it == m_generatorsByName.end() ) | ||||
|             { | ||||
|                 GeneratorInfo* info = new GeneratorInfo( size ); | ||||
|                 m_generatorsByName.insert( std::make_pair( fileInfo, info ) ); | ||||
|                 m_generatorsInOrder.push_back( info ); | ||||
|                 return *info; | ||||
|             } | ||||
|             return *it->second; | ||||
|         } | ||||
|          | ||||
|         ///////////////////////////////////////////////////////////////////////         | ||||
|         bool moveNext | ||||
|         () | ||||
|         { | ||||
|             std::vector<GeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin(); | ||||
|             std::vector<GeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end(); | ||||
|             for(; it != itEnd; ++it ) | ||||
|             { | ||||
|                 if( (*it)->moveNext() ) | ||||
|                     return true; | ||||
|             } | ||||
|             return false; | ||||
|         } | ||||
|          | ||||
|     private: | ||||
|         std::map<std::string, GeneratorInfo*> m_generatorsByName; | ||||
|         std::vector<GeneratorInfo*> m_generatorsInOrder; | ||||
|     }; | ||||
|      | ||||
| } // end namespace Catch | ||||
|  | ||||
| #define INTERNAL_CATCH_LINESTR2( line ) #line | ||||
| #define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line ) | ||||
|  | ||||
| #define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" ) | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED | ||||
							
								
								
									
										96
									
								
								include/internal/catch_hub.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								include/internal/catch_hub.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,96 @@ | ||||
| /* | ||||
|  *  catch_hub.h | ||||
|  *  Catch | ||||
|  * | ||||
|  *  Created by Phil on 31/12/2010. | ||||
|  *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved. | ||||
|  * | ||||
|  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||
|  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||
|  * | ||||
|  */ | ||||
| #ifndef TWOBLUECUBES_CATCH_HUB_H_INCLUDED | ||||
| #define TWOBLUECUBES_CATCH_HUB_H_INCLUDED | ||||
|  | ||||
| #include "catch_interfaces_reporter.h" | ||||
|  | ||||
| #include <memory> | ||||
| #include <vector> | ||||
| #include <stdlib.h> | ||||
|  | ||||
| namespace Catch | ||||
| { | ||||
|     class TestCaseInfo; | ||||
|     struct IResultCapture; | ||||
|     struct ITestCaseRegistry; | ||||
|     struct IRunner; | ||||
|     struct IExceptionTranslatorRegistry; | ||||
|     class GeneratorsForTest; | ||||
|  | ||||
|     class StreamBufBase : public std::streambuf | ||||
|     { | ||||
|     }; | ||||
|      | ||||
|     class Hub | ||||
|     { | ||||
|         Hub(); | ||||
|          | ||||
|         static Hub& me(); | ||||
|          | ||||
|         Hub( const Hub& ); | ||||
|         void operator=( const Hub& ); | ||||
|          | ||||
|     public: | ||||
|          | ||||
|         static void setRunner | ||||
|             ( IRunner* runner  | ||||
|             ); | ||||
|          | ||||
|         static void setResultCapture | ||||
|             ( IResultCapture* resultCapture  | ||||
|             ); | ||||
|          | ||||
|         static IResultCapture& getResultCapture | ||||
|             (); | ||||
|          | ||||
|         static IReporterRegistry& getReporterRegistry | ||||
|             (); | ||||
|          | ||||
|         static ITestCaseRegistry& getTestCaseRegistry | ||||
|             (); | ||||
|          | ||||
|         static IExceptionTranslatorRegistry& getExceptionTranslatorRegistry | ||||
|             (); | ||||
|          | ||||
|         static std::streambuf* createStreamBuf | ||||
|             ( const std::string& streamName | ||||
|             ); | ||||
|          | ||||
|         static IRunner& getRunner | ||||
|             (); | ||||
|          | ||||
|         static size_t getGeneratorIndex | ||||
|             (   const std::string& fileInfo,  | ||||
|                 size_t totalSize  | ||||
|             ); | ||||
|          | ||||
|         static bool advanceGeneratorsForCurrentTest | ||||
|             (); | ||||
|          | ||||
|     private: | ||||
|         GeneratorsForTest* findGeneratorsForCurrentTest | ||||
|             (); | ||||
|          | ||||
|         GeneratorsForTest& getGeneratorsForCurrentTest | ||||
|             (); | ||||
|          | ||||
|         std::auto_ptr<IReporterRegistry> m_reporterRegistry; | ||||
|         std::auto_ptr<ITestCaseRegistry> m_testCaseRegistry; | ||||
|         std::auto_ptr<IExceptionTranslatorRegistry> m_exceptionTranslatorRegistry; | ||||
|         IRunner* m_runner; | ||||
|         IResultCapture* m_resultCapture; | ||||
|         std::map<std::string, GeneratorsForTest*> m_generatorsByTestName; | ||||
|     }; | ||||
| } | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_HUB_H_INCLUDED | ||||
							
								
								
									
										143
									
								
								include/internal/catch_hub_impl.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								include/internal/catch_hub_impl.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,143 @@ | ||||
| /* | ||||
|  *  catch_hub_impl.hpp | ||||
|  *  Catch | ||||
|  * | ||||
|  *  Created by Phil on 31/12/2010. | ||||
|  *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved. | ||||
|  * | ||||
|  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||
|  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||
|  * | ||||
|  */ | ||||
| #include "catch_hub.h" | ||||
| #include "catch_reporter_registry.hpp" | ||||
| #include "catch_test_case_registry_impl.hpp" | ||||
| #include "catch_exception_translator_registry.hpp" | ||||
| #include "catch_runner_impl.hpp" | ||||
| #include "catch_generators_impl.hpp" | ||||
| #include "catch_stream.hpp" | ||||
|  | ||||
| namespace Catch | ||||
| {     | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     Hub::Hub | ||||
|     () | ||||
|     :   m_reporterRegistry( new ReporterRegistry ), | ||||
|         m_testCaseRegistry( new TestRegistry ), | ||||
|         m_exceptionTranslatorRegistry( new ExceptionTranslatorRegistry ) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     Hub& Hub::me | ||||
|     () | ||||
|     { | ||||
|         static Hub hub; | ||||
|         return hub; | ||||
|     } | ||||
|  | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     void Hub::setRunner( IRunner* runner ) | ||||
|     { | ||||
|         me().m_runner = runner; | ||||
|     } | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     void Hub::setResultCapture( IResultCapture* resultCapture ) | ||||
|     { | ||||
|         me().m_resultCapture = resultCapture; | ||||
|     } | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     IResultCapture& Hub::getResultCapture | ||||
|     () | ||||
|     { | ||||
|         return *me().m_resultCapture; | ||||
|     } | ||||
|  | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     IRunner& Hub::getRunner | ||||
|     () | ||||
|     { | ||||
|         return *me().m_runner; | ||||
|     } | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     IReporterRegistry& Hub::getReporterRegistry | ||||
|     () | ||||
|     { | ||||
|         return *me().m_reporterRegistry.get(); | ||||
|     } | ||||
|  | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     ITestCaseRegistry& Hub::getTestCaseRegistry | ||||
|     () | ||||
|     { | ||||
|         return *me().m_testCaseRegistry.get(); | ||||
|     } | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     IExceptionTranslatorRegistry& Hub::getExceptionTranslatorRegistry | ||||
|     () | ||||
|     { | ||||
|         return *me().m_exceptionTranslatorRegistry.get(); | ||||
|     } | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     std::streambuf* Hub::createStreamBuf | ||||
|     ( | ||||
|         const std::string& streamName | ||||
|     ) | ||||
|     { | ||||
|         if( streamName == "stdout" ) return std::cout.rdbuf(); | ||||
|         if( streamName == "stderr" ) return std::cerr.rdbuf(); | ||||
|         if( streamName == "debug" ) return new StreamBufImpl<OutputDebugWriter>; | ||||
|          | ||||
|         throw std::domain_error( "Unknown stream: " + streamName ); | ||||
|     } | ||||
|  | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     GeneratorsForTest* Hub::findGeneratorsForCurrentTest | ||||
|     () | ||||
|     { | ||||
|         std::string testName = getResultCapture().getCurrentTestName(); | ||||
|          | ||||
|         std::map<std::string, GeneratorsForTest*>::const_iterator it =  | ||||
|             m_generatorsByTestName.find( testName ); | ||||
|         return it != m_generatorsByTestName.end() | ||||
|             ? it->second | ||||
|             : NULL; | ||||
|     } | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     GeneratorsForTest& Hub::getGeneratorsForCurrentTest | ||||
|     () | ||||
|     { | ||||
|         GeneratorsForTest* generators = findGeneratorsForCurrentTest(); | ||||
|         if( !generators ) | ||||
|         { | ||||
|             std::string testName = getResultCapture().getCurrentTestName(); | ||||
|             generators = new GeneratorsForTest(); | ||||
|             m_generatorsByTestName.insert( std::make_pair( testName, generators ) ); | ||||
|         } | ||||
|         return *generators; | ||||
|     } | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     size_t Hub::getGeneratorIndex | ||||
|     ( | ||||
|         const std::string& fileInfo,  | ||||
|         size_t totalSize  | ||||
|     ) | ||||
|     { | ||||
|         return me().getGeneratorsForCurrentTest() | ||||
|             .getGeneratorInfo( fileInfo, totalSize ) | ||||
|             .getCurrentIndex(); | ||||
|     } | ||||
|  | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     bool Hub::advanceGeneratorsForCurrentTest | ||||
|     () | ||||
|     { | ||||
|         GeneratorsForTest* generators = me().findGeneratorsForCurrentTest(); | ||||
|         return generators && generators->moveNext(); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										74
									
								
								include/internal/catch_interfaces_capture.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								include/internal/catch_interfaces_capture.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,74 @@ | ||||
| /* | ||||
|  *  catch_interfaces_capture.h | ||||
|  *  Catch | ||||
|  * | ||||
|  *  Created by Phil on 07/01/2011. | ||||
|  *  Copyright 2011 Two Blue Cubes Ltd. All rights reserved. | ||||
|  * | ||||
|  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||
|  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||
|  * | ||||
|  */ | ||||
| #ifndef TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED | ||||
| #define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED | ||||
|  | ||||
| #include <string> | ||||
| #include "catch_result_type.h" | ||||
|  | ||||
| namespace Catch | ||||
| {     | ||||
|     class TestCaseInfo; | ||||
|     class ScopedInfo; | ||||
|     class MutableResultInfo; | ||||
|  | ||||
|     struct IResultCapture | ||||
|     { | ||||
|         virtual ~IResultCapture | ||||
|         () | ||||
|         {} | ||||
|          | ||||
|         virtual void testEnded | ||||
|             (   const ResultInfo& result  | ||||
|             ) = 0; | ||||
|         virtual bool sectionStarted | ||||
|             (   const std::string& name,  | ||||
|                 const std::string& description,  | ||||
|                 const std::string& filename, | ||||
|                 std::size_t line, | ||||
|                 std::size_t& successes,  | ||||
|                 std::size_t& failures  | ||||
|             ) = 0; | ||||
|         virtual void sectionEnded | ||||
|             (   const std::string& name,  | ||||
|                 std::size_t successes,  | ||||
|                 std::size_t failures  | ||||
|             ) = 0; | ||||
|         virtual void pushScopedInfo | ||||
|             (   ScopedInfo* scopedInfo  | ||||
|             ) = 0; | ||||
|         virtual void popScopedInfo | ||||
|             (   ScopedInfo* scopedInfo  | ||||
|             ) = 0; | ||||
|         virtual bool shouldDebugBreak | ||||
|             () const = 0; | ||||
|          | ||||
|         virtual ResultAction::Value acceptResult | ||||
|             (   bool result  | ||||
|             ) = 0; | ||||
|         virtual ResultAction::Value acceptResult | ||||
|             (   ResultWas::OfType result | ||||
|             ) = 0; | ||||
|         virtual ResultAction::Value acceptExpression | ||||
|             (   const MutableResultInfo& resultInfo  | ||||
|             ) = 0; | ||||
|         virtual void acceptMessage | ||||
|             (   const std::string& msg  | ||||
|             ) = 0; | ||||
|          | ||||
|         virtual std::string getCurrentTestName | ||||
|             () const = 0; | ||||
|          | ||||
|     }; | ||||
| } | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED | ||||
							
								
								
									
										92
									
								
								include/internal/catch_interfaces_exception.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								include/internal/catch_interfaces_exception.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,92 @@ | ||||
| /* | ||||
|  *  catch_exception_interfaces.h | ||||
|  *  Catch | ||||
|  * | ||||
|  *  Created by Phil on 20/04/2011. | ||||
|  *  Copyright 2011 Two Blue Cubes Ltd. All rights reserved. | ||||
|  * | ||||
|  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||
|  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||
|  * | ||||
|  */ | ||||
| #ifndef TWOBLUECUBES_CATCH_INTERFACES_EXCEPTIONS_H_INCLUDED | ||||
| #define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTIONS_H_INCLUDED | ||||
|  | ||||
| #include <string> | ||||
|                                                | ||||
| namespace Catch | ||||
| {     | ||||
|     typedef std::string(*exceptionTranslateFunction)(); | ||||
|  | ||||
|     struct IExceptionTranslator | ||||
|     { | ||||
|         virtual ~IExceptionTranslator(){} | ||||
|         virtual std::string translate() const = 0; | ||||
|     }; | ||||
|      | ||||
|     struct IExceptionTranslatorRegistry | ||||
|     { | ||||
|         virtual ~IExceptionTranslatorRegistry | ||||
|         () | ||||
|         {} | ||||
|          | ||||
|         virtual void registerTranslator | ||||
|             (   IExceptionTranslator* translator  | ||||
|             ) = 0; | ||||
|         virtual std::string translateActiveException | ||||
|             () const = 0; | ||||
|          | ||||
|     }; | ||||
|  | ||||
|     class ExceptionTranslatorRegistrar | ||||
|     { | ||||
|         template<typename T> | ||||
|         class ExceptionTranslator : public IExceptionTranslator | ||||
|         { | ||||
|         public: | ||||
|              | ||||
|             ExceptionTranslator | ||||
|             ( | ||||
|                 std::string(*translateFunction)( T& )  | ||||
|             ) | ||||
|             : m_translateFunction( translateFunction ) | ||||
|             {} | ||||
|              | ||||
|             virtual std::string translate | ||||
|             () | ||||
|             const | ||||
|             { | ||||
|                 try | ||||
|                 { | ||||
|                     throw; | ||||
|                 } | ||||
|                 catch( T& ex ) | ||||
|                 { | ||||
|                     return m_translateFunction( ex ); | ||||
|                 } | ||||
|             } | ||||
|              | ||||
|         protected: | ||||
|             std::string(*m_translateFunction)( T& ); | ||||
|         }; | ||||
|          | ||||
|     public: | ||||
|         template<typename T> | ||||
|         ExceptionTranslatorRegistrar | ||||
|         ( | ||||
|             std::string(*translateFunction)( T& )  | ||||
|         ) | ||||
|         { | ||||
|             Catch::Hub::getExceptionTranslatorRegistry().registerTranslator | ||||
|                 ( new ExceptionTranslator<T>( translateFunction ) ); | ||||
|         } | ||||
|     }; | ||||
| } | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| #define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \ | ||||
|     static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \ | ||||
|     namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\ | ||||
|     static std::string INTERNAL_CATCH_UNIQUE_NAME(  catch_internal_ExceptionTranslator )( signature ) | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_INTERFACES_EXCEPTIONS_H_INCLUDED | ||||
							
								
								
									
										145
									
								
								include/internal/catch_interfaces_reporter.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								include/internal/catch_interfaces_reporter.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,145 @@ | ||||
| /* | ||||
|  *  catch_interfaces_reporter.h | ||||
|  *  Test | ||||
|  * | ||||
|  *  Created by Phil on 31/12/2010. | ||||
|  *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved. | ||||
|  * | ||||
|  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||
|  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #ifndef TWOBLUECUBES_CATCH_IREPORTERREGISTRY_INCLUDED | ||||
| #define TWOBLUECUBES_CATCH_IREPORTERREGISTRY_INCLUDED | ||||
|  | ||||
| #include "catch_common.h" | ||||
|  | ||||
| #include <string> | ||||
| #include <ostream> | ||||
| #include <map> | ||||
|  | ||||
| namespace Catch | ||||
| { | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     struct IReporterConfig | ||||
|     { | ||||
|         virtual ~IReporterConfig | ||||
|         () | ||||
|         {} | ||||
|          | ||||
|         virtual std::ostream& stream | ||||
|             () const = 0; | ||||
|          | ||||
|         virtual bool includeSuccessfulResults | ||||
|             () const = 0; | ||||
|  | ||||
|         virtual std::string getName | ||||
|             () const = 0; | ||||
|     }; | ||||
|      | ||||
|     class TestCaseInfo; | ||||
|     class ResultInfo; | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     struct IReporter : NonCopyable | ||||
|     { | ||||
|         virtual ~IReporter | ||||
|             (){} | ||||
|          | ||||
|         virtual void StartTesting | ||||
|             () = 0; | ||||
|          | ||||
|         virtual void EndTesting | ||||
|             (   std::size_t succeeded,  | ||||
|                 std::size_t failed  | ||||
|             ) = 0; | ||||
|          | ||||
|         virtual void StartGroup | ||||
|             (   const std::string& groupName | ||||
|             ) = 0; | ||||
|          | ||||
|         virtual void EndGroup | ||||
|             (   const std::string& groupName,  | ||||
|                 std::size_t succeeded,  | ||||
|                 std::size_t failed  | ||||
|             ) = 0; | ||||
|          | ||||
|         virtual void StartSection | ||||
|             (   const std::string& sectionName,  | ||||
|                 const std::string description  | ||||
|             ) = 0; | ||||
|          | ||||
|         virtual void EndSection | ||||
|             (   const std::string& sectionName,  | ||||
|                 std::size_t succeeded,  | ||||
|                 std::size_t failed  | ||||
|             ) = 0; | ||||
|          | ||||
|         virtual void StartTestCase | ||||
|             (   const TestCaseInfo& testInfo  | ||||
|             ) = 0; | ||||
|          | ||||
|         virtual void EndTestCase | ||||
|             (   const TestCaseInfo& testInfo,  | ||||
|                 std::size_t succeeded,  | ||||
|                 std::size_t failed, | ||||
|                 const std::string& stdOut,  | ||||
|                 const std::string& stdErr  | ||||
|             ) = 0; | ||||
|          | ||||
|         virtual void Result | ||||
|             (   const ResultInfo& result  | ||||
|             ) = 0; | ||||
|     }; | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     struct IReporterFactory | ||||
|     { | ||||
|         virtual ~IReporterFactory | ||||
|             (){} | ||||
|          | ||||
|         virtual IReporter* create | ||||
|             (   const IReporterConfig& config  | ||||
|             ) const = 0; | ||||
|          | ||||
|         virtual std::string getDescription | ||||
|             () const = 0; | ||||
|     }; | ||||
|  | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     struct IReporterRegistry | ||||
|     { | ||||
|         typedef std::map<std::string, IReporterFactory*> FactoryMap; | ||||
|  | ||||
|         virtual ~IReporterRegistry | ||||
|             (){} | ||||
|  | ||||
|         virtual IReporter* create | ||||
|             (   const std::string& name,  | ||||
|                 const IReporterConfig& config  | ||||
|             ) const = 0; | ||||
|          | ||||
|         virtual void registerReporter | ||||
|             (   const std::string& name,  | ||||
|                 IReporterFactory* factory  | ||||
|             ) = 0; | ||||
|          | ||||
|         virtual const FactoryMap& getFactories | ||||
|             () const = 0; | ||||
|  | ||||
|     }; | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     inline std::string trim( const std::string& str ) | ||||
|     { | ||||
|         std::string::size_type start = str.find_first_not_of( "\n\r\t " ); | ||||
|         std::string::size_type end = str.find_last_not_of( "\n\r\t " ); | ||||
|          | ||||
|         return start < end ? str.substr( start, 1+end-start ) : ""; | ||||
|     } | ||||
|      | ||||
|      | ||||
| } | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_IREPORTERREGISTRY_INCLUDED | ||||
							
								
								
									
										44
									
								
								include/internal/catch_interfaces_runner.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								include/internal/catch_interfaces_runner.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | ||||
| /* | ||||
|  *  catch_interfaces_runner.h | ||||
|  *  Catch | ||||
|  * | ||||
|  *  Created by Phil on 07/01/2011. | ||||
|  *  Copyright 2011 Two Blue Cubes Ltd. All rights reserved. | ||||
|  * | ||||
|  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||
|  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||
|  * | ||||
|  */ | ||||
| #ifndef TWOBLUECUBES_INTERNAL_CATCH_INTERFACES_RUNNER_H_INCLUDED | ||||
| #define TWOBLUECUBES_INTERNAL_CATCH_INTERFACES_RUNNER_H_INCLUDED | ||||
|  | ||||
| #include <string> | ||||
|  | ||||
| namespace Catch | ||||
| { | ||||
|     class TestCaseInfo; | ||||
|      | ||||
|     struct IRunner | ||||
|     { | ||||
|         virtual ~IRunner | ||||
|         () | ||||
|         {} | ||||
|          | ||||
|         virtual void runAll | ||||
|             (   bool runHiddenTests = false | ||||
|             ) = 0; | ||||
|          | ||||
|         virtual std::size_t runMatching | ||||
|             ( const std::string& rawTestSpec  | ||||
|             ) = 0; | ||||
|          | ||||
|         virtual std::size_t getSuccessCount | ||||
|             () const = 0; | ||||
|          | ||||
|         virtual std:: size_t getFailureCount | ||||
|             () const = 0; | ||||
|          | ||||
|     }; | ||||
| } | ||||
|  | ||||
| #endif // TWOBLUECUBES_INTERNAL_CATCH_INTERFACES_RUNNER_H_INCLUDED | ||||
							
								
								
									
										64
									
								
								include/internal/catch_interfaces_testcase.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								include/internal/catch_interfaces_testcase.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | ||||
| /* | ||||
|  *  catch_interfaces_testcase.h | ||||
|  *  Catch | ||||
|  * | ||||
|  *  Created by Phil on 07/01/2011. | ||||
|  *  Copyright 2011 Two Blue Cubes Ltd. All rights reserved. | ||||
|  * | ||||
|  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||
|  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #ifndef TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED | ||||
| #define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED | ||||
|  | ||||
| #include <vector> | ||||
|  | ||||
| namespace Catch | ||||
| { | ||||
|     struct ITestCase | ||||
|     { | ||||
|         virtual ~ITestCase | ||||
|         () | ||||
|         {} | ||||
|          | ||||
|         virtual void invoke | ||||
|             () const = 0; | ||||
|          | ||||
|         virtual ITestCase* clone | ||||
|             () const = 0; | ||||
|          | ||||
|         virtual bool operator ==  | ||||
|             ( const ITestCase& other  | ||||
|             ) const = 0; | ||||
|          | ||||
|         virtual bool operator <  | ||||
|             ( const ITestCase& other  | ||||
|             ) const = 0; | ||||
|     }; | ||||
|      | ||||
|     class TestCaseInfo; | ||||
|  | ||||
|     struct ITestCaseRegistry | ||||
|     { | ||||
|         virtual ~ITestCaseRegistry | ||||
|         () | ||||
|         {} | ||||
|  | ||||
|         virtual void registerTest | ||||
|             ( const TestCaseInfo& testInfo  | ||||
|             ) = 0; | ||||
|          | ||||
|         virtual const std::vector<TestCaseInfo>& getAllTests | ||||
|             () const = 0; | ||||
|  | ||||
|         virtual std::vector<TestCaseInfo> getMatchingTestCases | ||||
|             ( const std::string& rawTestSpec  | ||||
|             ) = 0; | ||||
|     }; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED | ||||
							
								
								
									
										71
									
								
								include/internal/catch_list.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								include/internal/catch_list.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,71 @@ | ||||
| /* | ||||
|  *  catch_list.hpp | ||||
|  *  Catch | ||||
|  * | ||||
|  *  Created by Phil on 5/11/2010. | ||||
|  *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved. | ||||
|  * | ||||
|  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||
|  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #ifndef TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED | ||||
| #define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED | ||||
|  | ||||
| #include "catch_commandline.hpp" | ||||
| #include <limits> | ||||
|  | ||||
| namespace Catch | ||||
| { | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     inline int List | ||||
|     ( | ||||
|         const Config& config | ||||
|     ) | ||||
|     { | ||||
|         if( config.listWhat() & Config::List::Reports ) | ||||
|         { | ||||
|             std::cout << "Available reports:\n"; | ||||
|             IReporterRegistry::FactoryMap::const_iterator it = Hub::getReporterRegistry().getFactories().begin(); | ||||
|             IReporterRegistry::FactoryMap::const_iterator itEnd = Hub::getReporterRegistry().getFactories().end(); | ||||
|             for(; it != itEnd; ++it ) | ||||
|             { | ||||
|                 // !TBD: consider listAs() | ||||
|                 std::cout << "\t" << it->first << "\n\t\t'" << it->second->getDescription() << "'\n"; | ||||
|             } | ||||
|             std::cout << std::endl; | ||||
|         } | ||||
|         if( config.listWhat() & Config::List::Tests ) | ||||
|         { | ||||
|             std::cout << "Available tests:\n"; | ||||
|             std::vector<TestCaseInfo>::const_iterator it = Hub::getTestCaseRegistry().getAllTests().begin(); | ||||
|             std::vector<TestCaseInfo>::const_iterator itEnd = Hub::getTestCaseRegistry().getAllTests().end(); | ||||
|             for(; it != itEnd; ++it ) | ||||
|             { | ||||
|                 // !TBD: consider listAs() | ||||
|                 std::cout << "\t" << it->getName() << "\n\t\t '" << it->getDescription() << "'\n"; | ||||
|             } | ||||
|             std::cout << std::endl; | ||||
|         } | ||||
|         if( ( config.listWhat() & Config::List::All ) == 0 ) | ||||
|         { | ||||
|             std::cerr << "Unknown list type" << std::endl; | ||||
|             return (std::numeric_limits<int>::max)(); | ||||
|         } | ||||
|          | ||||
|         if( config.getReporter() ) | ||||
|         { | ||||
|             std::cerr << "Reporters ignored when listing" << std::endl; | ||||
|         } | ||||
|         if( !config.testsSpecified() ) | ||||
|         { | ||||
|             std::cerr << "Test specs ignored when listing" << std::endl; | ||||
|         } | ||||
|         return 0; | ||||
|  | ||||
|     } | ||||
|      | ||||
| } // end namespace Catch | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED | ||||
							
								
								
									
										59
									
								
								include/internal/catch_reporter_registrars.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								include/internal/catch_reporter_registrars.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | ||||
| /* | ||||
|  *  catch_reporter_registrars.hpp | ||||
|  *  Test | ||||
|  * | ||||
|  *  Created by Phil on 31/12/2010. | ||||
|  *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved. | ||||
|  * | ||||
|  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||
|  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||
|  * | ||||
|  */ | ||||
| #ifndef TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED | ||||
| #define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED | ||||
|  | ||||
| #include "catch_hub.h" | ||||
|  | ||||
| namespace Catch | ||||
| {     | ||||
|     template<typename T> | ||||
|     class ReporterRegistrar | ||||
|     { | ||||
|         class ReporterFactory : public IReporterFactory | ||||
|         { | ||||
|             /////////////////////////////////////////////////////////////////// | ||||
|             virtual IReporter* create | ||||
|             ( | ||||
|                 const IReporterConfig& config  | ||||
|             ) | ||||
|             const | ||||
|             { | ||||
|                 return new T( config ); | ||||
|             } | ||||
|             /////////////////////////////////////////////////////////////////// | ||||
|             virtual std::string getDescription | ||||
|             () | ||||
|             const | ||||
|             { | ||||
|                 return T::getDescription(); | ||||
|             } | ||||
|         }; | ||||
|          | ||||
|     public:         | ||||
|  | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         ReporterRegistrar | ||||
|         ( | ||||
|             const std::string& name | ||||
|         ) | ||||
|         { | ||||
|             Hub::getReporterRegistry().registerReporter( name, new ReporterFactory() ); | ||||
|         } | ||||
|     };  | ||||
| } | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| #define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ | ||||
|     Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED | ||||
							
								
								
									
										69
									
								
								include/internal/catch_reporter_registry.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								include/internal/catch_reporter_registry.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | ||||
| /* | ||||
|  *  catch_reporter_registry.hpp | ||||
|  *  Catch | ||||
|  * | ||||
|  *  Created by Phil on 29/10/2010. | ||||
|  *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved. | ||||
|  * | ||||
|  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||
|  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||
|  * | ||||
|  */ | ||||
| #ifndef TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED | ||||
| #define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED | ||||
|  | ||||
| #include "catch_interfaces_reporter.h" | ||||
|  | ||||
| #include <map> | ||||
|  | ||||
| namespace Catch | ||||
| { | ||||
|     class ReporterRegistry : public IReporterRegistry | ||||
|     { | ||||
|     public: | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         ~ReporterRegistry | ||||
|         () | ||||
|         { | ||||
|             deleteAllValues( m_factories ); | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         virtual IReporter* create | ||||
|         ( | ||||
|             const std::string& name,  | ||||
|             const IReporterConfig& config  | ||||
|         ) | ||||
|         const | ||||
|         { | ||||
|             FactoryMap::const_iterator it =  m_factories.find( name ); | ||||
|             if( it == m_factories.end() ) | ||||
|                 return NULL; | ||||
|             return it->second->create( config ); | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         void registerReporter | ||||
|         ( | ||||
|             const std::string& name,  | ||||
|             IReporterFactory* factory  | ||||
|         ) | ||||
|         { | ||||
|             m_factories.insert( std::make_pair( name, factory ) ); | ||||
|         }         | ||||
|  | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         const FactoryMap& getFactories | ||||
|         () | ||||
|         const | ||||
|         { | ||||
|             return m_factories; | ||||
|         } | ||||
|  | ||||
|     private: | ||||
|         FactoryMap m_factories; | ||||
|     }; | ||||
| } | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED | ||||
							
								
								
									
										51
									
								
								include/internal/catch_result_type.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								include/internal/catch_result_type.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | ||||
| /* | ||||
|  *  catch_result_type.h | ||||
|  *  Catch | ||||
|  * | ||||
|  *  Created by Phil on 07/01/2011. | ||||
|  *  Copyright 2011 Two Blue Cubes Ltd. All rights reserved. | ||||
|  * | ||||
|  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||
|  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #ifndef TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED | ||||
| #define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED | ||||
|  | ||||
| namespace Catch | ||||
| {     | ||||
|  | ||||
| struct ResultWas{ enum OfType | ||||
|     { | ||||
|         Unknown = -1, | ||||
|         Ok = 0, | ||||
|         Info = 1, | ||||
|         Warning = 2, | ||||
|          | ||||
|         FailureBit = 0x10, | ||||
|          | ||||
|         ExpressionFailed = FailureBit | 1, | ||||
|         ExplicitFailure = FailureBit | 2, | ||||
|          | ||||
|         Exception = 0x100 | FailureBit, | ||||
|          | ||||
|         ThrewException = Exception | 1, | ||||
|         DidntThrowException = Exception | 2 | ||||
|          | ||||
|     }; }; | ||||
|  | ||||
|     struct ResultAction | ||||
|     { | ||||
|         enum Value | ||||
|         { | ||||
|             None, | ||||
|             Failed = 1,     // Failure - but no debug break if Debug bit not set | ||||
|             DebugFailed = 3 // Indicates that the debugger should break, if possible | ||||
|         };     | ||||
|     }; | ||||
|      | ||||
| } | ||||
|  | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED | ||||
							
								
								
									
										173
									
								
								include/internal/catch_resultinfo.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										173
									
								
								include/internal/catch_resultinfo.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,173 @@ | ||||
| /* | ||||
|  *  catch_resultinfo.hpp | ||||
|  *  Catch | ||||
|  * | ||||
|  *  Created by Phil on 28/10/2010. | ||||
|  *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved. | ||||
|  * | ||||
|  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||
|  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||
|  * | ||||
|  */ | ||||
| #ifndef TWOBLUECUBES_CATCH_RESULT_INFO_HPP_INCLUDED | ||||
| #define TWOBLUECUBES_CATCH_RESULT_INFO_HPP_INCLUDED | ||||
|  | ||||
| #include <string> | ||||
| #include "catch_result_type.h" | ||||
|  | ||||
| namespace Catch | ||||
| {     | ||||
|     class ResultInfo | ||||
|     { | ||||
|     public: | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         ResultInfo | ||||
|         () | ||||
|         :   m_line( 0 ), | ||||
|             m_result( ResultWas::Unknown ), | ||||
|             m_isNot( false ) | ||||
|         {} | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         ResultInfo | ||||
|         ( | ||||
|             const char* expr,  | ||||
|             ResultWas::OfType result,  | ||||
|             bool isNot,  | ||||
|             const char* filename,  | ||||
|             std::size_t line,  | ||||
|             const char* macroName, | ||||
|             const char* message | ||||
|         ) | ||||
|         :   m_macroName( macroName ), | ||||
|             m_filename( filename ), | ||||
|             m_line( line ), | ||||
|             m_expr( expr ), | ||||
|             m_op( isNotExpression( expr ) ? "!" : "" ), | ||||
|             m_message( message ), | ||||
|             m_result( result ), | ||||
|             m_isNot( isNot ) | ||||
|         { | ||||
|             if( isNot ) | ||||
|                 m_expr = "!" + m_expr; | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         bool ok | ||||
|         () | ||||
|         const | ||||
|         { | ||||
|             return ( m_result & ResultWas::FailureBit ) != ResultWas::FailureBit; | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         ResultWas::OfType getResultType | ||||
|         () | ||||
|         const | ||||
|         { | ||||
|             return m_result; | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         bool hasExpression | ||||
|         () | ||||
|         const | ||||
|         { | ||||
|             return !m_expr.empty(); | ||||
|         } | ||||
|  | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         bool hasMessage | ||||
|         () | ||||
|         const | ||||
|         { | ||||
|             return !m_message.empty(); | ||||
|         } | ||||
|  | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         std::string getExpression | ||||
|         () | ||||
|         const | ||||
|         { | ||||
|             return m_expr; | ||||
|         } | ||||
|  | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         std::string getExpandedExpression | ||||
|         () | ||||
|         const | ||||
|         { | ||||
|             return hasExpression() ? getExpandedExpressionInternal() : ""; | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         std::string getMessage | ||||
|         () | ||||
|         const | ||||
|         { | ||||
|             return m_message; | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         std::string getFilename | ||||
|         () | ||||
|         const | ||||
|         { | ||||
|             return m_filename; | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         std::size_t getLine | ||||
|         () | ||||
|         const | ||||
|         { | ||||
|             return m_line; | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         std::string getTestMacroName | ||||
|         () | ||||
|         const | ||||
|         { | ||||
|             return m_macroName; | ||||
|         } | ||||
|  | ||||
|     protected: | ||||
|  | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         std::string getExpandedExpressionInternal | ||||
|         () | ||||
|         const | ||||
|         { | ||||
|             if( m_op == "" || m_isNot ) | ||||
|                 return m_lhs.empty() ? m_expr : m_op + m_lhs; | ||||
|             else if( m_op != "!" ) | ||||
|                 return m_lhs + " " + m_op + " " + m_rhs; | ||||
|             else | ||||
|                 return "{can't expand - use " + m_macroName + "_NOT( " + m_expr.substr(1) + " ) instead of " + m_macroName + "( " + m_expr + " ) for better diagnostics}"; | ||||
|         } | ||||
|  | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         bool isNotExpression | ||||
|         ( | ||||
|             const char* expr | ||||
|         ) | ||||
|         { | ||||
|             return expr && expr[0] == '!'; | ||||
|         }         | ||||
|          | ||||
|     protected: | ||||
|         std::string m_macroName; | ||||
|         std::string m_filename; | ||||
|         std::size_t m_line; | ||||
|         std::string m_expr, m_lhs, m_rhs, m_op; | ||||
|         std::string m_message; | ||||
|         ResultWas::OfType m_result; | ||||
|         bool m_isNot; | ||||
|     }; | ||||
|      | ||||
| } // end namespace Catch | ||||
|  | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_RESULT_INFO_HPP_INCLUDED | ||||
							
								
								
									
										609
									
								
								include/internal/catch_runner_impl.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										609
									
								
								include/internal/catch_runner_impl.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,609 @@ | ||||
| /* | ||||
|  *  catch_runner.hpp | ||||
|  *  Catch | ||||
|  * | ||||
|  *  Created by Phil on 22/10/2010. | ||||
|  *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved. | ||||
|  * | ||||
|  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||
|  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||
|  * | ||||
|  */ | ||||
| #ifndef TWOBLUECUBES_INTERNAL_CATCH_RUNNER_HPP_INCLUDED | ||||
| #define TWOBLUECUBES_INTERNAL_CATCH_RUNNER_HPP_INCLUDED | ||||
|  | ||||
| #include "catch_interfaces_runner.h" | ||||
| #include "catch_interfaces_reporter.h" | ||||
| #include "catch_config.hpp" | ||||
| #include "catch_test_registry.hpp" | ||||
| #include "catch_test_case_info.hpp" | ||||
| #include "catch_capture.hpp" | ||||
|  | ||||
| #include <set> | ||||
| #include <string> | ||||
|  | ||||
| namespace Catch | ||||
| { | ||||
|      | ||||
|     class StreamRedirect | ||||
|     { | ||||
|     public: | ||||
|         ///////////////////////////////////////////////////////////////////////         | ||||
|         StreamRedirect | ||||
|         ( | ||||
|             std::ostream& stream,  | ||||
|             std::string& targetString | ||||
|         ) | ||||
|         :   m_stream( stream ), | ||||
|             m_prevBuf( stream.rdbuf() ), | ||||
|             m_targetString( targetString ) | ||||
|         {             | ||||
|             stream.rdbuf( m_oss.rdbuf() ); | ||||
|         } | ||||
|          | ||||
|         ///////////////////////////////////////////////////////////////////////         | ||||
|         ~StreamRedirect | ||||
|         () | ||||
|         { | ||||
|             m_targetString = m_oss.str(); | ||||
|             m_stream.rdbuf( m_prevBuf ); | ||||
|         } | ||||
|          | ||||
|     private: | ||||
|         std::ostream& m_stream; | ||||
|         std::streambuf* m_prevBuf; | ||||
|         std::ostringstream m_oss; | ||||
|         std::string& m_targetString; | ||||
|     }; | ||||
|      | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     ///////////////////////////////////////////////////////////////////////////     | ||||
|     class SectionInfo | ||||
|     { | ||||
|     public: | ||||
|         enum Status | ||||
|         { | ||||
|             Root, | ||||
|             Unknown, | ||||
|             NonLeaf, | ||||
|             UntestedLeaf, | ||||
|             TestedLeaf | ||||
|         }; | ||||
|          | ||||
|         ///////////////////////////////////////////////////////////////////////         | ||||
|         SectionInfo | ||||
|         ( | ||||
|             SectionInfo* parent | ||||
|         ) | ||||
|         :   m_status( Unknown ), | ||||
|             m_parent( parent ) | ||||
|         { | ||||
|         } | ||||
|  | ||||
|         ///////////////////////////////////////////////////////////////////////         | ||||
|         SectionInfo | ||||
|         () | ||||
|         :   m_status( Root ), | ||||
|             m_parent( NULL ) | ||||
|         { | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         ~SectionInfo | ||||
|         () | ||||
|         { | ||||
|             deleteAllValues( m_subSections ); | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         bool shouldRun | ||||
|         () | ||||
|         const | ||||
|         { | ||||
|             return m_status != TestedLeaf; | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         bool ran | ||||
|         () | ||||
|         { | ||||
|             if( m_status != NonLeaf ) | ||||
|             { | ||||
|                 m_status = TestedLeaf; | ||||
|                 return true; | ||||
|             } | ||||
|             return false; | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         SectionInfo* getSubSection | ||||
|         ( | ||||
|             const std::string& name | ||||
|         ) | ||||
|         { | ||||
|             std::map<std::string, SectionInfo*>::const_iterator it = m_subSections.find( name ); | ||||
|             if( it != m_subSections.end() ) | ||||
|                 return it->second; | ||||
|              | ||||
|             SectionInfo* subSection = new SectionInfo( this ); | ||||
|             m_subSections.insert( std::make_pair( name, subSection ) ); | ||||
|             m_status = NonLeaf; | ||||
|             return subSection; | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         SectionInfo* getParent | ||||
|         () | ||||
|         { | ||||
|             return m_parent; | ||||
|         } | ||||
|          | ||||
|         ///////////////////////////////////////////////////////////////////////         | ||||
|         bool hasUntestedSections | ||||
|         () | ||||
|         const | ||||
|         { | ||||
|             if( m_status == Unknown || m_status == UntestedLeaf ) | ||||
|                 return true; | ||||
|              | ||||
|             std::map<std::string, SectionInfo*>::const_iterator it = m_subSections.begin(); | ||||
|             std::map<std::string, SectionInfo*>::const_iterator itEnd = m_subSections.end(); | ||||
|             for(; it != itEnd; ++it ) | ||||
|             { | ||||
|                 if( it->second->hasUntestedSections() ) | ||||
|                     return true; | ||||
|             } | ||||
|             return false; | ||||
|         } | ||||
|      | ||||
|     private: | ||||
|         Status m_status; | ||||
|         std::map<std::string, SectionInfo*> m_subSections; | ||||
|         SectionInfo* m_parent; | ||||
|     }; | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
|     class RunningTest | ||||
|     { | ||||
|         enum RunStatus | ||||
|         { | ||||
|             NothingRun, | ||||
|             EncounteredASection, | ||||
|             RanAtLeastOneSection, | ||||
|             RanToCompletionWithSections, | ||||
|             RanToCompletionWithNoSections | ||||
|         }; | ||||
|          | ||||
|     public: | ||||
|         ///////////////////////////////////////////////////////////////////////         | ||||
|         explicit RunningTest | ||||
|         ( | ||||
|             const TestCaseInfo* info = NULL  | ||||
|         ) | ||||
|         :   m_info( info ), | ||||
|             m_runStatus( RanAtLeastOneSection ), | ||||
|             m_currentSection( &m_rootSection ) | ||||
|         { | ||||
|         } | ||||
|          | ||||
|         ///////////////////////////////////////////////////////////////////////         | ||||
|         bool wasSectionSeen | ||||
|         () | ||||
|         const | ||||
|         { | ||||
|             return  m_runStatus == RanAtLeastOneSection ||  | ||||
|                     m_runStatus == RanToCompletionWithSections; | ||||
|         } | ||||
|  | ||||
|         ///////////////////////////////////////////////////////////////////////         | ||||
|         void reset | ||||
|         () | ||||
|         { | ||||
|             m_runStatus = NothingRun; | ||||
|         } | ||||
|  | ||||
|         ///////////////////////////////////////////////////////////////////////         | ||||
|         void ranToCompletion | ||||
|         () | ||||
|         { | ||||
|             m_runStatus =   m_runStatus == RanAtLeastOneSection || | ||||
|                             m_runStatus == EncounteredASection | ||||
|                 ? RanToCompletionWithSections | ||||
|                 : RanToCompletionWithNoSections; | ||||
|         } | ||||
|          | ||||
|         ///////////////////////////////////////////////////////////////////////         | ||||
|         bool addSection | ||||
|         ( | ||||
|             const std::string& name | ||||
|         ) | ||||
|         { | ||||
|             if( m_runStatus == NothingRun ) | ||||
|                 m_runStatus = EncounteredASection; | ||||
|              | ||||
|             SectionInfo* thisSection = m_currentSection->getSubSection( name ); | ||||
|              | ||||
|             if( !wasSectionSeen() && thisSection->shouldRun() ) | ||||
|             { | ||||
|                 m_currentSection = thisSection; | ||||
|                 return true; | ||||
|             } | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         ///////////////////////////////////////////////////////////////////////         | ||||
|         void endSection | ||||
|         ( | ||||
|             const std::string& | ||||
|         ) | ||||
|         { | ||||
|             if( m_currentSection->ran() ) | ||||
|                 m_runStatus = RanAtLeastOneSection; | ||||
|             m_currentSection = m_currentSection->getParent(); | ||||
|         } | ||||
|  | ||||
|         ///////////////////////////////////////////////////////////////////////         | ||||
|         const TestCaseInfo& getTestCaseInfo | ||||
|         () | ||||
|         const | ||||
|         { | ||||
|             return *m_info; | ||||
|         } | ||||
|          | ||||
|         ///////////////////////////////////////////////////////////////////////         | ||||
|         bool hasUntestedSections | ||||
|         () | ||||
|         const | ||||
|         { | ||||
|             return  m_rootSection.hasUntestedSections() || | ||||
|                     m_runStatus == RanAtLeastOneSection; | ||||
|         } | ||||
|          | ||||
|     private: | ||||
|         const TestCaseInfo* m_info; | ||||
|         RunStatus m_runStatus; | ||||
|         SectionInfo m_rootSection; | ||||
|         SectionInfo* m_currentSection; | ||||
|     }; | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     ///////////////////////////////////////////////////////////////////////////     | ||||
|     class Runner : public IResultCapture, public IRunner | ||||
|     { | ||||
|         Runner( const Runner& ); | ||||
|         void operator =( const Runner& ); | ||||
|          | ||||
|     public: | ||||
|  | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         explicit Runner | ||||
|         ( | ||||
|             const Config& config  | ||||
|         ) | ||||
|         :   m_runningTest( NULL ), | ||||
|             m_config( config ), | ||||
|             m_successes( 0 ), | ||||
|             m_failures( 0 ), | ||||
|             m_reporter( m_config.getReporter() ), | ||||
|             m_prevRunner( &Hub::getRunner() ), | ||||
|             m_prevResultCapture( &Hub::getResultCapture() ) | ||||
|         { | ||||
|             Hub::setRunner( this ); | ||||
|             Hub::setResultCapture( this ); | ||||
|             m_reporter->StartTesting(); | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         ~Runner | ||||
|         () | ||||
|         { | ||||
|             m_reporter->EndTesting( m_successes, m_failures ); | ||||
|             Hub::setRunner( m_prevRunner ); | ||||
|             Hub::setResultCapture( m_prevResultCapture ); | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         virtual void runAll | ||||
|         ( | ||||
|             bool runHiddenTests = false | ||||
|         ) | ||||
|         { | ||||
|             std::vector<TestCaseInfo> allTests = Hub::getTestCaseRegistry().getAllTests(); | ||||
|             for( std::size_t i=0; i < allTests.size(); ++i ) | ||||
|             { | ||||
|                 if( runHiddenTests || !allTests[i].isHidden() ) | ||||
|                    runTest( allTests[i] ); | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         virtual std::size_t runMatching | ||||
|         ( | ||||
|             const std::string& rawTestSpec | ||||
|         ) | ||||
|         { | ||||
|             TestSpec testSpec( rawTestSpec ); | ||||
|              | ||||
|             std::vector<TestCaseInfo> allTests = Hub::getTestCaseRegistry().getAllTests(); | ||||
|             std::size_t testsRun = 0; | ||||
|             for( std::size_t i=0; i < allTests.size(); ++i ) | ||||
|             { | ||||
|                 if( testSpec.matches( allTests[i].getName() ) ) | ||||
|                 { | ||||
|                     runTest( allTests[i] ); | ||||
|                     testsRun++; | ||||
|                 } | ||||
|             } | ||||
|             return testsRun; | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         void runTest | ||||
|         ( | ||||
|             const TestCaseInfo& testInfo | ||||
|         ) | ||||
|         { | ||||
|             std::size_t prevSuccessCount = m_successes; | ||||
|             std::size_t prevFailureCount = m_failures; | ||||
|  | ||||
|             std::string redirectedCout; | ||||
|             std::string redirectedCerr; | ||||
|              | ||||
|             m_reporter->StartTestCase( testInfo ); | ||||
|              | ||||
|             m_runningTest = new RunningTest( &testInfo ); | ||||
|  | ||||
|             do | ||||
|             { | ||||
|                 do | ||||
|                 { | ||||
|                     m_currentResult.setFileAndLine( m_runningTest->getTestCaseInfo().getFilename(),  | ||||
|                                                     m_runningTest->getTestCaseInfo().getLine() ); | ||||
|                     runCurrentTest( redirectedCout, redirectedCerr ); | ||||
|                 } | ||||
|                 while( m_runningTest->hasUntestedSections() ); | ||||
|             } | ||||
|             while( Hub::advanceGeneratorsForCurrentTest() ); | ||||
|  | ||||
|             delete m_runningTest; | ||||
|             m_runningTest = NULL; | ||||
|  | ||||
|             m_reporter->EndTestCase( testInfo, m_successes - prevSuccessCount, m_failures - prevFailureCount, redirectedCout, redirectedCerr ); | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         virtual std::size_t getSuccessCount | ||||
|         () | ||||
|         const | ||||
|         { | ||||
|             return m_successes; | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         virtual std:: size_t getFailureCount | ||||
|         () | ||||
|         const | ||||
|         { | ||||
|             return m_failures; | ||||
|         } | ||||
|  | ||||
|     private: // IResultCapture | ||||
|  | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         virtual ResultAction::Value acceptResult | ||||
|         ( | ||||
|             bool result | ||||
|         ) | ||||
|         { | ||||
|             return acceptResult( result ? ResultWas::Ok : ResultWas::ExpressionFailed ); | ||||
|         } | ||||
|  | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         virtual ResultAction::Value acceptResult | ||||
|         ( | ||||
|             ResultWas::OfType result | ||||
|         ) | ||||
|         { | ||||
|             m_currentResult.setResultType( result );             | ||||
|             return actOnCurrentResult(); | ||||
|         } | ||||
|  | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         virtual ResultAction::Value acceptExpression | ||||
|         ( | ||||
|             const MutableResultInfo& resultInfo | ||||
|         ) | ||||
|         { | ||||
|             m_currentResult = resultInfo; | ||||
|             return actOnCurrentResult(); | ||||
|         } | ||||
|  | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         virtual void acceptMessage | ||||
|         ( | ||||
|             const std::string& msg | ||||
|         ) | ||||
|         { | ||||
|             m_currentResult.setMessage( msg ); | ||||
|         } | ||||
|                  | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         virtual void testEnded | ||||
|         ( | ||||
|             const ResultInfo& result         | ||||
|         ) | ||||
|         {  | ||||
|             if( result.getResultType() == ResultWas::Ok ) | ||||
|             { | ||||
|                 m_successes++; | ||||
|             } | ||||
|             else if( !result.ok() ) | ||||
|             { | ||||
|                 m_failures++; | ||||
|  | ||||
|                 std::vector<ResultInfo>::const_iterator it = m_info.begin(); | ||||
|                 std::vector<ResultInfo>::const_iterator itEnd = m_info.end(); | ||||
|                 for(; it != itEnd; ++it ) | ||||
|                     m_reporter->Result( *it ); | ||||
|                 m_info.clear(); | ||||
|             } | ||||
|              | ||||
|             if( result.getResultType() == ResultWas::Info ) | ||||
|                 m_info.push_back( result ); | ||||
|             else | ||||
|                 m_reporter->Result( result ); | ||||
|         } | ||||
|  | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         virtual bool sectionStarted | ||||
|         ( | ||||
|             const std::string& name,  | ||||
|             const std::string& description, | ||||
|             const std::string& filename, | ||||
|             std::size_t line, | ||||
|             std::size_t& successes, | ||||
|             std::size_t& failures  | ||||
|         ) | ||||
|         { | ||||
|             std::ostringstream oss; | ||||
|             oss << filename << ":" << line; | ||||
|  | ||||
|             if( !m_runningTest->addSection( oss.str() ) ) | ||||
|                 return false; | ||||
|  | ||||
|             m_currentResult.setFileAndLine( filename, line ); | ||||
|             m_reporter->StartSection( name, description ); | ||||
|             successes = m_successes; | ||||
|             failures = m_failures; | ||||
|              | ||||
|             return true; | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         virtual void sectionEnded | ||||
|         ( | ||||
|             const std::string& name,  | ||||
|             std::size_t prevSuccesses,  | ||||
|             std::size_t prevFailures  | ||||
|         ) | ||||
|         { | ||||
|             m_runningTest->endSection( name ); | ||||
|             m_reporter->EndSection( name, m_successes - prevSuccesses, m_failures - prevFailures ); | ||||
|         } | ||||
|  | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         virtual void pushScopedInfo | ||||
|         ( | ||||
|             ScopedInfo* scopedInfo  | ||||
|         ) | ||||
|         { | ||||
|             m_scopedInfos.push_back( scopedInfo ); | ||||
|         } | ||||
|  | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         virtual void popScopedInfo | ||||
|         ( | ||||
|             ScopedInfo* scopedInfo | ||||
|         ) | ||||
|         { | ||||
|             if( m_scopedInfos.back() == scopedInfo ) | ||||
|                 m_scopedInfos.pop_back(); | ||||
|         } | ||||
|  | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         virtual bool shouldDebugBreak | ||||
|         ()  | ||||
|         const | ||||
|         { | ||||
|             return m_config.shouldDebugBreak(); | ||||
|         } | ||||
|  | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         virtual std::string getCurrentTestName | ||||
|         ()  | ||||
|         const | ||||
|         { | ||||
|             return m_runningTest | ||||
|                 ? m_runningTest->getTestCaseInfo().getName() | ||||
|                 : ""; | ||||
|         } | ||||
|          | ||||
|     private: | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         ResultAction::Value actOnCurrentResult | ||||
|         () | ||||
|         { | ||||
|             testEnded( m_currentResult ); | ||||
|              | ||||
|             bool ok = m_currentResult.ok(); | ||||
|             m_currentResult = MutableResultInfo(); | ||||
|             if( ok ) | ||||
|                 return ResultAction::None; | ||||
|             else if( shouldDebugBreak() ) | ||||
|                 return ResultAction::DebugFailed; | ||||
|             else | ||||
|                 return ResultAction::Failed; | ||||
|         } | ||||
|  | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         void runCurrentTest | ||||
|         ( | ||||
|             std::string& redirectedCout, | ||||
|             std::string& redirectedCerr | ||||
|         ) | ||||
|         {             | ||||
|             try | ||||
|             { | ||||
|                 m_runningTest->reset(); | ||||
|                 StreamRedirect coutRedir( std::cout, redirectedCout ); | ||||
|                 StreamRedirect cerrRedir( std::cerr, redirectedCerr ); | ||||
|                 m_runningTest->getTestCaseInfo().invoke(); | ||||
|                 m_runningTest->ranToCompletion(); | ||||
|             } | ||||
|             catch( TestFailureException& ) | ||||
|             { | ||||
|                 // This just means the test was aborted due to failure | ||||
|             } | ||||
|             catch( std::exception& ex ) | ||||
|             { | ||||
|                 acceptMessage( ex.what() ); | ||||
|                 acceptResult( ResultWas::ThrewException ); | ||||
|             } | ||||
|             catch( std::string& msg ) | ||||
|             { | ||||
|                 acceptMessage( msg ); | ||||
|                 acceptResult( ResultWas::ThrewException ); | ||||
|             } | ||||
|             catch( const char* msg ) | ||||
|             { | ||||
|                 acceptMessage( msg ); | ||||
|                 acceptResult( ResultWas::ThrewException ); | ||||
|             } | ||||
|             catch(...) | ||||
|             { | ||||
|                 acceptMessage( Catch::Hub::getExceptionTranslatorRegistry().translateActiveException() ); | ||||
|                 acceptResult( ResultWas::ThrewException ); | ||||
|             } | ||||
|             m_info.clear(); | ||||
|         } | ||||
|          | ||||
|     private: | ||||
|         RunningTest* m_runningTest; | ||||
|         MutableResultInfo m_currentResult; | ||||
|  | ||||
|         const Config& m_config; | ||||
|         std::size_t m_successes; | ||||
|         std::size_t m_failures; | ||||
|         IReporter* m_reporter; | ||||
|         std::vector<ScopedInfo*> m_scopedInfos; | ||||
|         std::vector<ResultInfo> m_info; | ||||
|         IRunner* m_prevRunner; | ||||
|         IResultCapture* m_prevResultCapture; | ||||
|     }; | ||||
| } | ||||
|  | ||||
| #endif // TWOBLUECUBES_INTERNAL_CATCH_RUNNER_HPP_INCLUDED | ||||
							
								
								
									
										67
									
								
								include/internal/catch_section.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								include/internal/catch_section.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,67 @@ | ||||
| /* | ||||
|  *  catch_section.hpp | ||||
|  *  Catch | ||||
|  * | ||||
|  *  Created by Phil on 03/11/2010. | ||||
|  *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved. | ||||
|  * | ||||
|  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||
|  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #ifndef TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED | ||||
| #define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED | ||||
|  | ||||
| #include "catch_capture.hpp" | ||||
|  | ||||
| #include <string> | ||||
|  | ||||
| namespace Catch | ||||
| { | ||||
|     class Section | ||||
|     { | ||||
|     public: | ||||
|         ///////////////////////////////////////////////////////////////////////         | ||||
|         Section | ||||
|         ( | ||||
|             const std::string& name,  | ||||
|             const std::string& description, | ||||
|             const std::string& filename, | ||||
|             std::size_t line | ||||
|         ) | ||||
|         :   m_name( name ), | ||||
|             m_sectionIncluded( Hub::getResultCapture().sectionStarted( name, description, filename, line, m_successes, m_failures ) ) | ||||
|         { | ||||
|         } | ||||
|  | ||||
|         ///////////////////////////////////////////////////////////////////////         | ||||
|         ~Section | ||||
|         () | ||||
|         { | ||||
|             if( m_sectionIncluded ) | ||||
|                 Hub::getResultCapture().sectionEnded( m_name, m_successes, m_failures ); | ||||
|         } | ||||
|          | ||||
|         ///////////////////////////////////////////////////////////////////////         | ||||
|         // This indicates whether the section should be executed or not | ||||
|         operator bool | ||||
|         () | ||||
|         { | ||||
|             return m_sectionIncluded; | ||||
|         } | ||||
|  | ||||
|     private: | ||||
|          | ||||
|         std::string m_name; | ||||
|         std::size_t m_successes; | ||||
|         std::size_t m_failures; | ||||
|         bool m_sectionIncluded; | ||||
|     }; | ||||
|      | ||||
| } // end namespace Catch | ||||
|  | ||||
| #define INTERNAL_CATCH_SECTION( name, desc ) \ | ||||
|     if( Catch::Section INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( name, desc, __FILE__, __LINE__ ) ) | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED | ||||
							
								
								
									
										154
									
								
								include/internal/catch_self_test.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								include/internal/catch_self_test.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,154 @@ | ||||
| /* | ||||
|  *  catch_self_test.hpp | ||||
|  *  Catch | ||||
|  * | ||||
|  *  Created by Phil on 14/01/2011. | ||||
|  *  Copyright 2011 Two Blue Cubes Ltd. All rights reserved. | ||||
|  * | ||||
|  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||
|  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||
|  * | ||||
|  */ | ||||
| #ifndef TWOBLUECUBES_CATCH_SELF_TEST_HPP_INCLUDED | ||||
| #define TWOBLUECUBES_CATCH_SELF_TEST_HPP_INCLUDED | ||||
|  | ||||
| #include "../catch.hpp" | ||||
| #include "catch_runner_impl.hpp" | ||||
|  | ||||
| namespace Catch | ||||
| { | ||||
|  | ||||
|     class EmbeddedRunner | ||||
|     { | ||||
|     public: | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         EmbeddedRunner | ||||
|         () | ||||
|         { | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         std::size_t runMatching | ||||
|         ( | ||||
|             const std::string& rawTestSpec | ||||
|         ) | ||||
|         { | ||||
|             std::ostringstream oss; | ||||
|             Config config; | ||||
|             config.setStreamBuf( oss.rdbuf() ); | ||||
|             config.setReporter( "basic" ); | ||||
|  | ||||
|             std::size_t result; | ||||
|              | ||||
|             // Scoped because Runner doesn't report EndTesting until its destructor | ||||
|             { | ||||
|                 Runner runner( config ); | ||||
|                 result = runner.runMatching( rawTestSpec ); | ||||
|                 m_successes = runner.getSuccessCount(); | ||||
|                 m_failures = runner.getFailureCount(); | ||||
|             } | ||||
|             m_output = oss.str(); | ||||
|             return result; | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         std::string getOutput | ||||
|         () | ||||
|         { | ||||
|             return m_output; | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         std::size_t getSuccessCount | ||||
|         () | ||||
|         const | ||||
|         { | ||||
|             return m_successes; | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         std:: size_t getFailureCount | ||||
|         () | ||||
|         const | ||||
|         { | ||||
|             return m_failures; | ||||
|         } | ||||
|  | ||||
|     private: | ||||
|         std::size_t m_successes; | ||||
|         std::size_t m_failures; | ||||
|         std::string m_output; | ||||
|     }; | ||||
|  | ||||
|     class MetaTestRunner | ||||
|     { | ||||
|     public: | ||||
|         struct Expected | ||||
|         { | ||||
|             enum Result | ||||
|             { | ||||
|                 ToSucceed, | ||||
|                 ToFail | ||||
|             }; | ||||
|         }; | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         static void runMatching | ||||
|         ( | ||||
|             const std::string& testSpec,  | ||||
|             Expected::Result expectedResult | ||||
|         ) | ||||
|         { | ||||
|             forEach(    Hub::getTestCaseRegistry().getMatchingTestCases( testSpec ),  | ||||
|                         MetaTestRunner( expectedResult ) ); | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         MetaTestRunner | ||||
|         ( | ||||
|             Expected::Result expectedResult | ||||
|         ) | ||||
|         : m_expectedResult( expectedResult ) | ||||
|         {         | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         void operator() | ||||
|         ( | ||||
|             const TestCaseInfo& testCase | ||||
|         ) | ||||
|         { | ||||
|             EmbeddedRunner runner; | ||||
|             runner.runMatching( testCase.getName() ); | ||||
|             switch( m_expectedResult ) | ||||
|             { | ||||
|                 case Expected::ToSucceed: | ||||
|                     if( runner.getFailureCount() > 0 ) | ||||
|                     { | ||||
|                         INFO( runner.getOutput() ); | ||||
|                         FAIL( "Expected test case '"  | ||||
|                              << testCase.getName()  | ||||
|                              << "' to succeed but there was/ were "  | ||||
|                              << runner.getFailureCount() << " failure(s)" ); | ||||
|                     } | ||||
|                     break; | ||||
|                 case Expected::ToFail: | ||||
|                     if( runner.getSuccessCount() > 0 ) | ||||
|                     { | ||||
|                         INFO( runner.getOutput() ); | ||||
|                         FAIL( "Expected test case '"  | ||||
|                              << testCase.getName()  | ||||
|                              << "' to fail but there was/ were "  | ||||
|                              << runner.getSuccessCount() << " success(es)" ); | ||||
|                     } | ||||
|                     break; | ||||
|             }         | ||||
|         }; | ||||
|          | ||||
|     private: | ||||
|         Expected::Result m_expectedResult; | ||||
|     }; | ||||
|      | ||||
| } | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_SELF_TEST_HPP_INCLUDED | ||||
							
								
								
									
										90
									
								
								include/internal/catch_stream.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								include/internal/catch_stream.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,90 @@ | ||||
| /* | ||||
|  *  catch_stream.hpp | ||||
|  *  Catch | ||||
|  * | ||||
|  *  Created by Phil on 17/01/2011. | ||||
|  *  Copyright 2011 Two Blue Cubes Ltd. All rights reserved. | ||||
|  * | ||||
|  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||
|  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #ifndef TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED | ||||
| #define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED | ||||
|  | ||||
| #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 | ||||
|         () | ||||
|         { | ||||
|             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(), pptr() - pbase() ) ); | ||||
|                 setp( pbase(), epptr() ); | ||||
|             } | ||||
|             return 0; | ||||
|         } | ||||
|     }; | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
|     struct OutputDebugWriter | ||||
|     { | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         void operator() | ||||
|         ( | ||||
|             const std::string &str | ||||
|         ) | ||||
|         { | ||||
|             writeToDebugConsole( str ); | ||||
|         } | ||||
|     }; | ||||
| } | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED | ||||
							
								
								
									
										227
									
								
								include/internal/catch_test_case_info.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										227
									
								
								include/internal/catch_test_case_info.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,227 @@ | ||||
| /* | ||||
|  *  catch_test_case_info.hpp | ||||
|  *  Catch | ||||
|  * | ||||
|  *  Created by Phil on 29/10/2010. | ||||
|  *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved. | ||||
|  * | ||||
|  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||
|  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #ifndef TWOBLUECUBES_CATCH_TESTCASEINFO_HPP_INCLUDED | ||||
| #define TWOBLUECUBES_CATCH_TESTCASEINFO_HPP_INCLUDED | ||||
|  | ||||
| #include "catch_interfaces_testcase.h" | ||||
| #include <map> | ||||
| #include <string> | ||||
|  | ||||
| namespace Catch | ||||
| { | ||||
|     class TestCaseInfo | ||||
|     { | ||||
|     public: | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         TestCaseInfo | ||||
|         ( | ||||
|             ITestCase* testCase,  | ||||
|             const char* name,  | ||||
|             const char* description, | ||||
|             const char* filename, | ||||
|             std::size_t line | ||||
|         ) | ||||
|         :   m_test( testCase ), | ||||
|             m_name( name ), | ||||
|             m_description( description ), | ||||
|             m_filename( filename ), | ||||
|             m_line( line ) | ||||
|         { | ||||
|         } | ||||
|  | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         TestCaseInfo | ||||
|         () | ||||
|         :   m_test( NULL ) | ||||
|         { | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         TestCaseInfo | ||||
|         ( | ||||
|             const TestCaseInfo& other | ||||
|         ) | ||||
|         :   m_test( other.m_test->clone() ), | ||||
|             m_name( other.m_name ), | ||||
|             m_description( other.m_description ), | ||||
|             m_filename( other.m_filename ), | ||||
|             m_line( other.m_line ) | ||||
|         { | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         TestCaseInfo | ||||
|         ( | ||||
|             const TestCaseInfo& other, | ||||
|             const std::string& name | ||||
|         ) | ||||
|         :   m_test( other.m_test->clone() ), | ||||
|             m_name( name ), | ||||
|             m_description( other.m_description ), | ||||
|             m_filename( other.m_filename ), | ||||
|             m_line( other.m_line ) | ||||
|         { | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         TestCaseInfo& operator =  | ||||
|         ( | ||||
|             const TestCaseInfo& other  | ||||
|         ) | ||||
|         { | ||||
|             TestCaseInfo temp( other ); | ||||
|             swap( temp ); | ||||
|             return *this; | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         ~TestCaseInfo | ||||
|         () | ||||
|         { | ||||
|             delete m_test; | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         void invoke | ||||
|         () | ||||
|         const | ||||
|         { | ||||
|             m_test->invoke(); | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         const std::string& getName | ||||
|         () | ||||
|         const | ||||
|         { | ||||
|             return m_name; | ||||
|         } | ||||
|  | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         const std::string& getDescription | ||||
|         () | ||||
|         const | ||||
|         { | ||||
|             return m_description; | ||||
|         } | ||||
|  | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         const std::string& getFilename | ||||
|         () | ||||
|         const | ||||
|         { | ||||
|             return m_filename; | ||||
|         } | ||||
|  | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         std::size_t getLine | ||||
|         () | ||||
|         const | ||||
|         { | ||||
|             return m_line; | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         bool isHidden | ||||
|         () | ||||
|         const | ||||
|         { | ||||
|             return m_name.size() >= 2 && m_name[0] == '.' && m_name[1] == '/'; | ||||
|         }         | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         void swap | ||||
|         ( | ||||
|             TestCaseInfo& other | ||||
|         ) | ||||
|         { | ||||
|             std::swap( m_test, other.m_test ); | ||||
|             m_name.swap( other.m_name ); | ||||
|             m_description.swap( other.m_description ); | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         bool operator ==  | ||||
|         ( | ||||
|             const TestCaseInfo& other | ||||
|         ) | ||||
|         const | ||||
|         { | ||||
|             return *m_test == *other.m_test && m_name == other.m_name && m_description == other.m_description;             | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         bool operator < | ||||
|         ( | ||||
|             const TestCaseInfo& other | ||||
|         )  | ||||
|         const | ||||
|         { | ||||
|             if( m_name < other.m_name ) | ||||
|                 return true; | ||||
|             if( m_name > other.m_name ) | ||||
|                 return false; | ||||
|  | ||||
|             return *m_test < *other.m_test; | ||||
|         } | ||||
|  | ||||
|     private: | ||||
|         ITestCase* m_test; | ||||
|         std::string m_name; | ||||
|         std::string m_description; | ||||
|         std::string m_filename; | ||||
|         std::size_t m_line; | ||||
|          | ||||
|     }; | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     ///////////////////////////////////////////////////////////////////////////     | ||||
|      | ||||
|     class TestSpec | ||||
|     { | ||||
|     public: | ||||
|         ///////////////////////////////////////////////////////////////////////         | ||||
|         TestSpec | ||||
|         ( | ||||
|             const std::string& rawSpec | ||||
|         ) | ||||
|         :   m_rawSpec( rawSpec ), | ||||
|             m_isWildcarded( false ) | ||||
|         { | ||||
|             if( m_rawSpec[m_rawSpec.size()-1] == '*' ) | ||||
|             { | ||||
|                 m_rawSpec = m_rawSpec.substr( 0, m_rawSpec.size()-1 ); | ||||
|                 m_isWildcarded = true; | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         ///////////////////////////////////////////////////////////////////////         | ||||
|         bool matches | ||||
|         ( | ||||
|             const std::string& testName | ||||
|         ) | ||||
|         const | ||||
|         { | ||||
|             if( !m_isWildcarded ) | ||||
|                 return m_rawSpec == testName; | ||||
|             else | ||||
|                 return testName.size() >= m_rawSpec.size() && testName.substr( 0, m_rawSpec.size() ) == m_rawSpec;             | ||||
|         } | ||||
|          | ||||
|     private: | ||||
|         std::string m_rawSpec; | ||||
|         bool m_isWildcarded; | ||||
|     }; | ||||
| } | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_TESTCASEINFO_HPP_INCLUDED | ||||
							
								
								
									
										182
									
								
								include/internal/catch_test_case_registry_impl.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										182
									
								
								include/internal/catch_test_case_registry_impl.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,182 @@ | ||||
| /* | ||||
|  *  catch_test_case_registry_impl.hpp | ||||
|  *  Catch | ||||
|  * | ||||
|  *  Created by Phil on 7/1/2011 | ||||
|  *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved. | ||||
|  * | ||||
|  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||
|  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #include "catch_test_registry.hpp" | ||||
| #include "catch_test_case_info.hpp" | ||||
| #include "catch_hub.h" | ||||
|  | ||||
| #include <vector> | ||||
| #include <set> | ||||
| #include <sstream> | ||||
|  | ||||
| #include <iostream> // !TBD DBG | ||||
| namespace Catch | ||||
| { | ||||
|     class TestRegistry : public ITestCaseRegistry | ||||
|     { | ||||
|     public: | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         TestRegistry | ||||
|         () | ||||
|         : m_unnamedCount( 0 ) | ||||
|         { | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         virtual void registerTest | ||||
|         ( | ||||
|             const TestCaseInfo& testInfo | ||||
|         ) | ||||
|         { | ||||
|             if( testInfo.getName() == "" ) | ||||
|             { | ||||
|                 std::ostringstream oss; | ||||
|                 oss << testInfo.getName() << "unnamed/" << ++m_unnamedCount; | ||||
|                 return registerTest( TestCaseInfo( testInfo, oss.str() ) ); | ||||
|             } | ||||
|             if( m_functions.find( testInfo ) == m_functions.end() ) | ||||
|             { | ||||
|                 m_functions.insert( testInfo ); | ||||
|                 m_functionsInOrder.push_back( testInfo ); | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         virtual const std::vector<TestCaseInfo>& getAllTests | ||||
|         () | ||||
|         const | ||||
|         { | ||||
|             return m_functionsInOrder; | ||||
|         } | ||||
|  | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         virtual std::vector<TestCaseInfo> getMatchingTestCases | ||||
|         (  | ||||
|             const std::string& rawTestSpec  | ||||
|         ) | ||||
|         { | ||||
|             TestSpec testSpec( rawTestSpec ); | ||||
|              | ||||
|             std::vector<TestCaseInfo> testList; | ||||
|             std::vector<TestCaseInfo>::const_iterator it = m_functionsInOrder.begin(); | ||||
|             std::vector<TestCaseInfo>::const_iterator itEnd = m_functionsInOrder.end(); | ||||
|             for(; it != itEnd; ++it ) | ||||
|             { | ||||
|                 if( testSpec.matches( it->getName() ) ) | ||||
|                 { | ||||
|                     testList.push_back( *it ); | ||||
|                     std::cout << it->getName() << std::endl; | ||||
|                 } | ||||
|             } | ||||
|             return testList; | ||||
|         } | ||||
|          | ||||
|     private: | ||||
|          | ||||
|         std::set<TestCaseInfo> m_functions; | ||||
|         std::vector<TestCaseInfo> m_functionsInOrder; | ||||
|         size_t m_unnamedCount; | ||||
|     }; | ||||
|  | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|      | ||||
|      | ||||
|     struct FreeFunctionTestCase : ITestCase | ||||
|     { | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         FreeFunctionTestCase | ||||
|         ( | ||||
|             TestFunction fun | ||||
|         ) | ||||
|         : m_fun( fun ) | ||||
|         {} | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         virtual void invoke | ||||
|         () | ||||
|         const | ||||
|         { | ||||
|             m_fun(); | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         virtual ITestCase* clone | ||||
|         () | ||||
|         const | ||||
|         { | ||||
|             return new FreeFunctionTestCase( m_fun ); | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         virtual bool operator ==  | ||||
|         ( | ||||
|             const ITestCase& other  | ||||
|         ) | ||||
|         const | ||||
|         { | ||||
|             const FreeFunctionTestCase* ffOther = dynamic_cast<const FreeFunctionTestCase*> ( &other ); | ||||
|             return ffOther && m_fun == ffOther->m_fun; | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////////// | ||||
|         virtual bool operator < | ||||
|         ( | ||||
|             const ITestCase& other  | ||||
|         ) | ||||
|         const | ||||
|         { | ||||
|             const FreeFunctionTestCase* ffOther = dynamic_cast<const FreeFunctionTestCase*> ( &other ); | ||||
|             return ffOther && m_fun < ffOther->m_fun; | ||||
|         } | ||||
|          | ||||
|     private: | ||||
|         TestFunction m_fun; | ||||
|     }; | ||||
|          | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     AutoReg::AutoReg | ||||
|     ( | ||||
|         TestFunction function,  | ||||
|         const char* name, | ||||
|         const char* description, | ||||
|         const char* filename, | ||||
|         std::size_t line | ||||
|     ) | ||||
|     { | ||||
|         registerTestCase( new FreeFunctionTestCase( function ), name, description, filename, line ); | ||||
|     }     | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     AutoReg::~AutoReg | ||||
|     () | ||||
|     { | ||||
|     } | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     void AutoReg::registerTestCase | ||||
|     ( | ||||
|         ITestCase* testCase,  | ||||
|         const char* name,  | ||||
|         const char* description, | ||||
|         const char* filename, | ||||
|         std::size_t line | ||||
|     ) | ||||
|     { | ||||
|         Hub::getTestCaseRegistry().registerTest( TestCaseInfo( testCase, name, description, filename, line ) ); | ||||
|     } | ||||
|      | ||||
| } // end namespace Catch | ||||
|  | ||||
							
								
								
									
										149
									
								
								include/internal/catch_test_registry.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								include/internal/catch_test_registry.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,149 @@ | ||||
| /* | ||||
|  *  catch_test_registry.hpp | ||||
|  *  Catch | ||||
|  * | ||||
|  *  Created by Phil on 18/10/2010. | ||||
|  *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved. | ||||
|  * | ||||
|  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||
|  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||
|  * | ||||
|  */ | ||||
| #ifndef TWOBLUECUBES_CATCH_REGISTRY_HPP_INCLUDED | ||||
| #define TWOBLUECUBES_CATCH_REGISTRY_HPP_INCLUDED | ||||
|  | ||||
| #include "catch_common.h" | ||||
| #include "catch_interfaces_testcase.h" | ||||
|  | ||||
| namespace Catch | ||||
| { | ||||
|      | ||||
| template<typename C> | ||||
| struct MethodTestCase : ITestCase | ||||
| { | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     MethodTestCase | ||||
|     ( | ||||
|         void (C::*method)()  | ||||
|     ) | ||||
|     : m_method( method ) | ||||
|     {} | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     virtual void invoke | ||||
|     () | ||||
|     const | ||||
|     { | ||||
|         C obj; | ||||
|         (obj.*m_method)(); | ||||
|     } | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     virtual ITestCase* clone | ||||
|     () | ||||
|     const | ||||
|     { | ||||
|         return new MethodTestCase<C>( m_method ); | ||||
|     } | ||||
|  | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     virtual bool operator ==  | ||||
|     ( | ||||
|         const ITestCase& other | ||||
|     ) | ||||
|     const | ||||
|     { | ||||
|         const MethodTestCase* mtOther = dynamic_cast<const MethodTestCase*>( &other ); | ||||
|         return mtOther && m_method == mtOther->m_method; | ||||
|     } | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     virtual bool operator <  | ||||
|     ( | ||||
|         const ITestCase& other | ||||
|     ) | ||||
|     const | ||||
|     { | ||||
|         const MethodTestCase* mtOther = dynamic_cast<const MethodTestCase*>( &other ); | ||||
|         return mtOther && &m_method < &mtOther->m_method; | ||||
|     } | ||||
|      | ||||
| private: | ||||
|     void (C::*m_method)(); | ||||
| }; | ||||
|  | ||||
| typedef void(*TestFunction)(); | ||||
|      | ||||
| struct AutoReg | ||||
| { | ||||
|     AutoReg | ||||
|         (   TestFunction function,  | ||||
|             const char* name,  | ||||
|             const char* description, | ||||
|             const char* filename, | ||||
|             std::size_t line | ||||
|         ); | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     template<typename C> | ||||
|     AutoReg | ||||
|     ( | ||||
|         void (C::*method)(),  | ||||
|         const char* name,  | ||||
|         const char* description, | ||||
|         const char* filename, | ||||
|         std::size_t line | ||||
|     ) | ||||
|     { | ||||
|         registerTestCase( new MethodTestCase<C>( method ), name, description, filename, line ); | ||||
|     } | ||||
|      | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     void registerTestCase | ||||
|     ( | ||||
|         ITestCase* testCase,  | ||||
|         const char* name,  | ||||
|         const char* description, | ||||
|         const char* filename, | ||||
|         std::size_t line | ||||
|     ); | ||||
|      | ||||
|     ~AutoReg | ||||
|         (); | ||||
|      | ||||
| private: | ||||
|     AutoReg | ||||
|         ( const AutoReg& ); | ||||
|      | ||||
|     void operator= | ||||
|         ( const AutoReg& ); | ||||
| }; | ||||
|      | ||||
| } // end namespace Catch | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \ | ||||
|     static void INTERNAL_CATCH_UNIQUE_NAME( catch_internal_TestFunction )(); \ | ||||
|     namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME(  catch_internal_TestFunction ), Name, Desc, __FILE__, __LINE__ ); }\ | ||||
|     static void INTERNAL_CATCH_UNIQUE_NAME(  catch_internal_TestFunction )() | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| #define INTERNAL_CATCH_TESTCASE_NORETURN( Name, Desc ) \ | ||||
|     static void INTERNAL_CATCH_UNIQUE_NAME( catch_internal_TestFunction )() ATTRIBUTE_NORETURN; \ | ||||
|     namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME(  catch_internal_TestFunction ), Name, Desc, __FILE__, __LINE__ ); }\ | ||||
|     static void INTERNAL_CATCH_UNIQUE_NAME(  catch_internal_TestFunction )() | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| #define CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \ | ||||
|     namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, Name, Desc, __FILE__, __LINE__ ); } | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| #define TEST_CASE_METHOD( ClassName, TestName, Desc )\ | ||||
|     struct INTERNAL_CATCH_UNIQUE_NAME( Catch_FixtureWrapper ) : ClassName \ | ||||
|     { \ | ||||
|         void test(); \ | ||||
|     }; \ | ||||
|     namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( Catch_FixtureWrapper )::test, TestName, Desc, __FILE__, __LINE__ ); } \ | ||||
|     void INTERNAL_CATCH_UNIQUE_NAME( Catch_FixtureWrapper )::test() | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_REGISTRY_HPP_INCLUDED | ||||
							
								
								
									
										332
									
								
								include/internal/catch_xmlwriter.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										332
									
								
								include/internal/catch_xmlwriter.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,332 @@ | ||||
| /* | ||||
|  *  catch_xmlwriter.hpp | ||||
|  *  Catch | ||||
|  * | ||||
|  *  Created by Phil on 09/12/2010. | ||||
|  *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved. | ||||
|  * | ||||
|  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||
|  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||
|  */ | ||||
| #ifndef TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED | ||||
| #define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED | ||||
|  | ||||
| #include <sstream> | ||||
| #include <string> | ||||
| #include <vector> | ||||
|  | ||||
| namespace Catch | ||||
| { | ||||
|     class XmlWriter | ||||
|     { | ||||
|     public: | ||||
|          | ||||
|         class ScopedElement | ||||
|         { | ||||
|         public: | ||||
|             /////////////////////////////////////////////////////////////////// | ||||
|             ScopedElement | ||||
|             ( | ||||
|                 XmlWriter* writer | ||||
|             ) | ||||
|             :   m_writer( writer ) | ||||
|             { | ||||
|             } | ||||
|              | ||||
|             /////////////////////////////////////////////////////////////////// | ||||
|             ScopedElement | ||||
|             ( | ||||
|                 const ScopedElement& other | ||||
|             ) | ||||
|             :   m_writer( other.m_writer ) | ||||
|             { | ||||
|                 other.m_writer = NULL; | ||||
|             } | ||||
|              | ||||
|             /////////////////////////////////////////////////////////////////// | ||||
|             ~ScopedElement | ||||
|             () | ||||
|             { | ||||
|                 if( m_writer ) | ||||
|                     m_writer->endElement(); | ||||
|             } | ||||
|  | ||||
|             /////////////////////////////////////////////////////////////////// | ||||
|             ScopedElement& writeText | ||||
|             ( | ||||
|                 const std::string& text | ||||
|             ) | ||||
|             { | ||||
|                 m_writer->writeText( text ); | ||||
|                 return *this; | ||||
|             } | ||||
|  | ||||
|             /////////////////////////////////////////////////////////////////// | ||||
|             template<typename T> | ||||
|             ScopedElement& writeAttribute | ||||
|             ( | ||||
|                 const std::string& name, | ||||
|                 const T& attribute | ||||
|             ) | ||||
|             { | ||||
|                 m_writer->writeAttribute( name, attribute ); | ||||
|                 return *this; | ||||
|             } | ||||
|              | ||||
|         private: | ||||
|             mutable XmlWriter* m_writer; | ||||
|         }; | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         XmlWriter | ||||
|         () | ||||
|         :   m_tagIsOpen( false ), | ||||
|             m_needsNewline( false ), | ||||
|             m_os( &std::cout ) | ||||
|         { | ||||
|         } | ||||
|  | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         XmlWriter | ||||
|         ( | ||||
|             std::ostream& os | ||||
|         ) | ||||
|         :   m_tagIsOpen( false ), | ||||
|             m_needsNewline( false ), | ||||
|             m_os( &os ) | ||||
|         { | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         ~XmlWriter | ||||
|         () | ||||
|         { | ||||
|             while( !m_tags.empty() ) | ||||
|             { | ||||
|                 endElement(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         XmlWriter& operator =  | ||||
|         ( | ||||
|             const XmlWriter& other | ||||
|         ) | ||||
|         { | ||||
|             XmlWriter temp( other ); | ||||
|             swap( temp ); | ||||
|             return *this; | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         void swap | ||||
|         ( | ||||
|             XmlWriter& other | ||||
|         ) | ||||
|         { | ||||
|             std::swap( m_tagIsOpen, other.m_tagIsOpen ); | ||||
|             std::swap( m_needsNewline, other.m_needsNewline ); | ||||
|             std::swap( m_tags, other.m_tags ); | ||||
|             std::swap( m_indent, other.m_indent ); | ||||
|             std::swap( m_os, other.m_os ); | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         XmlWriter& startElement | ||||
|         ( | ||||
|             const std::string& name | ||||
|         ) | ||||
|         { | ||||
|             ensureTagClosed(); | ||||
|             newlineIfNecessary(); | ||||
|             stream() << m_indent << "<" << name; | ||||
|             m_tags.push_back( name ); | ||||
|             m_indent += "  "; | ||||
|             m_tagIsOpen = true; | ||||
|             return *this; | ||||
|         } | ||||
|  | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         ScopedElement scopedElement | ||||
|         ( | ||||
|             const std::string& name | ||||
|         ) | ||||
|         { | ||||
|             ScopedElement scoped( this ); | ||||
|             startElement( name ); | ||||
|             return scoped; | ||||
|         } | ||||
|  | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         XmlWriter& endElement | ||||
|         () | ||||
|         { | ||||
|             newlineIfNecessary(); | ||||
|             m_indent = m_indent.substr( 0, m_indent.size()-2 ); | ||||
|             if( m_tagIsOpen ) | ||||
|             { | ||||
|                 stream() << "/>\n"; | ||||
|                 m_tagIsOpen = false; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 stream() << m_indent << "</" << m_tags.back() << ">\n"; | ||||
|             }  | ||||
|             m_tags.pop_back(); | ||||
|             return *this; | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         XmlWriter& writeAttribute | ||||
|         ( | ||||
|             const std::string& name,  | ||||
|             const std::string& attribute | ||||
|         ) | ||||
|         { | ||||
|             if( !name.empty() && !attribute.empty() ) | ||||
|             { | ||||
|                 stream() << " " << name << "=\""; | ||||
|                 writeEncodedText( attribute ); | ||||
|                 stream() << "\""; | ||||
|             } | ||||
|             return *this; | ||||
|         } | ||||
|  | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         XmlWriter& writeAttribute | ||||
|         ( | ||||
|             const std::string& name,  | ||||
|             bool attribute | ||||
|         ) | ||||
|         { | ||||
|             stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\""; | ||||
|             return *this; | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         template<typename T> | ||||
|         XmlWriter& writeAttribute | ||||
|         ( | ||||
|             const std::string& name,  | ||||
|             const T& attribute | ||||
|         ) | ||||
|         { | ||||
|             if( !name.empty() ) | ||||
|             { | ||||
|                 stream() << " " << name << "=\"" << attribute << "\""; | ||||
|             } | ||||
|             return *this; | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         XmlWriter& writeText | ||||
|         ( | ||||
|             const std::string& text | ||||
|         ) | ||||
|         { | ||||
|             if( !text.empty() ) | ||||
|             { | ||||
|                 bool tagWasOpen = m_tagIsOpen; | ||||
|                 ensureTagClosed(); | ||||
|                 if( tagWasOpen ) | ||||
|                     stream() << m_indent; | ||||
|                 writeEncodedText( text ); | ||||
|                 m_needsNewline = true; | ||||
|             } | ||||
|             return *this; | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         XmlWriter& writeComment | ||||
|         ( | ||||
|             const std::string& text  | ||||
|         ) | ||||
|         { | ||||
|             ensureTagClosed(); | ||||
|             stream() << m_indent << "<!--" << text << "-->"; | ||||
|             m_needsNewline = true; | ||||
|             return *this; | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         XmlWriter& writeBlankLine | ||||
|         () | ||||
|         { | ||||
|             ensureTagClosed(); | ||||
|             stream() << "\n"; | ||||
|             return *this; | ||||
|         } | ||||
|          | ||||
|     private: | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         std::ostream& stream | ||||
|         () | ||||
|         { | ||||
|             return *m_os; | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         void ensureTagClosed | ||||
|         () | ||||
|         { | ||||
|             if( m_tagIsOpen ) | ||||
|             { | ||||
|                 stream() << ">\n"; | ||||
|                 m_tagIsOpen = false; | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         void newlineIfNecessary | ||||
|         () | ||||
|         { | ||||
|             if( m_needsNewline ) | ||||
|             { | ||||
|                 stream() << "\n"; | ||||
|                 m_needsNewline = false; | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         void writeEncodedText | ||||
|         ( | ||||
|             const std::string& text | ||||
|         ) | ||||
|         { | ||||
|             // !TBD finish this | ||||
|             if( !findReplaceableString( text, "<", "<" ) && | ||||
|                !findReplaceableString( text, "&", "&" ) && | ||||
|                !findReplaceableString( text, "\"", ""e;" ) ) | ||||
|             { | ||||
|                 stream() << text; | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         /////////////////////////////////////////////////////////////////////// | ||||
|         bool findReplaceableString | ||||
|         ( | ||||
|             const std::string& text,  | ||||
|             const std::string& replaceWhat,  | ||||
|             const std::string& replaceWith | ||||
|         ) | ||||
|         { | ||||
|             std::string::size_type pos = text.find_first_of( replaceWhat ); | ||||
|             if( pos != std::string::npos ) | ||||
|             { | ||||
|                 stream() << text.substr( 0, pos ) << replaceWith; | ||||
|                 writeEncodedText( text.substr( pos+1 ) ); | ||||
|                 return true; | ||||
|             } | ||||
|             return false; | ||||
|         } | ||||
|          | ||||
|         bool m_tagIsOpen; | ||||
|         bool m_needsNewline; | ||||
|         std::vector<std::string> m_tags; | ||||
|         std::string m_indent; | ||||
|         std::ostream* m_os; | ||||
|     }; | ||||
|      | ||||
| } | ||||
| #endif | ||||
		Reference in New Issue
	
	Block a user
	 Phil Nash
					Phil Nash