11 #ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
12 #define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
14 #define TWOBLUECUBES_CATCH_HPP_INCLUDED
17 # pragma clang system_header
18 #elif defined __GNUC__
19 # pragma GCC system_header
26 # pragma warning(push)
27 # pragma warning(disable: 161 1682)
29 # pragma clang diagnostic ignored "-Wglobal-constructors"
30 # pragma clang diagnostic ignored "-Wvariadic-macros"
31 # pragma clang diagnostic ignored "-Wc99-extensions"
32 # pragma clang diagnostic ignored "-Wunused-variable"
33 # pragma clang diagnostic push
34 # pragma clang diagnostic ignored "-Wpadded"
35 # pragma clang diagnostic ignored "-Wc++98-compat"
36 # pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
37 # pragma clang diagnostic ignored "-Wswitch-enum"
38 # pragma clang diagnostic ignored "-Wcovered-switch-default"
40 #elif defined __GNUC__
41 # pragma GCC diagnostic ignored "-Wvariadic-macros"
42 # pragma GCC diagnostic ignored "-Wunused-variable"
43 # pragma GCC diagnostic push
44 # pragma GCC diagnostic ignored "-Wpadded"
46 #if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER)
51 # ifndef CLARA_CONFIG_MAIN
52 # define CLARA_CONFIG_MAIN_NOT_DEFINED
53 # define CLARA_CONFIG_MAIN
58 #define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED
61 #define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
63 #define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
64 #define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
65 #define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
67 #define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
68 #define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
75 #define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
107 # if __has_feature(cxx_nullptr)
108 # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
111 # if __has_feature(cxx_noexcept)
112 # define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
125 #ifdef __EDG_VERSION__
139 #if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
140 # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
152 #if (_MSC_VER >= 1600)
153 # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
154 # define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
157 #if (_MSC_VER >= 1900 )
158 #define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
159 #define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
167 #if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \
168 ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \
169 ( defined __GNUC__ && __GNUC__ >= 3 ) || \
170 ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L )
172 #define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
180 #if defined(__cplusplus) && __cplusplus >= 201103L
182 # define CATCH_CPP11_OR_GREATER
184 # if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR)
185 # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
188 # ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
189 # define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
192 # ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
193 # define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
196 # ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
197 # define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
200 # ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE
201 # define CATCH_INTERNAL_CONFIG_CPP11_TUPLE
204 # ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
205 # define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
208 # if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG)
209 # define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG
212 # if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE)
213 # define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE
215 # if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR)
216 # define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
222 #if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11)
223 # define CATCH_CONFIG_CPP11_NULLPTR
225 #if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11)
226 # define CATCH_CONFIG_CPP11_NOEXCEPT
228 #if defined(CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_NO_CPP11)
229 # define CATCH_CONFIG_CPP11_GENERATED_METHODS
231 #if defined(CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_NO_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_NO_CPP11)
232 # define CATCH_CONFIG_CPP11_IS_ENUM
234 #if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11)
235 # define CATCH_CONFIG_CPP11_TUPLE
237 #if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS)
238 # define CATCH_CONFIG_VARIADIC_MACROS
240 #if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_CPP11)
241 # define CATCH_CONFIG_CPP11_LONG_LONG
243 #if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11)
244 # define CATCH_CONFIG_CPP11_OVERRIDE
246 #if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11)
247 # define CATCH_CONFIG_CPP11_UNIQUE_PTR
251 #if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT)
252 # define CATCH_NOEXCEPT noexcept
253 # define CATCH_NOEXCEPT_IS(x) noexcept(x)
255 # define CATCH_NOEXCEPT throw()
256 # define CATCH_NOEXCEPT_IS(x)
260 #ifdef CATCH_CONFIG_CPP11_NULLPTR
261 # define CATCH_NULL nullptr
263 # define CATCH_NULL NULL
267 #ifdef CATCH_CONFIG_CPP11_OVERRIDE
268 # define CATCH_OVERRIDE override
270 # define CATCH_OVERRIDE
274 #ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR
275 # define CATCH_AUTO_PTR( T ) std::unique_ptr<T>
277 # define CATCH_AUTO_PTR( T ) std::auto_ptr<T>
290 #ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
307 typedef void (
SafeBool::*type)()
const;
309 static type makeSafe(
bool value ) {
310 return value ? &SafeBool::trueValue : 0;
313 void trueValue()
const {}
316 template<
typename ContainerT>
317 inline void deleteAll( ContainerT& container ) {
318 typename ContainerT::const_iterator it = container.begin();
319 typename ContainerT::const_iterator itEnd = container.end();
320 for(; it != itEnd; ++it )
323 template<
typename AssociativeContainerT>
324 inline void deleteAllValues( AssociativeContainerT& container ) {
325 typename AssociativeContainerT::const_iterator it = container.begin();
326 typename AssociativeContainerT::const_iterator itEnd = container.end();
327 for(; it != itEnd; ++it )
331 bool startsWith( std::string
const& s, std::string
const& prefix );
332 bool endsWith( std::string
const& s, std::string
const& suffix );
333 bool contains( std::string
const& s, std::string
const& infix );
334 void toLowerInPlace( std::string& s );
335 std::string toLower( std::string
const& s );
336 std::string trim( std::string
const& str );
337 bool replaceInPlace( std::string& str, std::string
const& replaceThis, std::string
const& withThis );
340 pluralise( std::size_t count, std::string
const& label );
342 friend std::ostream& operator << ( std::ostream& os,
pluralise const& pluraliser );
353 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
366 std::ostream& operator << ( std::ostream& os,
SourceLineInfo const& info );
369 inline bool isTrue(
bool value ){
return value; }
370 inline bool alwaysTrue() {
return true; }
371 inline bool alwaysFalse() {
return false; }
373 void throwLogicError( std::string
const& message, SourceLineInfo
const& locationInfo );
375 void seedRng( IConfig
const& config );
376 unsigned int rngSeed();
383 std::string operator+() {
384 return std::string();
393 #define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
394 #define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO );
408 virtual const char* what()
const CATCH_NOEXCEPT;
418 #define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO )
421 #define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED
424 #define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED
432 virtual bool moveNext() = 0;
433 virtual std::size_t getCurrentIndex()
const = 0;
439 virtual IGeneratorInfo& getGeneratorInfo( std::string
const& fileInfo, std::size_t size ) = 0;
440 virtual bool moveNext() = 0;
448 #define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED
451 #pragma clang diagnostic push
452 #pragma clang diagnostic ignored "-Wpadded"
463 Ptr() : m_p( CATCH_NULL ){}
464 Ptr( T* p ) : m_p( p ){
468 Ptr(
Ptr const& other ) : m_p( other.m_p ){
481 Ptr& operator = ( T* p ){
486 Ptr& operator = (
Ptr const& other ){
491 void swap(
Ptr& other ) { std::swap( m_p, other.m_p ); }
492 T* get()
const{
return m_p; }
493 T& operator*()
const {
return *m_p; }
494 T* operator->()
const {
return m_p; }
495 bool operator !()
const {
return m_p == CATCH_NULL; }
496 operator SafeBool::type()
const {
return SafeBool::makeSafe( m_p != CATCH_NULL ); }
504 virtual void addRef()
const = 0;
505 virtual void release()
const = 0;
508 template<
typename T = IShared>
513 virtual void addRef()
const {
516 virtual void release()
const {
521 mutable unsigned int m_rc;
527 #pragma clang diagnostic pop
538 struct IResultCapture;
540 struct IGeneratorsForTest;
548 virtual IRunner* getRunner() = 0;
549 virtual size_t getGeneratorIndex( std::string
const& fileInfo,
size_t totalSize ) = 0;
550 virtual bool advanceGeneratorsForCurrentTest() = 0;
557 virtual void setResultCapture(
IResultCapture* resultCapture ) = 0;
558 virtual void setRunner(
IRunner* runner ) = 0;
564 void cleanUpContext();
565 Stream createStream( std::string
const& streamName );
570 #define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
573 #define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
582 virtual void invoke ()
const = 0;
592 virtual std::vector<TestCase>
const& getAllTests()
const = 0;
593 virtual std::vector<TestCase>
const& getAllTestsSorted( IConfig
const& config )
const = 0;
596 bool matchTest(
TestCase const& testCase, TestSpec
const& testSpec, IConfig
const& config );
597 std::vector<TestCase> filterTests( std::vector<TestCase>
const& testCases, TestSpec
const& testSpec, IConfig
const& config );
598 std::vector<TestCase>
const& getAllTestCasesSorted( IConfig
const& config );
610 virtual void invoke()
const {
618 void (C::*m_method)();
621 typedef void(*TestFunction)();
624 NameAndDesc(
const char* _name =
"",
const char* _description=
"" )
625 : name( _name ), description( _description )
629 const char* description;
632 void registerTestCase
634 char const* className,
641 ( TestFunction
function,
647 (
void (C::*method)(),
648 char const* className,
663 void operator= (
AutoReg const& );
666 void registerTestCaseFunction
667 ( TestFunction
function,
673 #ifdef CATCH_CONFIG_VARIADIC_MACROS
675 #define INTERNAL_CATCH_TESTCASE( ... ) \
676 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \
677 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\
678 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )()
681 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
682 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); }
685 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... )\
687 struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \
690 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \
692 void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test()
695 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
696 Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) );
700 #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
701 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \
702 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\
703 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )()
706 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
707 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); }
710 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
712 struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \
715 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \
717 void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test()
720 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \
721 Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) );
725 #define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
728 #define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED
731 #define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED
744 ExpressionFailed = FailureBit | 1,
745 ExplicitFailure = FailureBit | 2,
747 Exception = 0x100 | FailureBit,
749 ThrewException = Exception | 1,
750 DidntThrowException = Exception | 2,
752 FatalErrorCondition = 0x200 | FailureBit
756 inline bool isOk( ResultWas::OfType resultType ) {
757 return ( resultType & ResultWas::FailureBit ) == 0;
759 inline bool isJustInfo(
int flags ) {
760 return flags == ResultWas::Info;
767 ContinueOnFailure = 0x02,
772 inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) {
773 return static_cast<ResultDisposition::Flags
>(
static_cast<int>( lhs ) |
static_cast<int>( rhs ) );
776 inline bool shouldContinueOnFailure(
int flags ) {
return ( flags & ResultDisposition::ContinueOnFailure ) != 0; }
777 inline bool isFalseTest(
int flags ) {
return ( flags & ResultDisposition::FalseTest ) != 0; }
778 inline bool shouldSuppressFailure(
int flags ) {
return ( flags & ResultDisposition::SuppressFail ) != 0; }
783 #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED
794 std::string
const& _capturedExpression,
795 ResultDisposition::Flags _resultDisposition );
797 std::string macroName;
799 std::string capturedExpression;
800 ResultDisposition::Flags resultDisposition;
807 std::string reconstructedExpression;
809 ResultWas::OfType resultType;
817 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
825 bool succeeded()
const;
826 ResultWas::OfType getResultType()
const;
827 bool hasExpression()
const;
828 bool hasMessage()
const;
829 std::string getExpression()
const;
830 std::string getExpressionInMacro()
const;
831 bool hasExpandedExpression()
const;
832 std::string getExpandedExpression()
const;
833 std::string getMessage()
const;
835 std::string getTestMacroName()
const;
845 #define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
852 template<
typename ExpressionT>
class AllOf;
853 template<
typename ExpressionT>
class AnyOf;
854 template<
typename ExpressionT>
class Not;
857 template<
typename ExpressionT>
860 typedef ExpressionT ExpressionType;
864 virtual bool match( ExpressionT
const& expr )
const = 0;
865 virtual std::string toString()
const = 0;
872 template<
typename DerivedT,
typename ExpressionT>
881 template<
typename ExpressionT>
885 Not(
Not const& other ) : m_matcher( other.m_matcher ) {}
887 virtual bool match( ExpressionT
const& expr )
const CATCH_OVERRIDE {
888 return !m_matcher->match( expr );
891 virtual std::string toString()
const CATCH_OVERRIDE {
892 return "not " + m_matcher->toString();
898 template<
typename ExpressionT>
903 AllOf(
AllOf const& other ) : m_matchers( other.m_matchers ) {}
906 m_matchers.push_back( matcher.clone() );
909 virtual bool match( ExpressionT
const& expr )
const
911 for( std::size_t i = 0; i < m_matchers.size(); ++i )
912 if( !m_matchers[i]->match( expr ) )
916 virtual std::string toString()
const {
917 std::ostringstream oss;
919 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
922 oss << m_matchers[i]->toString();
929 AllOf allOfExpr( *
this );
930 allOfExpr.add( other );
935 std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
938 template<
typename ExpressionT>
943 AnyOf(
AnyOf const& other ) : m_matchers( other.m_matchers ) {}
946 m_matchers.push_back( matcher.clone() );
949 virtual bool match( ExpressionT
const& expr )
const
951 for( std::size_t i = 0; i < m_matchers.size(); ++i )
952 if( m_matchers[i]->match( expr ) )
956 virtual std::string toString()
const {
957 std::ostringstream oss;
959 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
962 oss << m_matchers[i]->toString();
969 AnyOf anyOfExpr( *
this );
970 anyOfExpr.add( other );
975 std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
980 template<
typename ExpressionT>
983 allOfExpr.add( *
this );
984 allOfExpr.add( other );
988 template<
typename ExpressionT>
989 Generic::AnyOf<ExpressionT> Matcher<ExpressionT>::operator || ( Matcher<ExpressionT>
const& other )
const {
990 Generic::AnyOf<ExpressionT> anyOfExpr;
991 anyOfExpr.add( *
this );
992 anyOfExpr.add( other );
996 template<
typename ExpressionT>
997 Generic::Not<ExpressionT> Matcher<ExpressionT>::operator ! ()
const {
998 return Generic::Not<ExpressionT>( *
this );
1001 namespace StdString {
1003 inline std::string makeString( std::string
const& str ) {
return str; }
1004 inline std::string makeString(
const char* str ) {
return str ? std::string( str ) : std::string(); }
1008 CasedString( std::string
const& str, CaseSensitive::Choice caseSensitivity )
1009 : m_caseSensitivity( caseSensitivity ),
1010 m_str( adjustString( str ) )
1012 std::string adjustString( std::string
const& str )
const {
1013 return m_caseSensitivity == CaseSensitive::No
1018 std::string toStringSuffix()
const
1020 return m_caseSensitivity == CaseSensitive::No
1021 ?
" (case insensitive)"
1024 CaseSensitive::Choice m_caseSensitivity;
1029 Equals( std::string
const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
1030 : m_data( str, caseSensitivity )
1032 Equals(
Equals const& other ) : m_data( other.m_data ){}
1036 virtual bool match( std::string
const& expr )
const {
1037 return m_data.m_str == m_data.adjustString( expr );;
1039 virtual std::string toString()
const {
1040 return "equals: \"" + m_data.m_str +
"\"" + m_data.toStringSuffix();
1047 Contains( std::string
const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
1048 : m_data( substr, caseSensitivity ){}
1053 virtual bool match( std::string
const& expr )
const {
1054 return m_data.adjustString( expr ).find( m_data.m_str ) != std::string::npos;
1056 virtual std::string toString()
const {
1057 return "contains: \"" + m_data.m_str +
"\"" + m_data.toStringSuffix();
1064 StartsWith( std::string
const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
1065 : m_data( substr, caseSensitivity ){}
1071 virtual bool match( std::string
const& expr )
const {
1072 return startsWith( m_data.adjustString( expr ), m_data.m_str );
1074 virtual std::string toString()
const {
1075 return "starts with: \"" + m_data.m_str +
"\"" + m_data.toStringSuffix();
1082 EndsWith( std::string
const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
1083 : m_data( substr, caseSensitivity ){}
1088 virtual bool match( std::string
const& expr )
const {
1089 return endsWith( m_data.adjustString( expr ), m_data.m_str );
1091 virtual std::string toString()
const {
1092 return "ends with: \"" + m_data.m_str +
"\"" + m_data.toStringSuffix();
1102 template<
typename ExpressionT>
1107 template<
typename ExpressionT>
1112 template<
typename ExpressionT>
1113 inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT>
const& m1,
1114 Impl::Matcher<ExpressionT>
const& m2,
1115 Impl::Matcher<ExpressionT>
const& m3 ) {
1116 return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
1118 template<
typename ExpressionT>
1119 inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT>
const& m1,
1120 Impl::Matcher<ExpressionT>
const& m2 ) {
1121 return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 );
1123 template<
typename ExpressionT>
1124 inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT>
const& m1,
1125 Impl::Matcher<ExpressionT>
const& m2,
1126 Impl::Matcher<ExpressionT>
const& m3 ) {
1127 return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
1130 inline Impl::StdString::Equals Equals( std::string
const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) {
1131 return Impl::StdString::Equals( str, caseSensitivity );
1133 inline Impl::StdString::Equals Equals(
const char* str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) {
1134 return Impl::StdString::Equals( Impl::StdString::makeString( str ), caseSensitivity );
1136 inline Impl::StdString::Contains Contains( std::string
const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) {
1137 return Impl::StdString::Contains( substr, caseSensitivity );
1139 inline Impl::StdString::Contains Contains(
const char* substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) {
1140 return Impl::StdString::Contains( Impl::StdString::makeString( substr ), caseSensitivity );
1142 inline Impl::StdString::StartsWith StartsWith( std::string
const& substr ) {
1143 return Impl::StdString::StartsWith( substr );
1145 inline Impl::StdString::StartsWith StartsWith(
const char* substr ) {
1146 return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) );
1148 inline Impl::StdString::EndsWith EndsWith( std::string
const& substr ) {
1149 return Impl::StdString::EndsWith( substr );
1151 inline Impl::StdString::EndsWith EndsWith(
const char* substr ) {
1152 return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) );
1157 using namespace Matchers;
1167 struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
1172 oss << other.oss.str();
1176 oss << other.oss.str();
1179 std::ostringstream oss;
1186 char const* capturedExpression,
1187 ResultDisposition::Flags resultDisposition,
1188 char const* secondArg =
"" );
1190 template<
typename T>
1194 template<
typename T>
1196 m_stream.oss << value;
1200 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT
const& );
1201 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT
const& );
1209 void endExpression();
1211 std::string reconstructExpression()
const;
1214 void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal );
1215 void captureResult( ResultWas::OfType resultType );
1216 void captureExpression();
1217 void captureExpectedException( std::string
const& expectedMessage );
1221 bool shouldDebugBreak()
const;
1222 bool allowThrows()
const;
1227 struct ExprComponents {
1228 ExprComponents() : testFalse(
false ) {}
1230 std::string lhs, rhs, op;
1234 bool m_shouldDebugBreak;
1242 #define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED
1245 #define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED
1248 #pragma warning(push)
1249 #pragma warning(disable:4389)
1255 namespace Internal {
1262 IsLessThanOrEqualTo,
1263 IsGreaterThanOrEqualTo
1266 template<Operator Op>
struct OperatorTraits {
static const char* getName(){
return "*error*"; } };
1267 template<>
struct OperatorTraits<IsEqualTo> {
static const char* getName(){
return "=="; } };
1268 template<>
struct OperatorTraits<IsNotEqualTo> {
static const char* getName(){
return "!="; } };
1269 template<>
struct OperatorTraits<IsLessThan> {
static const char* getName(){
return "<"; } };
1270 template<>
struct OperatorTraits<IsGreaterThan> {
static const char* getName(){
return ">"; } };
1271 template<>
struct OperatorTraits<IsLessThanOrEqualTo> {
static const char* getName(){
return "<="; } };
1272 template<>
struct OperatorTraits<IsGreaterThanOrEqualTo>{
static const char* getName(){
return ">="; } };
1274 template<
typename T>
1275 inline T& opCast(T
const& t) {
return const_cast<T&
>(t); }
1278 #ifdef CATCH_CONFIG_CPP11_NULLPTR
1279 inline std::nullptr_t opCast(std::nullptr_t) {
return nullptr; }
1284 template<
typename T1,
typename T2, Operator Op>
1287 template<
typename T1,
typename T2>
1289 static bool evaluate( T1
const& lhs, T2
const& rhs) {
1290 return opCast( lhs ) == opCast( rhs );
1293 template<
typename T1,
typename T2>
1295 static bool evaluate( T1
const& lhs, T2
const& rhs ) {
1296 return opCast( lhs ) != opCast( rhs );
1299 template<
typename T1,
typename T2>
1301 static bool evaluate( T1
const& lhs, T2
const& rhs ) {
1302 return opCast( lhs ) < opCast( rhs );
1305 template<
typename T1,
typename T2>
1307 static bool evaluate( T1
const& lhs, T2
const& rhs ) {
1308 return opCast( lhs ) > opCast( rhs );
1311 template<
typename T1,
typename T2>
1313 static bool evaluate( T1
const& lhs, T2
const& rhs ) {
1314 return opCast( lhs ) >= opCast( rhs );
1317 template<
typename T1,
typename T2>
1319 static bool evaluate( T1
const& lhs, T2
const& rhs ) {
1320 return opCast( lhs ) <= opCast( rhs );
1324 template<Operator Op,
typename T1,
typename T2>
1325 bool applyEvaluator( T1
const& lhs, T2
const& rhs ) {
1333 template<Operator Op,
typename T1,
typename T2>
1334 bool compare( T1
const& lhs, T2
const& rhs ) {
1335 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
1339 template<Operator Op>
bool compare(
unsigned int lhs,
int rhs ) {
1340 return applyEvaluator<Op>( lhs,
static_cast<unsigned int>( rhs ) );
1342 template<Operator Op>
bool compare(
unsigned long lhs,
int rhs ) {
1343 return applyEvaluator<Op>( lhs,
static_cast<unsigned int>( rhs ) );
1345 template<Operator Op>
bool compare(
unsigned char lhs,
int rhs ) {
1346 return applyEvaluator<Op>( lhs,
static_cast<unsigned int>( rhs ) );
1350 template<Operator Op>
bool compare(
unsigned int lhs,
long rhs ) {
1351 return applyEvaluator<Op>( lhs,
static_cast<unsigned long>( rhs ) );
1353 template<Operator Op>
bool compare(
unsigned long lhs,
long rhs ) {
1354 return applyEvaluator<Op>( lhs,
static_cast<unsigned long>( rhs ) );
1356 template<Operator Op>
bool compare(
unsigned char lhs,
long rhs ) {
1357 return applyEvaluator<Op>( lhs,
static_cast<unsigned long>( rhs ) );
1361 template<Operator Op>
bool compare(
int lhs,
unsigned int rhs ) {
1362 return applyEvaluator<Op>(
static_cast<unsigned int>( lhs ), rhs );
1364 template<Operator Op>
bool compare(
int lhs,
unsigned long rhs ) {
1365 return applyEvaluator<Op>(
static_cast<unsigned int>( lhs ), rhs );
1367 template<Operator Op>
bool compare(
int lhs,
unsigned char rhs ) {
1368 return applyEvaluator<Op>(
static_cast<unsigned int>( lhs ), rhs );
1372 template<Operator Op>
bool compare(
long lhs,
unsigned int rhs ) {
1373 return applyEvaluator<Op>(
static_cast<unsigned long>( lhs ), rhs );
1375 template<Operator Op>
bool compare(
long lhs,
unsigned long rhs ) {
1376 return applyEvaluator<Op>(
static_cast<unsigned long>( lhs ), rhs );
1378 template<Operator Op>
bool compare(
long lhs,
unsigned char rhs ) {
1379 return applyEvaluator<Op>(
static_cast<unsigned long>( lhs ), rhs );
1383 template<Operator Op,
typename T>
bool compare(
long lhs, T* rhs ) {
1384 return Evaluator<T*, T*, Op>::evaluate(
reinterpret_cast<T*
>( lhs ), rhs );
1386 template<Operator Op,
typename T>
bool compare( T* lhs,
long rhs ) {
1387 return Evaluator<T*, T*, Op>::evaluate( lhs,
reinterpret_cast<T*
>( rhs ) );
1391 template<Operator Op,
typename T>
bool compare(
int lhs, T* rhs ) {
1392 return Evaluator<T*, T*, Op>::evaluate(
reinterpret_cast<T*
>( lhs ), rhs );
1394 template<Operator Op,
typename T>
bool compare( T* lhs,
int rhs ) {
1395 return Evaluator<T*, T*, Op>::evaluate( lhs,
reinterpret_cast<T*
>( rhs ) );
1398 #ifdef CATCH_CONFIG_CPP11_LONG_LONG
1400 template<Operator Op>
bool compare(
long long lhs,
unsigned int rhs ) {
1401 return applyEvaluator<Op>(
static_cast<unsigned long>( lhs ), rhs );
1403 template<Operator Op>
bool compare(
long long lhs,
unsigned long rhs ) {
1404 return applyEvaluator<Op>(
static_cast<unsigned long>( lhs ), rhs );
1406 template<Operator Op>
bool compare(
long long lhs,
unsigned long long rhs ) {
1407 return applyEvaluator<Op>(
static_cast<unsigned long>( lhs ), rhs );
1409 template<Operator Op>
bool compare(
long long lhs,
unsigned char rhs ) {
1410 return applyEvaluator<Op>(
static_cast<unsigned long>( lhs ), rhs );
1414 template<Operator Op>
bool compare(
unsigned long long lhs,
int rhs ) {
1415 return applyEvaluator<Op>(
static_cast<long>( lhs ), rhs );
1417 template<Operator Op>
bool compare(
unsigned long long lhs,
long rhs ) {
1418 return applyEvaluator<Op>(
static_cast<long>( lhs ), rhs );
1420 template<Operator Op>
bool compare(
unsigned long long lhs,
long long rhs ) {
1421 return applyEvaluator<Op>(
static_cast<long>( lhs ), rhs );
1423 template<Operator Op>
bool compare(
unsigned long long lhs,
char rhs ) {
1424 return applyEvaluator<Op>(
static_cast<long>( lhs ), rhs );
1428 template<Operator Op,
typename T>
bool compare(
long long lhs, T* rhs ) {
1429 return Evaluator<T*, T*, Op>::evaluate(
reinterpret_cast<T*
>( lhs ), rhs );
1431 template<Operator Op,
typename T>
bool compare( T* lhs,
long long rhs ) {
1432 return Evaluator<T*, T*, Op>::evaluate( lhs,
reinterpret_cast<T*
>( rhs ) );
1436 #ifdef CATCH_CONFIG_CPP11_NULLPTR
1438 template<Operator Op,
typename T>
bool compare( std::nullptr_t, T* rhs ) {
1439 return Evaluator<T*, T*, Op>::evaluate(
nullptr, rhs );
1441 template<Operator Op,
typename T>
bool compare( T* lhs, std::nullptr_t ) {
1442 return Evaluator<T*, T*, Op>::evaluate( lhs,
nullptr );
1450 #pragma warning(pop)
1454 #define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED
1464 #define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED
1466 #import <Foundation/Foundation.h>
1468 #ifdef __has_feature
1469 #define CATCH_ARC_ENABLED __has_feature(objc_arc)
1471 #define CATCH_ARC_ENABLED 0
1474 void arcSafeRelease( NSObject* obj );
1475 id performOptionalSelector(
id obj,
SEL sel );
1477 #if !CATCH_ARC_ENABLED
1478 inline void arcSafeRelease( NSObject* obj ) {
1481 inline id performOptionalSelector(
id obj,
SEL sel ) {
1482 if( [obj respondsToSelector: sel] )
1483 return [obj performSelector: sel];
1486 #define CATCH_UNSAFE_UNRETAINED
1487 #define CATCH_ARC_STRONG
1489 inline void arcSafeRelease( NSObject* ){}
1490 inline id performOptionalSelector(
id obj,
SEL sel ) {
1492 #pragma clang diagnostic push
1493 #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
1495 if( [obj respondsToSelector: sel] )
1496 return [obj performSelector: sel];
1498 #pragma clang diagnostic pop
1502 #define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
1503 #define CATCH_ARC_STRONG __strong
1508 #ifdef CATCH_CONFIG_CPP11_TUPLE
1512 #ifdef CATCH_CONFIG_CPP11_IS_ENUM
1513 #include <type_traits>
1519 template<
typename T>
1520 std::string toString( T
const& value );
1524 std::string toString( std::string
const& value );
1525 std::string toString( std::wstring
const& value );
1526 std::string toString(
const char*
const value );
1527 std::string toString(
char*
const value );
1528 std::string toString(
const wchar_t*
const value );
1529 std::string toString(
wchar_t*
const value );
1530 std::string toString(
int value );
1531 std::string toString(
unsigned long value );
1532 std::string toString(
unsigned int value );
1533 std::string toString(
const double value );
1534 std::string toString(
const float value );
1535 std::string toString(
bool value );
1536 std::string toString(
char value );
1537 std::string toString(
signed char value );
1538 std::string toString(
unsigned char value );
1540 #ifdef CATCH_CONFIG_CPP11_LONG_LONG
1541 std::string toString(
long long value );
1542 std::string toString(
unsigned long long value );
1545 #ifdef CATCH_CONFIG_CPP11_NULLPTR
1546 std::string toString( std::nullptr_t );
1550 std::string toString( NSString
const *
const& nsstring );
1551 std::string toString( NSString * CATCH_ARC_STRONG
const& nsstring );
1552 std::string toString( NSObject*
const& nsObject );
1557 extern const std::string unprintableString;
1560 template<
typename T>
BorgType( T
const& );
1566 TrueType& testStreamable( std::ostream& );
1571 template<
typename T>
1573 static std::ostream &s;
1575 enum { value =
sizeof( testStreamable(s << t) ) ==
sizeof(
TrueType ) };
1578 #if defined(CATCH_CONFIG_CPP11_IS_ENUM)
1579 template<
typename T,
1580 bool IsEnum = std::is_enum<T>::value
1582 struct EnumStringMaker
1584 static std::string convert( T
const& ) {
return unprintableString; }
1587 template<
typename T>
1588 struct EnumStringMaker<T,true>
1590 static std::string convert( T
const& v )
1592 return ::Catch::toString(
1593 static_cast<typename std::underlying_type<T>::type
>(v)
1600 #if defined(CATCH_CONFIG_CPP11_IS_ENUM)
1601 template<
typename T>
1602 static std::string convert( T
const& v )
1604 return EnumStringMaker<T>::convert( v );
1607 template<
typename T>
1608 static std::string convert( T
const& ) {
return unprintableString; }
1614 template<
typename T>
1615 static std::string convert( T
const& _value ) {
1616 std::ostringstream oss;
1622 std::string rawMemoryToString(
const void *
object, std::size_t size );
1624 template<
typename T>
1625 inline std::string rawMemoryToString(
const T&
object ) {
1626 return rawMemoryToString( &
object,
sizeof(
object) );
1631 template<
typename T>
1635 template<
typename T>
1637 template<
typename U>
1638 static std::string convert( U* p ) {
1642 return Detail::rawMemoryToString( p );
1646 template<
typename R,
typename C>
1648 static std::string convert( R C::* p ) {
1652 return Detail::rawMemoryToString( p );
1657 template<
typename InputIterator>
1658 std::string rangeToString( InputIterator first, InputIterator last );
1668 template<
typename T,
typename Allocator>
1669 std::string toString( std::vector<T,Allocator>
const& v ) {
1670 return Detail::rangeToString( v.begin(), v.end() );
1673 #ifdef CATCH_CONFIG_CPP11_TUPLE
1676 namespace TupleDetail {
1680 bool = (N < std::tuple_size<Tuple>::value)
1682 struct ElementPrinter {
1683 static void print(
const Tuple& tuple, std::ostream& os )
1685 os << ( N ?
", " :
" " )
1686 << Catch::toString(std::get<N>(tuple));
1687 ElementPrinter<Tuple,N+1>::print(tuple,os);
1695 struct ElementPrinter<Tuple,N,false> {
1696 static void print(
const Tuple&, std::ostream& ) {}
1701 template<
typename ...Types>
1702 struct StringMaker<std::tuple<Types...>> {
1704 static std::string convert(
const std::tuple<Types...>& tuple )
1706 std::ostringstream os;
1708 TupleDetail::ElementPrinter<std::tuple<Types...>>::print( tuple, os );
1716 template<
typename T>
1717 std::string makeString( T
const& value ) {
1718 return StringMaker<T>::convert( value );
1729 template<
typename T>
1730 std::string toString( T
const& value ) {
1731 return StringMaker<T>::convert( value );
1735 template<
typename InputIterator>
1736 std::string rangeToString( InputIterator first, InputIterator last ) {
1737 std::ostringstream oss;
1739 if( first != last ) {
1740 oss << Catch::toString( *first );
1741 for( ++first ; first != last ; ++first )
1742 oss <<
", " << Catch::toString( *first );
1755 template<
typename T>
1758 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
1764 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
1769 template<
typename RhsT>
1771 return captureExpression<Internal::IsEqualTo>( rhs );
1774 template<
typename RhsT>
1776 return captureExpression<Internal::IsNotEqualTo>( rhs );
1779 template<
typename RhsT>
1781 return captureExpression<Internal::IsLessThan>( rhs );
1784 template<
typename RhsT>
1786 return captureExpression<Internal::IsGreaterThan>( rhs );
1789 template<
typename RhsT>
1791 return captureExpression<Internal::IsLessThanOrEqualTo>( rhs );
1794 template<
typename RhsT>
1796 return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs );
1800 return captureExpression<Internal::IsEqualTo>( rhs );
1804 return captureExpression<Internal::IsNotEqualTo>( rhs );
1807 void endExpression() {
1808 bool value = m_lhs ? true :
false;
1810 .setLhs( Catch::toString( value ) )
1811 .setResultType( value )
1817 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( RhsT
const& );
1818 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( RhsT
const& );
1819 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( RhsT
const& );
1820 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( RhsT
const& );
1821 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT
const& );
1822 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT
const& );
1825 template<Internal::Operator Op,
typename RhsT>
1828 .setResultType( Internal::compare<Op>( m_lhs, rhs ) )
1829 .setLhs( Catch::toString( m_lhs ) )
1830 .setRhs( Catch::toString( rhs ) )
1844 template<
typename T>
1845 inline ExpressionLhs<T const&> ResultBuilder::operator <= ( T
const& operand ) {
1846 return ExpressionLhs<T const&>( *
this, operand );
1849 inline ExpressionLhs<bool> ResultBuilder::operator <= (
bool value ) {
1850 return ExpressionLhs<bool>( *
this, value );
1856 #define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
1865 ResultWas::OfType _type );
1867 std::string macroName;
1869 ResultWas::OfType type;
1870 std::string message;
1871 unsigned int sequence;
1873 bool operator == (
MessageInfo const& other )
const {
1874 return sequence == other.sequence;
1876 bool operator < (
MessageInfo const& other )
const {
1877 return sequence < other.sequence;
1880 static unsigned int globalCount;
1886 ResultWas::OfType type )
1887 : m_info( macroName, lineInfo, type )
1890 template<
typename T>
1897 std::ostringstream m_stream;
1912 #define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
1919 class AssertionResult;
1920 struct AssertionInfo;
1922 struct SectionEndInfo;
1924 class ScopedMessageBuilder;
1932 virtual bool sectionStarted(
SectionInfo const& sectionInfo,
1933 Counts& assertions ) = 0;
1935 virtual void sectionEndedEarly(
SectionEndInfo const& endInfo ) = 0;
1936 virtual void pushScopedMessage(
MessageInfo const& message ) = 0;
1937 virtual void popScopedMessage(
MessageInfo const& message ) = 0;
1939 virtual std::string getCurrentTestName()
const = 0;
1942 virtual void handleFatalErrorCondition( std::string
const& message ) = 0;
1949 #define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
1952 #define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED
1954 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
1955 #define CATCH_PLATFORM_MAC
1956 #elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
1957 #define CATCH_PLATFORM_IPHONE
1958 #elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
1959 #define CATCH_PLATFORM_WINDOWS
1966 bool isDebuggerActive();
1967 void writeToDebugConsole( std::string
const& text );
1970 #ifdef CATCH_PLATFORM_MAC
1975 #if defined(__ppc64__) || defined(__ppc__)
1976 #define CATCH_BREAK_INTO_DEBUGGER() \
1977 if( Catch::isDebuggerActive() ) { \
1978 __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
1979 : : : "memory","r0","r3","r4" ); \
1982 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );}
1986 #elif defined(_MSC_VER)
1987 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); }
1988 #elif defined(__MINGW32__)
1989 extern "C" __declspec(dllimport)
void __stdcall DebugBreak();
1990 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); }
1993 #ifndef CATCH_BREAK_INTO_DEBUGGER
1994 #define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue();
1998 #define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
2005 virtual bool aborting()
const = 0;
2014 #define INTERNAL_CATCH_REACT( resultBuilder ) \
2015 if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \
2016 resultBuilder.react();
2019 #define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \
2021 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
2023 ( __catchResult <= expr ).endExpression(); \
2026 __catchResult.useActiveException( Catch::ResultDisposition::Normal ); \
2028 INTERNAL_CATCH_REACT( __catchResult ) \
2029 } while( Catch::isTrue( false && (expr) ) )
2032 #define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \
2033 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
2034 if( Catch::getResultCapture().getLastResult()->succeeded() )
2037 #define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \
2038 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
2039 if( !Catch::getResultCapture().getLastResult()->succeeded() )
2042 #define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \
2044 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
2047 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2050 __catchResult.useActiveException( resultDisposition ); \
2052 INTERNAL_CATCH_REACT( __catchResult ) \
2053 } while( Catch::alwaysFalse() )
2056 #define INTERNAL_CATCH_THROWS( expr, resultDisposition, matcher, macroName ) \
2058 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \
2059 if( __catchResult.allowThrows() ) \
2062 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
2065 __catchResult.captureExpectedException( matcher ); \
2068 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2069 INTERNAL_CATCH_REACT( __catchResult ) \
2070 } while( Catch::alwaysFalse() )
2073 #define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \
2075 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
2076 if( __catchResult.allowThrows() ) \
2079 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
2081 catch( exceptionType ) { \
2082 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2085 __catchResult.useActiveException( resultDisposition ); \
2088 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2089 INTERNAL_CATCH_REACT( __catchResult ) \
2090 } while( Catch::alwaysFalse() )
2093 #ifdef CATCH_CONFIG_VARIADIC_MACROS
2094 #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \
2096 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
2097 __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \
2098 __catchResult.captureResult( messageType ); \
2099 INTERNAL_CATCH_REACT( __catchResult ) \
2100 } while( Catch::alwaysFalse() )
2102 #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \
2104 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
2105 __catchResult << log + ::Catch::StreamEndStop(); \
2106 __catchResult.captureResult( messageType ); \
2107 INTERNAL_CATCH_REACT( __catchResult ) \
2108 } while( Catch::alwaysFalse() )
2112 #define INTERNAL_CATCH_INFO( log, macroName ) \
2113 Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log;
2116 #define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \
2118 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \
2120 std::string matcherAsString = (matcher).toString(); \
2122 .setLhs( Catch::toString( arg ) ) \
2123 .setRhs( matcherAsString == Catch::Detail::unprintableString ? #matcher : matcherAsString ) \
2124 .setOp( "matches" ) \
2125 .setResultType( (matcher).match( arg ) ); \
2126 __catchResult.captureExpression(); \
2128 __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \
2130 INTERNAL_CATCH_REACT( __catchResult ) \
2131 } while( Catch::alwaysFalse() )
2134 #define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
2137 #define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED
2140 #define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED
2147 Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {}
2151 diff.passed = passed - other.passed;
2152 diff.failed = failed - other.failed;
2153 diff.failedButOk = failedButOk - other.failedButOk;
2157 passed += other.passed;
2158 failed += other.failed;
2159 failedButOk += other.failedButOk;
2163 std::size_t total()
const {
2164 return passed + failed + failedButOk;
2166 bool allPassed()
const {
2167 return failed == 0 && failedButOk == 0;
2169 bool allOk()
const {
2175 std::size_t failedButOk;
2182 diff.assertions = assertions - other.assertions;
2183 diff.testCases = testCases - other.testCases;
2188 Totals diff = *
this - prevTotals;
2189 if( diff.assertions.failed > 0 )
2190 ++diff.testCases.failed;
2191 else if( diff.assertions.failedButOk > 0 )
2192 ++diff.testCases.failedButOk;
2194 ++diff.testCases.passed;
2199 assertions += other.assertions;
2200 testCases += other.testCases;
2214 std::string
const& _name,
2215 std::string
const& _description = std::string() );
2218 std::string description;
2224 : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
2229 double durationInSeconds;
2235 #define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED
2237 #ifdef CATCH_PLATFORM_WINDOWS
2238 typedef unsigned long long uint64_t;
2247 Timer() : m_ticks( 0 ) {}
2249 unsigned int getElapsedMicroseconds()
const;
2250 unsigned int getElapsedMilliseconds()
const;
2251 double getElapsedSeconds()
const;
2269 operator bool()
const;
2276 bool m_sectionIncluded;
2282 #ifdef CATCH_CONFIG_VARIADIC_MACROS
2283 #define INTERNAL_CATCH_SECTION( ... ) \
2284 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) )
2286 #define INTERNAL_CATCH_SECTION( name, desc ) \
2287 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) )
2291 #define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
2300 template<
typename T>
2303 virtual T getValue( std::size_t index )
const = 0;
2304 virtual std::size_t size ()
const = 0;
2307 template<
typename T>
2312 virtual T getValue( std::size_t index )
const {
2313 return m_from+
static_cast<int>( index );
2316 virtual std::size_t size()
const {
2317 return static_cast<std::size_t
>( 1+m_to-m_from );
2326 template<
typename T>
2331 void add( T value ) {
2332 m_values.push_back( value );
2335 virtual T getValue( std::size_t index )
const {
2336 return m_values[index];
2339 virtual std::size_t size()
const {
2340 return m_values.size();
2344 std::vector<T> m_values;
2347 template<
typename T>
2354 : m_fileInfo( other.m_fileInfo ),
2361 m_fileInfo = fileInfo;
2366 deleteAll( m_composed );
2369 operator T ()
const {
2370 size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize );
2372 typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin();
2373 typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
2374 for(
size_t index = 0; it != itEnd; ++it )
2377 if( overallIndex >= index && overallIndex < index + generator->size() )
2379 return generator->getValue( overallIndex-index );
2381 index += generator->size();
2383 CATCH_INTERNAL_ERROR(
"Indexed past end of generated range" );
2388 m_totalSize += generator->size();
2389 m_composed.push_back( generator );
2399 valuesGen->add( value );
2407 std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) );
2408 m_totalSize += other.m_totalSize;
2409 other.m_composed.clear();
2412 std::vector<const IGenerator<T>*> m_composed;
2413 std::string m_fileInfo;
2417 namespace Generators
2419 template<
typename T>
2426 template<
typename T>
2427 CompositeGenerator<T> values( T val1, T val2 ) {
2428 CompositeGenerator<T> generators;
2429 ValuesGenerator<T>* valuesGen =
new ValuesGenerator<T>();
2430 valuesGen->add( val1 );
2431 valuesGen->add( val2 );
2432 generators.add( valuesGen );
2436 template<
typename T>
2437 CompositeGenerator<T> values( T val1, T val2, T val3 ){
2438 CompositeGenerator<T> generators;
2439 ValuesGenerator<T>* valuesGen =
new ValuesGenerator<T>();
2440 valuesGen->add( val1 );
2441 valuesGen->add( val2 );
2442 valuesGen->add( val3 );
2443 generators.add( valuesGen );
2447 template<
typename T>
2448 CompositeGenerator<T> values( T val1, T val2, T val3, T val4 ) {
2449 CompositeGenerator<T> generators;
2450 ValuesGenerator<T>* valuesGen =
new ValuesGenerator<T>();
2451 valuesGen->add( val1 );
2452 valuesGen->add( val2 );
2453 valuesGen->add( val3 );
2454 valuesGen->add( val4 );
2455 generators.add( valuesGen );
2461 using namespace Generators;
2465 #define INTERNAL_CATCH_LINESTR2( line ) #line
2466 #define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
2468 #define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
2471 #define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
2477 #define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
2484 struct ITestCaseRegistry;
2485 struct IExceptionTranslatorRegistry;
2486 struct IExceptionTranslator;
2487 struct IReporterRegistry;
2488 struct IReporterFactory;
2493 virtual IReporterRegistry
const& getReporterRegistry()
const = 0;
2502 virtual void registerTest(
TestCase const& testInfo ) = 0;
2509 std::string translateActiveException();
2515 typedef std::string(*exceptionTranslateFunction)();
2517 struct IExceptionTranslator;
2518 typedef std::vector<const IExceptionTranslator*> ExceptionTranslators;
2522 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd )
const = 0;
2528 virtual std::string translateActiveException()
const = 0;
2532 template<
typename T>
2536 ExceptionTranslator( std::string(*translateFunction)( T& ) )
2537 : m_translateFunction( translateFunction )
2540 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd )
const CATCH_OVERRIDE {
2545 return (*it)->translate( it+1, itEnd );
2548 return m_translateFunction( ex );
2553 std::string(*m_translateFunction)( T& );
2557 template<
typename T>
2559 getMutableRegistryHub().registerTranslator
2560 (
new ExceptionTranslator<T>( translateFunction ) );
2566 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \
2567 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \
2568 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\
2569 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature )
2572 #define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
2582 explicit Approx (
double value )
2583 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
2589 : m_epsilon( other.m_epsilon ),
2590 m_scale( other.m_scale ),
2591 m_value( other.m_value )
2598 Approx operator()(
double value ) {
2600 approx.epsilon( m_epsilon );
2601 approx.scale( m_scale );
2605 friend bool operator == (
double lhs,
Approx const& rhs ) {
2607 return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) );
2610 friend bool operator == (
Approx const& lhs,
double rhs ) {
2611 return operator==( rhs, lhs );
2614 friend bool operator != (
double lhs,
Approx const& rhs ) {
2615 return !operator==( lhs, rhs );
2618 friend bool operator != (
Approx const& lhs,
double rhs ) {
2619 return !operator==( rhs, lhs );
2622 Approx& epsilon(
double newEpsilon ) {
2623 m_epsilon = newEpsilon;
2627 Approx& scale(
double newScale ) {
2632 std::string toString()
const {
2633 std::ostringstream oss;
2634 oss <<
"Approx( " << Catch::toString( m_value ) <<
" )";
2646 inline std::string toString<Detail::Approx>(
Detail::Approx const& value ) {
2647 return value.toString();
2653 #define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED
2656 #define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED
2675 #define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); }
2677 #define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED
2682 template<
typename T>
2685 Option() : nullableValue( CATCH_NULL ) {}
2686 Option( T
const& _value )
2687 : nullableValue(
new( storage ) T( _value ) )
2690 : nullableValue( _other ?
new( storage ) T( *_other ) : CATCH_NULL )
2698 if( &_other !=
this ) {
2701 nullableValue =
new( storage ) T( *_other );
2705 Option& operator = ( T
const& _value ) {
2707 nullableValue =
new( storage ) T( _value );
2713 nullableValue->~T();
2714 nullableValue = CATCH_NULL;
2717 T& operator*() {
return *nullableValue; }
2718 T
const& operator*()
const {
return *nullableValue; }
2719 T* operator->() {
return nullableValue; }
2720 const T* operator->()
const {
return nullableValue; }
2722 T valueOr( T
const& defaultValue )
const {
2723 return nullableValue ? *nullableValue : defaultValue;
2726 bool some()
const {
return nullableValue != CATCH_NULL; }
2727 bool none()
const {
return nullableValue == CATCH_NULL; }
2729 bool operator !()
const {
return nullableValue == CATCH_NULL; }
2730 operator SafeBool::type()
const {
2731 return SafeBool::makeSafe( some() );
2736 char storage[
sizeof(T)];
2746 virtual std::string expandAliases( std::string
const& unexpandedTestSpec )
const = 0;
2756 #define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
2762 #pragma clang diagnostic push
2763 #pragma clang diagnostic ignored "-Wpadded"
2771 enum SpecialProperties{
2774 ShouldFail = 1 << 2,
2780 std::string
const& _className,
2781 std::string
const& _description,
2782 std::set<std::string>
const& _tags,
2787 friend void setTags(
TestCaseInfo& testCaseInfo, std::set<std::string>
const& tags );
2789 bool isHidden()
const;
2790 bool throws()
const;
2791 bool okToFail()
const;
2792 bool expectedToFail()
const;
2795 std::string className;
2796 std::string description;
2797 std::set<std::string> tags;
2798 std::set<std::string> lcaseTags;
2799 std::string tagsAsString;
2801 SpecialProperties properties;
2810 TestCase withName( std::string
const& _newName )
const;
2812 void invoke()
const;
2817 bool operator == (
TestCase const& other )
const;
2818 bool operator < (
TestCase const& other )
const;
2826 std::string
const& className,
2827 std::string
const& name,
2828 std::string
const& description,
2833 #pragma clang diagnostic pop
2839 #define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
2841 #import <objc/runtime.h>
2863 class OcMethod :
public SharedImpl<ITestCase> {
2866 OcMethod( Class cls,
SEL sel ) : m_cls( cls ), m_sel( sel ) {}
2868 virtual void invoke()
const {
2869 id obj = [[m_cls alloc] init];
2871 performOptionalSelector( obj,
@selector(setUp) );
2872 performOptionalSelector( obj, m_sel );
2873 performOptionalSelector( obj,
@selector(tearDown) );
2875 arcSafeRelease( obj );
2878 virtual ~OcMethod() {}
2886 inline std::string getAnnotation( Class cls,
2887 std::string
const& annotationName,
2888 std::string
const& testCaseName ) {
2889 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
2890 SEL sel = NSSelectorFromString( selStr );
2891 arcSafeRelease( selStr );
2892 id value = performOptionalSelector( cls, sel );
2894 return [(NSString*)value UTF8String];
2899 inline size_t registerTestMethods() {
2900 size_t noTestMethods = 0;
2901 int noClasses = objc_getClassList( CATCH_NULL, 0 );
2903 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc(
sizeof(Class) * noClasses);
2904 objc_getClassList( classes, noClasses );
2906 for(
int c = 0; c < noClasses; c++ ) {
2907 Class cls = classes[c];
2910 Method* methods = class_copyMethodList( cls, &count );
2911 for( u_int m = 0; m < count ; m++ ) {
2912 SEL selector = method_getName(methods[m]);
2913 std::string methodName = sel_getName(selector);
2914 if( startsWith( methodName,
"Catch_TestCase_" ) ) {
2915 std::string testCaseName = methodName.substr( 15 );
2916 std::string name = Detail::getAnnotation( cls,
"Name", testCaseName );
2917 std::string desc = Detail::getAnnotation( cls,
"Description", testCaseName );
2918 const char* className = class_getName( cls );
2920 getMutableRegistryHub().registerTest( makeTestCase(
new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) );
2927 return noTestMethods;
2930 namespace Matchers {
2932 namespace NSStringMatchers {
2934 template<
typename MatcherT>
2935 struct StringHolder : MatcherImpl<MatcherT, NSString*>{
2936 StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
2937 StringHolder( StringHolder
const& other ) : m_substr( [other.m_substr copy] ){}
2939 arcSafeRelease( m_substr );
2945 struct Equals : StringHolder<Equals> {
2946 Equals( NSString* substr ) : StringHolder( substr ){}
2948 virtual bool match( ExpressionType
const& str )
const {
2949 return (str != nil || m_substr == nil ) &&
2950 [str isEqualToString:m_substr];
2953 virtual std::string toString()
const {
2954 return "equals string: " + Catch::toString( m_substr );
2958 struct Contains : StringHolder<Contains> {
2959 Contains( NSString* substr ) : StringHolder( substr ){}
2961 virtual bool match( ExpressionType
const& str )
const {
2962 return (str != nil || m_substr == nil ) &&
2963 [str rangeOfString:m_substr].location != NSNotFound;
2966 virtual std::string toString()
const {
2967 return "contains string: " + Catch::toString( m_substr );
2971 struct StartsWith : StringHolder<StartsWith> {
2972 StartsWith( NSString* substr ) : StringHolder( substr ){}
2974 virtual bool match( ExpressionType
const& str )
const {
2975 return (str != nil || m_substr == nil ) &&
2976 [str rangeOfString:m_substr].location == 0;
2979 virtual std::string toString()
const {
2980 return "starts with: " + Catch::toString( m_substr );
2983 struct EndsWith : StringHolder<EndsWith> {
2984 EndsWith( NSString* substr ) : StringHolder( substr ){}
2986 virtual bool match( ExpressionType
const& str )
const {
2987 return (str != nil || m_substr == nil ) &&
2988 [str rangeOfString:m_substr].location == [str length] - [m_substr length];
2991 virtual std::string toString()
const {
2992 return "ends with: " + Catch::toString( m_substr );
2999 inline Impl::NSStringMatchers::Equals
3000 Equals( NSString* substr ){
return Impl::NSStringMatchers::Equals( substr ); }
3002 inline Impl::NSStringMatchers::Contains
3003 Contains( NSString* substr ){
return Impl::NSStringMatchers::Contains( substr ); }
3005 inline Impl::NSStringMatchers::StartsWith
3006 StartsWith( NSString* substr ){
return Impl::NSStringMatchers::StartsWith( substr ); }
3008 inline Impl::NSStringMatchers::EndsWith
3009 EndsWith( NSString* substr ){
return Impl::NSStringMatchers::EndsWith( substr ); }
3013 using namespace Matchers;
3018 #define OC_TEST_CASE( name, desc )\
3019 +(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \
3023 +(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \
3027 -(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test )
3033 #define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
3039 #pragma clang diagnostic push
3040 #pragma clang diagnostic ignored "-Wweak-vtables"
3044 #define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
3047 #define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
3050 #define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
3053 #define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED
3056 #pragma clang diagnostic push
3057 #pragma clang diagnostic ignored "-Wpadded"
3061 #define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED
3064 #pragma clang diagnostic push
3065 #pragma clang diagnostic ignored "-Wpadded"
3069 #define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED
3073 class WildcardPattern {
3074 enum WildcardPosition {
3076 WildcardAtStart = 1,
3078 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
3083 WildcardPattern( std::string
const& pattern, CaseSensitive::Choice caseSensitivity )
3084 : m_caseSensitivity( caseSensitivity ),
3085 m_wildcard( NoWildcard ),
3086 m_pattern( adjustCase( pattern ) )
3088 if( startsWith( m_pattern,
"*" ) ) {
3089 m_pattern = m_pattern.substr( 1 );
3090 m_wildcard = WildcardAtStart;
3092 if( endsWith( m_pattern,
"*" ) ) {
3093 m_pattern = m_pattern.substr( 0, m_pattern.size()-1 );
3094 m_wildcard =
static_cast<WildcardPosition
>( m_wildcard | WildcardAtEnd );
3097 virtual ~WildcardPattern();
3098 virtual bool matches( std::string
const& str )
const {
3099 switch( m_wildcard ) {
3101 return m_pattern == adjustCase( str );
3102 case WildcardAtStart:
3103 return endsWith( adjustCase( str ), m_pattern );
3105 return startsWith( adjustCase( str ), m_pattern );
3106 case WildcardAtBothEnds:
3107 return contains( adjustCase( str ), m_pattern );
3111 #pragma clang diagnostic push
3112 #pragma clang diagnostic ignored "-Wunreachable-code"
3114 throw std::logic_error(
"Unknown enum" );
3116 #pragma clang diagnostic pop
3120 std::string adjustCase( std::string
const& str )
const {
3121 return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str;
3123 CaseSensitive::Choice m_caseSensitivity;
3124 WildcardPosition m_wildcard;
3125 std::string m_pattern;
3135 struct Pattern : SharedImpl<> {
3137 virtual bool matches( TestCaseInfo
const& testCase )
const = 0;
3139 class NamePattern :
public Pattern {
3141 NamePattern( std::string
const& name )
3142 : m_wildcardPattern( toLower( name ), CaseSensitive::No )
3144 virtual ~NamePattern();
3145 virtual bool matches( TestCaseInfo
const& testCase )
const {
3146 return m_wildcardPattern.matches( toLower( testCase.name ) );
3149 WildcardPattern m_wildcardPattern;
3152 class TagPattern :
public Pattern {
3154 TagPattern( std::string
const& tag ) : m_tag( toLower( tag ) ) {}
3155 virtual ~TagPattern();
3156 virtual bool matches( TestCaseInfo
const& testCase )
const {
3157 return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end();
3163 class ExcludedPattern :
public Pattern {
3165 ExcludedPattern( Ptr<Pattern>
const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}
3166 virtual ~ExcludedPattern();
3167 virtual bool matches( TestCaseInfo
const& testCase )
const {
return !m_underlyingPattern->matches( testCase ); }
3169 Ptr<Pattern> m_underlyingPattern;
3173 std::vector<Ptr<Pattern> > m_patterns;
3175 bool matches( TestCaseInfo
const& testCase )
const {
3177 for( std::vector<Ptr<Pattern> >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it )
3178 if( !(*it)->matches( testCase ) )
3185 bool hasFilters()
const {
3186 return !m_filters.empty();
3188 bool matches( TestCaseInfo
const& testCase )
const {
3190 for( std::vector<Filter>::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it )
3191 if( it->matches( testCase ) )
3197 std::vector<Filter> m_filters;
3199 friend class TestSpecParser;
3204 #pragma clang diagnostic pop
3209 class TestSpecParser {
3210 enum Mode{ None, Name, QuotedName, Tag };
3213 std::size_t m_start, m_pos;
3215 TestSpec::Filter m_currentFilter;
3216 TestSpec m_testSpec;
3217 ITagAliasRegistry
const* m_tagAliases;
3220 TestSpecParser( ITagAliasRegistry
const& tagAliases ) : m_tagAliases( &tagAliases ) {}
3222 TestSpecParser& parse( std::string
const& arg ) {
3224 m_exclusion =
false;
3225 m_start = std::string::npos;
3226 m_arg = m_tagAliases->expandAliases( arg );
3227 for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
3228 visitChar( m_arg[m_pos] );
3229 if( m_mode == Name )
3230 addPattern<TestSpec::NamePattern>();
3233 TestSpec testSpec() {
3238 void visitChar(
char c ) {
3239 if( m_mode == None ) {
3242 case '~': m_exclusion =
true;
return;
3243 case '[':
return startNewMode( Tag, ++m_pos );
3244 case '"':
return startNewMode( QuotedName, ++m_pos );
3245 default: startNewMode( Name, m_pos );
break;
3248 if( m_mode == Name ) {
3250 addPattern<TestSpec::NamePattern>();
3253 else if( c ==
'[' ) {
3254 if( subString() ==
"exclude:" )
3257 addPattern<TestSpec::NamePattern>();
3258 startNewMode( Tag, ++m_pos );
3261 else if( m_mode == QuotedName && c ==
'"' )
3262 addPattern<TestSpec::NamePattern>();
3263 else if( m_mode == Tag && c ==
']' )
3264 addPattern<TestSpec::TagPattern>();
3266 void startNewMode( Mode mode, std::size_t start ) {
3270 std::string subString()
const {
return m_arg.substr( m_start, m_pos - m_start ); }
3271 template<
typename T>
3273 std::string token = subString();
3274 if( startsWith( token,
"exclude:" ) ) {
3276 token = token.substr( 8 );
3278 if( !token.empty() ) {
3279 Ptr<TestSpec::Pattern> pattern =
new T( token );
3281 pattern =
new TestSpec::ExcludedPattern( pattern );
3282 m_currentFilter.m_patterns.push_back( pattern );
3284 m_exclusion =
false;
3288 if( !m_currentFilter.m_patterns.empty() ) {
3289 m_testSpec.m_filters.push_back( m_currentFilter );
3290 m_currentFilter = TestSpec::Filter();
3294 inline TestSpec parseTestSpec( std::string
const& arg ) {
3295 return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec();
3301 #pragma clang diagnostic pop
3305 #define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED
3313 struct Verbosity {
enum Level {
3319 struct WarnAbout {
enum What {
3324 struct ShowDurations {
enum OrNot {
3329 struct RunTests {
enum InWhatOrder {
3331 InLexicographicalOrder,
3337 struct IConfig : IShared {
3341 virtual bool allowThrows()
const = 0;
3342 virtual std::ostream& stream()
const = 0;
3343 virtual std::string name()
const = 0;
3344 virtual bool includeSuccessfulResults()
const = 0;
3345 virtual bool shouldDebugBreak()
const = 0;
3346 virtual bool warnAboutMissingAssertions()
const = 0;
3347 virtual int abortAfter()
const = 0;
3348 virtual bool showInvisibles()
const = 0;
3349 virtual ShowDurations::OrNot showDurations()
const = 0;
3350 virtual TestSpec
const& testSpec()
const = 0;
3351 virtual RunTests::InWhatOrder runOrder()
const = 0;
3352 virtual unsigned int rngSeed()
const = 0;
3353 virtual bool forceColour()
const = 0;
3358 #define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
3361 #define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
3363 #include <streambuf>
3367 class StreamBufBase :
public std::streambuf {
3369 virtual ~StreamBufBase() CATCH_NOEXCEPT;
3373 #include <streambuf>
3379 std::ostream& cout();
3380 std::ostream& cerr();
3383 virtual ~IStream() CATCH_NOEXCEPT;
3384 virtual std::ostream& stream() const = 0;
3387 class FileStream : public IStream {
3388 mutable std::ofstream m_ofs;
3390 FileStream( std::string
const& filename );
3391 virtual ~FileStream() CATCH_NOEXCEPT;
3393 virtual std::ostream& stream() const CATCH_OVERRIDE;
3396 class CoutStream : public IStream {
3397 mutable std::ostream m_os;
3400 virtual ~CoutStream() CATCH_NOEXCEPT;
3403 virtual std::ostream& stream() const CATCH_OVERRIDE;
3406 class DebugOutStream : public IStream {
3407 std::auto_ptr<StreamBufBase> m_streamBuf;
3408 mutable std::ostream m_os;
3411 virtual ~DebugOutStream() CATCH_NOEXCEPT;
3414 virtual std::ostream& stream() const CATCH_OVERRIDE;
3424 #ifndef CATCH_CONFIG_CONSOLE_WIDTH
3425 #define CATCH_CONFIG_CONSOLE_WIDTH 80
3433 : listTests( false ),
3435 listReporters( false ),
3436 listTestNamesOnly( false ),
3437 showSuccessfulTests( false ),
3438 shouldDebugBreak( false ),
3441 showInvisibles( false ),
3442 forceColour( false ),
3443 filenamesAsTags( false ),
3446 verbosity( Verbosity::Normal ),
3447 warnings( WarnAbout::Nothing ),
3448 showDurations( ShowDurations::DefaultForReporter ),
3449 runOrder( RunTests::InDeclarationOrder )
3455 bool listTestNamesOnly;
3457 bool showSuccessfulTests;
3458 bool shouldDebugBreak;
3461 bool showInvisibles;
3463 bool filenamesAsTags;
3466 unsigned int rngSeed;
3468 Verbosity::Level verbosity;
3469 WarnAbout::What warnings;
3470 ShowDurations::OrNot showDurations;
3471 RunTests::InWhatOrder runOrder;
3473 std::string outputFilename;
3475 std::string processName;
3477 std::vector<std::string> reporterNames;
3478 std::vector<std::string> testsOrTags;
3481 class Config :
public SharedImpl<IConfig> {
3483 Config( Config
const& other );
3484 Config& operator = ( Config
const& other );
3485 virtual void dummy();
3491 Config( ConfigData
const& data )
3493 m_stream( openStream() )
3495 if( !data.testsOrTags.empty() ) {
3496 TestSpecParser parser( ITagAliasRegistry::get() );
3497 for( std::size_t i = 0; i < data.testsOrTags.size(); ++i )
3498 parser.parse( data.testsOrTags[i] );
3499 m_testSpec = parser.testSpec();
3506 std::string
const& getFilename()
const {
3507 return m_data.outputFilename ;
3510 bool listTests()
const {
return m_data.listTests; }
3511 bool listTestNamesOnly()
const {
return m_data.listTestNamesOnly; }
3512 bool listTags()
const {
return m_data.listTags; }
3513 bool listReporters()
const {
return m_data.listReporters; }
3515 std::string getProcessName()
const {
return m_data.processName; }
3517 bool shouldDebugBreak()
const {
return m_data.shouldDebugBreak; }
3519 std::vector<std::string> getReporterNames()
const {
return m_data.reporterNames; }
3521 int abortAfter()
const {
return m_data.abortAfter; }
3523 TestSpec
const& testSpec()
const {
return m_testSpec; }
3525 bool showHelp()
const {
return m_data.showHelp; }
3526 bool showInvisibles()
const {
return m_data.showInvisibles; }
3529 virtual bool allowThrows()
const {
return !m_data.noThrow; }
3530 virtual std::ostream& stream()
const {
return m_stream->stream(); }
3531 virtual std::string name()
const {
return m_data.name.empty() ? m_data.processName : m_data.name; }
3532 virtual bool includeSuccessfulResults()
const {
return m_data.showSuccessfulTests; }
3533 virtual bool warnAboutMissingAssertions()
const {
return m_data.warnings & WarnAbout::NoAssertions; }
3534 virtual ShowDurations::OrNot showDurations()
const {
return m_data.showDurations; }
3535 virtual RunTests::InWhatOrder runOrder()
const {
return m_data.runOrder; }
3536 virtual unsigned int rngSeed()
const {
return m_data.rngSeed; }
3537 virtual bool forceColour()
const {
return m_data.forceColour; }
3541 IStream
const* openStream() {
3542 if( m_data.outputFilename.empty() )
3543 return new CoutStream();
3544 else if( m_data.outputFilename[0] ==
'%' ) {
3545 if( m_data.outputFilename ==
"%debug" )
3546 return new DebugOutStream();
3548 throw std::domain_error(
"Unrecognised stream: " + m_data.outputFilename );
3551 return new FileStream( m_data.outputFilename );
3555 std::auto_ptr<IStream const> m_stream;
3556 TestSpec m_testSpec;
3562 #define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED
3565 #ifdef CLARA_CONFIG_CONSOLE_WIDTH
3566 #define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH
3567 #undef CLARA_CONFIG_CONSOLE_WIDTH
3569 #define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
3572 #define STITCH_CLARA_OPEN_NAMESPACE namespace Catch {
3576 #if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE)
3578 #ifndef STITCH_CLARA_OPEN_NAMESPACE
3579 #define TWOBLUECUBES_CLARA_H_INCLUDED
3580 #define STITCH_CLARA_OPEN_NAMESPACE
3581 #define STITCH_CLARA_CLOSE_NAMESPACE
3583 #define STITCH_CLARA_CLOSE_NAMESPACE }
3586 #define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE
3591 #if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE)
3592 #ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
3593 #define TBC_TEXT_FORMAT_H_INCLUDED
3601 #ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
3602 namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
3607 #ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
3608 const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
3610 const unsigned int consoleWidth = 80;
3613 struct TextAttributes {
3615 : initialIndent( std::string::npos ),
3617 width( consoleWidth-1 ),
3621 TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value;
return *
this; }
3622 TextAttributes& setIndent( std::size_t _value ) { indent = _value;
return *
this; }
3623 TextAttributes& setWidth( std::size_t _value ) { width = _value;
return *
this; }
3624 TextAttributes& setTabChar(
char _value ) { tabChar = _value;
return *
this; }
3626 std::size_t initialIndent;
3634 Text( std::string
const& _str, TextAttributes
const& _attr = TextAttributes() )
3637 std::string wrappableChars =
" [({.,/|\\-";
3638 std::size_t indent = _attr.initialIndent != std::string::npos
3639 ? _attr.initialIndent
3641 std::string remainder = _str;
3643 while( !remainder.empty() ) {
3644 if( lines.size() >= 1000 ) {
3645 lines.push_back(
"... message truncated due to excessive size" );
3648 std::size_t tabPos = std::string::npos;
3649 std::size_t width = (std::min)( remainder.size(), _attr.width - indent );
3650 std::size_t pos = remainder.find_first_of(
'\n' );
3651 if( pos <= width ) {
3654 pos = remainder.find_last_of( _attr.tabChar, width );
3655 if( pos != std::string::npos ) {
3657 if( remainder[width] ==
'\n' )
3659 remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 );
3662 if( width == remainder.size() ) {
3663 spliceLine( indent, remainder, width );
3665 else if( remainder[width] ==
'\n' ) {
3666 spliceLine( indent, remainder, width );
3667 if( width <= 1 || remainder.size() != 1 )
3668 remainder = remainder.substr( 1 );
3669 indent = _attr.indent;
3672 pos = remainder.find_last_of( wrappableChars, width );
3673 if( pos != std::string::npos && pos > 0 ) {
3674 spliceLine( indent, remainder, pos );
3675 if( remainder[0] ==
' ' )
3676 remainder = remainder.substr( 1 );
3679 spliceLine( indent, remainder, width-1 );
3680 lines.back() += "-";
3682 if( lines.size() == 1 )
3683 indent = _attr.indent;
3684 if( tabPos != std::string::npos )
3690 void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) {
3691 lines.push_back( std::string( _indent,
' ' ) + _remainder.substr( 0, _pos ) );
3692 _remainder = _remainder.substr( _pos );
3695 typedef std::vector<std::string>::const_iterator const_iterator;
3697 const_iterator begin()
const {
return lines.begin(); }
3698 const_iterator end()
const {
return lines.end(); }
3699 std::string
const& last()
const {
return lines.back(); }
3700 std::size_t size()
const {
return lines.size(); }
3701 std::string
const& operator[]( std::size_t _index )
const {
return lines[_index]; }
3702 std::string toString()
const {
3703 std::ostringstream oss;
3708 inline friend std::ostream& operator << ( std::ostream& _stream, Text
const& _text ) {
3709 for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
3710 it != itEnd; ++it ) {
3711 if( it != _text.begin() )
3720 TextAttributes attr;
3721 std::vector<std::string> lines;
3726 #ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
3735 #undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE
3738 #include <algorithm>
3739 #include <stdexcept>
3743 #ifdef STITCH_CLARA_OPEN_NAMESPACE
3744 STITCH_CLARA_OPEN_NAMESPACE
3749 struct UnpositionalTag {};
3751 extern UnpositionalTag _;
3753 #ifdef CLARA_CONFIG_MAIN
3759 #ifdef CLARA_CONSOLE_WIDTH
3760 const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH;
3762 const unsigned int consoleWidth = 80;
3765 using namespace Tbc;
3767 inline bool startsWith( std::string
const& str, std::string
const& prefix ) {
3768 return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix;
3771 template<
typename T>
struct RemoveConstRef{
typedef T type; };
3772 template<
typename T>
struct RemoveConstRef<T&>{
typedef T type; };
3773 template<
typename T>
struct RemoveConstRef<T const&>{
typedef T type; };
3774 template<
typename T>
struct RemoveConstRef<T const>{
typedef T type; };
3776 template<
typename T>
struct IsBool {
static const bool value =
false; };
3777 template<>
struct IsBool<bool> {
static const bool value =
true; };
3779 template<
typename T>
3780 void convertInto( std::string
const& _source, T& _dest ) {
3781 std::stringstream ss;
3785 throw std::runtime_error(
"Unable to convert " + _source +
" to destination type" );
3787 inline void convertInto( std::string
const& _source, std::string& _dest ) {
3790 inline void convertInto( std::string
const& _source,
bool& _dest ) {
3791 std::string sourceLC = _source;
3792 std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), ::tolower );
3793 if( sourceLC ==
"y" || sourceLC ==
"1" || sourceLC ==
"true" || sourceLC ==
"yes" || sourceLC ==
"on" )
3795 else if( sourceLC ==
"n" || sourceLC ==
"0" || sourceLC ==
"false" || sourceLC ==
"no" || sourceLC ==
"off" )
3798 throw std::runtime_error(
"Expected a boolean value but did not recognise:\n '" + _source +
"'" );
3800 inline void convertInto(
bool _source,
bool& _dest ) {
3803 template<
typename T>
3804 inline void convertInto(
bool, T& ) {
3805 throw std::runtime_error(
"Invalid conversion" );
3808 template<
typename ConfigT>
3809 struct IArgFunction {
3810 virtual ~IArgFunction() {}
3811 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
3812 IArgFunction() =
default;
3813 IArgFunction( IArgFunction
const& ) =
default;
3815 virtual void set( ConfigT& config, std::string
const& value )
const = 0;
3816 virtual void setFlag( ConfigT& config )
const = 0;
3817 virtual bool takesArg()
const = 0;
3818 virtual IArgFunction* clone()
const = 0;
3821 template<
typename ConfigT>
3822 class BoundArgFunction {
3824 BoundArgFunction() : functionObj( CATCH_NULL ) {}
3825 BoundArgFunction( IArgFunction<ConfigT>* _functionObj ) : functionObj( _functionObj ) {}
3826 BoundArgFunction( BoundArgFunction
const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : CATCH_NULL ) {}
3827 BoundArgFunction& operator = ( BoundArgFunction
const& other ) {
3828 IArgFunction<ConfigT>* newFunctionObj = other.functionObj ? other.functionObj->clone() : CATCH_NULL;
3830 functionObj = newFunctionObj;
3833 ~BoundArgFunction() {
delete functionObj; }
3835 void set( ConfigT& config, std::string
const& value )
const {
3836 functionObj->set( config, value );
3838 void setFlag( ConfigT& config )
const {
3839 functionObj->setFlag( config );
3841 bool takesArg()
const {
return functionObj->takesArg(); }
3843 bool isSet()
const {
3844 return functionObj != CATCH_NULL;
3847 IArgFunction<ConfigT>* functionObj;
3850 template<
typename C>
3851 struct NullBinder : IArgFunction<C>{
3852 virtual void set( C&, std::string
const& )
const {}
3853 virtual void setFlag( C& )
const {}
3854 virtual bool takesArg()
const {
return true; }
3855 virtual IArgFunction<C>* clone()
const {
return new NullBinder( *
this ); }
3858 template<
typename C,
typename M>
3859 struct BoundDataMember : IArgFunction<C>{
3860 BoundDataMember( M C::* _member ) : member( _member ) {}
3861 virtual void set( C& p, std::string
const& stringValue )
const {
3862 convertInto( stringValue, p.*member );
3864 virtual void setFlag( C& p )
const {
3865 convertInto(
true, p.*member );
3867 virtual bool takesArg()
const {
return !IsBool<M>::value; }
3868 virtual IArgFunction<C>* clone()
const {
return new BoundDataMember( *
this ); }
3871 template<
typename C,
typename M>
3872 struct BoundUnaryMethod : IArgFunction<C>{
3873 BoundUnaryMethod(
void (C::*_member)( M ) ) : member( _member ) {}
3874 virtual void set( C& p, std::string
const& stringValue )
const {
3875 typename RemoveConstRef<M>::type value;
3876 convertInto( stringValue, value );
3877 (p.*member)( value );
3879 virtual void setFlag( C& p )
const {
3880 typename RemoveConstRef<M>::type value;
3881 convertInto(
true, value );
3882 (p.*member)( value );
3884 virtual bool takesArg()
const {
return !IsBool<M>::value; }
3885 virtual IArgFunction<C>* clone()
const {
return new BoundUnaryMethod( *
this ); }
3886 void (C::*member)( M );
3888 template<
typename C>
3889 struct BoundNullaryMethod : IArgFunction<C>{
3890 BoundNullaryMethod(
void (C::*_member)() ) : member( _member ) {}
3891 virtual void set( C& p, std::string
const& stringValue )
const {
3893 convertInto( stringValue, value );
3897 virtual void setFlag( C& p )
const {
3900 virtual bool takesArg()
const {
return false; }
3901 virtual IArgFunction<C>* clone()
const {
return new BoundNullaryMethod( *
this ); }
3902 void (C::*member)();
3905 template<
typename C>
3906 struct BoundUnaryFunction : IArgFunction<C>{
3907 BoundUnaryFunction(
void (*_function)( C& ) ) : function( _function ) {}
3908 virtual void set( C& obj, std::string
const& stringValue )
const {
3910 convertInto( stringValue, value );
3914 virtual void setFlag( C& p )
const {
3917 virtual bool takesArg()
const {
return false; }
3918 virtual IArgFunction<C>* clone()
const {
return new BoundUnaryFunction( *
this ); }
3919 void (*
function)( C& );
3922 template<
typename C,
typename T>
3923 struct BoundBinaryFunction : IArgFunction<C>{
3924 BoundBinaryFunction(
void (*_function)( C&, T ) ) : function( _function ) {}
3925 virtual void set( C& obj, std::string
const& stringValue )
const {
3926 typename RemoveConstRef<T>::type value;
3927 convertInto( stringValue, value );
3928 function( obj, value );
3930 virtual void setFlag( C& obj )
const {
3931 typename RemoveConstRef<T>::type value;
3932 convertInto(
true, value );
3933 function( obj, value );
3935 virtual bool takesArg()
const {
return !IsBool<T>::value; }
3936 virtual IArgFunction<C>* clone()
const {
return new BoundBinaryFunction( *
this ); }
3937 void (*
function)( C&, T );
3943 Parser() : separators(
" \t=:" ) {}
3946 enum Type { Positional, ShortOpt, LongOpt };
3947 Token( Type _type, std::string
const& _data ) : type( _type ), data( _data ) {}
3952 void parseIntoTokens(
int argc,
char const *
const * argv, std::vector<Parser::Token>& tokens )
const {
3953 const std::string doubleDash =
"--";
3954 for(
int i = 1; i < argc && argv[i] != doubleDash; ++i )
3955 parseIntoTokens( argv[i] , tokens);
3957 void parseIntoTokens( std::string arg, std::vector<Parser::Token>& tokens )
const {
3958 while( !arg.empty() ) {
3959 Parser::Token token( Parser::Token::Positional, arg );
3961 if( token.data[0] ==
'-' ) {
3962 if( token.data.size() > 1 && token.data[1] ==
'-' ) {
3963 token = Parser::Token( Parser::Token::LongOpt, token.data.substr( 2 ) );
3966 token = Parser::Token( Parser::Token::ShortOpt, token.data.substr( 1 ) );
3967 if( token.data.size() > 1 && separators.find( token.data[1] ) == std::string::npos ) {
3968 arg =
"-" + token.data.substr( 1 );
3969 token.data = token.data.substr( 0, 1 );
3973 if( token.type != Parser::Token::Positional ) {
3974 std::size_t pos = token.data.find_first_of( separators );
3975 if( pos != std::string::npos ) {
3976 arg = token.data.substr( pos+1 );
3977 token.data = token.data.substr( 0, pos );
3980 tokens.push_back( token );
3983 std::string separators;
3986 template<
typename ConfigT>
3987 struct CommonArgProperties {
3988 CommonArgProperties() {}
3989 CommonArgProperties( Detail::BoundArgFunction<ConfigT>
const& _boundField ) : boundField( _boundField ) {}
3991 Detail::BoundArgFunction<ConfigT> boundField;
3992 std::string description;
3994 std::string placeholder;
3996 bool takesArg()
const {
3997 return !placeholder.empty();
3999 void validate()
const {
4000 if( !boundField.isSet() )
4001 throw std::logic_error(
"option not bound" );
4004 struct OptionArgProperties {
4005 std::vector<std::string> shortNames;
4006 std::string longName;
4008 bool hasShortName( std::string
const& shortName )
const {
4009 return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end();
4011 bool hasLongName( std::string
const& _longName )
const {
4012 return _longName == longName;
4015 struct PositionalArgProperties {
4016 PositionalArgProperties() : position( -1 ) {}
4019 bool isFixedPositional()
const {
4020 return position != -1;
4024 template<
typename ConfigT>
4027 struct Arg : CommonArgProperties<ConfigT>, OptionArgProperties, PositionalArgProperties {
4029 Arg( Detail::BoundArgFunction<ConfigT>
const& _boundField ) : CommonArgProperties<ConfigT>( _boundField ) {}
4031 using CommonArgProperties<ConfigT>::placeholder;
4033 std::string dbgName()
const {
4034 if( !longName.empty() )
4035 return "--" + longName;
4036 if( !shortNames.empty() )
4037 return "-" + shortNames[0];
4038 return "positional args";
4040 std::string commands()
const {
4041 std::ostringstream oss;
4043 std::vector<std::string>::const_iterator it = shortNames.begin(), itEnd = shortNames.end();
4044 for(; it != itEnd; ++it ) {
4051 if( !longName.empty() ) {
4054 oss <<
"--" << longName;
4056 if( !placeholder.empty() )
4057 oss <<
" <" << placeholder <<
">";
4062 typedef CATCH_AUTO_PTR( Arg ) ArgAutoPtr;
4064 friend void addOptName( Arg& arg, std::string
const& optName )
4066 if( optName.empty() )
4068 if( Detail::startsWith( optName,
"--" ) ) {
4069 if( !arg.longName.empty() )
4070 throw std::logic_error(
"Only one long opt may be specified. '"
4072 +
"' already specified, now attempting to add '"
4074 arg.longName = optName.substr( 2 );
4076 else if( Detail::startsWith( optName,
"-" ) )
4077 arg.shortNames.push_back( optName.substr( 1 ) );
4079 throw std::logic_error(
"option must begin with - or --. Option was: '" + optName +
"'" );
4081 friend void setPositionalArg( Arg& arg,
int position )
4083 arg.position = position;
4088 ArgBuilder( Arg* arg ) : m_arg( arg ) {}
4091 template<
typename C,
typename M>
4092 void bind( M C::* field, std::string
const& placeholder ) {
4093 m_arg->boundField =
new Detail::BoundDataMember<C,M>( field );
4094 m_arg->placeholder = placeholder;
4097 template<
typename C>
4098 void bind(
bool C::* field ) {
4099 m_arg->boundField =
new Detail::BoundDataMember<C,bool>( field );
4103 template<
typename C,
typename M>
4104 void bind(
void (C::* unaryMethod)( M ), std::string
const& placeholder ) {
4105 m_arg->boundField =
new Detail::BoundUnaryMethod<C,M>( unaryMethod );
4106 m_arg->placeholder = placeholder;
4110 template<
typename C>
4111 void bind(
void (C::* unaryMethod)(
bool ) ) {
4112 m_arg->boundField =
new Detail::BoundUnaryMethod<C,bool>( unaryMethod );
4116 template<
typename C>
4117 void bind(
void (C::* nullaryMethod)() ) {
4118 m_arg->boundField =
new Detail::BoundNullaryMethod<C>( nullaryMethod );
4122 template<
typename C>
4123 void bind(
void (* unaryFunction)( C& ) ) {
4124 m_arg->boundField =
new Detail::BoundUnaryFunction<C>( unaryFunction );
4128 template<
typename C,
typename T>
4129 void bind(
void (* binaryFunction)( C&, T ), std::string
const& placeholder ) {
4130 m_arg->boundField =
new Detail::BoundBinaryFunction<C, T>( binaryFunction );
4131 m_arg->placeholder = placeholder;
4134 ArgBuilder& describe( std::string
const& description ) {
4135 m_arg->description = description;
4138 ArgBuilder& detail( std::string
const& _detail ) {
4139 m_arg->detail = _detail;
4147 class OptBuilder :
public ArgBuilder {
4149 OptBuilder( Arg* arg ) : ArgBuilder( arg ) {}
4150 OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {}
4152 OptBuilder& operator[]( std::string
const& optName ) {
4153 addOptName( *ArgBuilder::m_arg, optName );
4161 : m_boundProcessName( new Detail::NullBinder<ConfigT>() ),
4162 m_highestSpecifiedArgPosition( 0 ),
4163 m_throwOnUnrecognisedTokens( false )
4165 CommandLine( CommandLine
const& other )
4166 : m_boundProcessName( other.m_boundProcessName ),
4167 m_options ( other.m_options ),
4168 m_positionalArgs( other.m_positionalArgs ),
4169 m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ),
4170 m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens )
4172 if( other.m_floatingArg.get() )
4173 m_floatingArg.reset(
new Arg( *other.m_floatingArg ) );
4176 CommandLine& setThrowOnUnrecognisedTokens(
bool shouldThrow =
true ) {
4177 m_throwOnUnrecognisedTokens = shouldThrow;
4181 OptBuilder operator[]( std::string
const& optName ) {
4182 m_options.push_back( Arg() );
4183 addOptName( m_options.back(), optName );
4184 OptBuilder builder( &m_options.back() );
4188 ArgBuilder operator[](
int position ) {
4189 m_positionalArgs.insert( std::make_pair( position, Arg() ) );
4190 if( position > m_highestSpecifiedArgPosition )
4191 m_highestSpecifiedArgPosition = position;
4192 setPositionalArg( m_positionalArgs[position], position );
4193 ArgBuilder builder( &m_positionalArgs[position] );
4198 ArgBuilder operator[]( UnpositionalTag ) {
4199 if( m_floatingArg.get() )
4200 throw std::logic_error(
"Only one unpositional argument can be added" );
4201 m_floatingArg.reset(
new Arg() );
4202 ArgBuilder builder( m_floatingArg.get() );
4206 template<
typename C,
typename M>
4207 void bindProcessName( M C::* field ) {
4208 m_boundProcessName =
new Detail::BoundDataMember<C,M>( field );
4210 template<
typename C,
typename M>
4211 void bindProcessName(
void (C::*_unaryMethod)( M ) ) {
4212 m_boundProcessName =
new Detail::BoundUnaryMethod<C,M>( _unaryMethod );
4215 void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth )
const {
4216 typename std::vector<Arg>::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it;
4217 std::size_t maxWidth = 0;
4218 for( it = itBegin; it != itEnd; ++it )
4219 maxWidth = (std::max)( maxWidth, it->commands().size() );
4221 for( it = itBegin; it != itEnd; ++it ) {
4222 Detail::Text usageText( it->commands(), Detail::TextAttributes()
4223 .setWidth( maxWidth+indent )
4224 .setIndent( indent ) );
4225 Detail::Text desc( it->description, Detail::TextAttributes()
4226 .setWidth( width - maxWidth - 3 ) );
4228 for( std::size_t i = 0; i < (std::max)( usageText.size(), desc.size() ); ++i ) {
4229 std::string usageCol = i < usageText.size() ? usageText[i] :
"";
4232 if( i < desc.size() && !desc[i].empty() )
4233 os << std::string( indent + 2 + maxWidth - usageCol.size(),
' ' )
4239 std::string optUsage()
const {
4240 std::ostringstream oss;
4245 void argSynopsis( std::ostream& os )
const {
4246 for(
int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) {
4249 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( i );
4250 if( it != m_positionalArgs.end() )
4251 os <<
"<" << it->second.placeholder <<
">";
4252 else if( m_floatingArg.get() )
4253 os <<
"<" << m_floatingArg->placeholder <<
">";
4255 throw std::logic_error(
"non consecutive positional arguments with no floating args" );
4258 if( m_floatingArg.get() ) {
4259 if( m_highestSpecifiedArgPosition > 1 )
4261 os <<
"[<" << m_floatingArg->placeholder <<
"> ...]";
4264 std::string argSynopsis()
const {
4265 std::ostringstream oss;
4270 void usage( std::ostream& os, std::string
const& procName )
const {
4272 os <<
"usage:\n " << procName <<
" ";
4274 if( !m_options.empty() ) {
4275 os <<
" [options]\n\nwhere options are: \n";
4280 std::string usage( std::string
const& procName )
const {
4281 std::ostringstream oss;
4282 usage( oss, procName );
4286 ConfigT parse(
int argc,
char const *
const * argv )
const {
4288 parseInto( argc, argv, config );
4292 std::vector<Parser::Token> parseInto(
int argc,
char const *
const * argv, ConfigT& config )
const {
4293 std::string processName = argv[0];
4294 std::size_t lastSlash = processName.find_last_of(
"/\\" );
4295 if( lastSlash != std::string::npos )
4296 processName = processName.substr( lastSlash+1 );
4297 m_boundProcessName.set( config, processName );
4298 std::vector<Parser::Token> tokens;
4300 parser.parseIntoTokens( argc, argv, tokens );
4301 return populate( tokens, config );
4304 std::vector<Parser::Token> populate( std::vector<Parser::Token>
const& tokens, ConfigT& config )
const {
4306 std::vector<Parser::Token> unusedTokens = populateOptions( tokens, config );
4307 unusedTokens = populateFixedArgs( unusedTokens, config );
4308 unusedTokens = populateFloatingArgs( unusedTokens, config );
4309 return unusedTokens;
4312 std::vector<Parser::Token> populateOptions( std::vector<Parser::Token>
const& tokens, ConfigT& config )
const {
4313 std::vector<Parser::Token> unusedTokens;
4314 std::vector<std::string> errors;
4315 for( std::size_t i = 0; i < tokens.size(); ++i ) {
4316 Parser::Token
const& token = tokens[i];
4317 typename std::vector<Arg>::const_iterator it = m_options.begin(), itEnd = m_options.end();
4318 for(; it != itEnd; ++it ) {
4319 Arg const& arg = *it;
4322 if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) ||
4323 ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) {
4324 if( arg.takesArg() ) {
4325 if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional )
4326 errors.push_back(
"Expected argument to option: " + token.data );
4328 arg.boundField.set( config, tokens[++i].data );
4331 arg.boundField.setFlag( config );
4336 catch( std::exception& ex ) {
4337 errors.push_back( std::string( ex.what() ) +
"\n- while parsing: (" + arg.commands() +
")" );
4341 if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens )
4342 unusedTokens.push_back( token );
4343 else if( errors.empty() && m_throwOnUnrecognisedTokens )
4344 errors.push_back(
"unrecognised option: " + token.data );
4347 if( !errors.empty() ) {
4348 std::ostringstream oss;
4349 for( std::vector<std::string>::const_iterator it = errors.begin(), itEnd = errors.end();
4352 if( it != errors.begin() )
4356 throw std::runtime_error( oss.str() );
4358 return unusedTokens;
4360 std::vector<Parser::Token> populateFixedArgs( std::vector<Parser::Token>
const& tokens, ConfigT& config )
const {
4361 std::vector<Parser::Token> unusedTokens;
4363 for( std::size_t i = 0; i < tokens.size(); ++i ) {
4364 Parser::Token
const& token = tokens[i];
4365 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( position );
4366 if( it != m_positionalArgs.end() )
4367 it->second.boundField.set( config, token.data );
4369 unusedTokens.push_back( token );
4370 if( token.type == Parser::Token::Positional )
4373 return unusedTokens;
4375 std::vector<Parser::Token> populateFloatingArgs( std::vector<Parser::Token>
const& tokens, ConfigT& config )
const {
4376 if( !m_floatingArg.get() )
4378 std::vector<Parser::Token> unusedTokens;
4379 for( std::size_t i = 0; i < tokens.size(); ++i ) {
4380 Parser::Token
const& token = tokens[i];
4381 if( token.type == Parser::Token::Positional )
4382 m_floatingArg->boundField.set( config, token.data );
4384 unusedTokens.push_back( token );
4386 return unusedTokens;
4389 void validate()
const
4391 if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() )
4392 throw std::logic_error(
"No options or arguments specified" );
4394 for(
typename std::vector<Arg>::const_iterator it = m_options.begin(),
4395 itEnd = m_options.end();
4401 Detail::BoundArgFunction<ConfigT> m_boundProcessName;
4402 std::vector<Arg> m_options;
4403 std::map<int, Arg> m_positionalArgs;
4404 ArgAutoPtr m_floatingArg;
4405 int m_highestSpecifiedArgPosition;
4406 bool m_throwOnUnrecognisedTokens;
4411 STITCH_CLARA_CLOSE_NAMESPACE
4412 #undef STITCH_CLARA_OPEN_NAMESPACE
4413 #undef STITCH_CLARA_CLOSE_NAMESPACE
4416 #undef STITCH_CLARA_OPEN_NAMESPACE
4419 #ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
4420 #define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
4421 #undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
4428 inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; }
4429 inline void abortAfterX( ConfigData& config,
int x ) {
4431 throw std::runtime_error(
"Value after -x or --abortAfter must be greater than zero" );
4432 config.abortAfter = x;
4434 inline void addTestOrTags( ConfigData& config, std::string
const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); }
4435 inline void addReporterName( ConfigData& config, std::string
const& _reporterName ) { config.reporterNames.push_back( _reporterName ); }
4437 inline void addWarning( ConfigData& config, std::string
const& _warning ) {
4438 if( _warning ==
"NoAssertions" )
4439 config.warnings =
static_cast<WarnAbout::What
>( config.warnings | WarnAbout::NoAssertions );
4441 throw std::runtime_error(
"Unrecognised warning: '" + _warning +
"'" );
4443 inline void setOrder( ConfigData& config, std::string
const& order ) {
4444 if( startsWith(
"declared", order ) )
4445 config.runOrder = RunTests::InDeclarationOrder;
4446 else if( startsWith(
"lexical", order ) )
4447 config.runOrder = RunTests::InLexicographicalOrder;
4448 else if( startsWith(
"random", order ) )
4449 config.runOrder = RunTests::InRandomOrder;
4451 throw std::runtime_error(
"Unrecognised ordering: '" + order +
"'" );
4453 inline void setRngSeed( ConfigData& config, std::string
const& seed ) {
4454 if( seed ==
"time" ) {
4455 config.rngSeed =
static_cast<unsigned int>( std::time(0) );
4458 std::stringstream ss;
4460 ss >> config.rngSeed;
4462 throw std::runtime_error(
"Argment to --rng-seed should be the word 'time' or a number" );
4465 inline void setVerbosity( ConfigData& config,
int level ) {
4467 config.verbosity =
static_cast<Verbosity::Level
>( level );
4469 inline void setShowDurations( ConfigData& config,
bool _showDurations ) {
4470 config.showDurations = _showDurations
4471 ? ShowDurations::Always
4472 : ShowDurations::Never;
4474 inline void loadTestNamesFromFile( ConfigData& config, std::string
const& _filename ) {
4475 std::ifstream f( _filename.c_str() );
4477 throw std::domain_error(
"Unable to load input file: " + _filename );
4480 while( std::getline( f, line ) ) {
4482 if( !line.empty() && !startsWith( line,
"#" ) )
4483 addTestOrTags( config,
"\"" + line +
"\"," );
4487 inline Clara::CommandLine<ConfigData> makeCommandLineParser() {
4489 using namespace Clara;
4490 CommandLine<ConfigData> cli;
4492 cli.bindProcessName( &ConfigData::processName );
4494 cli["-?"]["-h"]["--help"]
4495 .describe(
"display usage information" )
4496 .bind( &ConfigData::showHelp );
4498 cli["-l"]["--list-tests"]
4499 .describe(
"list all/matching test cases" )
4500 .bind( &ConfigData::listTests );
4502 cli["-t"]["--list-tags"]
4503 .describe(
"list all/matching tags" )
4504 .bind( &ConfigData::listTags );
4506 cli["-s"]["--success"]
4507 .describe(
"include successful tests in output" )
4508 .bind( &ConfigData::showSuccessfulTests );
4510 cli["-b"]["--break"]
4511 .describe(
"break into debugger on failure" )
4512 .bind( &ConfigData::shouldDebugBreak );
4514 cli["-e"]["--nothrow"]
4515 .describe(
"skip exception tests" )
4516 .bind( &ConfigData::noThrow );
4518 cli["-i"]["--invisibles"]
4519 .describe(
"show invisibles (tabs, newlines)" )
4520 .bind( &ConfigData::showInvisibles );
4523 .describe(
"output filename" )
4524 .bind( &ConfigData::outputFilename,
"filename" );
4526 cli["-r"]["--reporter"]
4528 .describe(
"reporter to use (defaults to console)" )
4529 .bind( &addReporterName,
"name" );
4532 .describe(
"suite name" )
4533 .bind( &ConfigData::name,
"name" );
4535 cli["-a"]["--abort"]
4536 .describe(
"abort at first failure" )
4537 .bind( &abortAfterFirst );
4539 cli["-x"]["--abortx"]
4540 .describe(
"abort after x failures" )
4541 .bind( &abortAfterX,
"no. failures" );
4544 .describe(
"enable warnings" )
4545 .bind( &addWarning,
"warning name" );
4555 .describe(
"which test or tests to use" )
4556 .bind( &addTestOrTags,
"test name, pattern or tags" );
4558 cli["-d"]["--durations"]
4559 .describe(
"show test durations" )
4560 .bind( &setShowDurations,
"yes/no" );
4562 cli["-f"]["--input-file"]
4563 .describe(
"load test names to run from a file" )
4564 .bind( &loadTestNamesFromFile,
"filename" );
4566 cli["-#"]["--filenames-as-tags"]
4567 .describe(
"adds a tag for the filename" )
4568 .bind( &ConfigData::filenamesAsTags );
4571 cli["--list-test-names-only"]
4572 .describe(
"list all/matching test cases names only" )
4573 .bind( &ConfigData::listTestNamesOnly );
4575 cli["--list-reporters"]
4576 .describe(
"list all reporters" )
4577 .bind( &ConfigData::listReporters );
4580 .describe(
"test case order (defaults to decl)" )
4581 .bind( &setOrder,
"decl|lex|rand" );
4584 .describe(
"set a specific seed for random numbers" )
4585 .bind( &setRngSeed,
"'time'|number" );
4587 cli["--force-colour"]
4588 .describe(
"force colourised output" )
4589 .bind( &ConfigData::forceColour );
4597 #define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
4600 #define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED
4602 #define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
4604 #define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch
4607 #ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4608 # ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
4609 # ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
4610 # define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
4613 # define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
4616 #ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
4622 #ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4623 namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
4628 #ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
4629 const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
4631 const unsigned int consoleWidth = 80;
4634 struct TextAttributes {
4636 : initialIndent( std::string::npos ),
4638 width( consoleWidth-1 ),
4642 TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value;
return *
this; }
4643 TextAttributes& setIndent( std::size_t _value ) { indent = _value;
return *
this; }
4644 TextAttributes& setWidth( std::size_t _value ) { width = _value;
return *
this; }
4645 TextAttributes& setTabChar(
char _value ) { tabChar = _value;
return *
this; }
4647 std::size_t initialIndent;
4655 Text( std::string
const& _str, TextAttributes
const& _attr = TextAttributes() )
4658 std::string wrappableChars =
" [({.,/|\\-";
4659 std::size_t indent = _attr.initialIndent != std::string::npos
4660 ? _attr.initialIndent
4662 std::string remainder = _str;
4664 while( !remainder.empty() ) {
4665 if( lines.size() >= 1000 ) {
4666 lines.push_back(
"... message truncated due to excessive size" );
4669 std::size_t tabPos = std::string::npos;
4670 std::size_t width = (std::min)( remainder.size(), _attr.width - indent );
4671 std::size_t pos = remainder.find_first_of(
'\n' );
4672 if( pos <= width ) {
4675 pos = remainder.find_last_of( _attr.tabChar, width );
4676 if( pos != std::string::npos ) {
4678 if( remainder[width] ==
'\n' )
4680 remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 );
4683 if( width == remainder.size() ) {
4684 spliceLine( indent, remainder, width );
4686 else if( remainder[width] ==
'\n' ) {
4687 spliceLine( indent, remainder, width );
4688 if( width <= 1 || remainder.size() != 1 )
4689 remainder = remainder.substr( 1 );
4690 indent = _attr.indent;
4693 pos = remainder.find_last_of( wrappableChars, width );
4694 if( pos != std::string::npos && pos > 0 ) {
4695 spliceLine( indent, remainder, pos );
4696 if( remainder[0] ==
' ' )
4697 remainder = remainder.substr( 1 );
4700 spliceLine( indent, remainder, width-1 );
4701 lines.back() += "-";
4703 if( lines.size() == 1 )
4704 indent = _attr.indent;
4705 if( tabPos != std::string::npos )
4711 void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) {
4712 lines.push_back( std::string( _indent,
' ' ) + _remainder.substr( 0, _pos ) );
4713 _remainder = _remainder.substr( _pos );
4716 typedef std::vector<std::string>::const_iterator const_iterator;
4718 const_iterator begin()
const {
return lines.begin(); }
4719 const_iterator end()
const {
return lines.end(); }
4720 std::string
const& last()
const {
return lines.back(); }
4721 std::size_t size()
const {
return lines.size(); }
4722 std::string
const& operator[]( std::size_t _index )
const {
return lines[_index]; }
4723 std::string toString()
const {
4724 std::ostringstream oss;
4729 inline friend std::ostream& operator << ( std::ostream& _stream, Text
const& _text ) {
4730 for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
4731 it != itEnd; ++it ) {
4732 if( it != _text.begin() )
4741 TextAttributes attr;
4742 std::vector<std::string> lines;
4747 #ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4752 #undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4756 using Tbc::TextAttributes;
4760 #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED
4778 BrightRed = Bright | Red,
4779 BrightGreen = Bright | Green,
4780 LightGrey = Bright | Grey,
4781 BrightWhite = Bright | White,
4784 FileName = LightGrey,
4786 ResultError = BrightRed,
4787 ResultSuccess = BrightGreen,
4788 ResultExpectedFailure = Warning,
4793 OriginalExpression = Cyan,
4794 ReconstructedExpression = Yellow,
4796 SecondaryText = LightGrey,
4801 Colour( Code _colourCode );
4802 Colour( Colour
const& other );
4806 static void use( Code _colourCode );
4812 inline std::ostream& operator << ( std::ostream& os, Colour
const& ) {
return os; }
4817 #define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
4826 struct ReporterConfig {
4827 explicit ReporterConfig( Ptr<IConfig const>
const& _fullConfig )
4828 : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
4830 ReporterConfig( Ptr<IConfig const>
const& _fullConfig, std::ostream& _stream )
4831 : m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
4833 std::ostream& stream()
const {
return *m_stream; }
4834 Ptr<IConfig const> fullConfig()
const {
return m_fullConfig; }
4837 std::ostream* m_stream;
4838 Ptr<IConfig const> m_fullConfig;
4841 struct ReporterPreferences {
4842 ReporterPreferences()
4843 : shouldRedirectStdOut( false )
4846 bool shouldRedirectStdOut;
4849 template<
typename T>
4850 struct LazyStat : Option<T> {
4851 LazyStat() : used( false ) {}
4852 LazyStat& operator=( T
const& _value ) {
4853 Option<T>::operator=( _value );
4864 struct TestRunInfo {
4865 TestRunInfo( std::string
const& _name ) : name( _name ) {}
4869 GroupInfo( std::string
const& _name,
4870 std::size_t _groupIndex,
4871 std::size_t _groupsCount )
4873 groupIndex( _groupIndex ),
4874 groupsCounts( _groupsCount )
4878 std::size_t groupIndex;
4879 std::size_t groupsCounts;
4882 struct AssertionStats {
4883 AssertionStats( AssertionResult
const& _assertionResult,
4884 std::vector<MessageInfo>
const& _infoMessages,
4885 Totals
const& _totals )
4886 : assertionResult( _assertionResult ),
4887 infoMessages( _infoMessages ),
4890 if( assertionResult.hasMessage() ) {
4893 MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
4894 builder << assertionResult.getMessage();
4895 builder.m_info.message = builder.m_stream.str();
4897 infoMessages.push_back( builder.m_info );
4900 virtual ~AssertionStats();
4902 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
4903 AssertionStats( AssertionStats
const& ) =
default;
4904 AssertionStats( AssertionStats && ) =
default;
4905 AssertionStats& operator = ( AssertionStats
const& ) =
default;
4906 AssertionStats& operator = ( AssertionStats && ) =
default;
4909 AssertionResult assertionResult;
4910 std::vector<MessageInfo> infoMessages;
4914 struct SectionStats {
4915 SectionStats( SectionInfo
const& _sectionInfo,
4916 Counts
const& _assertions,
4917 double _durationInSeconds,
4918 bool _missingAssertions )
4919 : sectionInfo( _sectionInfo ),
4920 assertions( _assertions ),
4921 durationInSeconds( _durationInSeconds ),
4922 missingAssertions( _missingAssertions )
4924 virtual ~SectionStats();
4925 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
4926 SectionStats( SectionStats
const& ) =
default;
4927 SectionStats( SectionStats && ) =
default;
4928 SectionStats& operator = ( SectionStats
const& ) =
default;
4929 SectionStats& operator = ( SectionStats && ) =
default;
4932 SectionInfo sectionInfo;
4934 double durationInSeconds;
4935 bool missingAssertions;
4938 struct TestCaseStats {
4939 TestCaseStats( TestCaseInfo
const& _testInfo,
4940 Totals
const& _totals,
4941 std::string
const& _stdOut,
4942 std::string
const& _stdErr,
4944 : testInfo( _testInfo ),
4948 aborting( _aborting )
4950 virtual ~TestCaseStats();
4952 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
4953 TestCaseStats( TestCaseStats
const& ) =
default;
4954 TestCaseStats( TestCaseStats && ) =
default;
4955 TestCaseStats& operator = ( TestCaseStats
const& ) =
default;
4956 TestCaseStats& operator = ( TestCaseStats && ) =
default;
4959 TestCaseInfo testInfo;
4966 struct TestGroupStats {
4967 TestGroupStats( GroupInfo
const& _groupInfo,
4968 Totals
const& _totals,
4970 : groupInfo( _groupInfo ),
4972 aborting( _aborting )
4974 TestGroupStats( GroupInfo
const& _groupInfo )
4975 : groupInfo( _groupInfo ),
4978 virtual ~TestGroupStats();
4980 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
4981 TestGroupStats( TestGroupStats
const& ) =
default;
4982 TestGroupStats( TestGroupStats && ) =
default;
4983 TestGroupStats& operator = ( TestGroupStats
const& ) =
default;
4984 TestGroupStats& operator = ( TestGroupStats && ) =
default;
4987 GroupInfo groupInfo;
4992 struct TestRunStats {
4993 TestRunStats( TestRunInfo
const& _runInfo,
4994 Totals
const& _totals,
4996 : runInfo( _runInfo ),
4998 aborting( _aborting )
5000 virtual ~TestRunStats();
5002 # ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS
5003 TestRunStats( TestRunStats
const& _other )
5004 : runInfo( _other.runInfo ),
5005 totals( _other.totals ),
5006 aborting( _other.aborting )
5009 TestRunStats( TestRunStats
const& ) =
default;
5010 TestRunStats( TestRunStats && ) =
default;
5011 TestRunStats& operator = ( TestRunStats
const& ) =
default;
5012 TestRunStats& operator = ( TestRunStats && ) =
default;
5015 TestRunInfo runInfo;
5020 struct IStreamingReporter : IShared {
5021 virtual ~IStreamingReporter();
5026 virtual ReporterPreferences getPreferences()
const = 0;
5028 virtual void noMatchingTestCases( std::string
const& spec ) = 0;
5030 virtual void testRunStarting( TestRunInfo
const& testRunInfo ) = 0;
5031 virtual void testGroupStarting( GroupInfo
const& groupInfo ) = 0;
5033 virtual void testCaseStarting( TestCaseInfo
const& testInfo ) = 0;
5034 virtual void sectionStarting( SectionInfo
const& sectionInfo ) = 0;
5036 virtual void assertionStarting( AssertionInfo
const& assertionInfo ) = 0;
5039 virtual bool assertionEnded( AssertionStats
const& assertionStats ) = 0;
5041 virtual void sectionEnded( SectionStats
const& sectionStats ) = 0;
5042 virtual void testCaseEnded( TestCaseStats
const& testCaseStats ) = 0;
5043 virtual void testGroupEnded( TestGroupStats
const& testGroupStats ) = 0;
5044 virtual void testRunEnded( TestRunStats
const& testRunStats ) = 0;
5046 virtual void skipTest( TestCaseInfo
const& testInfo ) = 0;
5049 struct IReporterFactory : IShared {
5050 virtual ~IReporterFactory();
5051 virtual IStreamingReporter* create( ReporterConfig
const& config )
const = 0;
5052 virtual std::string getDescription()
const = 0;
5055 struct IReporterRegistry {
5056 typedef std::map<std::string, Ptr<IReporterFactory> > FactoryMap;
5057 typedef std::vector<Ptr<IReporterFactory> > Listeners;
5059 virtual ~IReporterRegistry();
5060 virtual IStreamingReporter* create( std::string
const& name, Ptr<IConfig const>
const& config )
const = 0;
5061 virtual FactoryMap
const& getFactories()
const = 0;
5062 virtual Listeners
const& getListeners()
const = 0;
5065 Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter>
const& existingReporter, Ptr<IStreamingReporter>
const& additionalReporter );
5070 #include <algorithm>
5074 inline std::size_t listTests( Config
const& config ) {
5076 TestSpec testSpec = config.testSpec();
5077 if( config.testSpec().hasFilters() )
5078 Catch::cout() <<
"Matching test cases:\n";
5080 Catch::cout() <<
"All available test cases:\n";
5081 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse(
"*" ).testSpec();
5084 std::size_t matchedTests = 0;
5085 TextAttributes nameAttr, tagsAttr;
5086 nameAttr.setInitialIndent( 2 ).setIndent( 4 );
5087 tagsAttr.setIndent( 6 );
5089 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
5090 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
5094 TestCaseInfo
const& testCaseInfo = it->getTestCaseInfo();
5095 Colour::Code colour = testCaseInfo.isHidden()
5096 ? Colour::SecondaryText
5098 Colour colourGuard( colour );
5100 Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl;
5101 if( !testCaseInfo.tags.empty() )
5102 Catch::cout() << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl;
5105 if( !config.testSpec().hasFilters() )
5106 Catch::cout() << pluralise( matchedTests,
"test case" ) <<
"\n" << std::endl;
5108 Catch::cout() << pluralise( matchedTests,
"matching test case" ) <<
"\n" << std::endl;
5109 return matchedTests;
5112 inline std::size_t listTestsNamesOnly( Config
const& config ) {
5113 TestSpec testSpec = config.testSpec();
5114 if( !config.testSpec().hasFilters() )
5115 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse(
"*" ).testSpec();
5116 std::size_t matchedTests = 0;
5117 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
5118 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
5122 TestCaseInfo
const& testCaseInfo = it->getTestCaseInfo();
5123 Catch::cout() << testCaseInfo.name << std::endl;
5125 return matchedTests;
5129 TagInfo() : count ( 0 ) {}
5130 void add( std::string
const& spelling ) {
5132 spellings.insert( spelling );
5134 std::string all()
const {
5136 for( std::set<std::string>::const_iterator it = spellings.begin(), itEnd = spellings.end();
5139 out += "[" + *it + "]";
5142 std::set<std::string> spellings;
5146 inline std::size_t listTags( Config
const& config ) {
5147 TestSpec testSpec = config.testSpec();
5148 if( config.testSpec().hasFilters() )
5149 Catch::cout() <<
"Tags for matching test cases:\n";
5151 Catch::cout() <<
"All available tags:\n";
5152 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse(
"*" ).testSpec();
5155 std::map<std::string, TagInfo> tagCounts;
5157 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
5158 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
5161 for( std::set<std::string>::const_iterator tagIt = it->getTestCaseInfo().tags.begin(),
5162 tagItEnd = it->getTestCaseInfo().tags.end();
5165 std::string tagName = *tagIt;
5166 std::string lcaseTagName = toLower( tagName );
5167 std::map<std::string, TagInfo>::iterator countIt = tagCounts.find( lcaseTagName );
5168 if( countIt == tagCounts.end() )
5169 countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first;
5170 countIt->second.add( tagName );
5174 for( std::map<std::string, TagInfo>::const_iterator countIt = tagCounts.begin(),
5175 countItEnd = tagCounts.end();
5176 countIt != countItEnd;
5178 std::ostringstream oss;
5179 oss <<
" " << std::setw(2) << countIt->second.count <<
" ";
5180 Text wrapper( countIt->second.all(), TextAttributes()
5181 .setInitialIndent( 0 )
5182 .setIndent( oss.str().size() )
5183 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) );
5184 Catch::cout() << oss.str() << wrapper <<
"\n";
5186 Catch::cout() << pluralise( tagCounts.size(),
"tag" ) <<
"\n" << std::endl;
5187 return tagCounts.size();
5190 inline std::size_t listReporters( Config
const& ) {
5191 Catch::cout() <<
"Available reporters:\n";
5192 IReporterRegistry::FactoryMap
const& factories = getRegistryHub().getReporterRegistry().getFactories();
5193 IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it;
5194 std::size_t maxNameLen = 0;
5195 for(it = itBegin; it != itEnd; ++it )
5196 maxNameLen = (std::max)( maxNameLen, it->first.size() );
5198 for(it = itBegin; it != itEnd; ++it ) {
5199 Text wrapper( it->second->getDescription(), TextAttributes()
5200 .setInitialIndent( 0 )
5201 .setIndent( 7+maxNameLen )
5202 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) );
5203 Catch::cout() <<
" "
5206 << std::string( maxNameLen - it->first.size() + 2,
' ' )
5209 Catch::cout() << std::endl;
5210 return factories.size();
5213 inline Option<std::size_t> list( Config
const& config ) {
5214 Option<std::size_t> listedCount;
5215 if( config.listTests() )
5216 listedCount = listedCount.valueOr(0) + listTests( config );
5217 if( config.listTestNamesOnly() )
5218 listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config );
5219 if( config.listTags() )
5220 listedCount = listedCount.valueOr(0) + listTags( config );
5221 if( config.listReporters() )
5222 listedCount = listedCount.valueOr(0) + listReporters( config );
5229 #define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
5232 #define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
5240 namespace TestCaseTracking {
5242 struct ITracker : SharedImpl<> {
5243 virtual ~ITracker();
5246 virtual std::string name()
const = 0;
5249 virtual bool isComplete()
const = 0;
5250 virtual bool isSuccessfullyCompleted()
const = 0;
5251 virtual bool isOpen()
const = 0;
5252 virtual bool hasChildren()
const = 0;
5254 virtual ITracker& parent() = 0;
5257 virtual void close() = 0;
5258 virtual void fail() = 0;
5259 virtual void markAsNeedingAnotherRun() = 0;
5261 virtual void addChild( Ptr<ITracker>
const& child ) = 0;
5262 virtual ITracker* findChild( std::string
const& name ) = 0;
5263 virtual void openChild() = 0;
5266 class TrackerContext {
5274 Ptr<ITracker> m_rootTracker;
5275 ITracker* m_currentTracker;
5276 RunState m_runState;
5280 static TrackerContext& instance() {
5281 static TrackerContext s_instance;
5286 : m_currentTracker( CATCH_NULL ),
5287 m_runState( NotStarted )
5290 ITracker& startRun();
5293 m_rootTracker.reset();
5294 m_currentTracker = CATCH_NULL;
5295 m_runState = NotStarted;
5299 m_currentTracker = m_rootTracker.get();
5300 m_runState = Executing;
5302 void completeCycle() {
5303 m_runState = CompletedCycle;
5306 bool completedCycle()
const {
5307 return m_runState == CompletedCycle;
5309 ITracker& currentTracker() {
5310 return *m_currentTracker;
5312 void setCurrentTracker( ITracker* tracker ) {
5313 m_currentTracker = tracker;
5317 class TrackerBase :
public ITracker {
5324 CompletedSuccessfully,
5327 class TrackerHasName {
5330 TrackerHasName( std::string
const& name ) : m_name( name ) {}
5331 bool operator ()( Ptr<ITracker>
const& tracker ) {
5332 return tracker->name() == m_name;
5335 typedef std::vector<Ptr<ITracker> > Children;
5337 TrackerContext& m_ctx;
5339 Children m_children;
5340 CycleState m_runState;
5342 TrackerBase( std::string
const& name, TrackerContext& ctx, ITracker* parent )
5346 m_runState( NotStarted )
5348 virtual ~TrackerBase();
5350 virtual std::string name() const CATCH_OVERRIDE {
5353 virtual bool isComplete() const CATCH_OVERRIDE {
5354 return m_runState == CompletedSuccessfully || m_runState == Failed;
5356 virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE {
5357 return m_runState == CompletedSuccessfully;
5359 virtual bool isOpen() const CATCH_OVERRIDE {
5360 return m_runState != NotStarted && !isComplete();
5362 virtual bool hasChildren() const CATCH_OVERRIDE {
5363 return !m_children.empty();
5366 virtual void addChild( Ptr<ITracker>
const& child ) CATCH_OVERRIDE {
5367 m_children.push_back( child );
5370 virtual ITracker* findChild( std::string
const& name ) CATCH_OVERRIDE {
5371 Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( name ) );
5372 return( it != m_children.end() )
5376 virtual ITracker& parent() CATCH_OVERRIDE {
5381 virtual void openChild() CATCH_OVERRIDE {
5382 if( m_runState != ExecutingChildren ) {
5383 m_runState = ExecutingChildren;
5385 m_parent->openChild();
5389 m_runState = Executing;
5392 m_parent->openChild();
5395 virtual void close() CATCH_OVERRIDE {
5398 while( &m_ctx.currentTracker() !=
this )
5399 m_ctx.currentTracker().close();
5401 switch( m_runState ) {
5403 case CompletedSuccessfully:
5405 throw std::logic_error(
"Illogical state" );
5407 case NeedsAnotherRun:
5411 m_runState = CompletedSuccessfully;
5413 case ExecutingChildren:
5414 if( m_children.empty() || m_children.back()->isComplete() )
5415 m_runState = CompletedSuccessfully;
5419 throw std::logic_error(
"Unexpected state" );
5422 m_ctx.completeCycle();
5424 virtual void fail() CATCH_OVERRIDE {
5425 m_runState = Failed;
5427 m_parent->markAsNeedingAnotherRun();
5429 m_ctx.completeCycle();
5431 virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE {
5432 m_runState = NeedsAnotherRun;
5435 void moveToParent() {
5437 m_ctx.setCurrentTracker( m_parent );
5440 m_ctx.setCurrentTracker(
this );
5444 class SectionTracker :
public TrackerBase {
5446 SectionTracker( std::string
const& name, TrackerContext& ctx, ITracker* parent )
5447 : TrackerBase( name, ctx, parent )
5449 virtual ~SectionTracker();
5451 static SectionTracker& acquire( TrackerContext& ctx, std::string
const& name ) {
5452 SectionTracker* section = CATCH_NULL;
5454 ITracker& currentTracker = ctx.currentTracker();
5455 if( ITracker* childTracker = currentTracker.findChild( name ) ) {
5456 section =
dynamic_cast<SectionTracker*
>( childTracker );
5460 section =
new SectionTracker( name, ctx, ¤tTracker );
5461 currentTracker.addChild( section );
5463 if( !ctx.completedCycle() && !section->isComplete() ) {
5471 class IndexTracker :
public TrackerBase {
5475 IndexTracker( std::string
const& name, TrackerContext& ctx, ITracker* parent,
int size )
5476 : TrackerBase( name, ctx, parent ),
5480 virtual ~IndexTracker();
5482 static IndexTracker& acquire( TrackerContext& ctx, std::string
const& name,
int size ) {
5483 IndexTracker* tracker = CATCH_NULL;
5485 ITracker& currentTracker = ctx.currentTracker();
5486 if( ITracker* childTracker = currentTracker.findChild( name ) ) {
5487 tracker =
dynamic_cast<IndexTracker*
>( childTracker );
5491 tracker =
new IndexTracker( name, ctx, ¤tTracker, size );
5492 currentTracker.addChild( tracker );
5495 if( !ctx.completedCycle() && !tracker->isComplete() ) {
5496 if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun )
5497 tracker->moveNext();
5504 int index()
const {
return m_index; }
5511 virtual void close() CATCH_OVERRIDE {
5512 TrackerBase::close();
5513 if( m_runState == CompletedSuccessfully && m_index < m_size-1 )
5514 m_runState = Executing;
5518 inline ITracker& TrackerContext::startRun() {
5519 m_rootTracker =
new SectionTracker(
"{root}", *
this, CATCH_NULL );
5520 m_currentTracker = CATCH_NULL;
5521 m_runState = Executing;
5522 return *m_rootTracker;
5527 using TestCaseTracking::ITracker;
5528 using TestCaseTracking::TrackerContext;
5529 using TestCaseTracking::SectionTracker;
5530 using TestCaseTracking::IndexTracker;
5535 #define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
5540 inline void fatal( std::string
const& message,
int exitCode ) {
5541 IContext& context = Catch::getCurrentContext();
5542 IResultCapture* resultCapture = context.getResultCapture();
5543 resultCapture->handleFatalErrorCondition( message );
5545 if( Catch::alwaysTrue() )
5551 #if defined ( CATCH_PLATFORM_WINDOWS )
5555 struct FatalConditionHandler {
5567 struct SignalDefs {
int id;
const char* name; };
5568 extern SignalDefs signalDefs[];
5569 SignalDefs signalDefs[] = {
5570 { SIGINT,
"SIGINT - Terminal interrupt signal" },
5571 { SIGILL,
"SIGILL - Illegal instruction signal" },
5572 { SIGFPE,
"SIGFPE - Floating point error signal" },
5573 { SIGSEGV,
"SIGSEGV - Segmentation violation signal" },
5574 { SIGTERM,
"SIGTERM - Termination request signal" },
5575 { SIGABRT,
"SIGABRT - Abort (abnormal termination) signal" }
5578 struct FatalConditionHandler {
5580 static void handleSignal(
int sig ) {
5581 for( std::size_t i = 0; i <
sizeof(signalDefs)/
sizeof(SignalDefs); ++i )
5582 if( sig == signalDefs[i].
id )
5583 fatal( signalDefs[i].name, -sig );
5584 fatal(
"<unknown signal>", -sig );
5587 FatalConditionHandler() : m_isSet( true ) {
5588 for( std::size_t i = 0; i <
sizeof(signalDefs)/
sizeof(SignalDefs); ++i )
5589 signal( signalDefs[i].id, handleSignal );
5591 ~FatalConditionHandler() {
5596 for( std::size_t i = 0; i <
sizeof(signalDefs)/
sizeof(SignalDefs); ++i )
5597 signal( signalDefs[i].id, SIG_DFL );
5614 class StreamRedirect {
5617 StreamRedirect( std::ostream& stream, std::string& targetString )
5618 : m_stream( stream ),
5619 m_prevBuf( stream.rdbuf() ),
5620 m_targetString( targetString )
5622 stream.rdbuf( m_oss.rdbuf() );
5626 m_targetString += m_oss.str();
5627 m_stream.rdbuf( m_prevBuf );
5631 std::ostream& m_stream;
5632 std::streambuf* m_prevBuf;
5633 std::ostringstream m_oss;
5634 std::string& m_targetString;
5639 class RunContext :
public IResultCapture,
public IRunner {
5641 RunContext( RunContext
const& );
5642 void operator =( RunContext
const& );
5646 explicit RunContext( Ptr<IConfig const>
const& _config, Ptr<IStreamingReporter>
const& reporter )
5647 : m_runInfo( _config->name() ),
5648 m_context( getCurrentMutableContext() ),
5649 m_activeTestCase( CATCH_NULL ),
5650 m_config( _config ),
5651 m_reporter( reporter )
5653 m_context.setRunner(
this );
5654 m_context.setConfig( m_config );
5655 m_context.setResultCapture(
this );
5656 m_reporter->testRunStarting( m_runInfo );
5659 virtual ~RunContext() {
5660 m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) );
5663 void testGroupStarting( std::string
const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) {
5664 m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) );
5666 void testGroupEnded( std::string
const& testSpec, Totals
const& totals, std::size_t groupIndex, std::size_t groupsCount ) {
5667 m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) );
5670 Totals runTest( TestCase
const& testCase ) {
5671 Totals prevTotals = m_totals;
5673 std::string redirectedCout;
5674 std::string redirectedCerr;
5676 TestCaseInfo testInfo = testCase.getTestCaseInfo();
5678 m_reporter->testCaseStarting( testInfo );
5680 m_activeTestCase = &testCase;
5683 m_trackerContext.startRun();
5685 m_trackerContext.startCycle();
5686 m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, testInfo.name );
5687 runCurrentTest( redirectedCout, redirectedCerr );
5689 while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() );
5692 while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() );
5694 Totals deltaTotals = m_totals.delta( prevTotals );
5695 m_totals.testCases += deltaTotals.testCases;
5696 m_reporter->testCaseEnded( TestCaseStats( testInfo,
5702 m_activeTestCase = CATCH_NULL;
5703 m_testCaseTracker = CATCH_NULL;
5708 Ptr<IConfig const> config()
const {
5714 virtual void assertionEnded( AssertionResult
const& result ) {
5715 if( result.getResultType() == ResultWas::Ok ) {
5716 m_totals.assertions.passed++;
5718 else if( !result.isOk() ) {
5719 m_totals.assertions.failed++;
5722 if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) )
5726 m_lastAssertionInfo = AssertionInfo(
"", m_lastAssertionInfo.lineInfo,
"{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition );
5727 m_lastResult = result;
5730 virtual bool sectionStarted (
5731 SectionInfo
const& sectionInfo,
5735 std::ostringstream oss;
5736 oss << sectionInfo.name <<
"@" << sectionInfo.lineInfo;
5738 ITracker& sectionTracker = SectionTracker::acquire( m_trackerContext, oss.str() );
5739 if( !sectionTracker.isOpen() )
5741 m_activeSections.push_back( §ionTracker );
5743 m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
5745 m_reporter->sectionStarting( sectionInfo );
5747 assertions = m_totals.assertions;
5751 bool testForMissingAssertions( Counts& assertions ) {
5752 if( assertions.total() != 0 )
5754 if( !m_config->warnAboutMissingAssertions() )
5756 if( m_trackerContext.currentTracker().hasChildren() )
5758 m_totals.assertions.failed++;
5759 assertions.failed++;
5763 virtual void sectionEnded( SectionEndInfo
const& endInfo ) {
5764 Counts assertions = m_totals.assertions - endInfo.prevAssertions;
5765 bool missingAssertions = testForMissingAssertions( assertions );
5767 if( !m_activeSections.empty() ) {
5768 m_activeSections.back()->close();
5769 m_activeSections.pop_back();
5772 m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) );
5776 virtual void sectionEndedEarly( SectionEndInfo
const& endInfo ) {
5777 if( m_unfinishedSections.empty() )
5778 m_activeSections.back()->fail();
5780 m_activeSections.back()->close();
5781 m_activeSections.pop_back();
5783 m_unfinishedSections.push_back( endInfo );
5786 virtual void pushScopedMessage( MessageInfo
const& message ) {
5787 m_messages.push_back( message );
5790 virtual void popScopedMessage( MessageInfo
const& message ) {
5791 m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() );
5794 virtual std::string getCurrentTestName()
const {
5795 return m_activeTestCase
5796 ? m_activeTestCase->getTestCaseInfo().name
5800 virtual const AssertionResult* getLastResult()
const {
5801 return &m_lastResult;
5804 virtual void handleFatalErrorCondition( std::string
const& message ) {
5805 ResultBuilder resultBuilder = makeUnexpectedResultBuilder();
5806 resultBuilder.setResultType( ResultWas::FatalErrorCondition );
5807 resultBuilder << message;
5808 resultBuilder.captureExpression();
5810 handleUnfinishedSections();
5813 TestCaseInfo
const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
5814 SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description );
5817 assertions.failed = 1;
5818 SectionStats testCaseSectionStats( testCaseSection, assertions, 0,
false );
5819 m_reporter->sectionEnded( testCaseSectionStats );
5821 TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo();
5824 deltaTotals.testCases.failed = 1;
5825 m_reporter->testCaseEnded( TestCaseStats( testInfo,
5830 m_totals.testCases.failed++;
5831 testGroupEnded(
"", m_totals, 1, 1 );
5832 m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals,
false ) );
5837 bool aborting()
const {
5838 return m_totals.assertions.failed ==
static_cast<std::size_t
>( m_config->abortAfter() );
5843 void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) {
5844 TestCaseInfo
const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
5845 SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description );
5846 m_reporter->sectionStarting( testCaseSection );
5847 Counts prevAssertions = m_totals.assertions;
5848 double duration = 0;
5850 m_lastAssertionInfo = AssertionInfo(
"TEST_CASE", testCaseInfo.lineInfo,
"", ResultDisposition::Normal );
5852 seedRng( *m_config );
5856 if( m_reporter->getPreferences().shouldRedirectStdOut ) {
5857 StreamRedirect coutRedir( Catch::cout(), redirectedCout );
5858 StreamRedirect cerrRedir( Catch::cerr(), redirectedCerr );
5859 invokeActiveTestCase();
5862 invokeActiveTestCase();
5864 duration = timer.getElapsedSeconds();
5866 catch( TestFailureException& ) {
5870 makeUnexpectedResultBuilder().useActiveException();
5872 m_testCaseTracker->close();
5873 handleUnfinishedSections();
5876 Counts assertions = m_totals.assertions - prevAssertions;
5877 bool missingAssertions = testForMissingAssertions( assertions );
5879 if( testCaseInfo.okToFail() ) {
5880 std::swap( assertions.failedButOk, assertions.failed );
5881 m_totals.assertions.failed -= assertions.failedButOk;
5882 m_totals.assertions.failedButOk += assertions.failedButOk;
5885 SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions );
5886 m_reporter->sectionEnded( testCaseSectionStats );
5889 void invokeActiveTestCase() {
5890 FatalConditionHandler fatalConditionHandler;
5891 m_activeTestCase->invoke();
5892 fatalConditionHandler.reset();
5897 ResultBuilder makeUnexpectedResultBuilder()
const {
5898 return ResultBuilder( m_lastAssertionInfo.macroName.c_str(),
5899 m_lastAssertionInfo.lineInfo,
5900 m_lastAssertionInfo.capturedExpression.c_str(),
5901 m_lastAssertionInfo.resultDisposition );
5904 void handleUnfinishedSections() {
5907 for( std::vector<SectionEndInfo>::const_reverse_iterator it = m_unfinishedSections.rbegin(),
5908 itEnd = m_unfinishedSections.rend();
5911 sectionEnded( *it );
5912 m_unfinishedSections.clear();
5915 TestRunInfo m_runInfo;
5916 IMutableContext& m_context;
5917 TestCase
const* m_activeTestCase;
5918 ITracker* m_testCaseTracker;
5919 ITracker* m_currentSectionTracker;
5920 AssertionResult m_lastResult;
5922 Ptr<IConfig const> m_config;
5924 Ptr<IStreamingReporter> m_reporter;
5925 std::vector<MessageInfo> m_messages;
5926 AssertionInfo m_lastAssertionInfo;
5927 std::vector<SectionEndInfo> m_unfinishedSections;
5928 std::vector<ITracker*> m_activeSections;
5929 TrackerContext m_trackerContext;
5932 IResultCapture& getResultCapture() {
5933 if( IResultCapture* capture = getCurrentContext().getResultCapture() )
5936 throw std::logic_error(
"No result capture instance" );
5942 #define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED
5948 Version(
unsigned int _majorVersion,
5949 unsigned int _minorVersion,
5950 unsigned int _patchNumber,
5951 std::string
const& _branchName,
5952 unsigned int _buildNumber );
5954 unsigned int const majorVersion;
5955 unsigned int const minorVersion;
5956 unsigned int const patchNumber;
5959 std::string
const branchName;
5960 unsigned int const buildNumber;
5962 friend std::ostream& operator << ( std::ostream& os, Version
const& version );
5965 void operator=( Version
const& );
5968 extern Version libraryVersion;
5977 Ptr<IStreamingReporter> createReporter( std::string
const& reporterName, Ptr<Config>
const& config ) {
5978 Ptr<IStreamingReporter> reporter = getRegistryHub().getReporterRegistry().create( reporterName, config.get() );
5980 std::ostringstream oss;
5981 oss <<
"No reporter registered with name: '" << reporterName <<
"'";
5982 throw std::domain_error( oss.str() );
5987 Ptr<IStreamingReporter> makeReporter( Ptr<Config>
const& config ) {
5988 std::vector<std::string> reporters = config->getReporterNames();
5989 if( reporters.empty() )
5990 reporters.push_back(
"console" );
5992 Ptr<IStreamingReporter> reporter;
5993 for( std::vector<std::string>::const_iterator it = reporters.begin(), itEnd = reporters.end();
5996 reporter = addReporter( reporter, createReporter( *it, config ) );
5999 Ptr<IStreamingReporter> addListeners( Ptr<IConfig const>
const& config, Ptr<IStreamingReporter> reporters ) {
6000 IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners();
6001 for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end();
6004 reporters = addReporter(reporters, (*it)->create( ReporterConfig( config ) ) );
6008 Totals runTests( Ptr<Config>
const& config ) {
6010 Ptr<IConfig const> iconfig = config.get();
6012 Ptr<IStreamingReporter> reporter = makeReporter( config );
6013 reporter = addListeners( iconfig, reporter );
6015 RunContext context( iconfig, reporter );
6019 context.testGroupStarting( config->name(), 1, 1 );
6021 TestSpec testSpec = config->testSpec();
6022 if( !testSpec.hasFilters() )
6023 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse(
"~[.]" ).testSpec();
6025 std::vector<TestCase>
const& allTestCases = getAllTestCasesSorted( *iconfig );
6026 for( std::vector<TestCase>::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end();
6029 if( !context.aborting() && matchTest( *it, testSpec, *iconfig ) )
6030 totals += context.runTest( *it );
6032 reporter->skipTest( *it );
6035 context.testGroupEnded( iconfig->name(), totals, 1, 1 );
6039 void applyFilenamesAsTags( IConfig
const& config ) {
6040 std::vector<TestCase>
const& tests = getAllTestCasesSorted( config );
6041 for(std::size_t i = 0; i < tests.size(); ++i ) {
6042 TestCase& test =
const_cast<TestCase&
>( tests[i] );
6043 std::set<std::string> tags = test.tags;
6045 std::string filename = test.lineInfo.file;
6046 std::string::size_type lastSlash = filename.find_last_of(
"\\/" );
6047 if( lastSlash != std::string::npos )
6048 filename = filename.substr( lastSlash+1 );
6050 std::string::size_type lastDot = filename.find_last_of(
"." );
6051 if( lastDot != std::string::npos )
6052 filename = filename.substr( 0, lastDot );
6054 tags.insert(
"#" + filename );
6055 setTags( test, tags );
6059 class Session : NonCopyable {
6060 static bool alreadyInstantiated;
6064 struct OnUnusedOptions {
enum DoWhat { Ignore, Fail }; };
6067 : m_cli( makeCommandLineParser() ) {
6068 if( alreadyInstantiated ) {
6069 std::string msg =
"Only one instance of Catch::Session can ever be used";
6070 Catch::cerr() << msg << std::endl;
6071 throw std::logic_error( msg );
6073 alreadyInstantiated =
true;
6079 void showHelp( std::string
const& processName ) {
6080 Catch::cout() <<
"\nCatch v" << libraryVersion <<
"\n";
6082 m_cli.usage( Catch::cout(), processName );
6083 Catch::cout() <<
"For more detail usage please see the project docs\n" << std::endl;
6086 int applyCommandLine(
int argc,
char const*
const argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) {
6088 m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail );
6089 m_unusedTokens = m_cli.parseInto( argc, argv, m_configData );
6090 if( m_configData.showHelp )
6091 showHelp( m_configData.processName );
6094 catch( std::exception& ex ) {
6096 Colour colourGuard( Colour::Red );
6098 <<
"\nError(s) in input:\n"
6099 << Text( ex.what(), TextAttributes().setIndent(2) )
6102 m_cli.usage( Catch::cout(), m_configData.processName );
6103 return (std::numeric_limits<int>::max)();
6108 void useConfigData( ConfigData
const& _configData ) {
6109 m_configData = _configData;
6113 int run(
int argc,
char const*
const argv[] ) {
6115 int returnCode = applyCommandLine( argc, argv );
6116 if( returnCode == 0 )
6122 if( m_configData.showHelp )
6129 seedRng( *m_config );
6131 if( m_configData.filenamesAsTags )
6132 applyFilenamesAsTags( *m_config );
6135 if( Option<std::size_t> listed = list( config() ) )
6136 return static_cast<int>( *listed );
6138 return static_cast<int>( runTests( m_config ).assertions.failed );
6140 catch( std::exception& ex ) {
6141 Catch::cerr() << ex.what() << std::endl;
6142 return (std::numeric_limits<int>::max)();
6146 Clara::CommandLine<ConfigData>
const& cli()
const {
6149 std::vector<Clara::Parser::Token>
const& unusedTokens()
const {
6150 return m_unusedTokens;
6152 ConfigData& configData() {
6153 return m_configData;
6157 m_config =
new Config( m_configData );
6161 Clara::CommandLine<ConfigData> m_cli;
6162 std::vector<Clara::Parser::Token> m_unusedTokens;
6163 ConfigData m_configData;
6164 Ptr<Config> m_config;
6167 bool Session::alreadyInstantiated =
false;
6172 #define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED
6175 #define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
6181 #include <algorithm>
6186 bool operator() (TestCase i,TestCase j)
const {
return (i<j);}
6188 struct RandomNumberGenerator {
6189 int operator()(
int n )
const {
return std::rand() % n; }
6192 inline std::vector<TestCase> sortTests( IConfig
const& config, std::vector<TestCase>
const& unsortedTestCases ) {
6194 std::vector<TestCase> sorted = unsortedTestCases;
6196 switch( config.runOrder() ) {
6197 case RunTests::InLexicographicalOrder:
6198 std::sort( sorted.begin(), sorted.end(), LexSort() );
6200 case RunTests::InRandomOrder:
6204 RandomNumberGenerator rng;
6205 std::random_shuffle( sorted.begin(), sorted.end(), rng );
6208 case RunTests::InDeclarationOrder:
6214 bool matchTest( TestCase
const& testCase, TestSpec
const& testSpec, IConfig
const& config ) {
6215 return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() );
6218 void enforceNoDuplicateTestCases( std::vector<TestCase>
const& functions ) {
6219 std::set<TestCase> seenFunctions;
6220 for( std::vector<TestCase>::const_iterator it = functions.begin(), itEnd = functions.end();
6223 std::pair<std::set<TestCase>::const_iterator,
bool> prev = seenFunctions.insert( *it );
6226 << Colour( Colour::Red )
6227 <<
"error: TEST_CASE( \"" << it->name <<
"\" ) already defined.\n"
6228 <<
"\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo <<
"\n"
6229 <<
"\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl;
6235 std::vector<TestCase> filterTests( std::vector<TestCase>
const& testCases, TestSpec
const& testSpec, IConfig
const& config ) {
6236 std::vector<TestCase> filtered;
6237 filtered.reserve( testCases.size() );
6238 for( std::vector<TestCase>::const_iterator it = testCases.begin(), itEnd = testCases.end();
6241 if( matchTest( *it, testSpec, config ) )
6242 filtered.push_back( *it );
6245 std::vector<TestCase>
const& getAllTestCasesSorted( IConfig
const& config ) {
6246 return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config );
6249 class TestRegistry :
public ITestCaseRegistry {
6252 : m_currentSortOrder( RunTests::InDeclarationOrder ),
6255 virtual ~TestRegistry();
6257 virtual void registerTest( TestCase
const& testCase ) {
6258 std::string name = testCase.getTestCaseInfo().name;
6260 std::ostringstream oss;
6261 oss <<
"Anonymous test case " << ++m_unnamedCount;
6262 return registerTest( testCase.withName( oss.str() ) );
6264 m_functions.push_back( testCase );
6267 virtual std::vector<TestCase>
const& getAllTests()
const {
6270 virtual std::vector<TestCase>
const& getAllTestsSorted( IConfig
const& config )
const {
6271 if( m_sortedFunctions.empty() )
6272 enforceNoDuplicateTestCases( m_functions );
6274 if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) {
6275 m_sortedFunctions = sortTests( config, m_functions );
6276 m_currentSortOrder = config.runOrder();
6278 return m_sortedFunctions;
6282 std::vector<TestCase> m_functions;
6283 mutable RunTests::InWhatOrder m_currentSortOrder;
6284 mutable std::vector<TestCase> m_sortedFunctions;
6285 size_t m_unnamedCount;
6286 std::ios_base::Init m_ostreamInit;
6291 class FreeFunctionTestCase :
public SharedImpl<ITestCase> {
6294 FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {}
6296 virtual void invoke()
const {
6301 virtual ~FreeFunctionTestCase();
6306 inline std::string extractClassName( std::string
const& classOrQualifiedMethodName ) {
6307 std::string className = classOrQualifiedMethodName;
6308 if( startsWith( className,
"&" ) )
6310 std::size_t lastColons = className.rfind(
"::" );
6311 std::size_t penultimateColons = className.rfind(
"::", lastColons-1 );
6312 if( penultimateColons == std::string::npos )
6313 penultimateColons = 1;
6314 className = className.substr( penultimateColons, lastColons-penultimateColons );
6319 void registerTestCase
6320 ( ITestCase* testCase,
6321 char const* classOrQualifiedMethodName,
6322 NameAndDesc
const& nameAndDesc,
6323 SourceLineInfo
const& lineInfo ) {
6325 getMutableRegistryHub().registerTest
6328 extractClassName( classOrQualifiedMethodName ),
6330 nameAndDesc.description,
6333 void registerTestCaseFunction
6334 ( TestFunction
function,
6335 SourceLineInfo
const& lineInfo,
6336 NameAndDesc
const& nameAndDesc ) {
6337 registerTestCase(
new FreeFunctionTestCase(
function ),
"", nameAndDesc, lineInfo );
6343 ( TestFunction
function,
6344 SourceLineInfo
const& lineInfo,
6345 NameAndDesc
const& nameAndDesc ) {
6346 registerTestCaseFunction(
function, lineInfo, nameAndDesc );
6349 AutoReg::~AutoReg() {}
6354 #define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
6360 class ReporterRegistry :
public IReporterRegistry {
6364 virtual ~ReporterRegistry() CATCH_OVERRIDE {}
6366 virtual IStreamingReporter* create( std::string
const& name, Ptr<IConfig const>
const& config )
const CATCH_OVERRIDE {
6367 FactoryMap::const_iterator it = m_factories.find( name );
6368 if( it == m_factories.end() )
6370 return it->second->create( ReporterConfig( config ) );
6373 void registerReporter( std::string
const& name, Ptr<IReporterFactory>
const& factory ) {
6374 m_factories.insert( std::make_pair( name, factory ) );
6376 void registerListener( Ptr<IReporterFactory>
const& factory ) {
6377 m_listeners.push_back( factory );
6380 virtual FactoryMap
const& getFactories() const CATCH_OVERRIDE {
6383 virtual Listeners
const& getListeners() const CATCH_OVERRIDE {
6388 FactoryMap m_factories;
6389 Listeners m_listeners;
6394 #define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
6397 #import "Foundation/Foundation.h"
6402 class ExceptionTranslatorRegistry :
public IExceptionTranslatorRegistry {
6404 ~ExceptionTranslatorRegistry() {
6405 deleteAll( m_translators );
6408 virtual void registerTranslator(
const IExceptionTranslator* translator ) {
6409 m_translators.push_back( translator );
6412 virtual std::string translateActiveException()
const {
6417 return tryTranslators();
6419 @catch (NSException *exception) {
6420 return Catch::toString( [exception description] );
6423 return tryTranslators();
6426 catch( TestFailureException& ) {
6429 catch( std::exception& ex ) {
6432 catch( std::string& msg ) {
6435 catch(
const char* msg ) {
6439 return "Unknown exception";
6443 std::string tryTranslators()
const {
6444 if( m_translators.empty() )
6447 return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() );
6451 std::vector<const IExceptionTranslator*> m_translators;
6459 class RegistryHub :
public IRegistryHub,
public IMutableRegistryHub {
6461 RegistryHub( RegistryHub
const& );
6462 void operator=( RegistryHub
const& );
6467 virtual IReporterRegistry
const& getReporterRegistry() const CATCH_OVERRIDE {
6468 return m_reporterRegistry;
6470 virtual ITestCaseRegistry
const& getTestCaseRegistry() const CATCH_OVERRIDE {
6471 return m_testCaseRegistry;
6473 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE {
6474 return m_exceptionTranslatorRegistry;
6478 virtual void registerReporter( std::string
const& name, Ptr<IReporterFactory>
const& factory ) CATCH_OVERRIDE {
6479 m_reporterRegistry.registerReporter( name, factory );
6481 virtual void registerListener( Ptr<IReporterFactory>
const& factory ) CATCH_OVERRIDE {
6482 m_reporterRegistry.registerListener( factory );
6484 virtual void registerTest( TestCase
const& testInfo ) CATCH_OVERRIDE {
6485 m_testCaseRegistry.registerTest( testInfo );
6487 virtual void registerTranslator(
const IExceptionTranslator* translator ) CATCH_OVERRIDE {
6488 m_exceptionTranslatorRegistry.registerTranslator( translator );
6492 TestRegistry m_testCaseRegistry;
6493 ReporterRegistry m_reporterRegistry;
6494 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
6498 inline RegistryHub*& getTheRegistryHub() {
6499 static RegistryHub* theRegistryHub = CATCH_NULL;
6500 if( !theRegistryHub )
6501 theRegistryHub =
new RegistryHub();
6502 return theRegistryHub;
6506 IRegistryHub& getRegistryHub() {
6507 return *getTheRegistryHub();
6509 IMutableRegistryHub& getMutableRegistryHub() {
6510 return *getTheRegistryHub();
6513 delete getTheRegistryHub();
6514 getTheRegistryHub() = CATCH_NULL;
6517 std::string translateActiveException() {
6518 return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
6524 #define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
6530 NotImplementedException::NotImplementedException( SourceLineInfo
const& lineInfo )
6531 : m_lineInfo( lineInfo ) {
6532 std::ostringstream oss;
6533 oss << lineInfo <<
": function ";
6534 oss <<
"not implemented";
6538 const char* NotImplementedException::what() const CATCH_NOEXCEPT {
6539 return m_what.c_str();
6545 #define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED
6548 #define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
6550 #include <stdexcept>
6556 template<
typename WriterF,
size_t bufferSize=256>
6557 class StreamBufImpl :
public StreamBufBase {
6558 char data[bufferSize];
6563 setp( data, data +
sizeof(data) );
6566 ~StreamBufImpl() CATCH_NOEXCEPT {
6571 int overflow(
int c ) {
6575 if( pbase() == epptr() )
6576 m_writer( std::string( 1,
static_cast<char>( c ) ) );
6578 sputc(
static_cast<char>( c ) );
6584 if( pbase() != pptr() ) {
6585 m_writer( std::string( pbase(),
static_cast<std::string::size_type
>( pptr() - pbase() ) ) );
6586 setp( pbase(), epptr() );
6594 FileStream::FileStream( std::string
const& filename ) {
6595 m_ofs.open( filename.c_str() );
6596 if( m_ofs.fail() ) {
6597 std::ostringstream oss;
6598 oss <<
"Unable to open file: '" << filename <<
"'";
6599 throw std::domain_error( oss.str() );
6603 std::ostream& FileStream::stream()
const {
6607 struct OutputDebugWriter {
6609 void operator()( std::string
const&str ) {
6610 writeToDebugConsole( str );
6614 DebugOutStream::DebugOutStream()
6615 : m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ),
6616 m_os( m_streamBuf.get() )
6619 std::ostream& DebugOutStream::stream()
const {
6625 CoutStream::CoutStream()
6626 : m_os( Catch::cout().rdbuf() )
6629 std::ostream& CoutStream::stream()
const {
6633 #ifndef CATCH_CONFIG_NOSTDOUT
6634 std::ostream& cout() {
6637 std::ostream& cerr() {
6645 class Context :
public IMutableContext {
6647 Context() : m_config( CATCH_NULL ), m_runner( CATCH_NULL ), m_resultCapture( CATCH_NULL ) {}
6648 Context( Context
const& );
6649 void operator=( Context
const& );
6652 virtual IResultCapture* getResultCapture() {
6653 return m_resultCapture;
6655 virtual IRunner* getRunner() {
6658 virtual size_t getGeneratorIndex( std::string
const& fileInfo,
size_t totalSize ) {
6659 return getGeneratorsForCurrentTest()
6660 .getGeneratorInfo( fileInfo, totalSize )
6663 virtual bool advanceGeneratorsForCurrentTest() {
6664 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
6665 return generators && generators->moveNext();
6668 virtual Ptr<IConfig const> getConfig()
const {
6673 virtual void setResultCapture( IResultCapture* resultCapture ) {
6674 m_resultCapture = resultCapture;
6676 virtual void setRunner( IRunner* runner ) {
6679 virtual void setConfig( Ptr<IConfig const>
const& config ) {
6683 friend IMutableContext& getCurrentMutableContext();
6686 IGeneratorsForTest* findGeneratorsForCurrentTest() {
6687 std::string testName = getResultCapture()->getCurrentTestName();
6689 std::map<std::string, IGeneratorsForTest*>::const_iterator it =
6690 m_generatorsByTestName.find( testName );
6691 return it != m_generatorsByTestName.end()
6696 IGeneratorsForTest& getGeneratorsForCurrentTest() {
6697 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
6699 std::string testName = getResultCapture()->getCurrentTestName();
6700 generators = createGeneratorsForTest();
6701 m_generatorsByTestName.insert( std::make_pair( testName, generators ) );
6707 Ptr<IConfig const> m_config;
6709 IResultCapture* m_resultCapture;
6710 std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName;
6714 Context* currentContext = CATCH_NULL;
6716 IMutableContext& getCurrentMutableContext() {
6717 if( !currentContext )
6718 currentContext =
new Context();
6719 return *currentContext;
6721 IContext& getCurrentContext() {
6722 return getCurrentMutableContext();
6725 void cleanUpContext() {
6726 delete currentContext;
6727 currentContext = CATCH_NULL;
6732 #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
6737 struct IColourImpl {
6738 virtual ~IColourImpl() {}
6739 virtual void use( Colour::Code _colourCode ) = 0;
6742 struct NoColourImpl : IColourImpl {
6743 void use( Colour::Code ) {}
6745 static IColourImpl* instance() {
6746 static NoColourImpl s_instance;
6754 #if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI )
6755 # ifdef CATCH_PLATFORM_WINDOWS
6756 # define CATCH_CONFIG_COLOUR_WINDOWS
6758 # define CATCH_CONFIG_COLOUR_ANSI
6762 #if defined ( CATCH_CONFIG_COLOUR_WINDOWS )
6771 #include <windows.h>
6777 class Win32ColourImpl :
public IColourImpl {
6779 Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
6781 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
6782 GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );
6783 originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY );
6784 originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
6787 virtual void use( Colour::Code _colourCode ) {
6788 switch( _colourCode ) {
6789 case Colour::None:
return setTextAttribute( originalForegroundAttributes );
6790 case Colour::White:
return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
6791 case Colour::Red:
return setTextAttribute( FOREGROUND_RED );
6792 case Colour::Green:
return setTextAttribute( FOREGROUND_GREEN );
6793 case Colour::Blue:
return setTextAttribute( FOREGROUND_BLUE );
6794 case Colour::Cyan:
return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );
6795 case Colour::Yellow:
return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );
6796 case Colour::Grey:
return setTextAttribute( 0 );
6798 case Colour::LightGrey:
return setTextAttribute( FOREGROUND_INTENSITY );
6799 case Colour::BrightRed:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
6800 case Colour::BrightGreen:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
6801 case Colour::BrightWhite:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
6803 case Colour::Bright:
throw std::logic_error(
"not a colour" );
6808 void setTextAttribute( WORD _textAttribute ) {
6809 SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes );
6811 HANDLE stdoutHandle;
6812 WORD originalForegroundAttributes;
6813 WORD originalBackgroundAttributes;
6816 IColourImpl* platformColourInstance() {
6817 static Win32ColourImpl s_instance;
6824 #elif defined( CATCH_CONFIG_COLOUR_ANSI )
6835 class PosixColourImpl :
public IColourImpl {
6837 virtual void use( Colour::Code _colourCode ) {
6838 switch( _colourCode ) {
6840 case Colour::White:
return setColour(
"[0m" );
6841 case Colour::Red:
return setColour(
"[0;31m" );
6842 case Colour::Green:
return setColour(
"[0;32m" );
6843 case Colour::Blue:
return setColour(
"[0:34m" );
6844 case Colour::Cyan:
return setColour(
"[0;36m" );
6845 case Colour::Yellow:
return setColour(
"[0;33m" );
6846 case Colour::Grey:
return setColour(
"[1;30m" );
6848 case Colour::LightGrey:
return setColour(
"[0;37m" );
6849 case Colour::BrightRed:
return setColour(
"[1;31m" );
6850 case Colour::BrightGreen:
return setColour(
"[1;32m" );
6851 case Colour::BrightWhite:
return setColour(
"[1;37m" );
6853 case Colour::Bright:
throw std::logic_error(
"not a colour" );
6856 static IColourImpl* instance() {
6857 static PosixColourImpl s_instance;
6862 void setColour(
const char* _escapeCode ) {
6863 Catch::cout() <<
'\033' << _escapeCode;
6867 IColourImpl* platformColourInstance() {
6868 Ptr<IConfig const> config = getCurrentContext().getConfig();
6869 return (config && config->forceColour()) || isatty(STDOUT_FILENO)
6870 ? PosixColourImpl::instance()
6871 : NoColourImpl::instance();
6881 static IColourImpl* platformColourInstance() {
return NoColourImpl::instance(); }
6889 Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); }
6890 Colour::Colour( Colour
const& _other ) : m_moved( false ) {
const_cast<Colour&
>( _other ).m_moved =
true; }
6891 Colour::~Colour(){
if( !m_moved ) use( None ); }
6893 void Colour::use( Code _colourCode ) {
6894 static IColourImpl* impl = isDebuggerActive()
6895 ? NoColourImpl::instance()
6896 : platformColourInstance();
6897 impl->use( _colourCode );
6903 #define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
6911 struct GeneratorInfo : IGeneratorInfo {
6913 GeneratorInfo( std::size_t size )
6919 if( ++m_currentIndex == m_size ) {
6926 std::size_t getCurrentIndex()
const {
6927 return m_currentIndex;
6931 std::size_t m_currentIndex;
6936 class GeneratorsForTest :
public IGeneratorsForTest {
6939 ~GeneratorsForTest() {
6940 deleteAll( m_generatorsInOrder );
6943 IGeneratorInfo& getGeneratorInfo( std::string
const& fileInfo, std::size_t size ) {
6944 std::map<std::string, IGeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo );
6945 if( it == m_generatorsByName.end() ) {
6946 IGeneratorInfo* info =
new GeneratorInfo( size );
6947 m_generatorsByName.insert( std::make_pair( fileInfo, info ) );
6948 m_generatorsInOrder.push_back( info );
6955 std::vector<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
6956 std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end();
6957 for(; it != itEnd; ++it ) {
6958 if( (*it)->moveNext() )
6965 std::map<std::string, IGeneratorInfo*> m_generatorsByName;
6966 std::vector<IGeneratorInfo*> m_generatorsInOrder;
6969 IGeneratorsForTest* createGeneratorsForTest()
6971 return new GeneratorsForTest();
6977 #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED
6981 AssertionInfo::AssertionInfo( std::string
const& _macroName,
6982 SourceLineInfo
const& _lineInfo,
6983 std::string
const& _capturedExpression,
6984 ResultDisposition::Flags _resultDisposition )
6985 : macroName( _macroName ),
6986 lineInfo( _lineInfo ),
6987 capturedExpression( _capturedExpression ),
6988 resultDisposition( _resultDisposition )
6991 AssertionResult::AssertionResult() {}
6993 AssertionResult::AssertionResult( AssertionInfo
const& info, AssertionResultData
const& data )
6995 m_resultData( data )
6998 AssertionResult::~AssertionResult() {}
7001 bool AssertionResult::succeeded()
const {
7002 return Catch::isOk( m_resultData.resultType );
7006 bool AssertionResult::isOk()
const {
7007 return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition );
7010 ResultWas::OfType AssertionResult::getResultType()
const {
7011 return m_resultData.resultType;
7014 bool AssertionResult::hasExpression()
const {
7015 return !m_info.capturedExpression.empty();
7018 bool AssertionResult::hasMessage()
const {
7019 return !m_resultData.message.empty();
7022 std::string AssertionResult::getExpression()
const {
7023 if( isFalseTest( m_info.resultDisposition ) )
7024 return "!" + m_info.capturedExpression;
7026 return m_info.capturedExpression;
7028 std::string AssertionResult::getExpressionInMacro()
const {
7029 if( m_info.macroName.empty() )
7030 return m_info.capturedExpression;
7032 return m_info.macroName + "( " + m_info.capturedExpression + " )";
7035 bool AssertionResult::hasExpandedExpression()
const {
7036 return hasExpression() && getExpandedExpression() != getExpression();
7039 std::string AssertionResult::getExpandedExpression()
const {
7040 return m_resultData.reconstructedExpression;
7043 std::string AssertionResult::getMessage()
const {
7044 return m_resultData.message;
7046 SourceLineInfo AssertionResult::getSourceInfo()
const {
7047 return m_info.lineInfo;
7050 std::string AssertionResult::getTestMacroName()
const {
7051 return m_info.macroName;
7057 #define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED
7061 inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string
const& tag ) {
7062 if( startsWith( tag,
"." ) ||
7065 return TestCaseInfo::IsHidden;
7066 else if( tag ==
"!throws" )
7067 return TestCaseInfo::Throws;
7068 else if( tag ==
"!shouldfail" )
7069 return TestCaseInfo::ShouldFail;
7070 else if( tag ==
"!mayfail" )
7071 return TestCaseInfo::MayFail;
7073 return TestCaseInfo::None;
7075 inline bool isReservedTag( std::string
const& tag ) {
7076 return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !isalnum( tag[0] );
7078 inline void enforceNotReservedTag( std::string
const& tag, SourceLineInfo
const& _lineInfo ) {
7079 if( isReservedTag( tag ) ) {
7081 Colour colourGuard( Colour::Red );
7083 <<
"Tag name [" << tag <<
"] not allowed.\n"
7084 <<
"Tag names starting with non alpha-numeric characters are reserved\n";
7087 Colour colourGuard( Colour::FileName );
7088 Catch::cerr() << _lineInfo << std::endl;
7094 TestCase makeTestCase( ITestCase* _testCase,
7095 std::string
const& _className,
7096 std::string
const& _name,
7097 std::string
const& _descOrTags,
7098 SourceLineInfo
const& _lineInfo )
7100 bool isHidden( startsWith( _name,
"./" ) );
7103 std::set<std::string> tags;
7104 std::string desc, tag;
7106 for( std::size_t i = 0; i < _descOrTags.size(); ++i ) {
7107 char c = _descOrTags[i];
7116 TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag );
7117 if( prop == TestCaseInfo::IsHidden )
7119 else if( prop == TestCaseInfo::None )
7120 enforceNotReservedTag( tag, _lineInfo );
7131 tags.insert(
"hide" );
7135 TestCaseInfo info( _name, _className, desc, tags, _lineInfo );
7136 return TestCase( _testCase, info );
7139 void setTags( TestCaseInfo& testCaseInfo, std::set<std::string>
const& tags )
7141 testCaseInfo.tags = tags;
7142 testCaseInfo.lcaseTags.clear();
7144 std::ostringstream oss;
7145 for( std::set<std::string>::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it ) {
7146 oss <<
"[" << *it <<
"]";
7147 std::string lcaseTag = toLower( *it );
7148 testCaseInfo.properties =
static_cast<TestCaseInfo::SpecialProperties
>( testCaseInfo.properties | parseSpecialTag( lcaseTag ) );
7149 testCaseInfo.lcaseTags.insert( lcaseTag );
7151 testCaseInfo.tagsAsString = oss.str();
7154 TestCaseInfo::TestCaseInfo( std::string
const& _name,
7155 std::string
const& _className,
7156 std::string
const& _description,
7157 std::set<std::string>
const& _tags,
7158 SourceLineInfo
const& _lineInfo )
7160 className( _className ),
7161 description( _description ),
7162 lineInfo( _lineInfo ),
7165 setTags( *
this, _tags );
7168 TestCaseInfo::TestCaseInfo( TestCaseInfo
const& other )
7169 : name( other.name ),
7170 className( other.className ),
7171 description( other.description ),
7173 lcaseTags( other.lcaseTags ),
7174 tagsAsString( other.tagsAsString ),
7175 lineInfo( other.lineInfo ),
7176 properties( other.properties )
7179 bool TestCaseInfo::isHidden()
const {
7180 return ( properties & IsHidden ) != 0;
7182 bool TestCaseInfo::throws()
const {
7183 return ( properties & Throws ) != 0;
7185 bool TestCaseInfo::okToFail()
const {
7186 return ( properties & (ShouldFail | MayFail ) ) != 0;
7188 bool TestCaseInfo::expectedToFail()
const {
7189 return ( properties & (ShouldFail ) ) != 0;
7192 TestCase::TestCase( ITestCase* testCase, TestCaseInfo
const& info ) : TestCaseInfo( info ), test( testCase ) {}
7194 TestCase::TestCase( TestCase
const& other )
7195 : TestCaseInfo( other ),
7199 TestCase TestCase::withName( std::string
const& _newName )
const {
7200 TestCase other( *
this );
7201 other.name = _newName;
7205 void TestCase::swap( TestCase& other ) {
7206 test.swap( other.test );
7207 name.swap( other.name );
7208 className.swap( other.className );
7209 description.swap( other.description );
7210 tags.swap( other.tags );
7211 lcaseTags.swap( other.lcaseTags );
7212 tagsAsString.swap( other.tagsAsString );
7213 std::swap( TestCaseInfo::properties,
static_cast<TestCaseInfo&
>( other ).properties );
7214 std::swap( lineInfo, other.lineInfo );
7217 void TestCase::invoke()
const {
7221 bool TestCase::operator == ( TestCase
const& other )
const {
7222 return test.get() == other.test.get() &&
7223 name == other.name &&
7224 className == other.className;
7227 bool TestCase::operator < ( TestCase
const& other )
const {
7228 return name < other.name;
7230 TestCase& TestCase::operator = ( TestCase
const& other ) {
7231 TestCase temp( other );
7236 TestCaseInfo
const& TestCase::getTestCaseInfo()
const
7244 #define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED
7249 (
unsigned int _majorVersion,
7250 unsigned int _minorVersion,
7251 unsigned int _patchNumber,
7252 std::string
const& _branchName,
7253 unsigned int _buildNumber )
7254 : majorVersion( _majorVersion ),
7255 minorVersion( _minorVersion ),
7256 patchNumber( _patchNumber ),
7257 branchName( _branchName ),
7258 buildNumber( _buildNumber )
7261 std::ostream& operator << ( std::ostream& os, Version
const& version ) {
7262 os << version.majorVersion <<
"."
7263 << version.minorVersion <<
"."
7264 << version.patchNumber;
7266 if( !version.branchName.empty() ) {
7267 os <<
"-" << version.branchName
7268 <<
"." << version.buildNumber;
7273 Version libraryVersion( 1, 3, 3,
"", 0 );
7278 #define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED
7282 MessageInfo::MessageInfo( std::string
const& _macroName,
7283 SourceLineInfo
const& _lineInfo,
7284 ResultWas::OfType _type )
7285 : macroName( _macroName ),
7286 lineInfo( _lineInfo ),
7288 sequence( ++globalCount )
7292 unsigned int MessageInfo::globalCount = 0;
7296 ScopedMessage::ScopedMessage( MessageBuilder
const& builder )
7297 : m_info( builder.m_info )
7299 m_info.message = builder.m_stream.str();
7300 getResultCapture().pushScopedMessage( m_info );
7302 ScopedMessage::ScopedMessage( ScopedMessage
const& other )
7303 : m_info( other.m_info )
7306 ScopedMessage::~ScopedMessage() {
7307 getResultCapture().popScopedMessage( m_info );
7313 #define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED
7316 #define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED
7321 struct IReporter : IShared {
7322 virtual ~IReporter();
7324 virtual bool shouldRedirectStdout()
const = 0;
7326 virtual void StartTesting() = 0;
7327 virtual void EndTesting( Totals
const& totals ) = 0;
7328 virtual void StartGroup( std::string
const& groupName ) = 0;
7329 virtual void EndGroup( std::string
const& groupName, Totals
const& totals ) = 0;
7330 virtual void StartTestCase( TestCaseInfo
const& testInfo ) = 0;
7331 virtual void EndTestCase( TestCaseInfo
const& testInfo, Totals
const& totals, std::string
const& stdOut, std::string
const& stdErr ) = 0;
7332 virtual void StartSection( std::string
const& sectionName, std::string
const& description ) = 0;
7333 virtual void EndSection( std::string
const& sectionName, Counts
const& assertions ) = 0;
7334 virtual void NoAssertionsInSection( std::string
const& sectionName ) = 0;
7335 virtual void NoAssertionsInTestCase( std::string
const& testName ) = 0;
7336 virtual void Aborted() = 0;
7337 virtual void Result( AssertionResult
const& result ) = 0;
7340 class LegacyReporterAdapter :
public SharedImpl<IStreamingReporter>
7343 LegacyReporterAdapter( Ptr<IReporter>
const& legacyReporter );
7344 virtual ~LegacyReporterAdapter();
7346 virtual ReporterPreferences getPreferences()
const;
7347 virtual void noMatchingTestCases( std::string
const& );
7348 virtual void testRunStarting( TestRunInfo
const& );
7349 virtual void testGroupStarting( GroupInfo
const& groupInfo );
7350 virtual void testCaseStarting( TestCaseInfo
const& testInfo );
7351 virtual void sectionStarting( SectionInfo
const& sectionInfo );
7352 virtual void assertionStarting( AssertionInfo
const& );
7353 virtual bool assertionEnded( AssertionStats
const& assertionStats );
7354 virtual void sectionEnded( SectionStats
const& sectionStats );
7355 virtual void testCaseEnded( TestCaseStats
const& testCaseStats );
7356 virtual void testGroupEnded( TestGroupStats
const& testGroupStats );
7357 virtual void testRunEnded( TestRunStats
const& testRunStats );
7358 virtual void skipTest( TestCaseInfo
const& );
7361 Ptr<IReporter> m_legacyReporter;
7367 LegacyReporterAdapter::LegacyReporterAdapter( Ptr<IReporter>
const& legacyReporter )
7368 : m_legacyReporter( legacyReporter )
7370 LegacyReporterAdapter::~LegacyReporterAdapter() {}
7372 ReporterPreferences LegacyReporterAdapter::getPreferences()
const {
7373 ReporterPreferences prefs;
7374 prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout();
7378 void LegacyReporterAdapter::noMatchingTestCases( std::string
const& ) {}
7379 void LegacyReporterAdapter::testRunStarting( TestRunInfo
const& ) {
7380 m_legacyReporter->StartTesting();
7382 void LegacyReporterAdapter::testGroupStarting( GroupInfo
const& groupInfo ) {
7383 m_legacyReporter->StartGroup( groupInfo.name );
7385 void LegacyReporterAdapter::testCaseStarting( TestCaseInfo
const& testInfo ) {
7386 m_legacyReporter->StartTestCase( testInfo );
7388 void LegacyReporterAdapter::sectionStarting( SectionInfo
const& sectionInfo ) {
7389 m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description );
7391 void LegacyReporterAdapter::assertionStarting( AssertionInfo
const& ) {
7395 bool LegacyReporterAdapter::assertionEnded( AssertionStats
const& assertionStats ) {
7396 if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) {
7397 for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
7400 if( it->type == ResultWas::Info ) {
7401 ResultBuilder rb( it->macroName.c_str(), it->lineInfo,
"", ResultDisposition::Normal );
7403 rb.setResultType( ResultWas::Info );
7404 AssertionResult result = rb.build();
7405 m_legacyReporter->Result( result );
7409 m_legacyReporter->Result( assertionStats.assertionResult );
7412 void LegacyReporterAdapter::sectionEnded( SectionStats
const& sectionStats ) {
7413 if( sectionStats.missingAssertions )
7414 m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name );
7415 m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions );
7417 void LegacyReporterAdapter::testCaseEnded( TestCaseStats
const& testCaseStats ) {
7418 m_legacyReporter->EndTestCase
7419 ( testCaseStats.testInfo,
7420 testCaseStats.totals,
7421 testCaseStats.stdOut,
7422 testCaseStats.stdErr );
7424 void LegacyReporterAdapter::testGroupEnded( TestGroupStats
const& testGroupStats ) {
7425 if( testGroupStats.aborting )
7426 m_legacyReporter->Aborted();
7427 m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals );
7429 void LegacyReporterAdapter::testRunEnded( TestRunStats
const& testRunStats ) {
7430 m_legacyReporter->EndTesting( testRunStats.totals );
7432 void LegacyReporterAdapter::skipTest( TestCaseInfo
const& ) {
7439 #pragma clang diagnostic push
7440 #pragma clang diagnostic ignored "-Wc++11-long-long"
7443 #ifdef CATCH_PLATFORM_WINDOWS
7444 #include <windows.h>
7446 #include <sys/time.h>
7452 #ifdef CATCH_PLATFORM_WINDOWS
7453 uint64_t getCurrentTicks() {
7454 static uint64_t hz=0, hzo=0;
7456 QueryPerformanceFrequency(
reinterpret_cast<LARGE_INTEGER*
>( &hz ) );
7457 QueryPerformanceCounter(
reinterpret_cast<LARGE_INTEGER*
>( &hzo ) );
7460 QueryPerformanceCounter(
reinterpret_cast<LARGE_INTEGER*
>( &t ) );
7461 return ((t-hzo)*1000000)/hz;
7464 uint64_t getCurrentTicks() {
7466 gettimeofday(&t,CATCH_NULL);
7467 return static_cast<uint64_t
>( t.tv_sec ) * 1000000ull +
static_cast<uint64_t
>( t.tv_usec );
7472 void Timer::start() {
7473 m_ticks = getCurrentTicks();
7475 unsigned int Timer::getElapsedMicroseconds()
const {
7476 return static_cast<unsigned int>(getCurrentTicks() - m_ticks);
7478 unsigned int Timer::getElapsedMilliseconds()
const {
7479 return static_cast<unsigned int>(getElapsedMicroseconds()/1000);
7481 double Timer::getElapsedSeconds()
const {
7482 return getElapsedMicroseconds()/1000000.0;
7488 #pragma clang diagnostic pop
7491 #define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED
7495 bool startsWith( std::string
const& s, std::string
const& prefix ) {
7496 return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix;
7498 bool endsWith( std::string
const& s, std::string
const& suffix ) {
7499 return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix;
7501 bool contains( std::string
const& s, std::string
const& infix ) {
7502 return s.find( infix ) != std::string::npos;
7504 void toLowerInPlace( std::string& s ) {
7505 std::transform( s.begin(), s.end(), s.begin(), ::tolower );
7507 std::string toLower( std::string
const& s ) {
7509 toLowerInPlace( lc );
7512 std::string trim( std::string
const& str ) {
7513 static char const* whitespaceChars =
"\n\r\t ";
7514 std::string::size_type start = str.find_first_not_of( whitespaceChars );
7515 std::string::size_type end = str.find_last_not_of( whitespaceChars );
7517 return start != std::string::npos ? str.substr( start, 1+end-start ) :
"";
7520 bool replaceInPlace( std::string& str, std::string
const& replaceThis, std::string
const& withThis ) {
7521 bool replaced =
false;
7522 std::size_t i = str.find( replaceThis );
7523 while( i != std::string::npos ) {
7525 str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() );
7526 if( i < str.size()-withThis.size() )
7527 i = str.find( replaceThis, i+withThis.size() );
7529 i = std::string::npos;
7534 pluralise::pluralise( std::size_t count, std::string
const& label )
7539 std::ostream& operator << ( std::ostream& os, pluralise
const& pluraliser ) {
7540 os << pluraliser.m_count <<
" " << pluraliser.m_label;
7541 if( pluraliser.m_count != 1 )
7546 SourceLineInfo::SourceLineInfo() : line( 0 ){}
7547 SourceLineInfo::SourceLineInfo(
char const* _file, std::size_t _line )
7551 SourceLineInfo::SourceLineInfo( SourceLineInfo
const& other )
7552 : file( other.file ),
7555 bool SourceLineInfo::empty()
const {
7556 return file.empty();
7558 bool SourceLineInfo::operator == ( SourceLineInfo
const& other )
const {
7559 return line == other.line && file == other.file;
7561 bool SourceLineInfo::operator < ( SourceLineInfo
const& other )
const {
7562 return line < other.line || ( line == other.line && file < other.file );
7565 void seedRng( IConfig
const& config ) {
7566 if( config.rngSeed() != 0 )
7567 std::srand( config.rngSeed() );
7569 unsigned int rngSeed() {
7570 return getCurrentContext().getConfig()->rngSeed();
7573 std::ostream& operator << ( std::ostream& os, SourceLineInfo
const& info ) {
7575 os << info.file <<
"(" << info.line <<
")";
7577 os << info.file <<
":" << info.line;
7582 void throwLogicError( std::string
const& message, SourceLineInfo
const& locationInfo ) {
7583 std::ostringstream oss;
7584 oss << locationInfo <<
": Internal Catch error: '" << message <<
"'";
7586 throw std::logic_error( oss.str() );
7591 #define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
7595 SectionInfo::SectionInfo
7596 ( SourceLineInfo
const& _lineInfo,
7597 std::string
const& _name,
7598 std::string
const& _description )
7600 description( _description ),
7601 lineInfo( _lineInfo )
7604 Section::Section( SectionInfo
const& info )
7606 m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) )
7611 Section::~Section() {
7612 if( m_sectionIncluded ) {
7613 SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() );
7614 if( std::uncaught_exception() )
7615 getResultCapture().sectionEndedEarly( endInfo );
7617 getResultCapture().sectionEnded( endInfo );
7622 Section::operator bool()
const {
7623 return m_sectionIncluded;
7629 #define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
7633 #ifdef CATCH_PLATFORM_MAC
7636 #include <stdbool.h>
7637 #include <sys/types.h>
7639 #include <sys/sysctl.h>
7648 bool isDebuggerActive(){
7651 struct kinfo_proc info;
7657 info.kp_proc.p_flag = 0;
7664 mib[2] = KERN_PROC_PID;
7669 size =
sizeof(info);
7670 if( sysctl(mib,
sizeof(mib) /
sizeof(*mib), &info, &size, CATCH_NULL, 0) != 0 ) {
7671 Catch::cerr() <<
"\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl;
7677 return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
7681 #elif defined(_MSC_VER)
7682 extern "C" __declspec(dllimport)
int __stdcall IsDebuggerPresent();
7684 bool isDebuggerActive() {
7685 return IsDebuggerPresent() != 0;
7688 #elif defined(__MINGW32__)
7689 extern "C" __declspec(dllimport)
int __stdcall IsDebuggerPresent();
7691 bool isDebuggerActive() {
7692 return IsDebuggerPresent() != 0;
7697 inline bool isDebuggerActive() {
return false; }
7701 #ifdef CATCH_PLATFORM_WINDOWS
7702 extern "C" __declspec(dllimport)
void __stdcall OutputDebugStringA(
const char* );
7704 void writeToDebugConsole( std::string
const& text ) {
7705 ::OutputDebugStringA( text.c_str() );
7710 void writeToDebugConsole( std::string
const& text ) {
7712 Catch::cout() << text;
7718 #define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED
7724 const std::string unprintableString =
"{?}";
7727 const int hexThreshold = 255;
7730 enum Arch { Big, Little };
7732 static Arch which() {
7735 char asChar[sizeof (int)];
7739 return ( u.asChar[
sizeof(
int)-1] == 1 ) ? Big : Little;
7744 std::string rawMemoryToString(
const void *
object, std::size_t size )
7747 int i = 0, end =
static_cast<int>( size ), inc = 1;
7748 if( Endianness::which() == Endianness::Little ) {
7753 unsigned char const *bytes =
static_cast<unsigned char const *
>(object);
7754 std::ostringstream os;
7755 os <<
"0x" << std::setfill(
'0') << std::hex;
7756 for( ; i != end; i += inc )
7757 os << std::setw(2) << static_cast<unsigned>(bytes[i]);
7762 std::string toString( std::string
const& value ) {
7763 std::string s = value;
7764 if( getCurrentContext().getConfig()->showInvisibles() ) {
7765 for(
size_t i = 0; i < s.size(); ++i ) {
7768 case '\n': subs =
"\\n";
break;
7769 case '\t': subs =
"\\t";
break;
7772 if( !subs.empty() ) {
7773 s = s.substr( 0, i ) + subs + s.substr( i+1 );
7778 return "\"" + s + "\"";
7780 std::string toString( std::wstring
const& value ) {
7783 s.reserve( value.size() );
7784 for(
size_t i = 0; i < value.size(); ++i )
7785 s += value[i] <= 0xff ? static_cast<char>( value[i] ) : '?';
7786 return Catch::toString( s );
7789 std::string toString(
const char*
const value ) {
7790 return value ? Catch::toString( std::string( value ) ) : std::string(
"{null string}" );
7793 std::string toString(
char*
const value ) {
7794 return Catch::toString(
static_cast<const char*
>( value ) );
7797 std::string toString(
const wchar_t*
const value )
7799 return value ? Catch::toString( std::wstring(value) ) : std::string(
"{null string}" );
7802 std::string toString(
wchar_t*
const value )
7804 return Catch::toString(
static_cast<const wchar_t*
>( value ) );
7807 std::string toString(
int value ) {
7808 std::ostringstream oss;
7810 if( value > Detail::hexThreshold )
7811 oss <<
" (0x" << std::hex << value <<
")";
7815 std::string toString(
unsigned long value ) {
7816 std::ostringstream oss;
7818 if( value > Detail::hexThreshold )
7819 oss <<
" (0x" << std::hex << value <<
")";
7823 std::string toString(
unsigned int value ) {
7824 return Catch::toString(
static_cast<unsigned long>( value ) );
7827 template<
typename T>
7828 std::string fpToString( T value,
int precision ) {
7829 std::ostringstream oss;
7830 oss << std::setprecision( precision )
7833 std::string d = oss.str();
7834 std::size_t i = d.find_last_not_of(
'0' );
7835 if( i != std::string::npos && i != d.size()-1 ) {
7838 d = d.substr( 0, i+1 );
7843 std::string toString(
const double value ) {
7844 return fpToString( value, 10 );
7846 std::string toString(
const float value ) {
7847 return fpToString( value, 5 ) + "f";
7850 std::string toString(
bool value ) {
7851 return value ?
"true" :
"false";
7854 std::string toString(
char value ) {
7856 ? toString(
static_cast<unsigned int>( value ) )
7857 : Detail::makeString( value );
7860 std::string toString(
signed char value ) {
7861 return toString(
static_cast<char>( value ) );
7864 std::string toString(
unsigned char value ) {
7865 return toString(
static_cast<char>( value ) );
7868 #ifdef CATCH_CONFIG_CPP11_LONG_LONG
7869 std::string toString(
long long value ) {
7870 std::ostringstream oss;
7872 if( value > Detail::hexThreshold )
7873 oss <<
" (0x" << std::hex << value <<
")";
7876 std::string toString(
unsigned long long value ) {
7877 std::ostringstream oss;
7879 if( value > Detail::hexThreshold )
7880 oss <<
" (0x" << std::hex << value <<
")";
7885 #ifdef CATCH_CONFIG_CPP11_NULLPTR
7886 std::string toString( std::nullptr_t ) {
7892 std::string toString( NSString
const *
const& nsstring ) {
7895 return "@" + toString([nsstring UTF8String]);
7897 std::string toString( NSString * CATCH_ARC_STRONG
const& nsstring ) {
7900 return "@" + toString([nsstring UTF8String]);
7902 std::string toString( NSObject*
const& nsObject ) {
7903 return toString( [nsObject description] );
7910 #define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED
7914 std::string capturedExpressionWithSecondArgument( std::string
const& capturedExpression, std::string
const& secondArg ) {
7915 return secondArg.empty() || secondArg ==
"\"\""
7916 ? capturedExpression
7917 : capturedExpression + ", " + secondArg;
7919 ResultBuilder::ResultBuilder(
char const* macroName,
7920 SourceLineInfo
const& lineInfo,
7921 char const* capturedExpression,
7922 ResultDisposition::Flags resultDisposition,
7923 char const* secondArg )
7924 : m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ),
7925 m_shouldDebugBreak( false ),
7926 m_shouldThrow( false )
7929 ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) {
7930 m_data.resultType = result;
7933 ResultBuilder& ResultBuilder::setResultType(
bool result ) {
7934 m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed;
7937 ResultBuilder& ResultBuilder::setLhs( std::string
const& lhs ) {
7938 m_exprComponents.lhs = lhs;
7941 ResultBuilder& ResultBuilder::setRhs( std::string
const& rhs ) {
7942 m_exprComponents.rhs = rhs;
7945 ResultBuilder& ResultBuilder::setOp( std::string
const& op ) {
7946 m_exprComponents.op = op;
7950 void ResultBuilder::endExpression() {
7951 m_exprComponents.testFalse = isFalseTest( m_assertionInfo.resultDisposition );
7952 captureExpression();
7955 void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) {
7956 m_assertionInfo.resultDisposition = resultDisposition;
7957 m_stream.oss << Catch::translateActiveException();
7958 captureResult( ResultWas::ThrewException );
7961 void ResultBuilder::captureResult( ResultWas::OfType resultType ) {
7962 setResultType( resultType );
7963 captureExpression();
7965 void ResultBuilder::captureExpectedException( std::string
const& expectedMessage ) {
7966 if( expectedMessage.empty() )
7967 captureExpectedException( Matchers::Impl::Generic::AllOf<std::string>() );
7969 captureExpectedException( Matchers::Equals( expectedMessage ) );
7972 void ResultBuilder::captureExpectedException( Matchers::Impl::Matcher<std::string>
const& matcher ) {
7974 assert( m_exprComponents.testFalse ==
false );
7975 AssertionResultData data = m_data;
7976 data.resultType = ResultWas::Ok;
7977 data.reconstructedExpression = m_assertionInfo.capturedExpression;
7979 std::string actualMessage = Catch::translateActiveException();
7980 if( !matcher.match( actualMessage ) ) {
7981 data.resultType = ResultWas::ExpressionFailed;
7982 data.reconstructedExpression = actualMessage;
7984 AssertionResult result( m_assertionInfo, data );
7985 handleResult( result );
7988 void ResultBuilder::captureExpression() {
7989 AssertionResult result = build();
7990 handleResult( result );
7992 void ResultBuilder::handleResult( AssertionResult
const& result )
7994 getResultCapture().assertionEnded( result );
7996 if( !result.isOk() ) {
7997 if( getCurrentContext().getConfig()->shouldDebugBreak() )
7998 m_shouldDebugBreak =
true;
7999 if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) )
8000 m_shouldThrow =
true;
8003 void ResultBuilder::react() {
8008 bool ResultBuilder::shouldDebugBreak()
const {
return m_shouldDebugBreak; }
8009 bool ResultBuilder::allowThrows()
const {
return getCurrentContext().getConfig()->allowThrows(); }
8011 AssertionResult ResultBuilder::build()
const
8013 assert( m_data.resultType != ResultWas::Unknown );
8015 AssertionResultData data = m_data;
8018 if( m_exprComponents.testFalse ) {
8019 if( data.resultType == ResultWas::Ok )
8020 data.resultType = ResultWas::ExpressionFailed;
8021 else if( data.resultType == ResultWas::ExpressionFailed )
8022 data.resultType = ResultWas::Ok;
8025 data.message = m_stream.oss.str();
8026 data.reconstructedExpression = reconstructExpression();
8027 if( m_exprComponents.testFalse ) {
8028 if( m_exprComponents.op ==
"" )
8029 data.reconstructedExpression =
"!" + data.reconstructedExpression;
8031 data.reconstructedExpression =
"!(" + data.reconstructedExpression + ")";
8033 return AssertionResult( m_assertionInfo, data );
8035 std::string ResultBuilder::reconstructExpression()
const {
8036 if( m_exprComponents.op ==
"" )
8037 return m_exprComponents.lhs.empty() ? m_assertionInfo.capturedExpression : m_exprComponents.op + m_exprComponents.lhs;
8038 else if( m_exprComponents.op ==
"matches" )
8039 return m_exprComponents.lhs + " " + m_exprComponents.rhs;
8040 else if( m_exprComponents.op !=
"!" ) {
8041 if( m_exprComponents.lhs.size() + m_exprComponents.rhs.size() < 40 &&
8042 m_exprComponents.lhs.find(
"\n") == std::string::npos &&
8043 m_exprComponents.rhs.find(
"\n") == std::string::npos )
8044 return m_exprComponents.lhs + " " + m_exprComponents.op + " " + m_exprComponents.rhs;
8046 return m_exprComponents.lhs + "\n" + m_exprComponents.op + "\n" + m_exprComponents.rhs;
8049 return "{can't expand - use " + m_assertionInfo.macroName + "_FALSE( " + m_assertionInfo.capturedExpression.substr(1) + " ) instead of " + m_assertionInfo.macroName + "( " + m_assertionInfo.capturedExpression + " ) for better diagnostics}";
8055 #define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED
8058 #define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED
8064 class TagAliasRegistry :
public ITagAliasRegistry {
8066 virtual ~TagAliasRegistry();
8067 virtual Option<TagAlias> find( std::string
const& alias )
const;
8068 virtual std::string expandAliases( std::string
const& unexpandedTestSpec )
const;
8069 void add(
char const* alias,
char const* tag, SourceLineInfo
const& lineInfo );
8070 static TagAliasRegistry& get();
8073 std::map<std::string, TagAlias> m_registry;
8083 TagAliasRegistry::~TagAliasRegistry() {}
8085 Option<TagAlias> TagAliasRegistry::find( std::string
const& alias )
const {
8086 std::map<std::string, TagAlias>::const_iterator it = m_registry.find( alias );
8087 if( it != m_registry.end() )
8090 return Option<TagAlias>();
8093 std::string TagAliasRegistry::expandAliases( std::string
const& unexpandedTestSpec )
const {
8094 std::string expandedTestSpec = unexpandedTestSpec;
8095 for( std::map<std::string, TagAlias>::const_iterator it = m_registry.begin(), itEnd = m_registry.end();
8098 std::size_t pos = expandedTestSpec.find( it->first );
8099 if( pos != std::string::npos ) {
8100 expandedTestSpec = expandedTestSpec.substr( 0, pos ) +
8102 expandedTestSpec.substr( pos + it->first.size() );
8105 return expandedTestSpec;
8108 void TagAliasRegistry::add(
char const* alias,
char const* tag, SourceLineInfo
const& lineInfo ) {
8110 if( !startsWith( alias,
"[@" ) || !endsWith( alias,
"]" ) ) {
8111 std::ostringstream oss;
8112 oss <<
"error: tag alias, \"" << alias <<
"\" is not of the form [@alias name].\n" << lineInfo;
8113 throw std::domain_error( oss.str().c_str() );
8115 if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) {
8116 std::ostringstream oss;
8117 oss <<
"error: tag alias, \"" << alias <<
"\" already registered.\n"
8118 <<
"\tFirst seen at " << find(alias)->lineInfo <<
"\n"
8119 <<
"\tRedefined at " << lineInfo;
8120 throw std::domain_error( oss.str().c_str() );
8124 TagAliasRegistry& TagAliasRegistry::get() {
8125 static TagAliasRegistry instance;
8130 ITagAliasRegistry::~ITagAliasRegistry() {}
8131 ITagAliasRegistry
const& ITagAliasRegistry::get() {
return TagAliasRegistry::get(); }
8133 RegistrarForTagAliases::RegistrarForTagAliases(
char const* alias,
char const* tag, SourceLineInfo
const& lineInfo ) {
8135 TagAliasRegistry::get().add( alias, tag, lineInfo );
8137 catch( std::exception& ex ) {
8138 Colour colourGuard( Colour::Red );
8139 Catch::cerr() << ex.what() << std::endl;
8147 #define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED
8151 class MultipleReporters :
public SharedImpl<IStreamingReporter> {
8152 typedef std::vector<Ptr<IStreamingReporter> > Reporters;
8153 Reporters m_reporters;
8156 void add( Ptr<IStreamingReporter>
const& reporter ) {
8157 m_reporters.push_back( reporter );
8162 virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
8163 return m_reporters[0]->getPreferences();
8166 virtual void noMatchingTestCases( std::string
const& spec ) CATCH_OVERRIDE {
8167 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8170 (*it)->noMatchingTestCases( spec );
8173 virtual void testRunStarting( TestRunInfo
const& testRunInfo ) CATCH_OVERRIDE {
8174 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8177 (*it)->testRunStarting( testRunInfo );
8180 virtual void testGroupStarting( GroupInfo
const& groupInfo ) CATCH_OVERRIDE {
8181 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8184 (*it)->testGroupStarting( groupInfo );
8187 virtual void testCaseStarting( TestCaseInfo
const& testInfo ) CATCH_OVERRIDE {
8188 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8191 (*it)->testCaseStarting( testInfo );
8194 virtual void sectionStarting( SectionInfo
const& sectionInfo ) CATCH_OVERRIDE {
8195 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8198 (*it)->sectionStarting( sectionInfo );
8201 virtual void assertionStarting( AssertionInfo
const& assertionInfo ) CATCH_OVERRIDE {
8202 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8205 (*it)->assertionStarting( assertionInfo );
8209 virtual bool assertionEnded( AssertionStats
const& assertionStats ) CATCH_OVERRIDE {
8210 bool clearBuffer =
false;
8211 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8214 clearBuffer |= (*it)->assertionEnded( assertionStats );
8218 virtual void sectionEnded( SectionStats
const& sectionStats ) CATCH_OVERRIDE {
8219 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8222 (*it)->sectionEnded( sectionStats );
8225 virtual void testCaseEnded( TestCaseStats
const& testCaseStats ) CATCH_OVERRIDE {
8226 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8229 (*it)->testCaseEnded( testCaseStats );
8232 virtual void testGroupEnded( TestGroupStats
const& testGroupStats ) CATCH_OVERRIDE {
8233 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8236 (*it)->testGroupEnded( testGroupStats );
8239 virtual void testRunEnded( TestRunStats
const& testRunStats ) CATCH_OVERRIDE {
8240 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8243 (*it)->testRunEnded( testRunStats );
8246 virtual void skipTest( TestCaseInfo
const& testInfo ) CATCH_OVERRIDE {
8247 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8250 (*it)->skipTest( testInfo );
8254 Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter>
const& existingReporter, Ptr<IStreamingReporter>
const& additionalReporter ) {
8255 Ptr<IStreamingReporter> resultingReporter;
8257 if( existingReporter ) {
8258 MultipleReporters* multi =
dynamic_cast<MultipleReporters*
>( existingReporter.get() );
8260 multi =
new MultipleReporters;
8261 resultingReporter = Ptr<IStreamingReporter>( multi );
8262 if( existingReporter )
8263 multi->add( existingReporter );
8266 resultingReporter = existingReporter;
8267 multi->add( additionalReporter );
8270 resultingReporter = additionalReporter;
8272 return resultingReporter;
8278 #define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
8281 #define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
8287 struct StreamingReporterBase : SharedImpl<IStreamingReporter> {
8289 StreamingReporterBase( ReporterConfig
const& _config )
8290 : m_config( _config.fullConfig() ),
8291 stream( _config.stream() )
8293 m_reporterPrefs.shouldRedirectStdOut =
false;
8296 virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
8297 return m_reporterPrefs;
8300 virtual ~StreamingReporterBase() CATCH_OVERRIDE;
8302 virtual
void noMatchingTestCases( std::
string const& ) CATCH_OVERRIDE {}
8304 virtual void testRunStarting( TestRunInfo
const& _testRunInfo ) CATCH_OVERRIDE {
8305 currentTestRunInfo = _testRunInfo;
8307 virtual void testGroupStarting( GroupInfo
const& _groupInfo ) CATCH_OVERRIDE {
8308 currentGroupInfo = _groupInfo;
8311 virtual void testCaseStarting( TestCaseInfo
const& _testInfo ) CATCH_OVERRIDE {
8312 currentTestCaseInfo = _testInfo;
8314 virtual void sectionStarting( SectionInfo
const& _sectionInfo ) CATCH_OVERRIDE {
8315 m_sectionStack.push_back( _sectionInfo );
8318 virtual void sectionEnded( SectionStats
const& ) CATCH_OVERRIDE {
8319 m_sectionStack.pop_back();
8321 virtual void testCaseEnded( TestCaseStats
const& ) CATCH_OVERRIDE {
8322 currentTestCaseInfo.reset();
8324 virtual void testGroupEnded( TestGroupStats
const& ) CATCH_OVERRIDE {
8325 currentGroupInfo.reset();
8327 virtual void testRunEnded( TestRunStats
const& ) CATCH_OVERRIDE {
8328 currentTestCaseInfo.reset();
8329 currentGroupInfo.reset();
8330 currentTestRunInfo.reset();
8333 virtual void skipTest( TestCaseInfo
const& ) CATCH_OVERRIDE {
8338 Ptr<IConfig const> m_config;
8339 std::ostream& stream;
8341 LazyStat<TestRunInfo> currentTestRunInfo;
8342 LazyStat<GroupInfo> currentGroupInfo;
8343 LazyStat<TestCaseInfo> currentTestCaseInfo;
8345 std::vector<SectionInfo> m_sectionStack;
8346 ReporterPreferences m_reporterPrefs;
8349 struct CumulativeReporterBase : SharedImpl<IStreamingReporter> {
8350 template<
typename T,
typename ChildNodeT>
8351 struct Node : SharedImpl<> {
8352 explicit Node( T
const& _value ) : value( _value ) {}
8355 typedef std::vector<Ptr<ChildNodeT> > ChildNodes;
8357 ChildNodes children;
8359 struct SectionNode : SharedImpl<> {
8360 explicit SectionNode( SectionStats
const& _stats ) : stats( _stats ) {}
8361 virtual ~SectionNode();
8363 bool operator == ( SectionNode
const& other )
const {
8364 return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
8366 bool operator == ( Ptr<SectionNode>
const& other )
const {
8367 return operator==( *other );
8371 typedef std::vector<Ptr<SectionNode> > ChildSections;
8372 typedef std::vector<AssertionStats> Assertions;
8373 ChildSections childSections;
8374 Assertions assertions;
8379 struct BySectionInfo {
8380 BySectionInfo( SectionInfo
const& other ) : m_other( other ) {}
8381 BySectionInfo( BySectionInfo
const& other ) : m_other( other.m_other ) {}
8382 bool operator() ( Ptr<SectionNode>
const& node )
const {
8383 return node->stats.sectionInfo.lineInfo == m_other.lineInfo;
8386 void operator=( BySectionInfo
const& );
8387 SectionInfo
const& m_other;
8390 typedef Node<TestCaseStats, SectionNode> TestCaseNode;
8391 typedef Node<TestGroupStats, TestCaseNode> TestGroupNode;
8392 typedef Node<TestRunStats, TestGroupNode> TestRunNode;
8394 CumulativeReporterBase( ReporterConfig
const& _config )
8395 : m_config( _config.fullConfig() ),
8396 stream( _config.stream() )
8398 m_reporterPrefs.shouldRedirectStdOut =
false;
8400 ~CumulativeReporterBase();
8402 virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
8403 return m_reporterPrefs;
8406 virtual void testRunStarting( TestRunInfo
const& ) CATCH_OVERRIDE {}
8407 virtual void testGroupStarting( GroupInfo
const& ) CATCH_OVERRIDE {}
8409 virtual void testCaseStarting( TestCaseInfo
const& ) CATCH_OVERRIDE {}
8411 virtual void sectionStarting( SectionInfo
const& sectionInfo ) CATCH_OVERRIDE {
8412 SectionStats incompleteStats( sectionInfo, Counts(), 0,
false );
8413 Ptr<SectionNode> node;
8414 if( m_sectionStack.empty() ) {
8415 if( !m_rootSection )
8416 m_rootSection =
new SectionNode( incompleteStats );
8417 node = m_rootSection;
8420 SectionNode& parentNode = *m_sectionStack.back();
8421 SectionNode::ChildSections::const_iterator it =
8422 std::find_if( parentNode.childSections.begin(),
8423 parentNode.childSections.end(),
8424 BySectionInfo( sectionInfo ) );
8425 if( it == parentNode.childSections.end() ) {
8426 node =
new SectionNode( incompleteStats );
8427 parentNode.childSections.push_back( node );
8432 m_sectionStack.push_back( node );
8433 m_deepestSection = node;
8436 virtual void assertionStarting( AssertionInfo
const& ) CATCH_OVERRIDE {}
8438 virtual bool assertionEnded( AssertionStats
const& assertionStats ) {
8439 assert( !m_sectionStack.empty() );
8440 SectionNode& sectionNode = *m_sectionStack.back();
8441 sectionNode.assertions.push_back( assertionStats );
8444 virtual void sectionEnded( SectionStats
const& sectionStats ) CATCH_OVERRIDE {
8445 assert( !m_sectionStack.empty() );
8446 SectionNode& node = *m_sectionStack.back();
8447 node.stats = sectionStats;
8448 m_sectionStack.pop_back();
8450 virtual void testCaseEnded( TestCaseStats
const& testCaseStats ) CATCH_OVERRIDE {
8451 Ptr<TestCaseNode> node =
new TestCaseNode( testCaseStats );
8452 assert( m_sectionStack.size() == 0 );
8453 node->children.push_back( m_rootSection );
8454 m_testCases.push_back( node );
8455 m_rootSection.reset();
8457 assert( m_deepestSection );
8458 m_deepestSection->stdOut = testCaseStats.stdOut;
8459 m_deepestSection->stdErr = testCaseStats.stdErr;
8461 virtual void testGroupEnded( TestGroupStats
const& testGroupStats ) CATCH_OVERRIDE {
8462 Ptr<TestGroupNode> node =
new TestGroupNode( testGroupStats );
8463 node->children.swap( m_testCases );
8464 m_testGroups.push_back( node );
8466 virtual void testRunEnded( TestRunStats
const& testRunStats ) CATCH_OVERRIDE {
8467 Ptr<TestRunNode> node =
new TestRunNode( testRunStats );
8468 node->children.swap( m_testGroups );
8469 m_testRuns.push_back( node );
8470 testRunEndedCumulative();
8472 virtual void testRunEndedCumulative() = 0;
8474 virtual void skipTest( TestCaseInfo
const& ) CATCH_OVERRIDE {}
8476 Ptr<IConfig const> m_config;
8477 std::ostream& stream;
8478 std::vector<AssertionStats> m_assertions;
8479 std::vector<std::vector<Ptr<SectionNode> > > m_sections;
8480 std::vector<Ptr<TestCaseNode> > m_testCases;
8481 std::vector<Ptr<TestGroupNode> > m_testGroups;
8483 std::vector<Ptr<TestRunNode> > m_testRuns;
8485 Ptr<SectionNode> m_rootSection;
8486 Ptr<SectionNode> m_deepestSection;
8487 std::vector<Ptr<SectionNode> > m_sectionStack;
8488 ReporterPreferences m_reporterPrefs;
8493 char const* getLineOfChars() {
8494 static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0};
8496 memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 );
8497 line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0;
8502 struct TestEventListenerBase : StreamingReporterBase {
8503 TestEventListenerBase( ReporterConfig
const& _config )
8504 : StreamingReporterBase( _config )
8507 virtual void assertionStarting( AssertionInfo
const& ) CATCH_OVERRIDE {}
8508 virtual bool assertionEnded( AssertionStats
const& ) CATCH_OVERRIDE {
8516 #define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
8520 template<
typename T>
8521 class LegacyReporterRegistrar {
8523 class ReporterFactory :
public IReporterFactory {
8524 virtual IStreamingReporter* create( ReporterConfig
const& config )
const {
8525 return new LegacyReporterAdapter(
new T( config ) );
8528 virtual std::string getDescription()
const {
8529 return T::getDescription();
8535 LegacyReporterRegistrar( std::string
const& name ) {
8536 getMutableRegistryHub().registerReporter( name,
new ReporterFactory() );
8540 template<
typename T>
8541 class ReporterRegistrar {
8543 class ReporterFactory :
public SharedImpl<IReporterFactory> {
8556 virtual IStreamingReporter* create( ReporterConfig
const& config )
const {
8557 return new T( config );
8560 virtual std::string getDescription()
const {
8561 return T::getDescription();
8567 ReporterRegistrar( std::string
const& name ) {
8568 getMutableRegistryHub().registerReporter( name,
new ReporterFactory() );
8572 template<
typename T>
8573 class ListenerRegistrar {
8575 class ListenerFactory :
public SharedImpl<IReporterFactory> {
8577 virtual IStreamingReporter* create( ReporterConfig
const& config )
const {
8578 return new T( config );
8580 virtual std::string getDescription()
const {
8587 ListenerRegistrar() {
8588 getMutableRegistryHub().registerListener(
new ListenerFactory() );
8593 #define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \
8594 namespace{ Catch::LegacyReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
8596 #define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
8597 namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
8599 #define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \
8600 namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; }
8603 #define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
8614 enum ForWhat { ForTextNodes, ForAttributes };
8616 XmlEncode( std::string
const& str, ForWhat forWhat = ForTextNodes )
8618 m_forWhat( forWhat )
8621 void encodeTo( std::ostream& os )
const {
8626 for( std::size_t i = 0; i < m_str.size(); ++ i ) {
8629 case '<': os <<
"<";
break;
8630 case '&': os <<
"&";
break;
8634 if( i > 2 && m_str[i-1] ==
']' && m_str[i-2] ==
']' )
8641 if( m_forWhat == ForAttributes )
8649 if ( ( c <
'\x09' ) || ( c >
'\x0D' && c <
'\x20') || c==
'\x7F' )
8650 os <<
"&#x" << std::uppercase << std::hex <<
static_cast<int>( c );
8657 friend std::ostream& operator << ( std::ostream& os, XmlEncode
const& xmlEncode ) {
8658 xmlEncode.encodeTo( os );
8670 class ScopedElement {
8672 ScopedElement( XmlWriter* writer )
8673 : m_writer( writer )
8676 ScopedElement( ScopedElement
const& other )
8677 : m_writer( other.m_writer ){
8678 other.m_writer = CATCH_NULL;
8683 m_writer->endElement();
8686 ScopedElement& writeText( std::string
const& text,
bool indent =
true ) {
8687 m_writer->writeText( text, indent );
8691 template<
typename T>
8692 ScopedElement& writeAttribute( std::string
const& name, T
const& attribute ) {
8693 m_writer->writeAttribute( name, attribute );
8698 mutable XmlWriter* m_writer;
8702 : m_tagIsOpen( false ),
8703 m_needsNewline( false ),
8704 m_os( &Catch::cout() )
8707 XmlWriter( std::ostream& os )
8708 : m_tagIsOpen( false ),
8709 m_needsNewline( false ),
8714 while( !m_tags.empty() )
8718 XmlWriter& startElement( std::string
const& name ) {
8720 newlineIfNecessary();
8721 stream() << m_indent <<
"<" << name;
8722 m_tags.push_back( name );
8728 ScopedElement scopedElement( std::string
const& name ) {
8729 ScopedElement scoped(
this );
8730 startElement( name );
8734 XmlWriter& endElement() {
8735 newlineIfNecessary();
8736 m_indent = m_indent.substr( 0, m_indent.size()-2 );
8739 m_tagIsOpen =
false;
8742 stream() << m_indent <<
"</" << m_tags.back() <<
">\n";
8748 XmlWriter& writeAttribute( std::string
const& name, std::string
const& attribute ) {
8749 if( !name.empty() && !attribute.empty() )
8750 stream() <<
" " << name <<
"=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) <<
"\"";
8754 XmlWriter& writeAttribute( std::string
const& name,
bool attribute ) {
8755 stream() <<
" " << name <<
"=\"" << ( attribute ?
"true" :
"false" ) <<
"\"";
8759 template<
typename T>
8760 XmlWriter& writeAttribute( std::string
const& name, T
const& attribute ) {
8761 std::ostringstream oss;
8763 return writeAttribute( name, oss.str() );
8766 XmlWriter& writeText( std::string
const& text,
bool indent =
true ) {
8767 if( !text.empty() ){
8768 bool tagWasOpen = m_tagIsOpen;
8770 if( tagWasOpen && indent )
8771 stream() << m_indent;
8772 stream() << XmlEncode( text );
8773 m_needsNewline =
true;
8778 XmlWriter& writeComment( std::string
const& text ) {
8780 stream() << m_indent <<
"<!--" << text <<
"-->";
8781 m_needsNewline =
true;
8785 XmlWriter& writeBlankLine() {
8791 void setStream( std::ostream& os ) {
8796 XmlWriter( XmlWriter
const& );
8797 void operator=( XmlWriter
const& );
8799 std::ostream& stream() {
8803 void ensureTagClosed() {
8806 m_tagIsOpen =
false;
8810 void newlineIfNecessary() {
8811 if( m_needsNewline ) {
8813 m_needsNewline =
false;
8818 bool m_needsNewline;
8819 std::vector<std::string> m_tags;
8820 std::string m_indent;
8827 #define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED
8831 # pragma warning(pop)
8833 # pragma clang diagnostic pop
8835 #elif defined __GNUC__
8836 # pragma GCC diagnostic pop
8841 class XmlReporter :
public StreamingReporterBase {
8843 XmlReporter( ReporterConfig
const& _config )
8844 : StreamingReporterBase( _config ),
8847 m_reporterPrefs.shouldRedirectStdOut =
true;
8850 virtual ~XmlReporter() CATCH_OVERRIDE;
8852 static std::
string getDescription() {
8853 return "Reports test results as an XML document";
8858 virtual void noMatchingTestCases( std::string
const& s ) CATCH_OVERRIDE {
8859 StreamingReporterBase::noMatchingTestCases( s );
8862 virtual void testRunStarting( TestRunInfo
const& testInfo ) CATCH_OVERRIDE {
8863 StreamingReporterBase::testRunStarting( testInfo );
8864 m_xml.setStream( stream );
8865 m_xml.startElement(
"Catch" );
8866 if( !m_config->name().empty() )
8867 m_xml.writeAttribute(
"name", m_config->name() );
8870 virtual void testGroupStarting( GroupInfo
const& groupInfo ) CATCH_OVERRIDE {
8871 StreamingReporterBase::testGroupStarting( groupInfo );
8872 m_xml.startElement(
"Group" )
8873 .writeAttribute(
"name", groupInfo.name );
8876 virtual void testCaseStarting( TestCaseInfo
const& testInfo ) CATCH_OVERRIDE {
8877 StreamingReporterBase::testCaseStarting(testInfo);
8878 m_xml.startElement(
"TestCase" ).writeAttribute(
"name", trim( testInfo.name ) );
8880 if ( m_config->showDurations() == ShowDurations::Always )
8881 m_testCaseTimer.start();
8884 virtual void sectionStarting( SectionInfo
const& sectionInfo ) CATCH_OVERRIDE {
8885 StreamingReporterBase::sectionStarting( sectionInfo );
8886 if( m_sectionDepth++ > 0 ) {
8887 m_xml.startElement(
"Section" )
8888 .writeAttribute(
"name", trim( sectionInfo.name ) )
8889 .writeAttribute(
"description", sectionInfo.description );
8893 virtual void assertionStarting( AssertionInfo
const& ) CATCH_OVERRIDE { }
8895 virtual bool assertionEnded( AssertionStats
const& assertionStats ) CATCH_OVERRIDE {
8896 const AssertionResult& assertionResult = assertionStats.assertionResult;
8899 if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) {
8900 for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
8903 if( it->type == ResultWas::Info ) {
8904 m_xml.scopedElement(
"Info" )
8905 .writeText( it->message );
8906 }
else if ( it->type == ResultWas::Warning ) {
8907 m_xml.scopedElement(
"Warning" )
8908 .writeText( it->message );
8914 if( !m_config->includeSuccessfulResults() && isOk(assertionResult.getResultType()) )
8918 if( assertionResult.hasExpression() ) {
8919 m_xml.startElement(
"Expression" )
8920 .writeAttribute(
"success", assertionResult.succeeded() )
8921 .writeAttribute(
"type", assertionResult.getTestMacroName() )
8922 .writeAttribute(
"filename", assertionResult.getSourceInfo().file )
8923 .writeAttribute(
"line", assertionResult.getSourceInfo().line );
8925 m_xml.scopedElement(
"Original" )
8926 .writeText( assertionResult.getExpression() );
8927 m_xml.scopedElement(
"Expanded" )
8928 .writeText( assertionResult.getExpandedExpression() );
8932 switch( assertionResult.getResultType() ) {
8933 case ResultWas::ThrewException:
8934 m_xml.scopedElement(
"Exception" )
8935 .writeAttribute(
"filename", assertionResult.getSourceInfo().file )
8936 .writeAttribute(
"line", assertionResult.getSourceInfo().line )
8937 .writeText( assertionResult.getMessage() );
8939 case ResultWas::FatalErrorCondition:
8940 m_xml.scopedElement(
"Fatal Error Condition" )
8941 .writeAttribute(
"filename", assertionResult.getSourceInfo().file )
8942 .writeAttribute(
"line", assertionResult.getSourceInfo().line )
8943 .writeText( assertionResult.getMessage() );
8945 case ResultWas::Info:
8946 m_xml.scopedElement(
"Info" )
8947 .writeText( assertionResult.getMessage() );
8949 case ResultWas::Warning:
8952 case ResultWas::ExplicitFailure:
8953 m_xml.scopedElement(
"Failure" )
8954 .writeText( assertionResult.getMessage() );
8960 if( assertionResult.hasExpression() )
8966 virtual void sectionEnded( SectionStats
const& sectionStats ) CATCH_OVERRIDE {
8967 StreamingReporterBase::sectionEnded( sectionStats );
8968 if( --m_sectionDepth > 0 ) {
8969 XmlWriter::ScopedElement e = m_xml.scopedElement(
"OverallResults" );
8970 e.writeAttribute(
"successes", sectionStats.assertions.passed );
8971 e.writeAttribute(
"failures", sectionStats.assertions.failed );
8972 e.writeAttribute(
"expectedFailures", sectionStats.assertions.failedButOk );
8974 if ( m_config->showDurations() == ShowDurations::Always )
8975 e.writeAttribute(
"durationInSeconds", sectionStats.durationInSeconds );
8981 virtual void testCaseEnded( TestCaseStats
const& testCaseStats ) CATCH_OVERRIDE {
8982 StreamingReporterBase::testCaseEnded( testCaseStats );
8983 XmlWriter::ScopedElement e = m_xml.scopedElement(
"OverallResult" );
8984 e.writeAttribute(
"success", testCaseStats.totals.assertions.allOk() );
8986 if ( m_config->showDurations() == ShowDurations::Always )
8987 e.writeAttribute(
"durationInSeconds", m_testCaseTimer.getElapsedSeconds() );
8992 virtual void testGroupEnded( TestGroupStats
const& testGroupStats ) CATCH_OVERRIDE {
8993 StreamingReporterBase::testGroupEnded( testGroupStats );
8995 m_xml.scopedElement(
"OverallResults" )
8996 .writeAttribute(
"successes", testGroupStats.totals.assertions.passed )
8997 .writeAttribute(
"failures", testGroupStats.totals.assertions.failed )
8998 .writeAttribute(
"expectedFailures", testGroupStats.totals.assertions.failedButOk );
9002 virtual void testRunEnded( TestRunStats
const& testRunStats ) CATCH_OVERRIDE {
9003 StreamingReporterBase::testRunEnded( testRunStats );
9004 m_xml.scopedElement(
"OverallResults" )
9005 .writeAttribute(
"successes", testRunStats.totals.assertions.passed )
9006 .writeAttribute(
"failures", testRunStats.totals.assertions.failed )
9007 .writeAttribute(
"expectedFailures", testRunStats.totals.assertions.failedButOk );
9012 Timer m_testCaseTimer;
9017 INTERNAL_CATCH_REGISTER_REPORTER(
"xml", XmlReporter )
9022 #define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED
9028 class JunitReporter :
public CumulativeReporterBase {
9030 JunitReporter( ReporterConfig
const& _config )
9031 : CumulativeReporterBase( _config ),
9032 xml( _config.stream() )
9034 m_reporterPrefs.shouldRedirectStdOut =
true;
9037 virtual ~JunitReporter() CATCH_OVERRIDE;
9039 static std::
string getDescription() {
9040 return "Reports test results in an XML format that looks like Ant's junitreport target";
9043 virtual void noMatchingTestCases( std::string
const& ) CATCH_OVERRIDE {}
9045 virtual void testRunStarting( TestRunInfo
const& runInfo ) CATCH_OVERRIDE {
9046 CumulativeReporterBase::testRunStarting( runInfo );
9047 xml.startElement(
"testsuites" );
9050 virtual void testGroupStarting( GroupInfo
const& groupInfo ) CATCH_OVERRIDE {
9052 stdOutForSuite.str(
"");
9053 stdErrForSuite.str(
"");
9054 unexpectedExceptions = 0;
9055 CumulativeReporterBase::testGroupStarting( groupInfo );
9058 virtual bool assertionEnded( AssertionStats
const& assertionStats ) CATCH_OVERRIDE {
9059 if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException )
9060 unexpectedExceptions++;
9061 return CumulativeReporterBase::assertionEnded( assertionStats );
9064 virtual void testCaseEnded( TestCaseStats
const& testCaseStats ) CATCH_OVERRIDE {
9065 stdOutForSuite << testCaseStats.stdOut;
9066 stdErrForSuite << testCaseStats.stdErr;
9067 CumulativeReporterBase::testCaseEnded( testCaseStats );
9070 virtual void testGroupEnded( TestGroupStats
const& testGroupStats ) CATCH_OVERRIDE {
9071 double suiteTime = suiteTimer.getElapsedSeconds();
9072 CumulativeReporterBase::testGroupEnded( testGroupStats );
9073 writeGroup( *m_testGroups.back(), suiteTime );
9076 virtual void testRunEndedCumulative() CATCH_OVERRIDE {
9080 void writeGroup( TestGroupNode
const& groupNode,
double suiteTime ) {
9081 XmlWriter::ScopedElement e = xml.scopedElement(
"testsuite" );
9082 TestGroupStats
const& stats = groupNode.value;
9083 xml.writeAttribute(
"name", stats.groupInfo.name );
9084 xml.writeAttribute(
"errors", unexpectedExceptions );
9085 xml.writeAttribute(
"failures", stats.totals.assertions.failed-unexpectedExceptions );
9086 xml.writeAttribute(
"tests", stats.totals.assertions.total() );
9087 xml.writeAttribute(
"hostname",
"tbd" );
9088 if( m_config->showDurations() == ShowDurations::Never )
9089 xml.writeAttribute(
"time",
"" );
9091 xml.writeAttribute(
"time", suiteTime );
9092 xml.writeAttribute(
"timestamp",
"tbd" );
9095 for( TestGroupNode::ChildNodes::const_iterator
9096 it = groupNode.children.begin(), itEnd = groupNode.children.end();
9099 writeTestCase( **it );
9101 xml.scopedElement(
"system-out" ).writeText( trim( stdOutForSuite.str() ),
false );
9102 xml.scopedElement(
"system-err" ).writeText( trim( stdErrForSuite.str() ),
false );
9105 void writeTestCase( TestCaseNode
const& testCaseNode ) {
9106 TestCaseStats
const& stats = testCaseNode.value;
9110 assert( testCaseNode.children.size() == 1 );
9111 SectionNode
const& rootSection = *testCaseNode.children.front();
9113 std::string className = stats.testInfo.className;
9115 if( className.empty() ) {
9116 if( rootSection.childSections.empty() )
9117 className =
"global";
9119 writeSection( className,
"", rootSection );
9122 void writeSection( std::string
const& className,
9123 std::string
const& rootName,
9124 SectionNode
const& sectionNode ) {
9125 std::string name = trim( sectionNode.stats.sectionInfo.name );
9126 if( !rootName.empty() )
9127 name = rootName + "/" + name;
9129 if( !sectionNode.assertions.empty() ||
9130 !sectionNode.stdOut.empty() ||
9131 !sectionNode.stdErr.empty() ) {
9132 XmlWriter::ScopedElement e = xml.scopedElement(
"testcase" );
9133 if( className.empty() ) {
9134 xml.writeAttribute(
"classname", name );
9135 xml.writeAttribute(
"name",
"root" );
9138 xml.writeAttribute(
"classname", className );
9139 xml.writeAttribute(
"name", name );
9141 xml.writeAttribute(
"time", Catch::toString( sectionNode.stats.durationInSeconds ) );
9143 writeAssertions( sectionNode );
9145 if( !sectionNode.stdOut.empty() )
9146 xml.scopedElement(
"system-out" ).writeText( trim( sectionNode.stdOut ),
false );
9147 if( !sectionNode.stdErr.empty() )
9148 xml.scopedElement(
"system-err" ).writeText( trim( sectionNode.stdErr ),
false );
9150 for( SectionNode::ChildSections::const_iterator
9151 it = sectionNode.childSections.begin(),
9152 itEnd = sectionNode.childSections.end();
9155 if( className.empty() )
9156 writeSection( name,
"", **it );
9158 writeSection( className, name, **it );
9161 void writeAssertions( SectionNode
const& sectionNode ) {
9162 for( SectionNode::Assertions::const_iterator
9163 it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end();
9166 writeAssertion( *it );
9168 void writeAssertion( AssertionStats
const& stats ) {
9169 AssertionResult
const& result = stats.assertionResult;
9170 if( !result.isOk() ) {
9171 std::string elementName;
9172 switch( result.getResultType() ) {
9173 case ResultWas::ThrewException:
9174 case ResultWas::FatalErrorCondition:
9175 elementName =
"error";
9177 case ResultWas::ExplicitFailure:
9178 elementName =
"failure";
9180 case ResultWas::ExpressionFailed:
9181 elementName =
"failure";
9183 case ResultWas::DidntThrowException:
9184 elementName =
"failure";
9188 case ResultWas::Info:
9189 case ResultWas::Warning:
9191 case ResultWas::Unknown:
9192 case ResultWas::FailureBit:
9193 case ResultWas::Exception:
9194 elementName =
"internalError";
9198 XmlWriter::ScopedElement e = xml.scopedElement( elementName );
9200 xml.writeAttribute(
"message", result.getExpandedExpression() );
9201 xml.writeAttribute(
"type", result.getTestMacroName() );
9203 std::ostringstream oss;
9204 if( !result.getMessage().empty() )
9205 oss << result.getMessage() <<
"\n";
9206 for( std::vector<MessageInfo>::const_iterator
9207 it = stats.infoMessages.begin(),
9208 itEnd = stats.infoMessages.end();
9211 if( it->type == ResultWas::Info )
9212 oss << it->message <<
"\n";
9214 oss <<
"at " << result.getSourceInfo();
9215 xml.writeText( oss.str(),
false );
9221 std::ostringstream stdOutForSuite;
9222 std::ostringstream stdErrForSuite;
9223 unsigned int unexpectedExceptions;
9226 INTERNAL_CATCH_REGISTER_REPORTER(
"junit", JunitReporter )
9231 #define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED
9235 struct ConsoleReporter : StreamingReporterBase {
9236 ConsoleReporter( ReporterConfig
const& _config )
9237 : StreamingReporterBase( _config ),
9238 m_headerPrinted( false )
9241 virtual ~ConsoleReporter() CATCH_OVERRIDE;
9242 static std::
string getDescription() {
9243 return "Reports test results as plain lines of text";
9246 virtual void noMatchingTestCases( std::string
const& spec ) CATCH_OVERRIDE {
9247 stream <<
"No test cases matched '" << spec <<
"'" << std::endl;
9250 virtual void assertionStarting( AssertionInfo
const& ) CATCH_OVERRIDE {
9253 virtual bool assertionEnded( AssertionStats
const& _assertionStats ) CATCH_OVERRIDE {
9254 AssertionResult
const& result = _assertionStats.assertionResult;
9256 bool printInfoMessages =
true;
9259 if( !m_config->includeSuccessfulResults() && result.isOk() ) {
9260 if( result.getResultType() != ResultWas::Warning )
9262 printInfoMessages =
false;
9267 AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
9269 stream << std::endl;
9273 virtual void sectionStarting( SectionInfo
const& _sectionInfo ) CATCH_OVERRIDE {
9274 m_headerPrinted =
false;
9275 StreamingReporterBase::sectionStarting( _sectionInfo );
9277 virtual void sectionEnded( SectionStats
const& _sectionStats ) CATCH_OVERRIDE {
9278 if( _sectionStats.missingAssertions ) {
9280 Colour colour( Colour::ResultError );
9281 if( m_sectionStack.size() > 1 )
9282 stream <<
"\nNo assertions in section";
9284 stream <<
"\nNo assertions in test case";
9285 stream <<
" '" << _sectionStats.sectionInfo.name <<
"'\n" << std::endl;
9287 if( m_headerPrinted ) {
9288 if( m_config->showDurations() == ShowDurations::Always )
9289 stream <<
"Completed in " << _sectionStats.durationInSeconds <<
"s" << std::endl;
9290 m_headerPrinted =
false;
9293 if( m_config->showDurations() == ShowDurations::Always )
9294 stream << _sectionStats.sectionInfo.name <<
" completed in " << _sectionStats.durationInSeconds <<
"s" << std::endl;
9296 StreamingReporterBase::sectionEnded( _sectionStats );
9299 virtual void testCaseEnded( TestCaseStats
const& _testCaseStats ) CATCH_OVERRIDE {
9300 StreamingReporterBase::testCaseEnded( _testCaseStats );
9301 m_headerPrinted =
false;
9303 virtual void testGroupEnded( TestGroupStats
const& _testGroupStats ) CATCH_OVERRIDE {
9304 if( currentGroupInfo.used ) {
9305 printSummaryDivider();
9306 stream <<
"Summary for group '" << _testGroupStats.groupInfo.name <<
"':\n";
9307 printTotals( _testGroupStats.totals );
9308 stream <<
"\n" << std::endl;
9310 StreamingReporterBase::testGroupEnded( _testGroupStats );
9312 virtual void testRunEnded( TestRunStats
const& _testRunStats ) CATCH_OVERRIDE {
9313 printTotalsDivider( _testRunStats.totals );
9314 printTotals( _testRunStats.totals );
9315 stream << std::endl;
9316 StreamingReporterBase::testRunEnded( _testRunStats );
9321 class AssertionPrinter {
9322 void operator= ( AssertionPrinter
const& );
9324 AssertionPrinter( std::ostream& _stream, AssertionStats
const& _stats,
bool _printInfoMessages )
9325 : stream( _stream ),
9327 result( _stats.assertionResult ),
9328 colour( Colour::None ),
9329 message( result.getMessage() ),
9330 messages( _stats.infoMessages ),
9331 printInfoMessages( _printInfoMessages )
9333 switch( result.getResultType() ) {
9335 colour = Colour::Success;
9336 passOrFail =
"PASSED";
9338 if( _stats.infoMessages.size() == 1 )
9339 messageLabel =
"with message";
9340 if( _stats.infoMessages.size() > 1 )
9341 messageLabel =
"with messages";
9343 case ResultWas::ExpressionFailed:
9344 if( result.isOk() ) {
9345 colour = Colour::Success;
9346 passOrFail =
"FAILED - but was ok";
9349 colour = Colour::Error;
9350 passOrFail =
"FAILED";
9352 if( _stats.infoMessages.size() == 1 )
9353 messageLabel =
"with message";
9354 if( _stats.infoMessages.size() > 1 )
9355 messageLabel =
"with messages";
9357 case ResultWas::ThrewException:
9358 colour = Colour::Error;
9359 passOrFail =
"FAILED";
9360 messageLabel =
"due to unexpected exception with message";
9362 case ResultWas::FatalErrorCondition:
9363 colour = Colour::Error;
9364 passOrFail =
"FAILED";
9365 messageLabel =
"due to a fatal error condition";
9367 case ResultWas::DidntThrowException:
9368 colour = Colour::Error;
9369 passOrFail =
"FAILED";
9370 messageLabel =
"because no exception was thrown where one was expected";
9372 case ResultWas::Info:
9373 messageLabel =
"info";
9375 case ResultWas::Warning:
9376 messageLabel =
"warning";
9378 case ResultWas::ExplicitFailure:
9379 passOrFail =
"FAILED";
9380 colour = Colour::Error;
9381 if( _stats.infoMessages.size() == 1 )
9382 messageLabel =
"explicitly with message";
9383 if( _stats.infoMessages.size() > 1 )
9384 messageLabel =
"explicitly with messages";
9387 case ResultWas::Unknown:
9388 case ResultWas::FailureBit:
9389 case ResultWas::Exception:
9390 passOrFail =
"** internal error **";
9391 colour = Colour::Error;
9396 void print()
const {
9398 if( stats.totals.assertions.total() > 0 ) {
9402 printOriginalExpression();
9403 printReconstructedExpression();
9412 void printResultType()
const {
9413 if( !passOrFail.empty() ) {
9414 Colour colourGuard( colour );
9415 stream << passOrFail <<
":\n";
9418 void printOriginalExpression()
const {
9419 if( result.hasExpression() ) {
9420 Colour colourGuard( Colour::OriginalExpression );
9422 stream << result.getExpressionInMacro();
9426 void printReconstructedExpression()
const {
9427 if( result.hasExpandedExpression() ) {
9428 stream <<
"with expansion:\n";
9429 Colour colourGuard( Colour::ReconstructedExpression );
9430 stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) <<
"\n";
9433 void printMessage()
const {
9434 if( !messageLabel.empty() )
9435 stream << messageLabel <<
":" <<
"\n";
9436 for( std::vector<MessageInfo>::const_iterator it = messages.begin(), itEnd = messages.end();
9440 if( printInfoMessages || it->type != ResultWas::Info )
9441 stream << Text( it->message, TextAttributes().setIndent(2) ) <<
"\n";
9444 void printSourceInfo()
const {
9445 Colour colourGuard( Colour::FileName );
9446 stream << result.getSourceInfo() <<
": ";
9449 std::ostream& stream;
9450 AssertionStats
const& stats;
9451 AssertionResult
const& result;
9452 Colour::Code colour;
9453 std::string passOrFail;
9454 std::string messageLabel;
9455 std::string message;
9456 std::vector<MessageInfo> messages;
9457 bool printInfoMessages;
9462 if( !currentTestRunInfo.used )
9464 if( !currentGroupInfo.used )
9465 lazyPrintGroupInfo();
9467 if( !m_headerPrinted ) {
9468 printTestCaseAndSectionHeader();
9469 m_headerPrinted =
true;
9472 void lazyPrintRunInfo() {
9473 stream <<
"\n" << getLineOfChars<'~'>() <<
"\n";
9474 Colour colour( Colour::SecondaryText );
9475 stream << currentTestRunInfo->name
9476 <<
" is a Catch v" << libraryVersion <<
" host application.\n"
9477 <<
"Run with -? for options\n\n";
9479 if( m_config->rngSeed() != 0 )
9480 stream <<
"Randomness seeded to: " << m_config->rngSeed() <<
"\n\n";
9482 currentTestRunInfo.used =
true;
9484 void lazyPrintGroupInfo() {
9485 if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) {
9486 printClosedHeader(
"Group: " + currentGroupInfo->name );
9487 currentGroupInfo.used =
true;
9490 void printTestCaseAndSectionHeader() {
9491 assert( !m_sectionStack.empty() );
9492 printOpenHeader( currentTestCaseInfo->name );
9494 if( m_sectionStack.size() > 1 ) {
9495 Colour colourGuard( Colour::Headers );
9497 std::vector<SectionInfo>::const_iterator
9498 it = m_sectionStack.begin()+1,
9499 itEnd = m_sectionStack.end();
9500 for( ; it != itEnd; ++it )
9501 printHeaderString( it->name, 2 );
9504 SourceLineInfo lineInfo = m_sectionStack.front().lineInfo;
9506 if( !lineInfo.empty() ){
9507 stream << getLineOfChars<
'-'>() <<
"\n";
9508 Colour colourGuard( Colour::FileName );
9509 stream << lineInfo <<
"\n";
9511 stream << getLineOfChars<'.'>() <<
"\n" << std::endl;
9514 void printClosedHeader( std::string
const& _name ) {
9515 printOpenHeader( _name );
9516 stream << getLineOfChars<
'.'>() <<
"\n";
9518 void printOpenHeader( std::string
const& _name ) {
9519 stream << getLineOfChars<
'-'>() <<
"\n";
9521 Colour colourGuard( Colour::Headers );
9522 printHeaderString( _name );
9528 void printHeaderString( std::string
const& _string, std::size_t indent = 0 ) {
9529 std::size_t i = _string.find(
": " );
9530 if( i != std::string::npos )
9534 stream << Text( _string, TextAttributes()
9535 .setIndent( indent+i)
9536 .setInitialIndent( indent ) ) <<
"\n";
9539 struct SummaryColumn {
9541 SummaryColumn( std::string
const& _label, Colour::Code _colour )
9545 SummaryColumn addRow( std::size_t count ) {
9546 std::ostringstream oss;
9548 std::string row = oss.str();
9549 for( std::vector<std::string>::iterator it = rows.begin(); it != rows.end(); ++it ) {
9550 while( it->size() < row.size() )
9552 while( it->size() > row.size() )
9555 rows.push_back( row );
9560 Colour::Code colour;
9561 std::vector<std::string> rows;
9565 void printTotals( Totals
const& totals ) {
9566 if( totals.testCases.total() == 0 ) {
9567 stream << Colour( Colour::Warning ) <<
"No tests ran\n";
9569 else if( totals.assertions.total() > 0 && totals.assertions.allPassed() ) {
9570 stream << Colour( Colour::ResultSuccess ) <<
"All tests passed";
9572 << pluralise( totals.assertions.passed,
"assertion" ) <<
" in "
9573 << pluralise( totals.testCases.passed,
"test case" ) <<
")"
9578 std::vector<SummaryColumn> columns;
9579 columns.push_back( SummaryColumn(
"", Colour::None )
9580 .addRow( totals.testCases.total() )
9581 .addRow( totals.assertions.total() ) );
9582 columns.push_back( SummaryColumn(
"passed", Colour::Success )
9583 .addRow( totals.testCases.passed )
9584 .addRow( totals.assertions.passed ) );
9585 columns.push_back( SummaryColumn(
"failed", Colour::ResultError )
9586 .addRow( totals.testCases.failed )
9587 .addRow( totals.assertions.failed ) );
9588 columns.push_back( SummaryColumn(
"failed as expected", Colour::ResultExpectedFailure )
9589 .addRow( totals.testCases.failedButOk )
9590 .addRow( totals.assertions.failedButOk ) );
9592 printSummaryRow(
"test cases", columns, 0 );
9593 printSummaryRow(
"assertions", columns, 1 );
9596 void printSummaryRow( std::string
const& label, std::vector<SummaryColumn>
const& cols, std::size_t row ) {
9597 for( std::vector<SummaryColumn>::const_iterator it = cols.begin(); it != cols.end(); ++it ) {
9598 std::string value = it->rows[row];
9599 if( it->label.empty() ) {
9600 stream << label <<
": ";
9604 stream << Colour( Colour::Warning ) <<
"- none -";
9606 else if( value !=
"0" ) {
9607 stream << Colour( Colour::LightGrey ) <<
" | ";
9608 stream << Colour( it->colour )
9609 << value <<
" " << it->label;
9615 static std::size_t makeRatio( std::size_t number, std::size_t total ) {
9616 std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0;
9617 return ( ratio == 0 && number > 0 ) ? 1 : ratio;
9619 static std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) {
9620 if( i > j && i > k )
9628 void printTotalsDivider( Totals
const& totals ) {
9629 if( totals.testCases.total() > 0 ) {
9630 std::size_t failedRatio = makeRatio( totals.testCases.failed, totals.testCases.total() );
9631 std::size_t failedButOkRatio = makeRatio( totals.testCases.failedButOk, totals.testCases.total() );
9632 std::size_t passedRatio = makeRatio( totals.testCases.passed, totals.testCases.total() );
9633 while( failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH-1 )
9634 findMax( failedRatio, failedButOkRatio, passedRatio )++;
9635 while( failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH-1 )
9636 findMax( failedRatio, failedButOkRatio, passedRatio )--;
9638 stream << Colour( Colour::Error ) << std::string( failedRatio,
'=' );
9639 stream << Colour( Colour::ResultExpectedFailure ) << std::string( failedButOkRatio,
'=' );
9640 if( totals.testCases.allPassed() )
9641 stream << Colour( Colour::ResultSuccess ) << std::string( passedRatio,
'=' );
9643 stream << Colour( Colour::Success ) << std::string( passedRatio,
'=' );
9646 stream << Colour( Colour::Warning ) << std::string( CATCH_CONFIG_CONSOLE_WIDTH-1,
'=' );
9650 void printSummaryDivider() {
9651 stream << getLineOfChars<
'-'>() <<
"\n";
9655 bool m_headerPrinted;
9658 INTERNAL_CATCH_REGISTER_REPORTER(
"console", ConsoleReporter )
9663 #define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED
9667 struct CompactReporter : StreamingReporterBase {
9669 CompactReporter( ReporterConfig
const& _config )
9670 : StreamingReporterBase( _config )
9673 virtual ~CompactReporter();
9675 static std::string getDescription() {
9676 return "Reports test results on a single line, suitable for IDEs";
9679 virtual ReporterPreferences getPreferences()
const {
9680 ReporterPreferences prefs;
9681 prefs.shouldRedirectStdOut =
false;
9685 virtual void noMatchingTestCases( std::string
const& spec ) {
9686 stream <<
"No test cases matched '" << spec <<
"'" << std::endl;
9689 virtual void assertionStarting( AssertionInfo
const& ) {
9692 virtual bool assertionEnded( AssertionStats
const& _assertionStats ) {
9693 AssertionResult
const& result = _assertionStats.assertionResult;
9695 bool printInfoMessages =
true;
9698 if( !m_config->includeSuccessfulResults() && result.isOk() ) {
9699 if( result.getResultType() != ResultWas::Warning )
9701 printInfoMessages =
false;
9704 AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
9707 stream << std::endl;
9711 virtual void testRunEnded( TestRunStats
const& _testRunStats ) {
9712 printTotals( _testRunStats.totals );
9713 stream <<
"\n" << std::endl;
9714 StreamingReporterBase::testRunEnded( _testRunStats );
9718 class AssertionPrinter {
9719 void operator= ( AssertionPrinter
const& );
9721 AssertionPrinter( std::ostream& _stream, AssertionStats
const& _stats,
bool _printInfoMessages )
9724 , result( _stats.assertionResult )
9725 , messages( _stats.infoMessages )
9726 , itMessage( _stats.infoMessages.begin() )
9727 , printInfoMessages( _printInfoMessages )
9733 itMessage = messages.begin();
9735 switch( result.getResultType() ) {
9737 printResultType( Colour::ResultSuccess, passedString() );
9738 printOriginalExpression();
9739 printReconstructedExpression();
9740 if ( ! result.hasExpression() )
9741 printRemainingMessages( Colour::None );
9743 printRemainingMessages();
9745 case ResultWas::ExpressionFailed:
9747 printResultType( Colour::ResultSuccess, failedString() + std::string(
" - but was ok" ) );
9749 printResultType( Colour::Error, failedString() );
9750 printOriginalExpression();
9751 printReconstructedExpression();
9752 printRemainingMessages();
9754 case ResultWas::ThrewException:
9755 printResultType( Colour::Error, failedString() );
9756 printIssue(
"unexpected exception with message:" );
9758 printExpressionWas();
9759 printRemainingMessages();
9761 case ResultWas::FatalErrorCondition:
9762 printResultType( Colour::Error, failedString() );
9763 printIssue(
"fatal error condition with message:" );
9765 printExpressionWas();
9766 printRemainingMessages();
9768 case ResultWas::DidntThrowException:
9769 printResultType( Colour::Error, failedString() );
9770 printIssue(
"expected exception, got none" );
9771 printExpressionWas();
9772 printRemainingMessages();
9774 case ResultWas::Info:
9775 printResultType( Colour::None,
"info" );
9777 printRemainingMessages();
9779 case ResultWas::Warning:
9780 printResultType( Colour::None,
"warning" );
9782 printRemainingMessages();
9784 case ResultWas::ExplicitFailure:
9785 printResultType( Colour::Error, failedString() );
9786 printIssue(
"explicitly" );
9787 printRemainingMessages( Colour::None );
9790 case ResultWas::Unknown:
9791 case ResultWas::FailureBit:
9792 case ResultWas::Exception:
9793 printResultType( Colour::Error,
"** internal error **" );
9801 static Colour::Code dimColour() {
return Colour::FileName; }
9803 #ifdef CATCH_PLATFORM_MAC
9804 static const char* failedString() {
return "FAILED"; }
9805 static const char* passedString() {
return "PASSED"; }
9807 static const char* failedString() {
return "failed"; }
9808 static const char* passedString() {
return "passed"; }
9811 void printSourceInfo()
const {
9812 Colour colourGuard( Colour::FileName );
9813 stream << result.getSourceInfo() <<
":";
9816 void printResultType( Colour::Code colour, std::string passOrFail )
const {
9817 if( !passOrFail.empty() ) {
9819 Colour colourGuard( colour );
9820 stream <<
" " << passOrFail;
9826 void printIssue( std::string issue )
const {
9827 stream <<
" " << issue;
9830 void printExpressionWas() {
9831 if( result.hasExpression() ) {
9834 Colour colour( dimColour() );
9835 stream <<
" expression was:";
9837 printOriginalExpression();
9841 void printOriginalExpression()
const {
9842 if( result.hasExpression() ) {
9843 stream <<
" " << result.getExpression();
9847 void printReconstructedExpression()
const {
9848 if( result.hasExpandedExpression() ) {
9850 Colour colour( dimColour() );
9853 stream << result.getExpandedExpression();
9857 void printMessage() {
9858 if ( itMessage != messages.end() ) {
9859 stream <<
" '" << itMessage->message <<
"'";
9864 void printRemainingMessages( Colour::Code colour = dimColour() ) {
9865 if ( itMessage == messages.end() )
9869 std::vector<MessageInfo>::const_iterator itEnd = messages.end();
9870 const std::size_t N =
static_cast<std::size_t
>( std::distance( itMessage, itEnd ) );
9873 Colour colourGuard( colour );
9874 stream <<
" with " << pluralise( N,
"message" ) <<
":";
9877 for(; itMessage != itEnd; ) {
9879 if( printInfoMessages || itMessage->type != ResultWas::Info ) {
9880 stream <<
" '" << itMessage->message <<
"'";
9881 if ( ++itMessage != itEnd ) {
9882 Colour colourGuard( dimColour() );
9890 std::ostream& stream;
9891 AssertionStats
const& stats;
9892 AssertionResult
const& result;
9893 std::vector<MessageInfo> messages;
9894 std::vector<MessageInfo>::const_iterator itMessage;
9895 bool printInfoMessages;
9905 std::string bothOrAll( std::size_t count )
const {
9906 return count == 1 ?
"" : count == 2 ?
"both " :
"all " ;
9909 void printTotals(
const Totals& totals )
const {
9910 if( totals.testCases.total() == 0 ) {
9911 stream <<
"No tests ran.";
9913 else if( totals.testCases.failed == totals.testCases.total() ) {
9914 Colour colour( Colour::ResultError );
9915 const std::string qualify_assertions_failed =
9916 totals.assertions.failed == totals.assertions.total() ?
9917 bothOrAll( totals.assertions.failed ) :
"";
9919 "Failed " << bothOrAll( totals.testCases.failed )
9920 << pluralise( totals.testCases.failed,
"test case" ) <<
", "
9921 "failed " << qualify_assertions_failed <<
9922 pluralise( totals.assertions.failed,
"assertion" ) <<
".";
9924 else if( totals.assertions.total() == 0 ) {
9926 "Passed " << bothOrAll( totals.testCases.total() )
9927 << pluralise( totals.testCases.total(),
"test case" )
9928 <<
" (no assertions).";
9930 else if( totals.assertions.failed ) {
9931 Colour colour( Colour::ResultError );
9933 "Failed " << pluralise( totals.testCases.failed,
"test case" ) <<
", "
9934 "failed " << pluralise( totals.assertions.failed,
"assertion" ) <<
".";
9937 Colour colour( Colour::ResultSuccess );
9939 "Passed " << bothOrAll( totals.testCases.passed )
9940 << pluralise( totals.testCases.passed,
"test case" ) <<
9941 " with " << pluralise( totals.assertions.passed,
"assertion" ) <<
".";
9946 INTERNAL_CATCH_REGISTER_REPORTER(
"compact", CompactReporter )
9953 NonCopyable::~NonCopyable() {}
9954 IShared::~IShared() {}
9955 IStream::~IStream() CATCH_NOEXCEPT {}
9956 FileStream::~FileStream() CATCH_NOEXCEPT {}
9957 CoutStream::~CoutStream() CATCH_NOEXCEPT {}
9958 DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {}
9959 StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {}
9960 IContext::~IContext() {}
9961 IResultCapture::~IResultCapture() {}
9962 ITestCase::~ITestCase() {}
9963 ITestCaseRegistry::~ITestCaseRegistry() {}
9964 IRegistryHub::~IRegistryHub() {}
9965 IMutableRegistryHub::~IMutableRegistryHub() {}
9966 IExceptionTranslator::~IExceptionTranslator() {}
9967 IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {}
9968 IReporter::~IReporter() {}
9969 IReporterFactory::~IReporterFactory() {}
9970 IReporterRegistry::~IReporterRegistry() {}
9971 IStreamingReporter::~IStreamingReporter() {}
9972 AssertionStats::~AssertionStats() {}
9973 SectionStats::~SectionStats() {}
9974 TestCaseStats::~TestCaseStats() {}
9975 TestGroupStats::~TestGroupStats() {}
9976 TestRunStats::~TestRunStats() {}
9977 CumulativeReporterBase::SectionNode::~SectionNode() {}
9978 CumulativeReporterBase::~CumulativeReporterBase() {}
9980 StreamingReporterBase::~StreamingReporterBase() {}
9981 ConsoleReporter::~ConsoleReporter() {}
9982 CompactReporter::~CompactReporter() {}
9983 IRunner::~IRunner() {}
9984 IMutableContext::~IMutableContext() {}
9985 IConfig::~IConfig() {}
9986 XmlReporter::~XmlReporter() {}
9987 JunitReporter::~JunitReporter() {}
9988 TestRegistry::~TestRegistry() {}
9989 FreeFunctionTestCase::~FreeFunctionTestCase() {}
9990 IGeneratorInfo::~IGeneratorInfo() {}
9991 IGeneratorsForTest::~IGeneratorsForTest() {}
9992 WildcardPattern::~WildcardPattern() {}
9993 TestSpec::Pattern::~Pattern() {}
9994 TestSpec::NamePattern::~NamePattern() {}
9995 TestSpec::TagPattern::~TagPattern() {}
9996 TestSpec::ExcludedPattern::~ExcludedPattern() {}
9998 Matchers::Impl::StdString::Equals::~Equals() {}
9999 Matchers::Impl::StdString::Contains::~Contains() {}
10000 Matchers::Impl::StdString::StartsWith::~StartsWith() {}
10001 Matchers::Impl::StdString::EndsWith::~EndsWith() {}
10003 void Config::dummy() {}
10005 namespace TestCaseTracking {
10006 ITracker::~ITracker() {}
10007 TrackerBase::~TrackerBase() {}
10008 SectionTracker::~SectionTracker() {}
10009 IndexTracker::~IndexTracker() {}
10014 #pragma clang diagnostic pop
10019 #ifdef CATCH_CONFIG_MAIN
10021 #define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
10026 int main (
int argc,
char * argv[]) {
10027 return Catch::Session().run( argc, argv );
10033 int main (
int argc,
char *
const argv[]) {
10034 #if !CATCH_ARC_ENABLED
10035 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
10038 Catch::registerTestMethods();
10039 int result = Catch::Session().run( argc, (
char*
const*)argv );
10041 #if !CATCH_ARC_ENABLED
10052 #ifdef CLARA_CONFIG_MAIN_NOT_DEFINED
10053 # undef CLARA_CONFIG_MAIN
10059 #ifdef CATCH_CONFIG_PREFIX_ALL
10061 #define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" )
10062 #define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "CATCH_REQUIRE_FALSE" )
10064 #define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "CATCH_REQUIRE_THROWS" )
10065 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" )
10066 #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "CATCH_REQUIRE_THROWS_WITH" )
10067 #define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" )
10069 #define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" )
10070 #define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CATCH_CHECK_FALSE" )
10071 #define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_IF" )
10072 #define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" )
10073 #define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" )
10075 #define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" )
10076 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" )
10077 #define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CATCH_CHECK_THROWS_WITH" )
10078 #define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" )
10080 #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" )
10081 #define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" )
10083 #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
10084 #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg )
10085 #define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
10086 #define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
10087 #define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
10089 #ifdef CATCH_CONFIG_VARIADIC_MACROS
10090 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
10091 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
10092 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
10093 #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
10094 #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
10095 #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ )
10096 #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ )
10098 #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
10099 #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
10100 #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
10101 #define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description )
10102 #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
10103 #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg )
10104 #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg )
10106 #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
10108 #define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
10109 #define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
10111 #define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
10114 #ifdef CATCH_CONFIG_VARIADIC_MACROS
10115 #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
10116 #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
10118 #define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags )
10119 #define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags )
10121 #define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc, "" )
10122 #define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc, "" )
10123 #define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" )
10124 #define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc, "" )
10125 #define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" )
10130 #define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" )
10131 #define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "REQUIRE_FALSE" )
10133 #define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "REQUIRE_THROWS" )
10134 #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" )
10135 #define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "REQUIRE_THROWS_WITH" )
10136 #define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" )
10138 #define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" )
10139 #define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CHECK_FALSE" )
10140 #define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_IF" )
10141 #define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" )
10142 #define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" )
10144 #define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CHECK_THROWS" )
10145 #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" )
10146 #define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CHECK_THROWS_WITH" )
10147 #define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" )
10149 #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" )
10150 #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" )
10152 #define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
10153 #define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg )
10154 #define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
10155 #define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
10156 #define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
10158 #ifdef CATCH_CONFIG_VARIADIC_MACROS
10159 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
10160 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
10161 #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
10162 #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
10163 #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
10164 #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ )
10165 #define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ )
10167 #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
10168 #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
10169 #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
10170 #define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description )
10171 #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
10172 #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg )
10173 #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg )
10175 #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
10177 #define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
10178 #define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
10180 #define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
10184 #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
10187 #ifdef CATCH_CONFIG_VARIADIC_MACROS
10188 #define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
10189 #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
10191 #define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags )
10192 #define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags )
10194 #define GIVEN( desc ) SECTION( std::string(" Given: ") + desc, "" )
10195 #define WHEN( desc ) SECTION( std::string(" When: ") + desc, "" )
10196 #define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc, "" )
10197 #define THEN( desc ) SECTION( std::string(" Then: ") + desc, "" )
10198 #define AND_THEN( desc ) SECTION( std::string(" And: ") + desc, "" )
Definition: catch.hpp:812
Definition: catch.hpp:2308
Definition: catch.hpp:2348
Definition: catch.hpp:2580
Definition: catch.hpp:2531
Definition: catch.hpp:1756
Definition: catch.hpp:1285
Definition: catch.hpp:899
Definition: catch.hpp:939
Definition: catch.hpp:882
Definition: catch.hpp:605
Definition: catch.hpp:289
Definition: catch.hpp:401
Definition: catch.hpp:2683
Definition: catch.hpp:461
Definition: catch.hpp:1182
Definition: catch.hpp:305
Definition: catch.hpp:1900
Definition: catch.hpp:2263
Definition: catch.hpp:2804
Definition: catch.hpp:2245
Definition: catch.hpp:2327
Definition: catch.hpp:790
Definition: catch.hpp:804
Definition: catch.hpp:638
Definition: catch.hpp:284
Definition: catch.hpp:1169
Definition: catch.hpp:2146
Definition: catch.hpp:1559
Definition: catch.hpp:1564
Definition: catch.hpp:1572
Definition: catch.hpp:1599
Definition: catch.hpp:1563
Definition: catch.hpp:544
Definition: catch.hpp:2525
Definition: catch.hpp:2520
Definition: catch.hpp:430
Definition: catch.hpp:2301
Definition: catch.hpp:436
Definition: catch.hpp:555
Definition: catch.hpp:2498
Definition: catch.hpp:2490
Definition: catch.hpp:1927
Definition: catch.hpp:2003
Definition: catch.hpp:502
Definition: catch.hpp:2743
Definition: catch.hpp:590
Definition: catch.hpp:581
Definition: catch.hpp:1266
Definition: catch.hpp:873
Definition: catch.hpp:859
Definition: catch.hpp:1007
Definition: catch.hpp:1046
Definition: catch.hpp:1081
Definition: catch.hpp:1028
Definition: catch.hpp:1063
Definition: catch.hpp:1883
Definition: catch.hpp:1862
Definition: catch.hpp:623
Definition: catch.hpp:2669
Definition: catch.hpp:764
Definition: catch.hpp:736
Definition: catch.hpp:2222
Definition: catch.hpp:2211
Definition: catch.hpp:509
Definition: catch.hpp:348
Definition: catch.hpp:382
Definition: catch.hpp:1633
Definition: catch.hpp:2662
Definition: catch.hpp:2770
Definition: catch.hpp:1163
Definition: catch.hpp:2178
Definition: catch.hpp:339